Switch HWUI to use native performance hint API

Test: None
Bug: 194204196
Change-Id: I80dfdb5d56921c465406cc4534e82738c668d46d
This commit is contained in:
Bo Liu
2021-07-17 16:42:13 -04:00
parent 4426772eab
commit 6a3fc60f43
6 changed files with 137 additions and 181 deletions

View File

@@ -16,6 +16,7 @@
#include "DrawFrameTask.h"
#include <dlfcn.h>
#include <gui/TraceUtils.h>
#include <utils/Log.h>
#include <algorithm>
@@ -26,11 +27,63 @@
#include "../RenderNode.h"
#include "CanvasContext.h"
#include "RenderThread.h"
#include "thread/CommonPool.h"
namespace android {
namespace uirenderer {
namespace renderthread {
namespace {
typedef APerformanceHintManager* (*APH_getManager)();
typedef APerformanceHintSession* (*APH_createSession)(APerformanceHintManager*, const int32_t*,
size_t, int64_t);
typedef void (*APH_updateTargetWorkDuration)(APerformanceHintSession*, int64_t);
typedef void (*APH_reportActualWorkDuration)(APerformanceHintSession*, int64_t);
typedef void (*APH_closeSession)(APerformanceHintSession* session);
bool gAPerformanceHintBindingInitialized = false;
APH_getManager gAPH_getManagerFn = nullptr;
APH_createSession gAPH_createSessionFn = nullptr;
APH_updateTargetWorkDuration gAPH_updateTargetWorkDurationFn = nullptr;
APH_reportActualWorkDuration gAPH_reportActualWorkDurationFn = nullptr;
APH_closeSession gAPH_closeSessionFn = nullptr;
void ensureAPerformanceHintBindingInitialized() {
if (gAPerformanceHintBindingInitialized) return;
void* handle_ = dlopen("libandroid.so", RTLD_NOW | RTLD_NODELETE);
LOG_ALWAYS_FATAL_IF(handle_ == nullptr, "Failed to dlopen libandroid.so!");
gAPH_getManagerFn = (APH_getManager)dlsym(handle_, "APerformanceHint_getManager");
LOG_ALWAYS_FATAL_IF(gAPH_getManagerFn == nullptr,
"Failed to find required symbol APerformanceHint_getManager!");
gAPH_createSessionFn = (APH_createSession)dlsym(handle_, "APerformanceHint_createSession");
LOG_ALWAYS_FATAL_IF(gAPH_createSessionFn == nullptr,
"Failed to find required symbol APerformanceHint_createSession!");
gAPH_updateTargetWorkDurationFn = (APH_updateTargetWorkDuration)dlsym(
handle_, "APerformanceHint_updateTargetWorkDuration");
LOG_ALWAYS_FATAL_IF(
gAPH_updateTargetWorkDurationFn == nullptr,
"Failed to find required symbol APerformanceHint_updateTargetWorkDuration!");
gAPH_reportActualWorkDurationFn = (APH_reportActualWorkDuration)dlsym(
handle_, "APerformanceHint_reportActualWorkDuration");
LOG_ALWAYS_FATAL_IF(
gAPH_reportActualWorkDurationFn == nullptr,
"Failed to find required symbol APerformanceHint_reportActualWorkDuration!");
gAPH_closeSessionFn = (APH_closeSession)dlsym(handle_, "APerformanceHint_closeSession");
LOG_ALWAYS_FATAL_IF(gAPH_closeSessionFn == nullptr,
"Failed to find required symbol APerformanceHint_closeSession!");
gAPerformanceHintBindingInitialized = true;
}
} // namespace
DrawFrameTask::DrawFrameTask()
: mRenderThread(nullptr)
, mContext(nullptr)
@@ -39,17 +92,13 @@ DrawFrameTask::DrawFrameTask()
DrawFrameTask::~DrawFrameTask() {}
void DrawFrameTask::setContext(RenderThread* thread, CanvasContext* context,
RenderNode* targetNode) {
void DrawFrameTask::setContext(RenderThread* thread, CanvasContext* context, RenderNode* targetNode,
int32_t uiThreadId, int32_t renderThreadId) {
mRenderThread = thread;
mContext = context;
mTargetNode = targetNode;
}
void DrawFrameTask::setHintSessionCallbacks(std::function<void(int64_t)> updateTargetWorkDuration,
std::function<void(int64_t)> reportActualWorkDuration) {
mUpdateTargetWorkDuration = std::move(updateTargetWorkDuration);
mReportActualWorkDuration = std::move(reportActualWorkDuration);
mUiThreadId = uiThreadId;
mRenderThreadId = renderThreadId;
}
void DrawFrameTask::pushLayerUpdate(DeferredLayerUpdater* layer) {
@@ -144,27 +193,25 @@ void DrawFrameTask::run() {
unblockUiThread();
}
// These member callbacks are effectively const as they are set once during init, so it's safe
// to use these directly instead of making local copies.
if (mUpdateTargetWorkDuration && mReportActualWorkDuration) {
constexpr int64_t kSanityCheckLowerBound = 100000; // 0.1ms
constexpr int64_t kSanityCheckUpperBound = 10000000000; // 10s
int64_t targetWorkDuration = frameDeadline - intendedVsync;
targetWorkDuration = targetWorkDuration * Properties::targetCpuTimePercentage / 100;
if (targetWorkDuration > kSanityCheckLowerBound &&
targetWorkDuration < kSanityCheckUpperBound &&
targetWorkDuration != mLastTargetWorkDuration) {
mLastTargetWorkDuration = targetWorkDuration;
mUpdateTargetWorkDuration(targetWorkDuration);
}
int64_t frameDuration = systemTime(SYSTEM_TIME_MONOTONIC) - frameStartTime;
int64_t actualDuration = frameDuration -
(std::min(syncDelayDuration, mLastDequeueBufferDuration)) -
dequeueBufferDuration;
if (actualDuration > kSanityCheckLowerBound && actualDuration < kSanityCheckUpperBound) {
mReportActualWorkDuration(actualDuration);
}
if (!mHintSessionWrapper) mHintSessionWrapper.emplace(mUiThreadId, mRenderThreadId);
constexpr int64_t kSanityCheckLowerBound = 100000; // 0.1ms
constexpr int64_t kSanityCheckUpperBound = 10000000000; // 10s
int64_t targetWorkDuration = frameDeadline - intendedVsync;
targetWorkDuration = targetWorkDuration * Properties::targetCpuTimePercentage / 100;
if (targetWorkDuration > kSanityCheckLowerBound &&
targetWorkDuration < kSanityCheckUpperBound &&
targetWorkDuration != mLastTargetWorkDuration) {
mLastTargetWorkDuration = targetWorkDuration;
mHintSessionWrapper->updateTargetWorkDuration(targetWorkDuration);
}
int64_t frameDuration = systemTime(SYSTEM_TIME_MONOTONIC) - frameStartTime;
int64_t actualDuration = frameDuration -
(std::min(syncDelayDuration, mLastDequeueBufferDuration)) -
dequeueBufferDuration;
if (actualDuration > kSanityCheckLowerBound && actualDuration < kSanityCheckUpperBound) {
mHintSessionWrapper->reportActualWorkDuration(actualDuration);
}
mLastDequeueBufferDuration = dequeueBufferDuration;
}
@@ -216,6 +263,44 @@ void DrawFrameTask::unblockUiThread() {
mSignal.signal();
}
DrawFrameTask::HintSessionWrapper::HintSessionWrapper(int32_t uiThreadId, int32_t renderThreadId) {
if (!Properties::useHintManager) return;
if (uiThreadId < 0 || renderThreadId < 0) return;
ensureAPerformanceHintBindingInitialized();
APerformanceHintManager* manager = gAPH_getManagerFn();
if (!manager) return;
std::vector<int32_t> tids = CommonPool::getThreadIds();
tids.push_back(uiThreadId);
tids.push_back(renderThreadId);
// DrawFrameTask code will always set a target duration before reporting actual durations.
// So this is just a placeholder value that's never used.
int64_t dummyTargetDurationNanos = 16666667;
mHintSession =
gAPH_createSessionFn(manager, tids.data(), tids.size(), dummyTargetDurationNanos);
}
DrawFrameTask::HintSessionWrapper::~HintSessionWrapper() {
if (mHintSession) {
gAPH_closeSessionFn(mHintSession);
}
}
void DrawFrameTask::HintSessionWrapper::updateTargetWorkDuration(long targetDurationNanos) {
if (mHintSession) {
gAPH_updateTargetWorkDurationFn(mHintSession, targetDurationNanos);
}
}
void DrawFrameTask::HintSessionWrapper::reportActualWorkDuration(long actualDurationNanos) {
if (mHintSession) {
gAPH_reportActualWorkDurationFn(mHintSession, actualDurationNanos);
}
}
} /* namespace renderthread */
} /* namespace uirenderer */
} /* namespace android */