diff options
Diffstat (limited to 'services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp')
-rw-r--r-- | services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp | 905 |
1 files changed, 567 insertions, 338 deletions
diff --git a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp index 162711d6f5..a03fd89297 100644 --- a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp +++ b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp @@ -17,7 +17,6 @@ // TODO(b/129481165): remove the #pragma below and fix conversion issues #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wconversion" -#pragma clang diagnostic ignored "-Wextra" // #define LOG_NDEBUG 0 #undef LOG_TAG @@ -28,7 +27,6 @@ #include "FakeComposerUtils.h" #include "MockComposerHal.h" -#include <binder/Parcel.h> #include <gui/DisplayEventReceiver.h> #include <gui/ISurfaceComposer.h> #include <gui/LayerDebugInfo.h> @@ -43,8 +41,7 @@ #include <hwbinder/ProcessState.h> #include <log/log.h> #include <private/gui/ComposerService.h> -#include <ui/DisplayMode.h> -#include <ui/DynamicDisplayInfo.h> +#include <ui/DisplayConfig.h> #include <utils/Looper.h> #include <gmock/gmock.h> @@ -64,20 +61,16 @@ namespace { // Mock test helpers using ::testing::_; +using ::testing::AtLeast; using ::testing::DoAll; +using ::testing::Invoke; using ::testing::Return; using ::testing::SetArgPointee; using Transaction = SurfaceComposerClient::Transaction; using Attribute = V2_4::IComposerClient::Attribute; -using Display = V2_1::Display; /////////////////////////////////////////////// -constexpr PhysicalDisplayId physicalIdFromHwcDisplayId(Display hwcId) { - return PhysicalDisplayId::fromPort(hwcId); -} -constexpr PhysicalDisplayId kPrimaryDisplayId = physicalIdFromHwcDisplayId(PRIMARY_DISPLAY); -constexpr PhysicalDisplayId kExternalDisplayId = physicalIdFromHwcDisplayId(EXTERNAL_DISPLAY); struct TestColor { public: @@ -91,6 +84,7 @@ constexpr static TestColor RED = {195, 63, 63, 255}; constexpr static TestColor LIGHT_RED = {255, 177, 177, 255}; constexpr static TestColor GREEN = {63, 195, 63, 255}; constexpr static TestColor BLUE = {63, 63, 195, 255}; +constexpr static TestColor DARK_GRAY = {63, 63, 63, 255}; constexpr static TestColor LIGHT_GRAY = {200, 200, 200, 255}; // Fill an RGBA_8888 formatted surface with a single color. @@ -158,7 +152,7 @@ protected: self->mReceivedDisplayEvents.push_back(buffer[i]); } } - ALOGD_IF(n < 0, "Error reading events (%s)", strerror(-n)); + ALOGD_IF(n < 0, "Error reading events (%s)\n", strerror(-n)); return 1; } @@ -174,7 +168,7 @@ protected: void setExpectationsForConfigs(Display display, std::vector<TestConfig> testConfigs, Config activeConfig, V2_4::VsyncPeriodNanos defaultVsyncPeriod) { std::vector<Config> configIds; - for (size_t i = 0; i < testConfigs.size(); i++) { + for (int i = 0; i < testConfigs.size(); i++) { configIds.push_back(testConfigs[i].id); EXPECT_CALL(*mMockComposer, @@ -244,7 +238,7 @@ protected: ASSERT_EQ(NO_ERROR, mComposerClient->initCheck()); mReceiver.reset(new DisplayEventReceiver(ISurfaceComposer::eVsyncSourceApp, - ISurfaceComposer::EventRegistration::modeChanged)); + ISurfaceComposer::eConfigChangedDispatch)); mLooper = new Looper(false); mLooper->addFd(mReceiver->getFd(), 0, ALOOPER_EVENT_INPUT, processDisplayEvents, this); } @@ -268,20 +262,16 @@ protected: mMockComposer = nullptr; } - void waitForDisplayTransaction(Display display) { + void waitForDisplayTransaction() { // Both a refresh and a vsync event are needed to apply pending display // transactions. - mFakeComposerClient->refreshDisplay(display); + mFakeComposerClient->refreshDisplay(EXTERNAL_DISPLAY); mFakeComposerClient->runVSyncAndWait(); // Extra vsync and wait to avoid a 10% flake due to a race. mFakeComposerClient->runVSyncAndWait(); } - bool waitForHotplugEvent(Display displayId, bool connected) { - return waitForHotplugEvent(PhysicalDisplayId(displayId), connected); - } - bool waitForHotplugEvent(PhysicalDisplayId displayId, bool connected) { int waitCount = 20; while (waitCount--) { @@ -290,8 +280,9 @@ protected: mReceivedDisplayEvents.pop_front(); ALOGV_IF(event.header.type == DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG, - "event hotplug: displayId %s, connected %d", - to_string(event.header.displayId).c_str(), event.hotplug.connected); + "event hotplug: displayId %" ANDROID_PHYSICAL_DISPLAY_ID_FORMAT + ", connected %d\t", + event.header.displayId, event.hotplug.connected); if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG && event.header.displayId == displayId && event.hotplug.connected == connected) { @@ -304,20 +295,20 @@ protected: return false; } - bool waitForModeChangedEvent(Display display, int32_t modeId) { - PhysicalDisplayId displayId(display); + bool waitForConfigChangedEvent(PhysicalDisplayId displayId, int32_t configId) { int waitCount = 20; while (waitCount--) { while (!mReceivedDisplayEvents.empty()) { auto event = mReceivedDisplayEvents.front(); mReceivedDisplayEvents.pop_front(); - ALOGV_IF(event.header.type == DisplayEventReceiver::DISPLAY_EVENT_MODE_CHANGE, - "event mode: displayId %s, modeId %d", - to_string(event.header.displayId).c_str(), event.modeChange.modeId); + ALOGV_IF(event.header.type == DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED, + "event config: displayId %" ANDROID_PHYSICAL_DISPLAY_ID_FORMAT + ", configId %d\t", + event.header.displayId, event.config.configId); - if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_MODE_CHANGE && - event.header.displayId == displayId && event.modeChange.modeId == modeId) { + if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED && + event.header.displayId == displayId && event.config.configId == configId) { return true; } } @@ -340,18 +331,18 @@ protected: mFakeComposerClient->hotplugDisplay(EXTERNAL_DISPLAY, V2_1::IComposerCallback::Connection::CONNECTED); - waitForDisplayTransaction(EXTERNAL_DISPLAY); + waitForDisplayTransaction(); EXPECT_TRUE(waitForHotplugEvent(EXTERNAL_DISPLAY, true)); { - const auto display = SurfaceComposerClient::getPhysicalDisplayToken(kExternalDisplayId); + const auto display = SurfaceComposerClient::getPhysicalDisplayToken(EXTERNAL_DISPLAY); EXPECT_FALSE(display == nullptr); - ui::DisplayMode mode; - EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayMode(display, &mode)); - const ui::Size& resolution = mode.resolution; + DisplayConfig config; + EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayConfig(display, &config)); + const ui::Size& resolution = config.resolution; EXPECT_EQ(ui::Size(200, 400), resolution); - EXPECT_EQ(1e9f / 16'666'666, mode.refreshRate); + EXPECT_EQ(1e9f / 16'666'666, config.refreshRate); auto surfaceControl = mComposerClient->createSurface(String8("Display Test Surface Foo"), @@ -371,16 +362,16 @@ protected: mFakeComposerClient->hotplugDisplay(EXTERNAL_DISPLAY, V2_1::IComposerCallback::Connection::DISCONNECTED); - waitForDisplayTransaction(EXTERNAL_DISPLAY); + waitForDisplayTransaction(); mFakeComposerClient->clearFrames(); EXPECT_TRUE(waitForHotplugEvent(EXTERNAL_DISPLAY, false)); { - const auto display = SurfaceComposerClient::getPhysicalDisplayToken(kExternalDisplayId); + const auto display = SurfaceComposerClient::getPhysicalDisplayToken(EXTERNAL_DISPLAY); EXPECT_TRUE(display == nullptr); - ui::DisplayMode mode; - EXPECT_NE(NO_ERROR, SurfaceComposerClient::getActiveDisplayMode(display, &mode)); + DisplayConfig config; + EXPECT_NE(NO_ERROR, SurfaceComposerClient::getActiveDisplayConfig(display, &config)); } } @@ -402,20 +393,20 @@ protected: mFakeComposerClient->hotplugDisplay(EXTERNAL_DISPLAY, V2_1::IComposerCallback::Connection::CONNECTED); - waitForDisplayTransaction(EXTERNAL_DISPLAY); + waitForDisplayTransaction(); EXPECT_TRUE(waitForHotplugEvent(EXTERNAL_DISPLAY, true)); - const auto display = SurfaceComposerClient::getPhysicalDisplayToken(kExternalDisplayId); + const auto display = SurfaceComposerClient::getPhysicalDisplayToken(EXTERNAL_DISPLAY); EXPECT_FALSE(display == nullptr); - ui::DisplayMode mode; - EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayMode(display, &mode)); - EXPECT_EQ(ui::Size(200, 400), mode.resolution); - EXPECT_EQ(1e9f / 16'666'666, mode.refreshRate); + DisplayConfig config; + EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayConfig(display, &config)); + EXPECT_EQ(ui::Size(200, 400), config.resolution); + EXPECT_EQ(1e9f / 16'666'666, config.refreshRate); mFakeComposerClient->clearFrames(); { - const ui::Size& resolution = mode.resolution; + const ui::Size& resolution = config.resolution; auto surfaceControl = mComposerClient->createSurface(String8("Display Test Surface Foo"), resolution.getWidth(), resolution.getHeight(), @@ -432,12 +423,11 @@ protected: } } - ui::DynamicDisplayInfo info; - EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getDynamicDisplayInfo(display, &info)); - const auto& modes = info.supportedDisplayModes; - EXPECT_EQ(modes.size(), 2); + Vector<DisplayConfig> configs; + EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayConfigs(display, &configs)); + EXPECT_EQ(configs.size(), 2); - // change active mode + // change active config if (mIs2_4Client) { EXPECT_CALL(*mMockComposer, setActiveConfigWithConstraints(EXTERNAL_DISPLAY, 2, _, _)) @@ -447,28 +437,28 @@ protected: .WillOnce(Return(V2_1::Error::NONE)); } - for (int i = 0; i < modes.size(); i++) { - const auto& mode = modes[i]; - if (mode.resolution.getWidth() == 800) { + for (int i = 0; i < configs.size(); i++) { + const auto& config = configs[i]; + if (config.resolution.getWidth() == 800) { EXPECT_EQ(NO_ERROR, - SurfaceComposerClient::setDesiredDisplayModeSpecs(display, i, false, - mode.refreshRate, - mode.refreshRate, - mode.refreshRate, - mode.refreshRate)); - waitForDisplayTransaction(EXTERNAL_DISPLAY); - EXPECT_TRUE(waitForModeChangedEvent(EXTERNAL_DISPLAY, i)); + SurfaceComposerClient::setDesiredDisplayConfigSpecs(display, i, + config.refreshRate, + config.refreshRate, + config.refreshRate, + config.refreshRate)); + waitForDisplayTransaction(); + EXPECT_TRUE(waitForConfigChangedEvent(EXTERNAL_DISPLAY, i)); break; } } - EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayMode(display, &mode)); - EXPECT_EQ(ui::Size(800, 1600), mode.resolution); - EXPECT_EQ(1e9f / 11'111'111, mode.refreshRate); + EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayConfig(display, &config)); + EXPECT_EQ(ui::Size(800, 1600), config.resolution); + EXPECT_EQ(1e9f / 11'111'111, config.refreshRate); mFakeComposerClient->clearFrames(); { - const ui::Size& resolution = mode.resolution; + const ui::Size& resolution = config.resolution; auto surfaceControl = mComposerClient->createSurface(String8("Display Test Surface Foo"), resolution.getWidth(), resolution.getHeight(), @@ -487,7 +477,7 @@ protected: mFakeComposerClient->hotplugDisplay(EXTERNAL_DISPLAY, V2_1::IComposerCallback::Connection::DISCONNECTED); - waitForDisplayTransaction(EXTERNAL_DISPLAY); + waitForDisplayTransaction(); mFakeComposerClient->clearFrames(); EXPECT_TRUE(waitForHotplugEvent(EXTERNAL_DISPLAY, false)); } @@ -510,20 +500,20 @@ protected: mFakeComposerClient->hotplugDisplay(EXTERNAL_DISPLAY, V2_1::IComposerCallback::Connection::CONNECTED); - waitForDisplayTransaction(EXTERNAL_DISPLAY); + waitForDisplayTransaction(); EXPECT_TRUE(waitForHotplugEvent(EXTERNAL_DISPLAY, true)); - const auto display = SurfaceComposerClient::getPhysicalDisplayToken(kExternalDisplayId); + const auto display = SurfaceComposerClient::getPhysicalDisplayToken(EXTERNAL_DISPLAY); EXPECT_FALSE(display == nullptr); - ui::DisplayMode mode; - EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayMode(display, &mode)); - EXPECT_EQ(ui::Size(800, 1600), mode.resolution); - EXPECT_EQ(1e9f / 16'666'666, mode.refreshRate); + DisplayConfig config; + EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayConfig(display, &config)); + EXPECT_EQ(ui::Size(800, 1600), config.resolution); + EXPECT_EQ(1e9f / 16'666'666, config.refreshRate); mFakeComposerClient->clearFrames(); { - const ui::Size& resolution = mode.resolution; + const ui::Size& resolution = config.resolution; auto surfaceControl = mComposerClient->createSurface(String8("Display Test Surface Foo"), resolution.getWidth(), resolution.getHeight(), @@ -540,12 +530,11 @@ protected: } } - ui::DynamicDisplayInfo info; - EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getDynamicDisplayInfo(display, &info)); - const auto& modes = info.supportedDisplayModes; - EXPECT_EQ(modes.size(), 2); + Vector<DisplayConfig> configs; + EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayConfigs(display, &configs)); + EXPECT_EQ(configs.size(), 2); - // change active mode + // change active config if (mIs2_4Client) { EXPECT_CALL(*mMockComposer, setActiveConfigWithConstraints(EXTERNAL_DISPLAY, 3, _, _)) .WillOnce(Return(V2_4::Error::NONE)); @@ -554,28 +543,28 @@ protected: .WillOnce(Return(V2_1::Error::NONE)); } - for (int i = 0; i < modes.size(); i++) { - const auto& mode = modes[i]; - if (mode.refreshRate == 1e9f / 11'111'111) { + for (int i = 0; i < configs.size(); i++) { + const auto& config = configs[i]; + if (config.refreshRate == 1e9f / 11'111'111) { EXPECT_EQ(NO_ERROR, - SurfaceComposerClient::setDesiredDisplayModeSpecs(display, i, false, - mode.refreshRate, - mode.refreshRate, - mode.refreshRate, - mode.refreshRate)); - waitForDisplayTransaction(EXTERNAL_DISPLAY); - EXPECT_TRUE(waitForModeChangedEvent(EXTERNAL_DISPLAY, i)); + SurfaceComposerClient::setDesiredDisplayConfigSpecs(display, i, + config.refreshRate, + config.refreshRate, + config.refreshRate, + config.refreshRate)); + waitForDisplayTransaction(); + EXPECT_TRUE(waitForConfigChangedEvent(EXTERNAL_DISPLAY, i)); break; } } - EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayMode(display, &mode)); - EXPECT_EQ(ui::Size(800, 1600), mode.resolution); - EXPECT_EQ(1e9f / 11'111'111, mode.refreshRate); + EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayConfig(display, &config)); + EXPECT_EQ(ui::Size(800, 1600), config.resolution); + EXPECT_EQ(1e9f / 11'111'111, config.refreshRate); mFakeComposerClient->clearFrames(); { - const ui::Size& resolution = mode.resolution; + const ui::Size& resolution = config.resolution; auto surfaceControl = mComposerClient->createSurface(String8("Display Test Surface Foo"), resolution.getWidth(), resolution.getHeight(), @@ -594,7 +583,7 @@ protected: mFakeComposerClient->hotplugDisplay(EXTERNAL_DISPLAY, V2_1::IComposerCallback::Connection::DISCONNECTED); - waitForDisplayTransaction(EXTERNAL_DISPLAY); + waitForDisplayTransaction(); mFakeComposerClient->clearFrames(); EXPECT_TRUE(waitForHotplugEvent(EXTERNAL_DISPLAY, false)); } @@ -627,20 +616,20 @@ protected: mFakeComposerClient->hotplugDisplay(EXTERNAL_DISPLAY, V2_1::IComposerCallback::Connection::CONNECTED); - waitForDisplayTransaction(EXTERNAL_DISPLAY); + waitForDisplayTransaction(); EXPECT_TRUE(waitForHotplugEvent(EXTERNAL_DISPLAY, true)); - const auto display = SurfaceComposerClient::getPhysicalDisplayToken(kExternalDisplayId); + const auto display = SurfaceComposerClient::getPhysicalDisplayToken(EXTERNAL_DISPLAY); EXPECT_FALSE(display == nullptr); - ui::DisplayMode mode; - EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayMode(display, &mode)); - EXPECT_EQ(ui::Size(800, 1600), mode.resolution); - EXPECT_EQ(1e9f / 16'666'666, mode.refreshRate); + DisplayConfig config; + EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayConfig(display, &config)); + EXPECT_EQ(ui::Size(800, 1600), config.resolution); + EXPECT_EQ(1e9f / 16'666'666, config.refreshRate); mFakeComposerClient->clearFrames(); { - const ui::Size& resolution = mode.resolution; + const ui::Size& resolution = config.resolution; auto surfaceControl = mComposerClient->createSurface(String8("Display Test Surface Foo"), resolution.getWidth(), resolution.getHeight(), @@ -657,12 +646,11 @@ protected: } } - ui::DynamicDisplayInfo info; - EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getDynamicDisplayInfo(display, &info)); - const auto& modes = info.supportedDisplayModes; - EXPECT_EQ(modes.size(), 4); + Vector<DisplayConfig> configs; + EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayConfigs(display, &configs)); + EXPECT_EQ(configs.size(), 4); - // change active mode to 800x1600@90Hz + // change active config to 800x1600@90Hz if (mIs2_4Client) { EXPECT_CALL(*mMockComposer, setActiveConfigWithConstraints(EXTERNAL_DISPLAY, 3, _, _)) .WillOnce(Return(V2_4::Error::NONE)); @@ -671,28 +659,28 @@ protected: .WillOnce(Return(V2_1::Error::NONE)); } - for (size_t i = 0; i < modes.size(); i++) { - const auto& mode = modes[i]; - if (mode.resolution.getWidth() == 800 && mode.refreshRate == 1e9f / 11'111'111) { + for (int i = 0; i < configs.size(); i++) { + const auto& config = configs[i]; + if (config.resolution.getWidth() == 800 && config.refreshRate == 1e9f / 11'111'111) { EXPECT_EQ(NO_ERROR, - SurfaceComposerClient::setDesiredDisplayModeSpecs(display, i, false, - modes[i].refreshRate, - modes[i].refreshRate, - modes[i].refreshRate, - modes[i].refreshRate)); - waitForDisplayTransaction(EXTERNAL_DISPLAY); - EXPECT_TRUE(waitForModeChangedEvent(EXTERNAL_DISPLAY, i)); + SurfaceComposerClient:: + setDesiredDisplayConfigSpecs(display, i, configs[i].refreshRate, + configs[i].refreshRate, + configs[i].refreshRate, + configs[i].refreshRate)); + waitForDisplayTransaction(); + EXPECT_TRUE(waitForConfigChangedEvent(EXTERNAL_DISPLAY, i)); break; } } - EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayMode(display, &mode)); - EXPECT_EQ(ui::Size(800, 1600), mode.resolution); - EXPECT_EQ(1e9f / 11'111'111, mode.refreshRate); + EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayConfig(display, &config)); + EXPECT_EQ(ui::Size(800, 1600), config.resolution); + EXPECT_EQ(1e9f / 11'111'111, config.refreshRate); mFakeComposerClient->clearFrames(); { - const ui::Size& resolution = mode.resolution; + const ui::Size& resolution = config.resolution; auto surfaceControl = mComposerClient->createSurface(String8("Display Test Surface Foo"), resolution.getWidth(), resolution.getHeight(), @@ -709,7 +697,7 @@ protected: } } - // change active mode to 1600x3200@120Hz + // change active config to 1600x3200@120Hz if (mIs2_4Client) { EXPECT_CALL(*mMockComposer, setActiveConfigWithConstraints(EXTERNAL_DISPLAY, 4, _, _)) .WillOnce(Return(V2_4::Error::NONE)); @@ -718,28 +706,28 @@ protected: .WillOnce(Return(V2_1::Error::NONE)); } - for (int i = 0; i < modes.size(); i++) { - const auto& mode = modes[i]; - if (mode.refreshRate == 1e9f / 8'333'333) { + for (int i = 0; i < configs.size(); i++) { + const auto& config = configs[i]; + if (config.refreshRate == 1e9f / 8'333'333) { EXPECT_EQ(NO_ERROR, - SurfaceComposerClient::setDesiredDisplayModeSpecs(display, i, false, - mode.refreshRate, - mode.refreshRate, - mode.refreshRate, - mode.refreshRate)); - waitForDisplayTransaction(EXTERNAL_DISPLAY); - EXPECT_TRUE(waitForModeChangedEvent(EXTERNAL_DISPLAY, i)); + SurfaceComposerClient::setDesiredDisplayConfigSpecs(display, i, + config.refreshRate, + config.refreshRate, + config.refreshRate, + config.refreshRate)); + waitForDisplayTransaction(); + EXPECT_TRUE(waitForConfigChangedEvent(EXTERNAL_DISPLAY, i)); break; } } - EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayMode(display, &mode)); - EXPECT_EQ(ui::Size(1600, 3200), mode.resolution); - EXPECT_EQ(1e9f / 8'333'333, mode.refreshRate); + EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayConfig(display, &config)); + EXPECT_EQ(ui::Size(1600, 3200), config.resolution); + EXPECT_EQ(1e9f / 8'333'333, config.refreshRate); mFakeComposerClient->clearFrames(); { - const ui::Size& resolution = mode.resolution; + const ui::Size& resolution = config.resolution; auto surfaceControl = mComposerClient->createSurface(String8("Display Test Surface Foo"), resolution.getWidth(), resolution.getHeight(), @@ -756,7 +744,7 @@ protected: } } - // change active mode to 1600x3200@90Hz + // change active config to 1600x3200@90Hz if (mIs2_4Client) { EXPECT_CALL(*mMockComposer, setActiveConfigWithConstraints(EXTERNAL_DISPLAY, 5, _, _)) .WillOnce(Return(V2_4::Error::NONE)); @@ -765,28 +753,28 @@ protected: .WillOnce(Return(V2_1::Error::NONE)); } - for (int i = 0; i < modes.size(); i++) { - const auto& mode = modes[i]; - if (mode.resolution.getWidth() == 1600 && mode.refreshRate == 1e9f / 11'111'111) { + for (int i = 0; i < configs.size(); i++) { + const auto& config = configs[i]; + if (config.resolution.getWidth() == 1600 && config.refreshRate == 1e9f / 11'111'111) { EXPECT_EQ(NO_ERROR, - SurfaceComposerClient::setDesiredDisplayModeSpecs(display, i, false, - mode.refreshRate, - mode.refreshRate, - mode.refreshRate, - mode.refreshRate)); - waitForDisplayTransaction(EXTERNAL_DISPLAY); - EXPECT_TRUE(waitForModeChangedEvent(EXTERNAL_DISPLAY, i)); + SurfaceComposerClient::setDesiredDisplayConfigSpecs(display, i, + config.refreshRate, + config.refreshRate, + config.refreshRate, + config.refreshRate)); + waitForDisplayTransaction(); + EXPECT_TRUE(waitForConfigChangedEvent(EXTERNAL_DISPLAY, i)); break; } } - EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayMode(display, &mode)); - EXPECT_EQ(ui::Size(1600, 3200), mode.resolution); - EXPECT_EQ(1e9f / 11'111'111, mode.refreshRate); + EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayConfig(display, &config)); + EXPECT_EQ(ui::Size(1600, 3200), config.resolution); + EXPECT_EQ(1e9f / 11'111'111, config.refreshRate); mFakeComposerClient->clearFrames(); { - const ui::Size& resolution = mode.resolution; + const ui::Size& resolution = config.resolution; auto surfaceControl = mComposerClient->createSurface(String8("Display Test Surface Foo"), resolution.getWidth(), resolution.getHeight(), @@ -805,7 +793,7 @@ protected: mFakeComposerClient->hotplugDisplay(EXTERNAL_DISPLAY, V2_1::IComposerCallback::Connection::DISCONNECTED); - waitForDisplayTransaction(EXTERNAL_DISPLAY); + waitForDisplayTransaction(); mFakeComposerClient->clearFrames(); EXPECT_TRUE(waitForHotplugEvent(EXTERNAL_DISPLAY, false)); } @@ -816,15 +804,15 @@ protected: mFakeComposerClient->hotplugDisplay(PRIMARY_DISPLAY, V2_1::IComposerCallback::Connection::DISCONNECTED); - waitForDisplayTransaction(PRIMARY_DISPLAY); + waitForDisplayTransaction(); EXPECT_TRUE(waitForHotplugEvent(PRIMARY_DISPLAY, false)); { - const auto display = SurfaceComposerClient::getPhysicalDisplayToken(kPrimaryDisplayId); + const auto display = SurfaceComposerClient::getPhysicalDisplayToken(PRIMARY_DISPLAY); EXPECT_TRUE(display == nullptr); - ui::DisplayMode mode; - auto result = SurfaceComposerClient::getActiveDisplayMode(display, &mode); + DisplayConfig config; + auto result = SurfaceComposerClient::getActiveDisplayConfig(display, &config); EXPECT_NE(NO_ERROR, result); } @@ -841,136 +829,19 @@ protected: mFakeComposerClient->hotplugDisplay(PRIMARY_DISPLAY, V2_1::IComposerCallback::Connection::CONNECTED); - waitForDisplayTransaction(PRIMARY_DISPLAY); + waitForDisplayTransaction(); EXPECT_TRUE(waitForHotplugEvent(PRIMARY_DISPLAY, true)); { - const auto display = SurfaceComposerClient::getPhysicalDisplayToken(kPrimaryDisplayId); + const auto display = SurfaceComposerClient::getPhysicalDisplayToken(PRIMARY_DISPLAY); EXPECT_FALSE(display == nullptr); - ui::DisplayMode mode; - auto result = SurfaceComposerClient::getActiveDisplayMode(display, &mode); + DisplayConfig config; + auto result = SurfaceComposerClient::getActiveDisplayConfig(display, &config); EXPECT_EQ(NO_ERROR, result); - ASSERT_EQ(ui::Size(400, 200), mode.resolution); - EXPECT_EQ(1e9f / 16'666'666, mode.refreshRate); - } - } - - void Test_SubsequentHotplugConnectUpdatesDisplay(Display hwcDisplayId) { - ALOGD("DisplayTest::Test_SubsequentHotplugConnectUpdatesDisplay"); - - // Send a hotplug connected event to set up the initial display modes. - // The primary display is already connected so this will update it. - // If we're running the test of an external display this will create it. - setExpectationsForConfigs(hwcDisplayId, - {{.id = 1, - .w = 800, - .h = 1600, - .vsyncPeriod = 11'111'111, - .group = 1}}, - /* activeConfig */ 1, 11'111'111); - - mFakeComposerClient->hotplugDisplay(hwcDisplayId, - V2_1::IComposerCallback::Connection::CONNECTED); - waitForDisplayTransaction(hwcDisplayId); - EXPECT_TRUE(waitForHotplugEvent(hwcDisplayId, true)); - - const auto displayId = physicalIdFromHwcDisplayId(hwcDisplayId); - const auto display = SurfaceComposerClient::getPhysicalDisplayToken(displayId); - EXPECT_FALSE(display == nullptr); - - // Verify that the active mode and the supported moded are updated - { - ui::DisplayMode mode; - EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayMode(display, &mode)); - EXPECT_EQ(ui::Size(800, 1600), mode.resolution); - EXPECT_EQ(1e9f / 11'111'111, mode.refreshRate); - - ui::DynamicDisplayInfo info; - EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getDynamicDisplayInfo(display, &info)); - const auto& modes = info.supportedDisplayModes; - EXPECT_EQ(modes.size(), 1); - } - - // Send another hotplug connected event - setExpectationsForConfigs(hwcDisplayId, - { - {.id = 1, - .w = 800, - .h = 1600, - .vsyncPeriod = 16'666'666, - .group = 1}, - {.id = 2, - .w = 800, - .h = 1600, - .vsyncPeriod = 11'111'111, - .group = 1}, - {.id = 3, - .w = 800, - .h = 1600, - .vsyncPeriod = 8'333'333, - .group = 1}, - }, - /* activeConfig */ 1, 16'666'666); - - mFakeComposerClient->hotplugDisplay(hwcDisplayId, - V2_1::IComposerCallback::Connection::CONNECTED); - waitForDisplayTransaction(hwcDisplayId); - EXPECT_TRUE(waitForHotplugEvent(hwcDisplayId, true)); - - // Verify that the active mode and the supported moded are updated - { - ui::DisplayMode mode; - EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayMode(display, &mode)); - EXPECT_EQ(ui::Size(800, 1600), mode.resolution); - EXPECT_EQ(1e9f / 16'666'666, mode.refreshRate); - } - - ui::DynamicDisplayInfo info; - EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getDynamicDisplayInfo(display, &info)); - const auto& modes = info.supportedDisplayModes; - EXPECT_EQ(modes.size(), 3); - - EXPECT_EQ(ui::Size(800, 1600), modes[0].resolution); - EXPECT_EQ(1e9f / 16'666'666, modes[0].refreshRate); - - EXPECT_EQ(ui::Size(800, 1600), modes[1].resolution); - EXPECT_EQ(1e9f / 11'111'111, modes[1].refreshRate); - - EXPECT_EQ(ui::Size(800, 1600), modes[2].resolution); - EXPECT_EQ(1e9f / 8'333'333, modes[2].refreshRate); - - // Verify that we are able to switch to any of the modes - for (int i = modes.size() - 1; i >= 0; i--) { - const auto hwcId = i + 1; - // Set up HWC expectations for the mode change - if (mIs2_4Client) { - EXPECT_CALL(*mMockComposer, - setActiveConfigWithConstraints(hwcDisplayId, hwcId, _, _)) - .WillOnce(Return(V2_4::Error::NONE)); - } else { - EXPECT_CALL(*mMockComposer, setActiveConfig(hwcDisplayId, hwcId)) - .WillOnce(Return(V2_1::Error::NONE)); - } - - EXPECT_EQ(NO_ERROR, - SurfaceComposerClient::setDesiredDisplayModeSpecs(display, i, false, - modes[i].refreshRate, - modes[i].refreshRate, - modes[i].refreshRate, - modes[i].refreshRate)); - // We need to refresh twice - once to apply the pending mode change request, - // and once to process the change. - waitForDisplayTransaction(hwcDisplayId); - waitForDisplayTransaction(hwcDisplayId); - EXPECT_TRUE(waitForModeChangedEvent(hwcDisplayId, i)) - << "Failure while switching to mode " << i; - - ui::DisplayMode mode; - EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayMode(display, &mode)); - EXPECT_EQ(ui::Size(800, 1600), mode.resolution); - EXPECT_EQ(modes[i].refreshRate, mode.refreshRate); + ASSERT_EQ(ui::Size(400, 200), config.resolution); + EXPECT_EQ(1e9f / 16'666'666, config.refreshRate); } } @@ -990,25 +861,6 @@ protected: using DisplayTest_2_1 = DisplayTest<FakeComposerService_2_1>; -// Tests that VSYNC injection can be safely toggled while invalidating. -TEST_F(DisplayTest_2_1, VsyncInjection) { - const auto flinger = ComposerService::getComposerService(); - bool enable = true; - - for (int i = 0; i < 100; i++) { - flinger->enableVSyncInjections(enable); - enable = !enable; - - constexpr uint32_t kForceInvalidate = 1004; - android::Parcel data, reply; - data.writeInterfaceToken(String16("android.ui.ISurfaceComposer")); - EXPECT_EQ(NO_ERROR, - android::IInterface::asBinder(flinger)->transact(kForceInvalidate, data, &reply)); - - std::this_thread::sleep_for(5ms); - } -} - TEST_F(DisplayTest_2_1, HotplugOneConfig) { Test_HotplugOneConfig(); } @@ -1029,14 +881,6 @@ TEST_F(DisplayTest_2_1, HotplugPrimaryOneConfig) { Test_HotplugPrimaryDisplay(); } -TEST_F(DisplayTest_2_1, SubsequentHotplugConnectUpdatesPrimaryDisplay) { - Test_SubsequentHotplugConnectUpdatesDisplay(PRIMARY_DISPLAY); -} - -TEST_F(DisplayTest_2_1, SubsequentHotplugConnectUpdatesExternalDisplay) { - Test_SubsequentHotplugConnectUpdatesDisplay(EXTERNAL_DISPLAY); -} - using DisplayTest_2_2 = DisplayTest<FakeComposerService_2_2>; TEST_F(DisplayTest_2_2, HotplugOneConfig) { @@ -1059,14 +903,6 @@ TEST_F(DisplayTest_2_2, HotplugPrimaryOneConfig) { Test_HotplugPrimaryDisplay(); } -TEST_F(DisplayTest_2_2, SubsequentHotplugConnectUpdatesPrimaryDisplay) { - Test_SubsequentHotplugConnectUpdatesDisplay(PRIMARY_DISPLAY); -} - -TEST_F(DisplayTest_2_2, SubsequentHotplugConnectUpdatesExternalDisplay) { - Test_SubsequentHotplugConnectUpdatesDisplay(EXTERNAL_DISPLAY); -} - using DisplayTest_2_3 = DisplayTest<FakeComposerService_2_3>; TEST_F(DisplayTest_2_3, HotplugOneConfig) { @@ -1089,14 +925,6 @@ TEST_F(DisplayTest_2_3, HotplugPrimaryOneConfig) { Test_HotplugPrimaryDisplay(); } -TEST_F(DisplayTest_2_3, SubsequentHotplugConnectUpdatesPrimaryDisplay) { - Test_SubsequentHotplugConnectUpdatesDisplay(PRIMARY_DISPLAY); -} - -TEST_F(DisplayTest_2_3, SubsequentHotplugConnectUpdatesExternalDisplay) { - Test_SubsequentHotplugConnectUpdatesDisplay(EXTERNAL_DISPLAY); -} - using DisplayTest_2_4 = DisplayTest<FakeComposerService_2_4>; TEST_F(DisplayTest_2_4, HotplugOneConfig) { @@ -1119,14 +947,6 @@ TEST_F(DisplayTest_2_4, HotplugPrimaryOneConfig) { Test_HotplugPrimaryDisplay(); } -TEST_F(DisplayTest_2_4, SubsequentHotplugConnectUpdatesPrimaryDisplay) { - Test_SubsequentHotplugConnectUpdatesDisplay(PRIMARY_DISPLAY); -} - -TEST_F(DisplayTest_2_4, SubsequentHotplugConnectUpdatesExternalDisplay) { - Test_SubsequentHotplugConnectUpdatesDisplay(EXTERNAL_DISPLAY); -} - //////////////////////////////////////////////// template <typename FakeComposerService> @@ -1168,13 +988,13 @@ protected: ASSERT_EQ(NO_ERROR, mComposerClient->initCheck()); ALOGI("TransactionTest::SetUp - display"); - const auto display = SurfaceComposerClient::getPhysicalDisplayToken(kPrimaryDisplayId); + const auto display = SurfaceComposerClient::getPhysicalDisplayToken(PRIMARY_DISPLAY); ASSERT_FALSE(display == nullptr); - ui::DisplayMode mode; - ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayMode(display, &mode)); + DisplayConfig config; + ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayConfig(display, &config)); - const ui::Size& resolution = mode.resolution; + const ui::Size& resolution = config.resolution; mDisplayWidth = resolution.getWidth(); mDisplayHeight = resolution.getHeight(); @@ -1293,12 +1113,37 @@ protected: EXPECT_TRUE(framesAreSame(frame2Ref, sFakeComposer->getFrameRects(2))); } + void Test_LayerResize() { + ALOGD("TransactionTest::LayerResize"); + { + TransactionScope ts(*sFakeComposer); + ts.setSize(mFGSurfaceControl, 128, 128); + } + + fillSurfaceRGBA8(mFGSurfaceControl, GREEN); + sFakeComposer->runVSyncAndWait(); + + ASSERT_EQ(3, sFakeComposer->getFrameCount()); // Make sure the waits didn't time out and + // there's no extra frames. + + auto frame1Ref = mBaseFrame; + // NOTE: The resize should not be visible for frame 1 as there's no buffer with new size + // posted. + EXPECT_TRUE(framesAreSame(frame1Ref, sFakeComposer->getFrameRects(1))); + + auto frame2Ref = frame1Ref; + frame2Ref[FG_LAYER].mSwapCount++; + frame2Ref[FG_LAYER].mDisplayFrame = hwc_rect_t{64, 64, 64 + 128, 64 + 128}; + frame2Ref[FG_LAYER].mSourceCrop = hwc_frect_t{0.f, 0.f, 128.f, 128.f}; + EXPECT_TRUE(framesAreSame(frame2Ref, sFakeComposer->getFrameRects(2))); + } + void Test_LayerCrop() { // TODO: Add scaling to confirm that crop happens in buffer space? { TransactionScope ts(*sFakeComposer); Rect cropRect(16, 16, 32, 32); - ts.setCrop(mFGSurfaceControl, cropRect); + ts.setCrop_legacy(mFGSurfaceControl, cropRect); } ASSERT_EQ(2, sFakeComposer->getFrameCount()); @@ -1443,6 +1288,77 @@ protected: } } + void Test_DeferredTransaction() { + // Synchronization surface + constexpr static int SYNC_LAYER = 2; + auto syncSurfaceControl = mComposerClient->createSurface(String8("Sync Test Surface"), 1, 1, + PIXEL_FORMAT_RGBA_8888, 0); + ASSERT_TRUE(syncSurfaceControl != nullptr); + ASSERT_TRUE(syncSurfaceControl->isValid()); + + fillSurfaceRGBA8(syncSurfaceControl, DARK_GRAY); + + { + TransactionScope ts(*sFakeComposer); + ts.setLayer(syncSurfaceControl, INT32_MAX - 1); + ts.setPosition(syncSurfaceControl, mDisplayWidth - 2, mDisplayHeight - 2); + ts.show(syncSurfaceControl); + } + auto referenceFrame = mBaseFrame; + referenceFrame.push_back(makeSimpleRect(mDisplayWidth - 2, mDisplayHeight - 2, + mDisplayWidth - 1, mDisplayHeight - 1)); + referenceFrame[SYNC_LAYER].mSwapCount = 1; + EXPECT_EQ(2, sFakeComposer->getFrameCount()); + EXPECT_TRUE(framesAreSame(referenceFrame, sFakeComposer->getLatestFrame())); + + // set up two deferred transactions on different frames - these should not yield composited + // frames + { + TransactionScope ts(*sFakeComposer); + ts.setAlpha(mFGSurfaceControl, 0.75); + ts.deferTransactionUntil_legacy(mFGSurfaceControl, syncSurfaceControl->getHandle(), + syncSurfaceControl->getSurface()->getNextFrameNumber()); + } + EXPECT_TRUE(framesAreSame(referenceFrame, sFakeComposer->getLatestFrame())); + + { + TransactionScope ts(*sFakeComposer); + ts.setPosition(mFGSurfaceControl, 128, 128); + ts.deferTransactionUntil_legacy(mFGSurfaceControl, syncSurfaceControl->getHandle(), + syncSurfaceControl->getSurface()->getNextFrameNumber() + + 1); + } + EXPECT_EQ(4, sFakeComposer->getFrameCount()); + EXPECT_TRUE(framesAreSame(referenceFrame, sFakeComposer->getLatestFrame())); + + // should trigger the first deferred transaction, but not the second one + fillSurfaceRGBA8(syncSurfaceControl, DARK_GRAY); + sFakeComposer->runVSyncAndWait(); + EXPECT_EQ(5, sFakeComposer->getFrameCount()); + + referenceFrame[FG_LAYER].mPlaneAlpha = 0.75f; + referenceFrame[SYNC_LAYER].mSwapCount++; + EXPECT_TRUE(framesAreSame(referenceFrame, sFakeComposer->getLatestFrame())); + + // should show up immediately since it's not deferred + { + TransactionScope ts(*sFakeComposer); + ts.setAlpha(mFGSurfaceControl, 1.0); + } + referenceFrame[FG_LAYER].mPlaneAlpha = 1.f; + EXPECT_EQ(6, sFakeComposer->getFrameCount()); + EXPECT_TRUE(framesAreSame(referenceFrame, sFakeComposer->getLatestFrame())); + + // trigger the second deferred transaction + fillSurfaceRGBA8(syncSurfaceControl, DARK_GRAY); + sFakeComposer->runVSyncAndWait(); + // TODO: Compute from layer size? + referenceFrame[FG_LAYER].mDisplayFrame = hwc_rect_t{128, 128, 128 + 64, 128 + 64}; + referenceFrame[SYNC_LAYER].mSwapCount++; + EXPECT_EQ(7, sFakeComposer->getFrameCount()); + EXPECT_TRUE(framesAreSame(referenceFrame, sFakeComposer->getLatestFrame())); + } + void Test_SetRelativeLayer() { constexpr int RELATIVE_LAYER = 2; auto relativeSurfaceControl = mComposerClient->createSurface(String8("Test Surface"), 64, @@ -1454,7 +1370,7 @@ protected: TransactionScope ts(*sFakeComposer); ts.setPosition(relativeSurfaceControl, 64, 64); ts.show(relativeSurfaceControl); - ts.setRelativeLayer(relativeSurfaceControl, mFGSurfaceControl, 1); + ts.setRelativeLayer(relativeSurfaceControl, mFGSurfaceControl->getHandle(), 1); } auto referenceFrame = mBaseFrame; // NOTE: All three layers will be visible as the surfaces are @@ -1492,6 +1408,10 @@ TEST_F(TransactionTest_2_1, DISABLED_LayerMove) { Test_LayerMove(); } +TEST_F(TransactionTest_2_1, DISABLED_LayerResize) { + Test_LayerResize(); +} + TEST_F(TransactionTest_2_1, DISABLED_LayerCrop) { Test_LayerCrop(); } @@ -1524,6 +1444,10 @@ TEST_F(TransactionTest_2_1, DISABLED_LayerSetMatrix) { Test_LayerSetMatrix(); } +TEST_F(TransactionTest_2_1, DISABLED_DeferredTransaction) { + Test_DeferredTransaction(); +} + TEST_F(TransactionTest_2_1, DISABLED_SetRelativeLayer) { Test_SetRelativeLayer(); } @@ -1539,7 +1463,7 @@ protected: Base::SetUp(); mChild = Base::mComposerClient->createSurface(String8("Child surface"), 10, 10, PIXEL_FORMAT_RGBA_8888, 0, - Base::mFGSurfaceControl->getHandle()); + Base::mFGSurfaceControl.get()); fillSurfaceRGBA8(mChild, LIGHT_GRAY); Base::sFakeComposer->runVSyncAndWait(); @@ -1587,7 +1511,7 @@ protected: ts.show(mChild); ts.setPosition(mChild, 0, 0); ts.setPosition(Base::mFGSurfaceControl, 0, 0); - ts.setCrop(Base::mFGSurfaceControl, Rect(0, 0, 5, 5)); + ts.setCrop_legacy(Base::mFGSurfaceControl, Rect(0, 0, 5, 5)); } // NOTE: The foreground surface would be occluded by the child // now, but is included in the stack because the child is @@ -1661,6 +1585,201 @@ protected: EXPECT_TRUE(framesAreSame(referenceFrame2, Base::sFakeComposer->getLatestFrame())); } + void Test_ReparentChildren() { + { + TransactionScope ts(*Base::sFakeComposer); + ts.show(mChild); + ts.setPosition(mChild, 10, 10); + ts.setPosition(Base::mFGSurfaceControl, 64, 64); + } + auto referenceFrame = Base::mBaseFrame; + referenceFrame[Base::FG_LAYER].mDisplayFrame = hwc_rect_t{64, 64, 64 + 64, 64 + 64}; + referenceFrame[CHILD_LAYER].mDisplayFrame = + hwc_rect_t{64 + 10, 64 + 10, 64 + 10 + 10, 64 + 10 + 10}; + EXPECT_TRUE(framesAreSame(referenceFrame, Base::sFakeComposer->getLatestFrame())); + + { + TransactionScope ts(*Base::sFakeComposer); + ts.reparentChildren(Base::mFGSurfaceControl, Base::mBGSurfaceControl->getHandle()); + } + + auto referenceFrame2 = referenceFrame; + referenceFrame2[Base::FG_LAYER].mDisplayFrame = hwc_rect_t{64, 64, 64 + 64, 64 + 64}; + referenceFrame2[CHILD_LAYER].mDisplayFrame = hwc_rect_t{10, 10, 10 + 10, 10 + 10}; + EXPECT_TRUE(framesAreSame(referenceFrame2, Base::sFakeComposer->getLatestFrame())); + } + + void Test_DetachChildrenSameClient() { + { + TransactionScope ts(*Base::sFakeComposer); + ts.show(mChild); + ts.setPosition(mChild, 10, 10); + ts.setPosition(Base::mFGSurfaceControl, 64, 64); + } + + auto referenceFrame = Base::mBaseFrame; + referenceFrame[Base::FG_LAYER].mDisplayFrame = hwc_rect_t{64, 64, 64 + 64, 64 + 64}; + referenceFrame[CHILD_LAYER].mDisplayFrame = + hwc_rect_t{64 + 10, 64 + 10, 64 + 10 + 10, 64 + 10 + 10}; + EXPECT_TRUE(framesAreSame(referenceFrame, Base::sFakeComposer->getLatestFrame())); + + { + TransactionScope ts(*Base::sFakeComposer); + ts.setPosition(Base::mFGSurfaceControl, 0, 0); + ts.detachChildren(Base::mFGSurfaceControl); + } + + { + TransactionScope ts(*Base::sFakeComposer); + ts.setPosition(Base::mFGSurfaceControl, 64, 64); + ts.hide(mChild); + } + + std::vector<RenderState> refFrame(2); + refFrame[Base::BG_LAYER] = Base::mBaseFrame[Base::BG_LAYER]; + refFrame[Base::FG_LAYER] = Base::mBaseFrame[Base::FG_LAYER]; + + EXPECT_TRUE(framesAreSame(refFrame, Base::sFakeComposer->getLatestFrame())); + } + + void Test_DetachChildrenDifferentClient() { + sp<SurfaceComposerClient> newComposerClient = new SurfaceComposerClient; + sp<SurfaceControl> childNewClient = + newComposerClient->createSurface(String8("New Child Test Surface"), 10, 10, + PIXEL_FORMAT_RGBA_8888, 0, + Base::mFGSurfaceControl.get()); + ASSERT_TRUE(childNewClient != nullptr); + ASSERT_TRUE(childNewClient->isValid()); + fillSurfaceRGBA8(childNewClient, LIGHT_GRAY); + + { + TransactionScope ts(*Base::sFakeComposer); + ts.hide(mChild); + ts.show(childNewClient); + ts.setPosition(childNewClient, 10, 10); + ts.setPosition(Base::mFGSurfaceControl, 64, 64); + } + + auto referenceFrame = Base::mBaseFrame; + referenceFrame[Base::FG_LAYER].mDisplayFrame = hwc_rect_t{64, 64, 64 + 64, 64 + 64}; + referenceFrame[CHILD_LAYER].mDisplayFrame = + hwc_rect_t{64 + 10, 64 + 10, 64 + 10 + 10, 64 + 10 + 10}; + EXPECT_TRUE(framesAreSame(referenceFrame, Base::sFakeComposer->getLatestFrame())); + + { + TransactionScope ts(*Base::sFakeComposer); + ts.detachChildren(Base::mFGSurfaceControl); + ts.setPosition(Base::mFGSurfaceControl, 0, 0); + } + + { + TransactionScope ts(*Base::sFakeComposer); + ts.setPosition(Base::mFGSurfaceControl, 64, 64); + ts.setPosition(childNewClient, 0, 0); + ts.hide(childNewClient); + } + + // Nothing should have changed. The child control becomes a no-op + // zombie on detach. See comments for detachChildren in the + // SurfaceControl.h file. + EXPECT_TRUE(framesAreSame(referenceFrame, Base::sFakeComposer->getLatestFrame())); + } + + void Test_InheritNonTransformScalingFromParent() { + { + TransactionScope ts(*Base::sFakeComposer); + ts.show(mChild); + ts.setPosition(mChild, 0, 0); + ts.setPosition(Base::mFGSurfaceControl, 0, 0); + } + + { + TransactionScope ts(*Base::sFakeComposer); + ts.setOverrideScalingMode(Base::mFGSurfaceControl, + NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW); + // We cause scaling by 2. + ts.setSize(Base::mFGSurfaceControl, 128, 128); + } + + auto referenceFrame = Base::mBaseFrame; + referenceFrame[Base::FG_LAYER].mDisplayFrame = hwc_rect_t{0, 0, 128, 128}; + referenceFrame[Base::FG_LAYER].mSourceCrop = hwc_frect_t{0.f, 0.f, 64.f, 64.f}; + referenceFrame[CHILD_LAYER].mDisplayFrame = hwc_rect_t{0, 0, 20, 20}; + referenceFrame[CHILD_LAYER].mSourceCrop = hwc_frect_t{0.f, 0.f, 10.f, 10.f}; + EXPECT_TRUE(framesAreSame(referenceFrame, Base::sFakeComposer->getLatestFrame())); + } + + // Regression test for b/37673612 + void Test_ChildrenWithParentBufferTransform() { + { + TransactionScope ts(*Base::sFakeComposer); + ts.show(mChild); + ts.setPosition(mChild, 0, 0); + ts.setPosition(Base::mFGSurfaceControl, 0, 0); + } + + // We set things up as in b/37673612 so that there is a mismatch between the buffer size and + // the WM specified state size. + { + TransactionScope ts(*Base::sFakeComposer); + ts.setSize(Base::mFGSurfaceControl, 128, 64); + } + + sp<Surface> s = Base::mFGSurfaceControl->getSurface(); + auto anw = static_cast<ANativeWindow*>(s.get()); + native_window_set_buffers_transform(anw, NATIVE_WINDOW_TRANSFORM_ROT_90); + native_window_set_buffers_dimensions(anw, 64, 128); + fillSurfaceRGBA8(Base::mFGSurfaceControl, RED); + Base::sFakeComposer->runVSyncAndWait(); + + // The child should still be in the same place and not have any strange scaling as in + // b/37673612. + auto referenceFrame = Base::mBaseFrame; + referenceFrame[Base::FG_LAYER].mDisplayFrame = hwc_rect_t{0, 0, 128, 64}; + referenceFrame[Base::FG_LAYER].mSourceCrop = hwc_frect_t{0.f, 0.f, 64.f, 128.f}; + referenceFrame[Base::FG_LAYER].mSwapCount++; + referenceFrame[CHILD_LAYER].mDisplayFrame = hwc_rect_t{0, 0, 10, 10}; + EXPECT_TRUE(framesAreSame(referenceFrame, Base::sFakeComposer->getLatestFrame())); + } + + void Test_Bug36858924() { + // Destroy the child layer + mChild.clear(); + + // Now recreate it as hidden + mChild = Base::mComposerClient->createSurface(String8("Child surface"), 10, 10, + PIXEL_FORMAT_RGBA_8888, + ISurfaceComposerClient::eHidden, + Base::mFGSurfaceControl.get()); + + // Show the child layer in a deferred transaction + { + TransactionScope ts(*Base::sFakeComposer); + ts.deferTransactionUntil_legacy(mChild, Base::mFGSurfaceControl->getHandle(), + Base::mFGSurfaceControl->getSurface() + ->getNextFrameNumber()); + ts.show(mChild); + } + + // Render the foreground surface a few times + // + // Prior to the bugfix for b/36858924, this would usually hang while trying to fill the + // third frame because SurfaceFlinger would never process the deferred transaction and would + // therefore never acquire/release the first buffer + ALOGI("Filling 1"); + fillSurfaceRGBA8(Base::mFGSurfaceControl, GREEN); + Base::sFakeComposer->runVSyncAndWait(); + ALOGI("Filling 2"); + fillSurfaceRGBA8(Base::mFGSurfaceControl, BLUE); + Base::sFakeComposer->runVSyncAndWait(); + ALOGI("Filling 3"); + fillSurfaceRGBA8(Base::mFGSurfaceControl, RED); + Base::sFakeComposer->runVSyncAndWait(); + ALOGI("Filling 4"); + fillSurfaceRGBA8(Base::mFGSurfaceControl, GREEN); + Base::sFakeComposer->runVSyncAndWait(); + } + sp<SurfaceControl> mChild; }; @@ -1686,6 +1805,31 @@ TEST_F(ChildLayerTest_2_1, DISABLED_LayerAlpha) { Test_LayerAlpha(); } +TEST_F(ChildLayerTest_2_1, DISABLED_ReparentChildren) { + Test_ReparentChildren(); +} + +TEST_F(ChildLayerTest_2_1, DISABLED_DetachChildrenSameClient) { + Test_DetachChildrenSameClient(); +} + +TEST_F(ChildLayerTest_2_1, DISABLED_DetachChildrenDifferentClient) { + Test_DetachChildrenDifferentClient(); +} + +TEST_F(ChildLayerTest_2_1, DISABLED_InheritNonTransformScalingFromParent) { + Test_InheritNonTransformScalingFromParent(); +} + +// Regression test for b/37673612 +TEST_F(ChildLayerTest_2_1, DISABLED_ChildrenWithParentBufferTransform) { + Test_ChildrenWithParentBufferTransform(); +} + +TEST_F(ChildLayerTest_2_1, DISABLED_Bug36858924) { + Test_Bug36858924(); +} + template <typename FakeComposerService> class ChildColorLayerTest : public ChildLayerTest<FakeComposerService> { using Base = ChildLayerTest<FakeComposerService>; @@ -1697,12 +1841,12 @@ protected: Base::mComposerClient->createSurface(String8("Child surface"), 0, 0, PIXEL_FORMAT_RGBA_8888, ISurfaceComposerClient::eFXSurfaceEffect, - Base::mFGSurfaceControl->getHandle()); + Base::mFGSurfaceControl.get()); { TransactionScope ts(*Base::sFakeComposer); ts.setColor(Base::mChild, {LIGHT_GRAY.r / 255.0f, LIGHT_GRAY.g / 255.0f, LIGHT_GRAY.b / 255.0f}); - ts.setCrop(Base::mChild, Rect(0, 0, 10, 10)); + ts.setCrop_legacy(Base::mChild, Rect(0, 0, 10, 10)); } Base::sFakeComposer->runVSyncAndWait(); @@ -1775,6 +1919,91 @@ TEST_F(ChildColorLayerTest_2_1, DISABLED_LayerAlpha) { TEST_F(ChildColorLayerTest_2_1, DISABLED_LayerZeroAlpha) { Test_LayerZeroAlpha(); } + +template <typename FakeComposerService> +class LatchingTest : public TransactionTest<FakeComposerService> { + using Base = TransactionTest<FakeComposerService>; + +protected: + void lockAndFillFGBuffer() { fillSurfaceRGBA8(Base::mFGSurfaceControl, RED, false); } + + void unlockFGBuffer() { + sp<Surface> s = Base::mFGSurfaceControl->getSurface(); + ASSERT_EQ(NO_ERROR, s->unlockAndPost()); + Base::sFakeComposer->runVSyncAndWait(); + } + + void completeFGResize() { + fillSurfaceRGBA8(Base::mFGSurfaceControl, RED); + Base::sFakeComposer->runVSyncAndWait(); + } + void restoreInitialState() { + TransactionScope ts(*Base::sFakeComposer); + ts.setSize(Base::mFGSurfaceControl, 64, 64); + ts.setPosition(Base::mFGSurfaceControl, 64, 64); + ts.setCrop_legacy(Base::mFGSurfaceControl, Rect(0, 0, 64, 64)); + } + + void Test_SurfacePositionLatching() { + // By default position can be updated even while + // a resize is pending. + { + TransactionScope ts(*Base::sFakeComposer); + ts.setSize(Base::mFGSurfaceControl, 32, 32); + ts.setPosition(Base::mFGSurfaceControl, 100, 100); + } + + // The size should not have updated as we have not provided a new buffer. + auto referenceFrame1 = Base::mBaseFrame; + referenceFrame1[Base::FG_LAYER].mDisplayFrame = hwc_rect_t{100, 100, 100 + 64, 100 + 64}; + EXPECT_TRUE(framesAreSame(referenceFrame1, Base::sFakeComposer->getLatestFrame())); + + restoreInitialState(); + + completeFGResize(); + + auto referenceFrame2 = Base::mBaseFrame; + referenceFrame2[Base::FG_LAYER].mDisplayFrame = hwc_rect_t{100, 100, 100 + 32, 100 + 32}; + referenceFrame2[Base::FG_LAYER].mSourceCrop = hwc_frect_t{0.f, 0.f, 32.f, 32.f}; + referenceFrame2[Base::FG_LAYER].mSwapCount++; + EXPECT_TRUE(framesAreSame(referenceFrame2, Base::sFakeComposer->getLatestFrame())); + } + + void Test_CropLatching() { + // Normally the crop applies immediately even while a resize is pending. + { + TransactionScope ts(*Base::sFakeComposer); + ts.setSize(Base::mFGSurfaceControl, 128, 128); + ts.setCrop_legacy(Base::mFGSurfaceControl, Rect(0, 0, 63, 63)); + } + + auto referenceFrame1 = Base::mBaseFrame; + referenceFrame1[Base::FG_LAYER].mDisplayFrame = hwc_rect_t{64, 64, 64 + 63, 64 + 63}; + referenceFrame1[Base::FG_LAYER].mSourceCrop = hwc_frect_t{0.f, 0.f, 63.f, 63.f}; + EXPECT_TRUE(framesAreSame(referenceFrame1, Base::sFakeComposer->getLatestFrame())); + + restoreInitialState(); + + completeFGResize(); + + auto referenceFrame2 = Base::mBaseFrame; + referenceFrame2[Base::FG_LAYER].mDisplayFrame = hwc_rect_t{64, 64, 64 + 63, 64 + 63}; + referenceFrame2[Base::FG_LAYER].mSourceCrop = hwc_frect_t{0.f, 0.f, 63.f, 63.f}; + referenceFrame2[Base::FG_LAYER].mSwapCount++; + EXPECT_TRUE(framesAreSame(referenceFrame2, Base::sFakeComposer->getLatestFrame())); + } +}; + +using LatchingTest_2_1 = LatchingTest<FakeComposerService_2_1>; + +TEST_F(LatchingTest_2_1, DISABLED_SurfacePositionLatching) { + Test_SurfacePositionLatching(); +} + +TEST_F(LatchingTest_2_1, DISABLED_CropLatching) { + Test_CropLatching(); +} + } // namespace int main(int argc, char** argv) { @@ -1787,4 +2016,4 @@ int main(int argc, char** argv) { } // TODO(b/129481165): remove the #pragma below and fix conversion issues -#pragma clang diagnostic pop // ignored "-Wconversion -Wextra" +#pragma clang diagnostic pop // ignored "-Wconversion" |