Merge "[Output Switcher] Fix ArrayIndexOutOfBoundsException" into udc-dev am: 4711434e64 am: 51f71550bc

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/22891385

Change-Id: Ifcecaca246a91c975d4ae90c739b4e3c43036271
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java
index d46e6b9..d949cf56f 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java
@@ -43,6 +43,7 @@
 import com.android.systemui.R;
 
 import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
 
 /**
  * Adapter for media output dialog.
@@ -53,6 +54,7 @@
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
     private static final float DEVICE_DISCONNECTED_ALPHA = 0.5f;
     private static final float DEVICE_CONNECTED_ALPHA = 1f;
+    protected List<MediaItem> mMediaItemList = new CopyOnWriteArrayList<>();
 
     public MediaOutputAdapter(MediaOutputController controller) {
         super(controller);
@@ -60,6 +62,13 @@
     }
 
     @Override
+    public void updateItems() {
+        mMediaItemList.clear();
+        mMediaItemList.addAll(mController.getMediaItemList());
+        notifyDataSetChanged();
+    }
+
+    @Override
     public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup,
             int viewType) {
         super.onCreateViewHolder(viewGroup, viewType);
@@ -80,14 +89,14 @@
     @Override
     public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int position) {
         if (mController.isAdvancedLayoutSupported()) {
-            if (position >= mController.getMediaItemList().size()) {
+            if (position >= mMediaItemList.size()) {
                 if (DEBUG) {
                     Log.d(TAG, "Incorrect position: " + position + " list size: "
-                            + mController.getMediaItemList().size());
+                            + mMediaItemList.size());
                 }
                 return;
             }
-            MediaItem currentMediaItem = mController.getMediaItemList().get(position);
+            MediaItem currentMediaItem = mMediaItemList.get(position);
             switch (currentMediaItem.getMediaItemType()) {
                 case MediaItem.MediaItemType.TYPE_GROUP_DIVIDER:
                     ((MediaGroupDividerViewHolder) viewHolder).onBind(currentMediaItem.getTitle());
@@ -120,11 +129,11 @@
     @Override
     public long getItemId(int position) {
         if (mController.isAdvancedLayoutSupported()) {
-            if (position >= mController.getMediaItemList().size()) {
+            if (position >= mMediaItemList.size()) {
                 Log.d(TAG, "Incorrect position for item id: " + position);
                 return position;
             }
-            MediaItem currentMediaItem = mController.getMediaItemList().get(position);
+            MediaItem currentMediaItem = mMediaItemList.get(position);
             return currentMediaItem.getMediaDevice().isPresent()
                     ? currentMediaItem.getMediaDevice().get().getId().hashCode()
                     : position;
@@ -144,12 +153,12 @@
     @Override
     public int getItemViewType(int position) {
         if (mController.isAdvancedLayoutSupported()
-                && position >= mController.getMediaItemList().size()) {
+                && position >= mMediaItemList.size()) {
             Log.d(TAG, "Incorrect position for item type: " + position);
             return MediaItem.MediaItemType.TYPE_GROUP_DIVIDER;
         }
         return mController.isAdvancedLayoutSupported()
-                ? mController.getMediaItemList().get(position).getMediaItemType()
+                ? mMediaItemList.get(position).getMediaItemType()
                 : super.getItemViewType(position);
     }
 
@@ -157,7 +166,7 @@
     public int getItemCount() {
         // Add extra one for "pair new"
         return mController.isAdvancedLayoutSupported()
-                ? mController.getMediaItemList().size()
+                ? mMediaItemList.size()
                 : mController.getMediaDevices().size() + 1;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java
index 73ab5272..151dbb2 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java
@@ -81,6 +81,11 @@
         mIsInitVolumeFirstTime = true;
     }
 
+    /**
+     * Refresh current dataset
+     */
+    public abstract void updateItems();
+
     @Override
     public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup,
             int viewType) {
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java
index 08e47a0..770e4df 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java
@@ -382,7 +382,7 @@
                     && currentActivePosition < mAdapter.getItemCount()) {
                 mAdapter.notifyItemChanged(currentActivePosition);
             } else {
-                mAdapter.notifyDataSetChanged();
+                mAdapter.updateItems();
             }
         } else {
             mMediaOutputController.setRefreshing(false);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java
index 17d2f7b..faca8a91d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java
@@ -119,6 +119,7 @@
         mMediaItems.add(new MediaItem(mMediaDevice2));
 
         mMediaOutputAdapter = new MediaOutputAdapter(mMediaOutputController);
+        mMediaOutputAdapter.updateItems();
         mViewHolder = (MediaOutputAdapter.MediaDeviceViewHolder) mMediaOutputAdapter
                 .onCreateViewHolder(new LinearLayout(mContext), 0);
         mSpyMediaOutputSeekbar = spy(mViewHolder.mSeekBar);
@@ -205,9 +206,11 @@
     public void advanced_onBindViewHolder_bindPairNew_verifyView() {
         when(mMediaOutputController.isAdvancedLayoutSupported()).thenReturn(true);
         mMediaOutputAdapter = new MediaOutputAdapter(mMediaOutputController);
+        mMediaOutputAdapter.updateItems();
         mViewHolder = (MediaOutputAdapter.MediaDeviceViewHolder) mMediaOutputAdapter
                 .onCreateViewHolder(new LinearLayout(mContext), 0);
         mMediaItems.add(new MediaItem());
+        mMediaOutputAdapter.updateItems();
         mMediaOutputAdapter.onBindViewHolder(mViewHolder, 2);
 
         assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.VISIBLE);
@@ -226,6 +229,7 @@
                         Collectors.toList()));
         when(mMediaOutputController.getSessionName()).thenReturn(TEST_SESSION_NAME);
         mMediaOutputAdapter = new MediaOutputAdapter(mMediaOutputController);
+        mMediaOutputAdapter.updateItems();
         mViewHolder = (MediaOutputAdapter.MediaDeviceViewHolder) mMediaOutputAdapter
                 .onCreateViewHolder(new LinearLayout(mContext), 0);
         mMediaOutputAdapter.getItemCount();
@@ -246,6 +250,7 @@
                         Collectors.toList()));
         when(mMediaOutputController.getSessionName()).thenReturn(null);
         mMediaOutputAdapter = new MediaOutputAdapter(mMediaOutputController);
+        mMediaOutputAdapter.updateItems();
         mViewHolder = (MediaOutputAdapter.MediaDeviceViewHolder) mMediaOutputAdapter
                 .onCreateViewHolder(new LinearLayout(mContext), 0);
         mMediaOutputAdapter.getItemCount();
@@ -605,9 +610,11 @@
     public void advanced_onItemClick_clickPairNew_verifyLaunchBluetoothPairing() {
         when(mMediaOutputController.isAdvancedLayoutSupported()).thenReturn(true);
         mMediaOutputAdapter = new MediaOutputAdapter(mMediaOutputController);
+        mMediaOutputAdapter.updateItems();
         mViewHolder = (MediaOutputAdapter.MediaDeviceViewHolder) mMediaOutputAdapter
                 .onCreateViewHolder(new LinearLayout(mContext), 0);
         mMediaItems.add(new MediaItem());
+        mMediaOutputAdapter.updateItems();
         mMediaOutputAdapter.onBindViewHolder(mViewHolder, 2);
         mViewHolder.mContainerLayout.performClick();
 
@@ -719,6 +726,7 @@
                 mMediaItems.stream().map((item) -> item.getMediaDevice().get()).collect(
                         Collectors.toList()));
         mMediaOutputAdapter = new MediaOutputAdapter(mMediaOutputController);
+        mMediaOutputAdapter.updateItems();
         mViewHolder = (MediaOutputAdapter.MediaDeviceViewHolder) mMediaOutputAdapter
                 .onCreateViewHolder(new LinearLayout(mContext), 0);
         List<MediaDevice> selectableDevices = new ArrayList<>();
@@ -753,4 +761,18 @@
 
         verify(mMediaOutputController).setCurrentColorScheme(wallpaperColors, true);
     }
+
+    @Test
+    public void updateItems_controllerItemsUpdated_notUpdatesInAdapterUntilUpdateItems() {
+        when(mMediaOutputController.isAdvancedLayoutSupported()).thenReturn(true);
+        mMediaOutputAdapter.updateItems();
+        List<MediaItem> updatedList = new ArrayList<>();
+        updatedList.add(new MediaItem());
+        when(mMediaOutputController.getMediaItemList()).thenReturn(updatedList);
+        assertThat(mMediaOutputAdapter.getItemCount()).isEqualTo(mMediaItems.size());
+
+        mMediaOutputAdapter.updateItems();
+
+        assertThat(mMediaOutputAdapter.getItemCount()).isEqualTo(updatedList.size());
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java
index f206409..480d59c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java
@@ -239,7 +239,7 @@
         when(mMediaOutputBaseAdapter.isDragging()).thenReturn(false);
         mMediaOutputBaseDialogImpl.refresh();
 
-        verify(mMediaOutputBaseAdapter).notifyDataSetChanged();
+        verify(mMediaOutputBaseAdapter).updateItems();
     }
 
     @Test