Loading services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp +6 −37 Original line number Diff line number Diff line Loading @@ -640,9 +640,6 @@ AidlPowerHalWrapper::AidlPowerHalWrapper(sp<IPower> powerHal) : mPowerHal(std::m } mSupportsPowerHint = checkPowerHintSessionSupported(); // Currently set to 0 to disable rate limiter by default mAllowedActualDeviation = base::GetIntProperty<nsecs_t>("debug.sf.allowed_actual_deviation", 0); } AidlPowerHalWrapper::~AidlPowerHalWrapper() { Loading Loading @@ -758,21 +755,6 @@ void AidlPowerHalWrapper::setTargetWorkDuration(int64_t targetDuration) { } } bool AidlPowerHalWrapper::shouldReportActualDurations() { // Report if we have never reported before or will go stale next frame if (!mLastActualDurationSent.has_value() || (mLastTargetDurationSent + systemTime() - mLastActualReportTimestamp) > kStaleTimeout.count()) { return true; } if (!mActualDuration.has_value()) { return false; } // Report if the change in actual duration exceeds the threshold return abs(*mActualDuration - *mLastActualDurationSent) > mAllowedActualDeviation; } void AidlPowerHalWrapper::sendActualWorkDuration(int64_t actualDuration, nsecs_t timestamp) { ATRACE_CALL(); Loading Loading @@ -801,12 +783,6 @@ void AidlPowerHalWrapper::sendActualWorkDuration(int64_t actualDuration, nsecs_t " with error: %" PRId64, reportedDuration, mLastTargetDurationSent, reportedDuration - mLastTargetDurationSent); // This rate limiter queues similar duration reports to the powerhal into // batches to avoid excessive binder calls. The criteria to send a given batch // are outlined in shouldReportActualDurationsNow() if (shouldReportActualDurations()) { ALOGV("Sending hint update batch"); mLastActualReportTimestamp = systemTime(); auto ret = mPowerHintSession->reportActualWorkDuration(mPowerHintQueue); if (!ret.isOk()) { ALOGW("Failed to report actual work durations with error: %s", Loading @@ -814,9 +790,6 @@ void AidlPowerHalWrapper::sendActualWorkDuration(int64_t actualDuration, nsecs_t mShouldReconnectHal = true; } mPowerHintQueue.clear(); // We save the actual duration here for rate limiting mLastActualDurationSent = actualDuration; } } bool AidlPowerHalWrapper::shouldReconnectHAL() { Loading @@ -831,10 +804,6 @@ std::optional<int64_t> AidlPowerHalWrapper::getTargetWorkDuration() { return mTargetDuration; } void AidlPowerHalWrapper::setAllowedActualDeviation(nsecs_t allowedDeviation) { mAllowedActualDeviation = allowedDeviation; } const bool AidlPowerHalWrapper::sTraceHintSessionData = base::GetBoolProperty(std::string("debug.sf.trace_hint_sessions"), false); Loading services/surfaceflinger/DisplayHardware/PowerAdvisor.h +0 −13 Original line number Diff line number Diff line Loading @@ -305,10 +305,6 @@ private: bool checkPowerHintSessionSupported(); void closePowerHintSession(); bool shouldReportActualDurations(); // Used for testing void setAllowedActualDeviation(nsecs_t); const sp<hardware::power::IPower> mPowerHal = nullptr; bool mHasExpensiveRendering = false; Loading @@ -328,19 +324,10 @@ private: // The list of thread ids, stored so we can restart the session from this class if needed std::vector<int32_t> mPowerHintThreadIds; bool mSupportsPowerHint = false; // Keep track of the last messages sent for rate limiter change detection std::optional<nsecs_t> mLastActualDurationSent; // Timestamp of the last report we sent, used to avoid stale sessions nsecs_t mLastActualReportTimestamp = 0; nsecs_t mLastTargetDurationSent = kDefaultTarget.count(); // Max amount the error term can vary without causing an actual value report nsecs_t mAllowedActualDeviation = -1; // Whether we should emit ATRACE_INT data for hint sessions static const bool sTraceHintSessionData; static constexpr const std::chrono::nanoseconds kDefaultTarget = 16ms; // Amount of time after the last message was sent before the session goes stale // actually 100ms but we use 80 here to give some slack static constexpr const std::chrono::nanoseconds kStaleTimeout = 80ms; }; } // namespace impl Loading services/surfaceflinger/tests/unittests/AidlPowerHalWrapperTest.cpp +12 −55 Original line number Diff line number Diff line Loading @@ -50,10 +50,8 @@ protected: sp<NiceMock<MockIPower>> mMockHal = nullptr; sp<NiceMock<MockIPowerHintSession>> mMockSession = nullptr; void verifyAndClearExpectations(); void sendActualWorkDurationGroup(std::vector<WorkDuration> durations, std::chrono::nanoseconds sleepBeforeLastSend); std::chrono::nanoseconds mAllowedDeviation; std::chrono::nanoseconds mStaleTimeout; void sendActualWorkDurationGroup(std::vector<WorkDuration> durations); static constexpr std::chrono::duration kStaleTimeout = 100ms; }; void AidlPowerHalWrapperTest::SetUp() { Loading @@ -61,9 +59,6 @@ void AidlPowerHalWrapperTest::SetUp() { mMockSession = sp<NiceMock<MockIPowerHintSession>>::make(); ON_CALL(*mMockHal.get(), getHintSessionPreferredRate(_)).WillByDefault(Return(Status::ok())); mWrapper = std::make_unique<AidlPowerHalWrapper>(mMockHal); mWrapper->setAllowedActualDeviation(std::chrono::nanoseconds{10ms}.count()); mAllowedDeviation = std::chrono::nanoseconds{mWrapper->mAllowedActualDeviation}; mStaleTimeout = AidlPowerHalWrapper::kStaleTimeout; } void AidlPowerHalWrapperTest::verifyAndClearExpectations() { Loading @@ -71,12 +66,8 @@ void AidlPowerHalWrapperTest::verifyAndClearExpectations() { Mock::VerifyAndClearExpectations(mMockSession.get()); } void AidlPowerHalWrapperTest::sendActualWorkDurationGroup( std::vector<WorkDuration> durations, std::chrono::nanoseconds sleepBeforeLastSend) { void AidlPowerHalWrapperTest::sendActualWorkDurationGroup(std::vector<WorkDuration> durations) { for (size_t i = 0; i < durations.size(); i++) { if (i == durations.size() - 1) { std::this_thread::sleep_for(sleepBeforeLastSend); } auto duration = durations[i]; mWrapper->sendActualWorkDuration(duration.durationNanos, duration.timeStampNanos); } Loading Loading @@ -206,58 +197,24 @@ TEST_F(AidlPowerHalWrapperTest, sendActualWorkDuration) { // 100ms const std::vector<std::pair<std::vector<std::pair<std::chrono::nanoseconds, nsecs_t>>, bool>> testCases = {{{{-1ms, 100}}, false}, {{{100ms - (mAllowedDeviation / 2), 100}}, false}, {{{100ms + (mAllowedDeviation / 2), 100}}, false}, {{{100ms + (mAllowedDeviation + 1ms), 100}}, true}, {{{100ms - (mAllowedDeviation + 1ms), 100}}, true}, {{{50ms, 100}}, true}, {{{100ms, 100}, {200ms, 200}}, true}, {{{100ms, 500}, {100ms, 600}, {3ms, 600}}, true}}; for (const auto& test : testCases) { // reset actual duration sendActualWorkDurationGroup({base}, mStaleTimeout); sendActualWorkDurationGroup({base}); auto raw = test.first; std::vector<WorkDuration> durations(raw.size()); std::transform(raw.begin(), raw.end(), durations.begin(), [](auto d) { return toWorkDuration(d); }); EXPECT_CALL(*mMockSession.get(), reportActualWorkDuration(durations)) for (auto& duration : durations) { EXPECT_CALL(*mMockSession.get(), reportActualWorkDuration(std::vector<WorkDuration>{duration})) .Times(test.second ? 1 : 0); sendActualWorkDurationGroup(durations, 0ms); verifyAndClearExpectations(); } } TEST_F(AidlPowerHalWrapperTest, sendActualWorkDuration_exceedsStaleTime) { 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(); auto base = toWorkDuration(100ms, 0); // test cases with actual work durations and whether it should update hint against baseline // 100ms const std::vector<std::tuple<std::vector<std::pair<std::chrono::nanoseconds, nsecs_t>>, std::chrono::nanoseconds, bool>> testCases = {{{{100ms, 100}}, mStaleTimeout, true}, {{{100ms + (mAllowedDeviation / 2), 100}}, mStaleTimeout, true}, {{{100ms, 100}}, mStaleTimeout / 2, false}}; for (const auto& test : testCases) { // reset actual duration sendActualWorkDurationGroup({base}, mStaleTimeout); auto raw = std::get<0>(test); std::vector<WorkDuration> durations(raw.size()); std::transform(raw.begin(), raw.end(), durations.begin(), [](auto d) { return toWorkDuration(d); }); EXPECT_CALL(*mMockSession.get(), reportActualWorkDuration(durations)) .Times(std::get<2>(test) ? 1 : 0); sendActualWorkDurationGroup(durations, std::get<1>(test)); sendActualWorkDurationGroup(durations); verifyAndClearExpectations(); } } Loading @@ -275,7 +232,7 @@ TEST_F(AidlPowerHalWrapperTest, sendActualWorkDuration_shouldReconnectOnError) { duration.durationNanos = 1; EXPECT_CALL(*mMockSession.get(), reportActualWorkDuration(_)) .WillOnce(Return(Status::fromExceptionCode(Status::Exception::EX_ILLEGAL_STATE))); sendActualWorkDurationGroup({duration}, 0ms); sendActualWorkDurationGroup({duration}); EXPECT_TRUE(mWrapper->shouldReconnectHAL()); } Loading Loading
services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp +6 −37 Original line number Diff line number Diff line Loading @@ -640,9 +640,6 @@ AidlPowerHalWrapper::AidlPowerHalWrapper(sp<IPower> powerHal) : mPowerHal(std::m } mSupportsPowerHint = checkPowerHintSessionSupported(); // Currently set to 0 to disable rate limiter by default mAllowedActualDeviation = base::GetIntProperty<nsecs_t>("debug.sf.allowed_actual_deviation", 0); } AidlPowerHalWrapper::~AidlPowerHalWrapper() { Loading Loading @@ -758,21 +755,6 @@ void AidlPowerHalWrapper::setTargetWorkDuration(int64_t targetDuration) { } } bool AidlPowerHalWrapper::shouldReportActualDurations() { // Report if we have never reported before or will go stale next frame if (!mLastActualDurationSent.has_value() || (mLastTargetDurationSent + systemTime() - mLastActualReportTimestamp) > kStaleTimeout.count()) { return true; } if (!mActualDuration.has_value()) { return false; } // Report if the change in actual duration exceeds the threshold return abs(*mActualDuration - *mLastActualDurationSent) > mAllowedActualDeviation; } void AidlPowerHalWrapper::sendActualWorkDuration(int64_t actualDuration, nsecs_t timestamp) { ATRACE_CALL(); Loading Loading @@ -801,12 +783,6 @@ void AidlPowerHalWrapper::sendActualWorkDuration(int64_t actualDuration, nsecs_t " with error: %" PRId64, reportedDuration, mLastTargetDurationSent, reportedDuration - mLastTargetDurationSent); // This rate limiter queues similar duration reports to the powerhal into // batches to avoid excessive binder calls. The criteria to send a given batch // are outlined in shouldReportActualDurationsNow() if (shouldReportActualDurations()) { ALOGV("Sending hint update batch"); mLastActualReportTimestamp = systemTime(); auto ret = mPowerHintSession->reportActualWorkDuration(mPowerHintQueue); if (!ret.isOk()) { ALOGW("Failed to report actual work durations with error: %s", Loading @@ -814,9 +790,6 @@ void AidlPowerHalWrapper::sendActualWorkDuration(int64_t actualDuration, nsecs_t mShouldReconnectHal = true; } mPowerHintQueue.clear(); // We save the actual duration here for rate limiting mLastActualDurationSent = actualDuration; } } bool AidlPowerHalWrapper::shouldReconnectHAL() { Loading @@ -831,10 +804,6 @@ std::optional<int64_t> AidlPowerHalWrapper::getTargetWorkDuration() { return mTargetDuration; } void AidlPowerHalWrapper::setAllowedActualDeviation(nsecs_t allowedDeviation) { mAllowedActualDeviation = allowedDeviation; } const bool AidlPowerHalWrapper::sTraceHintSessionData = base::GetBoolProperty(std::string("debug.sf.trace_hint_sessions"), false); Loading
services/surfaceflinger/DisplayHardware/PowerAdvisor.h +0 −13 Original line number Diff line number Diff line Loading @@ -305,10 +305,6 @@ private: bool checkPowerHintSessionSupported(); void closePowerHintSession(); bool shouldReportActualDurations(); // Used for testing void setAllowedActualDeviation(nsecs_t); const sp<hardware::power::IPower> mPowerHal = nullptr; bool mHasExpensiveRendering = false; Loading @@ -328,19 +324,10 @@ private: // The list of thread ids, stored so we can restart the session from this class if needed std::vector<int32_t> mPowerHintThreadIds; bool mSupportsPowerHint = false; // Keep track of the last messages sent for rate limiter change detection std::optional<nsecs_t> mLastActualDurationSent; // Timestamp of the last report we sent, used to avoid stale sessions nsecs_t mLastActualReportTimestamp = 0; nsecs_t mLastTargetDurationSent = kDefaultTarget.count(); // Max amount the error term can vary without causing an actual value report nsecs_t mAllowedActualDeviation = -1; // Whether we should emit ATRACE_INT data for hint sessions static const bool sTraceHintSessionData; static constexpr const std::chrono::nanoseconds kDefaultTarget = 16ms; // Amount of time after the last message was sent before the session goes stale // actually 100ms but we use 80 here to give some slack static constexpr const std::chrono::nanoseconds kStaleTimeout = 80ms; }; } // namespace impl Loading
services/surfaceflinger/tests/unittests/AidlPowerHalWrapperTest.cpp +12 −55 Original line number Diff line number Diff line Loading @@ -50,10 +50,8 @@ protected: sp<NiceMock<MockIPower>> mMockHal = nullptr; sp<NiceMock<MockIPowerHintSession>> mMockSession = nullptr; void verifyAndClearExpectations(); void sendActualWorkDurationGroup(std::vector<WorkDuration> durations, std::chrono::nanoseconds sleepBeforeLastSend); std::chrono::nanoseconds mAllowedDeviation; std::chrono::nanoseconds mStaleTimeout; void sendActualWorkDurationGroup(std::vector<WorkDuration> durations); static constexpr std::chrono::duration kStaleTimeout = 100ms; }; void AidlPowerHalWrapperTest::SetUp() { Loading @@ -61,9 +59,6 @@ void AidlPowerHalWrapperTest::SetUp() { mMockSession = sp<NiceMock<MockIPowerHintSession>>::make(); ON_CALL(*mMockHal.get(), getHintSessionPreferredRate(_)).WillByDefault(Return(Status::ok())); mWrapper = std::make_unique<AidlPowerHalWrapper>(mMockHal); mWrapper->setAllowedActualDeviation(std::chrono::nanoseconds{10ms}.count()); mAllowedDeviation = std::chrono::nanoseconds{mWrapper->mAllowedActualDeviation}; mStaleTimeout = AidlPowerHalWrapper::kStaleTimeout; } void AidlPowerHalWrapperTest::verifyAndClearExpectations() { Loading @@ -71,12 +66,8 @@ void AidlPowerHalWrapperTest::verifyAndClearExpectations() { Mock::VerifyAndClearExpectations(mMockSession.get()); } void AidlPowerHalWrapperTest::sendActualWorkDurationGroup( std::vector<WorkDuration> durations, std::chrono::nanoseconds sleepBeforeLastSend) { void AidlPowerHalWrapperTest::sendActualWorkDurationGroup(std::vector<WorkDuration> durations) { for (size_t i = 0; i < durations.size(); i++) { if (i == durations.size() - 1) { std::this_thread::sleep_for(sleepBeforeLastSend); } auto duration = durations[i]; mWrapper->sendActualWorkDuration(duration.durationNanos, duration.timeStampNanos); } Loading Loading @@ -206,58 +197,24 @@ TEST_F(AidlPowerHalWrapperTest, sendActualWorkDuration) { // 100ms const std::vector<std::pair<std::vector<std::pair<std::chrono::nanoseconds, nsecs_t>>, bool>> testCases = {{{{-1ms, 100}}, false}, {{{100ms - (mAllowedDeviation / 2), 100}}, false}, {{{100ms + (mAllowedDeviation / 2), 100}}, false}, {{{100ms + (mAllowedDeviation + 1ms), 100}}, true}, {{{100ms - (mAllowedDeviation + 1ms), 100}}, true}, {{{50ms, 100}}, true}, {{{100ms, 100}, {200ms, 200}}, true}, {{{100ms, 500}, {100ms, 600}, {3ms, 600}}, true}}; for (const auto& test : testCases) { // reset actual duration sendActualWorkDurationGroup({base}, mStaleTimeout); sendActualWorkDurationGroup({base}); auto raw = test.first; std::vector<WorkDuration> durations(raw.size()); std::transform(raw.begin(), raw.end(), durations.begin(), [](auto d) { return toWorkDuration(d); }); EXPECT_CALL(*mMockSession.get(), reportActualWorkDuration(durations)) for (auto& duration : durations) { EXPECT_CALL(*mMockSession.get(), reportActualWorkDuration(std::vector<WorkDuration>{duration})) .Times(test.second ? 1 : 0); sendActualWorkDurationGroup(durations, 0ms); verifyAndClearExpectations(); } } TEST_F(AidlPowerHalWrapperTest, sendActualWorkDuration_exceedsStaleTime) { 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(); auto base = toWorkDuration(100ms, 0); // test cases with actual work durations and whether it should update hint against baseline // 100ms const std::vector<std::tuple<std::vector<std::pair<std::chrono::nanoseconds, nsecs_t>>, std::chrono::nanoseconds, bool>> testCases = {{{{100ms, 100}}, mStaleTimeout, true}, {{{100ms + (mAllowedDeviation / 2), 100}}, mStaleTimeout, true}, {{{100ms, 100}}, mStaleTimeout / 2, false}}; for (const auto& test : testCases) { // reset actual duration sendActualWorkDurationGroup({base}, mStaleTimeout); auto raw = std::get<0>(test); std::vector<WorkDuration> durations(raw.size()); std::transform(raw.begin(), raw.end(), durations.begin(), [](auto d) { return toWorkDuration(d); }); EXPECT_CALL(*mMockSession.get(), reportActualWorkDuration(durations)) .Times(std::get<2>(test) ? 1 : 0); sendActualWorkDurationGroup(durations, std::get<1>(test)); sendActualWorkDurationGroup(durations); verifyAndClearExpectations(); } } Loading @@ -275,7 +232,7 @@ TEST_F(AidlPowerHalWrapperTest, sendActualWorkDuration_shouldReconnectOnError) { duration.durationNanos = 1; EXPECT_CALL(*mMockSession.get(), reportActualWorkDuration(_)) .WillOnce(Return(Status::fromExceptionCode(Status::Exception::EX_ILLEGAL_STATE))); sendActualWorkDurationGroup({duration}, 0ms); sendActualWorkDurationGroup({duration}); EXPECT_TRUE(mWrapper->shouldReconnectHAL()); } Loading