Switch HWUI to use native performance hint API
Test: None Bug: 194204196 Change-Id: I80dfdb5d56921c465406cc4534e82738c668d46d
This commit is contained in:
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user