Allow triming of font caches through WindowManager
This allows triming of Skia font caches when an app created a lot of
transient font allocations and it knows that it won't need it anymore.
This is primarily meant for persistent processes like SystemUI to avoid
font caches taking up memory after they're not needed anymore.
Bug: 275486055
Test: Tested as part of a follow-up commit, ran
LockscreenWithSwipeMicrobenchmark which showed a noticable
reduction of RSS+anon memory use after unlock.
Change-Id: I6d80003d8baab35cb2ca858d4e4d4696b32f3adf
This commit is contained in:
@@ -23,6 +23,7 @@ import android.compat.annotation.UnsupportedAppUsage;
|
||||
import android.content.Context;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.HardwareRenderer;
|
||||
import android.os.Build;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
@@ -550,6 +551,11 @@ public final class WindowManagerGlobal {
|
||||
ThreadedRenderer.trimMemory(level);
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public void trimCaches(@HardwareRenderer.CacheTrimLevel int level) {
|
||||
ThreadedRenderer.trimCaches(level);
|
||||
}
|
||||
|
||||
public void dumpGfxInfo(FileDescriptor fd, String[] args) {
|
||||
FileOutputStream fout = new FileOutputStream(fd);
|
||||
PrintWriter pw = new FastPrintWriter(fout);
|
||||
|
||||
@@ -144,6 +144,32 @@ public class HardwareRenderer {
|
||||
public @interface DumpFlags {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Trims all Skia caches.
|
||||
* @hide
|
||||
*/
|
||||
public static final int CACHE_TRIM_ALL = 0;
|
||||
/**
|
||||
* Trims Skia font caches.
|
||||
* @hide
|
||||
*/
|
||||
public static final int CACHE_TRIM_FONT = 1;
|
||||
/**
|
||||
* Trims Skia resource caches.
|
||||
* @hide
|
||||
*/
|
||||
public static final int CACHE_TRIM_RESOURCES = 2;
|
||||
|
||||
/** @hide */
|
||||
@IntDef(prefix = {"CACHE_TRIM_"}, value = {
|
||||
CACHE_TRIM_ALL,
|
||||
CACHE_TRIM_FONT,
|
||||
CACHE_TRIM_RESOURCES
|
||||
})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface CacheTrimLevel {}
|
||||
|
||||
/**
|
||||
* Name of the file that holds the shaders cache.
|
||||
*/
|
||||
@@ -1131,6 +1157,20 @@ public class HardwareRenderer {
|
||||
nTrimMemory(level);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke this when all font caches should be flushed. This can cause jank on next render
|
||||
* commands so use it only after expensive font allocation operations which would
|
||||
* allocate large amount of temporary memory.
|
||||
*
|
||||
* @param level Hint about which caches to trim. See {@link #CACHE_TRIM_ALL},
|
||||
* {@link #CACHE_TRIM_FONT}, {@link #CACHE_TRIM_RESOURCES}
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static void trimCaches(@CacheTrimLevel int level) {
|
||||
nTrimCaches(level);
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public static void overrideProperty(@NonNull String name, @NonNull String value) {
|
||||
if (name == null || value == null) {
|
||||
@@ -1497,6 +1537,8 @@ public class HardwareRenderer {
|
||||
|
||||
private static native void nTrimMemory(int level);
|
||||
|
||||
private static native void nTrimCaches(int level);
|
||||
|
||||
private static native void nOverrideProperty(String name, String value);
|
||||
|
||||
private static native void nFence(long nativeProxy);
|
||||
|
||||
@@ -31,6 +31,12 @@ enum class TrimLevel {
|
||||
RUNNING_MODERATE = 5,
|
||||
};
|
||||
|
||||
enum class CacheTrimLevel {
|
||||
ALL_CACHES = 0,
|
||||
FONT_CACHE = 1,
|
||||
RESOURCE_CACHE = 2,
|
||||
};
|
||||
|
||||
struct MemoryPolicy {
|
||||
// The initial scale factor applied to the display resolution. The default is 1, but
|
||||
// lower values may be used to start with a smaller initial cache size. The cache will
|
||||
|
||||
@@ -362,6 +362,10 @@ static void android_view_ThreadedRenderer_trimMemory(JNIEnv* env, jobject clazz,
|
||||
RenderProxy::trimMemory(level);
|
||||
}
|
||||
|
||||
static void android_view_ThreadedRenderer_trimCaches(JNIEnv* env, jobject clazz, jint level) {
|
||||
RenderProxy::trimCaches(level);
|
||||
}
|
||||
|
||||
static void android_view_ThreadedRenderer_overrideProperty(JNIEnv* env, jobject clazz,
|
||||
jstring name, jstring value) {
|
||||
const char* nameCharArray = env->GetStringUTFChars(name, NULL);
|
||||
@@ -1018,6 +1022,7 @@ static const JNINativeMethod gMethods[] = {
|
||||
(void*)android_view_ThreadedRenderer_notifyCallbackPending},
|
||||
{"nNotifyExpensiveFrame", "(J)V",
|
||||
(void*)android_view_ThreadedRenderer_notifyExpensiveFrame},
|
||||
{"nTrimCaches", "(I)V", (void*)android_view_ThreadedRenderer_trimCaches},
|
||||
};
|
||||
|
||||
static JavaVM* mJvm = nullptr;
|
||||
|
||||
@@ -139,6 +139,25 @@ void CacheManager::trimMemory(TrimLevel mode) {
|
||||
}
|
||||
}
|
||||
|
||||
void CacheManager::trimCaches(CacheTrimLevel mode) {
|
||||
switch (mode) {
|
||||
case CacheTrimLevel::FONT_CACHE:
|
||||
SkGraphics::PurgeFontCache();
|
||||
break;
|
||||
case CacheTrimLevel::RESOURCE_CACHE:
|
||||
SkGraphics::PurgeResourceCache();
|
||||
break;
|
||||
case CacheTrimLevel::ALL_CACHES:
|
||||
SkGraphics::PurgeAllCaches();
|
||||
if (mGrContext) {
|
||||
mGrContext->purgeUnlockedResources(false);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void CacheManager::trimStaleResources() {
|
||||
if (!mGrContext) {
|
||||
return;
|
||||
|
||||
@@ -48,6 +48,7 @@ public:
|
||||
void configureContext(GrContextOptions* context, const void* identity, ssize_t size);
|
||||
#endif
|
||||
void trimMemory(TrimLevel mode);
|
||||
void trimCaches(CacheTrimLevel mode);
|
||||
void trimStaleResources();
|
||||
void dumpMemoryUsage(String8& log, const RenderState* renderState = nullptr);
|
||||
void getMemoryUsage(size_t* cpuUsage, size_t* gpuUsage);
|
||||
|
||||
@@ -231,6 +231,15 @@ void RenderProxy::trimMemory(int level) {
|
||||
}
|
||||
}
|
||||
|
||||
void RenderProxy::trimCaches(int level) {
|
||||
// Avoid creating a RenderThread to do a trimMemory.
|
||||
if (RenderThread::hasInstance()) {
|
||||
RenderThread& thread = RenderThread::getInstance();
|
||||
const auto trimLevel = static_cast<CacheTrimLevel>(level);
|
||||
thread.queue().post([&thread, trimLevel]() { thread.trimCaches(trimLevel); });
|
||||
}
|
||||
}
|
||||
|
||||
void RenderProxy::purgeCaches() {
|
||||
if (RenderThread::hasInstance()) {
|
||||
RenderThread& thread = RenderThread::getInstance();
|
||||
|
||||
@@ -105,6 +105,7 @@ public:
|
||||
|
||||
void destroyHardwareResources();
|
||||
static void trimMemory(int level);
|
||||
static void trimCaches(int level);
|
||||
static void purgeCaches();
|
||||
static void overrideProperty(const char* name, const char* value);
|
||||
|
||||
|
||||
@@ -521,6 +521,11 @@ void RenderThread::trimMemory(TrimLevel level) {
|
||||
cacheManager().trimMemory(level);
|
||||
}
|
||||
|
||||
void RenderThread::trimCaches(CacheTrimLevel level) {
|
||||
ATRACE_CALL();
|
||||
cacheManager().trimCaches(level);
|
||||
}
|
||||
|
||||
} /* namespace renderthread */
|
||||
} /* namespace uirenderer */
|
||||
} /* namespace android */
|
||||
|
||||
@@ -174,6 +174,7 @@ public:
|
||||
}
|
||||
|
||||
void trimMemory(TrimLevel level);
|
||||
void trimCaches(CacheTrimLevel level);
|
||||
|
||||
/**
|
||||
* isCurrent provides a way to query, if the caller is running on
|
||||
|
||||
Reference in New Issue
Block a user