Merge "Fix drawable-state cache expired issue" into main am: 3ba29fc4e8
Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/2437312 Change-Id: Ia11517a53200e6010c014b890955976b66bcd001 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -53,6 +53,7 @@ import android.graphics.drawable.Drawable.ConstantState;
|
|||||||
import android.graphics.drawable.DrawableInflater;
|
import android.graphics.drawable.DrawableInflater;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.os.SystemClock;
|
||||||
import android.util.ArrayMap;
|
import android.util.ArrayMap;
|
||||||
import android.util.ArraySet;
|
import android.util.ArraySet;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
@@ -132,6 +133,11 @@ public class Resources {
|
|||||||
private static final Object sSync = new Object();
|
private static final Object sSync = new Object();
|
||||||
private final Object mUpdateLock = new Object();
|
private final Object mUpdateLock = new Object();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Controls whether we should preload resources during zygote init.
|
||||||
|
*/
|
||||||
|
private static final boolean PRELOAD_RESOURCES = true;
|
||||||
|
|
||||||
// Used by BridgeResources in layoutlib
|
// Used by BridgeResources in layoutlib
|
||||||
@UnsupportedAppUsage
|
@UnsupportedAppUsage
|
||||||
static Resources mSystem = null;
|
static Resources mSystem = null;
|
||||||
@@ -2666,6 +2672,98 @@ public class Resources {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load in commonly used resources, so they can be shared across processes.
|
||||||
|
*
|
||||||
|
* These tend to be a few Kbytes, but are frequently in the 20-40K range, and occasionally even
|
||||||
|
* larger.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
@UnsupportedAppUsage
|
||||||
|
public static void preloadResources() {
|
||||||
|
try {
|
||||||
|
final Resources sysRes = Resources.getSystem();
|
||||||
|
sysRes.startPreloading();
|
||||||
|
if (PRELOAD_RESOURCES) {
|
||||||
|
Log.i(TAG, "Preloading resources...");
|
||||||
|
|
||||||
|
long startTime = SystemClock.uptimeMillis();
|
||||||
|
TypedArray ar = sysRes.obtainTypedArray(
|
||||||
|
com.android.internal.R.array.preloaded_drawables);
|
||||||
|
int numberOfEntries = preloadDrawables(sysRes, ar);
|
||||||
|
ar.recycle();
|
||||||
|
Log.i(TAG, "...preloaded " + numberOfEntries + " resources in "
|
||||||
|
+ (SystemClock.uptimeMillis() - startTime) + "ms.");
|
||||||
|
|
||||||
|
startTime = SystemClock.uptimeMillis();
|
||||||
|
ar = sysRes.obtainTypedArray(
|
||||||
|
com.android.internal.R.array.preloaded_color_state_lists);
|
||||||
|
numberOfEntries = preloadColorStateLists(sysRes, ar);
|
||||||
|
ar.recycle();
|
||||||
|
Log.i(TAG, "...preloaded " + numberOfEntries + " resources in "
|
||||||
|
+ (SystemClock.uptimeMillis() - startTime) + "ms.");
|
||||||
|
|
||||||
|
if (sysRes.getBoolean(
|
||||||
|
com.android.internal.R.bool.config_freeformWindowManagement)) {
|
||||||
|
startTime = SystemClock.uptimeMillis();
|
||||||
|
ar = sysRes.obtainTypedArray(
|
||||||
|
com.android.internal.R.array.preloaded_freeform_multi_window_drawables);
|
||||||
|
numberOfEntries = preloadDrawables(sysRes, ar);
|
||||||
|
ar.recycle();
|
||||||
|
Log.i(TAG, "...preloaded " + numberOfEntries + " resource in "
|
||||||
|
+ (SystemClock.uptimeMillis() - startTime) + "ms.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sysRes.finishPreloading();
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
Log.w(TAG, "Failure preloading resources", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int preloadColorStateLists(Resources resources, TypedArray ar) {
|
||||||
|
final int numberOfEntries = ar.length();
|
||||||
|
for (int i = 0; i < numberOfEntries; i++) {
|
||||||
|
int id = ar.getResourceId(i, 0);
|
||||||
|
|
||||||
|
if (id != 0) {
|
||||||
|
if (resources.getColorStateList(id, null) == null) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Unable to find preloaded color resource #0x"
|
||||||
|
+ Integer.toHexString(id)
|
||||||
|
+ " (" + ar.getString(i) + ")");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return numberOfEntries;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int preloadDrawables(Resources resources, TypedArray ar) {
|
||||||
|
final int numberOfEntries = ar.length();
|
||||||
|
for (int i = 0; i < numberOfEntries; i++) {
|
||||||
|
int id = ar.getResourceId(i, 0);
|
||||||
|
|
||||||
|
if (id != 0) {
|
||||||
|
if (resources.getDrawable(id, null) == null) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Unable to find preloaded drawable resource #0x"
|
||||||
|
+ Integer.toHexString(id)
|
||||||
|
+ " (" + ar.getString(i) + ")");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return numberOfEntries;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear the cache when the framework resources packages is changed.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
@VisibleForTesting
|
||||||
|
public static void resetPreloadDrawableStateCache() {
|
||||||
|
ResourcesImpl.resetDrawableStateCache();
|
||||||
|
preloadResources();
|
||||||
|
}
|
||||||
|
|
||||||
/** @hide */
|
/** @hide */
|
||||||
public void dump(PrintWriter pw, String prefix) {
|
public void dump(PrintWriter pw, String prefix) {
|
||||||
pw.println(prefix + "class=" + getClass());
|
pw.println(prefix + "class=" + getClass());
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ import android.util.TypedValue;
|
|||||||
import android.util.Xml;
|
import android.util.Xml;
|
||||||
import android.view.DisplayAdjustments;
|
import android.view.DisplayAdjustments;
|
||||||
|
|
||||||
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
import com.android.internal.util.GrowingArrayUtils;
|
import com.android.internal.util.GrowingArrayUtils;
|
||||||
|
|
||||||
import libcore.util.NativeAllocationRegistry;
|
import libcore.util.NativeAllocationRegistry;
|
||||||
@@ -158,6 +159,23 @@ public class ResourcesImpl {
|
|||||||
sPreloadedDrawables[1] = new LongSparseArray<>();
|
sPreloadedDrawables[1] = new LongSparseArray<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear the cache when the framework resources packages is changed.
|
||||||
|
*
|
||||||
|
* It's only used in the test initial function instead of regular app behaviors. It doesn't
|
||||||
|
* guarantee the thread-safety so mark this with @VisibleForTesting.
|
||||||
|
*/
|
||||||
|
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
|
||||||
|
static void resetDrawableStateCache() {
|
||||||
|
synchronized (sSync) {
|
||||||
|
sPreloadedDrawables[0].clear();
|
||||||
|
sPreloadedDrawables[1].clear();
|
||||||
|
sPreloadedColorDrawables.clear();
|
||||||
|
sPreloadedComplexColors.clear();
|
||||||
|
sPreloaded = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new ResourcesImpl object with CompatibilityInfo.
|
* Creates a new ResourcesImpl object with CompatibilityInfo.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ import android.app.ApplicationLoaders;
|
|||||||
import android.compat.annotation.UnsupportedAppUsage;
|
import android.compat.annotation.UnsupportedAppUsage;
|
||||||
import android.content.pm.SharedLibraryInfo;
|
import android.content.pm.SharedLibraryInfo;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.content.res.TypedArray;
|
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Environment;
|
import android.os.Environment;
|
||||||
import android.os.IInstalld;
|
import android.os.IInstalld;
|
||||||
@@ -101,22 +100,11 @@ public class ZygoteInit {
|
|||||||
// --usap-socket-name parameter.
|
// --usap-socket-name parameter.
|
||||||
private static final String SOCKET_NAME_ARG = "--socket-name=";
|
private static final String SOCKET_NAME_ARG = "--socket-name=";
|
||||||
|
|
||||||
/**
|
|
||||||
* Used to pre-load resources.
|
|
||||||
*/
|
|
||||||
@UnsupportedAppUsage
|
|
||||||
private static Resources mResources;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The path of a file that contains classes to preload.
|
* The path of a file that contains classes to preload.
|
||||||
*/
|
*/
|
||||||
private static final String PRELOADED_CLASSES = "/system/etc/preloaded-classes";
|
private static final String PRELOADED_CLASSES = "/system/etc/preloaded-classes";
|
||||||
|
|
||||||
/**
|
|
||||||
* Controls whether we should preload resources during zygote init.
|
|
||||||
*/
|
|
||||||
private static final boolean PRELOAD_RESOURCES = true;
|
|
||||||
|
|
||||||
private static final int UNPRIVILEGED_UID = 9999;
|
private static final int UNPRIVILEGED_UID = 9999;
|
||||||
private static final int UNPRIVILEGED_GID = 9999;
|
private static final int UNPRIVILEGED_GID = 9999;
|
||||||
|
|
||||||
@@ -143,7 +131,7 @@ public class ZygoteInit {
|
|||||||
cacheNonBootClasspathClassLoaders();
|
cacheNonBootClasspathClassLoaders();
|
||||||
bootTimingsTraceLog.traceEnd(); // CacheNonBootClasspathClassLoaders
|
bootTimingsTraceLog.traceEnd(); // CacheNonBootClasspathClassLoaders
|
||||||
bootTimingsTraceLog.traceBegin("PreloadResources");
|
bootTimingsTraceLog.traceBegin("PreloadResources");
|
||||||
preloadResources();
|
Resources.preloadResources();
|
||||||
bootTimingsTraceLog.traceEnd(); // PreloadResources
|
bootTimingsTraceLog.traceEnd(); // PreloadResources
|
||||||
Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadAppProcessHALs");
|
Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadAppProcessHALs");
|
||||||
nativePreloadAppProcessHALs();
|
nativePreloadAppProcessHALs();
|
||||||
@@ -413,87 +401,6 @@ public class ZygoteInit {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Load in commonly used resources, so they can be shared across processes.
|
|
||||||
*
|
|
||||||
* These tend to be a few Kbytes, but are frequently in the 20-40K range, and occasionally even
|
|
||||||
* larger.
|
|
||||||
*/
|
|
||||||
private static void preloadResources() {
|
|
||||||
try {
|
|
||||||
mResources = Resources.getSystem();
|
|
||||||
mResources.startPreloading();
|
|
||||||
if (PRELOAD_RESOURCES) {
|
|
||||||
Log.i(TAG, "Preloading resources...");
|
|
||||||
|
|
||||||
long startTime = SystemClock.uptimeMillis();
|
|
||||||
TypedArray ar = mResources.obtainTypedArray(
|
|
||||||
com.android.internal.R.array.preloaded_drawables);
|
|
||||||
int N = preloadDrawables(ar);
|
|
||||||
ar.recycle();
|
|
||||||
Log.i(TAG, "...preloaded " + N + " resources in "
|
|
||||||
+ (SystemClock.uptimeMillis() - startTime) + "ms.");
|
|
||||||
|
|
||||||
startTime = SystemClock.uptimeMillis();
|
|
||||||
ar = mResources.obtainTypedArray(
|
|
||||||
com.android.internal.R.array.preloaded_color_state_lists);
|
|
||||||
N = preloadColorStateLists(ar);
|
|
||||||
ar.recycle();
|
|
||||||
Log.i(TAG, "...preloaded " + N + " resources in "
|
|
||||||
+ (SystemClock.uptimeMillis() - startTime) + "ms.");
|
|
||||||
|
|
||||||
if (mResources.getBoolean(
|
|
||||||
com.android.internal.R.bool.config_freeformWindowManagement)) {
|
|
||||||
startTime = SystemClock.uptimeMillis();
|
|
||||||
ar = mResources.obtainTypedArray(
|
|
||||||
com.android.internal.R.array.preloaded_freeform_multi_window_drawables);
|
|
||||||
N = preloadDrawables(ar);
|
|
||||||
ar.recycle();
|
|
||||||
Log.i(TAG, "...preloaded " + N + " resource in "
|
|
||||||
+ (SystemClock.uptimeMillis() - startTime) + "ms.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mResources.finishPreloading();
|
|
||||||
} catch (RuntimeException e) {
|
|
||||||
Log.w(TAG, "Failure preloading resources", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int preloadColorStateLists(TypedArray ar) {
|
|
||||||
int N = ar.length();
|
|
||||||
for (int i = 0; i < N; i++) {
|
|
||||||
int id = ar.getResourceId(i, 0);
|
|
||||||
|
|
||||||
if (id != 0) {
|
|
||||||
if (mResources.getColorStateList(id, null) == null) {
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"Unable to find preloaded color resource #0x"
|
|
||||||
+ Integer.toHexString(id)
|
|
||||||
+ " (" + ar.getString(i) + ")");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return N;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private static int preloadDrawables(TypedArray ar) {
|
|
||||||
int N = ar.length();
|
|
||||||
for (int i = 0; i < N; i++) {
|
|
||||||
int id = ar.getResourceId(i, 0);
|
|
||||||
|
|
||||||
if (id != 0) {
|
|
||||||
if (mResources.getDrawable(id, null) == null) {
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"Unable to find preloaded drawable resource #0x"
|
|
||||||
+ Integer.toHexString(id)
|
|
||||||
+ " (" + ar.getString(i) + ")");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return N;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Runs several special GCs to try to clean up a few generations of softly- and final-reachable
|
* Runs several special GCs to try to clean up a few generations of softly- and final-reachable
|
||||||
* objects, along with any other garbage. This is only useful just before a fork().
|
* objects, along with any other garbage. This is only useful just before a fork().
|
||||||
|
|||||||
Reference in New Issue
Block a user