From 6e9e5faa9799a8715d80400928b97b452b269fb0 Mon Sep 17 00:00:00 2001 From: Zhen Zhang Date: Tue, 12 Nov 2019 10:51:00 -0800 Subject: 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 --- core/java/android/widget/RemoteViews.java | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) (limited to 'core/java/android/widget/RemoteViews.java') diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java index 86cec5e0f0a2..c571737cec8f 100644 --- a/core/java/android/widget/RemoteViews.java +++ b/core/java/android/widget/RemoteViews.java @@ -201,6 +201,14 @@ public class RemoteViews implements Parcelable, Filter { */ 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. * @@ -3413,12 +3421,23 @@ public class RemoteViews implements Parcelable, Filter { // 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. @@ -3686,11 +3705,15 @@ public class RemoteViews implements Parcelable, Filter { 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); } -- cgit v1.2.3