Loading services/core/java/com/android/server/media/AudioManagerRouteController.java +24 −8 Original line number Diff line number Diff line Loading @@ -50,6 +50,7 @@ import android.util.SparseArray; import com.android.internal.R; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import java.util.ArrayList; import java.util.Arrays; Loading Loading @@ -171,6 +172,26 @@ import java.util.concurrent.CopyOnWriteArrayList; @NonNull Looper looper, @NonNull AudioProductStrategy strategyForMedia, @NonNull BluetoothAdapter btAdapter) { this( context, audioManager, looper, strategyForMedia, new BluetoothDeviceRoutesManager(context, looper, btAdapter)); } @RequiresPermission( anyOf = { Manifest.permission.MODIFY_AUDIO_ROUTING, Manifest.permission.QUERY_AUDIO_STATE }) @VisibleForTesting /* package */ AudioManagerRouteController( @NonNull Context context, @NonNull AudioManager audioManager, @NonNull Looper looper, @NonNull AudioProductStrategy strategyForMedia, @NonNull BluetoothDeviceRoutesManager bluetoothDeviceRoutesManager) { mContext = Objects.requireNonNull(context); mAudioManager = Objects.requireNonNull(audioManager); mHandler = new Handler(Objects.requireNonNull(looper)); Loading @@ -182,13 +203,7 @@ import java.util.concurrent.CopyOnWriteArrayList; mBuiltInSpeakerSuitabilityStatus = DeviceRouteController.getBuiltInSpeakerSuitabilityStatus(mContext); mBluetoothRouteController = new BluetoothDeviceRoutesManager( mContext, mHandler, looper, btAdapter, this::rebuildAvailableRoutesAndNotify); mBluetoothRouteController = Objects.requireNonNull(bluetoothDeviceRoutesManager); // Just build routes but don't notify. The caller may not expect the listener to be invoked // before this constructor has finished executing. rebuildAvailableRoutes(); Loading Loading @@ -220,7 +235,8 @@ import java.util.concurrent.CopyOnWriteArrayList; mBluetoothRouteController.start( com.android.media.flags.Flags.enableUseOfSingletonAudioManagerRouteController() ? UserHandle.SYSTEM : mUser); : mUser, this::rebuildAvailableRoutesAndNotify); mAudioManager.registerAudioDeviceCallback(mAudioDeviceCallback, mHandler); mAudioManager.addOnDevicesForAttributesChangedListener( AudioRoutingUtils.ATTRIBUTES_MEDIA, Loading services/core/java/com/android/server/media/BluetoothDeviceRoutesManager.java +12 −13 Original line number Diff line number Diff line Loading @@ -91,39 +91,37 @@ import java.util.stream.Collectors; private final Context mContext; @NonNull private final Handler mHandler; @NonNull private final BluetoothAdapter mBluetoothAdapter; @NonNull private final BluetoothRoutesUpdatedListener mListener; @NonNull private BluetoothRoutesUpdatedListener mListener; @NonNull private final BluetoothProfileMonitor mBluetoothProfileMonitor; BluetoothDeviceRoutesManager( @NonNull Context context, @NonNull Handler handler, @NonNull Looper looper, @NonNull BluetoothAdapter bluetoothAdapter, @NonNull BluetoothRoutesUpdatedListener listener) { @NonNull BluetoothAdapter bluetoothAdapter) { this( context, handler, looper, bluetoothAdapter, new BluetoothProfileMonitor(context, looper, bluetoothAdapter), listener); new BluetoothProfileMonitor(context, looper, bluetoothAdapter)); } @VisibleForTesting BluetoothDeviceRoutesManager( @NonNull Context context, @NonNull Handler handler, @NonNull Looper looper, @NonNull BluetoothAdapter bluetoothAdapter, @NonNull BluetoothProfileMonitor bluetoothProfileMonitor, @NonNull BluetoothRoutesUpdatedListener listener) { @NonNull BluetoothProfileMonitor bluetoothProfileMonitor) { mContext = Objects.requireNonNull(context); mHandler = handler; mHandler = new Handler(Objects.requireNonNull(looper)); mBluetoothAdapter = Objects.requireNonNull(bluetoothAdapter); mBluetoothProfileMonitor = Objects.requireNonNull(bluetoothProfileMonitor); mListener = Objects.requireNonNull(listener); // no-op listener, will be overrode in start() mListener = () -> {}; } public void start(UserHandle user) { public void start(UserHandle user, @NonNull BluetoothRoutesUpdatedListener listener) { mListener = listener; mBluetoothProfileMonitor.start(); IntentFilter adapterStateChangedIntentFilter = new IntentFilter(); Loading Loading @@ -346,6 +344,7 @@ import java.util.stream.Collectors; } return deviceName; } private SparseBooleanArray getConnectedProfiles(@NonNull BluetoothDevice device) { SparseBooleanArray connectedProfiles = new SparseBooleanArray(); if (mBluetoothProfileMonitor.isProfileSupported(BluetoothProfile.A2DP, device)) { Loading services/tests/media/mediarouterservicetest/src/com/android/server/media/AudioManagerRouteControllerTest.java +52 −25 Original line number Diff line number Diff line Loading @@ -107,6 +107,9 @@ public class AudioManagerRouteControllerTest { private Set<AudioDeviceInfo> mAvailableAudioDeviceInfos; @Mock private AudioManager mMockAudioManager; @Mock private DeviceRouteController.EventListener mEventListener; @Mock private BluetoothDeviceRoutesManager mMockBluetoothDeviceRoutesManager; @Mock private Context mMockContext; private Context mRealContext; private AudioManagerRouteController mControllerUnderTest; private AudioDeviceCallback mAudioDeviceCallback; private AudioProductStrategy mMediaAudioProductStrategy; Loading @@ -118,15 +121,14 @@ public class AudioManagerRouteControllerTest { mInstrumentation.getUiAutomation().adoptShellPermissionIdentity(MODIFY_AUDIO_ROUTING); Resources mockResources = Mockito.mock(Resources.class); when(mockResources.getText(anyInt())).thenReturn(FAKE_ROUTE_NAME); Context realContext = mInstrumentation.getContext(); Context mockContext = Mockito.mock(Context.class); when(mockContext.getResources()).thenReturn(mockResources); mRealContext = mInstrumentation.getContext(); when(mMockContext.getResources()).thenReturn(mockResources); // The bluetooth stack needs the application info, but we cannot use a spy because the // concrete class is package private, so we just return the application info through the // mock. when(mockContext.getApplicationInfo()).thenReturn(realContext.getApplicationInfo()); when(mMockContext.getApplicationInfo()).thenReturn(mRealContext.getApplicationInfo()); // Needed to check if it is a TV device. when(mockContext.getPackageManager()).thenReturn(realContext.getPackageManager()); when(mMockContext.getPackageManager()).thenReturn(mRealContext.getPackageManager()); // Setup the initial state so that the route controller is created in a sensible state. mSelectedAudioDeviceInfo = FAKE_AUDIO_DEVICE_INFO_BUILTIN_SPEAKER; Loading @@ -134,26 +136,7 @@ public class AudioManagerRouteControllerTest { updateMockAudioManagerState(); mMediaAudioProductStrategy = getMediaAudioProductStrategy(); BluetoothAdapter btAdapter = realContext.getSystemService(BluetoothManager.class).getAdapter(); mControllerUnderTest = new AudioManagerRouteController( mockContext, mMockAudioManager, Looper.getMainLooper(), mMediaAudioProductStrategy, btAdapter); mControllerUnderTest.registerRouteChangeListener(mEventListener); mControllerUnderTest.start(UserHandle.CURRENT_OR_SELF); ArgumentCaptor<AudioDeviceCallback> deviceCallbackCaptor = ArgumentCaptor.forClass(AudioDeviceCallback.class); verify(mMockAudioManager) .registerAudioDeviceCallback(deviceCallbackCaptor.capture(), any()); mAudioDeviceCallback = deviceCallbackCaptor.getValue(); // We clear any invocations during setup. clearInvocations(mEventListener); // Need call setUpControllerUnderTest before each test case. } @After Loading @@ -163,6 +146,7 @@ public class AudioManagerRouteControllerTest { @Test public void getSelectedRoute_afterDevicesConnect_returnsRightSelectedRoute() { setUpControllerUnderTest(/* useMockBluetoothDeviceRoutesManager= */ false); assertThat(mControllerUnderTest.getSelectedRoutes().getFirst().getType()) .isEqualTo(MediaRoute2Info.TYPE_BUILTIN_SPEAKER); Loading @@ -182,6 +166,7 @@ public class AudioManagerRouteControllerTest { @Test public void getSelectedRoute_afterDeviceRemovals_returnsExpectedRoutes() { setUpControllerUnderTest(/* useMockBluetoothDeviceRoutesManager= */ false); addAvailableAudioDeviceInfo( /* newSelectedDevice= */ FAKE_AUDIO_DEVICE_INFO_WIRED_HEADSET, /* newAvailableDevices...= */ FAKE_AUDIO_DEVICE_INFO_BLUETOOTH_A2DP, Loading Loading @@ -210,6 +195,7 @@ public class AudioManagerRouteControllerTest { @Test public void onAudioDevicesAdded_clearsAudioRoutingPoliciesCorrectly() { setUpControllerUnderTest(/* useMockBluetoothDeviceRoutesManager= */ false); clearInvocations(mMockAudioManager); addAvailableAudioDeviceInfo( /* newSelectedDevice= */ null, // Selected device doesn't change. Loading @@ -224,6 +210,7 @@ public class AudioManagerRouteControllerTest { @Test public void getAvailableDevices_ignoresInvalidMediaOutputs() { setUpControllerUnderTest(/* useMockBluetoothDeviceRoutesManager= */ false); addAvailableAudioDeviceInfo( /* newSelectedDevice= */ null, // Selected device doesn't change. /* newAvailableDevices...= */ FAKE_AUDIO_DEVICE_BUILTIN_EARPIECE); Loading @@ -239,6 +226,7 @@ public class AudioManagerRouteControllerTest { @Test public void transferTo_setsTheExpectedRoutingPolicy() { setUpControllerUnderTest(/* useMockBluetoothDeviceRoutesManager= */ false); addAvailableAudioDeviceInfo( /* newSelectedDevice= */ FAKE_AUDIO_DEVICE_INFO_WIRED_HEADSET, /* newAvailableDevices...= */ FAKE_AUDIO_DEVICE_INFO_BLUETOOTH_A2DP, Loading @@ -264,6 +252,7 @@ public class AudioManagerRouteControllerTest { @Test public void updateVolume_propagatesCorrectlyToRouteInfo() { setUpControllerUnderTest(/* useMockBluetoothDeviceRoutesManager= */ false); when(mMockAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC)).thenReturn(2); when(mMockAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC)).thenReturn(3); when(mMockAudioManager.getStreamMinVolume(AudioManager.STREAM_MUSIC)).thenReturn(1); Loading Loading @@ -303,6 +292,7 @@ public class AudioManagerRouteControllerTest { @Test public void getAvailableRoutes_whenNoProductNameIsProvided_usesTypeToPopulateName() { setUpControllerUnderTest(/* useMockBluetoothDeviceRoutesManager= */ false); assertThat(mControllerUnderTest.getSelectedRoutes().getFirst().getName().toString()) .isEqualTo(FAKE_AUDIO_DEVICE_INFO_BUILTIN_SPEAKER.getProductName().toString()); Loading @@ -316,6 +306,7 @@ public class AudioManagerRouteControllerTest { @Test public void getAvailableRoutes_whenAddressIsPopulatedForNonBluetoothDevice_usesCorrectName() { setUpControllerUnderTest(/* useMockBluetoothDeviceRoutesManager= */ false); addAvailableAudioDeviceInfo( /* newSelectedDevice= */ FAKE_AUDIO_DEVICE_INFO_WIRED_HEADSET_WITH_ADDRESS, /* newAvailableDevices...= */ FAKE_AUDIO_DEVICE_INFO_WIRED_HEADSET_WITH_ADDRESS, Loading Loading @@ -343,6 +334,7 @@ public class AudioManagerRouteControllerTest { @Test public void getAvailableRoutes_whenAddressIsNotPopulatedForNonBluetoothDevice_usesCorrectName() { setUpControllerUnderTest(/* useMockBluetoothDeviceRoutesManager= */ false); addAvailableAudioDeviceInfo( /* newSelectedDevice= */ FAKE_AUDIO_DEVICE_INFO_WIRED_HEADSET, /* newAvailableDevices...= */ FAKE_AUDIO_DEVICE_INFO_WIRED_HEADSET); Loading @@ -365,6 +357,7 @@ public class AudioManagerRouteControllerTest { @Test public void getSessionReleaseType_returnTypeSharing() { setUpControllerUnderTest(/* useMockBluetoothDeviceRoutesManager= */ false); when(mMockAudioManager.getDevicesForAttributes(ATTRIBUTES_MEDIA)) .thenReturn( List.of( Loading @@ -376,6 +369,7 @@ public class AudioManagerRouteControllerTest { @Test public void getSessionReleaseType_returnTypeUnsupported() { setUpControllerUnderTest(/* useMockBluetoothDeviceRoutesManager= */ false); when(mMockAudioManager.getDevicesForAttributes(ATTRIBUTES_MEDIA)) .thenReturn( List.of( Loading @@ -387,6 +381,39 @@ public class AudioManagerRouteControllerTest { // Internal methods. private void setUpControllerUnderTest(boolean useMockBluetoothDeviceRoutesManager) { if (useMockBluetoothDeviceRoutesManager) { mControllerUnderTest = new AudioManagerRouteController( mMockContext, mMockAudioManager, Looper.getMainLooper(), mMediaAudioProductStrategy, mMockBluetoothDeviceRoutesManager); } else { BluetoothAdapter btAdapter = mRealContext.getSystemService(BluetoothManager.class).getAdapter(); mControllerUnderTest = new AudioManagerRouteController( mMockContext, mMockAudioManager, Looper.getMainLooper(), mMediaAudioProductStrategy, btAdapter); } mControllerUnderTest.registerRouteChangeListener(mEventListener); mControllerUnderTest.start(UserHandle.CURRENT_OR_SELF); ArgumentCaptor<AudioDeviceCallback> deviceCallbackCaptor = ArgumentCaptor.forClass(AudioDeviceCallback.class); verify(mMockAudioManager) .registerAudioDeviceCallback(deviceCallbackCaptor.capture(), any()); mAudioDeviceCallback = deviceCallbackCaptor.getValue(); // We clear any invocations during setup. clearInvocations(mEventListener); } @NonNull private MediaRoute2Info getAvailableRouteWithType(int type) { return mControllerUnderTest.getAvailableRoutes().stream() Loading Loading
services/core/java/com/android/server/media/AudioManagerRouteController.java +24 −8 Original line number Diff line number Diff line Loading @@ -50,6 +50,7 @@ import android.util.SparseArray; import com.android.internal.R; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import java.util.ArrayList; import java.util.Arrays; Loading Loading @@ -171,6 +172,26 @@ import java.util.concurrent.CopyOnWriteArrayList; @NonNull Looper looper, @NonNull AudioProductStrategy strategyForMedia, @NonNull BluetoothAdapter btAdapter) { this( context, audioManager, looper, strategyForMedia, new BluetoothDeviceRoutesManager(context, looper, btAdapter)); } @RequiresPermission( anyOf = { Manifest.permission.MODIFY_AUDIO_ROUTING, Manifest.permission.QUERY_AUDIO_STATE }) @VisibleForTesting /* package */ AudioManagerRouteController( @NonNull Context context, @NonNull AudioManager audioManager, @NonNull Looper looper, @NonNull AudioProductStrategy strategyForMedia, @NonNull BluetoothDeviceRoutesManager bluetoothDeviceRoutesManager) { mContext = Objects.requireNonNull(context); mAudioManager = Objects.requireNonNull(audioManager); mHandler = new Handler(Objects.requireNonNull(looper)); Loading @@ -182,13 +203,7 @@ import java.util.concurrent.CopyOnWriteArrayList; mBuiltInSpeakerSuitabilityStatus = DeviceRouteController.getBuiltInSpeakerSuitabilityStatus(mContext); mBluetoothRouteController = new BluetoothDeviceRoutesManager( mContext, mHandler, looper, btAdapter, this::rebuildAvailableRoutesAndNotify); mBluetoothRouteController = Objects.requireNonNull(bluetoothDeviceRoutesManager); // Just build routes but don't notify. The caller may not expect the listener to be invoked // before this constructor has finished executing. rebuildAvailableRoutes(); Loading Loading @@ -220,7 +235,8 @@ import java.util.concurrent.CopyOnWriteArrayList; mBluetoothRouteController.start( com.android.media.flags.Flags.enableUseOfSingletonAudioManagerRouteController() ? UserHandle.SYSTEM : mUser); : mUser, this::rebuildAvailableRoutesAndNotify); mAudioManager.registerAudioDeviceCallback(mAudioDeviceCallback, mHandler); mAudioManager.addOnDevicesForAttributesChangedListener( AudioRoutingUtils.ATTRIBUTES_MEDIA, Loading
services/core/java/com/android/server/media/BluetoothDeviceRoutesManager.java +12 −13 Original line number Diff line number Diff line Loading @@ -91,39 +91,37 @@ import java.util.stream.Collectors; private final Context mContext; @NonNull private final Handler mHandler; @NonNull private final BluetoothAdapter mBluetoothAdapter; @NonNull private final BluetoothRoutesUpdatedListener mListener; @NonNull private BluetoothRoutesUpdatedListener mListener; @NonNull private final BluetoothProfileMonitor mBluetoothProfileMonitor; BluetoothDeviceRoutesManager( @NonNull Context context, @NonNull Handler handler, @NonNull Looper looper, @NonNull BluetoothAdapter bluetoothAdapter, @NonNull BluetoothRoutesUpdatedListener listener) { @NonNull BluetoothAdapter bluetoothAdapter) { this( context, handler, looper, bluetoothAdapter, new BluetoothProfileMonitor(context, looper, bluetoothAdapter), listener); new BluetoothProfileMonitor(context, looper, bluetoothAdapter)); } @VisibleForTesting BluetoothDeviceRoutesManager( @NonNull Context context, @NonNull Handler handler, @NonNull Looper looper, @NonNull BluetoothAdapter bluetoothAdapter, @NonNull BluetoothProfileMonitor bluetoothProfileMonitor, @NonNull BluetoothRoutesUpdatedListener listener) { @NonNull BluetoothProfileMonitor bluetoothProfileMonitor) { mContext = Objects.requireNonNull(context); mHandler = handler; mHandler = new Handler(Objects.requireNonNull(looper)); mBluetoothAdapter = Objects.requireNonNull(bluetoothAdapter); mBluetoothProfileMonitor = Objects.requireNonNull(bluetoothProfileMonitor); mListener = Objects.requireNonNull(listener); // no-op listener, will be overrode in start() mListener = () -> {}; } public void start(UserHandle user) { public void start(UserHandle user, @NonNull BluetoothRoutesUpdatedListener listener) { mListener = listener; mBluetoothProfileMonitor.start(); IntentFilter adapterStateChangedIntentFilter = new IntentFilter(); Loading Loading @@ -346,6 +344,7 @@ import java.util.stream.Collectors; } return deviceName; } private SparseBooleanArray getConnectedProfiles(@NonNull BluetoothDevice device) { SparseBooleanArray connectedProfiles = new SparseBooleanArray(); if (mBluetoothProfileMonitor.isProfileSupported(BluetoothProfile.A2DP, device)) { Loading
services/tests/media/mediarouterservicetest/src/com/android/server/media/AudioManagerRouteControllerTest.java +52 −25 Original line number Diff line number Diff line Loading @@ -107,6 +107,9 @@ public class AudioManagerRouteControllerTest { private Set<AudioDeviceInfo> mAvailableAudioDeviceInfos; @Mock private AudioManager mMockAudioManager; @Mock private DeviceRouteController.EventListener mEventListener; @Mock private BluetoothDeviceRoutesManager mMockBluetoothDeviceRoutesManager; @Mock private Context mMockContext; private Context mRealContext; private AudioManagerRouteController mControllerUnderTest; private AudioDeviceCallback mAudioDeviceCallback; private AudioProductStrategy mMediaAudioProductStrategy; Loading @@ -118,15 +121,14 @@ public class AudioManagerRouteControllerTest { mInstrumentation.getUiAutomation().adoptShellPermissionIdentity(MODIFY_AUDIO_ROUTING); Resources mockResources = Mockito.mock(Resources.class); when(mockResources.getText(anyInt())).thenReturn(FAKE_ROUTE_NAME); Context realContext = mInstrumentation.getContext(); Context mockContext = Mockito.mock(Context.class); when(mockContext.getResources()).thenReturn(mockResources); mRealContext = mInstrumentation.getContext(); when(mMockContext.getResources()).thenReturn(mockResources); // The bluetooth stack needs the application info, but we cannot use a spy because the // concrete class is package private, so we just return the application info through the // mock. when(mockContext.getApplicationInfo()).thenReturn(realContext.getApplicationInfo()); when(mMockContext.getApplicationInfo()).thenReturn(mRealContext.getApplicationInfo()); // Needed to check if it is a TV device. when(mockContext.getPackageManager()).thenReturn(realContext.getPackageManager()); when(mMockContext.getPackageManager()).thenReturn(mRealContext.getPackageManager()); // Setup the initial state so that the route controller is created in a sensible state. mSelectedAudioDeviceInfo = FAKE_AUDIO_DEVICE_INFO_BUILTIN_SPEAKER; Loading @@ -134,26 +136,7 @@ public class AudioManagerRouteControllerTest { updateMockAudioManagerState(); mMediaAudioProductStrategy = getMediaAudioProductStrategy(); BluetoothAdapter btAdapter = realContext.getSystemService(BluetoothManager.class).getAdapter(); mControllerUnderTest = new AudioManagerRouteController( mockContext, mMockAudioManager, Looper.getMainLooper(), mMediaAudioProductStrategy, btAdapter); mControllerUnderTest.registerRouteChangeListener(mEventListener); mControllerUnderTest.start(UserHandle.CURRENT_OR_SELF); ArgumentCaptor<AudioDeviceCallback> deviceCallbackCaptor = ArgumentCaptor.forClass(AudioDeviceCallback.class); verify(mMockAudioManager) .registerAudioDeviceCallback(deviceCallbackCaptor.capture(), any()); mAudioDeviceCallback = deviceCallbackCaptor.getValue(); // We clear any invocations during setup. clearInvocations(mEventListener); // Need call setUpControllerUnderTest before each test case. } @After Loading @@ -163,6 +146,7 @@ public class AudioManagerRouteControllerTest { @Test public void getSelectedRoute_afterDevicesConnect_returnsRightSelectedRoute() { setUpControllerUnderTest(/* useMockBluetoothDeviceRoutesManager= */ false); assertThat(mControllerUnderTest.getSelectedRoutes().getFirst().getType()) .isEqualTo(MediaRoute2Info.TYPE_BUILTIN_SPEAKER); Loading @@ -182,6 +166,7 @@ public class AudioManagerRouteControllerTest { @Test public void getSelectedRoute_afterDeviceRemovals_returnsExpectedRoutes() { setUpControllerUnderTest(/* useMockBluetoothDeviceRoutesManager= */ false); addAvailableAudioDeviceInfo( /* newSelectedDevice= */ FAKE_AUDIO_DEVICE_INFO_WIRED_HEADSET, /* newAvailableDevices...= */ FAKE_AUDIO_DEVICE_INFO_BLUETOOTH_A2DP, Loading Loading @@ -210,6 +195,7 @@ public class AudioManagerRouteControllerTest { @Test public void onAudioDevicesAdded_clearsAudioRoutingPoliciesCorrectly() { setUpControllerUnderTest(/* useMockBluetoothDeviceRoutesManager= */ false); clearInvocations(mMockAudioManager); addAvailableAudioDeviceInfo( /* newSelectedDevice= */ null, // Selected device doesn't change. Loading @@ -224,6 +210,7 @@ public class AudioManagerRouteControllerTest { @Test public void getAvailableDevices_ignoresInvalidMediaOutputs() { setUpControllerUnderTest(/* useMockBluetoothDeviceRoutesManager= */ false); addAvailableAudioDeviceInfo( /* newSelectedDevice= */ null, // Selected device doesn't change. /* newAvailableDevices...= */ FAKE_AUDIO_DEVICE_BUILTIN_EARPIECE); Loading @@ -239,6 +226,7 @@ public class AudioManagerRouteControllerTest { @Test public void transferTo_setsTheExpectedRoutingPolicy() { setUpControllerUnderTest(/* useMockBluetoothDeviceRoutesManager= */ false); addAvailableAudioDeviceInfo( /* newSelectedDevice= */ FAKE_AUDIO_DEVICE_INFO_WIRED_HEADSET, /* newAvailableDevices...= */ FAKE_AUDIO_DEVICE_INFO_BLUETOOTH_A2DP, Loading @@ -264,6 +252,7 @@ public class AudioManagerRouteControllerTest { @Test public void updateVolume_propagatesCorrectlyToRouteInfo() { setUpControllerUnderTest(/* useMockBluetoothDeviceRoutesManager= */ false); when(mMockAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC)).thenReturn(2); when(mMockAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC)).thenReturn(3); when(mMockAudioManager.getStreamMinVolume(AudioManager.STREAM_MUSIC)).thenReturn(1); Loading Loading @@ -303,6 +292,7 @@ public class AudioManagerRouteControllerTest { @Test public void getAvailableRoutes_whenNoProductNameIsProvided_usesTypeToPopulateName() { setUpControllerUnderTest(/* useMockBluetoothDeviceRoutesManager= */ false); assertThat(mControllerUnderTest.getSelectedRoutes().getFirst().getName().toString()) .isEqualTo(FAKE_AUDIO_DEVICE_INFO_BUILTIN_SPEAKER.getProductName().toString()); Loading @@ -316,6 +306,7 @@ public class AudioManagerRouteControllerTest { @Test public void getAvailableRoutes_whenAddressIsPopulatedForNonBluetoothDevice_usesCorrectName() { setUpControllerUnderTest(/* useMockBluetoothDeviceRoutesManager= */ false); addAvailableAudioDeviceInfo( /* newSelectedDevice= */ FAKE_AUDIO_DEVICE_INFO_WIRED_HEADSET_WITH_ADDRESS, /* newAvailableDevices...= */ FAKE_AUDIO_DEVICE_INFO_WIRED_HEADSET_WITH_ADDRESS, Loading Loading @@ -343,6 +334,7 @@ public class AudioManagerRouteControllerTest { @Test public void getAvailableRoutes_whenAddressIsNotPopulatedForNonBluetoothDevice_usesCorrectName() { setUpControllerUnderTest(/* useMockBluetoothDeviceRoutesManager= */ false); addAvailableAudioDeviceInfo( /* newSelectedDevice= */ FAKE_AUDIO_DEVICE_INFO_WIRED_HEADSET, /* newAvailableDevices...= */ FAKE_AUDIO_DEVICE_INFO_WIRED_HEADSET); Loading @@ -365,6 +357,7 @@ public class AudioManagerRouteControllerTest { @Test public void getSessionReleaseType_returnTypeSharing() { setUpControllerUnderTest(/* useMockBluetoothDeviceRoutesManager= */ false); when(mMockAudioManager.getDevicesForAttributes(ATTRIBUTES_MEDIA)) .thenReturn( List.of( Loading @@ -376,6 +369,7 @@ public class AudioManagerRouteControllerTest { @Test public void getSessionReleaseType_returnTypeUnsupported() { setUpControllerUnderTest(/* useMockBluetoothDeviceRoutesManager= */ false); when(mMockAudioManager.getDevicesForAttributes(ATTRIBUTES_MEDIA)) .thenReturn( List.of( Loading @@ -387,6 +381,39 @@ public class AudioManagerRouteControllerTest { // Internal methods. private void setUpControllerUnderTest(boolean useMockBluetoothDeviceRoutesManager) { if (useMockBluetoothDeviceRoutesManager) { mControllerUnderTest = new AudioManagerRouteController( mMockContext, mMockAudioManager, Looper.getMainLooper(), mMediaAudioProductStrategy, mMockBluetoothDeviceRoutesManager); } else { BluetoothAdapter btAdapter = mRealContext.getSystemService(BluetoothManager.class).getAdapter(); mControllerUnderTest = new AudioManagerRouteController( mMockContext, mMockAudioManager, Looper.getMainLooper(), mMediaAudioProductStrategy, btAdapter); } mControllerUnderTest.registerRouteChangeListener(mEventListener); mControllerUnderTest.start(UserHandle.CURRENT_OR_SELF); ArgumentCaptor<AudioDeviceCallback> deviceCallbackCaptor = ArgumentCaptor.forClass(AudioDeviceCallback.class); verify(mMockAudioManager) .registerAudioDeviceCallback(deviceCallbackCaptor.capture(), any()); mAudioDeviceCallback = deviceCallbackCaptor.getValue(); // We clear any invocations during setup. clearInvocations(mEventListener); } @NonNull private MediaRoute2Info getAvailableRouteWithType(int type) { return mControllerUnderTest.getAvailableRoutes().stream() Loading