Loading services/surfaceflinger/DisplayDevice.cpp +8 −3 Original line number Diff line number Diff line Loading @@ -535,8 +535,8 @@ void DisplayDevice::clearDesiredActiveModeState() { } void DisplayDevice::adjustRefreshRate(Fps pacesetterDisplayRefreshRate) { using fps_approx_ops::operator==; if (mRequestedRefreshRate == 0_Hz) { using fps_approx_ops::operator<=; if (mRequestedRefreshRate <= 0_Hz) { return; } Loading @@ -547,7 +547,12 @@ void DisplayDevice::adjustRefreshRate(Fps pacesetterDisplayRefreshRate) { } unsigned divisor = static_cast<unsigned>( std::round(pacesetterDisplayRefreshRate.getValue() / mRequestedRefreshRate.getValue())); std::floor(pacesetterDisplayRefreshRate.getValue() / mRequestedRefreshRate.getValue())); if (divisor == 0) { mAdjustedRefreshRate = 0_Hz; return; } mAdjustedRefreshRate = pacesetterDisplayRefreshRate / divisor; } Loading services/surfaceflinger/SurfaceFlinger.h +1 −1 Original line number Diff line number Diff line Loading @@ -499,7 +499,7 @@ private: // Implements ISurfaceComposer sp<IBinder> createDisplay(const String8& displayName, bool secure, float requestedRefreshRate = 0); float requestedRefreshRate = 0.0f); void destroyDisplay(const sp<IBinder>& displayToken); std::vector<PhysicalDisplayId> getPhysicalDisplayIds() const EXCLUDES(mStateLock) { Mutex::Autolock lock(mStateLock); Loading services/surfaceflinger/tests/unittests/SurfaceFlinger_CreateDisplayTest.cpp +126 −1 Original line number Diff line number Diff line Loading @@ -17,12 +17,60 @@ #undef LOG_TAG #define LOG_TAG "LibSurfaceFlingerUnittests" #include <scheduler/Fps.h> #include "DisplayTransactionTestHelpers.h" #include "FpsOps.h" namespace android { namespace { class CreateDisplayTest : public DisplayTransactionTest {}; class CreateDisplayTest : public DisplayTransactionTest { public: void createDisplayWithRequestedRefreshRate(const String8& name, uint64_t displayId, float pacesetterDisplayRefreshRate, float requestedRefreshRate, float expectedAdjustedRefreshRate) { // -------------------------------------------------------------------- // Call Expectations // -------------------------------------------------------------------- // Invocation sp<IBinder> displayToken = mFlinger.createDisplay(name, false, requestedRefreshRate); // -------------------------------------------------------------------- // Postconditions // The display should have been added to the current state ASSERT_TRUE(hasCurrentDisplayState(displayToken)); const auto& display = getCurrentDisplayState(displayToken); EXPECT_TRUE(display.isVirtual()); EXPECT_EQ(display.requestedRefreshRate, Fps::fromValue(requestedRefreshRate)); EXPECT_EQ(name.string(), display.displayName); std::optional<VirtualDisplayId> vid = DisplayId::fromValue<VirtualDisplayId>(displayId | DisplayId::FLAG_VIRTUAL); ASSERT_TRUE(vid.has_value()); sp<DisplayDevice> device = mFlinger.createVirtualDisplayDevice(displayToken, *vid, requestedRefreshRate); EXPECT_TRUE(device->isVirtual()); device->adjustRefreshRate(Fps::fromValue(pacesetterDisplayRefreshRate)); // verifying desired value EXPECT_EQ(device->getAdjustedRefreshRate(), Fps::fromValue(expectedAdjustedRefreshRate)); // verifying rounding up if (requestedRefreshRate < pacesetterDisplayRefreshRate) { EXPECT_GE(device->getAdjustedRefreshRate(), Fps::fromValue(requestedRefreshRate)); } else { EXPECT_EQ(device->getAdjustedRefreshRate(), Fps::fromValue(pacesetterDisplayRefreshRate)); } // -------------------------------------------------------------------- // Cleanup conditions } }; TEST_F(CreateDisplayTest, createDisplaySetsCurrentStateForNonsecureDisplay) { const String8 name("virtual.test"); Loading Loading @@ -84,5 +132,82 @@ TEST_F(CreateDisplayTest, createDisplaySetsCurrentStateForSecureDisplay) { EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame()).Times(1); } // Requesting 0 tells SF not to do anything, i.e., default to refresh as physical displays TEST_F(CreateDisplayTest, createDisplayWithRequestedRefreshRate0) { const String8 displayName("virtual.test"); const uint64_t displayId = 123ull; const float kPacesetterDisplayRefreshRate = 60.f; const float kRequestedRefreshRate = 0.f; const float kExpectedAdjustedRefreshRate = 0.f; createDisplayWithRequestedRefreshRate(displayName, displayId, kPacesetterDisplayRefreshRate, kRequestedRefreshRate, kExpectedAdjustedRefreshRate); } // Requesting negative refresh rate, will be ignored, same as requesting 0 TEST_F(CreateDisplayTest, createDisplayWithRequestedRefreshRateNegative) { const String8 displayName("virtual.test"); const uint64_t displayId = 123ull; const float kPacesetterDisplayRefreshRate = 60.f; const float kRequestedRefreshRate = -60.f; const float kExpectedAdjustedRefreshRate = 0.f; createDisplayWithRequestedRefreshRate(displayName, displayId, kPacesetterDisplayRefreshRate, kRequestedRefreshRate, kExpectedAdjustedRefreshRate); } // Requesting a higher refresh rate than the pacesetter TEST_F(CreateDisplayTest, createDisplayWithRequestedRefreshRateHigh) { const String8 displayName("virtual.test"); const uint64_t displayId = 123ull; const float kPacesetterDisplayRefreshRate = 60.f; const float kRequestedRefreshRate = 90.f; const float kExpectedAdjustedRefreshRate = 60.f; createDisplayWithRequestedRefreshRate(displayName, displayId, kPacesetterDisplayRefreshRate, kRequestedRefreshRate, kExpectedAdjustedRefreshRate); } // Requesting the same refresh rate as the pacesetter TEST_F(CreateDisplayTest, createDisplayWithRequestedRefreshRateSame) { const String8 displayName("virtual.test"); const uint64_t displayId = 123ull; const float kPacesetterDisplayRefreshRate = 60.f; const float kRequestedRefreshRate = 60.f; const float kExpectedAdjustedRefreshRate = 60.f; createDisplayWithRequestedRefreshRate(displayName, displayId, kPacesetterDisplayRefreshRate, kRequestedRefreshRate, kExpectedAdjustedRefreshRate); } // Requesting a divisor (30) of the pacesetter (60) should be honored TEST_F(CreateDisplayTest, createDisplayWithRequestedRefreshRateDivisor) { const String8 displayName("virtual.test"); const uint64_t displayId = 123ull; const float kPacesetterDisplayRefreshRate = 60.f; const float kRequestedRefreshRate = 30.f; const float kExpectedAdjustedRefreshRate = 30.f; createDisplayWithRequestedRefreshRate(displayName, displayId, kPacesetterDisplayRefreshRate, kRequestedRefreshRate, kExpectedAdjustedRefreshRate); } // Requesting a non divisor (45) of the pacesetter (120) should round up to a divisor (60) TEST_F(CreateDisplayTest, createDisplayWithRequestedRefreshRateNoneDivisor) { const String8 displayName("virtual.test"); const uint64_t displayId = 123ull; const float kPacesetterDisplayRefreshRate = 120.f; const float kRequestedRefreshRate = 45.f; const float kExpectedAdjustedRefreshRate = 60.f; createDisplayWithRequestedRefreshRate(displayName, displayId, kPacesetterDisplayRefreshRate, kRequestedRefreshRate, kExpectedAdjustedRefreshRate); } // Requesting a non divisor (75) of the pacesetter (120) should round up to pacesetter (120) TEST_F(CreateDisplayTest, createDisplayWithRequestedRefreshRateNoneDivisorMax) { const String8 displayName("virtual.test"); const uint64_t displayId = 123ull; const float kPacesetterDisplayRefreshRate = 120.f; const float kRequestedRefreshRate = 75.f; const float kExpectedAdjustedRefreshRate = 120.f; createDisplayWithRequestedRefreshRate(displayName, displayId, kPacesetterDisplayRefreshRate, kRequestedRefreshRate, kExpectedAdjustedRefreshRate); } } // namespace } // namespace android services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +23 −2 Original line number Diff line number Diff line Loading @@ -48,10 +48,12 @@ #include "TestableScheduler.h" #include "mock/DisplayHardware/MockComposer.h" #include "mock/DisplayHardware/MockDisplayMode.h" #include "mock/DisplayHardware/MockPowerAdvisor.h" #include "mock/MockEventThread.h" #include "mock/MockFrameTimeline.h" #include "mock/MockFrameTracer.h" #include "mock/MockSchedulerCallback.h" #include "mock/system/window/MockNativeWindow.h" namespace android { namespace renderengine { Loading Loading @@ -375,8 +377,8 @@ public: void commitAndComposite() { mFlinger->composite(commit(), kVsyncId); } auto createDisplay(const String8& displayName, bool secure) { return mFlinger->createDisplay(displayName, secure); auto createDisplay(const String8& displayName, bool secure, float requestedRefreshRate = 0.0f) { return mFlinger->createDisplay(displayName, secure, requestedRefreshRate); } auto destroyDisplay(const sp<IBinder>& displayToken) { Loading Loading @@ -525,6 +527,24 @@ public: mFlinger->getDynamicDisplayInfoFromToken(displayToken, dynamicDisplayInfo); } sp<DisplayDevice> createVirtualDisplayDevice(const sp<IBinder> displayToken, VirtualDisplayId displayId, float requestedRefreshRate) { constexpr ui::Size kResolution = {1080, 1920}; auto compositionDisplay = compositionengine::impl:: createDisplay(mFlinger->getCompositionEngine(), compositionengine::DisplayCreationArgsBuilder() .setId(displayId) .setPixels(kResolution) .setPowerAdvisor(&mPowerAdvisor) .build()); DisplayDeviceCreationArgs creationArgs(mFlinger, mFlinger->getHwComposer(), displayToken, compositionDisplay); creationArgs.requestedRefreshRate = Fps::fromValue(requestedRefreshRate); creationArgs.nativeWindow = sp<mock::NativeWindow>::make(); return sp<DisplayDevice>::make(creationArgs); } /* ------------------------------------------------------------------------ * Read-only access to private data to assert post-conditions. */ Loading Loading @@ -962,6 +982,7 @@ private: scheduler::mock::NoOpSchedulerCallback mNoOpSchedulerCallback; std::unique_ptr<frametimeline::impl::TokenManager> mTokenManager; scheduler::TestableScheduler* mScheduler = nullptr; Hwc2::mock::PowerAdvisor mPowerAdvisor; }; } // namespace android Loading
services/surfaceflinger/DisplayDevice.cpp +8 −3 Original line number Diff line number Diff line Loading @@ -535,8 +535,8 @@ void DisplayDevice::clearDesiredActiveModeState() { } void DisplayDevice::adjustRefreshRate(Fps pacesetterDisplayRefreshRate) { using fps_approx_ops::operator==; if (mRequestedRefreshRate == 0_Hz) { using fps_approx_ops::operator<=; if (mRequestedRefreshRate <= 0_Hz) { return; } Loading @@ -547,7 +547,12 @@ void DisplayDevice::adjustRefreshRate(Fps pacesetterDisplayRefreshRate) { } unsigned divisor = static_cast<unsigned>( std::round(pacesetterDisplayRefreshRate.getValue() / mRequestedRefreshRate.getValue())); std::floor(pacesetterDisplayRefreshRate.getValue() / mRequestedRefreshRate.getValue())); if (divisor == 0) { mAdjustedRefreshRate = 0_Hz; return; } mAdjustedRefreshRate = pacesetterDisplayRefreshRate / divisor; } Loading
services/surfaceflinger/SurfaceFlinger.h +1 −1 Original line number Diff line number Diff line Loading @@ -499,7 +499,7 @@ private: // Implements ISurfaceComposer sp<IBinder> createDisplay(const String8& displayName, bool secure, float requestedRefreshRate = 0); float requestedRefreshRate = 0.0f); void destroyDisplay(const sp<IBinder>& displayToken); std::vector<PhysicalDisplayId> getPhysicalDisplayIds() const EXCLUDES(mStateLock) { Mutex::Autolock lock(mStateLock); Loading
services/surfaceflinger/tests/unittests/SurfaceFlinger_CreateDisplayTest.cpp +126 −1 Original line number Diff line number Diff line Loading @@ -17,12 +17,60 @@ #undef LOG_TAG #define LOG_TAG "LibSurfaceFlingerUnittests" #include <scheduler/Fps.h> #include "DisplayTransactionTestHelpers.h" #include "FpsOps.h" namespace android { namespace { class CreateDisplayTest : public DisplayTransactionTest {}; class CreateDisplayTest : public DisplayTransactionTest { public: void createDisplayWithRequestedRefreshRate(const String8& name, uint64_t displayId, float pacesetterDisplayRefreshRate, float requestedRefreshRate, float expectedAdjustedRefreshRate) { // -------------------------------------------------------------------- // Call Expectations // -------------------------------------------------------------------- // Invocation sp<IBinder> displayToken = mFlinger.createDisplay(name, false, requestedRefreshRate); // -------------------------------------------------------------------- // Postconditions // The display should have been added to the current state ASSERT_TRUE(hasCurrentDisplayState(displayToken)); const auto& display = getCurrentDisplayState(displayToken); EXPECT_TRUE(display.isVirtual()); EXPECT_EQ(display.requestedRefreshRate, Fps::fromValue(requestedRefreshRate)); EXPECT_EQ(name.string(), display.displayName); std::optional<VirtualDisplayId> vid = DisplayId::fromValue<VirtualDisplayId>(displayId | DisplayId::FLAG_VIRTUAL); ASSERT_TRUE(vid.has_value()); sp<DisplayDevice> device = mFlinger.createVirtualDisplayDevice(displayToken, *vid, requestedRefreshRate); EXPECT_TRUE(device->isVirtual()); device->adjustRefreshRate(Fps::fromValue(pacesetterDisplayRefreshRate)); // verifying desired value EXPECT_EQ(device->getAdjustedRefreshRate(), Fps::fromValue(expectedAdjustedRefreshRate)); // verifying rounding up if (requestedRefreshRate < pacesetterDisplayRefreshRate) { EXPECT_GE(device->getAdjustedRefreshRate(), Fps::fromValue(requestedRefreshRate)); } else { EXPECT_EQ(device->getAdjustedRefreshRate(), Fps::fromValue(pacesetterDisplayRefreshRate)); } // -------------------------------------------------------------------- // Cleanup conditions } }; TEST_F(CreateDisplayTest, createDisplaySetsCurrentStateForNonsecureDisplay) { const String8 name("virtual.test"); Loading Loading @@ -84,5 +132,82 @@ TEST_F(CreateDisplayTest, createDisplaySetsCurrentStateForSecureDisplay) { EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame()).Times(1); } // Requesting 0 tells SF not to do anything, i.e., default to refresh as physical displays TEST_F(CreateDisplayTest, createDisplayWithRequestedRefreshRate0) { const String8 displayName("virtual.test"); const uint64_t displayId = 123ull; const float kPacesetterDisplayRefreshRate = 60.f; const float kRequestedRefreshRate = 0.f; const float kExpectedAdjustedRefreshRate = 0.f; createDisplayWithRequestedRefreshRate(displayName, displayId, kPacesetterDisplayRefreshRate, kRequestedRefreshRate, kExpectedAdjustedRefreshRate); } // Requesting negative refresh rate, will be ignored, same as requesting 0 TEST_F(CreateDisplayTest, createDisplayWithRequestedRefreshRateNegative) { const String8 displayName("virtual.test"); const uint64_t displayId = 123ull; const float kPacesetterDisplayRefreshRate = 60.f; const float kRequestedRefreshRate = -60.f; const float kExpectedAdjustedRefreshRate = 0.f; createDisplayWithRequestedRefreshRate(displayName, displayId, kPacesetterDisplayRefreshRate, kRequestedRefreshRate, kExpectedAdjustedRefreshRate); } // Requesting a higher refresh rate than the pacesetter TEST_F(CreateDisplayTest, createDisplayWithRequestedRefreshRateHigh) { const String8 displayName("virtual.test"); const uint64_t displayId = 123ull; const float kPacesetterDisplayRefreshRate = 60.f; const float kRequestedRefreshRate = 90.f; const float kExpectedAdjustedRefreshRate = 60.f; createDisplayWithRequestedRefreshRate(displayName, displayId, kPacesetterDisplayRefreshRate, kRequestedRefreshRate, kExpectedAdjustedRefreshRate); } // Requesting the same refresh rate as the pacesetter TEST_F(CreateDisplayTest, createDisplayWithRequestedRefreshRateSame) { const String8 displayName("virtual.test"); const uint64_t displayId = 123ull; const float kPacesetterDisplayRefreshRate = 60.f; const float kRequestedRefreshRate = 60.f; const float kExpectedAdjustedRefreshRate = 60.f; createDisplayWithRequestedRefreshRate(displayName, displayId, kPacesetterDisplayRefreshRate, kRequestedRefreshRate, kExpectedAdjustedRefreshRate); } // Requesting a divisor (30) of the pacesetter (60) should be honored TEST_F(CreateDisplayTest, createDisplayWithRequestedRefreshRateDivisor) { const String8 displayName("virtual.test"); const uint64_t displayId = 123ull; const float kPacesetterDisplayRefreshRate = 60.f; const float kRequestedRefreshRate = 30.f; const float kExpectedAdjustedRefreshRate = 30.f; createDisplayWithRequestedRefreshRate(displayName, displayId, kPacesetterDisplayRefreshRate, kRequestedRefreshRate, kExpectedAdjustedRefreshRate); } // Requesting a non divisor (45) of the pacesetter (120) should round up to a divisor (60) TEST_F(CreateDisplayTest, createDisplayWithRequestedRefreshRateNoneDivisor) { const String8 displayName("virtual.test"); const uint64_t displayId = 123ull; const float kPacesetterDisplayRefreshRate = 120.f; const float kRequestedRefreshRate = 45.f; const float kExpectedAdjustedRefreshRate = 60.f; createDisplayWithRequestedRefreshRate(displayName, displayId, kPacesetterDisplayRefreshRate, kRequestedRefreshRate, kExpectedAdjustedRefreshRate); } // Requesting a non divisor (75) of the pacesetter (120) should round up to pacesetter (120) TEST_F(CreateDisplayTest, createDisplayWithRequestedRefreshRateNoneDivisorMax) { const String8 displayName("virtual.test"); const uint64_t displayId = 123ull; const float kPacesetterDisplayRefreshRate = 120.f; const float kRequestedRefreshRate = 75.f; const float kExpectedAdjustedRefreshRate = 120.f; createDisplayWithRequestedRefreshRate(displayName, displayId, kPacesetterDisplayRefreshRate, kRequestedRefreshRate, kExpectedAdjustedRefreshRate); } } // namespace } // namespace android
services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +23 −2 Original line number Diff line number Diff line Loading @@ -48,10 +48,12 @@ #include "TestableScheduler.h" #include "mock/DisplayHardware/MockComposer.h" #include "mock/DisplayHardware/MockDisplayMode.h" #include "mock/DisplayHardware/MockPowerAdvisor.h" #include "mock/MockEventThread.h" #include "mock/MockFrameTimeline.h" #include "mock/MockFrameTracer.h" #include "mock/MockSchedulerCallback.h" #include "mock/system/window/MockNativeWindow.h" namespace android { namespace renderengine { Loading Loading @@ -375,8 +377,8 @@ public: void commitAndComposite() { mFlinger->composite(commit(), kVsyncId); } auto createDisplay(const String8& displayName, bool secure) { return mFlinger->createDisplay(displayName, secure); auto createDisplay(const String8& displayName, bool secure, float requestedRefreshRate = 0.0f) { return mFlinger->createDisplay(displayName, secure, requestedRefreshRate); } auto destroyDisplay(const sp<IBinder>& displayToken) { Loading Loading @@ -525,6 +527,24 @@ public: mFlinger->getDynamicDisplayInfoFromToken(displayToken, dynamicDisplayInfo); } sp<DisplayDevice> createVirtualDisplayDevice(const sp<IBinder> displayToken, VirtualDisplayId displayId, float requestedRefreshRate) { constexpr ui::Size kResolution = {1080, 1920}; auto compositionDisplay = compositionengine::impl:: createDisplay(mFlinger->getCompositionEngine(), compositionengine::DisplayCreationArgsBuilder() .setId(displayId) .setPixels(kResolution) .setPowerAdvisor(&mPowerAdvisor) .build()); DisplayDeviceCreationArgs creationArgs(mFlinger, mFlinger->getHwComposer(), displayToken, compositionDisplay); creationArgs.requestedRefreshRate = Fps::fromValue(requestedRefreshRate); creationArgs.nativeWindow = sp<mock::NativeWindow>::make(); return sp<DisplayDevice>::make(creationArgs); } /* ------------------------------------------------------------------------ * Read-only access to private data to assert post-conditions. */ Loading Loading @@ -962,6 +982,7 @@ private: scheduler::mock::NoOpSchedulerCallback mNoOpSchedulerCallback; std::unique_ptr<frametimeline::impl::TokenManager> mTokenManager; scheduler::TestableScheduler* mScheduler = nullptr; Hwc2::mock::PowerAdvisor mPowerAdvisor; }; } // namespace android