Loading services/surfaceflinger/Scheduler/DispSync.cpp +4 −1 Original line number Diff line number Diff line Loading @@ -453,7 +453,10 @@ DispSync::DispSync(const char* name) : mName(name), mRefreshSkipCount(0) { mThread = new DispSyncThread(name, mTraceDetailedInfo); } DispSync::~DispSync() {} DispSync::~DispSync() { mThread->stop(); mThread->requestExitAndWait(); } void DispSync::init(bool hasSyncFramework, int64_t dispSyncPresentTimeOffset) { mIgnorePresentFences = !hasSyncFramework; Loading services/surfaceflinger/tests/Transaction_test.cpp +62 −1 Original line number Diff line number Diff line Loading @@ -32,8 +32,9 @@ #include <gui/LayerState.h> #include <gui/Surface.h> #include <gui/SurfaceComposerClient.h> #include <private/gui/ComposerService.h> #include <hardware/hwcomposer_defs.h> #include <private/android_filesystem_config.h> #include <private/gui/ComposerService.h> #include <ui/ColorSpace.h> #include <ui/DisplayInfo.h> Loading Loading @@ -5522,4 +5523,64 @@ TEST_F(MultiDisplayLayerBoundsTest, RenderLayerInMirroredVirtualDisplay) { sc->expectColor(Rect(0, 0, 9, 9), {0, 0, 0, 255}); } class DisplayActiveConfigTest : public ::testing::Test { protected: void SetUp() override { mDisplayToken = SurfaceComposerClient::getInternalDisplayToken(); SurfaceComposerClient::getDisplayConfigs(mDisplayToken, &mDisplayconfigs); EXPECT_GT(mDisplayconfigs.size(), 0); // set display power to on to make sure config can be changed SurfaceComposerClient::setDisplayPowerMode(mDisplayToken, HWC_POWER_MODE_NORMAL); } sp<IBinder> mDisplayToken; Vector<DisplayInfo> mDisplayconfigs; }; TEST_F(DisplayActiveConfigTest, allConfigsAllowed) { std::vector<int32_t> allowedConfigs; // Add all configs to the allowed configs for (int i = 0; i < mDisplayconfigs.size(); i++) { allowedConfigs.push_back(i); } status_t res = SurfaceComposerClient::setAllowedDisplayConfigs(mDisplayToken, allowedConfigs); EXPECT_EQ(res, NO_ERROR); std::vector<int32_t> outConfigs; res = SurfaceComposerClient::getAllowedDisplayConfigs(mDisplayToken, &outConfigs); EXPECT_EQ(res, NO_ERROR); EXPECT_EQ(allowedConfigs, outConfigs); } TEST_F(DisplayActiveConfigTest, changeAllowedConfig) { // we need at least 2 configs available for this test if (mDisplayconfigs.size() <= 1) return; int activeConfig = SurfaceComposerClient::getActiveConfig(mDisplayToken); // We want to set the allowed config to everything but the active config std::vector<int32_t> allowedConfigs; for (int i = 0; i < mDisplayconfigs.size(); i++) { if (i != activeConfig) { allowedConfigs.push_back(i); } } status_t res = SurfaceComposerClient::setAllowedDisplayConfigs(mDisplayToken, allowedConfigs); EXPECT_EQ(res, NO_ERROR); // Allow some time for the config change std::this_thread::sleep_for(200ms); int newActiveConfig = SurfaceComposerClient::getActiveConfig(mDisplayToken); EXPECT_NE(activeConfig, newActiveConfig); // Make sure the new config is part of allowed config EXPECT_TRUE(std::find(allowedConfigs.begin(), allowedConfigs.end(), newActiveConfig) != allowedConfigs.end()); } } // namespace android services/surfaceflinger/tests/unittests/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -37,6 +37,7 @@ cc_test { "libsurfaceflinger_unittest_main.cpp", "AllowedDisplayConfigsTest.cpp", "CompositionTest.cpp", "DispSyncSourceTest.cpp", "DisplayIdentificationTest.cpp", "DisplayTransactionTest.cpp", "EventControlThreadTest.cpp", Loading services/surfaceflinger/tests/unittests/DispSyncSourceTest.cpp 0 → 100644 +164 −0 Original line number Diff line number Diff line /* * 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. */ #undef LOG_TAG #define LOG_TAG "LibSurfaceFlingerUnittests" #define LOG_NDEBUG 0 #include <inttypes.h> #include <gmock/gmock.h> #include <gtest/gtest.h> #include <log/log.h> #include "AsyncCallRecorder.h" #include "Scheduler/DispSyncSource.h" #include "mock/MockDispSync.h" namespace android { namespace { using namespace std::chrono_literals; using testing::Return; class DispSyncSourceTest : public testing::Test, private VSyncSource::Callback { protected: DispSyncSourceTest(); ~DispSyncSourceTest() override; void createDispSync(); void createDispSyncSource(); void onVSyncEvent(nsecs_t when) override; std::unique_ptr<mock::DispSync> mDispSync; std::unique_ptr<DispSyncSource> mDispSyncSource; AsyncCallRecorder<void (*)(nsecs_t)> mVSyncEventCallRecorder; static constexpr std::chrono::nanoseconds mPhaseOffset = 6ms; static constexpr int mIterations = 100; }; DispSyncSourceTest::DispSyncSourceTest() { const ::testing::TestInfo* const test_info = ::testing::UnitTest::GetInstance()->current_test_info(); ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name()); } DispSyncSourceTest::~DispSyncSourceTest() { const ::testing::TestInfo* const test_info = ::testing::UnitTest::GetInstance()->current_test_info(); ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name()); } void DispSyncSourceTest::onVSyncEvent(nsecs_t when) { ALOGD("onVSyncEvent: %" PRId64, when); mVSyncEventCallRecorder.recordCall(when); } void DispSyncSourceTest::createDispSync() { mDispSync = std::make_unique<mock::DispSync>(); } void DispSyncSourceTest::createDispSyncSource() { createDispSync(); mDispSyncSource = std::make_unique<DispSyncSource>(mDispSync.get(), mPhaseOffset.count(), true, "DispSyncSourceTest"); mDispSyncSource->setCallback(this); } /* ------------------------------------------------------------------------ * Test cases */ TEST_F(DispSyncSourceTest, createDispSync) { createDispSync(); EXPECT_TRUE(mDispSync); } TEST_F(DispSyncSourceTest, createDispSyncSource) { createDispSyncSource(); EXPECT_TRUE(mDispSyncSource); } TEST_F(DispSyncSourceTest, noCallbackAfterInit) { createDispSyncSource(); EXPECT_TRUE(mDispSyncSource); // DispSyncSource starts with Vsync disabled mDispSync->triggerCallback(); EXPECT_FALSE(mVSyncEventCallRecorder.waitForUnexpectedCall().has_value()); } TEST_F(DispSyncSourceTest, waitForCallbacks) { createDispSyncSource(); EXPECT_TRUE(mDispSyncSource); mDispSyncSource->setVSyncEnabled(true); EXPECT_EQ(mDispSync->getCallbackPhase(), mPhaseOffset.count()); for (int i = 0; i < mIterations; i++) { mDispSync->triggerCallback(); EXPECT_TRUE(mVSyncEventCallRecorder.waitForCall().has_value()); } } TEST_F(DispSyncSourceTest, waitForCallbacksWithPhaseChange) { createDispSyncSource(); EXPECT_TRUE(mDispSyncSource); mDispSyncSource->setVSyncEnabled(true); EXPECT_EQ(mDispSync->getCallbackPhase(), mPhaseOffset.count()); for (int i = 0; i < mIterations; i++) { mDispSync->triggerCallback(); EXPECT_TRUE(mVSyncEventCallRecorder.waitForCall().has_value()); } EXPECT_CALL(*mDispSync, getPeriod()).Times(1).WillOnce(Return(16666666)); mDispSyncSource->setPhaseOffset((mPhaseOffset / 2).count()); EXPECT_EQ(mDispSync->getCallbackPhase(), (mPhaseOffset / 2).count()); for (int i = 0; i < mIterations; i++) { mDispSync->triggerCallback(); EXPECT_TRUE(mVSyncEventCallRecorder.waitForCall().has_value()); } } TEST_F(DispSyncSourceTest, pauseCallbacks) { createDispSyncSource(); EXPECT_TRUE(mDispSyncSource); mDispSyncSource->setVSyncEnabled(true); EXPECT_EQ(mDispSync->getCallbackPhase(), mPhaseOffset.count()); mDispSync->triggerCallback(); EXPECT_TRUE(mVSyncEventCallRecorder.waitForCall().has_value()); mDispSyncSource->pauseVsyncCallback(true); mDispSync->triggerCallback(); EXPECT_FALSE(mVSyncEventCallRecorder.waitForUnexpectedCall().has_value()); mDispSyncSource->pauseVsyncCallback(false); mDispSync->triggerCallback(); EXPECT_TRUE(mVSyncEventCallRecorder.waitForUnexpectedCall().has_value()); } } // namespace } // namespace android services/surfaceflinger/tests/unittests/mock/MockDispSync.cpp +35 −0 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ */ #include "mock/MockDispSync.h" #include <thread> namespace android { namespace mock { Loading @@ -23,5 +24,39 @@ namespace mock { DispSync::DispSync() = default; DispSync::~DispSync() = default; status_t DispSync::addEventListener(const char* /*name*/, nsecs_t phase, Callback* callback, nsecs_t /*lastCallbackTime*/) { if (mCallback.callback != nullptr) { return BAD_VALUE; } mCallback = {callback, phase}; return NO_ERROR; } status_t DispSync::removeEventListener(Callback* callback, nsecs_t* /*outLastCallback*/) { if (mCallback.callback != callback) { return BAD_VALUE; } mCallback = {nullptr, 0}; return NO_ERROR; } status_t DispSync::changePhaseOffset(Callback* callback, nsecs_t phase) { if (mCallback.callback != callback) { return BAD_VALUE; } mCallback.phase = phase; return NO_ERROR; } void DispSync::triggerCallback() { if (mCallback.callback == nullptr) return; mCallback.callback->onDispSyncEvent( std::chrono::steady_clock::now().time_since_epoch().count()); } } // namespace mock } // namespace android Loading
services/surfaceflinger/Scheduler/DispSync.cpp +4 −1 Original line number Diff line number Diff line Loading @@ -453,7 +453,10 @@ DispSync::DispSync(const char* name) : mName(name), mRefreshSkipCount(0) { mThread = new DispSyncThread(name, mTraceDetailedInfo); } DispSync::~DispSync() {} DispSync::~DispSync() { mThread->stop(); mThread->requestExitAndWait(); } void DispSync::init(bool hasSyncFramework, int64_t dispSyncPresentTimeOffset) { mIgnorePresentFences = !hasSyncFramework; Loading
services/surfaceflinger/tests/Transaction_test.cpp +62 −1 Original line number Diff line number Diff line Loading @@ -32,8 +32,9 @@ #include <gui/LayerState.h> #include <gui/Surface.h> #include <gui/SurfaceComposerClient.h> #include <private/gui/ComposerService.h> #include <hardware/hwcomposer_defs.h> #include <private/android_filesystem_config.h> #include <private/gui/ComposerService.h> #include <ui/ColorSpace.h> #include <ui/DisplayInfo.h> Loading Loading @@ -5522,4 +5523,64 @@ TEST_F(MultiDisplayLayerBoundsTest, RenderLayerInMirroredVirtualDisplay) { sc->expectColor(Rect(0, 0, 9, 9), {0, 0, 0, 255}); } class DisplayActiveConfigTest : public ::testing::Test { protected: void SetUp() override { mDisplayToken = SurfaceComposerClient::getInternalDisplayToken(); SurfaceComposerClient::getDisplayConfigs(mDisplayToken, &mDisplayconfigs); EXPECT_GT(mDisplayconfigs.size(), 0); // set display power to on to make sure config can be changed SurfaceComposerClient::setDisplayPowerMode(mDisplayToken, HWC_POWER_MODE_NORMAL); } sp<IBinder> mDisplayToken; Vector<DisplayInfo> mDisplayconfigs; }; TEST_F(DisplayActiveConfigTest, allConfigsAllowed) { std::vector<int32_t> allowedConfigs; // Add all configs to the allowed configs for (int i = 0; i < mDisplayconfigs.size(); i++) { allowedConfigs.push_back(i); } status_t res = SurfaceComposerClient::setAllowedDisplayConfigs(mDisplayToken, allowedConfigs); EXPECT_EQ(res, NO_ERROR); std::vector<int32_t> outConfigs; res = SurfaceComposerClient::getAllowedDisplayConfigs(mDisplayToken, &outConfigs); EXPECT_EQ(res, NO_ERROR); EXPECT_EQ(allowedConfigs, outConfigs); } TEST_F(DisplayActiveConfigTest, changeAllowedConfig) { // we need at least 2 configs available for this test if (mDisplayconfigs.size() <= 1) return; int activeConfig = SurfaceComposerClient::getActiveConfig(mDisplayToken); // We want to set the allowed config to everything but the active config std::vector<int32_t> allowedConfigs; for (int i = 0; i < mDisplayconfigs.size(); i++) { if (i != activeConfig) { allowedConfigs.push_back(i); } } status_t res = SurfaceComposerClient::setAllowedDisplayConfigs(mDisplayToken, allowedConfigs); EXPECT_EQ(res, NO_ERROR); // Allow some time for the config change std::this_thread::sleep_for(200ms); int newActiveConfig = SurfaceComposerClient::getActiveConfig(mDisplayToken); EXPECT_NE(activeConfig, newActiveConfig); // Make sure the new config is part of allowed config EXPECT_TRUE(std::find(allowedConfigs.begin(), allowedConfigs.end(), newActiveConfig) != allowedConfigs.end()); } } // namespace android
services/surfaceflinger/tests/unittests/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -37,6 +37,7 @@ cc_test { "libsurfaceflinger_unittest_main.cpp", "AllowedDisplayConfigsTest.cpp", "CompositionTest.cpp", "DispSyncSourceTest.cpp", "DisplayIdentificationTest.cpp", "DisplayTransactionTest.cpp", "EventControlThreadTest.cpp", Loading
services/surfaceflinger/tests/unittests/DispSyncSourceTest.cpp 0 → 100644 +164 −0 Original line number Diff line number Diff line /* * 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. */ #undef LOG_TAG #define LOG_TAG "LibSurfaceFlingerUnittests" #define LOG_NDEBUG 0 #include <inttypes.h> #include <gmock/gmock.h> #include <gtest/gtest.h> #include <log/log.h> #include "AsyncCallRecorder.h" #include "Scheduler/DispSyncSource.h" #include "mock/MockDispSync.h" namespace android { namespace { using namespace std::chrono_literals; using testing::Return; class DispSyncSourceTest : public testing::Test, private VSyncSource::Callback { protected: DispSyncSourceTest(); ~DispSyncSourceTest() override; void createDispSync(); void createDispSyncSource(); void onVSyncEvent(nsecs_t when) override; std::unique_ptr<mock::DispSync> mDispSync; std::unique_ptr<DispSyncSource> mDispSyncSource; AsyncCallRecorder<void (*)(nsecs_t)> mVSyncEventCallRecorder; static constexpr std::chrono::nanoseconds mPhaseOffset = 6ms; static constexpr int mIterations = 100; }; DispSyncSourceTest::DispSyncSourceTest() { const ::testing::TestInfo* const test_info = ::testing::UnitTest::GetInstance()->current_test_info(); ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name()); } DispSyncSourceTest::~DispSyncSourceTest() { const ::testing::TestInfo* const test_info = ::testing::UnitTest::GetInstance()->current_test_info(); ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name()); } void DispSyncSourceTest::onVSyncEvent(nsecs_t when) { ALOGD("onVSyncEvent: %" PRId64, when); mVSyncEventCallRecorder.recordCall(when); } void DispSyncSourceTest::createDispSync() { mDispSync = std::make_unique<mock::DispSync>(); } void DispSyncSourceTest::createDispSyncSource() { createDispSync(); mDispSyncSource = std::make_unique<DispSyncSource>(mDispSync.get(), mPhaseOffset.count(), true, "DispSyncSourceTest"); mDispSyncSource->setCallback(this); } /* ------------------------------------------------------------------------ * Test cases */ TEST_F(DispSyncSourceTest, createDispSync) { createDispSync(); EXPECT_TRUE(mDispSync); } TEST_F(DispSyncSourceTest, createDispSyncSource) { createDispSyncSource(); EXPECT_TRUE(mDispSyncSource); } TEST_F(DispSyncSourceTest, noCallbackAfterInit) { createDispSyncSource(); EXPECT_TRUE(mDispSyncSource); // DispSyncSource starts with Vsync disabled mDispSync->triggerCallback(); EXPECT_FALSE(mVSyncEventCallRecorder.waitForUnexpectedCall().has_value()); } TEST_F(DispSyncSourceTest, waitForCallbacks) { createDispSyncSource(); EXPECT_TRUE(mDispSyncSource); mDispSyncSource->setVSyncEnabled(true); EXPECT_EQ(mDispSync->getCallbackPhase(), mPhaseOffset.count()); for (int i = 0; i < mIterations; i++) { mDispSync->triggerCallback(); EXPECT_TRUE(mVSyncEventCallRecorder.waitForCall().has_value()); } } TEST_F(DispSyncSourceTest, waitForCallbacksWithPhaseChange) { createDispSyncSource(); EXPECT_TRUE(mDispSyncSource); mDispSyncSource->setVSyncEnabled(true); EXPECT_EQ(mDispSync->getCallbackPhase(), mPhaseOffset.count()); for (int i = 0; i < mIterations; i++) { mDispSync->triggerCallback(); EXPECT_TRUE(mVSyncEventCallRecorder.waitForCall().has_value()); } EXPECT_CALL(*mDispSync, getPeriod()).Times(1).WillOnce(Return(16666666)); mDispSyncSource->setPhaseOffset((mPhaseOffset / 2).count()); EXPECT_EQ(mDispSync->getCallbackPhase(), (mPhaseOffset / 2).count()); for (int i = 0; i < mIterations; i++) { mDispSync->triggerCallback(); EXPECT_TRUE(mVSyncEventCallRecorder.waitForCall().has_value()); } } TEST_F(DispSyncSourceTest, pauseCallbacks) { createDispSyncSource(); EXPECT_TRUE(mDispSyncSource); mDispSyncSource->setVSyncEnabled(true); EXPECT_EQ(mDispSync->getCallbackPhase(), mPhaseOffset.count()); mDispSync->triggerCallback(); EXPECT_TRUE(mVSyncEventCallRecorder.waitForCall().has_value()); mDispSyncSource->pauseVsyncCallback(true); mDispSync->triggerCallback(); EXPECT_FALSE(mVSyncEventCallRecorder.waitForUnexpectedCall().has_value()); mDispSyncSource->pauseVsyncCallback(false); mDispSync->triggerCallback(); EXPECT_TRUE(mVSyncEventCallRecorder.waitForUnexpectedCall().has_value()); } } // namespace } // namespace android
services/surfaceflinger/tests/unittests/mock/MockDispSync.cpp +35 −0 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ */ #include "mock/MockDispSync.h" #include <thread> namespace android { namespace mock { Loading @@ -23,5 +24,39 @@ namespace mock { DispSync::DispSync() = default; DispSync::~DispSync() = default; status_t DispSync::addEventListener(const char* /*name*/, nsecs_t phase, Callback* callback, nsecs_t /*lastCallbackTime*/) { if (mCallback.callback != nullptr) { return BAD_VALUE; } mCallback = {callback, phase}; return NO_ERROR; } status_t DispSync::removeEventListener(Callback* callback, nsecs_t* /*outLastCallback*/) { if (mCallback.callback != callback) { return BAD_VALUE; } mCallback = {nullptr, 0}; return NO_ERROR; } status_t DispSync::changePhaseOffset(Callback* callback, nsecs_t phase) { if (mCallback.callback != callback) { return BAD_VALUE; } mCallback.phase = phase; return NO_ERROR; } void DispSync::triggerCallback() { if (mCallback.callback == nullptr) return; mCallback.callback->onDispSyncEvent( std::chrono::steady_clock::now().time_since_epoch().count()); } } // namespace mock } // namespace android