SF: Adding testable Scheduler and updating tests.
This follows ag/6337080 for clearity
Test: updating tests.
Bug: 123998711
Change-Id: I8999b3a1f002a9f5fb705e7de61294e9bc094298
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index 10ffc7a..7b5278c 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -144,6 +144,8 @@
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 3addd61..3101a9b 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 @@
::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 @@
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 @@
std::unordered_set<HWC2::Capability> mDefaultCapabilities = {HWC2::Capability::SidebandStream};
+ TestableScheduler* mScheduler;
TestableSurfaceFlinger mFlinger;
sp<DisplayDevice> mDisplay;
sp<DisplayDevice> mExternalDisplay;
@@ -155,7 +167,7 @@
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 6659d4a..19f308b 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 @@
DisplayTransactionTest();
~DisplayTransactionTest() override;
+ void setupScheduler();
+
// --------------------------------------------------------------------
// Mock/Fake injection
@@ -116,6 +119,7 @@
// --------------------------------------------------------------------
// Test instances
+ TestableScheduler* mScheduler;
TestableSurfaceFlinger mFlinger;
mock::EventThread* mEventThread = new mock::EventThread();
mock::EventThread* mSFEventThread = new mock::EventThread();
@@ -160,13 +164,10 @@
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 @@
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 @@
// 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 @@
// 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 @@
Case::PerFrameMetadataSupport::setupComposerCallExpectations(this);
EXPECT_CALL(*mSurfaceInterceptor, saveDisplayCreation(_)).Times(1);
-
expectHotplugReceived<Case, true>(mEventThread);
expectHotplugReceived<Case, true>(mSFEventThread);
}
@@ -3008,7 +3024,7 @@
}
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 0000000..dcbf973
--- /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 959126e..6313f1f 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -299,7 +299,6 @@
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 @@
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 @@
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 @@
// 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>());