From fea79005bd969d392f7f98a2f38d3bbfd877487c Mon Sep 17 00:00:00 2001 From: Bryce Lee Date: Fri, 7 Apr 2017 22:06:52 +0000 Subject: [PATCH] Do not make strong reference to Resources. This CL removes the strong reference added for mapping display ids and Resources to Displays. Instead, the key pair is now the display id and ResourcesKey, and the mapping is pruned when key is invalidated. Change-Id: If91368171212b28c40e03c15fb39c72412a44811 Fixes: 36625868 Test: make -j32 cts; cts-tradefed; run cts --module CtsAppTestCases --test android.app.cts.DisplayTest#testRotation --- core/java/android/app/ResourcesManager.java | 43 ++++++++++++++++++--- 1 file changed, 37 insertions(+), 6 deletions(-) diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java index d620a81e985b4..3191eec03ffa0 100644 --- a/core/java/android/app/ResourcesManager.java +++ b/core/java/android/app/ResourcesManager.java @@ -44,6 +44,8 @@ import com.android.internal.util.ArrayUtils; import java.lang.ref.WeakReference; import java.util.ArrayList; +import java.util.Iterator; +import java.util.Map; import java.util.Objects; import java.util.WeakHashMap; import java.util.function.Predicate; @@ -114,7 +116,7 @@ public class ResourcesManager { * A cache of DisplayId, Resources to Display. These display adjustments associated with these * {@link Display}s will change as the resources change. */ - private final ArrayMap, WeakReference> mResourceDisplays = + private final ArrayMap, WeakReference> mResourceDisplays = new ArrayMap<>(); public static ResourcesManager getInstance() { @@ -137,10 +139,7 @@ public class ResourcesManager { for (int i = 0; i < mResourceImpls.size();) { final ResourcesKey key = mResourceImpls.keyAt(i); if (key.isPathReferenced(path)) { - final ResourcesImpl res = mResourceImpls.removeAt(i).get(); - if (res != null) { - res.flushLayoutCache(); - } + cleanupResourceImpl(key); count++; } else { i++; @@ -251,8 +250,14 @@ public class ResourcesManager { * @param resources The {@link Resources} backing the display adjustments. */ public Display getAdjustedDisplay(final int displayId, Resources resources) { - final Pair key = Pair.create(displayId, resources); synchronized (this) { + // Note that the ResourcesKey might be {@code null} in the case that the + // {@link Resources} is actually from {@link Resources#getSystem}. In this case, it is + // not managed by {@link ResourcesManager}, but we still want to cache the display + // object. + final Pair key = Pair.create(displayId, + findKeyForResourceImplLocked(resources.getImpl())); + WeakReference wd = mResourceDisplays.get(key); if (wd != null) { final Display display = wd.get(); @@ -273,6 +278,32 @@ public class ResourcesManager { } } + private void cleanupResourceImpl(ResourcesKey removedKey) { + // Remove any resource to display mapping based on this key. + final Iterator, WeakReference>> iter = + mResourceDisplays.entrySet().iterator(); + while (iter.hasNext()) { + final Map.Entry, WeakReference> entry = + iter.next(); + final ResourcesKey key = entry.getKey().second; + + // Do not touch system resource displays (indicated by a {@code null} key) or + // non-matching keys. + if (key == null || !key.equals(removedKey)) { + continue; + } + + iter.remove(); + } + + // Remove resource key to resource impl mapping and flush cache + final ResourcesImpl res = mResourceImpls.remove(removedKey).get(); + + if (res != null) { + res.flushLayoutCache(); + } + } + /** * Creates an AssetManager from the paths within the ResourcesKey. *