From bd60e5bf2e58a5e6ef48281d684197aaf4f113fd Mon Sep 17 00:00:00 2001 From: Jason Monk Date: Thu, 2 Mar 2017 12:55:00 -0500 Subject: [PATCH] Let ResourcesManager generate CompatResources This will let the ResourcesImpl be updated and handle null cases better. Test: Select text while composing email. Change-Id: Ia8aed22f02b040a202db9cbb2bc02687c693cfa1 Fixes: 34761805 Fixes: 35869547 --- core/java/android/app/ContextImpl.java | 7 +++---- core/java/android/app/ResourcesManager.java | 20 +++++++++++-------- .../android/content/res/CompatResources.java | 14 +++++++++---- .../content/res/CompatibilityInfo.java | 14 +++++++++++++ 4 files changed, 39 insertions(+), 16 deletions(-) diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index 7ee93d0ee7907..0ab4b808af950 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -2254,11 +2254,10 @@ class ContextImpl extends Context { } void setResources(Resources r) { - if (mPackageInfo.getTargetSdkVersion() < VERSION_CODES.O) { - mResources = new CompatResources(r, this); - } else { - mResources = r; + if (r instanceof CompatResources) { + ((CompatResources) r).setContext(this); } + mResources = r; } void installSystemApplicationInfo(ApplicationInfo info, ClassLoader classLoader) { diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java index 52ec045d5b605..b42df5e2e0fb6 100644 --- a/core/java/android/app/ResourcesManager.java +++ b/core/java/android/app/ResourcesManager.java @@ -22,6 +22,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.content.pm.ActivityInfo; import android.content.res.AssetManager; +import android.content.res.CompatResources; import android.content.res.CompatibilityInfo; import android.content.res.Configuration; import android.content.res.Resources; @@ -447,7 +448,8 @@ public class ResourcesManager { * or the class loader is different. */ private @NonNull Resources getOrCreateResourcesForActivityLocked(@NonNull IBinder activityToken, - @NonNull ClassLoader classLoader, @NonNull ResourcesImpl impl) { + @NonNull ClassLoader classLoader, @NonNull ResourcesImpl impl, + @NonNull CompatibilityInfo compatInfo) { final ActivityResources activityResources = getOrCreateActivityResourcesStructLocked( activityToken); @@ -466,7 +468,8 @@ public class ResourcesManager { } } - Resources resources = new Resources(classLoader); + Resources resources = compatInfo.needsCompatResources() ? new CompatResources(classLoader) + : new Resources(classLoader); resources.setImpl(impl); activityResources.activityResources.add(new WeakReference<>(resources)); if (DEBUG) { @@ -481,7 +484,7 @@ public class ResourcesManager { * otherwise creates a new Resources object. */ private @NonNull Resources getOrCreateResourcesLocked(@NonNull ClassLoader classLoader, - @NonNull ResourcesImpl impl) { + @NonNull ResourcesImpl impl, @NonNull CompatibilityInfo compatInfo) { // Find an existing Resources that has this ResourcesImpl set. final int refCount = mResourceReferences.size(); for (int i = 0; i < refCount; i++) { @@ -498,7 +501,8 @@ public class ResourcesManager { } // Create a new Resources reference and use the existing ResourcesImpl object. - Resources resources = new Resources(classLoader); + Resources resources = compatInfo.needsCompatResources() ? new CompatResources(classLoader) + : new Resources(classLoader); resources.setImpl(impl); mResourceReferences.add(new WeakReference<>(resources)); if (DEBUG) { @@ -614,7 +618,7 @@ public class ResourcesManager { Slog.d(TAG, "- using existing impl=" + resourcesImpl); } return getOrCreateResourcesForActivityLocked(activityToken, classLoader, - resourcesImpl); + resourcesImpl, key.mCompatInfo); } // We will create the ResourcesImpl object outside of holding this lock. @@ -629,7 +633,7 @@ public class ResourcesManager { if (DEBUG) { Slog.d(TAG, "- using existing impl=" + resourcesImpl); } - return getOrCreateResourcesLocked(classLoader, resourcesImpl); + return getOrCreateResourcesLocked(classLoader, resourcesImpl, key.mCompatInfo); } // We will create the ResourcesImpl object outside of holding this lock. @@ -659,9 +663,9 @@ public class ResourcesManager { final Resources resources; if (activityToken != null) { resources = getOrCreateResourcesForActivityLocked(activityToken, classLoader, - resourcesImpl); + resourcesImpl, key.mCompatInfo); } else { - resources = getOrCreateResourcesLocked(classLoader, resourcesImpl); + resources = getOrCreateResourcesLocked(classLoader, resourcesImpl, key.mCompatInfo); } return resources; } diff --git a/core/java/android/content/res/CompatResources.java b/core/java/android/content/res/CompatResources.java index 15575fd10e83a..829b6b7f9a475 100644 --- a/core/java/android/content/res/CompatResources.java +++ b/core/java/android/content/res/CompatResources.java @@ -27,11 +27,17 @@ import java.lang.ref.WeakReference; */ public class CompatResources extends Resources { - private final WeakReference mContext; + private WeakReference mContext; - public CompatResources(Resources base, Context context) { - super(base.getClassLoader()); - setImpl(base.getImpl()); + public CompatResources(ClassLoader cls) { + super(cls); + mContext = new WeakReference<>(null); + } + + /** + * @hide + */ + public void setContext(Context context) { mContext = new WeakReference<>(context); } diff --git a/core/java/android/content/res/CompatibilityInfo.java b/core/java/android/content/res/CompatibilityInfo.java index da35ee92267e4..781e235338702 100644 --- a/core/java/android/content/res/CompatibilityInfo.java +++ b/core/java/android/content/res/CompatibilityInfo.java @@ -21,6 +21,8 @@ import android.graphics.Canvas; import android.graphics.PointF; import android.graphics.Rect; import android.graphics.Region; +import android.os.Build; +import android.os.Build.VERSION_CODES; import android.os.Parcel; import android.os.Parcelable; import android.util.DisplayMetrics; @@ -77,6 +79,11 @@ public class CompatibilityInfo implements Parcelable { */ private static final int NEEDS_SCREEN_COMPAT = 8; + /** + * Set if the application needs to run in with compat resources. + */ + private static final int NEEDS_COMPAT_RES = 16; + /** * The effective screen density we have selected for this application. */ @@ -96,6 +103,9 @@ public class CompatibilityInfo implements Parcelable { boolean forceCompat) { int compatFlags = 0; + if (appInfo.targetSdkVersion < VERSION_CODES.O) { + compatFlags |= NEEDS_COMPAT_RES; + } if (appInfo.requiresSmallestWidthDp != 0 || appInfo.compatibleWidthLimitDp != 0 || appInfo.largestWidthLimitDp != 0) { // New style screen requirements spec. @@ -274,6 +284,10 @@ public class CompatibilityInfo implements Parcelable { return (mCompatibilityFlags&NEVER_NEEDS_COMPAT) != 0; } + public boolean needsCompatResources() { + return (mCompatibilityFlags&NEEDS_COMPAT_RES) != 0; + } + /** * Returns the translator which translates the coordinates in compatibility mode. * @param params the window's parameter