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

Commit 9cd0d533 authored by shaoweishen's avatar shaoweishen Committed by Shaowei Shen
Browse files

[Output Switcher] Add "Suggested Devices" section in list

Apply logic for adding suggested device group divider in list when organize devices based on MediaDevice.isSuggestedDevice.

Bug: 258141461
Test: atest MediaOutputAdapterTest MediaOutputControllerTest MediaOutputBaseDialogTest MediaOutputDialogTest
Change-Id: Ie6372e185eb095e87ca679a701f93e0f6fe2f9f3
parent 4326b85b
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -2520,6 +2520,8 @@
    <string name="media_output_dialog_volume_percentage"><xliff:g id="percentage" example="10">%1$d</xliff:g>%%</string>
    <!-- Title for Speakers and Displays group. [CHAR LIMIT=NONE] -->
    <string name="media_output_group_title_speakers_and_displays">Speakers &amp; Displays</string>
    <!-- Title for Suggested Devices group. [CHAR LIMIT=NONE] -->
    <string name="media_output_group_title_suggested_device">Suggested Devices</string>

    <!-- Media Output Broadcast Dialog -->
    <!-- Title for Broadcast First Notify Dialog [CHAR LIMIT=60] -->
+34 −42
Original line number Diff line number Diff line
@@ -637,44 +637,21 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback,
            }
            // For the first time building list, to make sure the top device is the connected
            // device.
            if (mMediaItemList.isEmpty()) {
            boolean needToHandleMutingExpectedDevice =
                    hasMutingExpectedDevice() && !isCurrentConnectedDeviceRemote();
            final MediaDevice connectedMediaDevice =
                    needToHandleMutingExpectedDevice ? null
                            : getCurrentConnectedMediaDevice();
            if (mMediaItemList.isEmpty()) {
                if (connectedMediaDevice == null) {
                    if (DEBUG) {
                        Log.d(TAG, "No connected media device or muting expected device exist.");
                    }
                    if (needToHandleMutingExpectedDevice) {
                        for (MediaDevice device : devices) {
                            if (device.isMutingExpectedDevice()) {
                                mMediaItemList.add(0, new MediaItem(device));
                                mMediaItemList.add(1, new MediaItem(mContext.getString(
                                        R.string.media_output_group_title_speakers_and_displays),
                                        MediaItem.MediaItemType.TYPE_GROUP_DIVIDER));
                            } else {
                                mMediaItemList.add(new MediaItem(device));
                            }
                        }
                        mMediaItemList.add(new MediaItem());
                    } else {
                        mMediaItemList.addAll(
                                devices.stream().map(MediaItem::new).collect(Collectors.toList()));
                        categorizeMediaItems(null);
                    }
                    categorizeMediaItems(null, devices, needToHandleMutingExpectedDevice);
                    return;
                }
                // selected device exist
                for (MediaDevice device : devices) {
                    if (TextUtils.equals(device.getId(), connectedMediaDevice.getId())) {
                        mMediaItemList.add(0, new MediaItem(device));
                    } else {
                        mMediaItemList.add(new MediaItem(device));
                    }
                }
                categorizeMediaItems(connectedMediaDevice);
                categorizeMediaItems(connectedMediaDevice, devices, false);
                return;
            }
            // To keep the same list order
@@ -708,31 +685,46 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback,
        }
    }

    private void categorizeMediaItems(MediaDevice connectedMediaDevice) {
    private void categorizeMediaItems(MediaDevice connectedMediaDevice, List<MediaDevice> devices,
            boolean needToHandleMutingExpectedDevice) {
        synchronized (mMediaDevicesLock) {
            Set<String> selectedDevicesIds = getSelectedMediaDevice().stream().map(
                    MediaDevice::getId).collect(Collectors.toSet());
            if (connectedMediaDevice != null) {
                selectedDevicesIds.add(connectedMediaDevice.getId());
            }
            int latestSelected = 1;
            for (MediaItem item : mMediaItemList) {
                if (item.getMediaDevice().isPresent()) {
                    MediaDevice device = item.getMediaDevice().get();
                    if (selectedDevicesIds.contains(device.getId())) {
                        latestSelected = mMediaItemList.indexOf(item) + 1;
            boolean suggestedDeviceAdded = false;
            boolean displayGroupAdded = false;
            for (MediaDevice device : devices) {
                if (needToHandleMutingExpectedDevice && device.isMutingExpectedDevice()) {
                    mMediaItemList.add(0, new MediaItem(device));
                } else if (!needToHandleMutingExpectedDevice && selectedDevicesIds.contains(
                        device.getId())) {
                    mMediaItemList.add(0, new MediaItem(device));
                } else {
                        mMediaItemList.add(latestSelected, new MediaItem(mContext.getString(
                                R.string.media_output_group_title_speakers_and_displays),
                                MediaItem.MediaItemType.TYPE_GROUP_DIVIDER));
                        break;
                    if (device.isSuggestedDevice() && !suggestedDeviceAdded) {
                        attachGroupDivider(mContext.getString(
                                R.string.media_output_group_title_suggested_device));
                        suggestedDeviceAdded = true;
                    } else if (!device.isSuggestedDevice() && !displayGroupAdded) {
                        attachGroupDivider(mContext.getString(
                                R.string.media_output_group_title_speakers_and_displays));
                        displayGroupAdded = true;
                    }
                    mMediaItemList.add(new MediaItem(device));
                }
            }
            mMediaItemList.add(new MediaItem());
        }
    }

    private void attachGroupDivider(String title) {
        synchronized (mMediaDevicesLock) {
            mMediaItemList.add(
                    new MediaItem(title, MediaItem.MediaItemType.TYPE_GROUP_DIVIDER));
        }
    }

    private void attachRangeInfo(List<MediaDevice> devices) {
        for (MediaDevice mediaDevice : devices) {
            if (mNearbyDeviceInfoMap.containsKey(mediaDevice.getId())) {
+63 −11
Original line number Diff line number Diff line
@@ -102,8 +102,6 @@ public class MediaOutputControllerTest extends SysuiTestCase {
    private MediaOutputController.Callback mCb = mock(MediaOutputController.Callback.class);
    private MediaDevice mMediaDevice1 = mock(MediaDevice.class);
    private MediaDevice mMediaDevice2 = mock(MediaDevice.class);
    private MediaItem mMediaItem1 = mock(MediaItem.class);
    private MediaItem mMediaItem2 = mock(MediaItem.class);
    private NearbyDevice mNearbyDevice1 = mock(NearbyDevice.class);
    private NearbyDevice mNearbyDevice2 = mock(NearbyDevice.class);
    private MediaMetadata mMediaMetadata = mock(MediaMetadata.class);
@@ -127,7 +125,6 @@ public class MediaOutputControllerTest extends SysuiTestCase {
    private LocalMediaManager mLocalMediaManager;
    private List<MediaController> mMediaControllers = new ArrayList<>();
    private List<MediaDevice> mMediaDevices = new ArrayList<>();
    private List<MediaItem> mMediaItemList = new ArrayList<>();
    private List<NearbyDevice> mNearbyDevices = new ArrayList<>();
    private MediaDescription mMediaDescription;
    private List<RoutingSessionInfo> mRoutingSessionInfos = new ArrayList<>();
@@ -149,7 +146,9 @@ public class MediaOutputControllerTest extends SysuiTestCase {
                Optional.of(mNearbyMediaDevicesManager), mAudioManager, mPowerExemptionManager,
                mKeyguardManager, mFlags);
        when(mFlags.isEnabled(Flags.OUTPUT_SWITCHER_ADVANCED_LAYOUT)).thenReturn(false);
        when(mFlags.isEnabled(Flags.OUTPUT_SWITCHER_ROUTES_PROCESSING)).thenReturn(false);
        mLocalMediaManager = spy(mMediaOutputController.mLocalMediaManager);
        when(mLocalMediaManager.isPreferenceRouteListingExist()).thenReturn(false);
        mMediaOutputController.mLocalMediaManager = mLocalMediaManager;
        MediaDescription.Builder builder = new MediaDescription.Builder();
        builder.setTitle(TEST_SONG);
@@ -160,16 +159,12 @@ public class MediaOutputControllerTest extends SysuiTestCase {
        when(mMediaDevice2.getId()).thenReturn(TEST_DEVICE_2_ID);
        mMediaDevices.add(mMediaDevice1);
        mMediaDevices.add(mMediaDevice2);
        when(mMediaItem1.getMediaDevice()).thenReturn(Optional.of(mMediaDevice1));
        when(mMediaItem2.getMediaDevice()).thenReturn(Optional.of(mMediaDevice2));
        mMediaItemList.add(mMediaItem1);
        mMediaItemList.add(mMediaItem2);


        when(mNearbyDevice1.getMediaRoute2Id()).thenReturn(TEST_DEVICE_1_ID);
        when(mNearbyDevice1.getRangeZone()).thenReturn(NearbyDevice.RANGE_CLOSE);
        when(mNearbyDevice1.getRangeZone()).thenReturn(NearbyDevice.RANGE_FAR);
        when(mNearbyDevice2.getMediaRoute2Id()).thenReturn(TEST_DEVICE_2_ID);
        when(mNearbyDevice2.getRangeZone()).thenReturn(NearbyDevice.RANGE_FAR);
        when(mNearbyDevice2.getRangeZone()).thenReturn(NearbyDevice.RANGE_CLOSE);
        mNearbyDevices.add(mNearbyDevice1);
        mNearbyDevices.add(mNearbyDevice2);
    }
@@ -274,8 +269,20 @@ public class MediaOutputControllerTest extends SysuiTestCase {
        mMediaOutputController.onDevicesUpdated(mNearbyDevices);
        mMediaOutputController.onDeviceListUpdate(mMediaDevices);

        verify(mMediaDevice1).setRangeZone(NearbyDevice.RANGE_CLOSE);
        verify(mMediaDevice2).setRangeZone(NearbyDevice.RANGE_FAR);
        verify(mMediaDevice1).setRangeZone(NearbyDevice.RANGE_FAR);
        verify(mMediaDevice2).setRangeZone(NearbyDevice.RANGE_CLOSE);
    }

    @Test
    public void onDeviceListUpdate_withNearbyDevices_rankByRangeInformation()
            throws RemoteException {
        mMediaOutputController.start(mCb);
        reset(mCb);

        mMediaOutputController.onDevicesUpdated(mNearbyDevices);
        mMediaOutputController.onDeviceListUpdate(mMediaDevices);

        assertThat(mMediaDevices.get(0).getId()).isEqualTo(TEST_DEVICE_1_ID);
    }

    @Test
@@ -291,6 +298,22 @@ public class MediaOutputControllerTest extends SysuiTestCase {
        verify(mCb).onDeviceListChanged();
    }

    @Test
    public void routeProcessSupport_onDeviceListUpdate_preferenceExist_NotUpdatesRangeInformation()
            throws RemoteException {
        when(mLocalMediaManager.isPreferenceRouteListingExist()).thenReturn(true);
        when(mFlags.isEnabled(Flags.OUTPUT_SWITCHER_ROUTES_PROCESSING)).thenReturn(true);
        when(mFlags.isEnabled(Flags.OUTPUT_SWITCHER_ADVANCED_LAYOUT)).thenReturn(true);
        mMediaOutputController.start(mCb);
        reset(mCb);

        mMediaOutputController.onDevicesUpdated(mNearbyDevices);
        mMediaOutputController.onDeviceListUpdate(mMediaDevices);

        verify(mMediaDevice1, never()).setRangeZone(anyInt());
        verify(mMediaDevice2, never()).setRangeZone(anyInt());
    }

    @Test
    public void advanced_onDeviceListUpdate_verifyDeviceListCallback() {
        when(mFlags.isEnabled(Flags.OUTPUT_SWITCHER_ADVANCED_LAYOUT)).thenReturn(true);
@@ -307,6 +330,35 @@ public class MediaOutputControllerTest extends SysuiTestCase {

        assertThat(devices.containsAll(mMediaDevices)).isTrue();
        assertThat(devices.size()).isEqualTo(mMediaDevices.size());
        assertThat(mMediaOutputController.getMediaItemList().size()).isEqualTo(
                mMediaDevices.size() + 2);
        verify(mCb).onDeviceListChanged();
    }

    @Test
    public void advanced_categorizeMediaItems_withSuggestedDevice_verifyDeviceListSize() {
        when(mFlags.isEnabled(Flags.OUTPUT_SWITCHER_ADVANCED_LAYOUT)).thenReturn(true);
        when(mMediaDevice1.isSuggestedDevice()).thenReturn(true);
        when(mMediaDevice2.isSuggestedDevice()).thenReturn(false);

        mMediaOutputController.start(mCb);
        reset(mCb);
        mMediaOutputController.getMediaItemList().clear();
        mMediaOutputController.onDeviceListUpdate(mMediaDevices);
        final List<MediaDevice> devices = new ArrayList<>();
        int dividerSize = 0;
        for (MediaItem item : mMediaOutputController.getMediaItemList()) {
            if (item.getMediaDevice().isPresent()) {
                devices.add(item.getMediaDevice().get());
            }
            if (item.getMediaItemType() == MediaItem.MediaItemType.TYPE_GROUP_DIVIDER) {
                dividerSize++;
            }
        }

        assertThat(devices.containsAll(mMediaDevices)).isTrue();
        assertThat(devices.size()).isEqualTo(mMediaDevices.size());
        assertThat(dividerSize).isEqualTo(2);
        verify(mCb).onDeviceListChanged();
    }