Use static filter for inflater of RemoteViews

This will get rid of the RemoteViews leak caused by ViewStub keeping
reference of LayoutInflater. But subclasses of RemoteViews won't be
affected to avoid breaking overriden usage.
Bug: 141699084
Test: Manually test. Leak disappeared. atest RemoteViewsTest

Change-Id: I1b287a166df92e424208ae35eb84bfd6aa553ddf
diff --git a/api/current.txt b/api/current.txt
index f9a2957..8e71161 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -56944,7 +56944,7 @@
     method public int describeContents();
     method public int getLayoutId();
     method public String getPackage();
-    method public boolean onLoadClass(Class);
+    method @Deprecated public boolean onLoadClass(Class);
     method public void reapply(android.content.Context, android.view.View);
     method public void removeAllViews(int);
     method public void setAccessibilityTraversalAfter(int, int);
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 2931f33..c132452 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -10402,6 +10402,16 @@
             p.recycle();
             return brv;
         }
+
+        /**
+         * Override and return true, since {@link RemoteViews#onLoadClass(Class)} is not overridden.
+         *
+         * @see RemoteViews#shouldUseStaticFilter()
+         */
+        @Override
+        protected boolean shouldUseStaticFilter() {
+            return true;
+        }
     }
 
     /**
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 86cec5e..c571737 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -202,6 +202,14 @@
     public static final int FLAG_USE_LIGHT_BACKGROUND_LAYOUT = 4;
 
     /**
+     * Used to restrict the views which can be inflated
+     *
+     * @see android.view.LayoutInflater.Filter#onLoadClass(java.lang.Class)
+     */
+    private static final LayoutInflater.Filter INFLATER_FILTER =
+            (clazz) -> clazz.isAnnotationPresent(RemoteViews.RemoteView.class);
+
+    /**
      * Application that hosts the remote views.
      *
      * @hide
@@ -3413,13 +3421,24 @@
         // Clone inflater so we load resources from correct context and
         // we don't add a filter to the static version returned by getSystemService.
         inflater = inflater.cloneInContext(inflationContext);
-        inflater.setFilter(this);
+        inflater.setFilter(shouldUseStaticFilter() ? INFLATER_FILTER : this);
         View v = inflater.inflate(rv.getLayoutId(), parent, false);
         v.setTagInternal(R.id.widget_frame, rv.getLayoutId());
         return v;
     }
 
     /**
+     * A static filter is much lighter than RemoteViews itself. It's optimized here only for
+     * RemoteVies class. Subclasses should always override this and return true if not overriding
+     * {@link this#onLoadClass(Class)}.
+     *
+     * @hide
+     */
+    protected boolean shouldUseStaticFilter() {
+        return this.getClass().equals(RemoteViews.class);
+    }
+
+    /**
      * Implement this interface to receive a callback when
      * {@link #applyAsync} or {@link #reapplyAsync} is finished.
      * @hide
@@ -3686,11 +3705,15 @@
         return (mActions == null) ? 0 : mActions.size();
     }
 
-    /* (non-Javadoc)
+    /**
      * Used to restrict the views which can be inflated
      *
      * @see android.view.LayoutInflater.Filter#onLoadClass(java.lang.Class)
+     * @deprecated Used by system to enforce safe inflation of {@link RemoteViews}. Apps should not
+     * override this method. Changing of this method will NOT affect the process where RemoteViews
+     * is rendered.
      */
+    @Deprecated
     public boolean onLoadClass(Class clazz) {
         return clazz.isAnnotationPresent(RemoteView.class);
     }