Add unit tests for HintSessionWrapper
This patch adds several unit tests for HintSessionWrapper, including
one specifically for a recent race condition memory leak.
It also refactors HintSessionWrapper to better support testing, and
creates a macro to shorten the dlsym bindings.
Bug: 299541959
Test: hwuiunit
Change-Id: I05ed15cdbd157b109667563d30627cfc4ae83777
Merged-In: I05ed15cdbd157b109667563d30627cfc4ae83777
(cherry picked from commit 0c6683683e370e591a5c45ea24d9b5f48d250f5c)
diff --git a/libs/hwui/renderthread/HintSessionWrapper.cpp b/libs/hwui/renderthread/HintSessionWrapper.cpp
index 1f338ee..b34da51 100644
--- a/libs/hwui/renderthread/HintSessionWrapper.cpp
+++ b/libs/hwui/renderthread/HintSessionWrapper.cpp
@@ -32,65 +32,30 @@
namespace uirenderer {
namespace renderthread {
-namespace {
+#define BIND_APH_METHOD(name) \
+ name = (decltype(name))dlsym(handle_, "APerformanceHint_" #name); \
+ LOG_ALWAYS_FATAL_IF(name == nullptr, "Failed to find required symbol APerformanceHint_" #name)
-typedef APerformanceHintManager* (*APH_getManager)();
-typedef APerformanceHintSession* (*APH_createSession)(APerformanceHintManager*, const int32_t*,
- size_t, int64_t);
-typedef void (*APH_closeSession)(APerformanceHintSession* session);
-typedef void (*APH_updateTargetWorkDuration)(APerformanceHintSession*, int64_t);
-typedef void (*APH_reportActualWorkDuration)(APerformanceHintSession*, int64_t);
-typedef void (*APH_sendHint)(APerformanceHintSession* session, int32_t);
-
-bool gAPerformanceHintBindingInitialized = false;
-APH_getManager gAPH_getManagerFn = nullptr;
-APH_createSession gAPH_createSessionFn = nullptr;
-APH_closeSession gAPH_closeSessionFn = nullptr;
-APH_updateTargetWorkDuration gAPH_updateTargetWorkDurationFn = nullptr;
-APH_reportActualWorkDuration gAPH_reportActualWorkDurationFn = nullptr;
-APH_sendHint gAPH_sendHintFn = nullptr;
-
-void ensureAPerformanceHintBindingInitialized() {
- if (gAPerformanceHintBindingInitialized) return;
+void HintSessionWrapper::HintSessionBinding::init() {
+ if (mInitialized) 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!");
+ BIND_APH_METHOD(getManager);
+ BIND_APH_METHOD(createSession);
+ BIND_APH_METHOD(closeSession);
+ BIND_APH_METHOD(updateTargetWorkDuration);
+ BIND_APH_METHOD(reportActualWorkDuration);
+ BIND_APH_METHOD(sendHint);
- gAPH_createSessionFn = (APH_createSession)dlsym(handle_, "APerformanceHint_createSession");
- LOG_ALWAYS_FATAL_IF(gAPH_createSessionFn == nullptr,
- "Failed to find required symbol APerformanceHint_createSession!");
-
- gAPH_closeSessionFn = (APH_closeSession)dlsym(handle_, "APerformanceHint_closeSession");
- LOG_ALWAYS_FATAL_IF(gAPH_closeSessionFn == nullptr,
- "Failed to find required symbol APerformanceHint_closeSession!");
-
- 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_sendHintFn = (APH_sendHint)dlsym(handle_, "APerformanceHint_sendHint");
- LOG_ALWAYS_FATAL_IF(gAPH_sendHintFn == nullptr,
- "Failed to find required symbol APerformanceHint_sendHint!");
-
- gAPerformanceHintBindingInitialized = true;
+ mInitialized = true;
}
-} // namespace
-
HintSessionWrapper::HintSessionWrapper(pid_t uiThreadId, pid_t renderThreadId)
- : mUiThreadId(uiThreadId), mRenderThreadId(renderThreadId) {}
+ : mUiThreadId(uiThreadId)
+ , mRenderThreadId(renderThreadId)
+ , mBinding(std::make_shared<HintSessionBinding>()) {}
HintSessionWrapper::~HintSessionWrapper() {
destroy();
@@ -101,7 +66,7 @@
mHintSession = mHintSessionFuture.get();
}
if (mHintSession) {
- gAPH_closeSessionFn(mHintSession);
+ mBinding->closeSession(mHintSession);
mSessionValid = true;
mHintSession = nullptr;
}
@@ -133,9 +98,9 @@
// Assume that if we return before the end, it broke
mSessionValid = false;
- ensureAPerformanceHintBindingInitialized();
+ mBinding->init();
- APerformanceHintManager* manager = gAPH_getManagerFn();
+ APerformanceHintManager* manager = mBinding->getManager();
if (!manager) return false;
std::vector<pid_t> tids = CommonPool::getThreadIds();
@@ -145,8 +110,9 @@
// Use a placeholder target value to initialize,
// this will always be replaced elsewhere before it gets used
int64_t defaultTargetDurationNanos = 16666667;
- mHintSessionFuture = CommonPool::async([=, tids = std::move(tids)] {
- return gAPH_createSessionFn(manager, tids.data(), tids.size(), defaultTargetDurationNanos);
+ mHintSessionFuture = CommonPool::async([=, this, tids = std::move(tids)] {
+ return mBinding->createSession(manager, tids.data(), tids.size(),
+ defaultTargetDurationNanos);
});
return false;
}
@@ -158,7 +124,7 @@
targetWorkDurationNanos > kSanityCheckLowerBound &&
targetWorkDurationNanos < kSanityCheckUpperBound) {
mLastTargetWorkDuration = targetWorkDurationNanos;
- gAPH_updateTargetWorkDurationFn(mHintSession, targetWorkDurationNanos);
+ mBinding->updateTargetWorkDuration(mHintSession, targetWorkDurationNanos);
}
mLastFrameNotification = systemTime();
}
@@ -168,7 +134,7 @@
mResetsSinceLastReport = 0;
if (actualDurationNanos > kSanityCheckLowerBound &&
actualDurationNanos < kSanityCheckUpperBound) {
- gAPH_reportActualWorkDurationFn(mHintSession, actualDurationNanos);
+ mBinding->reportActualWorkDuration(mHintSession, actualDurationNanos);
}
}
@@ -179,14 +145,14 @@
if (now - mLastFrameNotification > kResetHintTimeout &&
mResetsSinceLastReport <= kMaxResetsSinceLastReport) {
++mResetsSinceLastReport;
- gAPH_sendHintFn(mHintSession, static_cast<int>(SessionHint::CPU_LOAD_RESET));
+ mBinding->sendHint(mHintSession, static_cast<int32_t>(SessionHint::CPU_LOAD_RESET));
}
mLastFrameNotification = now;
}
void HintSessionWrapper::sendLoadIncreaseHint() {
if (!init()) return;
- gAPH_sendHintFn(mHintSession, static_cast<int>(SessionHint::CPU_LOAD_UP));
+ mBinding->sendHint(mHintSession, static_cast<int32_t>(SessionHint::CPU_LOAD_UP));
}
} /* namespace renderthread */