summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/view/WindowManagerGlobal.java6
-rw-r--r--graphics/java/android/graphics/HardwareRenderer.java42
-rw-r--r--libs/hwui/MemoryPolicy.h6
-rw-r--r--libs/hwui/jni/android_graphics_HardwareRenderer.cpp5
-rw-r--r--libs/hwui/renderthread/CacheManager.cpp19
-rw-r--r--libs/hwui/renderthread/CacheManager.h1
-rw-r--r--libs/hwui/renderthread/RenderProxy.cpp9
-rw-r--r--libs/hwui/renderthread/RenderProxy.h1
-rw-r--r--libs/hwui/renderthread/RenderThread.cpp5
-rw-r--r--libs/hwui/renderthread/RenderThread.h1
-rw-r--r--packages/SystemUI/src/com/android/systemui/flags/Flags.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ResourceTrimmer.kt34
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/utils/GlobalWindowManager.kt6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/ResourceTrimmerTest.kt36
15 files changed, 171 insertions, 8 deletions
diff --git a/core/java/android/view/WindowManagerGlobal.java b/core/java/android/view/WindowManagerGlobal.java
index 02cd0372ea88..99a4f6b41ef3 100644
--- a/core/java/android/view/WindowManagerGlobal.java
+++ b/core/java/android/view/WindowManagerGlobal.java
@@ -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);
diff --git a/graphics/java/android/graphics/HardwareRenderer.java b/graphics/java/android/graphics/HardwareRenderer.java
index 9ed3d9c3c94b..9cde1878d9d8 100644
--- a/graphics/java/android/graphics/HardwareRenderer.java
+++ b/graphics/java/android/graphics/HardwareRenderer.java
@@ -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);
diff --git a/libs/hwui/MemoryPolicy.h b/libs/hwui/MemoryPolicy.h
index 139cdde5c0d2..347daf34f52a 100644
--- a/libs/hwui/MemoryPolicy.h
+++ b/libs/hwui/MemoryPolicy.h
@@ -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
diff --git a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
index 6a7411f5d859..d04de37f6961 100644
--- a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
+++ b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
@@ -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;
diff --git a/libs/hwui/renderthread/CacheManager.cpp b/libs/hwui/renderthread/CacheManager.cpp
index c00a2707e0a2..babce88b8e1e 100644
--- a/libs/hwui/renderthread/CacheManager.cpp
+++ b/libs/hwui/renderthread/CacheManager.cpp
@@ -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;
diff --git a/libs/hwui/renderthread/CacheManager.h b/libs/hwui/renderthread/CacheManager.h
index d21ac9badc43..5e43ac209696 100644
--- a/libs/hwui/renderthread/CacheManager.h
+++ b/libs/hwui/renderthread/CacheManager.h
@@ -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);
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 31b4b203c670..224c878bf43d 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -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();
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index 82072a6e2499..47c1b0cd28e5 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -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);
diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp
index 9ba67a2110c1..eb28c080c056 100644
--- a/libs/hwui/renderthread/RenderThread.cpp
+++ b/libs/hwui/renderthread/RenderThread.cpp
@@ -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 */
diff --git a/libs/hwui/renderthread/RenderThread.h b/libs/hwui/renderthread/RenderThread.h
index c77cd4134d1e..79e57de9d66f 100644
--- a/libs/hwui/renderthread/RenderThread.h
+++ b/libs/hwui/renderthread/RenderThread.h
@@ -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
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
index c8485dcdef41..cf517eb4f0e1 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
@@ -673,6 +673,10 @@ object Flags {
val TRIM_RESOURCES_WITH_BACKGROUND_TRIM_AT_LOCK =
unreleasedFlag(2401, "trim_resources_with_background_trim_on_lock")
+ // TODO:(b/283203305): Tracking bug
+ @JvmField
+ val TRIM_FONT_CACHES_AT_UNLOCK = releasedFlag(2402, "trim_font_caches_on_unlock")
+
// 2700 - unfold transitions
// TODO(b/265764985): Tracking Bug
@Keep
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ResourceTrimmer.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ResourceTrimmer.kt
index 8386a05b6647..d8affa4d6c21 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ResourceTrimmer.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ResourceTrimmer.kt
@@ -18,6 +18,7 @@ package com.android.systemui.keyguard
import android.annotation.WorkerThread
import android.content.ComponentCallbacks2
+import android.graphics.HardwareRenderer
import android.os.Trace
import android.util.Log
import com.android.systemui.CoreStartable
@@ -27,12 +28,13 @@ import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
+import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
+import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.keyguard.shared.model.WakefulnessState
import com.android.systemui.utils.GlobalWindowManager
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.map
@@ -50,6 +52,7 @@ class ResourceTrimmer
@Inject
constructor(
private val keyguardInteractor: KeyguardInteractor,
+ private val keyguardTransitionInteractor: KeyguardTransitionInteractor,
private val globalWindowManager: GlobalWindowManager,
@Application private val applicationScope: CoroutineScope,
@Background private val bgDispatcher: CoroutineDispatcher,
@@ -58,7 +61,10 @@ constructor(
override fun start() {
Log.d(LOG_TAG, "Resource trimmer registered.")
- if (!featureFlags.isEnabled(Flags.TRIM_RESOURCES_WITH_BACKGROUND_TRIM_AT_LOCK)) {
+ if (
+ !(featureFlags.isEnabled(Flags.TRIM_RESOURCES_WITH_BACKGROUND_TRIM_AT_LOCK) ||
+ featureFlags.isEnabled(Flags.TRIM_FONT_CACHES_AT_UNLOCK))
+ ) {
return
}
@@ -78,6 +84,30 @@ constructor(
.distinctUntilChanged()
.collect { onWakefulnessUpdated(it.first, it.second, it.third) }
}
+
+ applicationScope.launch(bgDispatcher) {
+ // We drop 1 to avoid triggering on initial collect().
+ keyguardTransitionInteractor.anyStateToGoneTransition.collect { transition ->
+ if (transition.transitionState == TransitionState.FINISHED) {
+ onKeyguardGone()
+ }
+ }
+ }
+ }
+
+ @WorkerThread
+ private fun onKeyguardGone() {
+ if (!featureFlags.isEnabled(Flags.TRIM_FONT_CACHES_AT_UNLOCK)) {
+ return
+ }
+
+ if (DEBUG) {
+ Log.d(LOG_TAG, "Trimming font caches since keyguard went away.")
+ }
+ // We want to clear temporary caches we've created while rendering and animating
+ // lockscreen elements, especially clocks.
+ globalWindowManager.trimMemory(ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN)
+ globalWindowManager.trimCaches(HardwareRenderer.CACHE_TRIM_FONT)
}
@WorkerThread
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index df68e7eb037b..0414a14205d7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -23,7 +23,6 @@ import static com.android.systemui.plugins.ActivityStarter.OnDismissAction;
import static com.android.systemui.statusbar.phone.BiometricUnlockController.MODE_WAKE_AND_UNLOCK;
import static com.android.systemui.statusbar.phone.BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING;
-import android.content.ComponentCallbacks2;
import android.content.Context;
import android.content.res.ColorStateList;
import android.hardware.biometrics.BiometricSourceType;
@@ -36,7 +35,6 @@ import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewRootImpl;
-import android.view.WindowManagerGlobal;
import android.window.BackEvent;
import android.window.OnBackAnimationCallback;
import android.window.OnBackInvokedDispatcher;
@@ -985,8 +983,6 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
mShadeViewController.resetViewGroupFade();
mCentralSurfaces.finishKeyguardFadingAway();
mBiometricUnlockController.finishKeyguardFadingAway();
- WindowManagerGlobal.getInstance().trimMemory(
- ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN);
}
private void wakeAndUnlockDejank() {
diff --git a/packages/SystemUI/src/com/android/systemui/utils/GlobalWindowManager.kt b/packages/SystemUI/src/com/android/systemui/utils/GlobalWindowManager.kt
index 038fddc1f7a9..4111850b53ed 100644
--- a/packages/SystemUI/src/com/android/systemui/utils/GlobalWindowManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/utils/GlobalWindowManager.kt
@@ -1,5 +1,6 @@
package com.android.systemui.utils
+import android.graphics.HardwareRenderer.CacheTrimLevel
import android.view.WindowManagerGlobal
import javax.inject.Inject
@@ -13,4 +14,9 @@ class GlobalWindowManager @Inject constructor() {
fun trimMemory(level: Int) {
WindowManagerGlobal.getInstance().trimMemory(level)
}
+
+ /** Sends a trim caches command to [WindowManagerGlobal]. */
+ fun trimCaches(@CacheTrimLevel level: Int) {
+ WindowManagerGlobal.getInstance().trimCaches(level)
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ResourceTrimmerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ResourceTrimmerTest.kt
index 367d206814cb..548d26f2aaed 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ResourceTrimmerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ResourceTrimmerTest.kt
@@ -1,6 +1,7 @@
package com.android.systemui.keyguard
import android.content.ComponentCallbacks2
+import android.graphics.HardwareRenderer
import android.testing.AndroidTestingRunner
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
@@ -9,7 +10,11 @@ import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.data.repository.FakeCommandQueue
import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
+import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
+import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
+import com.android.systemui.keyguard.shared.model.KeyguardState
+import com.android.systemui.keyguard.shared.model.TransitionStep
import com.android.systemui.keyguard.shared.model.WakeSleepReason
import com.android.systemui.keyguard.shared.model.WakefulnessModel
import com.android.systemui.keyguard.shared.model.WakefulnessState
@@ -25,6 +30,7 @@ import org.junit.runner.RunWith
import org.mockito.Mock
import org.mockito.Mockito.times
import org.mockito.Mockito.verify
+import org.mockito.Mockito.verifyNoMoreInteractions
import org.mockito.Mockito.verifyZeroInteractions
import org.mockito.MockitoAnnotations
@@ -37,6 +43,7 @@ class ResourceTrimmerTest : SysuiTestCase() {
private val testScope = TestScope(testDispatcher)
private val keyguardRepository = FakeKeyguardRepository()
private val featureFlags = FakeFeatureFlags()
+ private val keyguardTransitionRepository = FakeKeyguardTransitionRepository()
@Mock private lateinit var globalWindowManager: GlobalWindowManager
private lateinit var resourceTrimmer: ResourceTrimmer
@@ -45,13 +52,15 @@ class ResourceTrimmerTest : SysuiTestCase() {
fun setUp() {
MockitoAnnotations.initMocks(this)
featureFlags.set(Flags.TRIM_RESOURCES_WITH_BACKGROUND_TRIM_AT_LOCK, true)
+ featureFlags.set(Flags.TRIM_FONT_CACHES_AT_UNLOCK, true)
featureFlags.set(Flags.FACE_AUTH_REFACTOR, false)
keyguardRepository.setWakefulnessModel(
WakefulnessModel(WakefulnessState.AWAKE, WakeSleepReason.OTHER, WakeSleepReason.OTHER)
)
keyguardRepository.setDozeAmount(0f)
+ keyguardRepository.setKeyguardGoingAway(false)
- val interactor =
+ val keyguardInteractor =
KeyguardInteractor(
keyguardRepository,
FakeCommandQueue(),
@@ -60,7 +69,8 @@ class ResourceTrimmerTest : SysuiTestCase() {
)
resourceTrimmer =
ResourceTrimmer(
- interactor,
+ keyguardInteractor,
+ KeyguardTransitionInteractor(keyguardTransitionRepository),
globalWindowManager,
testScope.backgroundScope,
testDispatcher,
@@ -191,4 +201,26 @@ class ResourceTrimmerTest : SysuiTestCase() {
verifyZeroInteractions(globalWindowManager)
}
}
+
+ @Test
+ fun keyguardTransitionsToGone_trimsFontCache() =
+ testScope.runTest {
+ keyguardTransitionRepository.sendTransitionStep(
+ TransitionStep(KeyguardState.LOCKSCREEN, KeyguardState.GONE)
+ )
+ verify(globalWindowManager, times(1))
+ .trimMemory(ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN)
+ verify(globalWindowManager, times(1)).trimCaches(HardwareRenderer.CACHE_TRIM_FONT)
+ verifyNoMoreInteractions(globalWindowManager)
+ }
+
+ @Test
+ fun keyguardTransitionsToGone_flagDisabled_doesNotTrimFontCache() =
+ testScope.runTest {
+ featureFlags.set(Flags.TRIM_FONT_CACHES_AT_UNLOCK, false)
+ keyguardTransitionRepository.sendTransitionStep(
+ TransitionStep(KeyguardState.LOCKSCREEN, KeyguardState.GONE)
+ )
+ verifyNoMoreInteractions(globalWindowManager)
+ }
}