From 3f8b9fe50b739a6dd9b0aa35e6b1779c95fd6045 Mon Sep 17 00:00:00 2001 From: Brett Chabot Date: Fri, 21 May 2021 08:41:58 -0700 Subject: [PATCH 1/3] Backport 'Add ability to disable GL draws'. This feature is intended for use in headless test environments, where disabling drawing has minimal compatibility impact and can save significant resource usage when running UI tests. This feature is controlled via a new system property 'debug.hwui.drawing_enabled', and a HardwareRenderer API that can override the property value on a per-process basis. Bug: 201691826 Test: boot emulator Merged-In: I93c21e680382e03342f235dbf58bd7a5c8a6f767 Change-Id: I391c841e3a0cdcfcc6c7910a316a4dd5e970547d --- .../android/graphics/HardwareRenderer.java | 52 +++++++++++++++++++ libs/hwui/Properties.cpp | 21 ++++++++ libs/hwui/Properties.h | 14 +++++ .../jni/android_graphics_HardwareRenderer.cpp | 11 ++++ libs/hwui/renderthread/CanvasContext.cpp | 5 +- libs/hwui/renderthread/CanvasContext.h | 10 +++- 6 files changed, 110 insertions(+), 3 deletions(-) diff --git a/graphics/java/android/graphics/HardwareRenderer.java b/graphics/java/android/graphics/HardwareRenderer.java index c3b1cd74d29b..b61ae1259cf5 100644 --- a/graphics/java/android/graphics/HardwareRenderer.java +++ b/graphics/java/android/graphics/HardwareRenderer.java @@ -22,6 +22,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.app.Activity; import android.app.ActivityManager; +import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.content.pm.ActivityInfo; import android.content.res.Configuration; @@ -1075,6 +1076,53 @@ public class HardwareRenderer { ProcessInitializer.sInstance.setContext(context); } + /** + * Returns true if HardwareRender will produce output. + * + * This value is global to the process and affects all uses of HardwareRenderer, + * including + * those created by the system such as those used by the View tree when using hardware + * accelerated rendering. + * + * Default is true in all production environments, but may be false in testing-focused + * emulators or if {@link #setDrawingEnabled(boolean)} is used. + * + * Backported from android T. + * + * @hide + */ + @UnsupportedAppUsage + public static boolean isDrawingEnabled() { + return nIsDrawingEnabled(); + } + + /** + * Toggles whether or not HardwareRenderer will produce drawing output globally in the current + * process. + * + * This applies to all HardwareRenderer instances, including those created by the platform such + * as those used by the system for hardware accelerated View rendering. + * + * The capability to disable drawing output is intended for test environments, primarily + * headless ones. By setting this to false, tests that launch activities or interact with Views + * can be quicker with less RAM usage by skipping the final step of View drawing. All View + * lifecycle events will occur as normal, only the final step of rendering on the GPU to the + * display will be skipped. + * + * This can be toggled on and off at will, so screenshot tests can also run in this same + * environment by toggling drawing back on and forcing a frame to be drawn such as by calling + * view#invalidate(). Once drawn and the screenshot captured, this can then be turned back off. + * + * Backported from android T. + * + * @hide + */ + // TODO: Add link to androidx's Screenshot library for help with this + @UnsupportedAppUsage + public static void setDrawingEnabled(boolean drawingEnabled) { + nSetDrawingEnabled(drawingEnabled); + } + private static final class DestroyContextRunnable implements Runnable { private final long mNativeInstance; @@ -1393,4 +1441,8 @@ public class HardwareRenderer { private static native void nInitDisplayInfo(int width, int height, float refreshRate, int wideColorDataspace, long appVsyncOffsetNanos, long presentationDeadlineNanos); + + private static native void nSetDrawingEnabled(boolean drawingEnabled); + + private static native boolean nIsDrawingEnabled(); } diff --git a/libs/hwui/Properties.cpp b/libs/hwui/Properties.cpp index b8fa55a18dac..18fab8ee5f92 100644 --- a/libs/hwui/Properties.cpp +++ b/libs/hwui/Properties.cpp @@ -88,6 +88,9 @@ bool Properties::enableWebViewOverlays = false; StretchEffectBehavior Properties::stretchEffectBehavior = StretchEffectBehavior::ShaderHWUI; +bool Properties::drawingEnabled = true; +OverrideDrawingEnabled Properties::overrideDrawingEnabled = OverrideDrawingEnabled::Default; + bool Properties::load() { bool prevDebugLayersUpdates = debugLayersUpdates; bool prevDebugOverdraw = debugOverdraw; @@ -141,6 +144,11 @@ bool Properties::load() { enableWebViewOverlays = base::GetBoolProperty(PROPERTY_WEBVIEW_OVERLAYS_ENABLED, false); + drawingEnabled = base::GetBoolProperty(PROPERTY_DRAWING_ENABLED, true); + if (!drawingEnabled) { + enableRTAnimations = false; + } + return (prevDebugLayersUpdates != debugLayersUpdates) || (prevDebugOverdraw != debugOverdraw); } @@ -210,5 +218,18 @@ void Properties::overrideRenderPipelineType(RenderPipelineType type, bool inUnit sRenderPipelineType = type; } +void Properties::setDrawingEnabled(bool newDrawingEnabled) { + overrideDrawingEnabled = + newDrawingEnabled ? OverrideDrawingEnabled::On : OverrideDrawingEnabled::Off; + enableRTAnimations = newDrawingEnabled; +} + +bool Properties::isDrawingEnabled() { + if (overrideDrawingEnabled == OverrideDrawingEnabled::Default) { + return drawingEnabled; + } + return overrideDrawingEnabled == OverrideDrawingEnabled::On; +} + } // namespace uirenderer } // namespace android diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h index 7df6e2c92247..73fccb67800b 100644 --- a/libs/hwui/Properties.h +++ b/libs/hwui/Properties.h @@ -187,6 +187,12 @@ enum DebugLevel { */ #define PROPERTY_WEBVIEW_OVERLAYS_ENABLED "debug.hwui.webview_overlays_enabled" +/** + * Property for globally GL drawing state. Can be overridden per process with + * setDrawingEnabled. + */ +#define PROPERTY_DRAWING_ENABLED "debug.hwui.drawing_enabled" + /////////////////////////////////////////////////////////////////////////////// // Misc /////////////////////////////////////////////////////////////////////////////// @@ -208,6 +214,8 @@ enum class StretchEffectBehavior { UniformScale // Uniform scale stretch everywhere }; +enum class OverrideDrawingEnabled { Default, On, Off }; + /** * Renderthread-only singleton which manages several static rendering properties. Most of these * are driven by system properties which are queried once at initialization, and again if init() @@ -301,6 +309,12 @@ public: stretchEffectBehavior = behavior; } + // Represents if GL drawing is enabled. Should only be false in headless testing environments + static bool drawingEnabled; + static OverrideDrawingEnabled overrideDrawingEnabled; + static bool isDrawingEnabled(); + static void setDrawingEnabled(bool enable); + private: static StretchEffectBehavior stretchEffectBehavior; static ProfileType sProfileType; diff --git a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp index 54367b8334cb..9e56584ed582 100644 --- a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp +++ b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp @@ -817,6 +817,14 @@ static void android_view_ThreadedRenderer_initDisplayInfo(JNIEnv*, jclass, jint DeviceInfo::setPresentationDeadlineNanos(presentationDeadlineNanos); } +static void android_view_ThreadedRenderer_setDrawingEnabled(JNIEnv*, jclass, jboolean enabled) { + Properties::setDrawingEnabled(enabled); +} + +static jboolean android_view_ThreadedRenderer_isDrawingEnabled(JNIEnv*, jclass) { + return Properties::isDrawingEnabled(); +} + // ---------------------------------------------------------------------------- // HardwareRendererObserver // ---------------------------------------------------------------------------- @@ -953,6 +961,9 @@ static const JNINativeMethod gMethods[] = { {"preload", "()V", (void*)android_view_ThreadedRenderer_preload}, {"isWebViewOverlaysEnabled", "()Z", (void*)android_view_ThreadedRenderer_isWebViewOverlaysEnabled}, + {"nSetDrawingEnabled", "(Z)V", (void*)android_view_ThreadedRenderer_setDrawingEnabled}, + {"nIsDrawingEnabled", "()Z", (void*)android_view_ThreadedRenderer_isDrawingEnabled}, + }; static JavaVM* mJvm = nullptr; diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp index 2f3a509831d1..bb0b1352c360 100644 --- a/libs/hwui/renderthread/CanvasContext.cpp +++ b/libs/hwui/renderthread/CanvasContext.cpp @@ -256,7 +256,7 @@ void CanvasContext::setStopped(bool stopped) { } void CanvasContext::allocateBuffers() { - if (mNativeSurface) { + if (mNativeSurface && Properties::isDrawingEnabled()) { ANativeWindow_tryAllocateBuffers(mNativeSurface->getNativeWindow()); } } @@ -480,7 +480,8 @@ nsecs_t CanvasContext::draw() { SkRect dirty; mDamageAccumulator.finish(&dirty); - if (dirty.isEmpty() && Properties::skipEmptyFrames && !surfaceRequiresRedraw()) { + if (!Properties::isDrawingEnabled() || + (dirty.isEmpty() && Properties::skipEmptyFrames && !surfaceRequiresRedraw())) { mCurrentFrameInfo->addFlag(FrameInfoFlags::SkippedFrame); if (auto grContext = getGrContext()) { // Submit to ensure that any texture uploads complete and Skia can diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h index 6dbfcc349d50..2fed4686f16e 100644 --- a/libs/hwui/renderthread/CanvasContext.h +++ b/libs/hwui/renderthread/CanvasContext.h @@ -90,9 +90,17 @@ public: * and false otherwise (e.g. cache limits have been exceeded). */ bool pinImages(std::vector& mutableImages) { + if (!Properties::isDrawingEnabled()) { + return true; + } return mRenderPipeline->pinImages(mutableImages); } - bool pinImages(LsaVector>& images) { return mRenderPipeline->pinImages(images); } + bool pinImages(LsaVector>& images) { + if (!Properties::isDrawingEnabled()) { + return true; + } + return mRenderPipeline->pinImages(images); + } /** * Unpin any image that had be previously pinned to the GPU cache From 44dfd78b29cf80186bfcfc7ad2517ddab4ad0695 Mon Sep 17 00:00:00 2001 From: Brett Chabot Date: Tue, 29 Jun 2021 17:49:15 -0700 Subject: [PATCH 2/3] Backport 'add config to disable snapshots'. Bug: 201691826 Test: m Merged-In: I83d9ab4a15a862ea220debdd8da8b3d5673da276 Merged-In: Ibdff22eda7be6c91e2872e5ac3ae8f2fe1e65b69 Change-Id: I4914876e4925284d55951d16e472654ee599c619 --- core/res/res/values/config.xml | 3 +++ core/res/res/values/symbols.xml | 5 ++++- .../com/android/server/wm/TaskSnapshotController.java | 10 +++++++++- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index aa05b13984ec..f7e7d0e84932 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -5049,4 +5049,7 @@ 32 + + + false diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 092be40c499e..9ba1d5f38599 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -4403,7 +4403,7 @@ - + @@ -4426,4 +4426,7 @@ + + + diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java index e74371036619..a518222c3bde 100644 --- a/services/core/java/com/android/server/wm/TaskSnapshotController.java +++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java @@ -118,6 +118,11 @@ class TaskSnapshotController { */ private final boolean mIsRunningOnWear; + /** + * Flag indicating if device configuration has disabled app snapshots. + */ + private final boolean mConfigDisableTaskSnapshots; + TaskSnapshotController(WindowManagerService service) { mService = service; mPersister = new TaskSnapshotPersister(mService, Environment::getDataSystemCeDirectory); @@ -131,6 +136,8 @@ class TaskSnapshotController { PackageManager.FEATURE_WATCH); mHighResTaskSnapshotScale = mService.mContext.getResources().getFloat( com.android.internal.R.dimen.config_highResTaskSnapshotScale); + mConfigDisableTaskSnapshots = mService.mContext.getResources().getBoolean( + com.android.internal.R.bool.config_disableTaskSnapshots); } void systemReady() { @@ -488,7 +495,8 @@ class TaskSnapshotController { } boolean shouldDisableSnapshots() { - return mIsRunningOnWear || mIsRunningOnTv || mIsRunningOnIoT; + return mIsRunningOnWear || mIsRunningOnTv || mIsRunningOnIoT + || mConfigDisableTaskSnapshots; } /** From ab73aec1e484af56867268315d06db9c9052b40f Mon Sep 17 00:00:00 2001 From: Brett Chabot Date: Fri, 16 Jul 2021 14:38:11 -0700 Subject: [PATCH 3/3] Lazy load Properties::isDrawingEnabled. Properties::isDrawingEnabled can unexpectedly return true even if the system property debug.hwui.drawing_enabled is false, if its called before RenderThread is created. This commit changes the underlying logic to lazy load the debug.hwui.drawing_enabled prop value. Bug: 201691826 Test: m Change-Id: I599426c8734d418f073fd0456c2b1149fb69d80c --- libs/hwui/Properties.cpp | 20 +++++++++----------- libs/hwui/Properties.h | 7 +++---- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/libs/hwui/Properties.cpp b/libs/hwui/Properties.cpp index 18fab8ee5f92..c804418e8380 100644 --- a/libs/hwui/Properties.cpp +++ b/libs/hwui/Properties.cpp @@ -88,8 +88,7 @@ bool Properties::enableWebViewOverlays = false; StretchEffectBehavior Properties::stretchEffectBehavior = StretchEffectBehavior::ShaderHWUI; -bool Properties::drawingEnabled = true; -OverrideDrawingEnabled Properties::overrideDrawingEnabled = OverrideDrawingEnabled::Default; +DrawingEnabled Properties::drawingEnabled = DrawingEnabled::NotInitialized; bool Properties::load() { bool prevDebugLayersUpdates = debugLayersUpdates; @@ -144,10 +143,8 @@ bool Properties::load() { enableWebViewOverlays = base::GetBoolProperty(PROPERTY_WEBVIEW_OVERLAYS_ENABLED, false); - drawingEnabled = base::GetBoolProperty(PROPERTY_DRAWING_ENABLED, true); - if (!drawingEnabled) { - enableRTAnimations = false; - } + // call isDrawingEnabled to force loading of the property + isDrawingEnabled(); return (prevDebugLayersUpdates != debugLayersUpdates) || (prevDebugOverdraw != debugOverdraw); } @@ -219,16 +216,17 @@ void Properties::overrideRenderPipelineType(RenderPipelineType type, bool inUnit } void Properties::setDrawingEnabled(bool newDrawingEnabled) { - overrideDrawingEnabled = - newDrawingEnabled ? OverrideDrawingEnabled::On : OverrideDrawingEnabled::Off; + drawingEnabled = newDrawingEnabled ? DrawingEnabled::On : DrawingEnabled::Off; enableRTAnimations = newDrawingEnabled; } bool Properties::isDrawingEnabled() { - if (overrideDrawingEnabled == OverrideDrawingEnabled::Default) { - return drawingEnabled; + if (drawingEnabled == DrawingEnabled::NotInitialized) { + bool drawingEnabledProp = base::GetBoolProperty(PROPERTY_DRAWING_ENABLED, true); + drawingEnabled = drawingEnabledProp ? DrawingEnabled::On : DrawingEnabled::Off; + enableRTAnimations = drawingEnabledProp; } - return overrideDrawingEnabled == OverrideDrawingEnabled::On; + return drawingEnabled == DrawingEnabled::On; } } // namespace uirenderer diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h index 73fccb67800b..7f9782bf8d20 100644 --- a/libs/hwui/Properties.h +++ b/libs/hwui/Properties.h @@ -214,7 +214,7 @@ enum class StretchEffectBehavior { UniformScale // Uniform scale stretch everywhere }; -enum class OverrideDrawingEnabled { Default, On, Off }; +enum class DrawingEnabled { NotInitialized, On, Off }; /** * Renderthread-only singleton which manages several static rendering properties. Most of these @@ -309,9 +309,8 @@ public: stretchEffectBehavior = behavior; } - // Represents if GL drawing is enabled. Should only be false in headless testing environments - static bool drawingEnabled; - static OverrideDrawingEnabled overrideDrawingEnabled; + // Represents if drawing is enabled. Should only be Off in headless testing environments + static DrawingEnabled drawingEnabled; static bool isDrawingEnabled(); static void setDrawingEnabled(bool enable);