diff options
| author | 2022-04-07 23:10:49 +0000 | |
|---|---|---|
| committer | 2022-04-07 23:10:49 +0000 | |
| commit | b613ddbb221ef325802bbc7b77f4be0c65bb18d8 (patch) | |
| tree | 22c691b7c194a615e8a24f8cf4babe577c043d4d | |
| parent | f192aea54aaa8144881365d4413101afc6af4e32 (diff) | |
| parent | 5dc854ad88e467d2f2c8134461764a8d724970a2 (diff) | |
Merge "Add unit test on sending power hints in SurfaceFlinger" into tm-dev am: 822377104d am: 5dc854ad88
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/native/+/17573287
Change-Id: I9cbb68ce8f0b25977cb3cd77de20d86e7b427ba7
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
6 files changed, 199 insertions, 26 deletions
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 4d19408fed..1d43c6e2f4 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -95,6 +95,7 @@ #include <cmath> #include <cstdint> #include <functional> +#include <memory> #include <mutex> #include <optional> #include <type_traits> @@ -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<Hwc2::impl::PowerAdvisor>(*this)), mWindowInfosListenerInvoker(sp<WindowInfosListenerInvoker>::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<pid_t> renderEngineTid = getRenderEngine().getRenderEngineTid(); std::vector<int32_t> 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<IBinder>& 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<os::IInputFlinger> mInputFlinger; InputWindowCommands mInputWindowCommands; - Hwc2::impl::PowerAdvisor mPowerAdvisor; + std::unique_ptr<Hwc2::PowerAdvisor> 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<TimeStats>(mTimeStats)); mComposer = new Hwc2::mock::Composer(); + mPowerAdvisor = new Hwc2::mock::PowerAdvisor(); mFlinger.setupComposer(std::unique_ptr<Hwc2::Composer>(mComposer)); - + mFlinger.setupPowerAdvisor(std::unique_ptr<Hwc2::PowerAdvisor>(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<Fence> 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 <compositionengine/Display.h> +#include <compositionengine/mock/DisplaySurface.h> +#include <gmock/gmock.h> +#include <gtest/gtest.h> +#include <renderengine/mock/RenderEngine.h> +#include <algorithm> +#include <chrono> +#include <memory> +#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<DisplayDevice> mDisplay; + sp<compositionengine::mock::DisplaySurface> 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<renderengine::RenderEngine>(mRenderEngine)); + mFlinger.setupTimeStats(std::shared_ptr<TimeStats>(mTimeStats)); + mFlinger.setupComposer(std::unique_ptr<Hwc2::Composer>(mComposer)); + mFlinger.setupPowerAdvisor(std::unique_ptr<Hwc2::PowerAdvisor>(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<mock::EventThread>(); + auto sfEventThread = std::make_unique<mock::EventThread>(); + + 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<mock::VsyncController>(); + auto vsyncTracker = std::make_unique<mock::VSyncTracker>(); + + 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 <algorithm> +#include <chrono> #include <variant> #include <compositionengine/Display.h> @@ -200,6 +201,10 @@ public: std::make_unique<impl::HWComposer>(std::move(composer))); } + void setupPowerAdvisor(std::unique_ptr<Hwc2::PowerAdvisor> powerAdvisor) { + mFlinger->mPowerAdvisor = std::move(powerAdvisor); + } + void setupTimeStats(const std::shared_ptr<TimeStats>& 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<IBinder>* outHandle, const sp<IBinder>& parentHandle, int32_t* outLayerId, const sp<Layer>& 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; } |