1 /* 2 * Copyright (C) 2022 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.media.AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE; 20 import static android.media.AudioAttributes.USAGE_MEDIA; 21 22 import static com.android.car.audio.GainBuilder.DEFAULT_GAIN; 23 import static com.android.car.audio.GainBuilder.MAX_GAIN; 24 import static com.android.car.audio.GainBuilder.STEP_SIZE; 25 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; 26 27 import static com.google.common.truth.Truth.assertWithMessage; 28 29 import static org.junit.Assert.assertThrows; 30 import static org.mockito.ArgumentMatchers.any; 31 import static org.mockito.ArgumentMatchers.anyString; 32 import static org.mockito.ArgumentMatchers.eq; 33 import static org.mockito.Mockito.RETURNS_DEEP_STUBS; 34 import static org.mockito.Mockito.mock; 35 import static org.mockito.Mockito.never; 36 import static org.mockito.Mockito.spy; 37 import static org.mockito.Mockito.times; 38 import static org.mockito.Mockito.verify; 39 import static org.mockito.Mockito.when; 40 41 import android.car.media.CarVolumeGroupEvent; 42 import android.car.media.CarVolumeGroupInfo; 43 import android.car.test.mocks.AbstractExtendedMockitoTestCase; 44 import android.hardware.automotive.audiocontrol.AudioGainConfigInfo; 45 import android.hardware.automotive.audiocontrol.IAudioControl; 46 import android.hardware.automotive.audiocontrol.Reasons; 47 import android.os.IBinder; 48 import android.util.SparseArray; 49 50 import androidx.test.ext.junit.runners.AndroidJUnit4; 51 52 import com.android.car.audio.hal.AudioControlWrapperAidl; 53 import com.android.car.audio.hal.HalAudioGainCallback; 54 55 import org.junit.Before; 56 import org.junit.Test; 57 import org.junit.runner.RunWith; 58 import org.mockito.Mock; 59 60 import java.util.Arrays; 61 import java.util.List; 62 63 @RunWith(AndroidJUnit4.class) 64 public final class CarAudioGainMonitorTest extends AbstractExtendedMockitoTestCase { 65 private static final int PRIMARY_ZONE_ID = 0; 66 private static final int PASSENGER_ZONE_ID = 1; 67 private static final int UNKNOWN_ZONE_ID = 50; 68 private static final int REAR_ZONE_ID = 2; 69 private static final String PRIMARY_MEDIA_ADDRESS = "primary_media"; 70 private static final String PRIMARY_NAVIGATION_ADDRESS = "primary_navigation_address"; 71 private static final String PRIMARY_CALL_ADDRESS = "primary_call_address"; 72 private static final String REAR_MEDIA_ADDRESS = "rear_media"; 73 private static final int TEST_GROUP_ID = 0; 74 75 private static final CarAudioContext TEST_CAR_AUDIO_CONTEXT = 76 new CarAudioContext(CarAudioContext.getAllContextsInfo(), 77 /* useCoreAudioRouting= */ false); 78 79 private static final @CarAudioContext.AudioContext int TEST_MEDIA_AUDIO_CONTEXT = 80 TEST_CAR_AUDIO_CONTEXT.getContextForAudioAttribute( 81 CarAudioContext.getAudioAttributeFromUsage(USAGE_MEDIA)); 82 private static final @CarAudioContext.AudioContext int TEST_NAVIGATION_AUDIO_CONTEXT = 83 TEST_CAR_AUDIO_CONTEXT.getContextForAudioAttribute(CarAudioContext 84 .getAudioAttributeFromUsage(USAGE_ASSISTANCE_NAVIGATION_GUIDANCE)); 85 86 private static final CarVolumeGroupInfo TEST_PRIMARY_VOLUME_INFO = 87 new CarVolumeGroupInfo.Builder("group id " + TEST_GROUP_ID, PRIMARY_ZONE_ID, 88 TEST_GROUP_ID).setMinVolumeGainIndex(0) 89 .setMaxVolumeGainIndex(MAX_GAIN / STEP_SIZE) 90 .setVolumeGainIndex(DEFAULT_GAIN / STEP_SIZE) 91 .setMinActivationVolumeGainIndex(0) 92 .setMaxActivationVolumeGainIndex(MAX_GAIN / STEP_SIZE).build(); 93 94 private static final CarVolumeGroupInfo TEST_PASSENGER_VOLUME_INFO = 95 new CarVolumeGroupInfo.Builder("group id " + TEST_GROUP_ID, PASSENGER_ZONE_ID, 96 TEST_GROUP_ID).setMinVolumeGainIndex(0) 97 .setMaxVolumeGainIndex(MAX_GAIN / STEP_SIZE) 98 .setVolumeGainIndex(DEFAULT_GAIN / STEP_SIZE) 99 .setMinActivationVolumeGainIndex(0) 100 .setMaxActivationVolumeGainIndex(MAX_GAIN / STEP_SIZE).build(); 101 102 private static final CarVolumeGroupInfo TEST_REAR_VOLUME_INFO = 103 new CarVolumeGroupInfo.Builder("group id " + TEST_GROUP_ID, REAR_ZONE_ID, 104 TEST_GROUP_ID).setMinVolumeGainIndex(0) 105 .setMaxVolumeGainIndex(MAX_GAIN / STEP_SIZE) 106 .setVolumeGainIndex(DEFAULT_GAIN / STEP_SIZE) 107 .setMinActivationVolumeGainIndex(0) 108 .setMaxActivationVolumeGainIndex(MAX_GAIN / STEP_SIZE).build(); 109 110 private static final CarVolumeGroupEvent TEST_PRIMARY_VOLUME_GROUP_EVENT = 111 new CarVolumeGroupEvent.Builder(List.of(TEST_PRIMARY_VOLUME_INFO), 112 CarVolumeGroupEvent.EVENT_TYPE_VOLUME_GAIN_INDEX_CHANGED).build(); 113 114 private static final CarVolumeGroupEvent TEST_PASSENGER_VOLUME_GROUP_EVENT = 115 new CarVolumeGroupEvent.Builder(List.of(TEST_PASSENGER_VOLUME_INFO), 116 CarVolumeGroupEvent.EVENT_TYPE_VOLUME_GAIN_INDEX_CHANGED).build(); 117 118 private static final CarVolumeGroupEvent TEST_REAR_VOLUME_GROUP_EVENT = 119 new CarVolumeGroupEvent.Builder(List.of(TEST_REAR_VOLUME_INFO), 120 CarVolumeGroupEvent.EVENT_TYPE_VOLUME_GAIN_INDEX_CHANGED).build(); 121 122 private final SparseArray<CarAudioZone> mCarAudioZones = generateZoneMocks(); 123 124 @Mock private IBinder mBinder; 125 126 @Mock private IAudioControl mAudioControl; 127 128 @Mock 129 CarVolumeInfoWrapper mMockVolumeInfoWrapper; 130 131 private AudioControlWrapperAidl mAudioControlWrapperAidl; 132 133 @Override onSessionBuilder(CustomMockitoSessionBuilder session)134 protected void onSessionBuilder(CustomMockitoSessionBuilder session) { 135 session.spyStatic(AudioControlWrapperAidl.class); 136 } 137 138 @Before setUp()139 public void setUp() { 140 when(mBinder.queryLocalInterface(anyString())).thenReturn(mAudioControl); 141 doReturn(mBinder).when(AudioControlWrapperAidl::getService); 142 mAudioControlWrapperAidl = spy(new AudioControlWrapperAidl(mBinder)); 143 } 144 145 @Test constructor_fails()146 public void constructor_fails() { 147 assertThrows( 148 NullPointerException.class, 149 () -> 150 new CarAudioGainMonitor( 151 /* audioControlWrapper= */ null, mMockVolumeInfoWrapper, 152 /* carAudioZones= */ null)); 153 154 assertThrows( 155 NullPointerException.class, 156 () -> 157 new CarAudioGainMonitor( 158 mAudioControlWrapperAidl, mMockVolumeInfoWrapper, 159 /* carAudioZones= */ null)); 160 161 assertThrows( 162 NullPointerException.class, 163 () -> new CarAudioGainMonitor(/* audioControlWrapper= */ null, 164 mMockVolumeInfoWrapper, mCarAudioZones)); 165 } 166 167 @Test constructor_nullCarVolumeInfoWrapper_fails()168 public void constructor_nullCarVolumeInfoWrapper_fails() { 169 Throwable thrown = assertThrows(NullPointerException.class, () -> new CarAudioGainMonitor( 170 mAudioControlWrapperAidl, /* carVolumeInfoWrapper= */ null, mCarAudioZones)); 171 172 expectWithMessage("Constructor exception") 173 .that(thrown).hasMessageThat().contains("Car volume info wrapper can not be null"); 174 } 175 176 @Test constructor_succeeds()177 public void constructor_succeeds() { 178 CarAudioGainMonitor carAudioGainMonitor = 179 new CarAudioGainMonitor(mAudioControlWrapperAidl, mMockVolumeInfoWrapper, 180 mCarAudioZones); 181 182 expectWithMessage("carAudioGainMonitor").that(carAudioGainMonitor).isNotNull(); 183 } 184 185 @Test registercallback_succeeds()186 public void registercallback_succeeds() { 187 CarAudioGainMonitor carAudioGainMonitor = 188 new CarAudioGainMonitor(mAudioControlWrapperAidl, mMockVolumeInfoWrapper, 189 mCarAudioZones); 190 191 HalAudioGainCallback callback = mock(HalAudioGainCallback.class); 192 carAudioGainMonitor.registerAudioGainListener(callback); 193 verify(mAudioControlWrapperAidl).registerAudioGainCallback(eq(callback)); 194 195 carAudioGainMonitor.unregisterAudioGainListener(); 196 verify(mAudioControlWrapperAidl).unregisterAudioGainCallback(); 197 } 198 199 @Test registercallback_multipleTimes()200 public void registercallback_multipleTimes() { 201 CarAudioGainMonitor carAudioGainMonitor = 202 new CarAudioGainMonitor(mAudioControlWrapperAidl, mMockVolumeInfoWrapper, 203 mCarAudioZones); 204 HalAudioGainCallback callback = mock(HalAudioGainCallback.class); 205 carAudioGainMonitor.registerAudioGainListener(callback); 206 verify(mAudioControlWrapperAidl).registerAudioGainCallback(eq(callback)); 207 208 carAudioGainMonitor.registerAudioGainListener(callback); 209 verify(mAudioControlWrapperAidl, times(2)).registerAudioGainCallback(eq(callback)); 210 211 HalAudioGainCallback callback2 = mock(HalAudioGainCallback.class); 212 carAudioGainMonitor.registerAudioGainListener(callback2); 213 verify(mAudioControlWrapperAidl).registerAudioGainCallback(eq(callback2)); 214 } 215 216 @Test handleAudioDeviceGainsChanged_validZones()217 public void handleAudioDeviceGainsChanged_validZones() { 218 List<CarVolumeGroupEvent> events = 219 List.of( 220 TEST_PRIMARY_VOLUME_GROUP_EVENT, 221 TEST_PASSENGER_VOLUME_GROUP_EVENT, 222 TEST_REAR_VOLUME_GROUP_EVENT 223 ); 224 CarAudioGainMonitor carAudioGainMonitor = 225 new CarAudioGainMonitor(mAudioControlWrapperAidl, mMockVolumeInfoWrapper, 226 mCarAudioZones); 227 List<Integer> reasons = List.of(Reasons.REMOTE_MUTE, Reasons.NAV_DUCKING); 228 AudioGainConfigInfo primaryZoneGain = new AudioGainConfigInfo(); 229 primaryZoneGain.zoneId = PRIMARY_ZONE_ID; 230 primaryZoneGain.devicePortAddress = PRIMARY_MEDIA_ADDRESS; 231 CarAudioGainConfigInfo primaryZoneCarGain = new CarAudioGainConfigInfo(primaryZoneGain); 232 AudioGainConfigInfo primaryZoneGain2 = new AudioGainConfigInfo(); 233 primaryZoneGain2.zoneId = PRIMARY_ZONE_ID; 234 primaryZoneGain2.devicePortAddress = PRIMARY_NAVIGATION_ADDRESS; 235 CarAudioGainConfigInfo primaryZoneCarGain2 = new CarAudioGainConfigInfo(primaryZoneGain2); 236 AudioGainConfigInfo primaryZoneGain3 = new AudioGainConfigInfo(); 237 primaryZoneGain3.zoneId = PRIMARY_ZONE_ID; 238 primaryZoneGain3.devicePortAddress = PRIMARY_CALL_ADDRESS; 239 CarAudioGainConfigInfo primaryZoneCarGain3 = new CarAudioGainConfigInfo(primaryZoneGain3); 240 AudioGainConfigInfo passengerZoneGain = new AudioGainConfigInfo(); 241 passengerZoneGain.zoneId = PASSENGER_ZONE_ID; 242 CarAudioGainConfigInfo passengerZoneCarGain = new CarAudioGainConfigInfo(passengerZoneGain); 243 AudioGainConfigInfo rearZoneGain = new AudioGainConfigInfo(); 244 rearZoneGain.zoneId = REAR_ZONE_ID; 245 CarAudioGainConfigInfo rearZoneCarGain = new CarAudioGainConfigInfo(rearZoneGain); 246 247 SparseArray<List<CarAudioGainConfigInfo>> gainsForZones = new SparseArray<>(); 248 gainsForZones.put( 249 PRIMARY_ZONE_ID, 250 Arrays.asList(primaryZoneCarGain, primaryZoneCarGain2, primaryZoneCarGain3)); 251 gainsForZones.put(PASSENGER_ZONE_ID, Arrays.asList(passengerZoneCarGain)); 252 gainsForZones.put(REAR_ZONE_ID, Arrays.asList(rearZoneCarGain)); 253 254 List<CarAudioGainConfigInfo> gains = 255 List.of( 256 primaryZoneCarGain, 257 primaryZoneCarGain2, 258 primaryZoneCarGain3, 259 passengerZoneCarGain, 260 rearZoneCarGain); 261 carAudioGainMonitor.handleAudioDeviceGainsChanged(reasons, gains); 262 263 for (int index = 0; index < mCarAudioZones.size(); index++) { 264 CarAudioZone carAudioZone = mCarAudioZones.valueAt(index); 265 List<CarAudioGainConfigInfo> gainsForZone = gainsForZones.get(carAudioZone.getId()); 266 verify(carAudioZone).onAudioGainChanged(eq(reasons), eq(gainsForZone)); 267 } 268 verify(mMockVolumeInfoWrapper).onVolumeGroupEvent(eq(events)); 269 } 270 271 @Test handleAudioDeviceGainsChanged_validAndUnknownZones()272 public void handleAudioDeviceGainsChanged_validAndUnknownZones() { 273 List<CarVolumeGroupEvent> events = 274 List.of( 275 TEST_PRIMARY_VOLUME_GROUP_EVENT, 276 TEST_REAR_VOLUME_GROUP_EVENT 277 ); 278 CarAudioGainMonitor carAudioGainMonitor = 279 new CarAudioGainMonitor(mAudioControlWrapperAidl, mMockVolumeInfoWrapper, 280 mCarAudioZones); 281 List<Integer> reasons = List.of(Reasons.REMOTE_MUTE, Reasons.NAV_DUCKING); 282 AudioGainConfigInfo primaryZoneGain = new AudioGainConfigInfo(); 283 primaryZoneGain.zoneId = PRIMARY_ZONE_ID; 284 CarAudioGainConfigInfo primaryZoneCarGain = new CarAudioGainConfigInfo(primaryZoneGain); 285 AudioGainConfigInfo rearZoneGain = new AudioGainConfigInfo(); 286 rearZoneGain.zoneId = REAR_ZONE_ID; 287 CarAudioGainConfigInfo rearZoneCarGain = new CarAudioGainConfigInfo(rearZoneGain); 288 AudioGainConfigInfo unknownGain = new AudioGainConfigInfo(); 289 unknownGain.zoneId = UNKNOWN_ZONE_ID; 290 CarAudioGainConfigInfo unknownCarGain = new CarAudioGainConfigInfo(unknownGain); 291 292 SparseArray<List<CarAudioGainConfigInfo>> gainsForZones = new SparseArray<>(); 293 gainsForZones.put(PRIMARY_ZONE_ID, Arrays.asList(primaryZoneCarGain)); 294 gainsForZones.put(REAR_ZONE_ID, Arrays.asList(rearZoneCarGain)); 295 gainsForZones.put(UNKNOWN_ZONE_ID, Arrays.asList(unknownCarGain)); 296 297 List<CarAudioGainConfigInfo> gains = 298 List.of(primaryZoneCarGain, unknownCarGain, rearZoneCarGain); 299 carAudioGainMonitor.handleAudioDeviceGainsChanged(reasons, gains); 300 301 for (int index = 0; index < mCarAudioZones.size(); index++) { 302 CarAudioZone carAudioZone = mCarAudioZones.valueAt(index); 303 Integer zoneId = carAudioZone.getId(); 304 if (gainsForZones.contains(zoneId)) { 305 List<CarAudioGainConfigInfo> gainsForZone = gainsForZones.get(zoneId); 306 verify(carAudioZone).onAudioGainChanged(eq(reasons), eq(gainsForZone)); 307 continue; 308 } 309 verify(carAudioZone, never()).onAudioGainChanged(any(), any()); 310 } 311 verify(mMockVolumeInfoWrapper).onVolumeGroupEvent(eq(events)); 312 } 313 314 @Test handleAudioDeviceGainsChanged_unknownZones()315 public void handleAudioDeviceGainsChanged_unknownZones() { 316 CarAudioGainMonitor carAudioGainMonitor = 317 new CarAudioGainMonitor(mAudioControlWrapperAidl, mMockVolumeInfoWrapper, 318 mCarAudioZones); 319 List<Integer> reasons = List.of(Reasons.REMOTE_MUTE, Reasons.NAV_DUCKING); 320 321 AudioGainConfigInfo unknownGain = new AudioGainConfigInfo(); 322 unknownGain.zoneId = UNKNOWN_ZONE_ID; 323 CarAudioGainConfigInfo unknownCarGain = new CarAudioGainConfigInfo(unknownGain); 324 AudioGainConfigInfo unknownGain2 = new AudioGainConfigInfo(); 325 unknownGain2.zoneId = REAR_ZONE_ID + 1; 326 CarAudioGainConfigInfo unknownCarGain2 = new CarAudioGainConfigInfo(unknownGain2); 327 328 List<CarAudioGainConfigInfo> gains = List.of(unknownCarGain, unknownCarGain2); 329 carAudioGainMonitor.handleAudioDeviceGainsChanged(reasons, gains); 330 331 for (int index = 0; index < mCarAudioZones.size(); index++) { 332 CarAudioZone carAudioZone = mCarAudioZones.valueAt(index); 333 verify(carAudioZone, never()).onAudioGainChanged(any(), any()); 334 } 335 verify(mMockVolumeInfoWrapper, never()).onVolumeGroupEvent(any()); 336 } 337 338 @Test shouldBlockVolumeRequest_returnsTrue()339 public void shouldBlockVolumeRequest_returnsTrue() { 340 List<Integer> blockingReasons = 341 List.of(Reasons.FORCED_MASTER_MUTE, Reasons.TCU_MUTE, Reasons.REMOTE_MUTE); 342 343 // One by one 344 for (int index = 0; index < blockingReasons.size(); index++) { 345 List<Integer> reasons = Arrays.asList(blockingReasons.get(index)); 346 assertWithMessage("Volume Requests Blocked") 347 .that(CarAudioGainMonitor.shouldBlockVolumeRequest(reasons)) 348 .isTrue(); 349 } 350 // All 351 assertWithMessage("Volume Requests Blocked") 352 .that(CarAudioGainMonitor.shouldBlockVolumeRequest(blockingReasons)) 353 .isTrue(); 354 355 List<Integer> mixedReasons = 356 List.of( 357 Reasons.FORCED_MASTER_MUTE, 358 Reasons.NAV_DUCKING, 359 Reasons.THERMAL_LIMITATION); 360 361 assertWithMessage("Volume Requests Blocked") 362 .that(CarAudioGainMonitor.shouldBlockVolumeRequest(mixedReasons)) 363 .isTrue(); 364 } 365 366 @Test shouldBlockVolumeRequest_returnsFalse()367 public void shouldBlockVolumeRequest_returnsFalse() { 368 List<Integer> nonBlockingReasons = 369 List.of( 370 Reasons.NAV_DUCKING, 371 Reasons.ADAS_DUCKING, 372 Reasons.THERMAL_LIMITATION, 373 Reasons.SUSPEND_EXIT_VOL_LIMITATION); 374 375 // One by one 376 for (int index = 0; index < nonBlockingReasons.size(); index++) { 377 List<Integer> reasons = Arrays.asList(nonBlockingReasons.get(index)); 378 assertWithMessage("Volume Requests Blocked") 379 .that(CarAudioGainMonitor.shouldBlockVolumeRequest(reasons)) 380 .isFalse(); 381 } 382 // All 383 assertWithMessage("Volume Requests Blocked") 384 .that(CarAudioGainMonitor.shouldBlockVolumeRequest(nonBlockingReasons)) 385 .isFalse(); 386 } 387 388 @Test shouldLimitVolume_returnsTrue()389 public void shouldLimitVolume_returnsTrue() { 390 List<Integer> limitReasons = 391 List.of(Reasons.THERMAL_LIMITATION, Reasons.SUSPEND_EXIT_VOL_LIMITATION); 392 393 // One by one 394 for (int index = 0; index < limitReasons.size(); index++) { 395 List<Integer> reasons = Arrays.asList(limitReasons.get(index)); 396 assertWithMessage("Volume Limited") 397 .that(CarAudioGainMonitor.shouldLimitVolume(reasons)) 398 .isTrue(); 399 } 400 // All 401 assertWithMessage("Volume Limited") 402 .that(CarAudioGainMonitor.shouldLimitVolume(limitReasons)) 403 .isTrue(); 404 405 List<Integer> mixedReasons = 406 List.of( 407 Reasons.FORCED_MASTER_MUTE, 408 Reasons.NAV_DUCKING, 409 Reasons.THERMAL_LIMITATION); 410 411 assertWithMessage("Volume Limited") 412 .that(CarAudioGainMonitor.shouldLimitVolume(mixedReasons)) 413 .isTrue(); 414 } 415 416 @Test shouldLimitVolume_returnsFalse()417 public void shouldLimitVolume_returnsFalse() { 418 List<Integer> nonLimitReasons = 419 List.of( 420 Reasons.NAV_DUCKING, 421 Reasons.ADAS_DUCKING, 422 Reasons.FORCED_MASTER_MUTE, 423 Reasons.TCU_MUTE, 424 Reasons.REMOTE_MUTE); 425 426 // One by one 427 for (int index = 0; index < nonLimitReasons.size(); index++) { 428 List<Integer> reasons = Arrays.asList(nonLimitReasons.get(index)); 429 assertWithMessage("Volume Limited") 430 .that(CarAudioGainMonitor.shouldLimitVolume(reasons)) 431 .isFalse(); 432 } 433 // All 434 assertWithMessage("Volume Limited") 435 .that(CarAudioGainMonitor.shouldLimitVolume(nonLimitReasons)) 436 .isFalse(); 437 } 438 439 @Test shouldDuckGain_returnsTrue()440 public void shouldDuckGain_returnsTrue() { 441 List<Integer> limitReasons = List.of(Reasons.ADAS_DUCKING, Reasons.NAV_DUCKING); 442 443 // One by one 444 for (int index = 0; index < limitReasons.size(); index++) { 445 List<Integer> reasons = Arrays.asList(limitReasons.get(index)); 446 assertWithMessage("Volume Requests Blocked") 447 .that(CarAudioGainMonitor.shouldDuckGain(reasons)) 448 .isTrue(); 449 } 450 // All 451 assertWithMessage("Volume Attenuated") 452 .that(CarAudioGainMonitor.shouldDuckGain(limitReasons)) 453 .isTrue(); 454 455 List<Integer> mixedReasons = 456 List.of( 457 Reasons.FORCED_MASTER_MUTE, 458 Reasons.NAV_DUCKING, 459 Reasons.THERMAL_LIMITATION); 460 461 assertWithMessage("Volume Attenuated") 462 .that(CarAudioGainMonitor.shouldDuckGain(mixedReasons)) 463 .isTrue(); 464 } 465 466 @Test shouldDuckGain_returnsFalse()467 public void shouldDuckGain_returnsFalse() { 468 List<Integer> nonDuckingReasons = 469 List.of( 470 Reasons.THERMAL_LIMITATION, 471 Reasons.SUSPEND_EXIT_VOL_LIMITATION, 472 Reasons.FORCED_MASTER_MUTE, 473 Reasons.TCU_MUTE, 474 Reasons.REMOTE_MUTE); 475 476 // One by one 477 for (int index = 0; index < nonDuckingReasons.size(); index++) { 478 List<Integer> reasons = Arrays.asList(nonDuckingReasons.get(index)); 479 assertWithMessage("Volume Attenuated") 480 .that(CarAudioGainMonitor.shouldDuckGain(reasons)) 481 .isFalse(); 482 } 483 // All 484 assertWithMessage("Volume Attenuated") 485 .that(CarAudioGainMonitor.shouldDuckGain(nonDuckingReasons)) 486 .isFalse(); 487 } 488 489 @Test shouldMuteVolumeGroup_forEach_returnsTrue()490 public void shouldMuteVolumeGroup_forEach_returnsTrue() { 491 List<Integer> muteReasons = List.of(Reasons.TCU_MUTE, Reasons.REMOTE_MUTE); 492 493 for (int index = 0; index < muteReasons.size(); index++) { 494 List<Integer> reasons = Arrays.asList(muteReasons.get(index)); 495 assertWithMessage("Mute volume group for reason") 496 .that(CarAudioGainMonitor.shouldMuteVolumeGroup(reasons)).isTrue(); 497 } 498 } 499 500 @Test shouldMuteVolumeGroup_returnsTrue()501 public void shouldMuteVolumeGroup_returnsTrue() { 502 List<Integer> muteReasons = List.of(Reasons.TCU_MUTE, Reasons.REMOTE_MUTE); 503 504 assertWithMessage("Mute volume group for multiple reasons") 505 .that(CarAudioGainMonitor.shouldMuteVolumeGroup(muteReasons)).isTrue(); 506 } 507 508 @Test shouldMuteVolumeGroup_forEach_returnsFalse()509 public void shouldMuteVolumeGroup_forEach_returnsFalse() { 510 List<Integer> nonMuteReasons = List.of(Reasons.FORCED_MASTER_MUTE, Reasons.ADAS_DUCKING); 511 512 for (int index = 0; index < nonMuteReasons.size(); index++) { 513 List<Integer> reasons = Arrays.asList(nonMuteReasons.get(index)); 514 assertWithMessage("Mute volume group for reason") 515 .that(CarAudioGainMonitor.shouldMuteVolumeGroup(reasons)).isFalse(); 516 } 517 } 518 519 @Test shouldMuteVolumeGroup_returnsFalse()520 public void shouldMuteVolumeGroup_returnsFalse() { 521 List<Integer> nonMuteReasons = List.of(Reasons.FORCED_MASTER_MUTE, Reasons.ADAS_DUCKING); 522 523 assertWithMessage("Mute volume group for multiple reasons") 524 .that(CarAudioGainMonitor.shouldMuteVolumeGroup(nonMuteReasons)).isFalse(); 525 } 526 527 @Test shouldUpdateVolumeIndex_returnsTrue()528 public void shouldUpdateVolumeIndex_returnsTrue() { 529 List<Integer> reasons = List.of(Reasons.EXTERNAL_AMP_VOL_FEEDBACK, Reasons.TCU_MUTE); 530 531 assertWithMessage("Update volume index for reasons") 532 .that(CarAudioGainMonitor.shouldUpdateVolumeIndex(reasons)).isTrue(); 533 } 534 535 @Test shouldUpdateVolumeIndex_returnsFalse()536 public void shouldUpdateVolumeIndex_returnsFalse() { 537 List<Integer> reasons = 538 List.of( 539 Reasons.THERMAL_LIMITATION, 540 Reasons.SUSPEND_EXIT_VOL_LIMITATION, 541 Reasons.FORCED_MASTER_MUTE, 542 Reasons.TCU_MUTE, 543 Reasons.REMOTE_MUTE); 544 545 assertWithMessage("Update volume index for reasons") 546 .that(CarAudioGainMonitor.shouldUpdateVolumeIndex(reasons)).isFalse(); 547 } 548 549 @Test convertReasonsToExtraInfo_supportedReasons_isEqualTo()550 public void convertReasonsToExtraInfo_supportedReasons_isEqualTo() { 551 List<Integer> reasons = 552 List.of( 553 Reasons.REMOTE_MUTE, 554 Reasons.THERMAL_LIMITATION, 555 Reasons.SUSPEND_EXIT_VOL_LIMITATION, 556 Reasons.TCU_MUTE, 557 Reasons.FORCED_MASTER_MUTE, 558 Reasons.ADAS_DUCKING, 559 Reasons.NAV_DUCKING, 560 Reasons.EXTERNAL_AMP_VOL_FEEDBACK, 561 Reasons.PROJECTION_DUCKING); 562 List<Integer> extraInfos = 563 List.of( 564 CarVolumeGroupEvent.EXTRA_INFO_MUTE_TOGGLED_BY_AUDIO_SYSTEM, 565 CarVolumeGroupEvent.EXTRA_INFO_TRANSIENT_ATTENUATION_THERMAL, 566 CarVolumeGroupEvent.EXTRA_INFO_ATTENUATION_ACTIVATION, 567 CarVolumeGroupEvent.EXTRA_INFO_MUTE_TOGGLED_BY_EMERGENCY, 568 CarVolumeGroupEvent.EXTRA_INFO_TRANSIENT_ATTENUATION_EXTERNAL, 569 CarVolumeGroupEvent.EXTRA_INFO_TRANSIENT_ATTENUATION_NAVIGATION, 570 CarVolumeGroupEvent.EXTRA_INFO_VOLUME_INDEX_CHANGED_BY_AUDIO_SYSTEM, 571 CarVolumeGroupEvent.EXTRA_INFO_TRANSIENT_ATTENUATION_PROJECTION); 572 573 assertWithMessage("Convert reasons to extra infos") 574 .that(CarAudioGainMonitor.convertReasonsToExtraInfo(reasons)).isEqualTo(extraInfos); 575 } 576 577 @Test convertReasonsToExtraInfo_unSupportedReasons_isEmpty()578 public void convertReasonsToExtraInfo_unSupportedReasons_isEmpty() { 579 List<Integer> reasons = 580 List.of( 581 Reasons.FORCED_MASTER_MUTE, 582 Reasons.OTHER); 583 584 assertWithMessage("Convert reasons to extra infos") 585 .that(CarAudioGainMonitor.convertReasonsToExtraInfo(reasons).isEmpty()).isTrue(); 586 } 587 generateZoneMocks()588 private static SparseArray<CarAudioZone> generateZoneMocks() { 589 SparseArray<CarAudioZone> zones = new SparseArray<>(); 590 CarAudioZone primaryZone = mock(CarAudioZone.class, RETURNS_DEEP_STUBS); 591 when(primaryZone.getId()).thenReturn(PRIMARY_ZONE_ID); 592 when(primaryZone.getAddressForContext(TEST_MEDIA_AUDIO_CONTEXT)) 593 .thenReturn(PRIMARY_MEDIA_ADDRESS); 594 when(primaryZone.getAddressForContext(TEST_NAVIGATION_AUDIO_CONTEXT)) 595 .thenReturn(PRIMARY_NAVIGATION_ADDRESS); 596 when(primaryZone.onAudioGainChanged(any(), any())) 597 .thenReturn(List.of(TEST_PRIMARY_VOLUME_GROUP_EVENT)); 598 zones.append(PRIMARY_ZONE_ID, primaryZone); 599 600 CarAudioZone passengerZone = mock(CarAudioZone.class, RETURNS_DEEP_STUBS); 601 when(passengerZone.getId()).thenReturn(PASSENGER_ZONE_ID); 602 when(passengerZone.onAudioGainChanged(any(), any())) 603 .thenReturn(List.of(TEST_PASSENGER_VOLUME_GROUP_EVENT)); 604 zones.append(PASSENGER_ZONE_ID, passengerZone); 605 606 CarAudioZone rearZone = mock(CarAudioZone.class, RETURNS_DEEP_STUBS); 607 when(rearZone.getId()).thenReturn(REAR_ZONE_ID); 608 when(rearZone.getAddressForContext(TEST_MEDIA_AUDIO_CONTEXT)) 609 .thenReturn(REAR_MEDIA_ADDRESS); 610 when(rearZone.onAudioGainChanged(any(), any())) 611 .thenReturn(List.of(TEST_REAR_VOLUME_GROUP_EVENT)); 612 zones.append(REAR_ZONE_ID, rearZone); 613 614 return zones; 615 } 616 } 617