From da3559683482a61d93b06bed6f46349f6f01dc63 Mon Sep 17 00:00:00 2001 From: John Reck Date: Thu, 24 Jun 2021 17:09:32 -0400 Subject: [PATCH] Delete RenderProxy off of the cleaner thread Speculation for the cause of an ANR. HardwareRenderer's cleaner can block on RenderThread, which in turn blocks ART's cleaner thread. This can potentially cause other blockages, but it's also poor behavior to have such a long-running Cleaner anyway. Avoid this by putting cleanup to CommonPool. Bug: 191514384 Test: make, CtsUiRenderingTestCases still passes Change-Id: I8190f7862528c3ac39ce636f6fca229322480968 --- libs/hwui/jni/android_graphics_HardwareRenderer.cpp | 2 +- libs/hwui/renderthread/RenderProxy.cpp | 12 ++++++++++++ libs/hwui/renderthread/RenderProxy.h | 8 ++++++-- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp index 9ff2f461d40d7..2c4402084160e 100644 --- a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp +++ b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp @@ -247,7 +247,7 @@ static jlong android_view_ThreadedRenderer_createProxy(JNIEnv* env, jobject claz static void android_view_ThreadedRenderer_deleteProxy(JNIEnv* env, jobject clazz, jlong proxyPtr) { RenderProxy* proxy = reinterpret_cast(proxyPtr); - delete proxy; + RenderProxy::asyncDelete(proxy); } static jboolean android_view_ThreadedRenderer_loadSystemProperties(JNIEnv* env, jobject clazz, diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp index c47050c31e9aa..8291fa7e4bab9 100644 --- a/libs/hwui/renderthread/RenderProxy.cpp +++ b/libs/hwui/renderthread/RenderProxy.cpp @@ -26,6 +26,7 @@ #include "renderthread/CanvasContext.h" #include "renderthread/RenderTask.h" #include "renderthread/RenderThread.h" +#include "thread/CommonPool.h" #include "utils/Macros.h" #include "utils/TimeUtils.h" @@ -42,6 +43,17 @@ RenderProxy::RenderProxy(bool translucent, RenderNode* rootRenderNode, mDrawFrameTask.setContext(&mRenderThread, mContext, rootRenderNode); } +void RenderProxy::asyncDelete(RenderProxy* proxy) { + if (!proxy) return; + + if (proxy->mContext) { + // Use the common pool because ~RenderProxy blocks on calling into RenderThread + CommonPool::post([proxy]() { delete proxy; }); + } else { + delete proxy; + } +} + RenderProxy::~RenderProxy() { destroyContext(); } diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h index d575aa77e4ab4..f4bcd07b2ef4a 100644 --- a/libs/hwui/renderthread/RenderProxy.h +++ b/libs/hwui/renderthread/RenderProxy.h @@ -62,10 +62,14 @@ enum { * references RenderProxy fields. This is safe as RenderProxy cannot * be deleted if it is blocked inside a call. */ -class RenderProxy { +class RenderProxy final { public: RenderProxy(bool opaque, RenderNode* rootNode, IContextFactory* contextFactory); - virtual ~RenderProxy(); + ~RenderProxy(); + + // Schedules a delete of the RenderProxy at a later date. Avoids blocking the current thread + // on destruction which ~RenderProxy does by default. + static void asyncDelete(RenderProxy*); // Won't take effect until next EGLSurface creation void setSwapBehavior(SwapBehavior swapBehavior);