diff options
author | 2024-10-11 02:40:29 +0000 | |
---|---|---|
committer | 2024-10-11 02:40:29 +0000 | |
commit | 3c7007a602684e686f01646f73de92ebae758ad4 (patch) | |
tree | 4ece441dd0ab5c1d6770928df01f0b1db0423fff | |
parent | 41757859a4f80456a9ca7b5f2ae4f2dde85e4ac3 (diff) | |
parent | 8f0f00551c7ed1de0c827b65cce6aaeb5a74a2ee (diff) |
Merge "Apply default selected device to all presets" into main
2 files changed, 214 insertions, 121 deletions
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/InputRouteManager.java b/packages/SettingsLib/src/com/android/settingslib/media/InputRouteManager.java index 727662b80d98..4f315a2a2486 100644 --- a/packages/SettingsLib/src/com/android/settingslib/media/InputRouteManager.java +++ b/packages/SettingsLib/src/com/android/settingslib/media/InputRouteManager.java @@ -22,6 +22,7 @@ import android.media.AudioAttributes; import android.media.AudioDeviceAttributes; import android.media.AudioDeviceCallback; import android.media.AudioDeviceInfo; +import android.media.AudioDeviceInfo.AudioDeviceType; import android.media.AudioManager; import android.media.MediaRecorder; import android.os.Handler; @@ -63,7 +64,7 @@ public final class InputRouteManager { @VisibleForTesting final List<MediaDevice> mInputMediaDevices = new CopyOnWriteArrayList<>(); - private MediaDevice mSelectedInputDevice; + private @AudioDeviceType int mSelectedInputDeviceType; private final Collection<InputDeviceCallback> mCallbacks = new CopyOnWriteArrayList<>(); private final Object mCallbackLock = new Object(); @@ -73,12 +74,12 @@ public final class InputRouteManager { new AudioDeviceCallback() { @Override public void onAudioDevicesAdded(@NonNull AudioDeviceInfo[] addedDevices) { - dispatchInputDeviceListUpdate(); + applyDefaultSelectedTypeToAllPresets(); } @Override public void onAudioDevicesRemoved(@NonNull AudioDeviceInfo[] removedDevices) { - dispatchInputDeviceListUpdate(); + applyDefaultSelectedTypeToAllPresets(); } }; @@ -92,9 +93,12 @@ public final class InputRouteManager { mAudioManager.addOnPreferredDevicesForCapturePresetChangedListener( new HandlerExecutor(handler), this::onPreferredDevicesForCapturePresetChangedListener); + + applyDefaultSelectedTypeToAllPresets(); } - private void onPreferredDevicesForCapturePresetChangedListener( + @VisibleForTesting + void onPreferredDevicesForCapturePresetChangedListener( @MediaRecorder.SystemSource int capturePreset, @NonNull List<AudioDeviceAttributes> devices) { if (capturePreset == MediaRecorder.AudioSource.MIC) { @@ -117,12 +121,30 @@ public final class InputRouteManager { } } + // TODO(b/355684672): handle edge case where there are two devices with the same type. Only + // using a single mSelectedInputDeviceType might not be enough to recognize the correct device. public @Nullable MediaDevice getSelectedInputDevice() { - return mSelectedInputDevice; + for (MediaDevice device : mInputMediaDevices) { + if (((InputMediaDevice) device).getAudioDeviceInfoType() == mSelectedInputDeviceType) { + return device; + } + } + return null; } - private void dispatchInputDeviceListUpdate() { - // Get selected input device. + private void applyDefaultSelectedTypeToAllPresets() { + mSelectedInputDeviceType = retrieveDefaultSelectedDeviceType(); + AudioDeviceAttributes deviceAttributes = + createInputDeviceAttributes(mSelectedInputDeviceType); + setPreferredDeviceForAllPresets(deviceAttributes); + } + + private AudioDeviceAttributes createInputDeviceAttributes(@AudioDeviceType int type) { + // Address is not used. + return new AudioDeviceAttributes(AudioDeviceAttributes.ROLE_INPUT, type, /* address= */ ""); + } + + private @AudioDeviceType int retrieveDefaultSelectedDeviceType() { List<AudioDeviceAttributes> attributesOfSelectedInputDevices = mAudioManager.getDevicesForAttributes(INPUT_ATTRIBUTES); int selectedInputDeviceAttributesType; @@ -138,7 +160,10 @@ public final class InputRouteManager { } selectedInputDeviceAttributesType = attributesOfSelectedInputDevices.get(0).getType(); } + return selectedInputDeviceAttributesType; + } + private void dispatchInputDeviceListUpdate() { // Get all input devices. AudioDeviceInfo[] audioDeviceInfos = mAudioManager.getDevices(AudioManager.GET_DEVICES_INPUTS); @@ -154,9 +179,8 @@ public final class InputRouteManager { isInputGainFixed(), getProductNameFromAudioDeviceInfo(info)); if (mediaDevice != null) { - if (info.getType() == selectedInputDeviceAttributesType) { + if (info.getType() == mSelectedInputDeviceType) { mediaDevice.setState(STATE_SELECTED); - mSelectedInputDevice = mediaDevice; } mInputMediaDevices.add(mediaDevice); } @@ -190,12 +214,12 @@ public final class InputRouteManager { } public void selectDevice(@NonNull MediaDevice device) { - if (!(device instanceof InputMediaDevice)) { + if (!(device instanceof InputMediaDevice inputMediaDevice)) { Slog.w(TAG, "This device is not an InputMediaDevice: " + device.getName()); return; } - if (device.equals(mSelectedInputDevice)) { + if (inputMediaDevice.getAudioDeviceInfoType() == mSelectedInputDeviceType) { Slog.w(TAG, "This device is already selected: " + device.getName()); return; } @@ -206,12 +230,11 @@ public final class InputRouteManager { return; } - // TODO(b/355684672): apply address for BT devices. + // Update mSelectedInputDeviceType directly based on user action. + mSelectedInputDeviceType = inputMediaDevice.getAudioDeviceInfoType(); + AudioDeviceAttributes deviceAttributes = - new AudioDeviceAttributes( - AudioDeviceAttributes.ROLE_INPUT, - ((InputMediaDevice) device).getAudioDeviceInfoType(), - /* address= */ ""); + createInputDeviceAttributes(inputMediaDevice.getAudioDeviceInfoType()); try { setPreferredDeviceForAllPresets(deviceAttributes); } catch (IllegalArgumentException e) { diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InputRouteManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InputRouteManagerTest.java index f63bfc70140d..782cee23fb42 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InputRouteManagerTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InputRouteManagerTest.java @@ -21,6 +21,7 @@ import static com.android.settingslib.media.InputRouteManager.PRESETS; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Mockito.atLeast; import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; @@ -55,6 +56,7 @@ public class InputRouteManagerTest { private static final int INPUT_USB_DEVICE_ID = 3; private static final int INPUT_USB_HEADSET_ID = 4; private static final int INPUT_USB_ACCESSORY_ID = 5; + private static final int HDMI_ID = 6; private static final int MAX_VOLUME = 1; private static final int CURRENT_VOLUME = 0; private static final boolean VOLUME_FIXED_TRUE = true; @@ -63,10 +65,86 @@ public class InputRouteManagerTest { private static final String PRODUCT_NAME_USB_HEADSET = "My USB Headset"; private static final String PRODUCT_NAME_USB_DEVICE = "My USB Device"; private static final String PRODUCT_NAME_USB_ACCESSORY = "My USB Accessory"; + private static final String PRODUCT_NAME_HDMI_DEVICE = "HDMI device"; private final Context mContext = spy(RuntimeEnvironment.application); private InputRouteManager mInputRouteManager; + private AudioDeviceInfo mockBuiltinMicInfo() { + final AudioDeviceInfo info = mock(AudioDeviceInfo.class); + when(info.getType()).thenReturn(AudioDeviceInfo.TYPE_BUILTIN_MIC); + when(info.getId()).thenReturn(BUILTIN_MIC_ID); + when(info.getAddress()).thenReturn(""); + when(info.getProductName()).thenReturn(PRODUCT_NAME_BUILTIN_MIC); + return info; + } + + private AudioDeviceInfo mockWiredHeadsetInfo() { + final AudioDeviceInfo info = mock(AudioDeviceInfo.class); + when(info.getType()).thenReturn(AudioDeviceInfo.TYPE_WIRED_HEADSET); + when(info.getId()).thenReturn(INPUT_WIRED_HEADSET_ID); + when(info.getAddress()).thenReturn(""); + when(info.getProductName()).thenReturn(PRODUCT_NAME_WIRED_HEADSET); + return info; + } + + private AudioDeviceInfo mockUsbDeviceInfo() { + final AudioDeviceInfo info = mock(AudioDeviceInfo.class); + when(info.getType()).thenReturn(AudioDeviceInfo.TYPE_USB_DEVICE); + when(info.getId()).thenReturn(INPUT_USB_DEVICE_ID); + when(info.getAddress()).thenReturn(""); + when(info.getProductName()).thenReturn(PRODUCT_NAME_USB_DEVICE); + return info; + } + + private AudioDeviceInfo mockUsbHeadsetInfo() { + final AudioDeviceInfo info = mock(AudioDeviceInfo.class); + when(info.getType()).thenReturn(AudioDeviceInfo.TYPE_USB_HEADSET); + when(info.getId()).thenReturn(INPUT_USB_HEADSET_ID); + when(info.getAddress()).thenReturn(""); + when(info.getProductName()).thenReturn(PRODUCT_NAME_USB_HEADSET); + return info; + } + + private AudioDeviceInfo mockUsbAccessoryInfo() { + final AudioDeviceInfo info = mock(AudioDeviceInfo.class); + when(info.getType()).thenReturn(AudioDeviceInfo.TYPE_USB_ACCESSORY); + when(info.getId()).thenReturn(INPUT_USB_ACCESSORY_ID); + when(info.getAddress()).thenReturn(""); + when(info.getProductName()).thenReturn(PRODUCT_NAME_USB_ACCESSORY); + return info; + } + + private AudioDeviceInfo mockHdmiInfo() { + final AudioDeviceInfo info = mock(AudioDeviceInfo.class); + when(info.getType()).thenReturn(AudioDeviceInfo.TYPE_HDMI); + when(info.getId()).thenReturn(HDMI_ID); + when(info.getAddress()).thenReturn(""); + when(info.getProductName()).thenReturn(PRODUCT_NAME_HDMI_DEVICE); + return info; + } + + private AudioDeviceAttributes getBuiltinMicDeviceAttributes() { + return new AudioDeviceAttributes( + AudioDeviceAttributes.ROLE_INPUT, + AudioDeviceInfo.TYPE_BUILTIN_MIC, + /* address= */ ""); + } + + private AudioDeviceAttributes getWiredHeadsetDeviceAttributes() { + return new AudioDeviceAttributes( + AudioDeviceAttributes.ROLE_INPUT, + AudioDeviceInfo.TYPE_WIRED_HEADSET, + /* address= */ ""); + } + + private void onPreferredDevicesForCapturePresetChanged(InputRouteManager inputRouteManager) { + final List<AudioDeviceAttributes> audioDeviceAttributesList = + new ArrayList<AudioDeviceAttributes>(); + inputRouteManager.onPreferredDevicesForCapturePresetChangedListener( + MediaRecorder.AudioSource.MIC, audioDeviceAttributesList); + } + @Before public void setUp() { MockitoAnnotations.initMocks(this); @@ -77,37 +155,15 @@ public class InputRouteManagerTest { @Test public void onAudioDevicesAdded_shouldUpdateInputMediaDevice() { - final AudioDeviceInfo info1 = mock(AudioDeviceInfo.class); - when(info1.getType()).thenReturn(AudioDeviceInfo.TYPE_BUILTIN_MIC); - when(info1.getId()).thenReturn(BUILTIN_MIC_ID); - when(info1.getProductName()).thenReturn(PRODUCT_NAME_BUILTIN_MIC); - - final AudioDeviceInfo info2 = mock(AudioDeviceInfo.class); - when(info2.getType()).thenReturn(AudioDeviceInfo.TYPE_WIRED_HEADSET); - when(info2.getId()).thenReturn(INPUT_WIRED_HEADSET_ID); - when(info2.getProductName()).thenReturn(PRODUCT_NAME_WIRED_HEADSET); - - final AudioDeviceInfo info3 = mock(AudioDeviceInfo.class); - when(info3.getType()).thenReturn(AudioDeviceInfo.TYPE_USB_DEVICE); - when(info3.getId()).thenReturn(INPUT_USB_DEVICE_ID); - when(info3.getProductName()).thenReturn(PRODUCT_NAME_USB_DEVICE); - - final AudioDeviceInfo info4 = mock(AudioDeviceInfo.class); - when(info4.getType()).thenReturn(AudioDeviceInfo.TYPE_USB_HEADSET); - when(info4.getId()).thenReturn(INPUT_USB_HEADSET_ID); - when(info4.getProductName()).thenReturn(PRODUCT_NAME_USB_HEADSET); - - final AudioDeviceInfo info5 = mock(AudioDeviceInfo.class); - when(info5.getType()).thenReturn(AudioDeviceInfo.TYPE_USB_ACCESSORY); - when(info5.getId()).thenReturn(INPUT_USB_ACCESSORY_ID); - when(info5.getProductName()).thenReturn(PRODUCT_NAME_USB_ACCESSORY); - - final AudioDeviceInfo unsupportedInfo = mock(AudioDeviceInfo.class); - when(unsupportedInfo.getType()).thenReturn(AudioDeviceInfo.TYPE_HDMI); - when(unsupportedInfo.getProductName()).thenReturn("HDMI device"); - final AudioManager audioManager = mock(AudioManager.class); - AudioDeviceInfo[] devices = {info1, info2, info3, info4, info5, unsupportedInfo}; + AudioDeviceInfo[] devices = { + mockBuiltinMicInfo(), + mockWiredHeadsetInfo(), + mockUsbDeviceInfo(), + mockUsbHeadsetInfo(), + mockUsbAccessoryInfo(), + mockHdmiInfo() + }; when(audioManager.getDevices(AudioManager.GET_DEVICES_INPUTS)).thenReturn(devices); InputRouteManager inputRouteManager = new InputRouteManager(mContext, audioManager); @@ -115,8 +171,9 @@ public class InputRouteManagerTest { assertThat(inputRouteManager.mInputMediaDevices).isEmpty(); inputRouteManager.mAudioDeviceCallback.onAudioDevicesAdded(devices); + onPreferredDevicesForCapturePresetChanged(inputRouteManager); - // The unsupported info should be filtered out. + // The unsupported (hdmi) info should be filtered out. assertThat(inputRouteManager.mInputMediaDevices).hasSize(devices.length - 1); assertThat(inputRouteManager.mInputMediaDevices.get(0).getId()) .isEqualTo(String.valueOf(BUILTIN_MIC_ID)); @@ -141,36 +198,25 @@ public class InputRouteManagerTest { final MediaDevice device = mock(MediaDevice.class); inputRouteManager.mInputMediaDevices.add(device); - final AudioDeviceInfo info = mock(AudioDeviceInfo.class); - when(info.getType()).thenReturn(AudioDeviceInfo.TYPE_WIRED_HEADSET); - inputRouteManager.mAudioDeviceCallback.onAudioDevicesRemoved(new AudioDeviceInfo[] {info}); + inputRouteManager.mAudioDeviceCallback.onAudioDevicesRemoved( + new AudioDeviceInfo[] {mockWiredHeadsetInfo()}); + onPreferredDevicesForCapturePresetChanged(inputRouteManager); assertThat(inputRouteManager.mInputMediaDevices).isEmpty(); } @Test public void getSelectedInputDevice_returnOneFromAudioManager() { - final AudioDeviceInfo info1 = mock(AudioDeviceInfo.class); - when(info1.getType()).thenReturn(AudioDeviceInfo.TYPE_WIRED_HEADSET); - when(info1.getId()).thenReturn(INPUT_WIRED_HEADSET_ID); - when(info1.getProductName()).thenReturn(PRODUCT_NAME_WIRED_HEADSET); - - final AudioDeviceInfo info2 = mock(AudioDeviceInfo.class); - when(info2.getType()).thenReturn(AudioDeviceInfo.TYPE_BUILTIN_MIC); - when(info2.getId()).thenReturn(BUILTIN_MIC_ID); - when(info2.getProductName()).thenReturn(PRODUCT_NAME_BUILTIN_MIC); - final AudioManager audioManager = mock(AudioManager.class); - AudioDeviceInfo[] devices = {info1, info2}; + AudioDeviceInfo[] devices = {mockWiredHeadsetInfo(), mockBuiltinMicInfo()}; when(audioManager.getDevices(AudioManager.GET_DEVICES_INPUTS)).thenReturn(devices); // Mock audioManager.getDevicesForAttributes returns exactly one audioDeviceAttributes. - AudioDeviceAttributes audioDeviceAttributes = new AudioDeviceAttributes(info1); when(audioManager.getDevicesForAttributes(INPUT_ATTRIBUTES)) - .thenReturn(Collections.singletonList(audioDeviceAttributes)); + .thenReturn(Collections.singletonList(getWiredHeadsetDeviceAttributes())); InputRouteManager inputRouteManager = new InputRouteManager(mContext, audioManager); - inputRouteManager.mAudioDeviceCallback.onAudioDevicesAdded(devices); + onPreferredDevicesForCapturePresetChanged(inputRouteManager); // The selected input device has the same type as the one returned from AudioManager. InputMediaDevice selectedInputDevice = @@ -181,31 +227,19 @@ public class InputRouteManagerTest { @Test public void getSelectedInputDevice_returnMoreThanOneFromAudioManager() { - final AudioDeviceInfo info1 = mock(AudioDeviceInfo.class); - when(info1.getType()).thenReturn(AudioDeviceInfo.TYPE_WIRED_HEADSET); - when(info1.getId()).thenReturn(INPUT_WIRED_HEADSET_ID); - when(info1.getProductName()).thenReturn(PRODUCT_NAME_WIRED_HEADSET); - - final AudioDeviceInfo info2 = mock(AudioDeviceInfo.class); - when(info2.getType()).thenReturn(AudioDeviceInfo.TYPE_BUILTIN_MIC); - when(info2.getId()).thenReturn(BUILTIN_MIC_ID); - when(info2.getProductName()).thenReturn(PRODUCT_NAME_BUILTIN_MIC); - final AudioManager audioManager = mock(AudioManager.class); - AudioDeviceInfo[] devices = {info1, info2}; + AudioDeviceInfo[] devices = {mockWiredHeadsetInfo(), mockBuiltinMicInfo()}; when(audioManager.getDevices(AudioManager.GET_DEVICES_INPUTS)).thenReturn(devices); // Mock audioManager.getDevicesForAttributes returns more than one audioDeviceAttributes. - AudioDeviceAttributes audioDeviceAttributes1 = new AudioDeviceAttributes(info1); - AudioDeviceAttributes audioDeviceAttributes2 = new AudioDeviceAttributes(info2); List<AudioDeviceAttributes> attributesOfSelectedInputDevices = new ArrayList<>(); - attributesOfSelectedInputDevices.add(audioDeviceAttributes1); - attributesOfSelectedInputDevices.add(audioDeviceAttributes2); + attributesOfSelectedInputDevices.add(getWiredHeadsetDeviceAttributes()); + attributesOfSelectedInputDevices.add(getBuiltinMicDeviceAttributes()); when(audioManager.getDevicesForAttributes(INPUT_ATTRIBUTES)) .thenReturn(attributesOfSelectedInputDevices); InputRouteManager inputRouteManager = new InputRouteManager(mContext, audioManager); - inputRouteManager.mAudioDeviceCallback.onAudioDevicesAdded(devices); + onPreferredDevicesForCapturePresetChanged(inputRouteManager); // The selected input device has the same type as the first one returned from AudioManager. InputMediaDevice selectedInputDevice = @@ -216,27 +250,17 @@ public class InputRouteManagerTest { @Test public void getSelectedInputDevice_returnEmptyFromAudioManager() { - final AudioDeviceInfo info1 = mock(AudioDeviceInfo.class); - when(info1.getType()).thenReturn(AudioDeviceInfo.TYPE_WIRED_HEADSET); - when(info1.getId()).thenReturn(INPUT_WIRED_HEADSET_ID); - when(info1.getProductName()).thenReturn(PRODUCT_NAME_WIRED_HEADSET); - - final AudioDeviceInfo info2 = mock(AudioDeviceInfo.class); - when(info2.getType()).thenReturn(AudioDeviceInfo.TYPE_BUILTIN_MIC); - when(info2.getId()).thenReturn(BUILTIN_MIC_ID); - when(info2.getProductName()).thenReturn(PRODUCT_NAME_BUILTIN_MIC); - final AudioManager audioManager = mock(AudioManager.class); - AudioDeviceInfo[] devices = {info1, info2}; + AudioDeviceInfo[] devices = {mockWiredHeadsetInfo(), mockBuiltinMicInfo()}; when(audioManager.getDevices(AudioManager.GET_DEVICES_INPUTS)).thenReturn(devices); // Mock audioManager.getDevicesForAttributes returns empty list of audioDeviceAttributes. - List<AudioDeviceAttributes> attributesOfSelectedInputDevices = new ArrayList<>(); + List<AudioDeviceAttributes> emptyAttributesOfSelectedInputDevices = new ArrayList<>(); when(audioManager.getDevicesForAttributes(INPUT_ATTRIBUTES)) - .thenReturn(attributesOfSelectedInputDevices); + .thenReturn(emptyAttributesOfSelectedInputDevices); InputRouteManager inputRouteManager = new InputRouteManager(mContext, audioManager); - inputRouteManager.mAudioDeviceCallback.onAudioDevicesAdded(devices); + onPreferredDevicesForCapturePresetChanged(inputRouteManager); // The selected input device has default type AudioDeviceInfo.TYPE_BUILTIN_MIC. InputMediaDevice selectedInputDevice = @@ -249,7 +273,7 @@ public class InputRouteManagerTest { public void selectDevice() { final AudioManager audioManager = mock(AudioManager.class); InputRouteManager inputRouteManager = new InputRouteManager(mContext, audioManager); - final MediaDevice inputMediaDevice = + final MediaDevice builtinMicDevice = InputMediaDevice.create( mContext, String.valueOf(BUILTIN_MIC_ID), @@ -258,16 +282,57 @@ public class InputRouteManagerTest { CURRENT_VOLUME, VOLUME_FIXED_TRUE, PRODUCT_NAME_BUILTIN_MIC); - inputRouteManager.selectDevice(inputMediaDevice); + inputRouteManager.selectDevice(builtinMicDevice); - AudioDeviceAttributes deviceAttributes = - new AudioDeviceAttributes( - AudioDeviceAttributes.ROLE_INPUT, - AudioDeviceInfo.TYPE_BUILTIN_MIC, - /* address= */ ""); for (@MediaRecorder.Source int preset : PRESETS) { verify(audioManager, atLeastOnce()) - .setPreferredDeviceForCapturePreset(preset, deviceAttributes); + .setPreferredDeviceForCapturePreset(preset, getBuiltinMicDeviceAttributes()); + } + } + + @Test + public void onInitiation_shouldApplyDefaultSelectedDeviceToAllPresets() { + final AudioManager audioManager = mock(AudioManager.class); + new InputRouteManager(mContext, audioManager); + + verify(audioManager, atLeastOnce()).getDevicesForAttributes(INPUT_ATTRIBUTES); + for (@MediaRecorder.Source int preset : PRESETS) { + verify(audioManager, atLeastOnce()) + .setPreferredDeviceForCapturePreset(preset, getBuiltinMicDeviceAttributes()); + } + } + + @Test + public void onAudioDevicesAdded_shouldApplyDefaultSelectedDeviceToAllPresets() { + final AudioManager audioManager = mock(AudioManager.class); + AudioDeviceAttributes wiredHeadsetDeviceAttributes = getWiredHeadsetDeviceAttributes(); + when(audioManager.getDevicesForAttributes(INPUT_ATTRIBUTES)) + .thenReturn(Collections.singletonList(wiredHeadsetDeviceAttributes)); + + InputRouteManager inputRouteManager = new InputRouteManager(mContext, audioManager); + AudioDeviceInfo[] devices = {mockWiredHeadsetInfo()}; + inputRouteManager.mAudioDeviceCallback.onAudioDevicesAdded(devices); + + // Called twice, one after initiation, the other after onAudioDevicesAdded call. + verify(audioManager, atLeast(2)).getDevicesForAttributes(INPUT_ATTRIBUTES); + for (@MediaRecorder.Source int preset : PRESETS) { + verify(audioManager, atLeast(2)) + .setPreferredDeviceForCapturePreset(preset, wiredHeadsetDeviceAttributes); + } + } + + @Test + public void onAudioDevicesRemoved_shouldApplyDefaultSelectedDeviceToAllPresets() { + final AudioManager audioManager = mock(AudioManager.class); + InputRouteManager inputRouteManager = new InputRouteManager(mContext, audioManager); + AudioDeviceInfo[] devices = {mockWiredHeadsetInfo()}; + inputRouteManager.mAudioDeviceCallback.onAudioDevicesRemoved(devices); + + // Called twice, one after initiation, the other after onAudioDevicesRemoved call. + verify(audioManager, atLeast(2)).getDevicesForAttributes(INPUT_ATTRIBUTES); + for (@MediaRecorder.Source int preset : PRESETS) { + verify(audioManager, atLeast(2)) + .setPreferredDeviceForCapturePreset(preset, getBuiltinMicDeviceAttributes()); } } @@ -288,27 +353,25 @@ public class InputRouteManagerTest { @Test public void onAudioDevicesAdded_shouldSetProductNameCorrectly() { - final AudioDeviceInfo info1 = mock(AudioDeviceInfo.class); - when(info1.getType()).thenReturn(AudioDeviceInfo.TYPE_WIRED_HEADSET); - when(info1.getId()).thenReturn(INPUT_WIRED_HEADSET_ID); + final AudioDeviceInfo info1 = mockWiredHeadsetInfo(); String firstProductName = "My first headset"; when(info1.getProductName()).thenReturn(firstProductName); + InputMediaDevice inputMediaDevice1 = createInputMediaDeviceFromDeviceInfo(info1); - final AudioDeviceInfo info2 = mock(AudioDeviceInfo.class); - when(info2.getType()).thenReturn(AudioDeviceInfo.TYPE_WIRED_HEADSET); - when(info2.getId()).thenReturn(INPUT_WIRED_HEADSET_ID); + final AudioDeviceInfo info2 = mockWiredHeadsetInfo(); String secondProductName = "My second headset"; when(info2.getProductName()).thenReturn(secondProductName); + InputMediaDevice inputMediaDevice2 = createInputMediaDeviceFromDeviceInfo(info2); - final AudioDeviceInfo infoWithNullProductName = mock(AudioDeviceInfo.class); - when(infoWithNullProductName.getType()).thenReturn(AudioDeviceInfo.TYPE_WIRED_HEADSET); - when(infoWithNullProductName.getId()).thenReturn(INPUT_WIRED_HEADSET_ID); + final AudioDeviceInfo infoWithNullProductName = mockWiredHeadsetInfo(); when(infoWithNullProductName.getProductName()).thenReturn(null); + InputMediaDevice inputMediaDevice3 = + createInputMediaDeviceFromDeviceInfo(infoWithNullProductName); - final AudioDeviceInfo infoWithBlankProductName = mock(AudioDeviceInfo.class); - when(infoWithBlankProductName.getType()).thenReturn(AudioDeviceInfo.TYPE_WIRED_HEADSET); - when(infoWithBlankProductName.getId()).thenReturn(INPUT_WIRED_HEADSET_ID); + final AudioDeviceInfo infoWithBlankProductName = mockWiredHeadsetInfo(); when(infoWithBlankProductName.getProductName()).thenReturn(""); + InputMediaDevice inputMediaDevice4 = + createInputMediaDeviceFromDeviceInfo(infoWithBlankProductName); final AudioManager audioManager = mock(AudioManager.class); AudioDeviceInfo[] devices = { @@ -321,15 +384,22 @@ public class InputRouteManagerTest { assertThat(inputRouteManager.mInputMediaDevices).isEmpty(); inputRouteManager.mAudioDeviceCallback.onAudioDevicesAdded(devices); + onPreferredDevicesForCapturePresetChanged(inputRouteManager); - assertThat(getProductNameAtIndex(inputRouteManager, 1)).isEqualTo(firstProductName); - assertThat(getProductNameAtIndex(inputRouteManager, 2)).isEqualTo(secondProductName); - assertThat(getProductNameAtIndex(inputRouteManager, 3)).isNull(); - assertThat(getProductNameAtIndex(inputRouteManager, 4)).isNull(); + assertThat(inputRouteManager.mInputMediaDevices) + .containsExactly( + inputMediaDevice1, inputMediaDevice2, inputMediaDevice3, inputMediaDevice4) + .inOrder(); } - private String getProductNameAtIndex(InputRouteManager inputRouteManager, int index) { - return ((InputMediaDevice) inputRouteManager.mInputMediaDevices.get(index)) - .getProductName(); + private InputMediaDevice createInputMediaDeviceFromDeviceInfo(AudioDeviceInfo info) { + return InputMediaDevice.create( + mContext, + String.valueOf(info.getId()), + info.getType(), + MAX_VOLUME, + CURRENT_VOLUME, + VOLUME_FIXED_TRUE, + info.getProductName() == null ? null : info.getProductName().toString()); } } |