Loading packages/SystemUI/res/values/strings.xml +2 −0 Original line number Diff line number Diff line Loading @@ -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 & 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] --> Loading packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java +34 −42 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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())) { Loading packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java +63 −11 Original line number Diff line number Diff line Loading @@ -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); Loading @@ -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<>(); Loading @@ -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); Loading @@ -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); } Loading Loading @@ -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 Loading @@ -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); Loading @@ -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(); } Loading Loading
packages/SystemUI/res/values/strings.xml +2 −0 Original line number Diff line number Diff line Loading @@ -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 & 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] --> Loading
packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java +34 −42 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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())) { Loading
packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java +63 −11 Original line number Diff line number Diff line Loading @@ -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); Loading @@ -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<>(); Loading @@ -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); Loading @@ -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); } Loading Loading @@ -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 Loading @@ -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); Loading @@ -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(); } Loading