Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a68b5fb8 authored by Iván Budnik's avatar Iván Budnik
Browse files

Avoid null connected devices when updating routing information

This is a non-functional change.

Flag: N/A
Test: atest com.android.settingslib.media
Bug: 332515672
Change-Id: I90129acc10a7bab1278ac896d4710c0d9825fc32
parent 8756fdba
Loading
Loading
Loading
Loading
+7 −5
Original line number Diff line number Diff line
@@ -254,8 +254,6 @@ public abstract class InfoMediaManager {
    protected abstract List<MediaRoute2Info> getTransferableRoutes(@NonNull String packageName);

    protected final void rebuildDeviceList() {
        mMediaDevices.clear();
        mCurrentConnectedDevice = null;
        buildAvailableRoutes();
    }

@@ -524,6 +522,7 @@ public abstract class InfoMediaManager {
    // MediaRoute2Info.getType was made public on API 34, but exists since API 30.
    @SuppressWarnings("NewApi")
    private synchronized void buildAvailableRoutes() {
        mMediaDevices.clear();
        RoutingSessionInfo activeSession = getActiveRoutingSession();

        for (MediaRoute2Info route : getAvailableRoutes(activeSession)) {
@@ -533,6 +532,12 @@ public abstract class InfoMediaManager {
            }
            addMediaDevice(route, activeSession);
        }

        // In practice, mMediaDevices should always have at least one route.
        if (!mMediaDevices.isEmpty()) {
            // First device on the list is always the first selected route.
            mCurrentConnectedDevice = mMediaDevices.get(0);
        }
    }

    private synchronized List<MediaRoute2Info> getAvailableRoutes(
@@ -643,9 +648,6 @@ public abstract class InfoMediaManager {
        if (mediaDevice != null) {
            if (activeSession.getSelectedRoutes().contains(route.getId())) {
                mediaDevice.setState(STATE_SELECTED);
                if (mCurrentConnectedDevice == null) {
                    mCurrentConnectedDevice = mediaDevice;
                }
            }
            mMediaDevices.add(mediaDevice);
        }
+42 −55
Original line number Diff line number Diff line
@@ -110,6 +110,17 @@ public class InfoMediaManagerTest {
                    .setAddress("00:00:00:00:00:00")
                    .build();

    private static final RoutingSessionInfo TEST_REMOTE_ROUTING_SESSION =
            new RoutingSessionInfo.Builder("FAKE_REMOTE_ROUTING_SESSION_ID", TEST_PACKAGE_NAME)
                    .addSelectedRoute(TEST_ID_1)
                    .build();

    private static final MediaRoute2Info TEST_REMOTE_ROUTE =
            new MediaRoute2Info.Builder(TEST_ID_1, "REMOTE_ROUTE")
                    .setSystemRoute(true)
                    .addFeature(MediaRoute2Info.FEATURE_LIVE_AUDIO)
                    .build();

    @Mock
    private MediaRouter2Manager mRouterManager;
    @Mock
@@ -151,7 +162,10 @@ public class InfoMediaManagerTest {
        RoutingSessionInfo sessionInfo = mock(RoutingSessionInfo.class);
        mInfoMediaManager.mRouterManager = mRouterManager;
        // Since test is running in Robolectric, return a fake session to avoid NPE.
        when(mRouterManager.getRoutingSessions(anyString())).thenReturn(List.of(sessionInfo));
        when(mRouterManager.getRoutingSessions(anyString()))
                .thenReturn(List.of(TEST_SYSTEM_ROUTING_SESSION));
        when(mRouterManager.getSelectedRoutes(any()))
                .thenReturn(List.of(TEST_SELECTED_SYSTEM_ROUTE));

        mInfoMediaManager.startScan();
        mInfoMediaManager.stopScan();
@@ -191,52 +205,27 @@ public class InfoMediaManagerTest {

    @Test
    public void onSessionReleased_shouldUpdateConnectedDevice() {
        final List<RoutingSessionInfo> routingSessionInfos = new ArrayList<>();
        final RoutingSessionInfo sessionInfo1 = mock(RoutingSessionInfo.class);
        routingSessionInfos.add(sessionInfo1);
        final RoutingSessionInfo sessionInfo2 = mock(RoutingSessionInfo.class);
        routingSessionInfos.add(sessionInfo2);

        final List<String> selectedRoutesSession1 = new ArrayList<>();
        selectedRoutesSession1.add(TEST_ID_1);
        when(sessionInfo1.getSelectedRoutes()).thenReturn(selectedRoutesSession1);

        final List<String> selectedRoutesSession2 = new ArrayList<>();
        selectedRoutesSession2.add(TEST_ID_2);
        when(sessionInfo2.getSelectedRoutes()).thenReturn(selectedRoutesSession2);

        mShadowRouter2Manager.setRoutingSessions(routingSessionInfos);

        final MediaRoute2Info info1 = mock(MediaRoute2Info.class);
        when(info1.getId()).thenReturn(TEST_ID_1);
        when(info1.getClientPackageName()).thenReturn(TEST_PACKAGE_NAME);

        final MediaRoute2Info info2 = mock(MediaRoute2Info.class);
        when(info2.getId()).thenReturn(TEST_ID_2);
        when(info2.getClientPackageName()).thenReturn(TEST_PACKAGE_NAME);

        final List<MediaRoute2Info> routes = new ArrayList<>();
        routes.add(info1);
        routes.add(info2);
        mShadowRouter2Manager.setAllRoutes(routes);
        mShadowRouter2Manager.setTransferableRoutes(routes);
        mInfoMediaManager.mRouterManager = mRouterManager;

        final MediaDevice mediaDevice1 = mInfoMediaManager.findMediaDevice(TEST_ID_1);
        assertThat(mediaDevice1).isNull();
        final MediaDevice mediaDevice2 = mInfoMediaManager.findMediaDevice(TEST_ID_2);
        assertThat(mediaDevice2).isNull();
        // Active routing session is last one in list.
        when(mRouterManager.getRoutingSessions(anyString()))
                .thenReturn(List.of(TEST_SYSTEM_ROUTING_SESSION, TEST_REMOTE_ROUTING_SESSION));
        when(mRouterManager.getSelectedRoutes(TEST_SYSTEM_ROUTING_SESSION))
                .thenReturn(List.of(TEST_SELECTED_SYSTEM_ROUTE));
        when(mRouterManager.getSelectedRoutes(TEST_REMOTE_ROUTING_SESSION))
                .thenReturn(List.of(TEST_REMOTE_ROUTE));

        mInfoMediaManager.mMediaRouterCallback.onRoutesUpdated();
        final MediaDevice infoDevice1 = mInfoMediaManager.mMediaDevices.get(0);
        assertThat(infoDevice1.getId()).isEqualTo(TEST_ID_1);
        final MediaDevice infoDevice2 = mInfoMediaManager.mMediaDevices.get(1);
        assertThat(infoDevice2.getId()).isEqualTo(TEST_ID_2);
        // The active routing session is the last one in the list, which maps to infoDevice2.
        assertThat(mInfoMediaManager.getCurrentConnectedDevice()).isEqualTo(infoDevice2);
        MediaDevice remoteDevice = mInfoMediaManager.findMediaDevice(TEST_REMOTE_ROUTE.getId());
        assertThat(remoteDevice).isNotNull();
        assertThat(mInfoMediaManager.getCurrentConnectedDevice()).isEqualTo(remoteDevice);

        routingSessionInfos.remove(sessionInfo2);
        mInfoMediaManager.mMediaRouterCallback.onSessionReleased(sessionInfo2);
        assertThat(mInfoMediaManager.getCurrentConnectedDevice()).isEqualTo(infoDevice1);
        when(mRouterManager.getRoutingSessions(anyString()))
                .thenReturn(List.of(TEST_SYSTEM_ROUTING_SESSION));
        mInfoMediaManager.mMediaRouterCallback.onSessionReleased(TEST_REMOTE_ROUTING_SESSION);
        MediaDevice systemRoute = mInfoMediaManager.findMediaDevice(TEST_SYSTEM_ROUTE_ID);
        assertThat(systemRoute).isNotNull();
        assertThat(mInfoMediaManager.getCurrentConnectedDevice()).isEqualTo(systemRoute);
    }

    @Test
@@ -794,18 +783,16 @@ public class InfoMediaManagerTest {

    @Test
    public void onSessionUpdated_shouldDispatchDeviceListAdded() {
        final MediaRoute2Info info = mock(MediaRoute2Info.class);
        when(info.getId()).thenReturn(TEST_ID);
        when(info.getClientPackageName()).thenReturn(TEST_PACKAGE_NAME);
        when(info.isSystemRoute()).thenReturn(true);

        final List<MediaRoute2Info> routes = new ArrayList<>();
        routes.add(info);
        mShadowRouter2Manager.setAllRoutes(routes);
        mInfoMediaManager.mRouterManager = mRouterManager;
        // Since test is running in Robolectric, return a fake session to avoid NPE.
        when(mRouterManager.getRoutingSessions(anyString()))
                .thenReturn(List.of(TEST_SYSTEM_ROUTING_SESSION));
        when(mRouterManager.getSelectedRoutes(any()))
                .thenReturn(List.of(TEST_SELECTED_SYSTEM_ROUTE));

        mInfoMediaManager.registerCallback(mCallback);

        mInfoMediaManager.mMediaRouterCallback.onSessionUpdated(mock(RoutingSessionInfo.class));
        mInfoMediaManager.mMediaRouterCallback.onSessionUpdated(TEST_SYSTEM_ROUTING_SESSION);

        verify(mCallback).onDeviceListAdded(any());
    }
@@ -871,7 +858,7 @@ public class InfoMediaManagerTest {
    }

    @Test
    public void addMediaDevice_deviceIncludedInSelectedDevices_shouldSetAsCurrentConnected() {
    public void onRoutesUpdated_setsFirstSelectedRouteAsCurrentConnectedDevice() {
        final CachedBluetoothDeviceManager cachedBluetoothDeviceManager =
                mock(CachedBluetoothDeviceManager.class);

@@ -886,14 +873,14 @@ public class InfoMediaManagerTest {

        when(mRouterManager.getRoutingSessions(TEST_PACKAGE_NAME))
                .thenReturn(List.of(selectedBtSession));
        when(mRouterManager.getSelectedRoutes(any())).thenReturn(List.of(TEST_BLUETOOTH_ROUTE));
        when(mLocalBluetoothManager.getCachedDeviceManager())
                .thenReturn(cachedBluetoothDeviceManager);
        when(cachedBluetoothDeviceManager.findDevice(any(BluetoothDevice.class)))
                .thenReturn(cachedDevice);
        mInfoMediaManager.mRouterManager = mRouterManager;

        mInfoMediaManager.mMediaDevices.clear();
        mInfoMediaManager.addMediaDevice(TEST_BLUETOOTH_ROUTE, selectedBtSession);
        mInfoMediaManager.mMediaRouterCallback.onRoutesUpdated();

        MediaDevice device = mInfoMediaManager.mMediaDevices.get(0);

+8 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package com.android.systemui.media.dialog;
import static com.google.common.truth.Truth.assertThat;

import static org.mockito.Mockito.any;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
@@ -47,6 +48,7 @@ import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
import com.android.settingslib.media.LocalMediaManager;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.animation.DialogTransitionAnimator;
import com.android.systemui.broadcast.BroadcastSender;
@@ -127,6 +129,12 @@ public class MediaOutputBaseDialogTest extends SysuiTestCase {
                mNearbyMediaDevicesManager, mAudioManager, mPowerExemptionManager,
                mKeyguardManager, mFlags, mUserTracker);

        // Using a fake package will cause routing operations to fail, so we intercept
        // scanning-related operations.
        mMediaOutputController.mLocalMediaManager = mock(LocalMediaManager.class);
        doNothing().when(mMediaOutputController.mLocalMediaManager).startScan();
        doNothing().when(mMediaOutputController.mLocalMediaManager).stopScan();

        mMediaOutputBaseDialogImpl = new MediaOutputBaseDialogImpl(mContext, mBroadcastSender,
                mMediaOutputController);
        mMediaOutputBaseDialogImpl.onCreate(new Bundle());