SF: Refactor Scheduler mock injection
Factor out TestableScheduler setup to TestableSurfaceFlinger,
and instantiate a VSyncModulator, since the std::optional may
be dereferenced in tests.
Bug: 123530318
Test: libsurfaceflinger_unittest
Change-Id: Ic7c95024e63d861c5c5c53e4973995a4fd83a7d8
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index 952643c..3883427 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -118,6 +118,14 @@
}
}
+Scheduler::Scheduler(std::unique_ptr<DispSync> primaryDispSync,
+ std::unique_ptr<EventControlThread> eventControlThread,
+ const scheduler::RefreshRateConfigs& configs)
+ : mHasSyncFramework(false),
+ mPrimaryDispSync(std::move(primaryDispSync)),
+ mEventControlThread(std::move(eventControlThread)),
+ mRefreshRateConfigs(configs) {}
+
Scheduler::~Scheduler() {
// Ensure the OneShotTimer threads are joined before we start destroying state.
mDisplayPowerTimer.reset();
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index 0d9d7aa..5905ff6 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -204,6 +204,10 @@
enum class TimerState { Reset, Expired };
enum class TouchState { Inactive, Active };
+ // Used by tests to inject mocks.
+ Scheduler(std::unique_ptr<DispSync>, std::unique_ptr<EventControlThread>,
+ const scheduler::RefreshRateConfigs&);
+
// Creates a connection on the given EventThread and forwards the given callbacks.
sp<EventThreadConnection> createConnectionInternal(EventThread*, ResyncCallback&&,
ISurfaceComposer::ConfigChanged);
diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index 47243a9..82dd3c7 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -34,7 +34,6 @@
#include "ColorLayer.h"
#include "Layer.h"
-#include "TestableScheduler.h"
#include "TestableSurfaceFlinger.h"
#include "mock/DisplayHardware/MockComposer.h"
#include "mock/MockDispSync.h"
@@ -95,10 +94,6 @@
mFlinger.mutableEventQueue().reset(mMessageQueue);
setupScheduler();
- EXPECT_CALL(*mPrimaryDispSync, computeNextRefresh(0)).WillRepeatedly(Return(0));
- EXPECT_CALL(*mPrimaryDispSync, getPeriod())
- .WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_REFRESH_RATE));
- EXPECT_CALL(*mPrimaryDispSync, expectedPresentTime()).WillRepeatedly(Return(0));
EXPECT_CALL(*mNativeWindow, query(NATIVE_WINDOW_WIDTH, _))
.WillRepeatedly(DoAll(SetArgPointee<1>(DEFAULT_DISPLAY_WIDTH), Return(0)));
EXPECT_CALL(*mNativeWindow, query(NATIVE_WINDOW_HEIGHT, _))
@@ -125,15 +120,22 @@
}
void setupScheduler() {
- mScheduler = new TestableScheduler(mFlinger.mutableRefreshRateConfigs());
- mScheduler->mutableEventControlThread().reset(mEventControlThread);
- mScheduler->mutablePrimaryDispSync().reset(mPrimaryDispSync);
- EXPECT_CALL(*mEventThread.get(), registerDisplayEventConnection(_));
- sp<Scheduler::ConnectionHandle> connectionHandle =
- mScheduler->addConnection(std::move(mEventThread));
- mFlinger.mutableSfConnectionHandle() = std::move(connectionHandle);
+ auto eventThread = std::make_unique<mock::EventThread>();
+ auto sfEventThread = std::make_unique<mock::EventThread>();
- mFlinger.mutableScheduler().reset(mScheduler);
+ EXPECT_CALL(*eventThread, registerDisplayEventConnection(_));
+ EXPECT_CALL(*sfEventThread, registerDisplayEventConnection(_));
+
+ auto primaryDispSync = std::make_unique<mock::DispSync>();
+
+ EXPECT_CALL(*primaryDispSync, computeNextRefresh(0)).WillRepeatedly(Return(0));
+ EXPECT_CALL(*primaryDispSync, getPeriod())
+ .WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_REFRESH_RATE));
+ EXPECT_CALL(*primaryDispSync, expectedPresentTime()).WillRepeatedly(Return(0));
+
+ mFlinger.setupScheduler(std::move(primaryDispSync),
+ std::make_unique<mock::EventControlThread>(),
+ std::move(eventThread), std::move(sfEventThread));
}
void setupForceGeometryDirty() {
@@ -157,7 +159,6 @@
std::unordered_set<HWC2::Capability> mDefaultCapabilities = {HWC2::Capability::SidebandStream};
- TestableScheduler* mScheduler;
TestableSurfaceFlinger mFlinger;
sp<DisplayDevice> mDisplay;
sp<DisplayDevice> mExternalDisplay;
@@ -168,13 +169,9 @@
sp<GraphicBuffer> mBuffer = new GraphicBuffer();
ANativeWindowBuffer* mNativeWindowBuffer = mBuffer->getNativeBuffer();
- std::unique_ptr<mock::EventThread> mEventThread = std::make_unique<mock::EventThread>();
- mock::EventControlThread* mEventControlThread = new mock::EventControlThread();
-
Hwc2::mock::Composer* mComposer = nullptr;
renderengine::mock::RenderEngine* mRenderEngine = new renderengine::mock::RenderEngine();
mock::MessageQueue* mMessageQueue = new mock::MessageQueue();
- mock::DispSync* mPrimaryDispSync = new mock::DispSync();
sp<Fence> mClientTargetAcquireFence = Fence::NO_FENCE;
diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
index 5f58e7d..8f6f3ec 100644
--- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
@@ -95,11 +95,10 @@
DisplayTransactionTest();
~DisplayTransactionTest() override;
- void setupScheduler();
-
// --------------------------------------------------------------------
// Mock/Fake injection
+ void injectMockScheduler();
void injectMockComposer(int virtualDisplayCount);
void injectFakeBufferQueueFactory();
void injectFakeNativeWindowSurfaceFactory();
@@ -119,11 +118,7 @@
// --------------------------------------------------------------------
// Test instances
- TestableScheduler* mScheduler;
TestableSurfaceFlinger mFlinger;
- mock::EventThread* mEventThread = new mock::EventThread();
- mock::EventThread* mSFEventThread = new mock::EventThread();
- mock::EventControlThread* mEventControlThread = new mock::EventControlThread();
sp<mock::NativeWindow> mNativeWindow = new mock::NativeWindow();
sp<GraphicBuffer> mBuffer = new GraphicBuffer();
@@ -134,7 +129,11 @@
Hwc2::mock::Composer* mComposer = nullptr;
mock::MessageQueue* mMessageQueue = new mock::MessageQueue();
mock::SurfaceInterceptor* mSurfaceInterceptor = new mock::SurfaceInterceptor();
- mock::DispSync* mPrimaryDispSync = new mock::DispSync();
+
+ mock::DispSync* mPrimaryDispSync = new mock::DispSync;
+ mock::EventControlThread* mEventControlThread = new mock::EventControlThread;
+ mock::EventThread* mEventThread = new mock::EventThread;
+ mock::EventThread* mSFEventThread = new mock::EventThread;
// These mocks are created only when expected to be created via a factory.
sp<mock::GraphicBufferConsumer> mConsumer;
@@ -164,7 +163,7 @@
return nullptr;
});
- setupScheduler();
+ injectMockScheduler();
mFlinger.mutableEventQueue().reset(mMessageQueue);
mFlinger.setupRenderEngine(std::unique_ptr<renderengine::RenderEngine>(mRenderEngine));
mFlinger.mutableInterceptor().reset(mSurfaceInterceptor);
@@ -178,20 +177,14 @@
ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name());
}
-void DisplayTransactionTest::setupScheduler() {
- mScheduler = new TestableScheduler(mFlinger.mutableRefreshRateConfigs());
- mScheduler->mutableEventControlThread().reset(mEventControlThread);
- mScheduler->mutablePrimaryDispSync().reset(mPrimaryDispSync);
+void DisplayTransactionTest::injectMockScheduler() {
EXPECT_CALL(*mEventThread, registerDisplayEventConnection(_));
EXPECT_CALL(*mSFEventThread, registerDisplayEventConnection(_));
- sp<Scheduler::ConnectionHandle> sfConnectionHandle =
- mScheduler->addConnection(std::unique_ptr<EventThread>(mSFEventThread));
- mFlinger.mutableSfConnectionHandle() = std::move(sfConnectionHandle);
- sp<Scheduler::ConnectionHandle> appConnectionHandle =
- mScheduler->addConnection(std::unique_ptr<EventThread>(mEventThread));
- mFlinger.mutableAppConnectionHandle() = std::move(appConnectionHandle);
- mFlinger.mutableScheduler().reset(mScheduler);
+ mFlinger.setupScheduler(std::unique_ptr<DispSync>(mPrimaryDispSync),
+ std::unique_ptr<EventControlThread>(mEventControlThread),
+ std::unique_ptr<EventThread>(mEventThread),
+ std::unique_ptr<EventThread>(mSFEventThread));
}
void DisplayTransactionTest::injectMockComposer(int virtualDisplayCount) {
@@ -1131,8 +1124,8 @@
// Preconditions
// vsync is enabled and available
- mScheduler->mutablePrimaryHWVsyncEnabled() = true;
- mScheduler->mutableHWVsyncAvailable() = true;
+ mFlinger.scheduler()->mutablePrimaryHWVsyncEnabled() = true;
+ mFlinger.scheduler()->mutableHWVsyncAvailable() = true;
// A display exists
auto existing = Case::Display::makeFakeExistingDisplayInjector(this);
@@ -1156,8 +1149,8 @@
// Postconditions
// vsyncs should be off and not available.
- EXPECT_FALSE(mScheduler->mutablePrimaryHWVsyncEnabled());
- EXPECT_FALSE(mScheduler->mutableHWVsyncAvailable());
+ EXPECT_FALSE(mFlinger.scheduler()->mutablePrimaryHWVsyncEnabled());
+ EXPECT_FALSE(mFlinger.scheduler()->mutableHWVsyncAvailable());
// The display should have been removed from the display map.
EXPECT_FALSE(hasDisplayDevice(existing.token()));
@@ -3008,7 +3001,7 @@
}
static void setInitialPrimaryHWVsyncEnabled(DisplayTransactionTest* test, bool enabled) {
- test->mScheduler->mutablePrimaryHWVsyncEnabled() = enabled;
+ test->mFlinger.scheduler()->mutablePrimaryHWVsyncEnabled() = enabled;
}
static void setupRepaintEverythingCallExpectations(DisplayTransactionTest* test) {
diff --git a/services/surfaceflinger/tests/unittests/TestableScheduler.h b/services/surfaceflinger/tests/unittests/TestableScheduler.h
index cb6980e..5157cc4 100644
--- a/services/surfaceflinger/tests/unittests/TestableScheduler.h
+++ b/services/surfaceflinger/tests/unittests/TestableScheduler.h
@@ -20,15 +20,16 @@
#include <gui/ISurfaceComposer.h>
#include "Scheduler/EventThread.h"
-#include "Scheduler/RefreshRateConfigs.h"
#include "Scheduler/Scheduler.h"
namespace android {
class TestableScheduler : public Scheduler {
public:
- TestableScheduler(const scheduler::RefreshRateConfigs& refreshRateConfig)
- : Scheduler([](bool) {}, refreshRateConfig) {}
+ TestableScheduler(std::unique_ptr<DispSync> primaryDispSync,
+ std::unique_ptr<EventControlThread> eventControlThread,
+ const scheduler::RefreshRateConfigs& configs)
+ : Scheduler(std::move(primaryDispSync), std::move(eventControlThread), configs) {}
// Creates EventThreadConnection with the given eventThread. Creates Scheduler::Connection
// and adds it to the list of connectins. Returns the ConnectionHandle for the
@@ -62,7 +63,7 @@
mutableEventControlThread().reset();
mutablePrimaryDispSync().reset();
mConnections.clear();
- };
+ }
};
} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index 64d34ee..97fafcb 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -36,7 +36,7 @@
#include "SurfaceFlinger.h"
#include "SurfaceFlingerFactory.h"
#include "SurfaceInterceptor.h"
-
+#include "TestableScheduler.h"
#include "TimeStats/TimeStats.h"
namespace android {
@@ -176,6 +176,8 @@
class TestableSurfaceFlinger {
public:
+ TestableScheduler* scheduler() { return mScheduler; }
+
// Extend this as needed for accessing SurfaceFlinger private (and public)
// functions.
@@ -188,6 +190,23 @@
std::make_unique<impl::HWComposer>(std::move(composer)));
}
+ void setupScheduler(std::unique_ptr<DispSync> primaryDispSync,
+ std::unique_ptr<EventControlThread> eventControlThread,
+ std::unique_ptr<EventThread> appEventThread,
+ std::unique_ptr<EventThread> sfEventThread) {
+ mScheduler =
+ new TestableScheduler(std::move(primaryDispSync), std::move(eventControlThread),
+ mFlinger->mRefreshRateConfigs);
+
+ mFlinger->mAppConnectionHandle = mScheduler->addConnection(std::move(appEventThread));
+ mFlinger->mSfConnectionHandle = mScheduler->addConnection(std::move(sfEventThread));
+
+ mFlinger->mScheduler.reset(mScheduler);
+ mFlinger->mVSyncModulator.emplace(*mScheduler, mFlinger->mAppConnectionHandle,
+ mFlinger->mSfConnectionHandle,
+ mFlinger->mPhaseOffsets->getCurrentOffsets());
+ }
+
using CreateBufferQueueFunction = surfaceflinger::test::Factory::CreateBufferQueueFunction;
void setCreateBufferQueueFunction(CreateBufferQueueFunction f) {
mFactory.mCreateBufferQueue = f;
@@ -338,10 +357,6 @@
auto& mutableHwcPhysicalDisplayIdMap() { return getHwComposer().mPhysicalDisplayIdMap; }
auto& mutableInternalHwcDisplayId() { return getHwComposer().mInternalHwcDisplayId; }
auto& mutableExternalHwcDisplayId() { return getHwComposer().mExternalHwcDisplayId; }
- auto& mutableScheduler() { return mFlinger->mScheduler; }
- auto& mutableAppConnectionHandle() { return mFlinger->mAppConnectionHandle; }
- auto& mutableSfConnectionHandle() { return mFlinger->mSfConnectionHandle; }
- auto& mutableRefreshRateConfigs() { return mFlinger->mRefreshRateConfigs; }
~TestableSurfaceFlinger() {
// All these pointer and container clears help ensure that GMock does
@@ -353,7 +368,6 @@
mutableDrawingState().displays.clear();
mutableEventQueue().reset();
mutableInterceptor().reset();
- mutableScheduler().reset();
mFlinger->mCompositionEngine->setHwComposer(std::unique_ptr<HWComposer>());
mFlinger->mCompositionEngine->setRenderEngine(
std::unique_ptr<renderengine::RenderEngine>());
@@ -573,6 +587,7 @@
surfaceflinger::test::Factory mFactory;
sp<SurfaceFlinger> mFlinger = new SurfaceFlinger(mFactory, SurfaceFlinger::SkipInitialization);
+ TestableScheduler* mScheduler = nullptr;
// We need to keep a reference to these so they are properly destroyed.
std::vector<std::unique_ptr<HWC2Display>> mFakeHwcDisplays;