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
This commit is contained in:
@@ -587,6 +587,13 @@ public final class ThreadedRenderer extends HardwareRenderer {
|
||||
updateWebViewOverlayCallbacks();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyCallbackPending() {
|
||||
if (isEnabled()) {
|
||||
super.notifyCallbackPending();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the light position based on the position of the window.
|
||||
*
|
||||
|
||||
@@ -2308,6 +2308,7 @@ public final class ViewRootImpl implements ViewParent,
|
||||
*/
|
||||
void notifyRendererOfFramePending() {
|
||||
if (mAttachInfo.mThreadedRenderer != null) {
|
||||
mAttachInfo.mThreadedRenderer.notifyCallbackPending();
|
||||
mAttachInfo.mThreadedRenderer.notifyFramePending();
|
||||
}
|
||||
}
|
||||
@@ -9125,6 +9126,9 @@ public final class ViewRootImpl implements ViewParent,
|
||||
mConsumeBatchedInputScheduled = true;
|
||||
mChoreographer.postCallback(Choreographer.CALLBACK_INPUT,
|
||||
mConsumedBatchedInputRunnable, null);
|
||||
if (mAttachInfo.mThreadedRenderer != null) {
|
||||
mAttachInfo.mThreadedRenderer.notifyCallbackPending();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9318,6 +9322,9 @@ public final class ViewRootImpl implements ViewParent,
|
||||
mViews.add(view);
|
||||
postIfNeededLocked();
|
||||
}
|
||||
if (mAttachInfo.mThreadedRenderer != null) {
|
||||
mAttachInfo.mThreadedRenderer.notifyCallbackPending();
|
||||
}
|
||||
}
|
||||
|
||||
public void addViewRect(AttachInfo.InvalidateInfo info) {
|
||||
@@ -9325,6 +9332,9 @@ public final class ViewRootImpl implements ViewParent,
|
||||
mViewRects.add(info);
|
||||
postIfNeededLocked();
|
||||
}
|
||||
if (mAttachInfo.mThreadedRenderer != null) {
|
||||
mAttachInfo.mThreadedRenderer.notifyCallbackPending();
|
||||
}
|
||||
}
|
||||
|
||||
public void removeView(View view) {
|
||||
|
||||
@@ -981,6 +981,15 @@ public class HardwareRenderer {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies the hardware renderer about pending choreographer callbacks.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public void notifyCallbackPending() {
|
||||
nNotifyCallbackPending(mNativeProxy);
|
||||
}
|
||||
|
||||
/**
|
||||
* b/68769804, b/66945974: For low FPS experiments.
|
||||
*
|
||||
@@ -1536,4 +1545,6 @@ public class HardwareRenderer {
|
||||
private static native boolean nIsDrawingEnabled();
|
||||
|
||||
private static native void nSetRtAnimationsEnabled(boolean rtAnimationsEnabled);
|
||||
|
||||
private static native void nNotifyCallbackPending(long nativeProxy);
|
||||
}
|
||||
|
||||
@@ -860,6 +860,11 @@ static void android_view_ThreadedRenderer_setRtAnimationsEnabled(JNIEnv* env, jo
|
||||
RenderProxy::setRtAnimationsEnabled(enabled);
|
||||
}
|
||||
|
||||
static void android_view_ThreadedRenderer_notifyCallbackPending(JNIEnv*, jclass, jlong proxyPtr) {
|
||||
RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
|
||||
proxy->notifyCallbackPending();
|
||||
}
|
||||
|
||||
// Plumbs the display density down to DeviceInfo.
|
||||
static void android_view_ThreadedRenderer_setDisplayDensityDpi(JNIEnv*, jclass, jint densityDpi) {
|
||||
// Convert from dpi to density-independent pixels.
|
||||
@@ -1037,6 +1042,8 @@ static const JNINativeMethod gMethods[] = {
|
||||
{"nIsDrawingEnabled", "()Z", (void*)android_view_ThreadedRenderer_isDrawingEnabled},
|
||||
{"nSetRtAnimationsEnabled", "(Z)V",
|
||||
(void*)android_view_ThreadedRenderer_setRtAnimationsEnabled},
|
||||
{"nNotifyCallbackPending", "(J)V",
|
||||
(void*)android_view_ThreadedRenderer_notifyCallbackPending},
|
||||
};
|
||||
|
||||
static JavaVM* mJvm = nullptr;
|
||||
|
||||
@@ -42,6 +42,7 @@ typedef APerformanceHintSession* (*APH_createSession)(APerformanceHintManager*,
|
||||
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_getManager gAPH_getManagerFn = nullptr;
|
||||
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 @@ void ensureAPerformanceHintBindingInitialized() {
|
||||
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 @@ void DrawFrameTask::run() {
|
||||
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::reportActualWorkDuration(long actualDura
|
||||
}
|
||||
}
|
||||
|
||||
void DrawFrameTask::HintSessionWrapper::sendHint(SessionHint hint) {
|
||||
if (mHintSession && Properties::isDrawingEnabled()) {
|
||||
gAPH_sendHintFn(mHintSession, static_cast<int>(hint));
|
||||
}
|
||||
}
|
||||
|
||||
} /* namespace renderthread */
|
||||
} /* namespace uirenderer */
|
||||
} /* namespace android */
|
||||
|
||||
@@ -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 @@ public:
|
||||
|
||||
void forceDrawNextFrame() { mForceDrawFrame = true; }
|
||||
|
||||
void sendLoadResetHint();
|
||||
|
||||
private:
|
||||
class HintSessionWrapper {
|
||||
public:
|
||||
@@ -98,6 +101,7 @@ private:
|
||||
|
||||
void updateTargetWorkDuration(long targetDurationNanos);
|
||||
void reportActualWorkDuration(long actualDurationNanos);
|
||||
void sendHint(SessionHint hint);
|
||||
|
||||
private:
|
||||
APerformanceHintSession* mHintSession = nullptr;
|
||||
@@ -135,6 +139,9 @@ private:
|
||||
nsecs_t mLastTargetWorkDuration = 0;
|
||||
std::optional<HintSessionWrapper> mHintSessionWrapper;
|
||||
|
||||
nsecs_t mLastFrameNotification = 0;
|
||||
nsecs_t kResetHintTimeout = 100_ms;
|
||||
|
||||
bool mForceDrawFrame = false;
|
||||
};
|
||||
|
||||
|
||||
@@ -236,6 +236,10 @@ void RenderProxy::notifyFramePending() {
|
||||
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());
|
||||
|
||||
@@ -109,6 +109,7 @@ public:
|
||||
static int maxTextureSize();
|
||||
void stopDrawing();
|
||||
void notifyFramePending();
|
||||
void notifyCallbackPending();
|
||||
|
||||
void dumpProfileInfo(int fd, int dumpFlags);
|
||||
// Not exported, only used for testing
|
||||
|
||||
Reference in New Issue
Block a user