Update HintManager to use NDK backend
- Update HintManager and its aidl types to use NDK backend
- Switch HintManager to using PowerHAL's WorkDuration
- Update SDK WorkDuration.java to no longer be parcelable,
since it isn't being sent over binders anymore.
- Remove duplicate WorkDuration in powermanager in favor of PowerHAL's
Bug: 315894228
Test: atest HintManagerServiceTest
Test: atest PerformanceHintNativeTestCases
Test: atest PerformanceHintManagerTest
Change-Id: Ibc5a3aa96e73a225fce980811694ee02bdabb963
diff --git a/native/android/Android.bp b/native/android/Android.bp
index 752ebdf..0cfb237 100644
--- a/native/android/Android.bp
+++ b/native/android/Android.bp
@@ -83,6 +83,7 @@
"libinput",
"libutils",
"libbinder",
+ "libbinder_ndk",
"libui",
"libgui",
"libharfbuzz_ng", // Only for including hb.h via minikin
@@ -100,6 +101,7 @@
"android.hardware.configstore-utils",
"android.os.flags-aconfig-cc",
"libnativedisplay",
+ "libfmq",
],
static_libs: [
diff --git a/native/android/performance_hint.cpp b/native/android/performance_hint.cpp
index 279f9d6..8227bdb 100644
--- a/native/android/performance_hint.cpp
+++ b/native/android/performance_hint.cpp
@@ -18,15 +18,15 @@
#include <aidl/android/hardware/power/SessionHint.h>
#include <aidl/android/hardware/power/SessionMode.h>
+#include <aidl/android/hardware/power/SessionTag.h>
+#include <aidl/android/hardware/power/WorkDuration.h>
+#include <aidl/android/os/IHintManager.h>
+#include <aidl/android/os/IHintSession.h>
#include <android-base/stringprintf.h>
-#include <android/WorkDuration.h>
-#include <android/os/IHintManager.h>
-#include <android/os/IHintSession.h>
+#include <android/binder_manager.h>
+#include <android/binder_status.h>
#include <android/performance_hint.h>
#include <android/trace.h>
-#include <binder/Binder.h>
-#include <binder/IBinder.h>
-#include <binder/IServiceManager.h>
#include <inttypes.h>
#include <performance_hint_private.h>
#include <utils/SystemClock.h>
@@ -37,22 +37,25 @@
#include <vector>
using namespace android;
-using namespace android::os;
+using namespace aidl::android::os;
using namespace std::chrono_literals;
-using AidlSessionHint = aidl::android::hardware::power::SessionHint;
-using AidlSessionMode = aidl::android::hardware::power::SessionMode;
+using HalSessionHint = aidl::android::hardware::power::SessionHint;
+using HalSessionMode = aidl::android::hardware::power::SessionMode;
+using HalWorkDuration = aidl::android::hardware::power::WorkDuration;
+
using android::base::StringPrintf;
struct APerformanceHintSession;
constexpr int64_t SEND_HINT_TIMEOUT = std::chrono::nanoseconds(100ms).count();
+struct AWorkDuration : public HalWorkDuration {};
struct APerformanceHintManager {
public:
static APerformanceHintManager* getInstance();
- APerformanceHintManager(sp<IHintManager> service, int64_t preferredRateNanos);
+ APerformanceHintManager(std::shared_ptr<IHintManager> service, int64_t preferredRateNanos);
APerformanceHintManager() = delete;
~APerformanceHintManager() = default;
@@ -61,17 +64,28 @@
int64_t getPreferredRateNanos() const;
private:
- static APerformanceHintManager* create(sp<IHintManager> iHintManager);
+ // Necessary to create an empty binder object
+ static void* tokenStubOnCreate(void*) {
+ return nullptr;
+ }
+ static void tokenStubOnDestroy(void*) {}
+ static binder_status_t tokenStubOnTransact(AIBinder*, transaction_code_t, const AParcel*,
+ AParcel*) {
+ return STATUS_OK;
+ }
- sp<IHintManager> mHintManager;
- const sp<IBinder> mToken = sp<BBinder>::make();
+ static APerformanceHintManager* create(std::shared_ptr<IHintManager> iHintManager);
+
+ std::shared_ptr<IHintManager> mHintManager;
+ ndk::SpAIBinder mToken;
const int64_t mPreferredRateNanos;
};
struct APerformanceHintSession {
public:
- APerformanceHintSession(sp<IHintManager> hintManager, sp<IHintSession> session,
- int64_t preferredRateNanos, int64_t targetDurationNanos);
+ APerformanceHintSession(std::shared_ptr<IHintManager> hintManager,
+ std::shared_ptr<IHintSession> session, int64_t preferredRateNanos,
+ int64_t targetDurationNanos);
APerformanceHintSession() = delete;
~APerformanceHintSession();
@@ -86,10 +100,10 @@
private:
friend struct APerformanceHintManager;
- int reportActualWorkDurationInternal(WorkDuration* workDuration);
+ int reportActualWorkDurationInternal(AWorkDuration* workDuration);
- sp<IHintManager> mHintManager;
- sp<IHintSession> mHintSession;
+ std::shared_ptr<IHintManager> mHintManager;
+ std::shared_ptr<IHintSession> mHintSession;
// HAL preferred update rate
const int64_t mPreferredRateNanos;
// Target duration for choosing update rate
@@ -101,7 +115,7 @@
// Last hint reported from sendHint indexed by hint value
std::vector<int64_t> mLastHintSentTimestamp;
// Cached samples
- std::vector<WorkDuration> mActualWorkDurations;
+ std::vector<HalWorkDuration> mActualWorkDurations;
std::string mSessionName;
static int32_t sIDCounter;
// The most recent set of thread IDs
@@ -114,19 +128,24 @@
void traceTargetDuration(int64_t targetDuration);
};
-static IHintManager* gIHintManagerForTesting = nullptr;
+static std::shared_ptr<IHintManager>* gIHintManagerForTesting = nullptr;
static APerformanceHintManager* gHintManagerForTesting = nullptr;
int32_t APerformanceHintSession::sIDCounter = 0;
// ===================================== APerformanceHintManager implementation
-APerformanceHintManager::APerformanceHintManager(sp<IHintManager> manager,
+APerformanceHintManager::APerformanceHintManager(std::shared_ptr<IHintManager> manager,
int64_t preferredRateNanos)
- : mHintManager(std::move(manager)), mPreferredRateNanos(preferredRateNanos) {}
+ : mHintManager(std::move(manager)), mPreferredRateNanos(preferredRateNanos) {
+ static AIBinder_Class* tokenBinderClass =
+ AIBinder_Class_define("phm_token", tokenStubOnCreate, tokenStubOnDestroy,
+ tokenStubOnTransact);
+ mToken = ndk::SpAIBinder(AIBinder_new(tokenBinderClass, nullptr));
+}
APerformanceHintManager* APerformanceHintManager::getInstance() {
if (gHintManagerForTesting) return gHintManagerForTesting;
if (gIHintManagerForTesting) {
- APerformanceHintManager* manager = create(gIHintManagerForTesting);
+ APerformanceHintManager* manager = create(*gIHintManagerForTesting);
gIHintManagerForTesting = nullptr;
return manager;
}
@@ -134,20 +153,19 @@
return instance;
}
-APerformanceHintManager* APerformanceHintManager::create(sp<IHintManager> manager) {
+APerformanceHintManager* APerformanceHintManager::create(std::shared_ptr<IHintManager> manager) {
if (!manager) {
- manager = interface_cast<IHintManager>(
- defaultServiceManager()->checkService(String16("performance_hint")));
+ manager = IHintManager::fromBinder(
+ ndk::SpAIBinder(AServiceManager_waitForService("performance_hint")));
}
if (manager == nullptr) {
ALOGE("%s: PerformanceHint service is not ready ", __FUNCTION__);
return nullptr;
}
int64_t preferredRateNanos = -1L;
- binder::Status ret = manager->getHintSessionPreferredRate(&preferredRateNanos);
+ ndk::ScopedAStatus ret = manager->getHintSessionPreferredRate(&preferredRateNanos);
if (!ret.isOk()) {
- ALOGE("%s: PerformanceHint cannot get preferred rate. %s", __FUNCTION__,
- ret.exceptionMessage().c_str());
+ ALOGE("%s: PerformanceHint cannot get preferred rate. %s", __FUNCTION__, ret.getMessage());
return nullptr;
}
if (preferredRateNanos <= 0) {
@@ -159,8 +177,8 @@
APerformanceHintSession* APerformanceHintManager::createSession(
const int32_t* threadIds, size_t size, int64_t initialTargetWorkDurationNanos) {
std::vector<int32_t> tids(threadIds, threadIds + size);
- sp<IHintSession> session;
- binder::Status ret =
+ std::shared_ptr<IHintSession> session;
+ ndk::ScopedAStatus ret =
mHintManager->createHintSession(mToken, tids, initialTargetWorkDurationNanos, &session);
if (!ret.isOk() || !session) {
return nullptr;
@@ -179,8 +197,8 @@
// ===================================== APerformanceHintSession implementation
-APerformanceHintSession::APerformanceHintSession(sp<IHintManager> hintManager,
- sp<IHintSession> session,
+APerformanceHintSession::APerformanceHintSession(std::shared_ptr<IHintManager> hintManager,
+ std::shared_ptr<IHintSession> session,
int64_t preferredRateNanos,
int64_t targetDurationNanos)
: mHintManager(hintManager),
@@ -189,17 +207,17 @@
mTargetDurationNanos(targetDurationNanos),
mFirstTargetMetTimestamp(0),
mLastTargetMetTimestamp(0) {
- const std::vector<AidlSessionHint> sessionHintRange{ndk::enum_range<AidlSessionHint>().begin(),
- ndk::enum_range<AidlSessionHint>().end()};
+ const std::vector<HalSessionHint> sessionHintRange{ndk::enum_range<HalSessionHint>().begin(),
+ ndk::enum_range<HalSessionHint>().end()};
mLastHintSentTimestamp = std::vector<int64_t>(sessionHintRange.size(), 0);
mSessionName = android::base::StringPrintf("ADPF Session %" PRId32, ++sIDCounter);
}
APerformanceHintSession::~APerformanceHintSession() {
- binder::Status ret = mHintSession->close();
+ ndk::ScopedAStatus ret = mHintSession->close();
if (!ret.isOk()) {
- ALOGE("%s: HintSession close failed: %s", __FUNCTION__, ret.exceptionMessage().c_str());
+ ALOGE("%s: HintSession close failed: %s", __FUNCTION__, ret.getMessage());
}
}
@@ -208,10 +226,10 @@
ALOGE("%s: targetDurationNanos must be positive", __FUNCTION__);
return EINVAL;
}
- binder::Status ret = mHintSession->updateTargetWorkDuration(targetDurationNanos);
+ ndk::ScopedAStatus ret = mHintSession->updateTargetWorkDuration(targetDurationNanos);
if (!ret.isOk()) {
ALOGE("%s: HintSession updateTargetWorkDuration failed: %s", __FUNCTION__,
- ret.exceptionMessage().c_str());
+ ret.getMessage());
return EPIPE;
}
mTargetDurationNanos = targetDurationNanos;
@@ -228,9 +246,12 @@
}
int APerformanceHintSession::reportActualWorkDuration(int64_t actualDurationNanos) {
- WorkDuration workDuration(0, actualDurationNanos, actualDurationNanos, 0);
+ HalWorkDuration workDuration{.durationNanos = actualDurationNanos,
+ .workPeriodStartTimestampNanos = 0,
+ .cpuDurationNanos = actualDurationNanos,
+ .gpuDurationNanos = 0};
- return reportActualWorkDurationInternal(&workDuration);
+ return reportActualWorkDurationInternal(static_cast<AWorkDuration*>(&workDuration));
}
int APerformanceHintSession::sendHint(SessionHint hint) {
@@ -238,17 +259,17 @@
ALOGE("%s: invalid session hint %d", __FUNCTION__, hint);
return EINVAL;
}
- int64_t now = elapsedRealtimeNano();
+ int64_t now = uptimeNanos();
// Limit sendHint to a pre-detemined rate for safety
if (now < (mLastHintSentTimestamp[hint] + SEND_HINT_TIMEOUT)) {
return 0;
}
- binder::Status ret = mHintSession->sendHint(hint);
+ ndk::ScopedAStatus ret = mHintSession->sendHint(hint);
if (!ret.isOk()) {
- ALOGE("%s: HintSession sendHint failed: %s", __FUNCTION__, ret.exceptionMessage().c_str());
+ ALOGE("%s: HintSession sendHint failed: %s", __FUNCTION__, ret.getMessage());
return EPIPE;
}
mLastHintSentTimestamp[hint] = now;
@@ -261,12 +282,12 @@
return EINVAL;
}
std::vector<int32_t> tids(threadIds, threadIds + size);
- binder::Status ret = mHintManager->setHintSessionThreads(mHintSession, tids);
+ ndk::ScopedAStatus ret = mHintManager->setHintSessionThreads(mHintSession, tids);
if (!ret.isOk()) {
- ALOGE("%s: failed: %s", __FUNCTION__, ret.exceptionMessage().c_str());
- if (ret.exceptionCode() == binder::Status::Exception::EX_ILLEGAL_ARGUMENT) {
+ ALOGE("%s: failed: %s", __FUNCTION__, ret.getMessage());
+ if (ret.getExceptionCode() == EX_ILLEGAL_ARGUMENT) {
return EINVAL;
- } else if (ret.exceptionCode() == binder::Status::Exception::EX_SECURITY) {
+ } else if (ret.getExceptionCode() == EX_SECURITY) {
return EPERM;
}
return EPIPE;
@@ -279,9 +300,9 @@
int APerformanceHintSession::getThreadIds(int32_t* const threadIds, size_t* size) {
std::vector<int32_t> tids;
- binder::Status ret = mHintManager->getHintSessionThreadIds(mHintSession, &tids);
+ ndk::ScopedAStatus ret = mHintManager->getHintSessionThreadIds(mHintSession, &tids);
if (!ret.isOk()) {
- ALOGE("%s: failed: %s", __FUNCTION__, ret.exceptionMessage().c_str());
+ ALOGE("%s: failed: %s", __FUNCTION__, ret.getMessage());
return EPIPE;
}
@@ -301,28 +322,27 @@
}
int APerformanceHintSession::setPreferPowerEfficiency(bool enabled) {
- binder::Status ret =
- mHintSession->setMode(static_cast<int32_t>(AidlSessionMode::POWER_EFFICIENCY), enabled);
+ ndk::ScopedAStatus ret =
+ mHintSession->setMode(static_cast<int32_t>(HalSessionMode::POWER_EFFICIENCY), enabled);
if (!ret.isOk()) {
ALOGE("%s: HintSession setPreferPowerEfficiency failed: %s", __FUNCTION__,
- ret.exceptionMessage().c_str());
+ ret.getMessage());
return EPIPE;
}
tracePowerEfficient(enabled);
return OK;
}
-int APerformanceHintSession::reportActualWorkDuration(AWorkDuration* aWorkDuration) {
- WorkDuration* workDuration = static_cast<WorkDuration*>(aWorkDuration);
+int APerformanceHintSession::reportActualWorkDuration(AWorkDuration* workDuration) {
return reportActualWorkDurationInternal(workDuration);
}
-int APerformanceHintSession::reportActualWorkDurationInternal(WorkDuration* workDuration) {
- int64_t actualTotalDurationNanos = workDuration->actualTotalDurationNanos;
+int APerformanceHintSession::reportActualWorkDurationInternal(AWorkDuration* workDuration) {
+ int64_t actualTotalDurationNanos = workDuration->durationNanos;
int64_t now = uptimeNanos();
- workDuration->timestampNanos = now;
- traceActualDuration(workDuration->actualTotalDurationNanos);
+ workDuration->timeStampNanos = now;
+ traceActualDuration(workDuration->durationNanos);
mActualWorkDurations.push_back(std::move(*workDuration));
if (actualTotalDurationNanos >= mTargetDurationNanos) {
@@ -346,14 +366,14 @@
mLastTargetMetTimestamp = now;
}
- binder::Status ret = mHintSession->reportActualWorkDuration2(mActualWorkDurations);
+ ndk::ScopedAStatus ret = mHintSession->reportActualWorkDuration2(mActualWorkDurations);
if (!ret.isOk()) {
ALOGE("%s: HintSession reportActualWorkDuration failed: %s", __FUNCTION__,
- ret.exceptionMessage().c_str());
+ ret.getMessage());
mFirstTargetMetTimestamp = 0;
mLastTargetMetTimestamp = 0;
traceBatchSize(mActualWorkDurations.size());
- return ret.exceptionCode() == binder::Status::EX_ILLEGAL_ARGUMENT ? EINVAL : EPIPE;
+ return ret.getExceptionCode() == EX_ILLEGAL_ARGUMENT ? EINVAL : EPIPE;
}
mActualWorkDurations.clear();
traceBatchSize(0);
@@ -481,18 +501,16 @@
AWorkDuration* workDurationPtr) {
VALIDATE_PTR(session)
VALIDATE_PTR(workDurationPtr)
- WorkDuration& workDuration = *static_cast<WorkDuration*>(workDurationPtr);
- VALIDATE_INT(workDuration.workPeriodStartTimestampNanos, > 0)
- VALIDATE_INT(workDuration.actualTotalDurationNanos, > 0)
- VALIDATE_INT(workDuration.actualCpuDurationNanos, >= 0)
- VALIDATE_INT(workDuration.actualGpuDurationNanos, >= 0)
- VALIDATE_INT(workDuration.actualGpuDurationNanos + workDuration.actualCpuDurationNanos, > 0)
+ VALIDATE_INT(workDurationPtr->durationNanos, > 0)
+ VALIDATE_INT(workDurationPtr->workPeriodStartTimestampNanos, > 0)
+ VALIDATE_INT(workDurationPtr->cpuDurationNanos, >= 0)
+ VALIDATE_INT(workDurationPtr->gpuDurationNanos, >= 0)
+ VALIDATE_INT(workDurationPtr->gpuDurationNanos + workDurationPtr->cpuDurationNanos, > 0)
return session->reportActualWorkDuration(workDurationPtr);
}
AWorkDuration* AWorkDuration_create() {
- WorkDuration* workDuration = new WorkDuration();
- return static_cast<AWorkDuration*>(workDuration);
+ return new AWorkDuration();
}
void AWorkDuration_release(AWorkDuration* aWorkDuration) {
@@ -500,37 +518,36 @@
delete aWorkDuration;
}
-void AWorkDuration_setWorkPeriodStartTimestampNanos(AWorkDuration* aWorkDuration,
- int64_t workPeriodStartTimestampNanos) {
- VALIDATE_PTR(aWorkDuration)
- WARN_INT(workPeriodStartTimestampNanos, > 0)
- static_cast<WorkDuration*>(aWorkDuration)->workPeriodStartTimestampNanos =
- workPeriodStartTimestampNanos;
-}
-
void AWorkDuration_setActualTotalDurationNanos(AWorkDuration* aWorkDuration,
int64_t actualTotalDurationNanos) {
VALIDATE_PTR(aWorkDuration)
WARN_INT(actualTotalDurationNanos, > 0)
- static_cast<WorkDuration*>(aWorkDuration)->actualTotalDurationNanos = actualTotalDurationNanos;
+ aWorkDuration->durationNanos = actualTotalDurationNanos;
+}
+
+void AWorkDuration_setWorkPeriodStartTimestampNanos(AWorkDuration* aWorkDuration,
+ int64_t workPeriodStartTimestampNanos) {
+ VALIDATE_PTR(aWorkDuration)
+ WARN_INT(workPeriodStartTimestampNanos, > 0)
+ aWorkDuration->workPeriodStartTimestampNanos = workPeriodStartTimestampNanos;
}
void AWorkDuration_setActualCpuDurationNanos(AWorkDuration* aWorkDuration,
int64_t actualCpuDurationNanos) {
VALIDATE_PTR(aWorkDuration)
WARN_INT(actualCpuDurationNanos, >= 0)
- static_cast<WorkDuration*>(aWorkDuration)->actualCpuDurationNanos = actualCpuDurationNanos;
+ aWorkDuration->cpuDurationNanos = actualCpuDurationNanos;
}
void AWorkDuration_setActualGpuDurationNanos(AWorkDuration* aWorkDuration,
int64_t actualGpuDurationNanos) {
VALIDATE_PTR(aWorkDuration)
WARN_INT(actualGpuDurationNanos, >= 0)
- static_cast<WorkDuration*>(aWorkDuration)->actualGpuDurationNanos = actualGpuDurationNanos;
+ aWorkDuration->gpuDurationNanos = actualGpuDurationNanos;
}
void APerformanceHint_setIHintManagerForTesting(void* iManager) {
delete gHintManagerForTesting;
gHintManagerForTesting = nullptr;
- gIHintManagerForTesting = static_cast<IHintManager*>(iManager);
+ gIHintManagerForTesting = static_cast<std::shared_ptr<IHintManager>*>(iManager);
}
diff --git a/native/android/tests/performance_hint/Android.bp b/native/android/tests/performance_hint/Android.bp
index fdc1bc6..608d5d8 100644
--- a/native/android/tests/performance_hint/Android.bp
+++ b/native/android/tests/performance_hint/Android.bp
@@ -39,6 +39,7 @@
"libandroid",
"liblog",
"libbinder",
+ "libbinder_ndk",
"libpowermanager",
"libutils",
],
diff --git a/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp b/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp
index 4553b49..bfbe34e 100644
--- a/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp
+++ b/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp
@@ -16,11 +16,11 @@
#define LOG_TAG "PerformanceHintNativeTest"
-#include <android/WorkDuration.h>
-#include <android/os/IHintManager.h>
-#include <android/os/IHintSession.h>
+#include <aidl/android/hardware/power/WorkDuration.h>
+#include <aidl/android/os/IHintManager.h>
+#include <android/binder_manager.h>
+#include <android/binder_status.h>
#include <android/performance_hint.h>
-#include <binder/IBinder.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <performance_hint_private.h>
@@ -28,48 +28,54 @@
#include <memory>
#include <vector>
-using android::binder::Status;
-using android::os::IHintManager;
-using android::os::IHintSession;
+using aidl::android::hardware::power::WorkDuration;
+using aidl::android::os::IHintManager;
+using aidl::android::os::IHintSession;
+using ndk::ScopedAStatus;
+using ndk::SpAIBinder;
using namespace android;
using namespace testing;
class MockIHintManager : public IHintManager {
public:
- MOCK_METHOD(Status, createHintSession,
- (const sp<IBinder>& token, const ::std::vector<int32_t>& tids,
- int64_t durationNanos, ::android::sp<IHintSession>* _aidl_return),
+ MOCK_METHOD(ScopedAStatus, createHintSession,
+ (const SpAIBinder& token, const ::std::vector<int32_t>& tids, int64_t durationNanos,
+ std::shared_ptr<IHintSession>* _aidl_return),
(override));
- MOCK_METHOD(Status, getHintSessionPreferredRate, (int64_t * _aidl_return), (override));
- MOCK_METHOD(Status, setHintSessionThreads,
- (const sp<IHintSession>& hintSession, const ::std::vector<int32_t>& tids),
+ MOCK_METHOD(ScopedAStatus, getHintSessionPreferredRate, (int64_t * _aidl_return), (override));
+ MOCK_METHOD(ScopedAStatus, setHintSessionThreads,
+ (const std::shared_ptr<IHintSession>& hintSession,
+ const ::std::vector<int32_t>& tids),
(override));
- MOCK_METHOD(Status, getHintSessionThreadIds,
- (const sp<IHintSession>& hintSession, ::std::vector<int32_t>* tids), (override));
- MOCK_METHOD(IBinder*, onAsBinder, (), (override));
+ MOCK_METHOD(ScopedAStatus, getHintSessionThreadIds,
+ (const std::shared_ptr<IHintSession>& hintSession, ::std::vector<int32_t>* tids),
+ (override));
+ MOCK_METHOD(SpAIBinder, asBinder, (), (override));
+ MOCK_METHOD(bool, isRemote, (), (override));
};
class MockIHintSession : public IHintSession {
public:
- MOCK_METHOD(Status, updateTargetWorkDuration, (int64_t targetDurationNanos), (override));
- MOCK_METHOD(Status, reportActualWorkDuration,
+ MOCK_METHOD(ScopedAStatus, updateTargetWorkDuration, (int64_t targetDurationNanos), (override));
+ MOCK_METHOD(ScopedAStatus, reportActualWorkDuration,
(const ::std::vector<int64_t>& actualDurationNanos,
const ::std::vector<int64_t>& timeStampNanos),
(override));
- MOCK_METHOD(Status, sendHint, (int32_t hint), (override));
- MOCK_METHOD(Status, setMode, (int32_t mode, bool enabled), (override));
- MOCK_METHOD(Status, close, (), (override));
- MOCK_METHOD(IBinder*, onAsBinder, (), (override));
- MOCK_METHOD(Status, reportActualWorkDuration2,
- (const ::std::vector<android::os::WorkDuration>& workDurations), (override));
+ MOCK_METHOD(ScopedAStatus, sendHint, (int32_t hint), (override));
+ MOCK_METHOD(ScopedAStatus, setMode, (int32_t mode, bool enabled), (override));
+ MOCK_METHOD(ScopedAStatus, close, (), (override));
+ MOCK_METHOD(ScopedAStatus, reportActualWorkDuration2,
+ (const ::std::vector<WorkDuration>& workDurations), (override));
+ MOCK_METHOD(SpAIBinder, asBinder, (), (override));
+ MOCK_METHOD(bool, isRemote, (), (override));
};
class PerformanceHintTest : public Test {
public:
void SetUp() override {
- mMockIHintManager = new StrictMock<MockIHintManager>();
- APerformanceHint_setIHintManagerForTesting(mMockIHintManager);
+ mMockIHintManager = ndk::SharedRefBase::make<NiceMock<MockIHintManager>>();
+ APerformanceHint_setIHintManagerForTesting(&mMockIHintManager);
}
void TearDown() override {
@@ -79,15 +85,50 @@
}
APerformanceHintManager* createManager() {
- EXPECT_CALL(*mMockIHintManager, getHintSessionPreferredRate(_))
- .Times(Exactly(1))
- .WillRepeatedly(DoAll(SetArgPointee<0>(123L), Return(Status())));
+ ON_CALL(*mMockIHintManager, getHintSessionPreferredRate(_))
+ .WillByDefault(DoAll(SetArgPointee<0>(123L), [] { return ScopedAStatus::ok(); }));
return APerformanceHint_getManager();
}
+ APerformanceHintSession* createSession(APerformanceHintManager* manager,
+ int64_t targetDuration = 56789L) {
+ mMockSession = ndk::SharedRefBase::make<NiceMock<MockIHintSession>>();
- StrictMock<MockIHintManager>* mMockIHintManager = nullptr;
+ std::vector<int32_t> tids;
+ tids.push_back(1);
+ tids.push_back(2);
+
+ ON_CALL(*mMockIHintManager, createHintSession(_, Eq(tids), Eq(targetDuration), _))
+ .WillByDefault(DoAll(SetArgPointee<3>(std::shared_ptr<IHintSession>(mMockSession)),
+ [] { return ScopedAStatus::ok(); }));
+ ON_CALL(*mMockIHintManager, setHintSessionThreads(_, _)).WillByDefault([] {
+ return ScopedAStatus::ok();
+ });
+ ON_CALL(*mMockSession, sendHint(_)).WillByDefault([] { return ScopedAStatus::ok(); });
+ ON_CALL(*mMockSession, setMode(_, _)).WillByDefault([] { return ScopedAStatus::ok(); });
+ ON_CALL(*mMockSession, close()).WillByDefault([] { return ScopedAStatus::ok(); });
+ ON_CALL(*mMockSession, updateTargetWorkDuration(_)).WillByDefault([] {
+ return ScopedAStatus::ok();
+ });
+ ON_CALL(*mMockSession, reportActualWorkDuration(_, _)).WillByDefault([] {
+ return ScopedAStatus::ok();
+ });
+ ON_CALL(*mMockSession, reportActualWorkDuration2(_)).WillByDefault([] {
+ return ScopedAStatus::ok();
+ });
+
+ return APerformanceHint_createSession(manager, tids.data(), tids.size(), targetDuration);
+ }
+
+ std::shared_ptr<NiceMock<MockIHintManager>> mMockIHintManager = nullptr;
+ std::shared_ptr<NiceMock<MockIHintSession>> mMockSession = nullptr;
};
+bool equalsWithoutTimestamp(WorkDuration lhs, WorkDuration rhs) {
+ return lhs.workPeriodStartTimestampNanos == rhs.workPeriodStartTimestampNanos &&
+ lhs.cpuDurationNanos == rhs.cpuDurationNanos &&
+ lhs.gpuDurationNanos == rhs.gpuDurationNanos && lhs.durationNanos == rhs.durationNanos;
+}
+
TEST_F(PerformanceHintTest, TestGetPreferredUpdateRateNanos) {
APerformanceHintManager* manager = createManager();
int64_t preferredUpdateRateNanos = APerformanceHint_getPreferredUpdateRateNanos(manager);
@@ -96,25 +137,11 @@
TEST_F(PerformanceHintTest, TestSession) {
APerformanceHintManager* manager = createManager();
-
- std::vector<int32_t> tids;
- tids.push_back(1);
- tids.push_back(2);
- int64_t targetDuration = 56789L;
-
- StrictMock<MockIHintSession>* iSession = new StrictMock<MockIHintSession>();
- sp<IHintSession> session_sp(iSession);
-
- EXPECT_CALL(*mMockIHintManager, createHintSession(_, Eq(tids), Eq(targetDuration), _))
- .Times(Exactly(1))
- .WillRepeatedly(DoAll(SetArgPointee<3>(std::move(session_sp)), Return(Status())));
-
- APerformanceHintSession* session =
- APerformanceHint_createSession(manager, tids.data(), tids.size(), targetDuration);
+ APerformanceHintSession* session = createSession(manager);
ASSERT_TRUE(session);
int64_t targetDurationNanos = 10;
- EXPECT_CALL(*iSession, updateTargetWorkDuration(Eq(targetDurationNanos))).Times(Exactly(1));
+ EXPECT_CALL(*mMockSession, updateTargetWorkDuration(Eq(targetDurationNanos))).Times(Exactly(1));
int result = APerformanceHint_updateTargetWorkDuration(session, targetDurationNanos);
EXPECT_EQ(0, result);
@@ -122,8 +149,7 @@
int64_t actualDurationNanos = 20;
std::vector<int64_t> actualDurations;
actualDurations.push_back(20);
- EXPECT_CALL(*iSession, reportActualWorkDuration(Eq(actualDurations), _)).Times(Exactly(1));
- EXPECT_CALL(*iSession, reportActualWorkDuration2(_)).Times(Exactly(1));
+ EXPECT_CALL(*mMockSession, reportActualWorkDuration2(_)).Times(Exactly(1));
result = APerformanceHint_reportActualWorkDuration(session, actualDurationNanos);
EXPECT_EQ(0, result);
@@ -133,114 +159,70 @@
EXPECT_EQ(EINVAL, result);
SessionHint hintId = SessionHint::CPU_LOAD_RESET;
- EXPECT_CALL(*iSession, sendHint(Eq(hintId))).Times(Exactly(1));
+ EXPECT_CALL(*mMockSession, sendHint(Eq(hintId))).Times(Exactly(1));
result = APerformanceHint_sendHint(session, hintId);
EXPECT_EQ(0, result);
usleep(110000); // Sleep for longer than the update timeout.
- EXPECT_CALL(*iSession, sendHint(Eq(hintId))).Times(Exactly(1));
+ EXPECT_CALL(*mMockSession, sendHint(Eq(hintId))).Times(Exactly(1));
result = APerformanceHint_sendHint(session, hintId);
EXPECT_EQ(0, result);
// Expect to get rate limited if we try to send faster than the limiter allows
- EXPECT_CALL(*iSession, sendHint(Eq(hintId))).Times(Exactly(0));
+ EXPECT_CALL(*mMockSession, sendHint(Eq(hintId))).Times(Exactly(0));
result = APerformanceHint_sendHint(session, hintId);
EXPECT_EQ(0, result);
result = APerformanceHint_sendHint(session, static_cast<SessionHint>(-1));
EXPECT_EQ(EINVAL, result);
- EXPECT_CALL(*iSession, close()).Times(Exactly(1));
+ EXPECT_CALL(*mMockSession, close()).Times(Exactly(1));
APerformanceHint_closeSession(session);
}
TEST_F(PerformanceHintTest, SetThreads) {
APerformanceHintManager* manager = createManager();
- std::vector<int32_t> tids;
- tids.push_back(1);
- tids.push_back(2);
- int64_t targetDuration = 56789L;
-
- StrictMock<MockIHintSession>* iSession = new StrictMock<MockIHintSession>();
- sp<IHintSession> session_sp(iSession);
-
- EXPECT_CALL(*mMockIHintManager, createHintSession(_, Eq(tids), Eq(targetDuration), _))
- .Times(Exactly(1))
- .WillRepeatedly(DoAll(SetArgPointee<3>(std::move(session_sp)), Return(Status())));
-
- APerformanceHintSession* session =
- APerformanceHint_createSession(manager, tids.data(), tids.size(), targetDuration);
+ APerformanceHintSession* session = createSession(manager);
ASSERT_TRUE(session);
- std::vector<int32_t> emptyTids;
- int result = APerformanceHint_setThreads(session, emptyTids.data(), emptyTids.size());
+ int32_t emptyTids[2];
+ int result = APerformanceHint_setThreads(session, emptyTids, 0);
EXPECT_EQ(EINVAL, result);
std::vector<int32_t> newTids;
newTids.push_back(1);
newTids.push_back(3);
- EXPECT_CALL(*mMockIHintManager, setHintSessionThreads(_, Eq(newTids)))
- .Times(Exactly(1))
- .WillOnce(Return(Status()));
+ EXPECT_CALL(*mMockIHintManager, setHintSessionThreads(_, Eq(newTids))).Times(Exactly(1));
result = APerformanceHint_setThreads(session, newTids.data(), newTids.size());
EXPECT_EQ(0, result);
- testing::Mock::VerifyAndClearExpectations(mMockIHintManager);
+ testing::Mock::VerifyAndClearExpectations(mMockIHintManager.get());
std::vector<int32_t> invalidTids;
- auto status = Status::fromExceptionCode(binder::Status::Exception::EX_SECURITY);
invalidTids.push_back(4);
invalidTids.push_back(6);
EXPECT_CALL(*mMockIHintManager, setHintSessionThreads(_, Eq(invalidTids)))
.Times(Exactly(1))
- .WillOnce(Return(status));
+ .WillOnce(Return(ByMove(ScopedAStatus::fromExceptionCode(EX_SECURITY))));
result = APerformanceHint_setThreads(session, invalidTids.data(), invalidTids.size());
EXPECT_EQ(EPERM, result);
}
TEST_F(PerformanceHintTest, SetPowerEfficient) {
APerformanceHintManager* manager = createManager();
-
- std::vector<int32_t> tids;
- tids.push_back(1);
- tids.push_back(2);
- int64_t targetDuration = 56789L;
-
- StrictMock<MockIHintSession>* iSession = new StrictMock<MockIHintSession>();
- sp<IHintSession> session_sp(iSession);
-
- EXPECT_CALL(*mMockIHintManager, createHintSession(_, Eq(tids), Eq(targetDuration), _))
- .Times(Exactly(1))
- .WillRepeatedly(DoAll(SetArgPointee<3>(std::move(session_sp)), Return(Status())));
-
- APerformanceHintSession* session =
- APerformanceHint_createSession(manager, tids.data(), tids.size(), targetDuration);
+ APerformanceHintSession* session = createSession(manager);
ASSERT_TRUE(session);
- EXPECT_CALL(*iSession, setMode(_, Eq(true))).Times(Exactly(1));
+ EXPECT_CALL(*mMockSession, setMode(_, Eq(true))).Times(Exactly(1));
int result = APerformanceHint_setPreferPowerEfficiency(session, true);
EXPECT_EQ(0, result);
- EXPECT_CALL(*iSession, setMode(_, Eq(false))).Times(Exactly(1));
+ EXPECT_CALL(*mMockSession, setMode(_, Eq(false))).Times(Exactly(1));
result = APerformanceHint_setPreferPowerEfficiency(session, false);
EXPECT_EQ(0, result);
}
TEST_F(PerformanceHintTest, CreateZeroTargetDurationSession) {
APerformanceHintManager* manager = createManager();
-
- std::vector<int32_t> tids;
- tids.push_back(1);
- tids.push_back(2);
- int64_t targetDuration = 0;
-
- StrictMock<MockIHintSession>* iSession = new StrictMock<MockIHintSession>();
- sp<IHintSession> session_sp(iSession);
-
- EXPECT_CALL(*mMockIHintManager, createHintSession(_, Eq(tids), Eq(targetDuration), _))
- .Times(Exactly(1))
- .WillRepeatedly(DoAll(SetArgPointee<3>(std::move(session_sp)), Return(Status())));
-
- APerformanceHintSession* session =
- APerformanceHint_createSession(manager, tids.data(), tids.size(), targetDuration);
+ APerformanceHintSession* session = createSession(manager, 0);
ASSERT_TRUE(session);
}
@@ -251,12 +233,12 @@
return false;
}
for (int i = 0; i < expected.size(); ++i) {
- android::os::WorkDuration expectedWorkDuration = expected[i];
- android::os::WorkDuration actualWorkDuration = arg[i];
- if (!expectedWorkDuration.equalsWithoutTimestamp(actualWorkDuration)) {
+ WorkDuration expectedWorkDuration = expected[i];
+ WorkDuration actualWorkDuration = arg[i];
+ if (!equalsWithoutTimestamp(expectedWorkDuration, actualWorkDuration)) {
*result_listener << "WorkDuration at [" << i << "] is different: "
- << "Expected: " << expectedWorkDuration
- << ", Actual: " << actualWorkDuration;
+ << "Expected: " << expectedWorkDuration.toString()
+ << ", Actual: " << actualWorkDuration.toString();
return false;
}
}
@@ -265,92 +247,37 @@
TEST_F(PerformanceHintTest, TestAPerformanceHint_reportActualWorkDuration2) {
APerformanceHintManager* manager = createManager();
-
- std::vector<int32_t> tids;
- tids.push_back(1);
- tids.push_back(2);
- int64_t targetDuration = 56789L;
-
- StrictMock<MockIHintSession>* iSession = new StrictMock<MockIHintSession>();
- sp<IHintSession> session_sp(iSession);
-
- EXPECT_CALL(*mMockIHintManager, createHintSession(_, Eq(tids), Eq(targetDuration), _))
- .Times(Exactly(1))
- .WillRepeatedly(DoAll(SetArgPointee<3>(std::move(session_sp)), Return(Status())));
-
- APerformanceHintSession* session =
- APerformanceHint_createSession(manager, tids.data(), tids.size(), targetDuration);
+ APerformanceHintSession* session = createSession(manager);
ASSERT_TRUE(session);
int64_t targetDurationNanos = 10;
- EXPECT_CALL(*iSession, updateTargetWorkDuration(Eq(targetDurationNanos))).Times(Exactly(1));
+ EXPECT_CALL(*mMockSession, updateTargetWorkDuration(Eq(targetDurationNanos))).Times(Exactly(1));
int result = APerformanceHint_updateTargetWorkDuration(session, targetDurationNanos);
EXPECT_EQ(0, result);
usleep(2); // Sleep for longer than preferredUpdateRateNanos.
- {
- std::vector<android::os::WorkDuration> actualWorkDurations;
- android::os::WorkDuration workDuration(1, 20, 13, 8);
- actualWorkDurations.push_back(workDuration);
+ struct TestPair {
+ WorkDuration duration;
+ int expectedResult;
+ };
+ std::vector<TestPair> testPairs{
+ {{1, 20, 1, 13, 8}, OK}, {{1, -20, 1, 13, 8}, EINVAL},
+ {{1, 20, -1, 13, 8}, EINVAL}, {{1, -20, 1, -13, 8}, EINVAL},
+ {{1, -20, 1, 13, -8}, EINVAL},
+ };
+ for (auto&& pair : testPairs) {
+ std::vector<WorkDuration> actualWorkDurations;
+ actualWorkDurations.push_back(pair.duration);
- EXPECT_CALL(*iSession, reportActualWorkDuration2(WorkDurationEq(actualWorkDurations)))
+ EXPECT_CALL(*mMockSession, reportActualWorkDuration2(WorkDurationEq(actualWorkDurations)))
.Times(Exactly(1));
result = APerformanceHint_reportActualWorkDuration2(session,
- static_cast<AWorkDuration*>(
- &workDuration));
- EXPECT_EQ(0, result);
+ reinterpret_cast<AWorkDuration*>(
+ &pair.duration));
+ EXPECT_EQ(pair.expectedResult, result);
}
- {
- std::vector<android::os::WorkDuration> actualWorkDurations;
- android::os::WorkDuration workDuration(-1, 20, 13, 8);
- actualWorkDurations.push_back(workDuration);
-
- EXPECT_CALL(*iSession, reportActualWorkDuration2(WorkDurationEq(actualWorkDurations)))
- .Times(Exactly(1));
- result = APerformanceHint_reportActualWorkDuration2(session,
- static_cast<AWorkDuration*>(
- &workDuration));
- EXPECT_EQ(22, result);
- }
- {
- std::vector<android::os::WorkDuration> actualWorkDurations;
- android::os::WorkDuration workDuration(1, -20, 13, 8);
- actualWorkDurations.push_back(workDuration);
-
- EXPECT_CALL(*iSession, reportActualWorkDuration2(WorkDurationEq(actualWorkDurations)))
- .Times(Exactly(1));
- result = APerformanceHint_reportActualWorkDuration2(session,
- static_cast<AWorkDuration*>(
- &workDuration));
- EXPECT_EQ(22, result);
- }
- {
- std::vector<android::os::WorkDuration> actualWorkDurations;
- android::os::WorkDuration workDuration(1, 20, -13, 8);
- actualWorkDurations.push_back(workDuration);
-
- EXPECT_CALL(*iSession, reportActualWorkDuration2(WorkDurationEq(actualWorkDurations)))
- .Times(Exactly(1));
- result = APerformanceHint_reportActualWorkDuration2(session,
- static_cast<AWorkDuration*>(
- &workDuration));
- EXPECT_EQ(EINVAL, result);
- }
- {
- std::vector<android::os::WorkDuration> actualWorkDurations;
- android::os::WorkDuration workDuration(1, 20, 13, -8);
- actualWorkDurations.push_back(workDuration);
-
- EXPECT_CALL(*iSession, reportActualWorkDuration2(WorkDurationEq(actualWorkDurations)))
- .Times(Exactly(1));
- result = APerformanceHint_reportActualWorkDuration2(session,
- static_cast<AWorkDuration*>(
- &workDuration));
- EXPECT_EQ(EINVAL, result);
- }
-
- EXPECT_CALL(*iSession, close()).Times(Exactly(1));
+ EXPECT_CALL(*mMockSession, close()).Times(Exactly(1));
APerformanceHint_closeSession(session);
}