blob: cc9ecd3c2d9ee8acc873de6c03d9a958af448c50 [file] [log] [blame]
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.car.audio;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.testng.Assert.expectThrows;
import android.app.ActivityManager;
import android.car.test.mocks.AbstractExtendedMockitoTestCase;
import android.os.UserHandle;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.common.primitives.Ints;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@RunWith(AndroidJUnit4.class)
public class CarVolumeGroupTest extends AbstractExtendedMockitoTestCase{
private static final int STEP_VALUE = 2;
private static final int MIN_GAIN = 0;
private static final int MAX_GAIN = 5;
private static final int DEFAULT_GAIN = 0;
private static final int TEST_USER_10 = 10;
private static final int TEST_USER_11 = 11;
private static final String OTHER_ADDRESS = "other_address";
private static final String MEDIA_DEVICE_ADDRESS = "music";
private static final String NAVIGATION_DEVICE_ADDRESS = "navigation";
private CarAudioDeviceInfo mMediaDevice;
private CarAudioDeviceInfo mNavigationDevice;
@Override
protected void onSessionBuilder(CustomMockitoSessionBuilder session) {
session.spyStatic(ActivityManager.class);
}
@Before
public void setUp() {
mMediaDevice = generateCarAudioDeviceInfo(MEDIA_DEVICE_ADDRESS);
mNavigationDevice = generateCarAudioDeviceInfo(NAVIGATION_DEVICE_ADDRESS);
}
@Test
public void bind_associatesDeviceAddresses() {
CarAudioSettings settings =
generateCarAudioSettings(0 , 0, 2);
CarVolumeGroup carVolumeGroup = new CarVolumeGroup(settings, 0, 0);
carVolumeGroup.bind(CarAudioContext.MUSIC, mMediaDevice);
assertEquals(1, carVolumeGroup.getAddresses().size());
carVolumeGroup.bind(CarAudioContext.NAVIGATION, mNavigationDevice);
List<String> addresses = carVolumeGroup.getAddresses();
assertEquals(2, addresses.size());
assertTrue(addresses.contains(MEDIA_DEVICE_ADDRESS));
assertTrue(addresses.contains(NAVIGATION_DEVICE_ADDRESS));
}
@Test
public void bind_checksForSameStepSize() {
CarAudioSettings settings =
generateCarAudioSettings(0 , 0, 2);
CarVolumeGroup carVolumeGroup = new CarVolumeGroup(settings, 0, 0);
carVolumeGroup.bind(CarAudioContext.MUSIC, mMediaDevice);
CarAudioDeviceInfo differentStepValueDevice = generateCarAudioDeviceInfo(
NAVIGATION_DEVICE_ADDRESS, STEP_VALUE + 1,
MIN_GAIN, MAX_GAIN);
IllegalArgumentException thrown = expectThrows(IllegalArgumentException.class,
() -> carVolumeGroup.bind(CarAudioContext.NAVIGATION, differentStepValueDevice));
assertThat(thrown).hasMessageThat()
.contains("Gain controls within one group must have same step value");
}
@Test
public void bind_updatesMinGainToSmallestValue() {
CarAudioSettings settings =
generateCarAudioSettings(0 , 0, 2);
CarVolumeGroup carVolumeGroup = new CarVolumeGroup(settings, 0, 0);
CarAudioDeviceInfo largestMinGain = generateCarAudioDeviceInfo(
NAVIGATION_DEVICE_ADDRESS, 1, 10, 10);
carVolumeGroup.bind(CarAudioContext.NAVIGATION, largestMinGain);
assertEquals(0, carVolumeGroup.getMaxGainIndex());
CarAudioDeviceInfo smallestMinGain = generateCarAudioDeviceInfo(
NAVIGATION_DEVICE_ADDRESS, 1, 2, 10);
carVolumeGroup.bind(CarAudioContext.NOTIFICATION, smallestMinGain);
assertEquals(8, carVolumeGroup.getMaxGainIndex());
CarAudioDeviceInfo middleMinGain = generateCarAudioDeviceInfo(
NAVIGATION_DEVICE_ADDRESS, 1, 7, 10);
carVolumeGroup.bind(CarAudioContext.VOICE_COMMAND, middleMinGain);
assertEquals(8, carVolumeGroup.getMaxGainIndex());
}
@Test
public void bind_updatesMaxGainToLargestValue() {
CarAudioSettings settings =
generateCarAudioSettings(0 , 0, 2);
CarVolumeGroup carVolumeGroup = new CarVolumeGroup(settings, 0, 0);
CarAudioDeviceInfo smallestMaxGain = generateCarAudioDeviceInfo(
NAVIGATION_DEVICE_ADDRESS, 1, 1, 5);
carVolumeGroup.bind(CarAudioContext.NAVIGATION, smallestMaxGain);
assertEquals(4, carVolumeGroup.getMaxGainIndex());
CarAudioDeviceInfo largestMaxGain = generateCarAudioDeviceInfo(
NAVIGATION_DEVICE_ADDRESS, 1, 1, 10);
carVolumeGroup.bind(CarAudioContext.NOTIFICATION, largestMaxGain);
assertEquals(9, carVolumeGroup.getMaxGainIndex());
CarAudioDeviceInfo middleMaxGain = generateCarAudioDeviceInfo(
NAVIGATION_DEVICE_ADDRESS, 1, 1, 7);
carVolumeGroup.bind(CarAudioContext.VOICE_COMMAND, middleMaxGain);
assertEquals(9, carVolumeGroup.getMaxGainIndex());
}
@Test
public void bind_checksThatTheSameContextIsNotBoundTwice() {
CarAudioSettings settings =
generateCarAudioSettings(0 , 0, 2);
CarVolumeGroup carVolumeGroup = new CarVolumeGroup(settings, 0, 0);
carVolumeGroup.bind(CarAudioContext.NAVIGATION, mMediaDevice);
IllegalArgumentException thrown = expectThrows(IllegalArgumentException.class,
() -> carVolumeGroup.bind(CarAudioContext.NAVIGATION, mMediaDevice));
assertThat(thrown).hasMessageThat()
.contains("Context NAVIGATION has already been bound to " + MEDIA_DEVICE_ADDRESS);
}
@Test
public void getContexts_returnsAllContextsBoundToVolumeGroup() {
CarVolumeGroup carVolumeGroup = testVolumeGroupSetup();
int[] contexts = carVolumeGroup.getContexts();
assertEquals(6, contexts.length);
List<Integer> contextsList = Ints.asList(contexts);
assertTrue(contextsList.contains(CarAudioContext.MUSIC));
assertTrue(contextsList.contains(CarAudioContext.CALL));
assertTrue(contextsList.contains(CarAudioContext.CALL_RING));
assertTrue(contextsList.contains(CarAudioContext.NAVIGATION));
assertTrue(contextsList.contains(CarAudioContext.ALARM));
assertTrue(contextsList.contains(CarAudioContext.NOTIFICATION));
}
@Test
public void getContextsForAddress_returnsContextsBoundToThatAddress() {
CarVolumeGroup carVolumeGroup = testVolumeGroupSetup();
int[] contexts = carVolumeGroup.getContextsForAddress(MEDIA_DEVICE_ADDRESS);
assertEquals(3, contexts.length);
List<Integer> contextsList = Ints.asList(contexts);
assertTrue(contextsList.contains(CarAudioContext.MUSIC));
assertTrue(contextsList.contains(CarAudioContext.CALL));
assertTrue(contextsList.contains(CarAudioContext.CALL_RING));
}
@Test
public void getContextsForAddress_returnsEmptyArrayIfAddressNotBound() {
CarVolumeGroup carVolumeGroup = testVolumeGroupSetup();
int[] contexts = carVolumeGroup.getContextsForAddress(OTHER_ADDRESS);
assertEquals(0, contexts.length);
}
@Test
public void getCarAudioDeviceInfoForAddress_returnsExpectedDevice() {
CarVolumeGroup carVolumeGroup = testVolumeGroupSetup();
CarAudioDeviceInfo actualDevice = carVolumeGroup.getCarAudioDeviceInfoForAddress(
MEDIA_DEVICE_ADDRESS);
assertEquals(mMediaDevice, actualDevice);
}
@Test
public void getCarAudioDeviceInfoForAddress_returnsNullIfAddressNotBound() {
CarVolumeGroup carVolumeGroup = testVolumeGroupSetup();
CarAudioDeviceInfo actualDevice = carVolumeGroup.getCarAudioDeviceInfoForAddress(
OTHER_ADDRESS);
assertNull(actualDevice);
}
@Test
public void setCurrentGainIndex_setsGainOnAllBoundDevices() {
CarVolumeGroup carVolumeGroup = testVolumeGroupSetup();
carVolumeGroup.setCurrentGainIndex(2);
verify(mMediaDevice).setCurrentGain(4);
verify(mNavigationDevice).setCurrentGain(4);
}
@Test
public void setCurrentGainIndex_updatesCurrentGainIndex() {
CarVolumeGroup carVolumeGroup = testVolumeGroupSetup();
carVolumeGroup.setCurrentGainIndex(2);
assertEquals(2, carVolumeGroup.getCurrentGainIndex());
}
@Test
public void setCurrentGainIndex_checksNewGainIsAboveMin() {
CarVolumeGroup carVolumeGroup = testVolumeGroupSetup();
IllegalArgumentException thrown = expectThrows(IllegalArgumentException.class,
() -> carVolumeGroup.setCurrentGainIndex(-1));
assertThat(thrown).hasMessageThat().contains("Gain out of range (0:5) -2index -1");
}
@Test
public void setCurrentGainIndex_checksNewGainIsBelowMax() {
CarVolumeGroup carVolumeGroup = testVolumeGroupSetup();
IllegalArgumentException thrown = expectThrows(IllegalArgumentException.class,
() -> carVolumeGroup.setCurrentGainIndex(3));
assertThat(thrown).hasMessageThat().contains("Gain out of range (0:5) 6index 3");
}
@Test
public void getMinGainIndex_alwaysReturnsZero() {
CarAudioSettings settings =
generateCarAudioSettings(0 , 0, 2);
CarVolumeGroup carVolumeGroup = new CarVolumeGroup(settings, 0, 0);
CarAudioDeviceInfo minGainPlusOneDevice = generateCarAudioDeviceInfo(
NAVIGATION_DEVICE_ADDRESS, STEP_VALUE, 10, MAX_GAIN);
carVolumeGroup.bind(CarAudioContext.NAVIGATION, minGainPlusOneDevice);
assertEquals(0, carVolumeGroup.getMinGainIndex());
CarAudioDeviceInfo minGainDevice = generateCarAudioDeviceInfo(
NAVIGATION_DEVICE_ADDRESS, STEP_VALUE, 1, MAX_GAIN);
carVolumeGroup.bind(CarAudioContext.NOTIFICATION, minGainDevice);
assertEquals(0, carVolumeGroup.getMinGainIndex());
}
@Test
public void loadVolumesForUser_setsCurrentGainIndexForUser() {
List<Integer> users = new ArrayList<>();
users.add(TEST_USER_10);
users.add(TEST_USER_11);
Map<Integer, Integer> storedGainIndex = new HashMap<>();
storedGainIndex.put(TEST_USER_10, 2);
storedGainIndex.put(TEST_USER_11, 0);
CarAudioSettings settings =
generateCarAudioSettings(users, 0 , 0, storedGainIndex);
CarVolumeGroup carVolumeGroup = new CarVolumeGroup(settings, 0, 0);
CarAudioDeviceInfo deviceInfo = generateCarAudioDeviceInfo(
NAVIGATION_DEVICE_ADDRESS, STEP_VALUE, MIN_GAIN, MAX_GAIN);
carVolumeGroup.bind(CarAudioContext.NAVIGATION, deviceInfo);
carVolumeGroup.loadVolumesForUser(TEST_USER_10);
assertEquals(2, carVolumeGroup.getCurrentGainIndex());
carVolumeGroup.loadVolumesForUser(TEST_USER_11);
assertEquals(0, carVolumeGroup.getCurrentGainIndex());
}
@Test
public void loadUserStoredGainIndex_setsCurrentGainIndexToDefault() {
CarAudioSettings settings =
generateCarAudioSettings(TEST_USER_10, 0, 0, 10);
CarVolumeGroup carVolumeGroup = new CarVolumeGroup(settings, 0, 0);
CarAudioDeviceInfo deviceInfo = generateCarAudioDeviceInfo(
NAVIGATION_DEVICE_ADDRESS, STEP_VALUE, MIN_GAIN, MAX_GAIN);
carVolumeGroup.bind(CarAudioContext.NAVIGATION, deviceInfo);
carVolumeGroup.setCurrentGainIndex(2);
assertEquals(2, carVolumeGroup.getCurrentGainIndex());
carVolumeGroup.loadVolumesForUser(0);
assertEquals(0, carVolumeGroup.getCurrentGainIndex());
}
@Test
public void setCurrentGainIndex_setsCurrentGainIndexForUser() {
List<Integer> users = new ArrayList<>();
users.add(TEST_USER_11);
Map<Integer, Integer> storedGainIndex = new HashMap<>();
storedGainIndex.put(TEST_USER_11, 2);
CarAudioSettings settings =
generateCarAudioSettings(users, 0 , 0, storedGainIndex);
CarVolumeGroup carVolumeGroup = new CarVolumeGroup(settings, 0, 0);
CarAudioDeviceInfo deviceInfo = generateCarAudioDeviceInfo(
NAVIGATION_DEVICE_ADDRESS, STEP_VALUE, MIN_GAIN, MAX_GAIN);
carVolumeGroup.bind(CarAudioContext.NAVIGATION, deviceInfo);
carVolumeGroup.loadVolumesForUser(TEST_USER_11);
carVolumeGroup.setCurrentGainIndex(MIN_GAIN);
verify(settings).storeVolumeGainIndexForUser(TEST_USER_11, 0, 0, MIN_GAIN);
}
@Test
public void setCurrentGainIndex_setsCurrentGainIndexForDefaultUser() {
List<Integer> users = new ArrayList<>();
users.add(UserHandle.USER_CURRENT);
Map<Integer, Integer> storedGainIndex = new HashMap<>();
storedGainIndex.put(UserHandle.USER_CURRENT, 2);
CarAudioSettings settings =
generateCarAudioSettings(users, 0 , 0, storedGainIndex);
CarVolumeGroup carVolumeGroup = new CarVolumeGroup(settings, 0, 0);
CarAudioDeviceInfo deviceInfo = generateCarAudioDeviceInfo(
NAVIGATION_DEVICE_ADDRESS, STEP_VALUE, MIN_GAIN, MAX_GAIN);
carVolumeGroup.bind(CarAudioContext.NAVIGATION, deviceInfo);
carVolumeGroup.setCurrentGainIndex(MIN_GAIN);
verify(settings)
.storeVolumeGainIndexForUser(UserHandle.USER_CURRENT, 0, 0, MIN_GAIN);
}
@Test
public void bind_setsCurrentGainIndexToStoredGainIndex() {
CarAudioSettings settings =
generateCarAudioSettings(0 , 0, 2);
CarVolumeGroup carVolumeGroup = new CarVolumeGroup(settings, 0, 0);
CarAudioDeviceInfo deviceInfo = generateCarAudioDeviceInfo(
NAVIGATION_DEVICE_ADDRESS, STEP_VALUE, MIN_GAIN, MAX_GAIN);
carVolumeGroup.bind(CarAudioContext.NAVIGATION, deviceInfo);
assertEquals(2, carVolumeGroup.getCurrentGainIndex());
}
@Test
public void getAddressForContext_returnsExpectedDeviceAddress() {
CarAudioSettings settings =
generateCarAudioSettings(0 , 0, 2);
CarVolumeGroup carVolumeGroup = new CarVolumeGroup(settings, 0, 0);
carVolumeGroup.bind(CarAudioContext.MUSIC, mMediaDevice);
String mediaAddress = carVolumeGroup.getAddressForContext(CarAudioContext.MUSIC);
assertEquals(mMediaDevice.getAddress(), mediaAddress);
}
@Test
public void getAddressForContext_returnsNull() {
CarAudioSettings settings =
generateCarAudioSettings(0 , 0, 2);
CarVolumeGroup carVolumeGroup = new CarVolumeGroup(settings, 0, 0);
String nullAddress = carVolumeGroup.getAddressForContext(CarAudioContext.MUSIC);
assertNull(nullAddress);
}
private CarVolumeGroup testVolumeGroupSetup() {
CarAudioSettings settings =
generateCarAudioSettings(0 , 0, 2);
CarVolumeGroup carVolumeGroup = new CarVolumeGroup(settings, 0, 0);
carVolumeGroup.bind(CarAudioContext.MUSIC, mMediaDevice);
carVolumeGroup.bind(CarAudioContext.CALL, mMediaDevice);
carVolumeGroup.bind(CarAudioContext.CALL_RING, mMediaDevice);
carVolumeGroup.bind(CarAudioContext.NAVIGATION, mNavigationDevice);
carVolumeGroup.bind(CarAudioContext.ALARM, mNavigationDevice);
carVolumeGroup.bind(CarAudioContext.NOTIFICATION, mNavigationDevice);
return carVolumeGroup;
}
private CarAudioDeviceInfo generateCarAudioDeviceInfo(String address) {
return generateCarAudioDeviceInfo(address, STEP_VALUE, MIN_GAIN, MAX_GAIN);
}
private CarAudioDeviceInfo generateCarAudioDeviceInfo(String address, int stepValue,
int minGain, int maxGain) {
CarAudioDeviceInfo cadiMock = Mockito.mock(CarAudioDeviceInfo.class);
when(cadiMock.getStepValue()).thenReturn(stepValue);
when(cadiMock.getDefaultGain()).thenReturn(DEFAULT_GAIN);
when(cadiMock.getMaxGain()).thenReturn(maxGain);
when(cadiMock.getMinGain()).thenReturn(minGain);
when(cadiMock.getAddress()).thenReturn(address);
return cadiMock;
}
private CarAudioSettings generateCarAudioSettings(int userId,
int zoneId, int id, int storedGainIndex) {
CarAudioSettings settingsMock = Mockito.mock(CarAudioSettings.class);
when(settingsMock.getStoredVolumeGainIndexForUser(userId, zoneId, id))
.thenReturn(storedGainIndex);
return settingsMock;
}
private CarAudioSettings generateCarAudioSettings(
int zoneId, int id, int storedGainIndex) {
CarAudioSettings settingsMock = Mockito.mock(CarAudioSettings.class);
when(settingsMock.getStoredVolumeGainIndexForUser(anyInt(), eq(zoneId),
eq(id))).thenReturn(storedGainIndex);
return settingsMock;
}
private CarAudioSettings generateCarAudioSettings(List<Integer> users,
int zoneId, int id, Map<Integer, Integer> storedGainIndex) {
CarAudioSettings settingsMock = Mockito.mock(CarAudioSettings.class);
for (Integer user : users) {
when(settingsMock.getStoredVolumeGainIndexForUser(user, zoneId,
id)).thenReturn(storedGainIndex.get(user));
}
return settingsMock;
}
}