Send HWUI load reset hint when Choreographer registers a callback
Send a load reset hint hint to DrawFrameTask through ThreadedRenderer
from ViewRootImpl whenever Choreographer registers a callback. This
allows the PowerHAL to allocate more resources for HWUI in response to
upcoming work, helping prevent frame drop.
Bug: b/243938267
Test: manual
Change-Id: Ie2cf809cf85530af04f4d0db3407853d4da03d62
diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp
index dc7676c..cb30614 100644
--- a/libs/hwui/renderthread/DrawFrameTask.cpp
+++ b/libs/hwui/renderthread/DrawFrameTask.cpp
@@ -42,6 +42,7 @@
size_t, int64_t);
typedef void (*APH_updateTargetWorkDuration)(APerformanceHintSession*, int64_t);
typedef void (*APH_reportActualWorkDuration)(APerformanceHintSession*, int64_t);
+typedef void (*APH_sendHint)(APerformanceHintSession* session, int32_t);
typedef void (*APH_closeSession)(APerformanceHintSession* session);
bool gAPerformanceHintBindingInitialized = false;
@@ -49,6 +50,7 @@
APH_createSession gAPH_createSessionFn = nullptr;
APH_updateTargetWorkDuration gAPH_updateTargetWorkDurationFn = nullptr;
APH_reportActualWorkDuration gAPH_reportActualWorkDurationFn = nullptr;
+APH_sendHint gAPH_sendHintFn = nullptr;
APH_closeSession gAPH_closeSessionFn = nullptr;
void ensureAPerformanceHintBindingInitialized() {
@@ -77,6 +79,10 @@
gAPH_reportActualWorkDurationFn == nullptr,
"Failed to find required symbol APerformanceHint_reportActualWorkDuration!");
+ gAPH_sendHintFn = (APH_sendHint)dlsym(handle_, "APerformanceHint_sendHint");
+ LOG_ALWAYS_FATAL_IF(gAPH_sendHintFn == nullptr,
+ "Failed to find required symbol APerformanceHint_sendHint!");
+
gAPH_closeSessionFn = (APH_closeSession)dlsym(handle_, "APerformanceHint_closeSession");
LOG_ALWAYS_FATAL_IF(gAPH_closeSessionFn == nullptr,
"Failed to find required symbol APerformanceHint_closeSession!");
@@ -239,6 +245,16 @@
mLastDequeueBufferDuration = dequeueBufferDuration;
}
+void DrawFrameTask::sendLoadResetHint() {
+ if (!(Properties::useHintManager && Properties::isDrawingEnabled())) return;
+ if (!mHintSessionWrapper) mHintSessionWrapper.emplace(mUiThreadId, mRenderThreadId);
+ nsecs_t now = systemTime();
+ if (now - mLastFrameNotification > kResetHintTimeout) {
+ mHintSessionWrapper->sendHint(SessionHint::CPU_LOAD_RESET);
+ }
+ mLastFrameNotification = now;
+}
+
bool DrawFrameTask::syncFrameState(TreeInfo& info) {
ATRACE_CALL();
int64_t vsync = mFrameInfo[static_cast<int>(FrameInfoIndex::Vsync)];
@@ -327,6 +343,12 @@
}
}
+void DrawFrameTask::HintSessionWrapper::sendHint(SessionHint hint) {
+ if (mHintSession && Properties::isDrawingEnabled()) {
+ gAPH_sendHintFn(mHintSession, static_cast<int>(hint));
+ }
+}
+
} /* namespace renderthread */
} /* namespace uirenderer */
} /* namespace android */
diff --git a/libs/hwui/renderthread/DrawFrameTask.h b/libs/hwui/renderthread/DrawFrameTask.h
index d6fc292..7eae41c 100644
--- a/libs/hwui/renderthread/DrawFrameTask.h
+++ b/libs/hwui/renderthread/DrawFrameTask.h
@@ -28,6 +28,7 @@
#include "../Rect.h"
#include "../TreeInfo.h"
#include "RenderTask.h"
+#include "utils/TimeUtils.h"
namespace android {
namespace uirenderer {
@@ -90,6 +91,8 @@
void forceDrawNextFrame() { mForceDrawFrame = true; }
+ void sendLoadResetHint();
+
private:
class HintSessionWrapper {
public:
@@ -98,6 +101,7 @@
void updateTargetWorkDuration(long targetDurationNanos);
void reportActualWorkDuration(long actualDurationNanos);
+ void sendHint(SessionHint hint);
private:
APerformanceHintSession* mHintSession = nullptr;
@@ -135,6 +139,9 @@
nsecs_t mLastTargetWorkDuration = 0;
std::optional<HintSessionWrapper> mHintSessionWrapper;
+ nsecs_t mLastFrameNotification = 0;
+ nsecs_t kResetHintTimeout = 100_ms;
+
bool mForceDrawFrame = false;
};
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 3324715..03a2bc9 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -236,6 +236,10 @@
mRenderThread.queue().post([this]() { mContext->notifyFramePending(); });
}
+void RenderProxy::notifyCallbackPending() {
+ mDrawFrameTask.sendLoadResetHint();
+}
+
void RenderProxy::dumpProfileInfo(int fd, int dumpFlags) {
mRenderThread.queue().runSync([&]() {
std::lock_guard lock(mRenderThread.getJankDataMutex());
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index 2a99a73..a21faa8 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -109,6 +109,7 @@
static int maxTextureSize();
void stopDrawing();
void notifyFramePending();
+ void notifyCallbackPending();
void dumpProfileInfo(int fd, int dumpFlags);
// Not exported, only used for testing