diff options
5 files changed, 113 insertions, 25 deletions
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h index 10ffc7a569..7b5278cddb 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.h +++ b/services/surfaceflinger/Scheduler/Scheduler.h @@ -144,6 +144,8 @@ protected: impl::EventThread::InterceptVSyncsCallback interceptCallback); private: + friend class TestableScheduler; + // Creates a connection on the given EventThread and forwards the given callbacks. sp<EventThreadConnection> createConnectionInternal(EventThread*, ResyncCallback&&); diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp index 3addd61e55..3101a9b8e2 100644 --- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp +++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp @@ -33,6 +33,7 @@ #include "ColorLayer.h" #include "Layer.h" +#include "TestableScheduler.h" #include "TestableSurfaceFlinger.h" #include "mock/DisplayHardware/MockComposer.h" #include "mock/MockDispSync.h" @@ -90,11 +91,9 @@ public: ::testing::UnitTest::GetInstance()->current_test_info(); ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name()); - mFlinger.mutableEventControlThread().reset(mEventControlThread); - mFlinger.mutableEventThread().reset(mEventThread); mFlinger.mutableEventQueue().reset(mMessageQueue); + setupScheduler(); - mFlinger.mutablePrimaryDispSync().reset(mPrimaryDispSync); EXPECT_CALL(*mPrimaryDispSync, computeNextRefresh(0)).WillRepeatedly(Return(0)); EXPECT_CALL(*mPrimaryDispSync, getPeriod()) .WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_REFRESH_RATE)); @@ -124,6 +123,18 @@ public: Mock::VerifyAndClear(mComposer); } + void setupScheduler() { + mScheduler = new TestableScheduler(); + 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); + + mFlinger.mutableScheduler().reset(mScheduler); + } + void setupForceGeometryDirty() { // TODO: This requires the visible region and other related // state to be set, and is problematic for BufferLayers since they are @@ -145,6 +156,7 @@ public: std::unordered_set<HWC2::Capability> mDefaultCapabilities = {HWC2::Capability::SidebandStream}; + TestableScheduler* mScheduler; TestableSurfaceFlinger mFlinger; sp<DisplayDevice> mDisplay; sp<DisplayDevice> mExternalDisplay; @@ -155,7 +167,7 @@ public: sp<GraphicBuffer> mBuffer = new GraphicBuffer(); ANativeWindowBuffer* mNativeWindowBuffer = mBuffer->getNativeBuffer(); - mock::EventThread* mEventThread = new mock::EventThread(); + std::unique_ptr<mock::EventThread> mEventThread = std::make_unique<mock::EventThread>(); mock::EventControlThread* mEventControlThread = new mock::EventControlThread(); Hwc2::mock::Composer* mComposer = nullptr; diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp index 6659d4ac8e..19f308b62a 100644 --- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp +++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp @@ -29,6 +29,7 @@ #include <ui/DebugUtils.h> #include "DisplayIdentificationTest.h" +#include "TestableScheduler.h" #include "TestableSurfaceFlinger.h" #include "mock/DisplayHardware/MockComposer.h" #include "mock/MockDispSync.h" @@ -94,6 +95,8 @@ public: DisplayTransactionTest(); ~DisplayTransactionTest() override; + void setupScheduler(); + // -------------------------------------------------------------------- // Mock/Fake injection @@ -116,6 +119,7 @@ public: // -------------------------------------------------------------------- // Test instances + TestableScheduler* mScheduler; TestableSurfaceFlinger mFlinger; mock::EventThread* mEventThread = new mock::EventThread(); mock::EventThread* mSFEventThread = new mock::EventThread(); @@ -160,13 +164,10 @@ DisplayTransactionTest::DisplayTransactionTest() { return nullptr; }); - mFlinger.mutableEventControlThread().reset(mEventControlThread); - mFlinger.mutableEventThread().reset(mEventThread); - mFlinger.mutableSFEventThread().reset(mSFEventThread); + setupScheduler(); mFlinger.mutableEventQueue().reset(mMessageQueue); mFlinger.setupRenderEngine(std::unique_ptr<renderengine::RenderEngine>(mRenderEngine)); mFlinger.mutableInterceptor().reset(mSurfaceInterceptor); - mFlinger.mutablePrimaryDispSync().reset(mPrimaryDispSync); injectMockComposer(0); } @@ -177,6 +178,22 @@ DisplayTransactionTest::~DisplayTransactionTest() { ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name()); } +void DisplayTransactionTest::setupScheduler() { + mScheduler = new TestableScheduler(); + mScheduler->mutableEventControlThread().reset(mEventControlThread); + mScheduler->mutablePrimaryDispSync().reset(mPrimaryDispSync); + 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); +} + void DisplayTransactionTest::injectMockComposer(int virtualDisplayCount) { mComposer = new Hwc2::mock::Composer(); EXPECT_CALL(*mComposer, getCapabilities()) @@ -1106,8 +1123,8 @@ TEST_F(DisplayTransactionTest, resetDisplayStateClearsState) { // Preconditions // vsync is enabled and available - mFlinger.mutablePrimaryHWVsyncEnabled() = true; - mFlinger.mutableHWVsyncAvailable() = true; + mScheduler->mutablePrimaryHWVsyncEnabled() = true; + mScheduler->mutableHWVsyncAvailable() = true; // A display exists auto existing = Case::Display::makeFakeExistingDisplayInjector(this); @@ -1131,8 +1148,8 @@ TEST_F(DisplayTransactionTest, resetDisplayStateClearsState) { // Postconditions // vsyncs should be off and not available. - EXPECT_FALSE(mFlinger.mutablePrimaryHWVsyncEnabled()); - EXPECT_FALSE(mFlinger.mutableHWVsyncAvailable()); + EXPECT_FALSE(mScheduler->mutablePrimaryHWVsyncEnabled()); + EXPECT_FALSE(mScheduler->mutableHWVsyncAvailable()); // The display should have been removed from the display map. EXPECT_FALSE(hasDisplayDevice(existing.token())); @@ -1557,7 +1574,6 @@ void HandleTransactionLockedTest::setupCommonCallExpectationsForConnectProcessin Case::PerFrameMetadataSupport::setupComposerCallExpectations(this); EXPECT_CALL(*mSurfaceInterceptor, saveDisplayCreation(_)).Times(1); - expectHotplugReceived<Case, true>(mEventThread); expectHotplugReceived<Case, true>(mSFEventThread); } @@ -3008,7 +3024,7 @@ struct DisplayPowerCase { } static void setInitialPrimaryHWVsyncEnabled(DisplayTransactionTest* test, bool enabled) { - test->mFlinger.mutablePrimaryHWVsyncEnabled() = enabled; + test->mScheduler->mutablePrimaryHWVsyncEnabled() = enabled; } static void setupRepaintEverythingCallExpectations(DisplayTransactionTest* test) { diff --git a/services/surfaceflinger/tests/unittests/TestableScheduler.h b/services/surfaceflinger/tests/unittests/TestableScheduler.h new file mode 100644 index 0000000000..dcbf973d2c --- /dev/null +++ b/services/surfaceflinger/tests/unittests/TestableScheduler.h @@ -0,0 +1,65 @@ +/* + * Copyright 2019 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. + */ + +#pragma once + +#include <gmock/gmock.h> + +#include "Scheduler/EventThread.h" +#include "Scheduler/Scheduler.h" + +namespace android { + +class TestableScheduler : public Scheduler { +public: + TestableScheduler() : Scheduler([](bool) {}) {} + + // Creates EventThreadConnection with the given eventThread. Creates Scheduler::Connection + // and adds it to the list of connectins. Returns the ConnectionHandle for the + // Scheduler::Connection. This allows plugging in mock::EventThread. + sp<Scheduler::ConnectionHandle> addConnection(std::unique_ptr<EventThread> eventThread) { + sp<EventThreadConnection> eventThreadConnection = + new EventThreadConnection(eventThread.get(), ResyncCallback(), + ResetIdleTimerCallback()); + const int64_t id = sNextId++; + mConnections.emplace(id, + std::make_unique<Scheduler::Connection>(new ConnectionHandle(id), + eventThreadConnection, + std::move(eventThread))); + return mConnections[id]->handle; + } + + /* ------------------------------------------------------------------------ + * Read-write access to private data to set up preconditions and assert + * post-conditions. + */ + auto& mutablePrimaryHWVsyncEnabled() { return mPrimaryHWVsyncEnabled; } + auto& mutableEventControlThread() { return mEventControlThread; } + auto& mutablePrimaryDispSync() { return mPrimaryDispSync; } + auto& mutableHWVsyncAvailable() { return mHWVsyncAvailable; } + + ~TestableScheduler() { + // All these pointer and container clears help ensure that GMock does + // not report a leaked object, since the Scheduler instance may + // still be referenced by something despite our best efforts to destroy + // it after each test is done. + 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 959126ef08..6313f1f10b 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -299,7 +299,6 @@ public: const auto& getAnimFrameTracker() const { return mFlinger->mAnimFrameTracker; } const auto& getHasPoweredOff() const { return mFlinger->mHasPoweredOff; } - const auto& getHWVsyncAvailable() const { return mFlinger->mHWVsyncAvailable; } const auto& getVisibleRegionsDirty() const { return mFlinger->mVisibleRegionsDirty; } auto& getHwComposer() const { return static_cast<impl::HWComposer&>(mFlinger->getHwComposer()); @@ -320,18 +319,12 @@ public: auto& mutableDisplayColorSetting() { return mFlinger->mDisplayColorSetting; } auto& mutableDisplays() { return mFlinger->mDisplays; } auto& mutableDrawingState() { return mFlinger->mDrawingState; } - auto& mutableEventControlThread() { return mFlinger->mEventControlThread; } auto& mutableEventQueue() { return mFlinger->mEventQueue; } - auto& mutableEventThread() { return mFlinger->mEventThread; } - auto& mutableSFEventThread() { return mFlinger->mSFEventThread; } auto& mutableGeometryInvalid() { return mFlinger->mGeometryInvalid; } - auto& mutableHWVsyncAvailable() { return mFlinger->mHWVsyncAvailable; } auto& mutableInterceptor() { return mFlinger->mInterceptor; } auto& mutableMainThreadId() { return mFlinger->mMainThreadId; } auto& mutablePendingHotplugEvents() { return mFlinger->mPendingHotplugEvents; } auto& mutablePhysicalDisplayTokens() { return mFlinger->mPhysicalDisplayTokens; } - auto& mutablePrimaryDispSync() { return mFlinger->mPrimaryDispSync; } - auto& mutablePrimaryHWVsyncEnabled() { return mFlinger->mPrimaryHWVsyncEnabled; } auto& mutableTexturePool() { return mFlinger->mTexturePool; } auto& mutableTransactionFlags() { return mFlinger->mTransactionFlags; } auto& mutableUseHwcVirtualDisplays() { return mFlinger->mUseHwcVirtualDisplays; } @@ -341,6 +334,9 @@ public: 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; } ~TestableSurfaceFlinger() { // All these pointer and container clears help ensure that GMock does @@ -348,12 +344,9 @@ public: // still be referenced by something despite our best efforts to destroy // it after each test is done. mutableDisplays().clear(); - mutableEventControlThread().reset(); mutableEventQueue().reset(); - mutableEventThread().reset(); - mutableSFEventThread().reset(); mutableInterceptor().reset(); - mutablePrimaryDispSync().reset(); + mutableScheduler().reset(); mFlinger->mCompositionEngine->setHwComposer(std::unique_ptr<HWComposer>()); mFlinger->mCompositionEngine->setRenderEngine( std::unique_ptr<renderengine::RenderEngine>()); |