diff options
3 files changed, 73 insertions, 17 deletions
diff --git a/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp b/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp index 05f488b64b..cbafdd337d 100644 --- a/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp +++ b/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp @@ -463,29 +463,41 @@ void AidlPowerHalWrapper::sendActualWorkDuration(int64_t actualDurationNanos, ALOGV("Failed to send actual work duration, skipping"); return; } - - WorkDuration duration; - duration.durationNanos = actualDurationNanos; - mActualDuration = actualDurationNanos; + nsecs_t reportedDuration = actualDurationNanos; // normalize the sent values to a pre-set target if (sNormalizeTarget) { - duration.durationNanos += mLastTargetDurationSent - mTargetDuration; + reportedDuration += mLastTargetDurationSent - mTargetDuration; + } else { + // when target duration change is within deviation and not updated, adjust the actual + // duration proportionally based on the difference, e.g. if new target is 5ms longer than + // last reported but actual duration is the same as last target, we want to report a smaller + // actual work duration now to indicate that we are overshooting + if (mLastTargetDurationSent != kDefaultTarget.count() && mTargetDuration != 0) { + reportedDuration = + static_cast<int64_t>(static_cast<long double>(mLastTargetDurationSent) / + mTargetDuration * actualDurationNanos); + mActualDuration = reportedDuration; + } } + mActualDuration = reportedDuration; + WorkDuration duration; + duration.durationNanos = reportedDuration; duration.timeStampNanos = timeStampNanos; mPowerHintQueue.push_back(duration); - nsecs_t targetNsec = mTargetDuration; - nsecs_t durationNsec = actualDurationNanos; - if (sTraceHintSessionData) { - ATRACE_INT64("Measured duration", durationNsec); - ATRACE_INT64("Target error term", targetNsec - durationNsec); + ATRACE_INT64("Measured duration", actualDurationNanos); + ATRACE_INT64("Target error term", mTargetDuration - actualDurationNanos); + + ATRACE_INT64("Reported duration", reportedDuration); + ATRACE_INT64("Reported target", mLastTargetDurationSent); + ATRACE_INT64("Reported target error term", mLastTargetDurationSent - reportedDuration); } - ALOGV("Sending actual work duration of: %" PRId64 " on target: %" PRId64 + ALOGV("Sending actual work duration of: %" PRId64 " on reported target: %" PRId64 " with error: %" PRId64, - durationNsec, targetNsec, targetNsec - durationNsec); + reportedDuration, mLastTargetDurationSent, mLastTargetDurationSent - reportedDuration); // This rate limiter queues similar duration reports to the powerhal into // batches to avoid excessive binder calls. The criteria to send a given batch @@ -501,7 +513,7 @@ void AidlPowerHalWrapper::sendActualWorkDuration(int64_t actualDurationNanos, } mPowerHintQueue.clear(); // we save the non-normalized value here to detect % changes - mLastActualDurationSent = actualDurationNanos; + mLastActualDurationSent = reportedDuration; } } diff --git a/services/surfaceflinger/DisplayHardware/PowerAdvisor.h b/services/surfaceflinger/DisplayHardware/PowerAdvisor.h index 3f47ffdd53..61bb32b8bd 100644 --- a/services/surfaceflinger/DisplayHardware/PowerAdvisor.h +++ b/services/surfaceflinger/DisplayHardware/PowerAdvisor.h @@ -173,8 +173,8 @@ private: // Max percent the actual duration can vary without causing a report (eg: 0.1 = 10%) static constexpr double kAllowedActualDeviationPercent = 0.1; - // Max percent the target duration can vary without causing a report (eg: 0.05 = 5%) - static constexpr double kAllowedTargetDeviationPercent = 0.05; + // Max percent the target duration can vary without causing a report (eg: 0.1 = 10%) + static constexpr double kAllowedTargetDeviationPercent = 0.1; // Target used for init and normalization, the actual value does not really matter static constexpr const std::chrono::nanoseconds kDefaultTarget = 50ms; // Amount of time after the last message was sent before the session goes stale diff --git a/services/surfaceflinger/tests/unittests/AidlPowerHalWrapperTest.cpp b/services/surfaceflinger/tests/unittests/AidlPowerHalWrapperTest.cpp index e25a0aea24..9ab35d741a 100644 --- a/services/surfaceflinger/tests/unittests/AidlPowerHalWrapperTest.cpp +++ b/services/surfaceflinger/tests/unittests/AidlPowerHalWrapperTest.cpp @@ -17,6 +17,7 @@ #undef LOG_TAG #define LOG_TAG "AidlPowerHalWrapperTest" +#include <android-base/stringprintf.h> #include <android/hardware/power/IPower.h> #include <android/hardware/power/IPowerHintSession.h> #include <gmock/gmock.h> @@ -82,6 +83,15 @@ WorkDuration toWorkDuration(std::chrono::nanoseconds durationNanos, int64_t time return duration; } +std::string printWorkDurations(const ::std::vector<WorkDuration>& durations) { + std::ostringstream os; + for (auto duration : durations) { + os << duration.toString(); + os << "\n"; + } + return os.str(); +} + namespace { TEST_F(AidlPowerHalWrapperTest, supportsPowerHintSession) { ASSERT_TRUE(mWrapper->supportsPowerHintSession()); @@ -143,8 +153,8 @@ TEST_F(AidlPowerHalWrapperTest, setTargetWorkDuration) { {-1ms, false}, {200ms, true}, {2ms, true}, - {96ms, false}, - {104ms, false}}; + {91ms, false}, + {109ms, false}}; for (const auto& test : testCases) { // reset to 100ms baseline @@ -212,6 +222,40 @@ TEST_F(AidlPowerHalWrapperTest, sendActualWorkDuration) { } } +TEST_F(AidlPowerHalWrapperTest, sendAdjustedActualWorkDuration) { + ASSERT_TRUE(mWrapper->supportsPowerHintSession()); + + std::vector<int32_t> threadIds = {1, 2}; + mWrapper->setPowerHintSessionThreadIds(threadIds); + EXPECT_CALL(*mMockHal.get(), createHintSession(_, _, threadIds, _, _)) + .WillOnce(DoAll(SetArgPointee<4>(mMockSession), Return(Status::ok()))); + ASSERT_TRUE(mWrapper->startPowerHintSession()); + verifyAndClearExpectations(); + + std::chrono::nanoseconds lastTarget = 100ms; + EXPECT_CALL(*mMockSession.get(), updateTargetWorkDuration(lastTarget.count())).Times(1); + mWrapper->setTargetWorkDuration(lastTarget.count()); + std::chrono::nanoseconds newTarget = 105ms; + mWrapper->setTargetWorkDuration(newTarget.count()); + EXPECT_CALL(*mMockSession.get(), updateTargetWorkDuration(newTarget.count())).Times(0); + std::chrono::nanoseconds actual = 21ms; + // 100 / 105 * 21ms = 20ms + std::chrono::nanoseconds expectedActualSent = 20ms; + std::vector<WorkDuration> expectedDurations = {toWorkDuration(expectedActualSent, 1)}; + + EXPECT_CALL(*mMockSession.get(), reportActualWorkDuration(_)) + .WillOnce(DoAll( + [expectedDurations](const ::std::vector<WorkDuration>& durationsSent) { + EXPECT_EQ(expectedDurations, durationsSent) + << base::StringPrintf("actual sent: %s vs expected: %s", + printWorkDurations(durationsSent).c_str(), + printWorkDurations(expectedDurations) + .c_str()); + }, + Return(Status::ok()))); + mWrapper->sendActualWorkDuration(actual.count(), 1); +} + TEST_F(AidlPowerHalWrapperTest, sendActualWorkDuration_exceedsStaleTime) { ASSERT_TRUE(mWrapper->supportsPowerHintSession()); |