From 74737915b1404de72e3dd208ac03420612adec08 Mon Sep 17 00:00:00 2001 From: Cody Northrop Date: Wed, 16 Nov 2022 23:31:31 -0700 Subject: [PATCH] GraphicsEnvironment: Determine storage limit for EGL blob cache The application has a quota provided by the platform informing it how much space it can use for temp storage. The value can change over time based platform resources. Use this value to dictate how much space drivers can use to store persistent entries in EGL blob cache. For games, allow 50% of the storage to be used. For non-games, limit to 25%. This CL works in conjunction with a native change to use multiple files for EGL blob cache. (ag/20505145) The limits for monolithic cache are unchanged. Test: ANGLE trace tests, various games and apps Bug: b/246966894 Change-Id: I38ee45a27c29f913f5de9c0d76722da0d1dcade3 --- core/java/android/os/GraphicsEnvironment.java | 48 +++++++++++++++++++ core/jni/android_os_GraphicsEnvironment.cpp | 5 ++ 2 files changed, 53 insertions(+) diff --git a/core/java/android/os/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java index fb8f84acc8f39..a83dea34e5b4a 100644 --- a/core/java/android/os/GraphicsEnvironment.java +++ b/core/java/android/os/GraphicsEnvironment.java @@ -27,6 +27,7 @@ import android.content.pm.IPackageManager; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; +import android.os.storage.StorageManager; import android.provider.Settings; import android.text.TextUtils; import android.util.Log; @@ -210,6 +211,25 @@ public class GraphicsEnvironment { mGameManager.notifyGraphicsEnvironmentSetup(); } Trace.traceEnd(Trace.TRACE_TAG_GRAPHICS); + + Trace.traceBegin(Trace.TRACE_TAG_GRAPHICS, "setBlobCacheQuotaBytes"); + new Thread(() -> { + try { + // Perform this lookup on a thread since getCacheQuotaBytes can be slow + // and we don't need the answer right away. The result is consumed in + // checkMultifileCacheSize in egl_cache_multifile.cpp. If the value isn't + // ready, a default is used. The results will likely be ready by the time + // an app starts using the blobcache. + final StorageManager sm = context.getSystemService(StorageManager.class); + final long cacheBytes = sm.getCacheQuotaBytes(appInfoWithMetaData.storageUuid); + final long scaledCacheBytes = + getScaledCacheQuotaBytes(packageName, cacheBytes, appInfoWithMetaData); + setBlobCacheQuotaBytes(scaledCacheBytes); + } catch (IOException e) { + Log.w(TAG, "Failed to look up getCacheQuotaBytes for package: " + packageName); + } + }).start(); + Trace.traceEnd(Trace.TRACE_TAG_GRAPHICS); } /** @@ -448,6 +468,31 @@ public class GraphicsEnvironment { return ai; } + private static long getScaledCacheQuotaBytes(String packageName, long cacheBytes, + ApplicationInfo appInfoWithMetaData) { + if (cacheBytes <= 0) { + Log.v(TAG, "cacheBytes are zero for " + packageName); + return 0; + } + // Limit the amount of temp storage available to OpenGL drivers to a percentage + // based on the app type. Games will typically need more space than applications, + // so give them 50%, 25% for everything else. + long scaledCacheBytes = 0; + if (((appInfoWithMetaData.flags & ApplicationInfo.FLAG_IS_GAME) != 0) + || appInfoWithMetaData.category == ApplicationInfo.CATEGORY_GAME) { + scaledCacheBytes = cacheBytes / 2; + Log.v(TAG, "Treating " + packageName + + " as a game, setting shader cache quota to 50% (" + + scaledCacheBytes + ")"); + } else { + scaledCacheBytes = cacheBytes / 4; + Log.v(TAG, "Treating " + packageName + + " as an application, setting shader cache quota to 25% (" + + scaledCacheBytes + ")"); + } + return scaledCacheBytes; + } + /** * Return the appropriate "default" driver, unless overridden by isAngleEnabledByGameMode(). */ @@ -996,4 +1041,7 @@ public class GraphicsEnvironment { * Then the app process is allowed to send stats to GpuStats module. */ public static native void hintActivityLaunch(); + + private static native void setBlobCacheQuotaBytes(long cacheBytes); + } diff --git a/core/jni/android_os_GraphicsEnvironment.cpp b/core/jni/android_os_GraphicsEnvironment.cpp index 78e2d3164993d..f0ae488efa689 100644 --- a/core/jni/android_os_GraphicsEnvironment.cpp +++ b/core/jni/android_os_GraphicsEnvironment.cpp @@ -122,6 +122,10 @@ void hintActivityLaunch_native(JNIEnv* env, jobject clazz) { android::GraphicsEnv::getInstance().hintActivityLaunch(); } +void setBlobCacheQuotaBytes_native(JNIEnv* env, jobject clazz, jlong cacheBytes) { + android::GraphicsEnv::getInstance().setBlobCacheQuotaBytes(cacheBytes); +} + const JNINativeMethod g_methods[] = { {"isDebuggable", "()Z", reinterpret_cast(isDebuggable_native)}, {"setDriverPathAndSphalLibraries", "(Ljava/lang/String;Ljava/lang/String;)V", @@ -143,6 +147,7 @@ const JNINativeMethod g_methods[] = { {"setDebugLayersGLES", "(Ljava/lang/String;)V", reinterpret_cast(setDebugLayersGLES_native)}, {"hintActivityLaunch", "()V", reinterpret_cast(hintActivityLaunch_native)}, + {"setBlobCacheQuotaBytes", "(J)V", reinterpret_cast(setBlobCacheQuotaBytes_native)}, }; const char* const kGraphicsEnvironmentName = "android/os/GraphicsEnvironment";