Merge "Merge "Making adapter child views in RemoteCollectionItemsAdapter size-aware" into android14-tests-dev am: 83b74c074b" into main am: dd7cd7c03a

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

Change-Id: I186fe70ba8748d5df90ff9957ace9cdb4838e437
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/core/java/android/appwidget/AppWidgetHostView.java b/core/java/android/appwidget/AppWidgetHostView.java
index 27f6a26..ec181da 100644
--- a/core/java/android/appwidget/AppWidgetHostView.java
+++ b/core/java/android/appwidget/AppWidgetHostView.java
@@ -156,6 +156,22 @@
     }
 
     /**
+     * @hide
+     */
+    public static class AdapterChildHostView extends AppWidgetHostView {
+
+        public AdapterChildHostView(Context context) {
+            super(context);
+        }
+
+        @Override
+        public Context getRemoteContextEnsuringCorrectCachedApkPath() {
+            // To reduce noise in error messages
+            return null;
+        }
+    }
+
+    /**
      * Set the AppWidget that will be displayed by this view. This method also adds default padding
      * to widgets, as described in {@link #getDefaultPaddingForWidget(Context, ComponentName, Rect)}
      * and can be overridden in order to add custom padding.
@@ -921,17 +937,31 @@
         setColorResources(RemoteViews.ColorResources.create(mContext, colorMapping));
     }
 
+    private void setColorResourcesStates(RemoteViews.ColorResources colorResources) {
+        mColorResources = colorResources;
+        mColorMappingChanged = true;
+        mViewMode = VIEW_MODE_NOINIT;
+    }
+
     /** @hide **/
     public void setColorResources(RemoteViews.ColorResources colorResources) {
         if (colorResources == mColorResources) {
             return;
         }
-        mColorResources = colorResources;
-        mColorMappingChanged = true;
-        mViewMode = VIEW_MODE_NOINIT;
+        setColorResourcesStates(colorResources);
         reapplyLastRemoteViews();
     }
 
+    /**
+     * @hide
+     */
+    public void setColorResourcesNoReapply(RemoteViews.ColorResources colorResources) {
+        if (colorResources == mColorResources) {
+            return;
+        }
+        setColorResourcesStates(colorResources);
+    }
+
     /** Check if, in the current context, the two color mappings are equivalent. */
     private boolean isSameColorMapping(SparseIntArray oldColors, SparseIntArray newColors) {
         if (oldColors.size() != newColors.size()) {
diff --git a/core/java/android/widget/RemoteCollectionItemsAdapter.java b/core/java/android/widget/RemoteCollectionItemsAdapter.java
index d843308..9b396ae 100644
--- a/core/java/android/widget/RemoteCollectionItemsAdapter.java
+++ b/core/java/android/widget/RemoteCollectionItemsAdapter.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.appwidget.AppWidgetHostView;
 import android.util.SparseIntArray;
 import android.view.View;
 import android.view.ViewGroup;
@@ -25,8 +26,6 @@
 import android.widget.RemoteViews.InteractionHandler;
 import android.widget.RemoteViews.RemoteCollectionItems;
 
-import com.android.internal.R;
-
 import java.util.stream.IntStream;
 
 /**
@@ -178,40 +177,14 @@
 
         RemoteViews item = mItems.getItemView(position);
         item.addFlags(RemoteViews.FLAG_WIDGET_IS_COLLECTION_CHILD);
-        View reapplyView = getViewToReapply(convertView, item);
 
-        // Reapply the RemoteViews if we can.
-        if (reapplyView != null) {
-            try {
-                item.reapply(
-                        parent.getContext(),
-                        reapplyView,
-                        mInteractionHandler,
-                        null /* size */,
-                        mColorResources);
-                return reapplyView;
-            } catch (RuntimeException e) {
-                // We can't reapply for some reason, we'll fallback to an apply and inflate a
-                // new view.
-            }
-        }
-
-        return item.apply(
-                parent.getContext(),
-                parent,
-                mInteractionHandler,
-                null /* size */,
-                mColorResources);
-    }
-
-    /** Returns {@code convertView} if it can be used to reapply {@code item}, or null otherwise. */
-    @Nullable
-    private static View getViewToReapply(@Nullable View convertView, @NonNull RemoteViews item) {
-        if (convertView == null) return null;
-
-        Object layoutIdTag = convertView.getTag(R.id.widget_frame);
-        if (!(layoutIdTag instanceof Integer)) return null;
-
-        return item.getLayoutId() == (Integer) layoutIdTag ? convertView : null;
+        AppWidgetHostView newView = convertView instanceof AppWidgetHostView.AdapterChildHostView
+                widgetChildView
+                ? widgetChildView
+                : new AppWidgetHostView.AdapterChildHostView(parent.getContext());
+        newView.setInteractionHandler(mInteractionHandler);
+        newView.setColorResourcesNoReapply(mColorResources);
+        newView.updateAppWidget(item);
+        return newView;
     }
 }
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index a740b65..eb3f96e 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -6913,13 +6913,13 @@
             View parent = (View) view.getParent();
             // Break the for loop on the first encounter of:
             //    1) an AdapterView,
-            //    2) an AppWidgetHostView that is not a RemoteViewsFrameLayout, or
+            //    2) an AppWidgetHostView that is not a child of an adapter view, or
             //    3) a null parent.
             // 2) and 3) are unexpected and catch the case where a child is not
             // correctly parented in an AdapterView.
             while (parent != null && !(parent instanceof AdapterView<?>)
                     && !((parent instanceof AppWidgetHostView)
-                    && !(parent instanceof RemoteViewsAdapter.RemoteViewsFrameLayout))) {
+                            && !(parent instanceof AppWidgetHostView.AdapterChildHostView))) {
                 parent = (View) parent.getParent();
             }
 
diff --git a/core/java/android/widget/RemoteViewsAdapter.java b/core/java/android/widget/RemoteViewsAdapter.java
index 61a7599..2f28a87 100644
--- a/core/java/android/widget/RemoteViewsAdapter.java
+++ b/core/java/android/widget/RemoteViewsAdapter.java
@@ -368,7 +368,7 @@
      * A FrameLayout which contains a loading view, and manages the re/applying of RemoteViews when
      * they are loaded.
      */
-    static class RemoteViewsFrameLayout extends AppWidgetHostView {
+    static class RemoteViewsFrameLayout extends AppWidgetHostView.AdapterChildHostView {
         private final FixedSizeRemoteViewsCache mCache;
 
         public int cacheIndex = -1;
@@ -408,11 +408,6 @@
         }
 
         @Override
-        protected Context getRemoteContextEnsuringCorrectCachedApkPath() {
-            return null;
-        }
-
-        @Override
         protected View getErrorView() {
             // Use the default loading view as the error view.
             return getDefaultView();