From 839fe5b4980502638b69ef909114d84e5833d41f Mon Sep 17 00:00:00 2001 From: Xiang Wang Date: Mon, 4 Apr 2022 17:39:38 +0000 Subject: Add unit test on sending power hints in SurfaceFlinger Bug: b/204322192 Test: atest libsurfaceflinger_unittest:libsurfaceflinger_unittest.SurfaceFlingerPowerHintTest#sendDurationsIncludingHwcWaitTime Change-Id: I0c9ba1abc169ba0b2136663e3937cd93191730ae --- services/surfaceflinger/SurfaceFlinger.cpp | 30 ++-- services/surfaceflinger/SurfaceFlinger.h | 2 +- services/surfaceflinger/tests/unittests/Android.bp | 1 + .../tests/unittests/CompositionTest.cpp | 7 +- .../unittests/SurfaceFlinger_PowerHintTest.cpp | 155 +++++++++++++++++++++ .../tests/unittests/TestableSurfaceFlinger.h | 30 ++-- 6 files changed, 199 insertions(+), 26 deletions(-) create mode 100644 services/surfaceflinger/tests/unittests/SurfaceFlinger_PowerHintTest.cpp diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 7ec8e6fec7..2b3455f775 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -95,6 +95,7 @@ #include #include #include +#include #include #include #include @@ -113,6 +114,7 @@ #include "DisplayHardware/FramebufferSurface.h" #include "DisplayHardware/HWComposer.h" #include "DisplayHardware/Hal.h" +#include "DisplayHardware/PowerAdvisor.h" #include "DisplayHardware/VirtualDisplaySurface.h" #include "DisplayRenderArea.h" #include "EffectLayer.h" @@ -327,7 +329,7 @@ SurfaceFlinger::SurfaceFlinger(Factory& factory, SkipInitializationTag) mTunnelModeEnabledReporter(new TunnelModeEnabledReporter()), mInternalDisplayDensity(getDensityFromProperty("ro.sf.lcd_density", true)), mEmulatedDisplayDensity(getDensityFromProperty("qemu.sf.lcd_density", false)), - mPowerAdvisor(*this), + mPowerAdvisor(std::make_unique(*this)), mWindowInfosListenerInvoker(sp::make(*this)) { ALOGI("Using HWComposer service: %s", mHwcServiceName.c_str()); } @@ -677,16 +679,16 @@ void SurfaceFlinger::bootFinished() { } readPersistentProperties(); - mPowerAdvisor.onBootFinished(); - mPowerAdvisor.enablePowerHint(mFlagManager.use_adpf_cpu_hint()); - if (mPowerAdvisor.usePowerHintSession()) { + mPowerAdvisor->onBootFinished(); + mPowerAdvisor->enablePowerHint(mFlagManager.use_adpf_cpu_hint()); + if (mPowerAdvisor->usePowerHintSession()) { std::optional renderEngineTid = getRenderEngine().getRenderEngineTid(); std::vector tidList; tidList.emplace_back(gettid()); if (renderEngineTid.has_value()) { tidList.emplace_back(*renderEngineTid); } - if (!mPowerAdvisor.startPowerHintSession(tidList)) { + if (!mPowerAdvisor->startPowerHintSession(tidList)) { ALOGW("Cannot start power hint session"); } } @@ -812,7 +814,7 @@ void SurfaceFlinger::init() { // set initial conditions (e.g. unblank default device) initializeDisplays(); - mPowerAdvisor.init(); + mPowerAdvisor->init(); char primeShaderCache[PROPERTY_VALUE_MAX]; property_get("service.sf.prime_shader_cache", primeShaderCache, "1"); @@ -1284,10 +1286,10 @@ void SurfaceFlinger::disableExpensiveRendering() { const char* const whence = __func__; auto future = mScheduler->schedule([=]() FTL_FAKE_GUARD(mStateLock) { ATRACE_NAME(whence); - if (mPowerAdvisor.isUsingExpensiveRendering()) { + if (mPowerAdvisor->isUsingExpensiveRendering()) { for (const auto& [_, display] : mDisplays) { constexpr bool kDisable = false; - mPowerAdvisor.setExpensiveRenderingExpected(display->getId(), kDisable); + mPowerAdvisor->setExpensiveRenderingExpected(display->getId(), kDisable); } } }); @@ -1809,7 +1811,7 @@ void SurfaceFlinger::scheduleCommit(FrameHint hint) { if (hint == FrameHint::kActive) { mScheduler->resetIdleTimer(); } - mPowerAdvisor.notifyDisplayUpdateImminent(); + mPowerAdvisor->notifyDisplayUpdateImminent(); mScheduler->scheduleFrame(); } @@ -1979,7 +1981,7 @@ nsecs_t SurfaceFlinger::calculateExpectedPresentTime(DisplayStatInfo stats) cons bool SurfaceFlinger::commit(nsecs_t frameTime, int64_t vsyncId, nsecs_t expectedVsyncTime) FTL_FAKE_GUARD(kMainThreadContext) { // we set this once at the beginning of commit to ensure consistency throughout the whole frame - mPowerHintSessionData.sessionEnabled = mPowerAdvisor.usePowerHintSession(); + mPowerHintSessionData.sessionEnabled = mPowerAdvisor->usePowerHintSession(); if (mPowerHintSessionData.sessionEnabled) { mPowerHintSessionData.commitStart = systemTime(); } @@ -1998,8 +2000,8 @@ bool SurfaceFlinger::commit(nsecs_t frameTime, int64_t vsyncId, nsecs_t expected mScheduledPresentTime = expectedVsyncTime; if (mPowerHintSessionData.sessionEnabled) { - mPowerAdvisor.setTargetWorkDuration(mExpectedPresentTime - - mPowerHintSessionData.commitStart); + mPowerAdvisor->setTargetWorkDuration(mExpectedPresentTime - + mPowerHintSessionData.commitStart); } const auto vsyncIn = [&] { if (!ATRACE_ENABLED()) return 0.f; @@ -2263,7 +2265,7 @@ void SurfaceFlinger::composite(nsecs_t frameTime, int64_t vsyncId) if (mPowerHintSessionData.sessionEnabled) { const nsecs_t flingerDuration = (mPowerHintSessionData.presentEnd - mPowerHintSessionData.commitStart); - mPowerAdvisor.sendActualWorkDuration(flingerDuration, mPowerHintSessionData.presentEnd); + mPowerAdvisor->sendActualWorkDuration(flingerDuration, mPowerHintSessionData.presentEnd); } } @@ -2918,7 +2920,7 @@ void SurfaceFlinger::processDisplayAdded(const wp& displayToken, builder.setPixels(resolution); builder.setIsSecure(state.isSecure); - builder.setPowerAdvisor(&mPowerAdvisor); + builder.setPowerAdvisor(mPowerAdvisor.get()); builder.setName(state.displayName); auto compositionDisplay = getCompositionEngine().createDisplay(builder.build()); compositionDisplay->setLayerCachingEnabled(mLayerCachingEnabled); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 910c5bb7e3..07da731cb6 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -1383,7 +1383,7 @@ private: sp mInputFlinger; InputWindowCommands mInputWindowCommands; - Hwc2::impl::PowerAdvisor mPowerAdvisor; + std::unique_ptr mPowerAdvisor; void enableRefreshRateOverlay(bool enable) REQUIRES(mStateLock); diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp index cc9d48cfcc..7823363e1e 100644 --- a/services/surfaceflinger/tests/unittests/Android.bp +++ b/services/surfaceflinger/tests/unittests/Android.bp @@ -103,6 +103,7 @@ cc_test { "SurfaceFlinger_HotplugTest.cpp", "SurfaceFlinger_NotifyPowerBoostTest.cpp", "SurfaceFlinger_OnInitializeDisplaysTest.cpp", + "SurfaceFlinger_PowerHintTest.cpp", "SurfaceFlinger_SetDisplayStateTest.cpp", "SurfaceFlinger_SetPowerModeInternalTest.cpp", "SurfaceFlinger_SetupNewDisplayDeviceInternalTest.cpp", diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp index 15c9d199cd..c541b9291f 100644 --- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp +++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp @@ -113,8 +113,9 @@ public: mFlinger.setupTimeStats(std::shared_ptr(mTimeStats)); mComposer = new Hwc2::mock::Composer(); + mPowerAdvisor = new Hwc2::mock::PowerAdvisor(); mFlinger.setupComposer(std::unique_ptr(mComposer)); - + mFlinger.setupPowerAdvisor(std::unique_ptr(mPowerAdvisor)); mFlinger.mutableMaxRenderTargetSize() = 16384; } @@ -188,7 +189,7 @@ public: Hwc2::mock::Composer* mComposer = nullptr; renderengine::mock::RenderEngine* mRenderEngine = new renderengine::mock::RenderEngine(); mock::TimeStats* mTimeStats = new mock::TimeStats(); - Hwc2::mock::PowerAdvisor mPowerAdvisor; + Hwc2::mock::PowerAdvisor* mPowerAdvisor = nullptr; sp mClientTargetAcquireFence = Fence::NO_FENCE; @@ -300,7 +301,7 @@ struct BaseDisplayVariant { .setId(DEFAULT_DISPLAY_ID) .setPixels({DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT}) .setIsSecure(Derived::IS_SECURE) - .setPowerAdvisor(&test->mPowerAdvisor) + .setPowerAdvisor(test->mPowerAdvisor) .setName(std::string("Injected display for ") + test_info->test_case_name() + "." + test_info->name()) .build(); diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_PowerHintTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_PowerHintTest.cpp new file mode 100644 index 0000000000..0a157c4bc1 --- /dev/null +++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_PowerHintTest.cpp @@ -0,0 +1,155 @@ +/* + * Copyright 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#undef LOG_TAG +#define LOG_TAG "SurfaceFlingerPowerHintTest" + +#include +#include +#include +#include +#include +#include +#include +#include +#include "TestableSurfaceFlinger.h" +#include "mock/DisplayHardware/MockComposer.h" +#include "mock/DisplayHardware/MockPowerAdvisor.h" +#include "mock/MockEventThread.h" +#include "mock/MockTimeStats.h" +#include "mock/MockVsyncController.h" +#include "mock/system/window/MockNativeWindow.h" + +using namespace android; +using namespace android::Hwc2::mock; +using namespace android::hardware::power; +using namespace std::chrono_literals; +using namespace testing; + +namespace android { +namespace { +using FakeHwcDisplayInjector = TestableSurfaceFlinger::FakeHwcDisplayInjector; +using FakeDisplayDeviceInjector = TestableSurfaceFlinger::FakeDisplayDeviceInjector; + +constexpr hal::HWDisplayId HWC_DISPLAY = FakeHwcDisplayInjector::DEFAULT_HWC_DISPLAY_ID; +constexpr PhysicalDisplayId DEFAULT_DISPLAY_ID = PhysicalDisplayId::fromPort(42u); +constexpr int DEFAULT_DISPLAY_WIDTH = 1920; +constexpr int DEFAULT_DISPLAY_HEIGHT = 1024; + +class SurfaceFlingerPowerHintTest : public Test { +public: + void SetUp() override; + + void setupScheduler(); + +protected: + TestableSurfaceFlinger mFlinger; + renderengine::mock::RenderEngine* mRenderEngine = new renderengine::mock::RenderEngine(); + sp mDisplay; + sp mDisplaySurface = + new compositionengine::mock::DisplaySurface(); + mock::NativeWindow* mNativeWindow = new mock::NativeWindow(); + mock::TimeStats* mTimeStats = new mock::TimeStats(); + Hwc2::mock::PowerAdvisor* mPowerAdvisor = nullptr; + Hwc2::mock::Composer* mComposer = nullptr; +}; + +void SurfaceFlingerPowerHintTest::SetUp() { + setupScheduler(); + mComposer = new Hwc2::mock::Composer(); + mPowerAdvisor = new Hwc2::mock::PowerAdvisor(); + mFlinger.setupRenderEngine(std::unique_ptr(mRenderEngine)); + mFlinger.setupTimeStats(std::shared_ptr(mTimeStats)); + mFlinger.setupComposer(std::unique_ptr(mComposer)); + mFlinger.setupPowerAdvisor(std::unique_ptr(mPowerAdvisor)); + static constexpr bool kIsPrimary = true; + FakeHwcDisplayInjector(DEFAULT_DISPLAY_ID, hal::DisplayType::PHYSICAL, kIsPrimary) + .setPowerMode(hal::PowerMode::ON) + .inject(&mFlinger, mComposer); + auto compostionEngineDisplayArgs = + compositionengine::DisplayCreationArgsBuilder() + .setId(DEFAULT_DISPLAY_ID) + .setPixels({DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT}) + .setPowerAdvisor(mPowerAdvisor) + .setName("injected display") + .build(); + auto compositionDisplay = + compositionengine::impl::createDisplay(mFlinger.getCompositionEngine(), + std::move(compostionEngineDisplayArgs)); + mDisplay = + FakeDisplayDeviceInjector(mFlinger, compositionDisplay, + ui::DisplayConnectionType::Internal, HWC_DISPLAY, kIsPrimary) + .setDisplaySurface(mDisplaySurface) + .setNativeWindow(mNativeWindow) + .setPowerMode(hal::PowerMode::ON) + .inject(); +} + +void SurfaceFlingerPowerHintTest::setupScheduler() { + auto eventThread = std::make_unique(); + auto sfEventThread = std::make_unique(); + + EXPECT_CALL(*eventThread, registerDisplayEventConnection(_)); + EXPECT_CALL(*eventThread, createEventConnection(_, _)) + .WillOnce(Return(new EventThreadConnection(eventThread.get(), /*callingUid=*/0, + ResyncCallback()))); + + EXPECT_CALL(*sfEventThread, registerDisplayEventConnection(_)); + EXPECT_CALL(*sfEventThread, createEventConnection(_, _)) + .WillOnce(Return(new EventThreadConnection(sfEventThread.get(), /*callingUid=*/0, + ResyncCallback()))); + + auto vsyncController = std::make_unique(); + auto vsyncTracker = std::make_unique(); + + EXPECT_CALL(*vsyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillRepeatedly(Return(0)); + EXPECT_CALL(*vsyncTracker, currentPeriod()) + .WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_VSYNC_PERIOD)); + EXPECT_CALL(*vsyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillRepeatedly(Return(0)); + + mFlinger.setupScheduler(std::move(vsyncController), std::move(vsyncTracker), + std::move(eventThread), std::move(sfEventThread), + TestableSurfaceFlinger::SchedulerCallbackImpl::kNoOp, + TestableSurfaceFlinger::kTwoDisplayModes); +} + +TEST_F(SurfaceFlingerPowerHintTest, sendDurationsIncludingHwcWaitTime) { + ON_CALL(*mPowerAdvisor, usePowerHintSession()).WillByDefault(Return(true)); + + const std::chrono::nanoseconds mockVsyncPeriod = 15ms; + const std::chrono::nanoseconds expectedTargetTime = 14ms; + EXPECT_CALL(*mPowerAdvisor, setTargetWorkDuration(Gt(expectedTargetTime.count()))).Times(1); + + const nsecs_t now = systemTime(); + const std::chrono::nanoseconds mockHwcRunTime = 20ms; + EXPECT_CALL(*mDisplaySurface, + prepareFrame(compositionengine::DisplaySurface::CompositionType::Hwc)) + .Times(1); + EXPECT_CALL(*mComposer, presentOrValidateDisplay(HWC_DISPLAY, _, _, _, _, _)) + .WillOnce([mockHwcRunTime] { + std::this_thread::sleep_for(mockHwcRunTime); + return hardware::graphics::composer::V2_1::Error::NONE; + }); + EXPECT_CALL(*mPowerAdvisor, + sendActualWorkDuration(Gt(mockHwcRunTime.count()), + Gt(now + mockHwcRunTime.count()))) + .Times(1); + static constexpr bool kVsyncId = 123; // arbitrary + mFlinger.commitAndComposite(now, kVsyncId, now + mockVsyncPeriod.count()); +} + +} // namespace +} // namespace android diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index bf2465ff2d..866d9eb4ae 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -17,6 +17,7 @@ #pragma once #include +#include #include #include @@ -200,6 +201,10 @@ public: std::make_unique(std::move(composer))); } + void setupPowerAdvisor(std::unique_ptr powerAdvisor) { + mFlinger->mPowerAdvisor = std::move(powerAdvisor); + } + void setupTimeStats(const std::shared_ptr& timeStats) { mFlinger->mCompositionEngine->setTimeStats(timeStats); } @@ -328,11 +333,26 @@ public: /* ------------------------------------------------------------------------ * Forwarding for functions being tested */ + + nsecs_t commit(nsecs_t frameTime, int64_t vsyncId, nsecs_t expectedVSyncTime) { + mFlinger->commit(frameTime, vsyncId, expectedVSyncTime); + return frameTime; + } + + nsecs_t commit(nsecs_t frameTime, int64_t vsyncId) { + std::chrono::nanoseconds period = 10ms; + return commit(frameTime, vsyncId, frameTime + period.count()); + } + nsecs_t commit() { const nsecs_t now = systemTime(); const nsecs_t expectedVsyncTime = now + 10'000'000; - mFlinger->commit(now, kVsyncId, expectedVsyncTime); - return now; + return commit(now, kVsyncId, expectedVsyncTime); + } + + void commitAndComposite(const nsecs_t frameTime, const int64_t vsyncId, + const nsecs_t expectedVsyncTime) { + mFlinger->composite(commit(frameTime, vsyncId, expectedVsyncTime), kVsyncId); } void commitAndComposite() { mFlinger->composite(commit(), kVsyncId); } @@ -458,11 +478,6 @@ public: mFlinger->onActiveDisplayChangedLocked(activeDisplay); } - auto commit(nsecs_t frameTime, int64_t vsyncId) { - const nsecs_t expectedVsyncTime = frameTime + 10'000'000; - mFlinger->commit(frameTime, vsyncId, expectedVsyncTime); - } - auto createLayer(LayerCreationArgs& args, sp* outHandle, const sp& parentHandle, int32_t* outLayerId, const sp& parentLayer, uint32_t* outTransformHint) { @@ -515,7 +530,6 @@ public: auto& mutablePhysicalDisplayTokens() { return mFlinger->mPhysicalDisplayTokens; } auto& mutableTexturePool() { return mFlinger->mTexturePool; } auto& mutableTransactionFlags() { return mFlinger->mTransactionFlags; } - auto& mutablePowerAdvisor() { return mFlinger->mPowerAdvisor; } auto& mutableDebugDisableHWC() { return mFlinger->mDebugDisableHWC; } auto& mutableMaxRenderTargetSize() { return mFlinger->mMaxRenderTargetSize; } -- cgit v1.2.3-59-g8ed1b