Loading packages/SystemUI/src/com/android/systemui/media/dialog/MediaItem.java +37 −25 Original line number Diff line number Diff line Loading @@ -16,7 +16,9 @@ package com.android.systemui.media.dialog; import androidx.annotation.IntDef; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import com.android.settingslib.media.MediaDevice; import com.android.systemui.res.R; Loading Loading @@ -46,40 +48,50 @@ public class MediaItem { int TYPE_PAIR_NEW_DEVICE = 2; } public MediaItem() { this.mMediaDeviceOptional = Optional.empty(); this.mTitle = null; this.mMediaItemType = MediaItemType.TYPE_PAIR_NEW_DEVICE; /** * Returns a new {@link MediaItemType#TYPE_DEVICE} {@link MediaItem} with its {@link * #getMediaDevice() media device} set to {@code device} and its title set to {@code device}'s * name. */ public static MediaItem createDeviceMediaItem(@NonNull MediaDevice device) { return new MediaItem(device, device.getName(), MediaItemType.TYPE_DEVICE); } public MediaItem(String title, int mediaItemType) { this.mMediaDeviceOptional = Optional.empty(); this.mTitle = title; this.mMediaItemType = mediaItemType; /** * Returns a new {@link MediaItemType#TYPE_PAIR_NEW_DEVICE} {@link MediaItem} with both {@link * #getMediaDevice() media device} and title set to {@code null}. */ public static MediaItem createPairNewDeviceMediaItem() { return new MediaItem( /* device */ null, /* title */ null, MediaItemType.TYPE_PAIR_NEW_DEVICE); } public MediaItem(MediaDevice mediaDevice) { this.mMediaDeviceOptional = Optional.of(mediaDevice); this.mTitle = mediaDevice.getName(); this.mMediaItemType = MediaItemType.TYPE_DEVICE; /** * Returns a new {@link MediaItemType#TYPE_GROUP_DIVIDER} {@link MediaItem} with the specified * title and a {@code null} {@link #getMediaDevice() media device}. */ public static MediaItem createGroupDividerMediaItem(@Nullable String title) { return new MediaItem(/* device */ null, title, MediaItemType.TYPE_GROUP_DIVIDER); } private MediaItem( @Nullable MediaDevice device, @Nullable String title, @MediaItemType int type) { this.mMediaDeviceOptional = Optional.ofNullable(device); this.mTitle = title; this.mMediaItemType = type; } public Optional<MediaDevice> getMediaDevice() { return mMediaDeviceOptional; } /** * Get layout id based on media item Type. */ public static int getMediaLayoutId(int mediaItemType) { switch (mediaItemType) { case MediaItemType.TYPE_DEVICE: case MediaItemType.TYPE_PAIR_NEW_DEVICE: return R.layout.media_output_list_item_advanced; case MediaItemType.TYPE_GROUP_DIVIDER: default: return R.layout.media_output_list_group_divider; } /** Get layout id based on media item Type. */ public static int getMediaLayoutId(@MediaItemType int mediaItemType) { return switch (mediaItemType) { case MediaItemType.TYPE_DEVICE, MediaItemType.TYPE_PAIR_NEW_DEVICE -> R.layout.media_output_list_item_advanced; default -> R.layout.media_output_list_group_divider; }; } public String getTitle() { Loading packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java +43 −36 Original line number Diff line number Diff line Loading @@ -68,6 +68,7 @@ import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import androidx.core.graphics.drawable.IconCompat; import com.android.internal.annotations.GuardedBy; import com.android.settingslib.RestrictedLockUtilsInternal; import com.android.settingslib.Utils; import com.android.settingslib.bluetooth.BluetoothUtils; Loading Loading @@ -656,10 +657,16 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, if (DEBUG) { Log.d(TAG, "No connected media device or muting expected device exist."); } return categorizeMediaItems(null, devices, needToHandleMutingExpectedDevice); return categorizeMediaItemsLocked( /* connectedMediaDevice */ null, devices, needToHandleMutingExpectedDevice); } // selected device exist return categorizeMediaItems(connectedMediaDevice, devices, false); return categorizeMediaItemsLocked( connectedMediaDevice, devices, /* needToHandleMutingExpectedDevice */ false); } // To keep the same list order final List<MediaDevice> targetMediaDevices = new ArrayList<>(); Loading @@ -682,8 +689,9 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, devices.removeAll(targetMediaDevices); targetMediaDevices.addAll(devices); } List<MediaItem> finalMediaItems = targetMediaDevices.stream().map( MediaItem::new).collect(Collectors.toList()); List<MediaItem> finalMediaItems = targetMediaDevices.stream() .map(MediaItem::createDeviceMediaItem) .collect(Collectors.toList()); dividerItems.forEach(finalMediaItems::add); attachConnectNewDeviceItemIfNeeded(finalMediaItems); return finalMediaItems; Loading @@ -694,13 +702,14 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, * Initial categorization of current devices, will not be called for updates to the devices * list. */ private List<MediaItem> categorizeMediaItems(MediaDevice connectedMediaDevice, @GuardedBy("mMediaDevicesLock") private List<MediaItem> categorizeMediaItemsLocked(MediaDevice connectedMediaDevice, List<MediaDevice> devices, boolean needToHandleMutingExpectedDevice) { synchronized (mMediaDevicesLock) { List<MediaItem> finalMediaItems = new ArrayList<>(); Set<String> selectedDevicesIds = getSelectedMediaDevice().stream().map( MediaDevice::getId).collect(Collectors.toSet()); Set<String> selectedDevicesIds = getSelectedMediaDevice().stream() .map(MediaDevice::getId) .collect(Collectors.toSet()); if (connectedMediaDevice != null) { selectedDevicesIds.add(connectedMediaDevice.getId()); } Loading @@ -708,10 +717,10 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, boolean displayGroupAdded = false; for (MediaDevice device : devices) { if (needToHandleMutingExpectedDevice && device.isMutingExpectedDevice()) { finalMediaItems.add(0, new MediaItem(device)); finalMediaItems.add(0, MediaItem.createDeviceMediaItem(device)); } else if (!needToHandleMutingExpectedDevice && selectedDevicesIds.contains( device.getId())) { finalMediaItems.add(0, new MediaItem(device)); finalMediaItems.add(0, MediaItem.createDeviceMediaItem(device)); } else { if (device.isSuggestedDevice() && !suggestedDeviceAdded) { attachGroupDivider(finalMediaItems, mContext.getString( Loading @@ -722,23 +731,21 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, R.string.media_output_group_title_speakers_and_displays)); displayGroupAdded = true; } finalMediaItems.add(new MediaItem(device)); finalMediaItems.add(MediaItem.createDeviceMediaItem(device)); } } attachConnectNewDeviceItemIfNeeded(finalMediaItems); return finalMediaItems; } } private void attachGroupDivider(List<MediaItem> mediaItems, String title) { mediaItems.add( new MediaItem(title, MediaItem.MediaItemType.TYPE_GROUP_DIVIDER)); mediaItems.add(MediaItem.createGroupDividerMediaItem(title)); } private void attachConnectNewDeviceItemIfNeeded(List<MediaItem> mediaItems) { // Attach "Connect a device" item only when current output is not remote and not a group if (!isCurrentConnectedDeviceRemote() && getSelectedMediaDevice().size() == 1) { mediaItems.add(new MediaItem()); mediaItems.add(MediaItem.createPairNewDeviceMediaItem()); } } Loading packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java +6 −5 Original line number Diff line number Diff line Loading @@ -113,8 +113,8 @@ public class MediaOutputAdapterTest extends SysuiTestCase { LocalMediaManager.MediaDeviceState.STATE_DISCONNECTED); mMediaDevices.add(mMediaDevice1); mMediaDevices.add(mMediaDevice2); mMediaItems.add(new MediaItem(mMediaDevice1)); mMediaItems.add(new MediaItem(mMediaDevice2)); mMediaItems.add(MediaItem.createDeviceMediaItem(mMediaDevice1)); mMediaItems.add(MediaItem.createDeviceMediaItem(mMediaDevice2)); mMediaOutputAdapter = new MediaOutputAdapter(mMediaOutputController); mMediaOutputAdapter.updateItems(); Loading Loading @@ -146,7 +146,8 @@ public class MediaOutputAdapterTest extends SysuiTestCase { mMediaOutputAdapter.updateItems(); mViewHolder = (MediaOutputAdapter.MediaDeviceViewHolder) mMediaOutputAdapter .onCreateViewHolder(new LinearLayout(mContext), 0); mMediaItems.add(new MediaItem()); mMediaItems.add(MediaItem.createPairNewDeviceMediaItem()); mMediaItems.add(MediaItem.createPairNewDeviceMediaItem()); mMediaOutputAdapter.updateItems(); mMediaOutputAdapter.onBindViewHolder(mViewHolder, 2); Loading Loading @@ -589,7 +590,7 @@ public class MediaOutputAdapterTest extends SysuiTestCase { mMediaOutputAdapter.updateItems(); mViewHolder = (MediaOutputAdapter.MediaDeviceViewHolder) mMediaOutputAdapter .onCreateViewHolder(new LinearLayout(mContext), 0); mMediaItems.add(new MediaItem()); mMediaItems.add(MediaItem.createPairNewDeviceMediaItem()); mMediaOutputAdapter.updateItems(); mMediaOutputAdapter.onBindViewHolder(mViewHolder, 2); mViewHolder.mContainerLayout.performClick(); Loading Loading @@ -725,7 +726,7 @@ public class MediaOutputAdapterTest extends SysuiTestCase { public void updateItems_controllerItemsUpdated_notUpdatesInAdapterUntilUpdateItems() { mMediaOutputAdapter.updateItems(); List<MediaItem> updatedList = new ArrayList<>(); updatedList.add(new MediaItem()); updatedList.add(MediaItem.createPairNewDeviceMediaItem()); when(mMediaOutputController.getMediaItemList()).thenReturn(updatedList); assertThat(mMediaOutputAdapter.getItemCount()).isEqualTo(mMediaItems.size()); Loading Loading
packages/SystemUI/src/com/android/systemui/media/dialog/MediaItem.java +37 −25 Original line number Diff line number Diff line Loading @@ -16,7 +16,9 @@ package com.android.systemui.media.dialog; import androidx.annotation.IntDef; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import com.android.settingslib.media.MediaDevice; import com.android.systemui.res.R; Loading Loading @@ -46,40 +48,50 @@ public class MediaItem { int TYPE_PAIR_NEW_DEVICE = 2; } public MediaItem() { this.mMediaDeviceOptional = Optional.empty(); this.mTitle = null; this.mMediaItemType = MediaItemType.TYPE_PAIR_NEW_DEVICE; /** * Returns a new {@link MediaItemType#TYPE_DEVICE} {@link MediaItem} with its {@link * #getMediaDevice() media device} set to {@code device} and its title set to {@code device}'s * name. */ public static MediaItem createDeviceMediaItem(@NonNull MediaDevice device) { return new MediaItem(device, device.getName(), MediaItemType.TYPE_DEVICE); } public MediaItem(String title, int mediaItemType) { this.mMediaDeviceOptional = Optional.empty(); this.mTitle = title; this.mMediaItemType = mediaItemType; /** * Returns a new {@link MediaItemType#TYPE_PAIR_NEW_DEVICE} {@link MediaItem} with both {@link * #getMediaDevice() media device} and title set to {@code null}. */ public static MediaItem createPairNewDeviceMediaItem() { return new MediaItem( /* device */ null, /* title */ null, MediaItemType.TYPE_PAIR_NEW_DEVICE); } public MediaItem(MediaDevice mediaDevice) { this.mMediaDeviceOptional = Optional.of(mediaDevice); this.mTitle = mediaDevice.getName(); this.mMediaItemType = MediaItemType.TYPE_DEVICE; /** * Returns a new {@link MediaItemType#TYPE_GROUP_DIVIDER} {@link MediaItem} with the specified * title and a {@code null} {@link #getMediaDevice() media device}. */ public static MediaItem createGroupDividerMediaItem(@Nullable String title) { return new MediaItem(/* device */ null, title, MediaItemType.TYPE_GROUP_DIVIDER); } private MediaItem( @Nullable MediaDevice device, @Nullable String title, @MediaItemType int type) { this.mMediaDeviceOptional = Optional.ofNullable(device); this.mTitle = title; this.mMediaItemType = type; } public Optional<MediaDevice> getMediaDevice() { return mMediaDeviceOptional; } /** * Get layout id based on media item Type. */ public static int getMediaLayoutId(int mediaItemType) { switch (mediaItemType) { case MediaItemType.TYPE_DEVICE: case MediaItemType.TYPE_PAIR_NEW_DEVICE: return R.layout.media_output_list_item_advanced; case MediaItemType.TYPE_GROUP_DIVIDER: default: return R.layout.media_output_list_group_divider; } /** Get layout id based on media item Type. */ public static int getMediaLayoutId(@MediaItemType int mediaItemType) { return switch (mediaItemType) { case MediaItemType.TYPE_DEVICE, MediaItemType.TYPE_PAIR_NEW_DEVICE -> R.layout.media_output_list_item_advanced; default -> R.layout.media_output_list_group_divider; }; } public String getTitle() { Loading
packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java +43 −36 Original line number Diff line number Diff line Loading @@ -68,6 +68,7 @@ import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import androidx.core.graphics.drawable.IconCompat; import com.android.internal.annotations.GuardedBy; import com.android.settingslib.RestrictedLockUtilsInternal; import com.android.settingslib.Utils; import com.android.settingslib.bluetooth.BluetoothUtils; Loading Loading @@ -656,10 +657,16 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, if (DEBUG) { Log.d(TAG, "No connected media device or muting expected device exist."); } return categorizeMediaItems(null, devices, needToHandleMutingExpectedDevice); return categorizeMediaItemsLocked( /* connectedMediaDevice */ null, devices, needToHandleMutingExpectedDevice); } // selected device exist return categorizeMediaItems(connectedMediaDevice, devices, false); return categorizeMediaItemsLocked( connectedMediaDevice, devices, /* needToHandleMutingExpectedDevice */ false); } // To keep the same list order final List<MediaDevice> targetMediaDevices = new ArrayList<>(); Loading @@ -682,8 +689,9 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, devices.removeAll(targetMediaDevices); targetMediaDevices.addAll(devices); } List<MediaItem> finalMediaItems = targetMediaDevices.stream().map( MediaItem::new).collect(Collectors.toList()); List<MediaItem> finalMediaItems = targetMediaDevices.stream() .map(MediaItem::createDeviceMediaItem) .collect(Collectors.toList()); dividerItems.forEach(finalMediaItems::add); attachConnectNewDeviceItemIfNeeded(finalMediaItems); return finalMediaItems; Loading @@ -694,13 +702,14 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, * Initial categorization of current devices, will not be called for updates to the devices * list. */ private List<MediaItem> categorizeMediaItems(MediaDevice connectedMediaDevice, @GuardedBy("mMediaDevicesLock") private List<MediaItem> categorizeMediaItemsLocked(MediaDevice connectedMediaDevice, List<MediaDevice> devices, boolean needToHandleMutingExpectedDevice) { synchronized (mMediaDevicesLock) { List<MediaItem> finalMediaItems = new ArrayList<>(); Set<String> selectedDevicesIds = getSelectedMediaDevice().stream().map( MediaDevice::getId).collect(Collectors.toSet()); Set<String> selectedDevicesIds = getSelectedMediaDevice().stream() .map(MediaDevice::getId) .collect(Collectors.toSet()); if (connectedMediaDevice != null) { selectedDevicesIds.add(connectedMediaDevice.getId()); } Loading @@ -708,10 +717,10 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, boolean displayGroupAdded = false; for (MediaDevice device : devices) { if (needToHandleMutingExpectedDevice && device.isMutingExpectedDevice()) { finalMediaItems.add(0, new MediaItem(device)); finalMediaItems.add(0, MediaItem.createDeviceMediaItem(device)); } else if (!needToHandleMutingExpectedDevice && selectedDevicesIds.contains( device.getId())) { finalMediaItems.add(0, new MediaItem(device)); finalMediaItems.add(0, MediaItem.createDeviceMediaItem(device)); } else { if (device.isSuggestedDevice() && !suggestedDeviceAdded) { attachGroupDivider(finalMediaItems, mContext.getString( Loading @@ -722,23 +731,21 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, R.string.media_output_group_title_speakers_and_displays)); displayGroupAdded = true; } finalMediaItems.add(new MediaItem(device)); finalMediaItems.add(MediaItem.createDeviceMediaItem(device)); } } attachConnectNewDeviceItemIfNeeded(finalMediaItems); return finalMediaItems; } } private void attachGroupDivider(List<MediaItem> mediaItems, String title) { mediaItems.add( new MediaItem(title, MediaItem.MediaItemType.TYPE_GROUP_DIVIDER)); mediaItems.add(MediaItem.createGroupDividerMediaItem(title)); } private void attachConnectNewDeviceItemIfNeeded(List<MediaItem> mediaItems) { // Attach "Connect a device" item only when current output is not remote and not a group if (!isCurrentConnectedDeviceRemote() && getSelectedMediaDevice().size() == 1) { mediaItems.add(new MediaItem()); mediaItems.add(MediaItem.createPairNewDeviceMediaItem()); } } Loading
packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java +6 −5 Original line number Diff line number Diff line Loading @@ -113,8 +113,8 @@ public class MediaOutputAdapterTest extends SysuiTestCase { LocalMediaManager.MediaDeviceState.STATE_DISCONNECTED); mMediaDevices.add(mMediaDevice1); mMediaDevices.add(mMediaDevice2); mMediaItems.add(new MediaItem(mMediaDevice1)); mMediaItems.add(new MediaItem(mMediaDevice2)); mMediaItems.add(MediaItem.createDeviceMediaItem(mMediaDevice1)); mMediaItems.add(MediaItem.createDeviceMediaItem(mMediaDevice2)); mMediaOutputAdapter = new MediaOutputAdapter(mMediaOutputController); mMediaOutputAdapter.updateItems(); Loading Loading @@ -146,7 +146,8 @@ public class MediaOutputAdapterTest extends SysuiTestCase { mMediaOutputAdapter.updateItems(); mViewHolder = (MediaOutputAdapter.MediaDeviceViewHolder) mMediaOutputAdapter .onCreateViewHolder(new LinearLayout(mContext), 0); mMediaItems.add(new MediaItem()); mMediaItems.add(MediaItem.createPairNewDeviceMediaItem()); mMediaItems.add(MediaItem.createPairNewDeviceMediaItem()); mMediaOutputAdapter.updateItems(); mMediaOutputAdapter.onBindViewHolder(mViewHolder, 2); Loading Loading @@ -589,7 +590,7 @@ public class MediaOutputAdapterTest extends SysuiTestCase { mMediaOutputAdapter.updateItems(); mViewHolder = (MediaOutputAdapter.MediaDeviceViewHolder) mMediaOutputAdapter .onCreateViewHolder(new LinearLayout(mContext), 0); mMediaItems.add(new MediaItem()); mMediaItems.add(MediaItem.createPairNewDeviceMediaItem()); mMediaOutputAdapter.updateItems(); mMediaOutputAdapter.onBindViewHolder(mViewHolder, 2); mViewHolder.mContainerLayout.performClick(); Loading Loading @@ -725,7 +726,7 @@ public class MediaOutputAdapterTest extends SysuiTestCase { public void updateItems_controllerItemsUpdated_notUpdatesInAdapterUntilUpdateItems() { mMediaOutputAdapter.updateItems(); List<MediaItem> updatedList = new ArrayList<>(); updatedList.add(new MediaItem()); updatedList.add(MediaItem.createPairNewDeviceMediaItem()); when(mMediaOutputController.getMediaItemList()).thenReturn(updatedList); assertThat(mMediaOutputAdapter.getItemCount()).isEqualTo(mMediaItems.size()); Loading