SF: Split DisplayTransactionTest

Test: atest libsurfaceflinger_unittests
Change-Id: Ia29e8fa68ccd128923d52c33e106aafb6c5e9b9c
diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp
index 9655cf3..8097a88 100644
--- a/services/surfaceflinger/tests/unittests/Android.bp
+++ b/services/surfaceflinger/tests/unittests/Android.bp
@@ -41,6 +41,8 @@
         "DisplayIdentificationTest.cpp",
         "DisplayIdGeneratorTest.cpp",
         "DisplayTransactionTest.cpp",
+        "DisplayDevice_GetBestColorModeTest.cpp",
+        "DisplayDevice_SetProjectionTest.cpp",
         "EventThreadTest.cpp",
         "FrameTimelineTest.cpp",
         "HWComposerTest.cpp",
@@ -50,6 +52,16 @@
         "LayerMetadataTest.cpp",
         "MessageQueueTest.cpp",
         "PromiseTest.cpp",
+        "SurfaceFlinger_CreateDisplayTest.cpp",
+        "SurfaceFlinger_DestroyDisplayTest.cpp",
+        "SurfaceFlinger_GetDisplayNativePrimariesTest.cpp",
+        "SurfaceFlinger_HandleTransactionLockedTest.cpp",
+        "SurfaceFlinger_NotifyPowerBoostTest.cpp",
+        "SurfaceFlinger_OnHotplugReceivedTest.cpp",
+        "SurfaceFlinger_OnInitializeDisplaysTest.cpp",
+        "SurfaceFlinger_SetDisplayStateTest.cpp",
+        "SurfaceFlinger_SetPowerModeInternalTest.cpp",
+        "SurfaceFlinger_SetupNewDisplayDeviceInternalTest.cpp",
         "SchedulerTest.cpp",
         "SchedulerUtilsTest.cpp",
         "SetFrameRateTest.cpp",
diff --git a/services/surfaceflinger/tests/unittests/DisplayDevice_GetBestColorModeTest.cpp b/services/surfaceflinger/tests/unittests/DisplayDevice_GetBestColorModeTest.cpp
new file mode 100644
index 0000000..2e53cd1
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/DisplayDevice_GetBestColorModeTest.cpp
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2020 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"
+
+#include "DisplayTransactionTestHelpers.h"
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+namespace android {
+namespace {
+
+using hal::RenderIntent;
+
+using FakeDisplayDeviceInjector = TestableSurfaceFlinger::FakeDisplayDeviceInjector;
+
+class GetBestColorModeTest : public DisplayTransactionTest {
+public:
+    void setHasWideColorGamut(bool hasWideColorGamut) { mHasWideColorGamut = hasWideColorGamut; }
+
+    void addHwcColorModesMapping(ui::ColorMode colorMode,
+                                 std::vector<ui::RenderIntent> renderIntents) {
+        mHwcColorModes[colorMode] = renderIntents;
+    }
+
+    void setInputDataspace(ui::Dataspace dataspace) { mInputDataspace = dataspace; }
+
+    void setInputRenderIntent(ui::RenderIntent renderIntent) { mInputRenderIntent = renderIntent; }
+
+    void getBestColorMode() {
+        auto displayDevice =
+                injectDefaultInternalDisplay([this](FakeDisplayDeviceInjector& injector) {
+                    injector.setHwcColorModes(mHwcColorModes);
+                    injector.setHasWideColorGamut(mHasWideColorGamut);
+                    injector.setNativeWindow(mNativeWindow);
+                });
+
+        displayDevice->getCompositionDisplay()
+                ->getDisplayColorProfile()
+                ->getBestColorMode(mInputDataspace, mInputRenderIntent, &mOutDataspace,
+                                   &mOutColorMode, &mOutRenderIntent);
+    }
+
+    ui::Dataspace mOutDataspace;
+    ui::ColorMode mOutColorMode;
+    ui::RenderIntent mOutRenderIntent;
+
+private:
+    ui::Dataspace mInputDataspace;
+    ui::RenderIntent mInputRenderIntent;
+    bool mHasWideColorGamut = false;
+    std::unordered_map<ui::ColorMode, std::vector<ui::RenderIntent>> mHwcColorModes;
+};
+
+TEST_F(GetBestColorModeTest, DataspaceDisplayP3_ColorModeSRGB) {
+    addHwcColorModesMapping(ui::ColorMode::SRGB,
+                            std::vector<ui::RenderIntent>(1, RenderIntent::COLORIMETRIC));
+    setInputDataspace(ui::Dataspace::DISPLAY_P3);
+    setInputRenderIntent(ui::RenderIntent::COLORIMETRIC);
+    setHasWideColorGamut(true);
+
+    getBestColorMode();
+
+    ASSERT_EQ(ui::Dataspace::V0_SRGB, mOutDataspace);
+    ASSERT_EQ(ui::ColorMode::SRGB, mOutColorMode);
+    ASSERT_EQ(ui::RenderIntent::COLORIMETRIC, mOutRenderIntent);
+}
+
+TEST_F(GetBestColorModeTest, DataspaceDisplayP3_ColorModeDisplayP3) {
+    addHwcColorModesMapping(ui::ColorMode::DISPLAY_P3,
+                            std::vector<ui::RenderIntent>(1, RenderIntent::COLORIMETRIC));
+    addHwcColorModesMapping(ui::ColorMode::SRGB,
+                            std::vector<ui::RenderIntent>(1, RenderIntent::COLORIMETRIC));
+    addHwcColorModesMapping(ui::ColorMode::DISPLAY_BT2020,
+                            std::vector<ui::RenderIntent>(1, RenderIntent::COLORIMETRIC));
+    setInputDataspace(ui::Dataspace::DISPLAY_P3);
+    setInputRenderIntent(ui::RenderIntent::COLORIMETRIC);
+    setHasWideColorGamut(true);
+
+    getBestColorMode();
+
+    ASSERT_EQ(ui::Dataspace::DISPLAY_P3, mOutDataspace);
+    ASSERT_EQ(ui::ColorMode::DISPLAY_P3, mOutColorMode);
+    ASSERT_EQ(ui::RenderIntent::COLORIMETRIC, mOutRenderIntent);
+}
+
+TEST_F(GetBestColorModeTest, DataspaceDisplayP3_ColorModeDISPLAY_BT2020) {
+    addHwcColorModesMapping(ui::ColorMode::DISPLAY_BT2020,
+                            std::vector<ui::RenderIntent>(1, RenderIntent::COLORIMETRIC));
+    setInputDataspace(ui::Dataspace::DISPLAY_P3);
+    setInputRenderIntent(ui::RenderIntent::COLORIMETRIC);
+    setHasWideColorGamut(true);
+
+    getBestColorMode();
+
+    ASSERT_EQ(ui::Dataspace::DISPLAY_BT2020, mOutDataspace);
+    ASSERT_EQ(ui::ColorMode::DISPLAY_BT2020, mOutColorMode);
+    ASSERT_EQ(ui::RenderIntent::COLORIMETRIC, mOutRenderIntent);
+}
+
+} // namespace
+} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/DisplayDevice_SetProjectionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayDevice_SetProjectionTest.cpp
new file mode 100644
index 0000000..9fe30f8
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/DisplayDevice_SetProjectionTest.cpp
@@ -0,0 +1,250 @@
+/*
+ * Copyright 2020 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"
+
+#include "DisplayTransactionTestHelpers.h"
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+namespace android {
+namespace {
+
+using FakeDisplayDeviceInjector = TestableSurfaceFlinger::FakeDisplayDeviceInjector;
+
+class DisplayDeviceSetProjectionTest : public DisplayTransactionTest {
+public:
+    static constexpr int32_t DEFAULT_DISPLAY_WIDTH = 1080;  // arbitrary
+    static constexpr int32_t DEFAULT_DISPLAY_HEIGHT = 1920; // arbitrary
+
+    static constexpr int32_t TRANSFORM_FLAGS_ROT_0 = 0;
+    static constexpr int32_t TRANSFORM_FLAGS_ROT_90 = HAL_TRANSFORM_ROT_90;
+    static constexpr int32_t TRANSFORM_FLAGS_ROT_180 = HAL_TRANSFORM_FLIP_H | HAL_TRANSFORM_FLIP_V;
+    static constexpr int32_t TRANSFORM_FLAGS_ROT_270 =
+            HAL_TRANSFORM_FLIP_H | HAL_TRANSFORM_FLIP_V | HAL_TRANSFORM_ROT_90;
+
+    DisplayDeviceSetProjectionTest(ui::Size flingerDisplaySize, ui::Size hardwareDisplaySize,
+                                   ui::Rotation physicalOrientation)
+          : mFlingerDisplaySize(flingerDisplaySize),
+            mHardwareDisplaySize(hardwareDisplaySize),
+            mPhysicalOrientation(physicalOrientation),
+            mDisplayDevice(createDisplayDevice()) {}
+
+    sp<DisplayDevice> createDisplayDevice() {
+        return injectDefaultInternalDisplay([this](FakeDisplayDeviceInjector& injector) {
+            injector.setPhysicalOrientation(mPhysicalOrientation);
+        });
+    }
+
+    ui::Size swapWH(const ui::Size size) const { return ui::Size(size.height, size.width); }
+
+    void setProjectionForRotation0() {
+        // A logical rotation of 0 uses the SurfaceFlinger display size
+        mDisplayDevice->setProjection(ui::ROTATION_0, Rect(mFlingerDisplaySize),
+                                      Rect(mFlingerDisplaySize));
+    }
+
+    void setProjectionForRotation90() {
+        // A logical rotation of 90 uses the SurfaceFlinger display size with
+        // the width/height swapped.
+        mDisplayDevice->setProjection(ui::ROTATION_90, Rect(swapWH(mFlingerDisplaySize)),
+                                      Rect(swapWH(mFlingerDisplaySize)));
+    }
+
+    void setProjectionForRotation180() {
+        // A logical rotation of 180 uses the SurfaceFlinger display size
+        mDisplayDevice->setProjection(ui::ROTATION_180, Rect(mFlingerDisplaySize),
+                                      Rect(mFlingerDisplaySize));
+    }
+
+    void setProjectionForRotation270() {
+        // A logical rotation of 270 uses the SurfaceFlinger display size with
+        // the width/height swapped.
+        mDisplayDevice->setProjection(ui::ROTATION_270, Rect(swapWH(mFlingerDisplaySize)),
+                                      Rect(swapWH(mFlingerDisplaySize)));
+    }
+
+    void expectStateForHardwareTransform0() {
+        const auto& compositionState = mDisplayDevice->getCompositionDisplay()->getState();
+        EXPECT_EQ(ui::Transform(TRANSFORM_FLAGS_ROT_0, mHardwareDisplaySize.width,
+                                mHardwareDisplaySize.height),
+                  compositionState.transform);
+        EXPECT_EQ(ui::ROTATION_0, compositionState.displaySpace.orientation);
+        EXPECT_EQ(Rect(mHardwareDisplaySize), compositionState.displaySpace.content);
+        EXPECT_EQ(Rect(mHardwareDisplaySize), compositionState.orientedDisplaySpace.content);
+        EXPECT_EQ(Rect(mHardwareDisplaySize), compositionState.layerStackSpace.content);
+        EXPECT_EQ(false, compositionState.needsFiltering);
+    }
+
+    void expectStateForHardwareTransform90() {
+        const auto& compositionState = mDisplayDevice->getCompositionDisplay()->getState();
+        EXPECT_EQ(ui::Transform(TRANSFORM_FLAGS_ROT_90, mHardwareDisplaySize.width,
+                                mHardwareDisplaySize.height),
+                  compositionState.transform);
+        EXPECT_EQ(ui::ROTATION_90, compositionState.displaySpace.orientation);
+        EXPECT_EQ(Rect(mHardwareDisplaySize), compositionState.displaySpace.content);
+        // For 90, the orientedDisplaySpaceRect and layerStackSpaceRect have the hardware display
+        // size width and height swapped
+        EXPECT_EQ(Rect(swapWH(mHardwareDisplaySize)),
+                  compositionState.orientedDisplaySpace.content);
+        EXPECT_EQ(Rect(swapWH(mHardwareDisplaySize)), compositionState.layerStackSpace.content);
+        EXPECT_EQ(false, compositionState.needsFiltering);
+    }
+
+    void expectStateForHardwareTransform180() {
+        const auto& compositionState = mDisplayDevice->getCompositionDisplay()->getState();
+        EXPECT_EQ(ui::Transform(TRANSFORM_FLAGS_ROT_180, mHardwareDisplaySize.width,
+                                mHardwareDisplaySize.height),
+                  compositionState.transform);
+        EXPECT_EQ(ui::ROTATION_180, compositionState.displaySpace.orientation);
+        EXPECT_EQ(Rect(mHardwareDisplaySize), compositionState.orientedDisplaySpace.content);
+        EXPECT_EQ(Rect(mHardwareDisplaySize), compositionState.layerStackSpace.content);
+        EXPECT_EQ(false, compositionState.needsFiltering);
+    }
+
+    void expectStateForHardwareTransform270() {
+        const auto& compositionState = mDisplayDevice->getCompositionDisplay()->getState();
+        EXPECT_EQ(ui::Transform(TRANSFORM_FLAGS_ROT_270, mHardwareDisplaySize.width,
+                                mHardwareDisplaySize.height),
+                  compositionState.transform);
+        EXPECT_EQ(ui::ROTATION_270, compositionState.displaySpace.orientation);
+        EXPECT_EQ(Rect(mHardwareDisplaySize), compositionState.displaySpace.content);
+        // For 270, the orientedDisplaySpaceRect and layerStackSpaceRect have the hardware display
+        // size width and height swapped
+        EXPECT_EQ(Rect(swapWH(mHardwareDisplaySize)),
+                  compositionState.orientedDisplaySpace.content);
+        EXPECT_EQ(Rect(swapWH(mHardwareDisplaySize)), compositionState.layerStackSpace.content);
+        EXPECT_EQ(false, compositionState.needsFiltering);
+    }
+
+    const ui::Size mFlingerDisplaySize;
+    const ui::Size mHardwareDisplaySize;
+    const ui::Rotation mPhysicalOrientation;
+    const sp<DisplayDevice> mDisplayDevice;
+};
+
+struct DisplayDeviceSetProjectionTest_Installed0 : public DisplayDeviceSetProjectionTest {
+    DisplayDeviceSetProjectionTest_Installed0()
+          : DisplayDeviceSetProjectionTest(ui::Size(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
+                                           ui::Size(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
+                                           ui::ROTATION_0) {}
+};
+
+TEST_F(DisplayDeviceSetProjectionTest_Installed0, checkWith0OutputRotation) {
+    setProjectionForRotation0();
+    expectStateForHardwareTransform0();
+}
+
+TEST_F(DisplayDeviceSetProjectionTest_Installed0, checkWith90OutputRotation) {
+    setProjectionForRotation90();
+    expectStateForHardwareTransform90();
+}
+
+TEST_F(DisplayDeviceSetProjectionTest_Installed0, checkWith180OutputRotation) {
+    setProjectionForRotation180();
+    expectStateForHardwareTransform180();
+}
+
+TEST_F(DisplayDeviceSetProjectionTest_Installed0, checkWith270OutputRotation) {
+    setProjectionForRotation270();
+    expectStateForHardwareTransform270();
+}
+
+struct DisplayDeviceSetProjectionTest_Installed90 : public DisplayDeviceSetProjectionTest {
+    DisplayDeviceSetProjectionTest_Installed90()
+          : DisplayDeviceSetProjectionTest(ui::Size(DEFAULT_DISPLAY_HEIGHT, DEFAULT_DISPLAY_WIDTH),
+                                           ui::Size(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
+                                           ui::ROTATION_90) {}
+};
+
+TEST_F(DisplayDeviceSetProjectionTest_Installed90, checkWith0OutputRotation) {
+    setProjectionForRotation0();
+    expectStateForHardwareTransform90();
+}
+
+TEST_F(DisplayDeviceSetProjectionTest_Installed90, checkWith90OutputRotation) {
+    setProjectionForRotation90();
+    expectStateForHardwareTransform180();
+}
+
+TEST_F(DisplayDeviceSetProjectionTest_Installed90, checkWith180OutputRotation) {
+    setProjectionForRotation180();
+    expectStateForHardwareTransform270();
+}
+
+TEST_F(DisplayDeviceSetProjectionTest_Installed90, checkWith270OutputRotation) {
+    setProjectionForRotation270();
+    expectStateForHardwareTransform0();
+}
+
+struct DisplayDeviceSetProjectionTest_Installed180 : public DisplayDeviceSetProjectionTest {
+    DisplayDeviceSetProjectionTest_Installed180()
+          : DisplayDeviceSetProjectionTest(ui::Size(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
+                                           ui::Size(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
+                                           ui::ROTATION_180) {}
+};
+
+TEST_F(DisplayDeviceSetProjectionTest_Installed180, checkWith0OutputRotation) {
+    setProjectionForRotation0();
+    expectStateForHardwareTransform180();
+}
+
+TEST_F(DisplayDeviceSetProjectionTest_Installed180, checkWith90OutputRotation) {
+    setProjectionForRotation90();
+    expectStateForHardwareTransform270();
+}
+
+TEST_F(DisplayDeviceSetProjectionTest_Installed180, checkWith180OutputRotation) {
+    setProjectionForRotation180();
+    expectStateForHardwareTransform0();
+}
+
+TEST_F(DisplayDeviceSetProjectionTest_Installed180, checkWith270OutputRotation) {
+    setProjectionForRotation270();
+    expectStateForHardwareTransform90();
+}
+
+struct DisplayDeviceSetProjectionTest_Installed270 : public DisplayDeviceSetProjectionTest {
+    DisplayDeviceSetProjectionTest_Installed270()
+          : DisplayDeviceSetProjectionTest(ui::Size(DEFAULT_DISPLAY_HEIGHT, DEFAULT_DISPLAY_WIDTH),
+                                           ui::Size(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
+                                           ui::ROTATION_270) {}
+};
+
+TEST_F(DisplayDeviceSetProjectionTest_Installed270, checkWith0OutputRotation) {
+    setProjectionForRotation0();
+    expectStateForHardwareTransform270();
+}
+
+TEST_F(DisplayDeviceSetProjectionTest_Installed270, checkWith90OutputRotation) {
+    setProjectionForRotation90();
+    expectStateForHardwareTransform0();
+}
+
+TEST_F(DisplayDeviceSetProjectionTest_Installed270, checkWith180OutputRotation) {
+    setProjectionForRotation180();
+    expectStateForHardwareTransform90();
+}
+
+TEST_F(DisplayDeviceSetProjectionTest_Installed270, checkWith270OutputRotation) {
+    setProjectionForRotation270();
+    expectStateForHardwareTransform180();
+}
+
+} // namespace
+} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
index e055e95..db05d5a 100644
--- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
@@ -14,160 +14,22 @@
  * limitations under the License.
  */
 
-// TODO(b/129481165): remove the #pragma below and fix conversion issues
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wconversion"
-
 #undef LOG_TAG
 #define LOG_TAG "LibSurfaceFlingerUnittests"
 
-#include <type_traits>
-
-#include <android/hardware/power/Boost.h>
-#include <binder/IPCThreadState.h>
-#include <compositionengine/Display.h>
-#include <compositionengine/DisplayColorProfile.h>
-#include <compositionengine/impl/Display.h>
-#include <compositionengine/impl/OutputCompositionState.h>
-#include <compositionengine/mock/Display.h>
-#include <compositionengine/mock/DisplayColorProfile.h>
-#include <compositionengine/mock/DisplaySurface.h>
-#include <compositionengine/mock/RenderSurface.h>
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-#include <gui/mock/GraphicBufferConsumer.h>
-#include <gui/mock/GraphicBufferProducer.h>
-#include <log/log.h>
-#include <private/android_filesystem_config.h>
-#include <renderengine/mock/RenderEngine.h>
-#include <ui/DebugUtils.h>
-
-#include "DisplayIdentificationTest.h"
-#include "TestableScheduler.h"
-#include "TestableSurfaceFlinger.h"
-#include "mock/DisplayHardware/MockComposer.h"
-#include "mock/DisplayHardware/MockPowerAdvisor.h"
-#include "mock/MockEventThread.h"
-#include "mock/MockMessageQueue.h"
-#include "mock/MockNativeWindowSurface.h"
-#include "mock/MockSchedulerCallback.h"
-#include "mock/MockSurfaceInterceptor.h"
-#include "mock/MockVsyncController.h"
-#include "mock/system/window/MockNativeWindow.h"
+#include "DisplayTransactionTestHelpers.h"
 
 namespace android {
-namespace {
 
-namespace hal = android::hardware::graphics::composer::hal;
-
-using android::hardware::power::Boost;
-
-using testing::_;
 using testing::AnyNumber;
 using testing::DoAll;
 using testing::Mock;
-using testing::ResultOf;
 using testing::Return;
-using testing::ReturnRefOfCopy;
 using testing::SetArgPointee;
-using testing::StrictMock;
 
-using hal::ColorMode;
-using hal::Connection;
-using hal::DisplayCapability;
-using hal::DisplayType;
-using hal::Error;
-using hal::Hdr;
-using hal::HWDisplayId;
-using hal::IComposer;
-using hal::IComposerClient;
-using hal::PerFrameMetadataKey;
-using hal::PowerMode;
-using hal::RenderIntent;
+using android::hardware::graphics::composer::hal::HWDisplayId;
 
 using FakeDisplayDeviceInjector = TestableSurfaceFlinger::FakeDisplayDeviceInjector;
-using FakeHwcDisplayInjector = TestableSurfaceFlinger::FakeHwcDisplayInjector;
-using HotplugEvent = TestableSurfaceFlinger::HotplugEvent;
-using HWC2Display = TestableSurfaceFlinger::HWC2Display;
-
-constexpr int32_t DEFAULT_REFRESH_RATE = 16'666'667;
-constexpr int32_t DEFAULT_DPI = 320;
-constexpr int DEFAULT_VIRTUAL_DISPLAY_SURFACE_FORMAT = HAL_PIXEL_FORMAT_RGB_565;
-
-constexpr int POWER_MODE_LEET = 1337; // An out of range power mode value
-
-/* ------------------------------------------------------------------------
- * Boolean avoidance
- *
- * To make calls and template instantiations more readable, we define some
- * local enums along with an implicit bool conversion.
- */
-
-#define BOOL_SUBSTITUTE(TYPENAME) enum class TYPENAME : bool { FALSE = false, TRUE = true };
-
-BOOL_SUBSTITUTE(Async);
-BOOL_SUBSTITUTE(Critical);
-BOOL_SUBSTITUTE(Primary);
-BOOL_SUBSTITUTE(Secure);
-BOOL_SUBSTITUTE(Virtual);
-
-/* ------------------------------------------------------------------------
- *
- */
-
-class DisplayTransactionTest : public testing::Test {
-public:
-    DisplayTransactionTest();
-    ~DisplayTransactionTest() override;
-
-    // --------------------------------------------------------------------
-    // Mock/Fake injection
-
-    void injectMockScheduler();
-    void injectMockComposer(int virtualDisplayCount);
-    void injectFakeBufferQueueFactory();
-    void injectFakeNativeWindowSurfaceFactory();
-    sp<DisplayDevice> injectDefaultInternalDisplay(std::function<void(FakeDisplayDeviceInjector&)>);
-
-    // --------------------------------------------------------------------
-    // Postcondition helpers
-
-    bool hasPhysicalHwcDisplay(HWDisplayId hwcDisplayId);
-    bool hasTransactionFlagSet(int flag);
-    bool hasDisplayDevice(sp<IBinder> displayToken);
-    sp<DisplayDevice> getDisplayDevice(sp<IBinder> displayToken);
-    bool hasCurrentDisplayState(sp<IBinder> displayToken);
-    const DisplayDeviceState& getCurrentDisplayState(sp<IBinder> displayToken);
-    bool hasDrawingDisplayState(sp<IBinder> displayToken);
-    const DisplayDeviceState& getDrawingDisplayState(sp<IBinder> displayToken);
-
-    // --------------------------------------------------------------------
-    // Test instances
-
-    TestableSurfaceFlinger mFlinger;
-    sp<mock::NativeWindow> mNativeWindow = new mock::NativeWindow();
-    sp<GraphicBuffer> mBuffer = new GraphicBuffer();
-    Hwc2::mock::PowerAdvisor mPowerAdvisor;
-
-    // These mocks are created by the test, but are destroyed by SurfaceFlinger
-    // by virtue of being stored into a std::unique_ptr. However we still need
-    // to keep a reference to them for use in setting up call expectations.
-    renderengine::mock::RenderEngine* mRenderEngine = new renderengine::mock::RenderEngine();
-    Hwc2::mock::Composer* mComposer = nullptr;
-    mock::MessageQueue* mMessageQueue = new mock::MessageQueue();
-    sp<mock::SurfaceInterceptor> mSurfaceInterceptor = new mock::SurfaceInterceptor;
-
-    mock::VsyncController* mVsyncController = new mock::VsyncController;
-    mock::VSyncTracker* mVSyncTracker = new mock::VSyncTracker;
-    mock::SchedulerCallback mSchedulerCallback;
-    mock::EventThread* mEventThread = new mock::EventThread;
-    mock::EventThread* mSFEventThread = new mock::EventThread;
-
-    // These mocks are created only when expected to be created via a factory.
-    sp<mock::GraphicBufferConsumer> mConsumer;
-    sp<mock::GraphicBufferProducer> mProducer;
-    surfaceflinger::mock::NativeWindowSurface* mNativeWindowSurface = nullptr;
-};
 
 DisplayTransactionTest::DisplayTransactionTest() {
     const ::testing::TestInfo* const test_info =
@@ -330,3298 +192,4 @@
     return mFlinger.mutableDrawingState().displays.valueFor(displayToken);
 }
 
-/* ------------------------------------------------------------------------
- *
- */
-
-template <typename PhysicalDisplay>
-struct PhysicalDisplayIdType {};
-
-template <uint64_t displayId>
-using HalVirtualDisplayIdType = std::integral_constant<uint64_t, displayId>;
-
-struct GpuVirtualDisplayIdType {};
-
-template <typename>
-struct IsPhysicalDisplayId : std::bool_constant<false> {};
-
-template <typename PhysicalDisplay>
-struct IsPhysicalDisplayId<PhysicalDisplayIdType<PhysicalDisplay>> : std::bool_constant<true> {};
-
-template <typename>
-struct DisplayIdGetter;
-
-template <typename PhysicalDisplay>
-struct DisplayIdGetter<PhysicalDisplayIdType<PhysicalDisplay>> {
-    static PhysicalDisplayId get() {
-        if (!PhysicalDisplay::HAS_IDENTIFICATION_DATA) {
-            return PhysicalDisplayId::fromPort(static_cast<bool>(PhysicalDisplay::PRIMARY)
-                                                       ? LEGACY_DISPLAY_TYPE_PRIMARY
-                                                       : LEGACY_DISPLAY_TYPE_EXTERNAL);
-        }
-
-        const auto info =
-                parseDisplayIdentificationData(PhysicalDisplay::PORT,
-                                               PhysicalDisplay::GET_IDENTIFICATION_DATA());
-        return info ? info->id : PhysicalDisplayId::fromPort(PhysicalDisplay::PORT);
-    }
-};
-
-template <uint64_t displayId>
-struct DisplayIdGetter<HalVirtualDisplayIdType<displayId>> {
-    static HalVirtualDisplayId get() { return HalVirtualDisplayId(displayId); }
-};
-
-template <>
-struct DisplayIdGetter<GpuVirtualDisplayIdType> {
-    static GpuVirtualDisplayId get() { return GpuVirtualDisplayId(0); }
-};
-
-template <typename>
-struct DisplayConnectionTypeGetter {
-    static constexpr std::optional<DisplayConnectionType> value;
-};
-
-template <typename PhysicalDisplay>
-struct DisplayConnectionTypeGetter<PhysicalDisplayIdType<PhysicalDisplay>> {
-    static constexpr std::optional<DisplayConnectionType> value = PhysicalDisplay::CONNECTION_TYPE;
-};
-
-template <typename>
-struct HwcDisplayIdGetter {
-    static constexpr std::optional<HWDisplayId> value;
-};
-
-constexpr HWDisplayId HWC_VIRTUAL_DISPLAY_HWC_DISPLAY_ID = 1010;
-
-template <uint64_t displayId>
-struct HwcDisplayIdGetter<HalVirtualDisplayIdType<displayId>> {
-    static constexpr std::optional<HWDisplayId> value = HWC_VIRTUAL_DISPLAY_HWC_DISPLAY_ID;
-};
-
-template <typename PhysicalDisplay>
-struct HwcDisplayIdGetter<PhysicalDisplayIdType<PhysicalDisplay>> {
-    static constexpr std::optional<HWDisplayId> value = PhysicalDisplay::HWC_DISPLAY_ID;
-};
-
-// DisplayIdType can be:
-//     1) PhysicalDisplayIdType<...> for generated ID of physical display backed by HWC.
-//     2) HalVirtualDisplayIdType<...> for hard-coded ID of virtual display backed by HWC.
-//     3) GpuVirtualDisplayIdType for virtual display without HWC backing.
-template <typename DisplayIdType, int width, int height, Critical critical, Async async,
-          Secure secure, Primary primary, int grallocUsage>
-struct DisplayVariant {
-    using DISPLAY_ID = DisplayIdGetter<DisplayIdType>;
-    using CONNECTION_TYPE = DisplayConnectionTypeGetter<DisplayIdType>;
-    using HWC_DISPLAY_ID_OPT = HwcDisplayIdGetter<DisplayIdType>;
-
-    // The display width and height
-    static constexpr int WIDTH = width;
-    static constexpr int HEIGHT = height;
-
-    static constexpr int GRALLOC_USAGE = grallocUsage;
-
-    // Whether the display is virtual or physical
-    static constexpr Virtual VIRTUAL =
-            IsPhysicalDisplayId<DisplayIdType>{} ? Virtual::FALSE : Virtual::TRUE;
-
-    // When creating native window surfaces for the framebuffer, whether those should be critical
-    static constexpr Critical CRITICAL = critical;
-
-    // When creating native window surfaces for the framebuffer, whether those should be async
-    static constexpr Async ASYNC = async;
-
-    // Whether the display should be treated as secure
-    static constexpr Secure SECURE = secure;
-
-    // Whether the display is primary
-    static constexpr Primary PRIMARY = primary;
-
-    static auto makeFakeExistingDisplayInjector(DisplayTransactionTest* test) {
-        auto ceDisplayArgs = compositionengine::DisplayCreationArgsBuilder();
-        if (auto displayId = PhysicalDisplayId::tryCast(DISPLAY_ID::get())) {
-            ceDisplayArgs.setPhysical({*displayId, DisplayConnectionType::Internal});
-        } else {
-            // We turn off the use of HwcVirtualDisplays, to prevent Composition Engine
-            // from calling into HWComposer. This way all virtual displays will get
-            // a GpuVirtualDisplayId, even if we are in the HwcVirtualDisplayVariant.
-            // In this case we later override it by calling display.setDisplayIdForTesting().
-            ceDisplayArgs.setUseHwcVirtualDisplays(false);
-
-            GpuVirtualDisplayId desiredDisplayId = GpuVirtualDisplayId::tryCast(DISPLAY_ID::get())
-                                                           .value_or(GpuVirtualDisplayId(0));
-
-            ON_CALL(test->mFlinger.gpuVirtualDisplayIdGenerator(), nextId())
-                    .WillByDefault(Return(desiredDisplayId));
-
-            auto& generator = test->mFlinger.gpuVirtualDisplayIdGenerator();
-            ceDisplayArgs.setGpuVirtualDisplayIdGenerator(generator);
-        }
-        ceDisplayArgs.setPixels({WIDTH, HEIGHT}).setPowerAdvisor(&test->mPowerAdvisor);
-
-        auto compositionDisplay =
-                compositionengine::impl::createDisplay(test->mFlinger.getCompositionEngine(),
-                                                       ceDisplayArgs.build());
-
-        if (HalVirtualDisplayId::tryCast(DISPLAY_ID::get())) {
-            // CompositionEngine has assigned a placeholder GpuVirtualDisplayId and we need to
-            // override it with the correct HalVirtualDisplayId.
-            compositionDisplay->setDisplayIdForTesting(DISPLAY_ID::get());
-        }
-
-        auto injector = FakeDisplayDeviceInjector(test->mFlinger, compositionDisplay,
-                                                  CONNECTION_TYPE::value, HWC_DISPLAY_ID_OPT::value,
-                                                  static_cast<bool>(PRIMARY));
-
-        injector.setSecure(static_cast<bool>(SECURE));
-        injector.setNativeWindow(test->mNativeWindow);
-
-        // Creating a DisplayDevice requires getting default dimensions from the
-        // native window along with some other initial setup.
-        EXPECT_CALL(*test->mNativeWindow, query(NATIVE_WINDOW_WIDTH, _))
-                .WillRepeatedly(DoAll(SetArgPointee<1>(WIDTH), Return(0)));
-        EXPECT_CALL(*test->mNativeWindow, query(NATIVE_WINDOW_HEIGHT, _))
-                .WillRepeatedly(DoAll(SetArgPointee<1>(HEIGHT), Return(0)));
-        EXPECT_CALL(*test->mNativeWindow, perform(NATIVE_WINDOW_SET_BUFFERS_FORMAT))
-                .WillRepeatedly(Return(0));
-        EXPECT_CALL(*test->mNativeWindow, perform(NATIVE_WINDOW_API_CONNECT))
-                .WillRepeatedly(Return(0));
-        EXPECT_CALL(*test->mNativeWindow, perform(NATIVE_WINDOW_SET_USAGE64))
-                .WillRepeatedly(Return(0));
-        EXPECT_CALL(*test->mNativeWindow, perform(NATIVE_WINDOW_API_DISCONNECT))
-                .WillRepeatedly(Return(0));
-
-        return injector;
-    }
-
-    // Called by tests to set up any native window creation call expectations.
-    static void setupNativeWindowSurfaceCreationCallExpectations(DisplayTransactionTest* test) {
-        EXPECT_CALL(*test->mNativeWindowSurface, getNativeWindow())
-                .WillOnce(Return(test->mNativeWindow));
-
-        EXPECT_CALL(*test->mNativeWindow, query(NATIVE_WINDOW_WIDTH, _))
-                .WillRepeatedly(DoAll(SetArgPointee<1>(WIDTH), Return(0)));
-        EXPECT_CALL(*test->mNativeWindow, query(NATIVE_WINDOW_HEIGHT, _))
-                .WillRepeatedly(DoAll(SetArgPointee<1>(HEIGHT), Return(0)));
-        EXPECT_CALL(*test->mNativeWindow, perform(NATIVE_WINDOW_SET_BUFFERS_FORMAT))
-                .WillRepeatedly(Return(0));
-        EXPECT_CALL(*test->mNativeWindow, perform(NATIVE_WINDOW_API_CONNECT))
-                .WillRepeatedly(Return(0));
-        EXPECT_CALL(*test->mNativeWindow, perform(NATIVE_WINDOW_SET_USAGE64))
-                .WillRepeatedly(Return(0));
-        EXPECT_CALL(*test->mNativeWindow, perform(NATIVE_WINDOW_API_DISCONNECT))
-                .WillRepeatedly(Return(0));
-    }
-
-    static void setupFramebufferConsumerBufferQueueCallExpectations(DisplayTransactionTest* test) {
-        EXPECT_CALL(*test->mConsumer, consumerConnect(_, false)).WillOnce(Return(NO_ERROR));
-        EXPECT_CALL(*test->mConsumer, setConsumerName(_)).WillRepeatedly(Return(NO_ERROR));
-        EXPECT_CALL(*test->mConsumer, setConsumerUsageBits(GRALLOC_USAGE))
-                .WillRepeatedly(Return(NO_ERROR));
-        EXPECT_CALL(*test->mConsumer, setDefaultBufferSize(WIDTH, HEIGHT))
-                .WillRepeatedly(Return(NO_ERROR));
-        EXPECT_CALL(*test->mConsumer, setMaxAcquiredBufferCount(_))
-                .WillRepeatedly(Return(NO_ERROR));
-    }
-
-    static void setupFramebufferProducerBufferQueueCallExpectations(DisplayTransactionTest* test) {
-        EXPECT_CALL(*test->mProducer, allocateBuffers(0, 0, 0, 0)).WillRepeatedly(Return());
-    }
-};
-
-template <HWDisplayId hwcDisplayId, DisplayType hwcDisplayType, typename DisplayVariant,
-          typename PhysicalDisplay = void>
-struct HwcDisplayVariant {
-    // The display id supplied by the HWC
-    static constexpr HWDisplayId HWC_DISPLAY_ID = hwcDisplayId;
-
-    // The HWC display type
-    static constexpr DisplayType HWC_DISPLAY_TYPE = hwcDisplayType;
-
-    // The HWC active configuration id
-    static constexpr int HWC_ACTIVE_CONFIG_ID = 2001;
-    static constexpr PowerMode INIT_POWER_MODE = PowerMode::ON;
-
-    static void injectPendingHotplugEvent(DisplayTransactionTest* test, Connection connection) {
-        test->mFlinger.mutablePendingHotplugEvents().emplace_back(
-                HotplugEvent{HWC_DISPLAY_ID, connection});
-    }
-
-    // Called by tests to inject a HWC display setup
-    static void injectHwcDisplayWithNoDefaultCapabilities(DisplayTransactionTest* test) {
-        const auto displayId = DisplayVariant::DISPLAY_ID::get();
-        ASSERT_FALSE(GpuVirtualDisplayId::tryCast(displayId));
-        FakeHwcDisplayInjector(displayId, HWC_DISPLAY_TYPE,
-                               static_cast<bool>(DisplayVariant::PRIMARY))
-                .setHwcDisplayId(HWC_DISPLAY_ID)
-                .setWidth(DisplayVariant::WIDTH)
-                .setHeight(DisplayVariant::HEIGHT)
-                .setActiveConfig(HWC_ACTIVE_CONFIG_ID)
-                .setPowerMode(INIT_POWER_MODE)
-                .inject(&test->mFlinger, test->mComposer);
-    }
-
-    // Called by tests to inject a HWC display setup
-    static void injectHwcDisplay(DisplayTransactionTest* test) {
-        EXPECT_CALL(*test->mComposer, getDisplayCapabilities(HWC_DISPLAY_ID, _))
-                .WillOnce(DoAll(SetArgPointee<1>(std::vector<DisplayCapability>({})),
-                                Return(Error::NONE)));
-        EXPECT_CALL(*test->mComposer, setPowerMode(HWC_DISPLAY_ID, INIT_POWER_MODE))
-                .WillOnce(Return(Error::NONE));
-        injectHwcDisplayWithNoDefaultCapabilities(test);
-    }
-
-    static std::shared_ptr<compositionengine::Display> injectCompositionDisplay(
-            DisplayTransactionTest* test) {
-        const ::testing::TestInfo* const test_info =
-                ::testing::UnitTest::GetInstance()->current_test_info();
-
-        auto ceDisplayArgs = compositionengine::DisplayCreationArgsBuilder()
-                                     .setPhysical({DisplayVariant::DISPLAY_ID::get(),
-                                                   PhysicalDisplay::CONNECTION_TYPE})
-                                     .setPixels({DisplayVariant::WIDTH, DisplayVariant::HEIGHT})
-                                     .setIsSecure(static_cast<bool>(DisplayVariant::SECURE))
-                                     .setPowerAdvisor(&test->mPowerAdvisor)
-                                     .setName(std::string("Injected display for ") +
-                                              test_info->test_case_name() + "." + test_info->name())
-                                     .build();
-
-        return compositionengine::impl::createDisplay(test->mFlinger.getCompositionEngine(),
-                                                      ceDisplayArgs);
-    }
-
-    static void setupHwcHotplugCallExpectations(DisplayTransactionTest* test) {
-        constexpr auto CONNECTION_TYPE =
-                PhysicalDisplay::CONNECTION_TYPE == DisplayConnectionType::Internal
-                ? IComposerClient::DisplayConnectionType::INTERNAL
-                : IComposerClient::DisplayConnectionType::EXTERNAL;
-
-        EXPECT_CALL(*test->mComposer, getDisplayConnectionType(HWC_DISPLAY_ID, _))
-                .WillOnce(DoAll(SetArgPointee<1>(CONNECTION_TYPE), Return(hal::V2_4::Error::NONE)));
-
-        EXPECT_CALL(*test->mComposer, setClientTargetSlotCount(_))
-                .WillOnce(Return(hal::Error::NONE));
-        EXPECT_CALL(*test->mComposer, getDisplayConfigs(HWC_DISPLAY_ID, _))
-                .WillOnce(DoAll(SetArgPointee<1>(std::vector<unsigned>{HWC_ACTIVE_CONFIG_ID}),
-                                Return(Error::NONE)));
-        EXPECT_CALL(*test->mComposer,
-                    getDisplayAttribute(HWC_DISPLAY_ID, HWC_ACTIVE_CONFIG_ID,
-                                        IComposerClient::Attribute::WIDTH, _))
-                .WillOnce(DoAll(SetArgPointee<3>(DisplayVariant::WIDTH), Return(Error::NONE)));
-        EXPECT_CALL(*test->mComposer,
-                    getDisplayAttribute(HWC_DISPLAY_ID, HWC_ACTIVE_CONFIG_ID,
-                                        IComposerClient::Attribute::HEIGHT, _))
-                .WillOnce(DoAll(SetArgPointee<3>(DisplayVariant::HEIGHT), Return(Error::NONE)));
-        EXPECT_CALL(*test->mComposer,
-                    getDisplayAttribute(HWC_DISPLAY_ID, HWC_ACTIVE_CONFIG_ID,
-                                        IComposerClient::Attribute::VSYNC_PERIOD, _))
-                .WillOnce(DoAll(SetArgPointee<3>(DEFAULT_REFRESH_RATE), Return(Error::NONE)));
-        EXPECT_CALL(*test->mComposer,
-                    getDisplayAttribute(HWC_DISPLAY_ID, HWC_ACTIVE_CONFIG_ID,
-                                        IComposerClient::Attribute::DPI_X, _))
-                .WillOnce(DoAll(SetArgPointee<3>(DEFAULT_DPI), Return(Error::NONE)));
-        EXPECT_CALL(*test->mComposer,
-                    getDisplayAttribute(HWC_DISPLAY_ID, HWC_ACTIVE_CONFIG_ID,
-                                        IComposerClient::Attribute::DPI_Y, _))
-                .WillOnce(DoAll(SetArgPointee<3>(DEFAULT_DPI), Return(Error::NONE)));
-        EXPECT_CALL(*test->mComposer,
-                    getDisplayAttribute(HWC_DISPLAY_ID, HWC_ACTIVE_CONFIG_ID,
-                                        IComposerClient::Attribute::CONFIG_GROUP, _))
-                .WillOnce(DoAll(SetArgPointee<3>(-1), Return(Error::NONE)));
-
-        if (PhysicalDisplay::HAS_IDENTIFICATION_DATA) {
-            EXPECT_CALL(*test->mComposer, getDisplayIdentificationData(HWC_DISPLAY_ID, _, _))
-                    .WillOnce(DoAll(SetArgPointee<1>(PhysicalDisplay::PORT),
-                                    SetArgPointee<2>(PhysicalDisplay::GET_IDENTIFICATION_DATA()),
-                                    Return(Error::NONE)));
-        } else {
-            EXPECT_CALL(*test->mComposer, getDisplayIdentificationData(HWC_DISPLAY_ID, _, _))
-                    .WillOnce(Return(Error::UNSUPPORTED));
-        }
-    }
-
-    // Called by tests to set up HWC call expectations
-    static void setupHwcGetActiveConfigCallExpectations(DisplayTransactionTest* test) {
-        EXPECT_CALL(*test->mComposer, getActiveConfig(HWC_DISPLAY_ID, _))
-                .WillRepeatedly(DoAll(SetArgPointee<1>(HWC_ACTIVE_CONFIG_ID), Return(Error::NONE)));
-    }
-};
-
-// Physical displays are expected to be synchronous, secure, and have a HWC display for output.
-constexpr uint32_t GRALLOC_USAGE_PHYSICAL_DISPLAY =
-        GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_COMPOSER | GRALLOC_USAGE_HW_FB;
-
-template <typename PhysicalDisplay, int width, int height, Critical critical>
-struct PhysicalDisplayVariant
-      : DisplayVariant<PhysicalDisplayIdType<PhysicalDisplay>, width, height, critical,
-                       Async::FALSE, Secure::TRUE, PhysicalDisplay::PRIMARY,
-                       GRALLOC_USAGE_PHYSICAL_DISPLAY>,
-        HwcDisplayVariant<PhysicalDisplay::HWC_DISPLAY_ID, DisplayType::PHYSICAL,
-                          DisplayVariant<PhysicalDisplayIdType<PhysicalDisplay>, width, height,
-                                         critical, Async::FALSE, Secure::TRUE,
-                                         PhysicalDisplay::PRIMARY, GRALLOC_USAGE_PHYSICAL_DISPLAY>,
-                          PhysicalDisplay> {};
-
-template <bool hasIdentificationData>
-struct PrimaryDisplay {
-    static constexpr auto CONNECTION_TYPE = DisplayConnectionType::Internal;
-    static constexpr Primary PRIMARY = Primary::TRUE;
-    static constexpr uint8_t PORT = 255;
-    static constexpr HWDisplayId HWC_DISPLAY_ID = 1001;
-    static constexpr bool HAS_IDENTIFICATION_DATA = hasIdentificationData;
-    static constexpr auto GET_IDENTIFICATION_DATA = getInternalEdid;
-};
-
-template <bool hasIdentificationData>
-struct ExternalDisplay {
-    static constexpr auto CONNECTION_TYPE = DisplayConnectionType::External;
-    static constexpr Primary PRIMARY = Primary::FALSE;
-    static constexpr uint8_t PORT = 254;
-    static constexpr HWDisplayId HWC_DISPLAY_ID = 1002;
-    static constexpr bool HAS_IDENTIFICATION_DATA = hasIdentificationData;
-    static constexpr auto GET_IDENTIFICATION_DATA = getExternalEdid;
-};
-
-struct TertiaryDisplay {
-    static constexpr Primary PRIMARY = Primary::FALSE;
-    static constexpr uint8_t PORT = 253;
-    static constexpr HWDisplayId HWC_DISPLAY_ID = 1003;
-    static constexpr auto GET_IDENTIFICATION_DATA = getExternalEdid;
-};
-
-// A primary display is a physical display that is critical
-using PrimaryDisplayVariant =
-        PhysicalDisplayVariant<PrimaryDisplay<false>, 3840, 2160, Critical::TRUE>;
-
-// An external display is physical display that is not critical.
-using ExternalDisplayVariant =
-        PhysicalDisplayVariant<ExternalDisplay<false>, 1920, 1280, Critical::FALSE>;
-
-using TertiaryDisplayVariant = PhysicalDisplayVariant<TertiaryDisplay, 1600, 1200, Critical::FALSE>;
-
-// A virtual display not supported by the HWC.
-constexpr uint32_t GRALLOC_USAGE_NONHWC_VIRTUAL_DISPLAY = 0;
-
-template <int width, int height, Secure secure>
-struct NonHwcVirtualDisplayVariant
-      : DisplayVariant<GpuVirtualDisplayIdType, width, height, Critical::FALSE, Async::TRUE, secure,
-                       Primary::FALSE, GRALLOC_USAGE_NONHWC_VIRTUAL_DISPLAY> {
-    using Base =
-            DisplayVariant<GpuVirtualDisplayIdType, width, height, Critical::FALSE, Async::TRUE,
-                           secure, Primary::FALSE, GRALLOC_USAGE_NONHWC_VIRTUAL_DISPLAY>;
-
-    static void injectHwcDisplay(DisplayTransactionTest*) {}
-
-    static std::shared_ptr<compositionengine::Display> injectCompositionDisplay(
-            DisplayTransactionTest* test) {
-        const ::testing::TestInfo* const test_info =
-                ::testing::UnitTest::GetInstance()->current_test_info();
-
-        ON_CALL(test->mFlinger.gpuVirtualDisplayIdGenerator(), nextId())
-                .WillByDefault(Return(Base::DISPLAY_ID::get()));
-
-        auto ceDisplayArgs = compositionengine::DisplayCreationArgsBuilder()
-                                     .setPixels({Base::WIDTH, Base::HEIGHT})
-                                     .setIsSecure(static_cast<bool>(Base::SECURE))
-                                     .setPowerAdvisor(&test->mPowerAdvisor)
-                                     .setName(std::string("Injected display for ") +
-                                              test_info->test_case_name() + "." + test_info->name())
-                                     .setGpuVirtualDisplayIdGenerator(
-                                             test->mFlinger.gpuVirtualDisplayIdGenerator())
-                                     .build();
-
-        return compositionengine::impl::createDisplay(test->mFlinger.getCompositionEngine(),
-                                                      ceDisplayArgs);
-    }
-
-    static void setupHwcGetActiveConfigCallExpectations(DisplayTransactionTest* test) {
-        EXPECT_CALL(*test->mComposer, getActiveConfig(_, _)).Times(0);
-    }
-
-    static void setupNativeWindowSurfaceCreationCallExpectations(DisplayTransactionTest* test) {
-        Base::setupNativeWindowSurfaceCreationCallExpectations(test);
-        EXPECT_CALL(*test->mNativeWindow, setSwapInterval(0)).Times(1);
-    }
-};
-
-// A virtual display supported by the HWC.
-constexpr uint32_t GRALLOC_USAGE_HWC_VIRTUAL_DISPLAY = GRALLOC_USAGE_HW_COMPOSER;
-
-template <int width, int height, Secure secure>
-struct HwcVirtualDisplayVariant
-      : DisplayVariant<HalVirtualDisplayIdType<42>, width, height, Critical::FALSE, Async::TRUE,
-                       secure, Primary::FALSE, GRALLOC_USAGE_HWC_VIRTUAL_DISPLAY>,
-        HwcDisplayVariant<HWC_VIRTUAL_DISPLAY_HWC_DISPLAY_ID, DisplayType::VIRTUAL,
-                          DisplayVariant<HalVirtualDisplayIdType<42>, width, height,
-                                         Critical::FALSE, Async::TRUE, secure, Primary::FALSE,
-                                         GRALLOC_USAGE_HWC_VIRTUAL_DISPLAY>> {
-    using Base = DisplayVariant<HalVirtualDisplayIdType<42>, width, height, Critical::FALSE,
-                                Async::TRUE, secure, Primary::FALSE, GRALLOC_USAGE_HW_COMPOSER>;
-    using Self = HwcVirtualDisplayVariant<width, height, secure>;
-
-    static std::shared_ptr<compositionengine::Display> injectCompositionDisplay(
-            DisplayTransactionTest* test) {
-        const ::testing::TestInfo* const test_info =
-                ::testing::UnitTest::GetInstance()->current_test_info();
-
-        // In order to prevent compostition engine calling into HWComposer, we
-        // 1. turn off the use of HWC virtual displays,
-        // 2. provide a GpuVirtualDisplayIdGenerator which always returns some fake ID
-        // 3. override the ID by calling setDisplayIdForTesting()
-
-        ON_CALL(test->mFlinger.gpuVirtualDisplayIdGenerator(), nextId())
-                .WillByDefault(Return(GpuVirtualDisplayId(0)));
-
-        auto ceDisplayArgs = compositionengine::DisplayCreationArgsBuilder()
-                                     .setUseHwcVirtualDisplays(false)
-                                     .setPixels({Base::WIDTH, Base::HEIGHT})
-                                     .setIsSecure(static_cast<bool>(Base::SECURE))
-                                     .setPowerAdvisor(&test->mPowerAdvisor)
-                                     .setName(std::string("Injected display for ") +
-                                              test_info->test_case_name() + "." + test_info->name())
-                                     .setGpuVirtualDisplayIdGenerator(
-                                             test->mFlinger.gpuVirtualDisplayIdGenerator())
-                                     .build();
-
-        auto compositionDisplay =
-                compositionengine::impl::createDisplay(test->mFlinger.getCompositionEngine(),
-                                                       ceDisplayArgs);
-        compositionDisplay->setDisplayIdForTesting(Base::DISPLAY_ID::get());
-
-        // Insert display data so that the HWC thinks it created the virtual display.
-        if (const auto displayId = Base::DISPLAY_ID::get();
-            HalVirtualDisplayId::tryCast(displayId)) {
-            test->mFlinger.mutableHwcDisplayData().try_emplace(displayId);
-        }
-
-        return compositionDisplay;
-    }
-
-    static void setupNativeWindowSurfaceCreationCallExpectations(DisplayTransactionTest* test) {
-        Base::setupNativeWindowSurfaceCreationCallExpectations(test);
-        EXPECT_CALL(*test->mNativeWindow, setSwapInterval(0)).Times(1);
-    }
-
-    static void setupHwcVirtualDisplayCreationCallExpectations(DisplayTransactionTest* test) {
-        EXPECT_CALL(*test->mComposer, createVirtualDisplay(Base::WIDTH, Base::HEIGHT, _, _))
-                .WillOnce(DoAll(SetArgPointee<3>(Self::HWC_DISPLAY_ID), Return(Error::NONE)));
-        EXPECT_CALL(*test->mComposer, setClientTargetSlotCount(_)).WillOnce(Return(Error::NONE));
-    }
-};
-
-// For this variant, SurfaceFlinger should not configure itself with wide
-// display support, so the display should not be configured for wide-color
-// support.
-struct WideColorSupportNotConfiguredVariant {
-    static constexpr bool WIDE_COLOR_SUPPORTED = false;
-
-    static void injectConfigChange(DisplayTransactionTest* test) {
-        test->mFlinger.mutableHasWideColorDisplay() = false;
-        test->mFlinger.mutableUseColorManagement() = false;
-        test->mFlinger.mutableDisplayColorSetting() = DisplayColorSetting::kUnmanaged;
-    }
-
-    static void setupComposerCallExpectations(DisplayTransactionTest* test) {
-        EXPECT_CALL(*test->mComposer, getColorModes(_, _)).Times(0);
-        EXPECT_CALL(*test->mComposer, getRenderIntents(_, _, _)).Times(0);
-        EXPECT_CALL(*test->mComposer, setColorMode(_, _, _)).Times(0);
-    }
-};
-
-// For this variant, SurfaceFlinger should configure itself with wide display
-// support, and the display should respond with an non-empty list of supported
-// color modes. Wide-color support should be configured.
-template <typename Display>
-struct WideColorP3ColorimetricSupportedVariant {
-    static constexpr bool WIDE_COLOR_SUPPORTED = true;
-
-    static void injectConfigChange(DisplayTransactionTest* test) {
-        test->mFlinger.mutableUseColorManagement() = true;
-        test->mFlinger.mutableHasWideColorDisplay() = true;
-        test->mFlinger.mutableDisplayColorSetting() = DisplayColorSetting::kUnmanaged;
-    }
-
-    static void setupComposerCallExpectations(DisplayTransactionTest* test) {
-        EXPECT_CALL(*test->mNativeWindow, perform(NATIVE_WINDOW_SET_BUFFERS_DATASPACE)).Times(1);
-
-        EXPECT_CALL(*test->mComposer, getColorModes(Display::HWC_DISPLAY_ID, _))
-                .WillOnce(DoAll(SetArgPointee<1>(std::vector<ColorMode>({ColorMode::DISPLAY_P3})),
-                                Return(Error::NONE)));
-        EXPECT_CALL(*test->mComposer,
-                    getRenderIntents(Display::HWC_DISPLAY_ID, ColorMode::DISPLAY_P3, _))
-                .WillOnce(DoAll(SetArgPointee<2>(
-                                        std::vector<RenderIntent>({RenderIntent::COLORIMETRIC})),
-                                Return(Error::NONE)));
-        EXPECT_CALL(*test->mComposer,
-                    setColorMode(Display::HWC_DISPLAY_ID, ColorMode::SRGB,
-                                 RenderIntent::COLORIMETRIC))
-                .WillOnce(Return(Error::NONE));
-    }
-};
-
-// For this variant, SurfaceFlinger should configure itself with wide display
-// support, but the display should respond with an empty list of supported color
-// modes. Wide-color support for the display should not be configured.
-template <typename Display>
-struct WideColorNotSupportedVariant {
-    static constexpr bool WIDE_COLOR_SUPPORTED = false;
-
-    static void injectConfigChange(DisplayTransactionTest* test) {
-        test->mFlinger.mutableUseColorManagement() = true;
-        test->mFlinger.mutableHasWideColorDisplay() = true;
-    }
-
-    static void setupComposerCallExpectations(DisplayTransactionTest* test) {
-        EXPECT_CALL(*test->mComposer, getColorModes(Display::HWC_DISPLAY_ID, _))
-                .WillOnce(DoAll(SetArgPointee<1>(std::vector<ColorMode>()), Return(Error::NONE)));
-        EXPECT_CALL(*test->mComposer, setColorMode(_, _, _)).Times(0);
-    }
-};
-
-// For this variant, the display is not a HWC display, so no HDR support should
-// be configured.
-struct NonHwcDisplayHdrSupportVariant {
-    static constexpr bool HDR10_PLUS_SUPPORTED = false;
-    static constexpr bool HDR10_SUPPORTED = false;
-    static constexpr bool HDR_HLG_SUPPORTED = false;
-    static constexpr bool HDR_DOLBY_VISION_SUPPORTED = false;
-    static void setupComposerCallExpectations(DisplayTransactionTest* test) {
-        EXPECT_CALL(*test->mComposer, getHdrCapabilities(_, _, _, _, _)).Times(0);
-    }
-};
-
-template <typename Display>
-struct Hdr10PlusSupportedVariant {
-    static constexpr bool HDR10_PLUS_SUPPORTED = true;
-    static constexpr bool HDR10_SUPPORTED = true;
-    static constexpr bool HDR_HLG_SUPPORTED = false;
-    static constexpr bool HDR_DOLBY_VISION_SUPPORTED = false;
-    static void setupComposerCallExpectations(DisplayTransactionTest* test) {
-        EXPECT_CALL(*test->mComposer, getHdrCapabilities(_, _, _, _, _))
-                .WillOnce(DoAll(SetArgPointee<1>(std::vector<Hdr>({
-                                        Hdr::HDR10_PLUS,
-                                        Hdr::HDR10,
-                                })),
-                                Return(Error::NONE)));
-    }
-};
-
-// For this variant, the composer should respond with a non-empty list of HDR
-// modes containing HDR10, so HDR10 support should be configured.
-template <typename Display>
-struct Hdr10SupportedVariant {
-    static constexpr bool HDR10_PLUS_SUPPORTED = false;
-    static constexpr bool HDR10_SUPPORTED = true;
-    static constexpr bool HDR_HLG_SUPPORTED = false;
-    static constexpr bool HDR_DOLBY_VISION_SUPPORTED = false;
-    static void setupComposerCallExpectations(DisplayTransactionTest* test) {
-        EXPECT_CALL(*test->mComposer, getHdrCapabilities(Display::HWC_DISPLAY_ID, _, _, _, _))
-                .WillOnce(DoAll(SetArgPointee<1>(std::vector<Hdr>({Hdr::HDR10})),
-                                Return(Error::NONE)));
-    }
-};
-
-// For this variant, the composer should respond with a non-empty list of HDR
-// modes containing HLG, so HLG support should be configured.
-template <typename Display>
-struct HdrHlgSupportedVariant {
-    static constexpr bool HDR10_PLUS_SUPPORTED = false;
-    static constexpr bool HDR10_SUPPORTED = false;
-    static constexpr bool HDR_HLG_SUPPORTED = true;
-    static constexpr bool HDR_DOLBY_VISION_SUPPORTED = false;
-    static void setupComposerCallExpectations(DisplayTransactionTest* test) {
-        EXPECT_CALL(*test->mComposer, getHdrCapabilities(Display::HWC_DISPLAY_ID, _, _, _, _))
-                .WillOnce(
-                        DoAll(SetArgPointee<1>(std::vector<Hdr>({Hdr::HLG})), Return(Error::NONE)));
-    }
-};
-
-// For this variant, the composer should respond with a non-empty list of HDR
-// modes containing DOLBY_VISION, so DOLBY_VISION support should be configured.
-template <typename Display>
-struct HdrDolbyVisionSupportedVariant {
-    static constexpr bool HDR10_PLUS_SUPPORTED = false;
-    static constexpr bool HDR10_SUPPORTED = false;
-    static constexpr bool HDR_HLG_SUPPORTED = false;
-    static constexpr bool HDR_DOLBY_VISION_SUPPORTED = true;
-    static void setupComposerCallExpectations(DisplayTransactionTest* test) {
-        EXPECT_CALL(*test->mComposer, getHdrCapabilities(Display::HWC_DISPLAY_ID, _, _, _, _))
-                .WillOnce(DoAll(SetArgPointee<1>(std::vector<Hdr>({Hdr::DOLBY_VISION})),
-                                Return(Error::NONE)));
-    }
-};
-
-// For this variant, the composer should respond with am empty list of HDR
-// modes, so no HDR support should be configured.
-template <typename Display>
-struct HdrNotSupportedVariant {
-    static constexpr bool HDR10_PLUS_SUPPORTED = false;
-    static constexpr bool HDR10_SUPPORTED = false;
-    static constexpr bool HDR_HLG_SUPPORTED = false;
-    static constexpr bool HDR_DOLBY_VISION_SUPPORTED = false;
-    static void setupComposerCallExpectations(DisplayTransactionTest* test) {
-        EXPECT_CALL(*test->mComposer, getHdrCapabilities(Display::HWC_DISPLAY_ID, _, _, _, _))
-                .WillOnce(DoAll(SetArgPointee<1>(std::vector<Hdr>()), Return(Error::NONE)));
-    }
-};
-
-struct NonHwcPerFrameMetadataSupportVariant {
-    static constexpr int PER_FRAME_METADATA_KEYS = 0;
-    static void setupComposerCallExpectations(DisplayTransactionTest* test) {
-        EXPECT_CALL(*test->mComposer, getPerFrameMetadataKeys(_)).Times(0);
-    }
-};
-
-template <typename Display>
-struct NoPerFrameMetadataSupportVariant {
-    static constexpr int PER_FRAME_METADATA_KEYS = 0;
-    static void setupComposerCallExpectations(DisplayTransactionTest* test) {
-        EXPECT_CALL(*test->mComposer, getPerFrameMetadataKeys(Display::HWC_DISPLAY_ID))
-                .WillOnce(Return(std::vector<PerFrameMetadataKey>()));
-    }
-};
-
-template <typename Display>
-struct Smpte2086PerFrameMetadataSupportVariant {
-    static constexpr int PER_FRAME_METADATA_KEYS = HdrMetadata::Type::SMPTE2086;
-    static void setupComposerCallExpectations(DisplayTransactionTest* test) {
-        EXPECT_CALL(*test->mComposer, getPerFrameMetadataKeys(Display::HWC_DISPLAY_ID))
-                .WillOnce(Return(std::vector<PerFrameMetadataKey>({
-                        PerFrameMetadataKey::DISPLAY_RED_PRIMARY_X,
-                        PerFrameMetadataKey::DISPLAY_RED_PRIMARY_Y,
-                        PerFrameMetadataKey::DISPLAY_GREEN_PRIMARY_X,
-                        PerFrameMetadataKey::DISPLAY_GREEN_PRIMARY_Y,
-                        PerFrameMetadataKey::DISPLAY_BLUE_PRIMARY_X,
-                        PerFrameMetadataKey::DISPLAY_BLUE_PRIMARY_Y,
-                        PerFrameMetadataKey::WHITE_POINT_X,
-                        PerFrameMetadataKey::WHITE_POINT_Y,
-                        PerFrameMetadataKey::MAX_LUMINANCE,
-                        PerFrameMetadataKey::MIN_LUMINANCE,
-                })));
-    }
-};
-
-template <typename Display>
-struct Cta861_3_PerFrameMetadataSupportVariant {
-    static constexpr int PER_FRAME_METADATA_KEYS = HdrMetadata::Type::CTA861_3;
-    static void setupComposerCallExpectations(DisplayTransactionTest* test) {
-        EXPECT_CALL(*test->mComposer, getPerFrameMetadataKeys(Display::HWC_DISPLAY_ID))
-                .WillOnce(Return(std::vector<PerFrameMetadataKey>({
-                        PerFrameMetadataKey::MAX_CONTENT_LIGHT_LEVEL,
-                        PerFrameMetadataKey::MAX_FRAME_AVERAGE_LIGHT_LEVEL,
-                })));
-    }
-};
-
-template <typename Display>
-struct Hdr10_Plus_PerFrameMetadataSupportVariant {
-    static constexpr int PER_FRAME_METADATA_KEYS = HdrMetadata::Type::HDR10PLUS;
-    static void setupComposerCallExpectations(DisplayTransactionTest* test) {
-        EXPECT_CALL(*test->mComposer, getPerFrameMetadataKeys(Display::HWC_DISPLAY_ID))
-                .WillOnce(Return(std::vector<PerFrameMetadataKey>({
-                        PerFrameMetadataKey::HDR10_PLUS_SEI,
-                })));
-    }
-};
-/* ------------------------------------------------------------------------
- * Typical display configurations to test
- */
-
-template <typename DisplayPolicy, typename WideColorSupportPolicy, typename HdrSupportPolicy,
-          typename PerFrameMetadataSupportPolicy>
-struct Case {
-    using Display = DisplayPolicy;
-    using WideColorSupport = WideColorSupportPolicy;
-    using HdrSupport = HdrSupportPolicy;
-    using PerFrameMetadataSupport = PerFrameMetadataSupportPolicy;
-};
-
-using SimplePrimaryDisplayCase =
-        Case<PrimaryDisplayVariant, WideColorNotSupportedVariant<PrimaryDisplayVariant>,
-             HdrNotSupportedVariant<PrimaryDisplayVariant>,
-             NoPerFrameMetadataSupportVariant<PrimaryDisplayVariant>>;
-using SimpleExternalDisplayCase =
-        Case<ExternalDisplayVariant, WideColorNotSupportedVariant<ExternalDisplayVariant>,
-             HdrNotSupportedVariant<ExternalDisplayVariant>,
-             NoPerFrameMetadataSupportVariant<ExternalDisplayVariant>>;
-using SimpleTertiaryDisplayCase =
-        Case<TertiaryDisplayVariant, WideColorNotSupportedVariant<TertiaryDisplayVariant>,
-             HdrNotSupportedVariant<TertiaryDisplayVariant>,
-             NoPerFrameMetadataSupportVariant<TertiaryDisplayVariant>>;
-using NonHwcVirtualDisplayCase =
-        Case<NonHwcVirtualDisplayVariant<1024, 768, Secure::FALSE>,
-             WideColorSupportNotConfiguredVariant, NonHwcDisplayHdrSupportVariant,
-             NonHwcPerFrameMetadataSupportVariant>;
-using SimpleHwcVirtualDisplayVariant = HwcVirtualDisplayVariant<1024, 768, Secure::TRUE>;
-using HwcVirtualDisplayCase =
-        Case<SimpleHwcVirtualDisplayVariant, WideColorSupportNotConfiguredVariant,
-             HdrNotSupportedVariant<SimpleHwcVirtualDisplayVariant>,
-             NoPerFrameMetadataSupportVariant<SimpleHwcVirtualDisplayVariant>>;
-using WideColorP3ColorimetricDisplayCase =
-        Case<PrimaryDisplayVariant, WideColorP3ColorimetricSupportedVariant<PrimaryDisplayVariant>,
-             HdrNotSupportedVariant<PrimaryDisplayVariant>,
-             NoPerFrameMetadataSupportVariant<PrimaryDisplayVariant>>;
-using Hdr10PlusDisplayCase =
-        Case<PrimaryDisplayVariant, WideColorNotSupportedVariant<PrimaryDisplayVariant>,
-             Hdr10SupportedVariant<PrimaryDisplayVariant>,
-             Hdr10_Plus_PerFrameMetadataSupportVariant<PrimaryDisplayVariant>>;
-using Hdr10DisplayCase =
-        Case<PrimaryDisplayVariant, WideColorNotSupportedVariant<PrimaryDisplayVariant>,
-             Hdr10SupportedVariant<PrimaryDisplayVariant>,
-             NoPerFrameMetadataSupportVariant<PrimaryDisplayVariant>>;
-using HdrHlgDisplayCase =
-        Case<PrimaryDisplayVariant, WideColorNotSupportedVariant<PrimaryDisplayVariant>,
-             HdrHlgSupportedVariant<PrimaryDisplayVariant>,
-             NoPerFrameMetadataSupportVariant<PrimaryDisplayVariant>>;
-using HdrDolbyVisionDisplayCase =
-        Case<PrimaryDisplayVariant, WideColorNotSupportedVariant<PrimaryDisplayVariant>,
-             HdrDolbyVisionSupportedVariant<PrimaryDisplayVariant>,
-             NoPerFrameMetadataSupportVariant<PrimaryDisplayVariant>>;
-using HdrSmpte2086DisplayCase =
-        Case<PrimaryDisplayVariant, WideColorNotSupportedVariant<PrimaryDisplayVariant>,
-             HdrNotSupportedVariant<PrimaryDisplayVariant>,
-             Smpte2086PerFrameMetadataSupportVariant<PrimaryDisplayVariant>>;
-using HdrCta861_3_DisplayCase =
-        Case<PrimaryDisplayVariant, WideColorNotSupportedVariant<PrimaryDisplayVariant>,
-             HdrNotSupportedVariant<PrimaryDisplayVariant>,
-             Cta861_3_PerFrameMetadataSupportVariant<PrimaryDisplayVariant>>;
-
-/* ------------------------------------------------------------------------
- *
- * SurfaceFlinger::onHotplugReceived
- */
-
-TEST_F(DisplayTransactionTest, hotplugEnqueuesEventsForDisplayTransaction) {
-    constexpr int currentSequenceId = 123;
-    constexpr HWDisplayId hwcDisplayId1 = 456;
-    constexpr HWDisplayId hwcDisplayId2 = 654;
-
-    // --------------------------------------------------------------------
-    // Preconditions
-
-    // Set the current sequence id for accepted events
-    mFlinger.mutableComposerSequenceId() = currentSequenceId;
-
-    // Set the main thread id so that the current thread does not appear to be
-    // the main thread.
-    mFlinger.mutableMainThreadId() = std::thread::id();
-
-    // --------------------------------------------------------------------
-    // Call Expectations
-
-    // We expect invalidate() to be invoked once to trigger display transaction
-    // processing.
-    EXPECT_CALL(*mMessageQueue, invalidate()).Times(1);
-
-    // --------------------------------------------------------------------
-    // Invocation
-
-    // Simulate two hotplug events (a connect and a disconnect)
-    mFlinger.onHotplugReceived(currentSequenceId, hwcDisplayId1, Connection::CONNECTED);
-    mFlinger.onHotplugReceived(currentSequenceId, hwcDisplayId2, Connection::DISCONNECTED);
-
-    // --------------------------------------------------------------------
-    // Postconditions
-
-    // The display transaction needed flag should be set.
-    EXPECT_TRUE(hasTransactionFlagSet(eDisplayTransactionNeeded));
-
-    // All events should be in the pending event queue.
-    const auto& pendingEvents = mFlinger.mutablePendingHotplugEvents();
-    ASSERT_EQ(2u, pendingEvents.size());
-    EXPECT_EQ(hwcDisplayId1, pendingEvents[0].hwcDisplayId);
-    EXPECT_EQ(Connection::CONNECTED, pendingEvents[0].connection);
-    EXPECT_EQ(hwcDisplayId2, pendingEvents[1].hwcDisplayId);
-    EXPECT_EQ(Connection::DISCONNECTED, pendingEvents[1].connection);
-}
-
-TEST_F(DisplayTransactionTest, hotplugDiscardsUnexpectedEvents) {
-    constexpr int currentSequenceId = 123;
-    constexpr int otherSequenceId = 321;
-    constexpr HWDisplayId displayId = 456;
-
-    // --------------------------------------------------------------------
-    // Preconditions
-
-    // Set the current sequence id for accepted events
-    mFlinger.mutableComposerSequenceId() = currentSequenceId;
-
-    // Set the main thread id so that the current thread does not appear to be
-    // the main thread.
-    mFlinger.mutableMainThreadId() = std::thread::id();
-
-    // --------------------------------------------------------------------
-    // Call Expectations
-
-    // We do not expect any calls to invalidate().
-    EXPECT_CALL(*mMessageQueue, invalidate()).Times(0);
-
-    // --------------------------------------------------------------------
-    // Invocation
-
-    // Call with an unexpected sequence id
-    mFlinger.onHotplugReceived(otherSequenceId, displayId, Connection::INVALID);
-
-    // --------------------------------------------------------------------
-    // Postconditions
-
-    // The display transaction needed flag should not be set
-    EXPECT_FALSE(hasTransactionFlagSet(eDisplayTransactionNeeded));
-
-    // There should be no pending events
-    EXPECT_TRUE(mFlinger.mutablePendingHotplugEvents().empty());
-}
-
-TEST_F(DisplayTransactionTest, hotplugProcessesEnqueuedEventsIfCalledOnMainThread) {
-    constexpr int currentSequenceId = 123;
-    constexpr HWDisplayId displayId1 = 456;
-
-    // --------------------------------------------------------------------
-    // Note:
-    // --------------------------------------------------------------------
-    // This test case is a bit tricky. We want to verify that
-    // onHotplugReceived() calls processDisplayHotplugEventsLocked(), but we
-    // don't really want to provide coverage for everything the later function
-    // does as there are specific tests for it.
-    // --------------------------------------------------------------------
-
-    // --------------------------------------------------------------------
-    // Preconditions
-
-    // Set the current sequence id for accepted events
-    mFlinger.mutableComposerSequenceId() = currentSequenceId;
-
-    // Set the main thread id so that the current thread does appear to be the
-    // main thread.
-    mFlinger.mutableMainThreadId() = std::this_thread::get_id();
-
-    // --------------------------------------------------------------------
-    // Call Expectations
-
-    // We expect invalidate() to be invoked once to trigger display transaction
-    // processing.
-    EXPECT_CALL(*mMessageQueue, invalidate()).Times(1);
-
-    // --------------------------------------------------------------------
-    // Invocation
-
-    // Simulate a disconnect on a display id that is not connected. This should
-    // be enqueued by onHotplugReceived(), and dequeued by
-    // processDisplayHotplugEventsLocked(), but then ignored as invalid.
-    mFlinger.onHotplugReceived(currentSequenceId, displayId1, Connection::DISCONNECTED);
-
-    // --------------------------------------------------------------------
-    // Postconditions
-
-    // The display transaction needed flag should be set.
-    EXPECT_TRUE(hasTransactionFlagSet(eDisplayTransactionNeeded));
-
-    // There should be no event queued on return, as it should have been
-    // processed.
-    EXPECT_TRUE(mFlinger.mutablePendingHotplugEvents().empty());
-}
-
-/* ------------------------------------------------------------------------
- * SurfaceFlinger::createDisplay
- */
-
-TEST_F(DisplayTransactionTest, createDisplaySetsCurrentStateForNonsecureDisplay) {
-    const String8 name("virtual.test");
-
-    // --------------------------------------------------------------------
-    // Call Expectations
-
-    // The call should notify the interceptor that a display was created.
-    EXPECT_CALL(*mSurfaceInterceptor, saveDisplayCreation(_)).Times(1);
-
-    // --------------------------------------------------------------------
-    // Invocation
-
-    sp<IBinder> displayToken = mFlinger.createDisplay(name, false);
-
-    // --------------------------------------------------------------------
-    // Postconditions
-
-    // The display should have been added to the current state
-    ASSERT_TRUE(hasCurrentDisplayState(displayToken));
-    const auto& display = getCurrentDisplayState(displayToken);
-    EXPECT_TRUE(display.isVirtual());
-    EXPECT_FALSE(display.isSecure);
-    EXPECT_EQ(name.string(), display.displayName);
-
-    // --------------------------------------------------------------------
-    // Cleanup conditions
-
-    // Destroying the display invalidates the display state.
-    EXPECT_CALL(*mMessageQueue, invalidate()).Times(1);
-}
-
-TEST_F(DisplayTransactionTest, createDisplaySetsCurrentStateForSecureDisplay) {
-    const String8 name("virtual.test");
-
-    // --------------------------------------------------------------------
-    // Call Expectations
-
-    // The call should notify the interceptor that a display was created.
-    EXPECT_CALL(*mSurfaceInterceptor, saveDisplayCreation(_)).Times(1);
-
-    // --------------------------------------------------------------------
-    // Invocation
-    int64_t oldId = IPCThreadState::self()->clearCallingIdentity();
-    // Set the calling identity to graphics so captureDisplay with secure is allowed.
-    IPCThreadState::self()->restoreCallingIdentity(static_cast<int64_t>(AID_GRAPHICS) << 32 |
-                                                   AID_GRAPHICS);
-    sp<IBinder> displayToken = mFlinger.createDisplay(name, true);
-    IPCThreadState::self()->restoreCallingIdentity(oldId);
-
-    // --------------------------------------------------------------------
-    // Postconditions
-
-    // The display should have been added to the current state
-    ASSERT_TRUE(hasCurrentDisplayState(displayToken));
-    const auto& display = getCurrentDisplayState(displayToken);
-    EXPECT_TRUE(display.isVirtual());
-    EXPECT_TRUE(display.isSecure);
-    EXPECT_EQ(name.string(), display.displayName);
-
-    // --------------------------------------------------------------------
-    // Cleanup conditions
-
-    // Destroying the display invalidates the display state.
-    EXPECT_CALL(*mMessageQueue, invalidate()).Times(1);
-}
-
-/* ------------------------------------------------------------------------
- * SurfaceFlinger::destroyDisplay
- */
-
-TEST_F(DisplayTransactionTest, destroyDisplayClearsCurrentStateForDisplay) {
-    using Case = NonHwcVirtualDisplayCase;
-
-    // --------------------------------------------------------------------
-    // Preconditions
-
-    // A virtual display exists
-    auto existing = Case::Display::makeFakeExistingDisplayInjector(this);
-    existing.inject();
-
-    // --------------------------------------------------------------------
-    // Call Expectations
-
-    // The call should notify the interceptor that a display was created.
-    EXPECT_CALL(*mSurfaceInterceptor, saveDisplayDeletion(_)).Times(1);
-
-    // Destroying the display invalidates the display state.
-    EXPECT_CALL(*mMessageQueue, invalidate()).Times(1);
-
-    // --------------------------------------------------------------------
-    // Invocation
-
-    mFlinger.destroyDisplay(existing.token());
-
-    // --------------------------------------------------------------------
-    // Postconditions
-
-    // The display should have been removed from the current state
-    EXPECT_FALSE(hasCurrentDisplayState(existing.token()));
-
-    // Ths display should still exist in the drawing state
-    EXPECT_TRUE(hasDrawingDisplayState(existing.token()));
-
-    // The display transaction needed flasg should be set
-    EXPECT_TRUE(hasTransactionFlagSet(eDisplayTransactionNeeded));
-}
-
-TEST_F(DisplayTransactionTest, destroyDisplayHandlesUnknownDisplay) {
-    // --------------------------------------------------------------------
-    // Preconditions
-
-    sp<BBinder> displayToken = new BBinder();
-
-    // --------------------------------------------------------------------
-    // Invocation
-
-    mFlinger.destroyDisplay(displayToken);
-}
-
-/* ------------------------------------------------------------------------
- * SurfaceFlinger::notifyPowerBoost
- */
-
-TEST_F(DisplayTransactionTest, notifyPowerBoostNotifiesTouchEvent) {
-    mFlinger.scheduler()->replaceTouchTimer(100);
-    std::this_thread::sleep_for(10ms);                  // wait for callback to be triggered
-    EXPECT_TRUE(mFlinger.scheduler()->isTouchActive()); // Starting timer activates touch
-
-    std::this_thread::sleep_for(110ms); // wait for reset touch timer to expire and trigger callback
-    EXPECT_FALSE(mFlinger.scheduler()->isTouchActive());
-
-    EXPECT_EQ(NO_ERROR, mFlinger.notifyPowerBoost(static_cast<int32_t>(Boost::CAMERA_SHOT)));
-    std::this_thread::sleep_for(10ms); // wait for callback to maybe be triggered
-    EXPECT_FALSE(mFlinger.scheduler()->isTouchActive());
-
-    std::this_thread::sleep_for(110ms); // wait for reset touch timer to expire and trigger callback
-    EXPECT_FALSE(mFlinger.scheduler()->isTouchActive());
-
-    EXPECT_EQ(NO_ERROR, mFlinger.notifyPowerBoost(static_cast<int32_t>(Boost::INTERACTION)));
-    std::this_thread::sleep_for(10ms); // wait for callback to be triggered.
-    EXPECT_TRUE(mFlinger.scheduler()->isTouchActive());
-}
-
-/* ------------------------------------------------------------------------
- * DisplayDevice::GetBestColorMode
- */
-class GetBestColorModeTest : public DisplayTransactionTest {
-public:
-    void setHasWideColorGamut(bool hasWideColorGamut) { mHasWideColorGamut = hasWideColorGamut; }
-
-    void addHwcColorModesMapping(ui::ColorMode colorMode,
-                                 std::vector<ui::RenderIntent> renderIntents) {
-        mHwcColorModes[colorMode] = renderIntents;
-    }
-
-    void setInputDataspace(ui::Dataspace dataspace) { mInputDataspace = dataspace; }
-
-    void setInputRenderIntent(ui::RenderIntent renderIntent) { mInputRenderIntent = renderIntent; }
-
-    void getBestColorMode() {
-        auto displayDevice =
-                injectDefaultInternalDisplay([this](FakeDisplayDeviceInjector& injector) {
-                    injector.setHwcColorModes(mHwcColorModes);
-                    injector.setHasWideColorGamut(mHasWideColorGamut);
-                    injector.setNativeWindow(mNativeWindow);
-                });
-
-        displayDevice->getCompositionDisplay()
-                ->getDisplayColorProfile()
-                ->getBestColorMode(mInputDataspace, mInputRenderIntent, &mOutDataspace,
-                                   &mOutColorMode, &mOutRenderIntent);
-    }
-
-    ui::Dataspace mOutDataspace;
-    ui::ColorMode mOutColorMode;
-    ui::RenderIntent mOutRenderIntent;
-
-private:
-    ui::Dataspace mInputDataspace;
-    ui::RenderIntent mInputRenderIntent;
-    bool mHasWideColorGamut = false;
-    std::unordered_map<ui::ColorMode, std::vector<ui::RenderIntent>> mHwcColorModes;
-};
-
-TEST_F(GetBestColorModeTest, DataspaceDisplayP3_ColorModeSRGB) {
-    addHwcColorModesMapping(ui::ColorMode::SRGB,
-                            std::vector<ui::RenderIntent>(1, RenderIntent::COLORIMETRIC));
-    setInputDataspace(ui::Dataspace::DISPLAY_P3);
-    setInputRenderIntent(ui::RenderIntent::COLORIMETRIC);
-    setHasWideColorGamut(true);
-
-    getBestColorMode();
-
-    ASSERT_EQ(ui::Dataspace::V0_SRGB, mOutDataspace);
-    ASSERT_EQ(ui::ColorMode::SRGB, mOutColorMode);
-    ASSERT_EQ(ui::RenderIntent::COLORIMETRIC, mOutRenderIntent);
-}
-
-TEST_F(GetBestColorModeTest, DataspaceDisplayP3_ColorModeDisplayP3) {
-    addHwcColorModesMapping(ui::ColorMode::DISPLAY_P3,
-                            std::vector<ui::RenderIntent>(1, RenderIntent::COLORIMETRIC));
-    addHwcColorModesMapping(ui::ColorMode::SRGB,
-                            std::vector<ui::RenderIntent>(1, RenderIntent::COLORIMETRIC));
-    addHwcColorModesMapping(ui::ColorMode::DISPLAY_BT2020,
-                            std::vector<ui::RenderIntent>(1, RenderIntent::COLORIMETRIC));
-    setInputDataspace(ui::Dataspace::DISPLAY_P3);
-    setInputRenderIntent(ui::RenderIntent::COLORIMETRIC);
-    setHasWideColorGamut(true);
-
-    getBestColorMode();
-
-    ASSERT_EQ(ui::Dataspace::DISPLAY_P3, mOutDataspace);
-    ASSERT_EQ(ui::ColorMode::DISPLAY_P3, mOutColorMode);
-    ASSERT_EQ(ui::RenderIntent::COLORIMETRIC, mOutRenderIntent);
-}
-
-TEST_F(GetBestColorModeTest, DataspaceDisplayP3_ColorModeDISPLAY_BT2020) {
-    addHwcColorModesMapping(ui::ColorMode::DISPLAY_BT2020,
-                            std::vector<ui::RenderIntent>(1, RenderIntent::COLORIMETRIC));
-    setInputDataspace(ui::Dataspace::DISPLAY_P3);
-    setInputRenderIntent(ui::RenderIntent::COLORIMETRIC);
-    setHasWideColorGamut(true);
-
-    getBestColorMode();
-
-    ASSERT_EQ(ui::Dataspace::DISPLAY_BT2020, mOutDataspace);
-    ASSERT_EQ(ui::ColorMode::DISPLAY_BT2020, mOutColorMode);
-    ASSERT_EQ(ui::RenderIntent::COLORIMETRIC, mOutRenderIntent);
-}
-
-/* ------------------------------------------------------------------------
- * DisplayDevice::setProjection
- */
-
-class DisplayDeviceSetProjectionTest : public DisplayTransactionTest {
-public:
-    static constexpr int32_t DEFAULT_DISPLAY_WIDTH = 1080;  // arbitrary
-    static constexpr int32_t DEFAULT_DISPLAY_HEIGHT = 1920; // arbitrary
-
-    static constexpr int32_t TRANSFORM_FLAGS_ROT_0 = 0;
-    static constexpr int32_t TRANSFORM_FLAGS_ROT_90 = HAL_TRANSFORM_ROT_90;
-    static constexpr int32_t TRANSFORM_FLAGS_ROT_180 = HAL_TRANSFORM_FLIP_H | HAL_TRANSFORM_FLIP_V;
-    static constexpr int32_t TRANSFORM_FLAGS_ROT_270 =
-            HAL_TRANSFORM_FLIP_H | HAL_TRANSFORM_FLIP_V | HAL_TRANSFORM_ROT_90;
-
-    DisplayDeviceSetProjectionTest(ui::Size flingerDisplaySize, ui::Size hardwareDisplaySize,
-                                   ui::Rotation physicalOrientation)
-          : mFlingerDisplaySize(flingerDisplaySize),
-            mHardwareDisplaySize(hardwareDisplaySize),
-            mPhysicalOrientation(physicalOrientation),
-            mDisplayDevice(createDisplayDevice()) {}
-
-    sp<DisplayDevice> createDisplayDevice() {
-        return injectDefaultInternalDisplay([this](FakeDisplayDeviceInjector& injector) {
-            injector.setPhysicalOrientation(mPhysicalOrientation);
-        });
-    }
-
-    ui::Size swapWH(const ui::Size size) const { return ui::Size(size.height, size.width); }
-
-    void setProjectionForRotation0() {
-        // A logical rotation of 0 uses the SurfaceFlinger display size
-        mDisplayDevice->setProjection(ui::ROTATION_0, Rect(mFlingerDisplaySize),
-                                      Rect(mFlingerDisplaySize));
-    }
-
-    void setProjectionForRotation90() {
-        // A logical rotation of 90 uses the SurfaceFlinger display size with
-        // the width/height swapped.
-        mDisplayDevice->setProjection(ui::ROTATION_90, Rect(swapWH(mFlingerDisplaySize)),
-                                      Rect(swapWH(mFlingerDisplaySize)));
-    }
-
-    void setProjectionForRotation180() {
-        // A logical rotation of 180 uses the SurfaceFlinger display size
-        mDisplayDevice->setProjection(ui::ROTATION_180, Rect(mFlingerDisplaySize),
-                                      Rect(mFlingerDisplaySize));
-    }
-
-    void setProjectionForRotation270() {
-        // A logical rotation of 270 uses the SurfaceFlinger display size with
-        // the width/height swapped.
-        mDisplayDevice->setProjection(ui::ROTATION_270, Rect(swapWH(mFlingerDisplaySize)),
-                                      Rect(swapWH(mFlingerDisplaySize)));
-    }
-
-    void expectStateForHardwareTransform0() {
-        const auto& compositionState = mDisplayDevice->getCompositionDisplay()->getState();
-        EXPECT_EQ(ui::Transform(TRANSFORM_FLAGS_ROT_0, mHardwareDisplaySize.width,
-                                mHardwareDisplaySize.height),
-                  compositionState.transform);
-        EXPECT_EQ(ui::ROTATION_0, compositionState.displaySpace.orientation);
-        EXPECT_EQ(Rect(mHardwareDisplaySize), compositionState.displaySpace.content);
-        EXPECT_EQ(Rect(mHardwareDisplaySize), compositionState.orientedDisplaySpace.content);
-        EXPECT_EQ(Rect(mHardwareDisplaySize), compositionState.layerStackSpace.content);
-        EXPECT_EQ(false, compositionState.needsFiltering);
-    }
-
-    void expectStateForHardwareTransform90() {
-        const auto& compositionState = mDisplayDevice->getCompositionDisplay()->getState();
-        EXPECT_EQ(ui::Transform(TRANSFORM_FLAGS_ROT_90, mHardwareDisplaySize.width,
-                                mHardwareDisplaySize.height),
-                  compositionState.transform);
-        EXPECT_EQ(ui::ROTATION_90, compositionState.displaySpace.orientation);
-        EXPECT_EQ(Rect(mHardwareDisplaySize), compositionState.displaySpace.content);
-        // For 90, the orientedDisplaySpaceRect and layerStackSpaceRect have the hardware display
-        // size width and height swapped
-        EXPECT_EQ(Rect(swapWH(mHardwareDisplaySize)),
-                  compositionState.orientedDisplaySpace.content);
-        EXPECT_EQ(Rect(swapWH(mHardwareDisplaySize)), compositionState.layerStackSpace.content);
-        EXPECT_EQ(false, compositionState.needsFiltering);
-    }
-
-    void expectStateForHardwareTransform180() {
-        const auto& compositionState = mDisplayDevice->getCompositionDisplay()->getState();
-        EXPECT_EQ(ui::Transform(TRANSFORM_FLAGS_ROT_180, mHardwareDisplaySize.width,
-                                mHardwareDisplaySize.height),
-                  compositionState.transform);
-        EXPECT_EQ(ui::ROTATION_180, compositionState.displaySpace.orientation);
-        EXPECT_EQ(Rect(mHardwareDisplaySize), compositionState.orientedDisplaySpace.content);
-        EXPECT_EQ(Rect(mHardwareDisplaySize), compositionState.layerStackSpace.content);
-        EXPECT_EQ(false, compositionState.needsFiltering);
-    }
-
-    void expectStateForHardwareTransform270() {
-        const auto& compositionState = mDisplayDevice->getCompositionDisplay()->getState();
-        EXPECT_EQ(ui::Transform(TRANSFORM_FLAGS_ROT_270, mHardwareDisplaySize.width,
-                                mHardwareDisplaySize.height),
-                  compositionState.transform);
-        EXPECT_EQ(ui::ROTATION_270, compositionState.displaySpace.orientation);
-        EXPECT_EQ(Rect(mHardwareDisplaySize), compositionState.displaySpace.content);
-        // For 270, the orientedDisplaySpaceRect and layerStackSpaceRect have the hardware display
-        // size width and height swapped
-        EXPECT_EQ(Rect(swapWH(mHardwareDisplaySize)),
-                  compositionState.orientedDisplaySpace.content);
-        EXPECT_EQ(Rect(swapWH(mHardwareDisplaySize)), compositionState.layerStackSpace.content);
-        EXPECT_EQ(false, compositionState.needsFiltering);
-    }
-
-    const ui::Size mFlingerDisplaySize;
-    const ui::Size mHardwareDisplaySize;
-    const ui::Rotation mPhysicalOrientation;
-    const sp<DisplayDevice> mDisplayDevice;
-};
-
-struct DisplayDeviceSetProjectionTest_Installed0 : public DisplayDeviceSetProjectionTest {
-    DisplayDeviceSetProjectionTest_Installed0()
-          : DisplayDeviceSetProjectionTest(ui::Size(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
-                                           ui::Size(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
-                                           ui::ROTATION_0) {}
-};
-
-TEST_F(DisplayDeviceSetProjectionTest_Installed0, checkWith0OutputRotation) {
-    setProjectionForRotation0();
-    expectStateForHardwareTransform0();
-}
-
-TEST_F(DisplayDeviceSetProjectionTest_Installed0, checkWith90OutputRotation) {
-    setProjectionForRotation90();
-    expectStateForHardwareTransform90();
-}
-
-TEST_F(DisplayDeviceSetProjectionTest_Installed0, checkWith180OutputRotation) {
-    setProjectionForRotation180();
-    expectStateForHardwareTransform180();
-}
-
-TEST_F(DisplayDeviceSetProjectionTest_Installed0, checkWith270OutputRotation) {
-    setProjectionForRotation270();
-    expectStateForHardwareTransform270();
-}
-
-struct DisplayDeviceSetProjectionTest_Installed90 : public DisplayDeviceSetProjectionTest {
-    DisplayDeviceSetProjectionTest_Installed90()
-          : DisplayDeviceSetProjectionTest(ui::Size(DEFAULT_DISPLAY_HEIGHT, DEFAULT_DISPLAY_WIDTH),
-                                           ui::Size(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
-                                           ui::ROTATION_90) {}
-};
-
-TEST_F(DisplayDeviceSetProjectionTest_Installed90, checkWith0OutputRotation) {
-    setProjectionForRotation0();
-    expectStateForHardwareTransform90();
-}
-
-TEST_F(DisplayDeviceSetProjectionTest_Installed90, checkWith90OutputRotation) {
-    setProjectionForRotation90();
-    expectStateForHardwareTransform180();
-}
-
-TEST_F(DisplayDeviceSetProjectionTest_Installed90, checkWith180OutputRotation) {
-    setProjectionForRotation180();
-    expectStateForHardwareTransform270();
-}
-
-TEST_F(DisplayDeviceSetProjectionTest_Installed90, checkWith270OutputRotation) {
-    setProjectionForRotation270();
-    expectStateForHardwareTransform0();
-}
-
-struct DisplayDeviceSetProjectionTest_Installed180 : public DisplayDeviceSetProjectionTest {
-    DisplayDeviceSetProjectionTest_Installed180()
-          : DisplayDeviceSetProjectionTest(ui::Size(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
-                                           ui::Size(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
-                                           ui::ROTATION_180) {}
-};
-
-TEST_F(DisplayDeviceSetProjectionTest_Installed180, checkWith0OutputRotation) {
-    setProjectionForRotation0();
-    expectStateForHardwareTransform180();
-}
-
-TEST_F(DisplayDeviceSetProjectionTest_Installed180, checkWith90OutputRotation) {
-    setProjectionForRotation90();
-    expectStateForHardwareTransform270();
-}
-
-TEST_F(DisplayDeviceSetProjectionTest_Installed180, checkWith180OutputRotation) {
-    setProjectionForRotation180();
-    expectStateForHardwareTransform0();
-}
-
-TEST_F(DisplayDeviceSetProjectionTest_Installed180, checkWith270OutputRotation) {
-    setProjectionForRotation270();
-    expectStateForHardwareTransform90();
-}
-
-struct DisplayDeviceSetProjectionTest_Installed270 : public DisplayDeviceSetProjectionTest {
-    DisplayDeviceSetProjectionTest_Installed270()
-          : DisplayDeviceSetProjectionTest(ui::Size(DEFAULT_DISPLAY_HEIGHT, DEFAULT_DISPLAY_WIDTH),
-                                           ui::Size(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
-                                           ui::ROTATION_270) {}
-};
-
-TEST_F(DisplayDeviceSetProjectionTest_Installed270, checkWith0OutputRotation) {
-    setProjectionForRotation0();
-    expectStateForHardwareTransform270();
-}
-
-TEST_F(DisplayDeviceSetProjectionTest_Installed270, checkWith90OutputRotation) {
-    setProjectionForRotation90();
-    expectStateForHardwareTransform0();
-}
-
-TEST_F(DisplayDeviceSetProjectionTest_Installed270, checkWith180OutputRotation) {
-    setProjectionForRotation180();
-    expectStateForHardwareTransform90();
-}
-
-TEST_F(DisplayDeviceSetProjectionTest_Installed270, checkWith270OutputRotation) {
-    setProjectionForRotation270();
-    expectStateForHardwareTransform180();
-}
-
-/* ------------------------------------------------------------------------
- * SurfaceFlinger::getDisplayNativePrimaries
- */
-
-class GetDisplayNativePrimaries : public DisplayTransactionTest {
-public:
-    GetDisplayNativePrimaries();
-    void populateDummyDisplayNativePrimaries(ui::DisplayPrimaries& primaries);
-    void checkDummyDisplayNativePrimaries(const ui::DisplayPrimaries& primaries);
-
-private:
-    static constexpr float mStartingTestValue = 1.0f;
-};
-
-GetDisplayNativePrimaries::GetDisplayNativePrimaries() {
-    SimplePrimaryDisplayCase::Display::injectHwcDisplay(this);
-    injectFakeNativeWindowSurfaceFactory();
-}
-
-void GetDisplayNativePrimaries::populateDummyDisplayNativePrimaries(
-        ui::DisplayPrimaries& primaries) {
-    float startingVal = mStartingTestValue;
-    primaries.red.X = startingVal++;
-    primaries.red.Y = startingVal++;
-    primaries.red.Z = startingVal++;
-    primaries.green.X = startingVal++;
-    primaries.green.Y = startingVal++;
-    primaries.green.Z = startingVal++;
-    primaries.blue.X = startingVal++;
-    primaries.blue.Y = startingVal++;
-    primaries.blue.Z = startingVal++;
-    primaries.white.X = startingVal++;
-    primaries.white.Y = startingVal++;
-    primaries.white.Z = startingVal++;
-}
-
-void GetDisplayNativePrimaries::checkDummyDisplayNativePrimaries(
-        const ui::DisplayPrimaries& primaries) {
-    float startingVal = mStartingTestValue;
-    EXPECT_EQ(primaries.red.X, startingVal++);
-    EXPECT_EQ(primaries.red.Y, startingVal++);
-    EXPECT_EQ(primaries.red.Z, startingVal++);
-    EXPECT_EQ(primaries.green.X, startingVal++);
-    EXPECT_EQ(primaries.green.Y, startingVal++);
-    EXPECT_EQ(primaries.green.Z, startingVal++);
-    EXPECT_EQ(primaries.blue.X, startingVal++);
-    EXPECT_EQ(primaries.blue.Y, startingVal++);
-    EXPECT_EQ(primaries.blue.Z, startingVal++);
-    EXPECT_EQ(primaries.white.X, startingVal++);
-    EXPECT_EQ(primaries.white.Y, startingVal++);
-    EXPECT_EQ(primaries.white.Z, startingVal++);
-}
-
-TEST_F(GetDisplayNativePrimaries, nullDisplayToken) {
-    ui::DisplayPrimaries primaries;
-    EXPECT_EQ(BAD_VALUE, mFlinger.getDisplayNativePrimaries(nullptr, primaries));
-}
-
-TEST_F(GetDisplayNativePrimaries, internalDisplayWithPrimariesData) {
-    auto injector = SimplePrimaryDisplayCase::Display::makeFakeExistingDisplayInjector(this);
-    injector.inject();
-    auto internalDisplayToken = injector.token();
-
-    ui::DisplayPrimaries expectedPrimaries;
-    populateDummyDisplayNativePrimaries(expectedPrimaries);
-    mFlinger.setInternalDisplayPrimaries(expectedPrimaries);
-
-    ui::DisplayPrimaries primaries;
-    EXPECT_EQ(NO_ERROR, mFlinger.getDisplayNativePrimaries(internalDisplayToken, primaries));
-
-    checkDummyDisplayNativePrimaries(primaries);
-}
-
-TEST_F(GetDisplayNativePrimaries, notInternalDisplayToken) {
-    sp<BBinder> notInternalDisplayToken = new BBinder();
-
-    ui::DisplayPrimaries primaries;
-    populateDummyDisplayNativePrimaries(primaries);
-    EXPECT_EQ(NAME_NOT_FOUND,
-              mFlinger.getDisplayNativePrimaries(notInternalDisplayToken, primaries));
-
-    // Check primaries argument wasn't modified in case of failure
-    checkDummyDisplayNativePrimaries(primaries);
-}
-
-/* ------------------------------------------------------------------------
- * SurfaceFlinger::setupNewDisplayDeviceInternal
- */
-
-class SetupNewDisplayDeviceInternalTest : public DisplayTransactionTest {
-public:
-    template <typename T>
-    void setupNewDisplayDeviceInternalTest();
-};
-
-template <typename Case>
-void SetupNewDisplayDeviceInternalTest::setupNewDisplayDeviceInternalTest() {
-    const sp<BBinder> displayToken = new BBinder();
-    const sp<compositionengine::mock::DisplaySurface> displaySurface =
-            new compositionengine::mock::DisplaySurface();
-    const sp<mock::GraphicBufferProducer> producer = new mock::GraphicBufferProducer();
-
-    // --------------------------------------------------------------------
-    // Preconditions
-
-    // Wide color displays support is configured appropriately
-    Case::WideColorSupport::injectConfigChange(this);
-
-    // The display is setup with the HWC.
-    Case::Display::injectHwcDisplay(this);
-
-    // SurfaceFlinger will use a test-controlled factory for native window
-    // surfaces.
-    injectFakeNativeWindowSurfaceFactory();
-
-    // A compositionengine::Display has already been created
-    auto compositionDisplay = Case::Display::injectCompositionDisplay(this);
-
-    // --------------------------------------------------------------------
-    // Call Expectations
-
-    // Various native window calls will be made.
-    Case::Display::setupNativeWindowSurfaceCreationCallExpectations(this);
-    Case::Display::setupHwcGetActiveConfigCallExpectations(this);
-    Case::WideColorSupport::setupComposerCallExpectations(this);
-    Case::HdrSupport::setupComposerCallExpectations(this);
-    Case::PerFrameMetadataSupport::setupComposerCallExpectations(this);
-
-    // --------------------------------------------------------------------
-    // Invocation
-
-    DisplayDeviceState state;
-    if (const auto connectionType = Case::Display::CONNECTION_TYPE::value) {
-        const auto displayId = PhysicalDisplayId::tryCast(Case::Display::DISPLAY_ID::get());
-        ASSERT_TRUE(displayId);
-        const auto hwcDisplayId = Case::Display::HWC_DISPLAY_ID_OPT::value;
-        ASSERT_TRUE(hwcDisplayId);
-        state.physical = {.id = *displayId, .type = *connectionType, .hwcDisplayId = *hwcDisplayId};
-    }
-
-    state.isSecure = static_cast<bool>(Case::Display::SECURE);
-
-    auto device = mFlinger.setupNewDisplayDeviceInternal(displayToken, compositionDisplay, state,
-                                                         displaySurface, producer);
-
-    // --------------------------------------------------------------------
-    // Postconditions
-
-    ASSERT_TRUE(device != nullptr);
-    EXPECT_EQ(Case::Display::DISPLAY_ID::get(), device->getId());
-    EXPECT_EQ(Case::Display::CONNECTION_TYPE::value, device->getConnectionType());
-    EXPECT_EQ(static_cast<bool>(Case::Display::VIRTUAL), device->isVirtual());
-    EXPECT_EQ(static_cast<bool>(Case::Display::SECURE), device->isSecure());
-    EXPECT_EQ(static_cast<bool>(Case::Display::PRIMARY), device->isPrimary());
-    EXPECT_EQ(Case::Display::WIDTH, device->getWidth());
-    EXPECT_EQ(Case::Display::HEIGHT, device->getHeight());
-    EXPECT_EQ(Case::WideColorSupport::WIDE_COLOR_SUPPORTED, device->hasWideColorGamut());
-    EXPECT_EQ(Case::HdrSupport::HDR10_PLUS_SUPPORTED, device->hasHDR10PlusSupport());
-    EXPECT_EQ(Case::HdrSupport::HDR10_SUPPORTED, device->hasHDR10Support());
-    EXPECT_EQ(Case::HdrSupport::HDR_HLG_SUPPORTED, device->hasHLGSupport());
-    EXPECT_EQ(Case::HdrSupport::HDR_DOLBY_VISION_SUPPORTED, device->hasDolbyVisionSupport());
-    // Note: This is not Case::Display::HWC_ACTIVE_CONFIG_ID as the ids are
-    // remapped, and the test only ever sets up one config. If there were an error
-    // looking up the remapped index, device->getActiveConfig() would be -1 instead.
-    EXPECT_EQ(0, device->getActiveConfig().value());
-    EXPECT_EQ(Case::PerFrameMetadataSupport::PER_FRAME_METADATA_KEYS,
-              device->getSupportedPerFrameMetadata());
-}
-
-TEST_F(SetupNewDisplayDeviceInternalTest, createSimplePrimaryDisplay) {
-    setupNewDisplayDeviceInternalTest<SimplePrimaryDisplayCase>();
-}
-
-TEST_F(SetupNewDisplayDeviceInternalTest, createSimpleExternalDisplay) {
-    setupNewDisplayDeviceInternalTest<SimpleExternalDisplayCase>();
-}
-
-TEST_F(SetupNewDisplayDeviceInternalTest, createNonHwcVirtualDisplay) {
-    setupNewDisplayDeviceInternalTest<NonHwcVirtualDisplayCase>();
-}
-
-TEST_F(SetupNewDisplayDeviceInternalTest, createHwcVirtualDisplay) {
-    setupNewDisplayDeviceInternalTest<HwcVirtualDisplayCase>();
-}
-
-TEST_F(SetupNewDisplayDeviceInternalTest, createWideColorP3Display) {
-    setupNewDisplayDeviceInternalTest<WideColorP3ColorimetricDisplayCase>();
-}
-
-TEST_F(SetupNewDisplayDeviceInternalTest, createHdr10PlusDisplay) {
-    setupNewDisplayDeviceInternalTest<Hdr10PlusDisplayCase>();
-}
-
-TEST_F(SetupNewDisplayDeviceInternalTest, createHdr10Display) {
-    setupNewDisplayDeviceInternalTest<Hdr10DisplayCase>();
-}
-
-TEST_F(SetupNewDisplayDeviceInternalTest, createHdrHlgDisplay) {
-    setupNewDisplayDeviceInternalTest<HdrHlgDisplayCase>();
-}
-
-TEST_F(SetupNewDisplayDeviceInternalTest, createHdrDolbyVisionDisplay) {
-    setupNewDisplayDeviceInternalTest<HdrDolbyVisionDisplayCase>();
-}
-
-TEST_F(SetupNewDisplayDeviceInternalTest, createHdrSmpte2086DisplayCase) {
-    setupNewDisplayDeviceInternalTest<HdrSmpte2086DisplayCase>();
-}
-
-TEST_F(SetupNewDisplayDeviceInternalTest, createHdrCta816_3_DisplayCase) {
-    setupNewDisplayDeviceInternalTest<HdrCta861_3_DisplayCase>();
-}
-
-/* ------------------------------------------------------------------------
- * SurfaceFlinger::handleTransactionLocked(eDisplayTransactionNeeded)
- */
-
-class HandleTransactionLockedTest : public DisplayTransactionTest {
-public:
-    template <typename Case>
-    void setupCommonPreconditions();
-
-    template <typename Case, bool connected>
-    static void expectHotplugReceived(mock::EventThread*);
-
-    template <typename Case>
-    void setupCommonCallExpectationsForConnectProcessing();
-
-    template <typename Case>
-    void setupCommonCallExpectationsForDisconnectProcessing();
-
-    template <typename Case>
-    void processesHotplugConnectCommon();
-
-    template <typename Case>
-    void ignoresHotplugConnectCommon();
-
-    template <typename Case>
-    void processesHotplugDisconnectCommon();
-
-    template <typename Case>
-    void verifyDisplayIsConnected(const sp<IBinder>& displayToken);
-
-    template <typename Case>
-    void verifyPhysicalDisplayIsConnected();
-
-    void verifyDisplayIsNotConnected(const sp<IBinder>& displayToken);
-};
-
-template <typename Case>
-void HandleTransactionLockedTest::setupCommonPreconditions() {
-    // Wide color displays support is configured appropriately
-    Case::WideColorSupport::injectConfigChange(this);
-
-    // SurfaceFlinger will use a test-controlled factory for BufferQueues
-    injectFakeBufferQueueFactory();
-
-    // SurfaceFlinger will use a test-controlled factory for native window
-    // surfaces.
-    injectFakeNativeWindowSurfaceFactory();
-}
-
-template <typename Case, bool connected>
-void HandleTransactionLockedTest::expectHotplugReceived(mock::EventThread* eventThread) {
-    const auto convert = [](auto physicalDisplayId) {
-        return std::make_optional(DisplayId{physicalDisplayId});
-    };
-
-    EXPECT_CALL(*eventThread,
-                onHotplugReceived(ResultOf(convert, Case::Display::DISPLAY_ID::get()), connected))
-            .Times(1);
-}
-
-template <typename Case>
-void HandleTransactionLockedTest::setupCommonCallExpectationsForConnectProcessing() {
-    Case::Display::setupHwcHotplugCallExpectations(this);
-
-    Case::Display::setupFramebufferConsumerBufferQueueCallExpectations(this);
-    Case::Display::setupFramebufferProducerBufferQueueCallExpectations(this);
-    Case::Display::setupNativeWindowSurfaceCreationCallExpectations(this);
-    Case::Display::setupHwcGetActiveConfigCallExpectations(this);
-
-    Case::WideColorSupport::setupComposerCallExpectations(this);
-    Case::HdrSupport::setupComposerCallExpectations(this);
-    Case::PerFrameMetadataSupport::setupComposerCallExpectations(this);
-
-    EXPECT_CALL(*mSurfaceInterceptor, saveDisplayCreation(_)).Times(1);
-    expectHotplugReceived<Case, true>(mEventThread);
-    expectHotplugReceived<Case, true>(mSFEventThread);
-}
-
-template <typename Case>
-void HandleTransactionLockedTest::setupCommonCallExpectationsForDisconnectProcessing() {
-    EXPECT_CALL(*mSurfaceInterceptor, saveDisplayDeletion(_)).Times(1);
-
-    expectHotplugReceived<Case, false>(mEventThread);
-    expectHotplugReceived<Case, false>(mSFEventThread);
-}
-
-template <typename Case>
-void HandleTransactionLockedTest::verifyDisplayIsConnected(const sp<IBinder>& displayToken) {
-    // The display device should have been set up in the list of displays.
-    ASSERT_TRUE(hasDisplayDevice(displayToken));
-    const auto& device = getDisplayDevice(displayToken);
-    EXPECT_EQ(static_cast<bool>(Case::Display::SECURE), device->isSecure());
-    EXPECT_EQ(static_cast<bool>(Case::Display::PRIMARY), device->isPrimary());
-
-    std::optional<DisplayDeviceState::Physical> expectedPhysical;
-    if (const auto connectionType = Case::Display::CONNECTION_TYPE::value) {
-        const auto displayId = PhysicalDisplayId::tryCast(Case::Display::DISPLAY_ID::get());
-        ASSERT_TRUE(displayId);
-        const auto hwcDisplayId = Case::Display::HWC_DISPLAY_ID_OPT::value;
-        ASSERT_TRUE(hwcDisplayId);
-        expectedPhysical = {.id = *displayId,
-                            .type = *connectionType,
-                            .hwcDisplayId = *hwcDisplayId};
-    }
-
-    // The display should have been set up in the current display state
-    ASSERT_TRUE(hasCurrentDisplayState(displayToken));
-    const auto& current = getCurrentDisplayState(displayToken);
-    EXPECT_EQ(static_cast<bool>(Case::Display::VIRTUAL), current.isVirtual());
-    EXPECT_EQ(expectedPhysical, current.physical);
-
-    // The display should have been set up in the drawing display state
-    ASSERT_TRUE(hasDrawingDisplayState(displayToken));
-    const auto& draw = getDrawingDisplayState(displayToken);
-    EXPECT_EQ(static_cast<bool>(Case::Display::VIRTUAL), draw.isVirtual());
-    EXPECT_EQ(expectedPhysical, draw.physical);
-}
-
-template <typename Case>
-void HandleTransactionLockedTest::verifyPhysicalDisplayIsConnected() {
-    // HWComposer should have an entry for the display
-    EXPECT_TRUE(hasPhysicalHwcDisplay(Case::Display::HWC_DISPLAY_ID));
-
-    // SF should have a display token.
-    const auto displayId = Case::Display::DISPLAY_ID::get();
-    ASSERT_TRUE(PhysicalDisplayId::tryCast(displayId));
-    ASSERT_TRUE(mFlinger.mutablePhysicalDisplayTokens().count(displayId) == 1);
-    auto& displayToken = mFlinger.mutablePhysicalDisplayTokens()[displayId];
-
-    verifyDisplayIsConnected<Case>(displayToken);
-}
-
-void HandleTransactionLockedTest::verifyDisplayIsNotConnected(const sp<IBinder>& displayToken) {
-    EXPECT_FALSE(hasDisplayDevice(displayToken));
-    EXPECT_FALSE(hasCurrentDisplayState(displayToken));
-    EXPECT_FALSE(hasDrawingDisplayState(displayToken));
-}
-
-template <typename Case>
-void HandleTransactionLockedTest::processesHotplugConnectCommon() {
-    // --------------------------------------------------------------------
-    // Preconditions
-
-    setupCommonPreconditions<Case>();
-
-    // A hotplug connect event is enqueued for a display
-    Case::Display::injectPendingHotplugEvent(this, Connection::CONNECTED);
-
-    // --------------------------------------------------------------------
-    // Call Expectations
-
-    setupCommonCallExpectationsForConnectProcessing<Case>();
-
-    // --------------------------------------------------------------------
-    // Invocation
-
-    mFlinger.handleTransactionLocked(eDisplayTransactionNeeded);
-
-    // --------------------------------------------------------------------
-    // Postconditions
-
-    verifyPhysicalDisplayIsConnected<Case>();
-
-    // --------------------------------------------------------------------
-    // Cleanup conditions
-
-    EXPECT_CALL(*mComposer,
-                setVsyncEnabled(Case::Display::HWC_DISPLAY_ID, IComposerClient::Vsync::DISABLE))
-            .WillOnce(Return(Error::NONE));
-    EXPECT_CALL(*mConsumer, consumerDisconnect()).WillOnce(Return(NO_ERROR));
-}
-
-template <typename Case>
-void HandleTransactionLockedTest::ignoresHotplugConnectCommon() {
-    // --------------------------------------------------------------------
-    // Preconditions
-
-    setupCommonPreconditions<Case>();
-
-    // A hotplug connect event is enqueued for a display
-    Case::Display::injectPendingHotplugEvent(this, Connection::CONNECTED);
-
-    // --------------------------------------------------------------------
-    // Invocation
-
-    mFlinger.handleTransactionLocked(eDisplayTransactionNeeded);
-
-    // --------------------------------------------------------------------
-    // Postconditions
-
-    // HWComposer should not have an entry for the display
-    EXPECT_FALSE(hasPhysicalHwcDisplay(Case::Display::HWC_DISPLAY_ID));
-}
-
-template <typename Case>
-void HandleTransactionLockedTest::processesHotplugDisconnectCommon() {
-    // --------------------------------------------------------------------
-    // Preconditions
-
-    setupCommonPreconditions<Case>();
-
-    // A hotplug disconnect event is enqueued for a display
-    Case::Display::injectPendingHotplugEvent(this, Connection::DISCONNECTED);
-
-    // The display is already completely set up.
-    Case::Display::injectHwcDisplay(this);
-    auto existing = Case::Display::makeFakeExistingDisplayInjector(this);
-    existing.inject();
-
-    // --------------------------------------------------------------------
-    // Call Expectations
-
-    EXPECT_CALL(*mComposer, getDisplayIdentificationData(Case::Display::HWC_DISPLAY_ID, _, _))
-            .Times(0);
-
-    setupCommonCallExpectationsForDisconnectProcessing<Case>();
-
-    // --------------------------------------------------------------------
-    // Invocation
-
-    mFlinger.handleTransactionLocked(eDisplayTransactionNeeded);
-
-    // --------------------------------------------------------------------
-    // Postconditions
-
-    // HWComposer should not have an entry for the display
-    EXPECT_FALSE(hasPhysicalHwcDisplay(Case::Display::HWC_DISPLAY_ID));
-
-    // SF should not have a display token.
-    const auto displayId = Case::Display::DISPLAY_ID::get();
-    ASSERT_TRUE(PhysicalDisplayId::tryCast(displayId));
-    ASSERT_TRUE(mFlinger.mutablePhysicalDisplayTokens().count(displayId) == 0);
-
-    // The existing token should have been removed
-    verifyDisplayIsNotConnected(existing.token());
-}
-
-TEST_F(HandleTransactionLockedTest, processesHotplugConnectPrimaryDisplay) {
-    processesHotplugConnectCommon<SimplePrimaryDisplayCase>();
-}
-
-TEST_F(HandleTransactionLockedTest,
-       processesHotplugConnectPrimaryDisplayWithExternalAlreadyConnected) {
-    // Inject an external display.
-    ExternalDisplayVariant::injectHwcDisplay(this);
-
-    processesHotplugConnectCommon<SimplePrimaryDisplayCase>();
-}
-
-TEST_F(HandleTransactionLockedTest, processesHotplugConnectExternalDisplay) {
-    // Inject a primary display.
-    PrimaryDisplayVariant::injectHwcDisplay(this);
-
-    processesHotplugConnectCommon<SimpleExternalDisplayCase>();
-}
-
-TEST_F(HandleTransactionLockedTest, ignoresHotplugConnectIfPrimaryAndExternalAlreadyConnected) {
-    // Inject both a primary and external display.
-    PrimaryDisplayVariant::injectHwcDisplay(this);
-    ExternalDisplayVariant::injectHwcDisplay(this);
-
-    // TODO: This is an unnecessary call.
-    EXPECT_CALL(*mComposer,
-                getDisplayIdentificationData(TertiaryDisplayVariant::HWC_DISPLAY_ID, _, _))
-            .WillOnce(DoAll(SetArgPointee<1>(TertiaryDisplay::PORT),
-                            SetArgPointee<2>(TertiaryDisplay::GET_IDENTIFICATION_DATA()),
-                            Return(Error::NONE)));
-
-    ignoresHotplugConnectCommon<SimpleTertiaryDisplayCase>();
-}
-
-TEST_F(HandleTransactionLockedTest, processesHotplugDisconnectPrimaryDisplay) {
-    processesHotplugDisconnectCommon<SimplePrimaryDisplayCase>();
-}
-
-TEST_F(HandleTransactionLockedTest, processesHotplugDisconnectExternalDisplay) {
-    processesHotplugDisconnectCommon<SimpleExternalDisplayCase>();
-}
-
-TEST_F(HandleTransactionLockedTest, processesHotplugConnectThenDisconnectPrimary) {
-    using Case = SimplePrimaryDisplayCase;
-
-    // --------------------------------------------------------------------
-    // Preconditions
-
-    setupCommonPreconditions<Case>();
-
-    // A hotplug connect event is enqueued for a display
-    Case::Display::injectPendingHotplugEvent(this, Connection::CONNECTED);
-    // A hotplug disconnect event is also enqueued for the same display
-    Case::Display::injectPendingHotplugEvent(this, Connection::DISCONNECTED);
-
-    // --------------------------------------------------------------------
-    // Call Expectations
-
-    setupCommonCallExpectationsForConnectProcessing<Case>();
-    setupCommonCallExpectationsForDisconnectProcessing<Case>();
-
-    EXPECT_CALL(*mComposer,
-                setVsyncEnabled(Case::Display::HWC_DISPLAY_ID, IComposerClient::Vsync::DISABLE))
-            .WillOnce(Return(Error::NONE));
-    EXPECT_CALL(*mConsumer, consumerDisconnect()).WillOnce(Return(NO_ERROR));
-
-    // --------------------------------------------------------------------
-    // Invocation
-
-    mFlinger.handleTransactionLocked(eDisplayTransactionNeeded);
-
-    // --------------------------------------------------------------------
-    // Postconditions
-
-    // HWComposer should not have an entry for the display
-    EXPECT_FALSE(hasPhysicalHwcDisplay(Case::Display::HWC_DISPLAY_ID));
-
-    // SF should not have a display token.
-    const auto displayId = Case::Display::DISPLAY_ID::get();
-    ASSERT_TRUE(PhysicalDisplayId::tryCast(displayId));
-    ASSERT_TRUE(mFlinger.mutablePhysicalDisplayTokens().count(displayId) == 0);
-}
-
-TEST_F(HandleTransactionLockedTest, processesHotplugDisconnectThenConnectPrimary) {
-    using Case = SimplePrimaryDisplayCase;
-
-    // --------------------------------------------------------------------
-    // Preconditions
-
-    setupCommonPreconditions<Case>();
-
-    // The display is already completely set up.
-    Case::Display::injectHwcDisplay(this);
-    auto existing = Case::Display::makeFakeExistingDisplayInjector(this);
-    existing.inject();
-
-    // A hotplug disconnect event is enqueued for a display
-    Case::Display::injectPendingHotplugEvent(this, Connection::DISCONNECTED);
-    // A hotplug connect event is also enqueued for the same display
-    Case::Display::injectPendingHotplugEvent(this, Connection::CONNECTED);
-
-    // --------------------------------------------------------------------
-    // Call Expectations
-
-    setupCommonCallExpectationsForConnectProcessing<Case>();
-    setupCommonCallExpectationsForDisconnectProcessing<Case>();
-
-    // --------------------------------------------------------------------
-    // Invocation
-
-    mFlinger.handleTransactionLocked(eDisplayTransactionNeeded);
-
-    // --------------------------------------------------------------------
-    // Postconditions
-
-    // The existing token should have been removed
-    verifyDisplayIsNotConnected(existing.token());
-    const auto displayId = Case::Display::DISPLAY_ID::get();
-    ASSERT_TRUE(PhysicalDisplayId::tryCast(displayId));
-    ASSERT_TRUE(mFlinger.mutablePhysicalDisplayTokens().count(displayId) == 1);
-    EXPECT_NE(existing.token(), mFlinger.mutablePhysicalDisplayTokens()[displayId]);
-
-    // A new display should be connected in its place
-
-    verifyPhysicalDisplayIsConnected<Case>();
-
-    // --------------------------------------------------------------------
-    // Cleanup conditions
-
-    EXPECT_CALL(*mComposer,
-                setVsyncEnabled(Case::Display::HWC_DISPLAY_ID, IComposerClient::Vsync::DISABLE))
-            .WillOnce(Return(Error::NONE));
-    EXPECT_CALL(*mConsumer, consumerDisconnect()).WillOnce(Return(NO_ERROR));
-}
-
-TEST_F(HandleTransactionLockedTest, processesVirtualDisplayAdded) {
-    using Case = HwcVirtualDisplayCase;
-
-    // --------------------------------------------------------------------
-    // Preconditions
-
-    // The HWC supports at least one virtual display
-    injectMockComposer(1);
-
-    setupCommonPreconditions<Case>();
-
-    // A virtual display was added to the current state, and it has a
-    // surface(producer)
-    sp<BBinder> displayToken = new BBinder();
-
-    DisplayDeviceState state;
-    state.isSecure = static_cast<bool>(Case::Display::SECURE);
-
-    sp<mock::GraphicBufferProducer> surface{new mock::GraphicBufferProducer()};
-    state.surface = surface;
-    mFlinger.mutableCurrentState().displays.add(displayToken, state);
-
-    // --------------------------------------------------------------------
-    // Call Expectations
-
-    Case::Display::setupFramebufferConsumerBufferQueueCallExpectations(this);
-    Case::Display::setupNativeWindowSurfaceCreationCallExpectations(this);
-
-    EXPECT_CALL(*surface, query(NATIVE_WINDOW_WIDTH, _))
-            .WillRepeatedly(DoAll(SetArgPointee<1>(Case::Display::WIDTH), Return(NO_ERROR)));
-    EXPECT_CALL(*surface, query(NATIVE_WINDOW_HEIGHT, _))
-            .WillRepeatedly(DoAll(SetArgPointee<1>(Case::Display::HEIGHT), Return(NO_ERROR)));
-    EXPECT_CALL(*surface, query(NATIVE_WINDOW_FORMAT, _))
-            .WillRepeatedly(DoAll(SetArgPointee<1>(DEFAULT_VIRTUAL_DISPLAY_SURFACE_FORMAT),
-                                  Return(NO_ERROR)));
-    EXPECT_CALL(*surface, query(NATIVE_WINDOW_CONSUMER_USAGE_BITS, _))
-            .WillRepeatedly(DoAll(SetArgPointee<1>(0), Return(NO_ERROR)));
-
-    EXPECT_CALL(*surface, setAsyncMode(true)).Times(1);
-
-    EXPECT_CALL(*mProducer, connect(_, NATIVE_WINDOW_API_EGL, false, _)).Times(1);
-    EXPECT_CALL(*mProducer, disconnect(_, _)).Times(1);
-
-    Case::Display::setupHwcVirtualDisplayCreationCallExpectations(this);
-    Case::WideColorSupport::setupComposerCallExpectations(this);
-    Case::HdrSupport::setupComposerCallExpectations(this);
-    Case::PerFrameMetadataSupport::setupComposerCallExpectations(this);
-
-    // --------------------------------------------------------------------
-    // Invocation
-
-    mFlinger.handleTransactionLocked(eDisplayTransactionNeeded);
-
-    // --------------------------------------------------------------------
-    // Postconditions
-
-    // The display device should have been set up in the list of displays.
-    verifyDisplayIsConnected<Case>(displayToken);
-
-    // --------------------------------------------------------------------
-    // Cleanup conditions
-
-    EXPECT_CALL(*mComposer, destroyVirtualDisplay(Case::Display::HWC_DISPLAY_ID))
-            .WillOnce(Return(Error::NONE));
-    EXPECT_CALL(*mConsumer, consumerDisconnect()).WillOnce(Return(NO_ERROR));
-
-    // Cleanup
-    mFlinger.mutableCurrentState().displays.removeItem(displayToken);
-    mFlinger.mutableDrawingState().displays.removeItem(displayToken);
-}
-
-TEST_F(HandleTransactionLockedTest, processesVirtualDisplayAddedWithNoSurface) {
-    using Case = HwcVirtualDisplayCase;
-
-    // --------------------------------------------------------------------
-    // Preconditions
-
-    // The HWC supports at least one virtual display
-    injectMockComposer(1);
-
-    setupCommonPreconditions<Case>();
-
-    // A virtual display was added to the current state, but it does not have a
-    // surface.
-    sp<BBinder> displayToken = new BBinder();
-
-    DisplayDeviceState state;
-    state.isSecure = static_cast<bool>(Case::Display::SECURE);
-
-    mFlinger.mutableCurrentState().displays.add(displayToken, state);
-
-    // --------------------------------------------------------------------
-    // Call Expectations
-
-    // --------------------------------------------------------------------
-    // Invocation
-
-    mFlinger.handleTransactionLocked(eDisplayTransactionNeeded);
-
-    // --------------------------------------------------------------------
-    // Postconditions
-
-    // There will not be a display device set up.
-    EXPECT_FALSE(hasDisplayDevice(displayToken));
-
-    // The drawing display state will be set from the current display state.
-    ASSERT_TRUE(hasDrawingDisplayState(displayToken));
-    const auto& draw = getDrawingDisplayState(displayToken);
-    EXPECT_EQ(static_cast<bool>(Case::Display::VIRTUAL), draw.isVirtual());
-}
-
-TEST_F(HandleTransactionLockedTest, processesVirtualDisplayRemoval) {
-    using Case = HwcVirtualDisplayCase;
-
-    // --------------------------------------------------------------------
-    // Preconditions
-
-    // A virtual display is set up but is removed from the current state.
-    const auto displayId = Case::Display::DISPLAY_ID::get();
-    ASSERT_TRUE(HalVirtualDisplayId::tryCast(displayId));
-    mFlinger.mutableHwcDisplayData().try_emplace(displayId);
-    Case::Display::injectHwcDisplay(this);
-    auto existing = Case::Display::makeFakeExistingDisplayInjector(this);
-    existing.inject();
-    mFlinger.mutableCurrentState().displays.removeItem(existing.token());
-
-    // --------------------------------------------------------------------
-    // Invocation
-
-    mFlinger.handleTransactionLocked(eDisplayTransactionNeeded);
-
-    // --------------------------------------------------------------------
-    // Postconditions
-
-    // The existing token should have been removed
-    verifyDisplayIsNotConnected(existing.token());
-}
-
-TEST_F(HandleTransactionLockedTest, processesDisplayLayerStackChanges) {
-    using Case = NonHwcVirtualDisplayCase;
-
-    constexpr uint32_t oldLayerStack = 0u;
-    constexpr uint32_t newLayerStack = 123u;
-
-    // --------------------------------------------------------------------
-    // Preconditions
-
-    // A display is set up
-    auto display = Case::Display::makeFakeExistingDisplayInjector(this);
-    display.inject();
-
-    // There is a change to the layerStack state
-    display.mutableDrawingDisplayState().layerStack = oldLayerStack;
-    display.mutableCurrentDisplayState().layerStack = newLayerStack;
-
-    // --------------------------------------------------------------------
-    // Invocation
-
-    mFlinger.handleTransactionLocked(eDisplayTransactionNeeded);
-
-    // --------------------------------------------------------------------
-    // Postconditions
-
-    EXPECT_EQ(newLayerStack, display.mutableDisplayDevice()->getLayerStack());
-}
-
-TEST_F(HandleTransactionLockedTest, processesDisplayTransformChanges) {
-    using Case = NonHwcVirtualDisplayCase;
-
-    constexpr ui::Rotation oldTransform = ui::ROTATION_0;
-    constexpr ui::Rotation newTransform = ui::ROTATION_180;
-
-    // --------------------------------------------------------------------
-    // Preconditions
-
-    // A display is set up
-    auto display = Case::Display::makeFakeExistingDisplayInjector(this);
-    display.inject();
-
-    // There is a change to the orientation state
-    display.mutableDrawingDisplayState().orientation = oldTransform;
-    display.mutableCurrentDisplayState().orientation = newTransform;
-
-    // --------------------------------------------------------------------
-    // Invocation
-
-    mFlinger.handleTransactionLocked(eDisplayTransactionNeeded);
-
-    // --------------------------------------------------------------------
-    // Postconditions
-
-    EXPECT_EQ(newTransform, display.mutableDisplayDevice()->getOrientation());
-}
-
-TEST_F(HandleTransactionLockedTest, processesDisplayLayerStackRectChanges) {
-    using Case = NonHwcVirtualDisplayCase;
-
-    const Rect oldLayerStackRect(0, 0, 0, 0);
-    const Rect newLayerStackRect(0, 0, 123, 456);
-
-    // --------------------------------------------------------------------
-    // Preconditions
-
-    // A display is set up
-    auto display = Case::Display::makeFakeExistingDisplayInjector(this);
-    display.inject();
-
-    // There is a change to the layerStackSpaceRect state
-    display.mutableDrawingDisplayState().layerStackSpaceRect = oldLayerStackRect;
-    display.mutableCurrentDisplayState().layerStackSpaceRect = newLayerStackRect;
-
-    // --------------------------------------------------------------------
-    // Invocation
-
-    mFlinger.handleTransactionLocked(eDisplayTransactionNeeded);
-
-    // --------------------------------------------------------------------
-    // Postconditions
-
-    EXPECT_EQ(newLayerStackRect, display.mutableDisplayDevice()->getLayerStackSpaceRect());
-}
-
-TEST_F(HandleTransactionLockedTest, processesDisplayFrameChanges) {
-    using Case = NonHwcVirtualDisplayCase;
-
-    const Rect oldFrame(0, 0, 0, 0);
-    const Rect newFrame(0, 0, 123, 456);
-
-    // --------------------------------------------------------------------
-    // Preconditions
-
-    // A display is set up
-    auto display = Case::Display::makeFakeExistingDisplayInjector(this);
-    display.inject();
-
-    // There is a change to the layerStackSpaceRect state
-    display.mutableDrawingDisplayState().orientedDisplaySpaceRect = oldFrame;
-    display.mutableCurrentDisplayState().orientedDisplaySpaceRect = newFrame;
-
-    // --------------------------------------------------------------------
-    // Invocation
-
-    mFlinger.handleTransactionLocked(eDisplayTransactionNeeded);
-
-    // --------------------------------------------------------------------
-    // Postconditions
-
-    EXPECT_EQ(newFrame, display.mutableDisplayDevice()->getOrientedDisplaySpaceRect());
-}
-
-TEST_F(HandleTransactionLockedTest, processesDisplayWidthChanges) {
-    using Case = NonHwcVirtualDisplayCase;
-
-    constexpr int oldWidth = 0;
-    constexpr int oldHeight = 10;
-    constexpr int newWidth = 123;
-
-    // --------------------------------------------------------------------
-    // Preconditions
-
-    // A display is set up
-    auto nativeWindow = new mock::NativeWindow();
-    auto displaySurface = new compositionengine::mock::DisplaySurface();
-    sp<GraphicBuffer> buf = new GraphicBuffer();
-    auto display = Case::Display::makeFakeExistingDisplayInjector(this);
-    display.setNativeWindow(nativeWindow);
-    display.setDisplaySurface(displaySurface);
-    // Setup injection expections
-    EXPECT_CALL(*nativeWindow, query(NATIVE_WINDOW_WIDTH, _))
-            .WillOnce(DoAll(SetArgPointee<1>(oldWidth), Return(0)));
-    EXPECT_CALL(*nativeWindow, query(NATIVE_WINDOW_HEIGHT, _))
-            .WillOnce(DoAll(SetArgPointee<1>(oldHeight), Return(0)));
-    EXPECT_CALL(*nativeWindow, perform(NATIVE_WINDOW_SET_BUFFERS_FORMAT)).Times(1);
-    EXPECT_CALL(*nativeWindow, perform(NATIVE_WINDOW_API_CONNECT)).Times(1);
-    EXPECT_CALL(*nativeWindow, perform(NATIVE_WINDOW_SET_USAGE64)).Times(1);
-    EXPECT_CALL(*nativeWindow, perform(NATIVE_WINDOW_API_DISCONNECT)).Times(1);
-    display.inject();
-
-    // There is a change to the layerStackSpaceRect state
-    display.mutableDrawingDisplayState().width = oldWidth;
-    display.mutableDrawingDisplayState().height = oldHeight;
-    display.mutableCurrentDisplayState().width = newWidth;
-    display.mutableCurrentDisplayState().height = oldHeight;
-
-    // --------------------------------------------------------------------
-    // Call Expectations
-
-    EXPECT_CALL(*displaySurface, resizeBuffers(newWidth, oldHeight)).Times(1);
-
-    // --------------------------------------------------------------------
-    // Invocation
-
-    mFlinger.handleTransactionLocked(eDisplayTransactionNeeded);
-}
-
-TEST_F(HandleTransactionLockedTest, processesDisplayHeightChanges) {
-    using Case = NonHwcVirtualDisplayCase;
-
-    constexpr int oldWidth = 0;
-    constexpr int oldHeight = 10;
-    constexpr int newHeight = 123;
-
-    // --------------------------------------------------------------------
-    // Preconditions
-
-    // A display is set up
-    auto nativeWindow = new mock::NativeWindow();
-    auto displaySurface = new compositionengine::mock::DisplaySurface();
-    sp<GraphicBuffer> buf = new GraphicBuffer();
-    auto display = Case::Display::makeFakeExistingDisplayInjector(this);
-    display.setNativeWindow(nativeWindow);
-    display.setDisplaySurface(displaySurface);
-    // Setup injection expections
-    EXPECT_CALL(*nativeWindow, query(NATIVE_WINDOW_WIDTH, _))
-            .WillOnce(DoAll(SetArgPointee<1>(oldWidth), Return(0)));
-    EXPECT_CALL(*nativeWindow, query(NATIVE_WINDOW_HEIGHT, _))
-            .WillOnce(DoAll(SetArgPointee<1>(oldHeight), Return(0)));
-    EXPECT_CALL(*nativeWindow, perform(NATIVE_WINDOW_SET_BUFFERS_FORMAT)).Times(1);
-    EXPECT_CALL(*nativeWindow, perform(NATIVE_WINDOW_API_CONNECT)).Times(1);
-    EXPECT_CALL(*nativeWindow, perform(NATIVE_WINDOW_SET_USAGE64)).Times(1);
-    EXPECT_CALL(*nativeWindow, perform(NATIVE_WINDOW_API_DISCONNECT)).Times(1);
-    display.inject();
-
-    // There is a change to the layerStackSpaceRect state
-    display.mutableDrawingDisplayState().width = oldWidth;
-    display.mutableDrawingDisplayState().height = oldHeight;
-    display.mutableCurrentDisplayState().width = oldWidth;
-    display.mutableCurrentDisplayState().height = newHeight;
-
-    // --------------------------------------------------------------------
-    // Call Expectations
-
-    EXPECT_CALL(*displaySurface, resizeBuffers(oldWidth, newHeight)).Times(1);
-
-    // --------------------------------------------------------------------
-    // Invocation
-
-    mFlinger.handleTransactionLocked(eDisplayTransactionNeeded);
-}
-
-/* ------------------------------------------------------------------------
- * SurfaceFlinger::setDisplayStateLocked
- */
-
-TEST_F(DisplayTransactionTest, setDisplayStateLockedDoesNothingWithUnknownDisplay) {
-    // --------------------------------------------------------------------
-    // Preconditions
-
-    // We have an unknown display token not associated with a known display
-    sp<BBinder> displayToken = new BBinder();
-
-    // The requested display state references the unknown display.
-    DisplayState state;
-    state.what = DisplayState::eLayerStackChanged;
-    state.token = displayToken;
-    state.layerStack = 456;
-
-    // --------------------------------------------------------------------
-    // Invocation
-
-    uint32_t flags = mFlinger.setDisplayStateLocked(state);
-
-    // --------------------------------------------------------------------
-    // Postconditions
-
-    // The returned flags are empty
-    EXPECT_EQ(0u, flags);
-
-    // The display token still doesn't match anything known.
-    EXPECT_FALSE(hasCurrentDisplayState(displayToken));
-}
-
-TEST_F(DisplayTransactionTest, setDisplayStateLockedDoesNothingWhenNoChanges) {
-    using Case = SimplePrimaryDisplayCase;
-
-    // --------------------------------------------------------------------
-    // Preconditions
-
-    // A display is already set up
-    auto display = Case::Display::makeFakeExistingDisplayInjector(this);
-    display.inject();
-
-    // No changes are made to the display
-    DisplayState state;
-    state.what = 0;
-    state.token = display.token();
-
-    // --------------------------------------------------------------------
-    // Invocation
-
-    uint32_t flags = mFlinger.setDisplayStateLocked(state);
-
-    // --------------------------------------------------------------------
-    // Postconditions
-
-    // The returned flags are empty
-    EXPECT_EQ(0u, flags);
-}
-
-TEST_F(DisplayTransactionTest, setDisplayStateLockedDoesNothingIfSurfaceDidNotChange) {
-    using Case = SimplePrimaryDisplayCase;
-
-    // --------------------------------------------------------------------
-    // Preconditions
-
-    // A display is already set up
-    auto display = Case::Display::makeFakeExistingDisplayInjector(this);
-    display.inject();
-
-    // There is a surface that can be set.
-    sp<mock::GraphicBufferProducer> surface = new mock::GraphicBufferProducer();
-
-    // The current display state has the surface set
-    display.mutableCurrentDisplayState().surface = surface;
-
-    // The incoming request sets the same surface
-    DisplayState state;
-    state.what = DisplayState::eSurfaceChanged;
-    state.token = display.token();
-    state.surface = surface;
-
-    // --------------------------------------------------------------------
-    // Invocation
-
-    uint32_t flags = mFlinger.setDisplayStateLocked(state);
-
-    // --------------------------------------------------------------------
-    // Postconditions
-
-    // The returned flags are empty
-    EXPECT_EQ(0u, flags);
-
-    // The current display state is unchanged.
-    EXPECT_EQ(surface.get(), display.getCurrentDisplayState().surface.get());
-}
-
-TEST_F(DisplayTransactionTest, setDisplayStateLockedRequestsUpdateIfSurfaceChanged) {
-    using Case = SimplePrimaryDisplayCase;
-
-    // --------------------------------------------------------------------
-    // Preconditions
-
-    // A display is already set up
-    auto display = Case::Display::makeFakeExistingDisplayInjector(this);
-    display.inject();
-
-    // There is a surface that can be set.
-    sp<mock::GraphicBufferProducer> surface = new mock::GraphicBufferProducer();
-
-    // The current display state does not have a surface
-    display.mutableCurrentDisplayState().surface = nullptr;
-
-    // The incoming request sets a surface
-    DisplayState state;
-    state.what = DisplayState::eSurfaceChanged;
-    state.token = display.token();
-    state.surface = surface;
-
-    // --------------------------------------------------------------------
-    // Invocation
-
-    uint32_t flags = mFlinger.setDisplayStateLocked(state);
-
-    // --------------------------------------------------------------------
-    // Postconditions
-
-    // The returned flags indicate a transaction is needed
-    EXPECT_EQ(eDisplayTransactionNeeded, flags);
-
-    // The current display layer stack state is set to the new value
-    EXPECT_EQ(surface.get(), display.getCurrentDisplayState().surface.get());
-}
-
-TEST_F(DisplayTransactionTest, setDisplayStateLockedDoesNothingIfLayerStackDidNotChange) {
-    using Case = SimplePrimaryDisplayCase;
-
-    // --------------------------------------------------------------------
-    // Preconditions
-
-    // A display is already set up
-    auto display = Case::Display::makeFakeExistingDisplayInjector(this);
-    display.inject();
-
-    // The display has a layer stack set
-    display.mutableCurrentDisplayState().layerStack = 456u;
-
-    // The incoming request sets the same layer stack
-    DisplayState state;
-    state.what = DisplayState::eLayerStackChanged;
-    state.token = display.token();
-    state.layerStack = 456u;
-
-    // --------------------------------------------------------------------
-    // Invocation
-
-    uint32_t flags = mFlinger.setDisplayStateLocked(state);
-
-    // --------------------------------------------------------------------
-    // Postconditions
-
-    // The returned flags are empty
-    EXPECT_EQ(0u, flags);
-
-    // The current display state is unchanged
-    EXPECT_EQ(456u, display.getCurrentDisplayState().layerStack);
-}
-
-TEST_F(DisplayTransactionTest, setDisplayStateLockedRequestsUpdateIfLayerStackChanged) {
-    using Case = SimplePrimaryDisplayCase;
-
-    // --------------------------------------------------------------------
-    // Preconditions
-
-    // A display is set up
-    auto display = Case::Display::makeFakeExistingDisplayInjector(this);
-    display.inject();
-
-    // The display has a layer stack set
-    display.mutableCurrentDisplayState().layerStack = 654u;
-
-    // The incoming request sets a different layer stack
-    DisplayState state;
-    state.what = DisplayState::eLayerStackChanged;
-    state.token = display.token();
-    state.layerStack = 456u;
-
-    // --------------------------------------------------------------------
-    // Invocation
-
-    uint32_t flags = mFlinger.setDisplayStateLocked(state);
-
-    // --------------------------------------------------------------------
-    // Postconditions
-
-    // The returned flags indicate a transaction is needed
-    EXPECT_EQ(eDisplayTransactionNeeded, flags);
-
-    // The desired display state has been set to the new value.
-    EXPECT_EQ(456u, display.getCurrentDisplayState().layerStack);
-}
-
-TEST_F(DisplayTransactionTest, setDisplayStateLockedDoesNothingIfProjectionDidNotChange) {
-    using Case = SimplePrimaryDisplayCase;
-    constexpr ui::Rotation initialOrientation = ui::ROTATION_180;
-    const Rect initialOrientedDisplayRect = {1, 2, 3, 4};
-    const Rect initialLayerStackRect = {5, 6, 7, 8};
-
-    // --------------------------------------------------------------------
-    // Preconditions
-
-    // A display is set up
-    auto display = Case::Display::makeFakeExistingDisplayInjector(this);
-    display.inject();
-
-    // The current display state projection state is all set
-    display.mutableCurrentDisplayState().orientation = initialOrientation;
-    display.mutableCurrentDisplayState().orientedDisplaySpaceRect = initialOrientedDisplayRect;
-    display.mutableCurrentDisplayState().layerStackSpaceRect = initialLayerStackRect;
-
-    // The incoming request sets the same projection state
-    DisplayState state;
-    state.what = DisplayState::eDisplayProjectionChanged;
-    state.token = display.token();
-    state.orientation = initialOrientation;
-    state.orientedDisplaySpaceRect = initialOrientedDisplayRect;
-    state.layerStackSpaceRect = initialLayerStackRect;
-
-    // --------------------------------------------------------------------
-    // Invocation
-
-    uint32_t flags = mFlinger.setDisplayStateLocked(state);
-
-    // --------------------------------------------------------------------
-    // Postconditions
-
-    // The returned flags are empty
-    EXPECT_EQ(0u, flags);
-
-    // The current display state is unchanged
-    EXPECT_EQ(initialOrientation, display.getCurrentDisplayState().orientation);
-
-    EXPECT_EQ(initialOrientedDisplayRect,
-              display.getCurrentDisplayState().orientedDisplaySpaceRect);
-    EXPECT_EQ(initialLayerStackRect, display.getCurrentDisplayState().layerStackSpaceRect);
-}
-
-TEST_F(DisplayTransactionTest, setDisplayStateLockedRequestsUpdateIfOrientationChanged) {
-    using Case = SimplePrimaryDisplayCase;
-    constexpr ui::Rotation initialOrientation = ui::ROTATION_90;
-    constexpr ui::Rotation desiredOrientation = ui::ROTATION_180;
-
-    // --------------------------------------------------------------------
-    // Preconditions
-
-    // A display is set up
-    auto display = Case::Display::makeFakeExistingDisplayInjector(this);
-    display.inject();
-
-    // The current display state has an orientation set
-    display.mutableCurrentDisplayState().orientation = initialOrientation;
-
-    // The incoming request sets a different orientation
-    DisplayState state;
-    state.what = DisplayState::eDisplayProjectionChanged;
-    state.token = display.token();
-    state.orientation = desiredOrientation;
-
-    // --------------------------------------------------------------------
-    // Invocation
-
-    uint32_t flags = mFlinger.setDisplayStateLocked(state);
-
-    // --------------------------------------------------------------------
-    // Postconditions
-
-    // The returned flags indicate a transaction is needed
-    EXPECT_EQ(eDisplayTransactionNeeded, flags);
-
-    // The current display state has the new value.
-    EXPECT_EQ(desiredOrientation, display.getCurrentDisplayState().orientation);
-}
-
-TEST_F(DisplayTransactionTest, setDisplayStateLockedRequestsUpdateIfFrameChanged) {
-    using Case = SimplePrimaryDisplayCase;
-    const Rect initialOrientedDisplayRect = {0, 0, 0, 0};
-    const Rect desiredOrientedDisplayRect = {5, 6, 7, 8};
-
-    // --------------------------------------------------------------------
-    // Preconditions
-
-    // A display is set up
-    auto display = Case::Display::makeFakeExistingDisplayInjector(this);
-    display.inject();
-
-    // The current display state does not have a orientedDisplaySpaceRect
-    display.mutableCurrentDisplayState().orientedDisplaySpaceRect = initialOrientedDisplayRect;
-
-    // The incoming request sets a orientedDisplaySpaceRect
-    DisplayState state;
-    state.what = DisplayState::eDisplayProjectionChanged;
-    state.token = display.token();
-    state.orientedDisplaySpaceRect = desiredOrientedDisplayRect;
-
-    // --------------------------------------------------------------------
-    // Invocation
-
-    uint32_t flags = mFlinger.setDisplayStateLocked(state);
-
-    // --------------------------------------------------------------------
-    // Postconditions
-
-    // The returned flags indicate a transaction is needed
-    EXPECT_EQ(eDisplayTransactionNeeded, flags);
-
-    // The current display state has the new value.
-    EXPECT_EQ(desiredOrientedDisplayRect,
-              display.getCurrentDisplayState().orientedDisplaySpaceRect);
-}
-
-TEST_F(DisplayTransactionTest, setDisplayStateLockedRequestsUpdateIfLayerStackRectChanged) {
-    using Case = SimplePrimaryDisplayCase;
-    const Rect initialLayerStackRect = {0, 0, 0, 0};
-    const Rect desiredLayerStackRect = {5, 6, 7, 8};
-
-    // --------------------------------------------------------------------
-    // Preconditions
-
-    // A display is set up
-    auto display = Case::Display::makeFakeExistingDisplayInjector(this);
-    display.inject();
-
-    // The current display state does not have a layerStackSpaceRect
-    display.mutableCurrentDisplayState().layerStackSpaceRect = initialLayerStackRect;
-
-    // The incoming request sets a layerStackSpaceRect
-    DisplayState state;
-    state.what = DisplayState::eDisplayProjectionChanged;
-    state.token = display.token();
-    state.layerStackSpaceRect = desiredLayerStackRect;
-
-    // --------------------------------------------------------------------
-    // Invocation
-
-    uint32_t flags = mFlinger.setDisplayStateLocked(state);
-
-    // --------------------------------------------------------------------
-    // Postconditions
-
-    // The returned flags indicate a transaction is needed
-    EXPECT_EQ(eDisplayTransactionNeeded, flags);
-
-    // The current display state has the new value.
-    EXPECT_EQ(desiredLayerStackRect, display.getCurrentDisplayState().layerStackSpaceRect);
-}
-
-TEST_F(DisplayTransactionTest, setDisplayStateLockedDoesNothingIfSizeDidNotChange) {
-    using Case = SimplePrimaryDisplayCase;
-    constexpr uint32_t initialWidth = 1024;
-    constexpr uint32_t initialHeight = 768;
-
-    // --------------------------------------------------------------------
-    // Preconditions
-
-    // A display is set up
-    auto display = Case::Display::makeFakeExistingDisplayInjector(this);
-    display.inject();
-
-    // The current display state has a size set
-    display.mutableCurrentDisplayState().width = initialWidth;
-    display.mutableCurrentDisplayState().height = initialHeight;
-
-    // The incoming request sets the same display size
-    DisplayState state;
-    state.what = DisplayState::eDisplaySizeChanged;
-    state.token = display.token();
-    state.width = initialWidth;
-    state.height = initialHeight;
-
-    // --------------------------------------------------------------------
-    // Invocation
-
-    uint32_t flags = mFlinger.setDisplayStateLocked(state);
-
-    // --------------------------------------------------------------------
-    // Postconditions
-
-    // The returned flags are empty
-    EXPECT_EQ(0u, flags);
-
-    // The current display state is unchanged
-    EXPECT_EQ(initialWidth, display.getCurrentDisplayState().width);
-    EXPECT_EQ(initialHeight, display.getCurrentDisplayState().height);
-}
-
-TEST_F(DisplayTransactionTest, setDisplayStateLockedRequestsUpdateIfWidthChanged) {
-    using Case = SimplePrimaryDisplayCase;
-    constexpr uint32_t initialWidth = 0;
-    constexpr uint32_t desiredWidth = 1024;
-
-    // --------------------------------------------------------------------
-    // Preconditions
-
-    // A display is set up
-    auto display = Case::Display::makeFakeExistingDisplayInjector(this);
-    display.inject();
-
-    // The display does not yet have a width
-    display.mutableCurrentDisplayState().width = initialWidth;
-
-    // The incoming request sets a display width
-    DisplayState state;
-    state.what = DisplayState::eDisplaySizeChanged;
-    state.token = display.token();
-    state.width = desiredWidth;
-
-    // --------------------------------------------------------------------
-    // Invocation
-
-    uint32_t flags = mFlinger.setDisplayStateLocked(state);
-
-    // --------------------------------------------------------------------
-    // Postconditions
-
-    // The returned flags indicate a transaction is needed
-    EXPECT_EQ(eDisplayTransactionNeeded, flags);
-
-    // The current display state has the new value.
-    EXPECT_EQ(desiredWidth, display.getCurrentDisplayState().width);
-}
-
-TEST_F(DisplayTransactionTest, setDisplayStateLockedRequestsUpdateIfHeightChanged) {
-    using Case = SimplePrimaryDisplayCase;
-    constexpr uint32_t initialHeight = 0;
-    constexpr uint32_t desiredHeight = 768;
-
-    // --------------------------------------------------------------------
-    // Preconditions
-
-    // A display is set up
-    auto display = Case::Display::makeFakeExistingDisplayInjector(this);
-    display.inject();
-
-    // The display does not yet have a height
-    display.mutableCurrentDisplayState().height = initialHeight;
-
-    // The incoming request sets a display height
-    DisplayState state;
-    state.what = DisplayState::eDisplaySizeChanged;
-    state.token = display.token();
-    state.height = desiredHeight;
-
-    // --------------------------------------------------------------------
-    // Invocation
-
-    uint32_t flags = mFlinger.setDisplayStateLocked(state);
-
-    // --------------------------------------------------------------------
-    // Postconditions
-
-    // The returned flags indicate a transaction is needed
-    EXPECT_EQ(eDisplayTransactionNeeded, flags);
-
-    // The current display state has the new value.
-    EXPECT_EQ(desiredHeight, display.getCurrentDisplayState().height);
-}
-
-/* ------------------------------------------------------------------------
- * SurfaceFlinger::onInitializeDisplays
- */
-
-TEST_F(DisplayTransactionTest, onInitializeDisplaysSetsUpPrimaryDisplay) {
-    using Case = SimplePrimaryDisplayCase;
-
-    // --------------------------------------------------------------------
-    // Preconditions
-
-    // A primary display is set up
-    Case::Display::injectHwcDisplay(this);
-    auto primaryDisplay = Case::Display::makeFakeExistingDisplayInjector(this);
-    primaryDisplay.inject();
-
-    // --------------------------------------------------------------------
-    // Call Expectations
-
-    // We expect the surface interceptor to possibly be used, but we treat it as
-    // disabled since it is called as a side effect rather than directly by this
-    // function.
-    EXPECT_CALL(*mSurfaceInterceptor, isEnabled()).WillOnce(Return(false));
-
-    // We expect a call to get the active display config.
-    Case::Display::setupHwcGetActiveConfigCallExpectations(this);
-
-    // We expect invalidate() to be invoked once to trigger display transaction
-    // processing.
-    EXPECT_CALL(*mMessageQueue, invalidate()).Times(1);
-
-    EXPECT_CALL(*mVSyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillRepeatedly(Return(0));
-
-    // --------------------------------------------------------------------
-    // Invocation
-
-    mFlinger.onInitializeDisplays();
-
-    // --------------------------------------------------------------------
-    // Postconditions
-
-    // The primary display should have a current state
-    ASSERT_TRUE(hasCurrentDisplayState(primaryDisplay.token()));
-    const auto& primaryDisplayState = getCurrentDisplayState(primaryDisplay.token());
-    // The layer stack state should be set to zero
-    EXPECT_EQ(0u, primaryDisplayState.layerStack);
-    // The orientation state should be set to zero
-    EXPECT_EQ(ui::ROTATION_0, primaryDisplayState.orientation);
-
-    // The orientedDisplaySpaceRect state should be set to INVALID
-    EXPECT_EQ(Rect::INVALID_RECT, primaryDisplayState.orientedDisplaySpaceRect);
-
-    // The layerStackSpaceRect state should be set to INVALID
-    EXPECT_EQ(Rect::INVALID_RECT, primaryDisplayState.layerStackSpaceRect);
-
-    // The width and height should both be zero
-    EXPECT_EQ(0u, primaryDisplayState.width);
-    EXPECT_EQ(0u, primaryDisplayState.height);
-
-    // The display should be set to PowerMode::ON
-    ASSERT_TRUE(hasDisplayDevice(primaryDisplay.token()));
-    auto displayDevice = primaryDisplay.mutableDisplayDevice();
-    EXPECT_EQ(PowerMode::ON, displayDevice->getPowerMode());
-
-    // The display refresh period should be set in the orientedDisplaySpaceRect tracker.
-    FrameStats stats;
-    mFlinger.getAnimFrameTracker().getStats(&stats);
-    EXPECT_EQ(DEFAULT_REFRESH_RATE, stats.refreshPeriodNano);
-
-    // The display transaction needed flag should be set.
-    EXPECT_TRUE(hasTransactionFlagSet(eDisplayTransactionNeeded));
-
-    // The compositor timing should be set to default values
-    const auto& compositorTiming = mFlinger.getCompositorTiming();
-    EXPECT_EQ(-DEFAULT_REFRESH_RATE, compositorTiming.deadline);
-    EXPECT_EQ(DEFAULT_REFRESH_RATE, compositorTiming.interval);
-    EXPECT_EQ(DEFAULT_REFRESH_RATE, compositorTiming.presentLatency);
-}
-
-/* ------------------------------------------------------------------------
- * SurfaceFlinger::setPowerModeInternal
- */
-
-// Used when we simulate a display that supports doze.
-template <typename Display>
-struct DozeIsSupportedVariant {
-    static constexpr bool DOZE_SUPPORTED = true;
-    static constexpr IComposerClient::PowerMode ACTUAL_POWER_MODE_FOR_DOZE =
-            IComposerClient::PowerMode::DOZE;
-    static constexpr IComposerClient::PowerMode ACTUAL_POWER_MODE_FOR_DOZE_SUSPEND =
-            IComposerClient::PowerMode::DOZE_SUSPEND;
-
-    static void setupComposerCallExpectations(DisplayTransactionTest* test) {
-        EXPECT_CALL(*test->mComposer, getDisplayCapabilities(Display::HWC_DISPLAY_ID, _))
-                .WillOnce(DoAll(SetArgPointee<1>(
-                                        std::vector<DisplayCapability>({DisplayCapability::DOZE})),
-                                Return(Error::NONE)));
-    }
-};
-
-template <typename Display>
-// Used when we simulate a display that does not support doze.
-struct DozeNotSupportedVariant {
-    static constexpr bool DOZE_SUPPORTED = false;
-    static constexpr IComposerClient::PowerMode ACTUAL_POWER_MODE_FOR_DOZE =
-            IComposerClient::PowerMode::ON;
-    static constexpr IComposerClient::PowerMode ACTUAL_POWER_MODE_FOR_DOZE_SUSPEND =
-            IComposerClient::PowerMode::ON;
-
-    static void setupComposerCallExpectations(DisplayTransactionTest* test) {
-        EXPECT_CALL(*test->mComposer, getDisplayCapabilities(Display::HWC_DISPLAY_ID, _))
-                .WillOnce(DoAll(SetArgPointee<1>(std::vector<DisplayCapability>({})),
-                                Return(Error::NONE)));
-    }
-};
-
-struct EventThreadBaseSupportedVariant {
-    static void setupVsyncAndEventThreadNoCallExpectations(DisplayTransactionTest* test) {
-        // The callback should not be notified to toggle VSYNC.
-        EXPECT_CALL(test->mSchedulerCallback, setVsyncEnabled(_)).Times(0);
-
-        // The event thread should not be notified.
-        EXPECT_CALL(*test->mEventThread, onScreenReleased()).Times(0);
-        EXPECT_CALL(*test->mEventThread, onScreenAcquired()).Times(0);
-    }
-};
-
-struct EventThreadNotSupportedVariant : public EventThreadBaseSupportedVariant {
-    static void setupAcquireAndEnableVsyncCallExpectations(DisplayTransactionTest* test) {
-        // These calls are only expected for the primary display.
-
-        // Instead expect no calls.
-        setupVsyncAndEventThreadNoCallExpectations(test);
-    }
-
-    static void setupReleaseAndDisableVsyncCallExpectations(DisplayTransactionTest* test) {
-        // These calls are only expected for the primary display.
-
-        // Instead expect no calls.
-        setupVsyncAndEventThreadNoCallExpectations(test);
-    }
-};
-
-struct EventThreadIsSupportedVariant : public EventThreadBaseSupportedVariant {
-    static void setupAcquireAndEnableVsyncCallExpectations(DisplayTransactionTest* test) {
-        // The callback should be notified to enable VSYNC.
-        EXPECT_CALL(test->mSchedulerCallback, setVsyncEnabled(true)).Times(1);
-
-        // The event thread should be notified that the screen was acquired.
-        EXPECT_CALL(*test->mEventThread, onScreenAcquired()).Times(1);
-    }
-
-    static void setupReleaseAndDisableVsyncCallExpectations(DisplayTransactionTest* test) {
-        // The callback should be notified to disable VSYNC.
-        EXPECT_CALL(test->mSchedulerCallback, setVsyncEnabled(false)).Times(1);
-
-        // The event thread should not be notified that the screen was released.
-        EXPECT_CALL(*test->mEventThread, onScreenReleased()).Times(1);
-    }
-};
-
-struct DispSyncIsSupportedVariant {
-    static void setupResetModelCallExpectations(DisplayTransactionTest* test) {
-        EXPECT_CALL(*test->mVsyncController, startPeriodTransition(DEFAULT_REFRESH_RATE)).Times(1);
-        EXPECT_CALL(*test->mVSyncTracker, resetModel()).Times(1);
-    }
-};
-
-struct DispSyncNotSupportedVariant {
-    static void setupResetModelCallExpectations(DisplayTransactionTest* /* test */) {}
-};
-
-// --------------------------------------------------------------------
-// Note:
-//
-// There are a large number of transitions we could test, however we only test a
-// selected subset which provides complete test coverage of the implementation.
-// --------------------------------------------------------------------
-
-template <PowerMode initialPowerMode, PowerMode targetPowerMode>
-struct TransitionVariantCommon {
-    static constexpr auto INITIAL_POWER_MODE = initialPowerMode;
-    static constexpr auto TARGET_POWER_MODE = targetPowerMode;
-
-    static void verifyPostconditions(DisplayTransactionTest*) {}
-};
-
-struct TransitionOffToOnVariant : public TransitionVariantCommon<PowerMode::OFF, PowerMode::ON> {
-    template <typename Case>
-    static void setupCallExpectations(DisplayTransactionTest* test) {
-        Case::setupComposerCallExpectations(test, IComposerClient::PowerMode::ON);
-        Case::EventThread::setupAcquireAndEnableVsyncCallExpectations(test);
-        Case::DispSync::setupResetModelCallExpectations(test);
-        Case::setupRepaintEverythingCallExpectations(test);
-    }
-
-    static void verifyPostconditions(DisplayTransactionTest* test) {
-        EXPECT_TRUE(test->mFlinger.getVisibleRegionsDirty());
-        EXPECT_TRUE(test->mFlinger.getHasPoweredOff());
-    }
-};
-
-struct TransitionOffToDozeSuspendVariant
-      : public TransitionVariantCommon<PowerMode::OFF, PowerMode::DOZE_SUSPEND> {
-    template <typename Case>
-    static void setupCallExpectations(DisplayTransactionTest* test) {
-        Case::setupComposerCallExpectations(test, Case::Doze::ACTUAL_POWER_MODE_FOR_DOZE_SUSPEND);
-        Case::EventThread::setupVsyncAndEventThreadNoCallExpectations(test);
-        Case::setupRepaintEverythingCallExpectations(test);
-    }
-
-    static void verifyPostconditions(DisplayTransactionTest* test) {
-        EXPECT_TRUE(test->mFlinger.getVisibleRegionsDirty());
-        EXPECT_TRUE(test->mFlinger.getHasPoweredOff());
-    }
-};
-
-struct TransitionOnToOffVariant : public TransitionVariantCommon<PowerMode::ON, PowerMode::OFF> {
-    template <typename Case>
-    static void setupCallExpectations(DisplayTransactionTest* test) {
-        Case::EventThread::setupReleaseAndDisableVsyncCallExpectations(test);
-        Case::setupComposerCallExpectations(test, IComposerClient::PowerMode::OFF);
-    }
-
-    static void verifyPostconditions(DisplayTransactionTest* test) {
-        EXPECT_TRUE(test->mFlinger.getVisibleRegionsDirty());
-    }
-};
-
-struct TransitionDozeSuspendToOffVariant
-      : public TransitionVariantCommon<PowerMode::DOZE_SUSPEND, PowerMode::OFF> {
-    template <typename Case>
-    static void setupCallExpectations(DisplayTransactionTest* test) {
-        Case::EventThread::setupVsyncAndEventThreadNoCallExpectations(test);
-        Case::setupComposerCallExpectations(test, IComposerClient::PowerMode::OFF);
-    }
-
-    static void verifyPostconditions(DisplayTransactionTest* test) {
-        EXPECT_TRUE(test->mFlinger.getVisibleRegionsDirty());
-    }
-};
-
-struct TransitionOnToDozeVariant : public TransitionVariantCommon<PowerMode::ON, PowerMode::DOZE> {
-    template <typename Case>
-    static void setupCallExpectations(DisplayTransactionTest* test) {
-        Case::EventThread::setupVsyncAndEventThreadNoCallExpectations(test);
-        Case::setupComposerCallExpectations(test, Case::Doze::ACTUAL_POWER_MODE_FOR_DOZE);
-    }
-};
-
-struct TransitionDozeSuspendToDozeVariant
-      : public TransitionVariantCommon<PowerMode::DOZE_SUSPEND, PowerMode::DOZE> {
-    template <typename Case>
-    static void setupCallExpectations(DisplayTransactionTest* test) {
-        Case::EventThread::setupAcquireAndEnableVsyncCallExpectations(test);
-        Case::DispSync::setupResetModelCallExpectations(test);
-        Case::setupComposerCallExpectations(test, Case::Doze::ACTUAL_POWER_MODE_FOR_DOZE);
-    }
-};
-
-struct TransitionDozeToOnVariant : public TransitionVariantCommon<PowerMode::DOZE, PowerMode::ON> {
-    template <typename Case>
-    static void setupCallExpectations(DisplayTransactionTest* test) {
-        Case::EventThread::setupVsyncAndEventThreadNoCallExpectations(test);
-        Case::setupComposerCallExpectations(test, IComposerClient::PowerMode::ON);
-    }
-};
-
-struct TransitionDozeSuspendToOnVariant
-      : public TransitionVariantCommon<PowerMode::DOZE_SUSPEND, PowerMode::ON> {
-    template <typename Case>
-    static void setupCallExpectations(DisplayTransactionTest* test) {
-        Case::EventThread::setupAcquireAndEnableVsyncCallExpectations(test);
-        Case::DispSync::setupResetModelCallExpectations(test);
-        Case::setupComposerCallExpectations(test, IComposerClient::PowerMode::ON);
-    }
-};
-
-struct TransitionOnToDozeSuspendVariant
-      : public TransitionVariantCommon<PowerMode::ON, PowerMode::DOZE_SUSPEND> {
-    template <typename Case>
-    static void setupCallExpectations(DisplayTransactionTest* test) {
-        Case::EventThread::setupReleaseAndDisableVsyncCallExpectations(test);
-        Case::setupComposerCallExpectations(test, Case::Doze::ACTUAL_POWER_MODE_FOR_DOZE_SUSPEND);
-    }
-};
-
-struct TransitionOnToUnknownVariant
-      : public TransitionVariantCommon<PowerMode::ON, static_cast<PowerMode>(POWER_MODE_LEET)> {
-    template <typename Case>
-    static void setupCallExpectations(DisplayTransactionTest* test) {
-        Case::EventThread::setupVsyncAndEventThreadNoCallExpectations(test);
-        Case::setupNoComposerPowerModeCallExpectations(test);
-    }
-};
-
-// --------------------------------------------------------------------
-// Note:
-//
-// Rather than testing the cartesian product of of
-// DozeIsSupported/DozeNotSupported with all other options, we use one for one
-// display type, and the other for another display type.
-// --------------------------------------------------------------------
-
-template <typename DisplayVariant, typename DozeVariant, typename EventThreadVariant,
-          typename DispSyncVariant, typename TransitionVariant>
-struct DisplayPowerCase {
-    using Display = DisplayVariant;
-    using Doze = DozeVariant;
-    using EventThread = EventThreadVariant;
-    using DispSync = DispSyncVariant;
-    using Transition = TransitionVariant;
-
-    static auto injectDisplayWithInitialPowerMode(DisplayTransactionTest* test, PowerMode mode) {
-        Display::injectHwcDisplayWithNoDefaultCapabilities(test);
-        auto display = Display::makeFakeExistingDisplayInjector(test);
-        display.inject();
-        display.mutableDisplayDevice()->setPowerMode(mode);
-        return display;
-    }
-
-    static void setInitialPrimaryHWVsyncEnabled(DisplayTransactionTest* test, bool enabled) {
-        test->mFlinger.scheduler()->mutablePrimaryHWVsyncEnabled() = enabled;
-    }
-
-    static void setupRepaintEverythingCallExpectations(DisplayTransactionTest* test) {
-        EXPECT_CALL(*test->mMessageQueue, invalidate()).Times(1);
-    }
-
-    static void setupSurfaceInterceptorCallExpectations(DisplayTransactionTest* test,
-                                                        PowerMode mode) {
-        EXPECT_CALL(*test->mSurfaceInterceptor, isEnabled()).WillOnce(Return(true));
-        EXPECT_CALL(*test->mSurfaceInterceptor, savePowerModeUpdate(_, static_cast<int32_t>(mode)))
-                .Times(1);
-    }
-
-    static void setupComposerCallExpectations(DisplayTransactionTest* test, PowerMode mode) {
-        // Any calls to get the active config will return a default value.
-        EXPECT_CALL(*test->mComposer, getActiveConfig(Display::HWC_DISPLAY_ID, _))
-                .WillRepeatedly(DoAll(SetArgPointee<1>(Display::HWC_ACTIVE_CONFIG_ID),
-                                      Return(Error::NONE)));
-
-        // Any calls to get whether the display supports dozing will return the value set by the
-        // policy variant.
-        EXPECT_CALL(*test->mComposer, getDozeSupport(Display::HWC_DISPLAY_ID, _))
-                .WillRepeatedly(DoAll(SetArgPointee<1>(Doze::DOZE_SUPPORTED), Return(Error::NONE)));
-
-        EXPECT_CALL(*test->mComposer, setPowerMode(Display::HWC_DISPLAY_ID, mode)).Times(1);
-    }
-
-    static void setupNoComposerPowerModeCallExpectations(DisplayTransactionTest* test) {
-        EXPECT_CALL(*test->mComposer, setPowerMode(Display::HWC_DISPLAY_ID, _)).Times(0);
-    }
-};
-
-// A sample configuration for the primary display.
-// In addition to having event thread support, we emulate doze support.
-template <typename TransitionVariant>
-using PrimaryDisplayPowerCase =
-        DisplayPowerCase<PrimaryDisplayVariant, DozeIsSupportedVariant<PrimaryDisplayVariant>,
-                         EventThreadIsSupportedVariant, DispSyncIsSupportedVariant,
-                         TransitionVariant>;
-
-// A sample configuration for the external display.
-// In addition to not having event thread support, we emulate not having doze
-// support.
-template <typename TransitionVariant>
-using ExternalDisplayPowerCase =
-        DisplayPowerCase<ExternalDisplayVariant, DozeNotSupportedVariant<ExternalDisplayVariant>,
-                         EventThreadNotSupportedVariant, DispSyncNotSupportedVariant,
-                         TransitionVariant>;
-
-class SetPowerModeInternalTest : public DisplayTransactionTest {
-public:
-    template <typename Case>
-    void transitionDisplayCommon();
-};
-
-template <PowerMode PowerMode>
-struct PowerModeInitialVSyncEnabled : public std::false_type {};
-
-template <>
-struct PowerModeInitialVSyncEnabled<PowerMode::ON> : public std::true_type {};
-
-template <>
-struct PowerModeInitialVSyncEnabled<PowerMode::DOZE> : public std::true_type {};
-
-template <typename Case>
-void SetPowerModeInternalTest::transitionDisplayCommon() {
-    // --------------------------------------------------------------------
-    // Preconditions
-
-    Case::Doze::setupComposerCallExpectations(this);
-    auto display =
-            Case::injectDisplayWithInitialPowerMode(this, Case::Transition::INITIAL_POWER_MODE);
-    Case::setInitialPrimaryHWVsyncEnabled(this,
-                                          PowerModeInitialVSyncEnabled<
-                                                  Case::Transition::INITIAL_POWER_MODE>::value);
-
-    // --------------------------------------------------------------------
-    // Call Expectations
-
-    Case::setupSurfaceInterceptorCallExpectations(this, Case::Transition::TARGET_POWER_MODE);
-    Case::Transition::template setupCallExpectations<Case>(this);
-
-    // --------------------------------------------------------------------
-    // Invocation
-
-    mFlinger.setPowerModeInternal(display.mutableDisplayDevice(),
-                                  Case::Transition::TARGET_POWER_MODE);
-
-    // --------------------------------------------------------------------
-    // Postconditions
-
-    Case::Transition::verifyPostconditions(this);
-}
-
-TEST_F(SetPowerModeInternalTest, setPowerModeInternalDoesNothingIfNoChange) {
-    using Case = SimplePrimaryDisplayCase;
-
-    // --------------------------------------------------------------------
-    // Preconditions
-
-    // A primary display device is set up
-    Case::Display::injectHwcDisplay(this);
-    auto display = Case::Display::makeFakeExistingDisplayInjector(this);
-    display.inject();
-
-    // The display is already set to PowerMode::ON
-    display.mutableDisplayDevice()->setPowerMode(PowerMode::ON);
-
-    // --------------------------------------------------------------------
-    // Invocation
-
-    mFlinger.setPowerModeInternal(display.mutableDisplayDevice(), PowerMode::ON);
-
-    // --------------------------------------------------------------------
-    // Postconditions
-
-    EXPECT_EQ(PowerMode::ON, display.mutableDisplayDevice()->getPowerMode());
-}
-
-TEST_F(SetPowerModeInternalTest, setPowerModeInternalDoesNothingIfVirtualDisplay) {
-    using Case = HwcVirtualDisplayCase;
-
-    // --------------------------------------------------------------------
-    // Preconditions
-
-    // Insert display data so that the HWC thinks it created the virtual display.
-    const auto displayId = Case::Display::DISPLAY_ID::get();
-    ASSERT_TRUE(HalVirtualDisplayId::tryCast(displayId));
-    mFlinger.mutableHwcDisplayData().try_emplace(displayId);
-
-    // A virtual display device is set up
-    Case::Display::injectHwcDisplay(this);
-    auto display = Case::Display::makeFakeExistingDisplayInjector(this);
-    display.inject();
-
-    // The display is set to PowerMode::ON
-    getDisplayDevice(display.token())->setPowerMode(PowerMode::ON);
-
-    // --------------------------------------------------------------------
-    // Invocation
-
-    mFlinger.setPowerModeInternal(display.mutableDisplayDevice(), PowerMode::OFF);
-
-    // --------------------------------------------------------------------
-    // Postconditions
-
-    EXPECT_EQ(PowerMode::ON, display.mutableDisplayDevice()->getPowerMode());
-}
-
-TEST_F(SetPowerModeInternalTest, transitionsDisplayFromOffToOnPrimaryDisplay) {
-    transitionDisplayCommon<PrimaryDisplayPowerCase<TransitionOffToOnVariant>>();
-}
-
-TEST_F(SetPowerModeInternalTest, transitionsDisplayFromOffToDozeSuspendPrimaryDisplay) {
-    transitionDisplayCommon<PrimaryDisplayPowerCase<TransitionOffToDozeSuspendVariant>>();
-}
-
-TEST_F(SetPowerModeInternalTest, transitionsDisplayFromOnToOffPrimaryDisplay) {
-    transitionDisplayCommon<PrimaryDisplayPowerCase<TransitionOnToOffVariant>>();
-}
-
-TEST_F(SetPowerModeInternalTest, transitionsDisplayFromDozeSuspendToOffPrimaryDisplay) {
-    transitionDisplayCommon<PrimaryDisplayPowerCase<TransitionDozeSuspendToOffVariant>>();
-}
-
-TEST_F(SetPowerModeInternalTest, transitionsDisplayFromOnToDozePrimaryDisplay) {
-    transitionDisplayCommon<PrimaryDisplayPowerCase<TransitionOnToDozeVariant>>();
-}
-
-TEST_F(SetPowerModeInternalTest, transitionsDisplayFromDozeSuspendToDozePrimaryDisplay) {
-    transitionDisplayCommon<PrimaryDisplayPowerCase<TransitionDozeSuspendToDozeVariant>>();
-}
-
-TEST_F(SetPowerModeInternalTest, transitionsDisplayFromDozeToOnPrimaryDisplay) {
-    transitionDisplayCommon<PrimaryDisplayPowerCase<TransitionDozeToOnVariant>>();
-}
-
-TEST_F(SetPowerModeInternalTest, transitionsDisplayFromDozeSuspendToOnPrimaryDisplay) {
-    transitionDisplayCommon<PrimaryDisplayPowerCase<TransitionDozeSuspendToOnVariant>>();
-}
-
-TEST_F(SetPowerModeInternalTest, transitionsDisplayFromOnToDozeSuspendPrimaryDisplay) {
-    transitionDisplayCommon<PrimaryDisplayPowerCase<TransitionOnToDozeSuspendVariant>>();
-}
-
-TEST_F(SetPowerModeInternalTest, transitionsDisplayFromOnToUnknownPrimaryDisplay) {
-    transitionDisplayCommon<PrimaryDisplayPowerCase<TransitionOnToUnknownVariant>>();
-}
-
-TEST_F(SetPowerModeInternalTest, transitionsDisplayFromOffToOnExternalDisplay) {
-    transitionDisplayCommon<ExternalDisplayPowerCase<TransitionOffToOnVariant>>();
-}
-
-TEST_F(SetPowerModeInternalTest, transitionsDisplayFromOffToDozeSuspendExternalDisplay) {
-    transitionDisplayCommon<ExternalDisplayPowerCase<TransitionOffToDozeSuspendVariant>>();
-}
-
-TEST_F(SetPowerModeInternalTest, transitionsDisplayFromOnToOffExternalDisplay) {
-    transitionDisplayCommon<ExternalDisplayPowerCase<TransitionOnToOffVariant>>();
-}
-
-TEST_F(SetPowerModeInternalTest, transitionsDisplayFromDozeSuspendToOffExternalDisplay) {
-    transitionDisplayCommon<ExternalDisplayPowerCase<TransitionDozeSuspendToOffVariant>>();
-}
-
-TEST_F(SetPowerModeInternalTest, transitionsDisplayFromOnToDozeExternalDisplay) {
-    transitionDisplayCommon<ExternalDisplayPowerCase<TransitionOnToDozeVariant>>();
-}
-
-TEST_F(SetPowerModeInternalTest, transitionsDisplayFromDozeSuspendToDozeExternalDisplay) {
-    transitionDisplayCommon<ExternalDisplayPowerCase<TransitionDozeSuspendToDozeVariant>>();
-}
-
-TEST_F(SetPowerModeInternalTest, transitionsDisplayFromDozeToOnExternalDisplay) {
-    transitionDisplayCommon<ExternalDisplayPowerCase<TransitionDozeToOnVariant>>();
-}
-
-TEST_F(SetPowerModeInternalTest, transitionsDisplayFromDozeSuspendToOnExternalDisplay) {
-    transitionDisplayCommon<ExternalDisplayPowerCase<TransitionDozeSuspendToOnVariant>>();
-}
-
-TEST_F(SetPowerModeInternalTest, transitionsDisplayFromOnToDozeSuspendExternalDisplay) {
-    transitionDisplayCommon<ExternalDisplayPowerCase<TransitionOnToDozeSuspendVariant>>();
-}
-
-TEST_F(SetPowerModeInternalTest, transitionsDisplayFromOnToUnknownExternalDisplay) {
-    transitionDisplayCommon<ExternalDisplayPowerCase<TransitionOnToUnknownVariant>>();
-}
-
-} // namespace
 } // namespace android
-
-// TODO(b/129481165): remove the #pragma below and fix conversion issues
-#pragma clang diagnostic pop // ignored "-Wconversion"
diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h b/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h
new file mode 100644
index 0000000..01cdb28
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h
@@ -0,0 +1,756 @@
+/*
+ * Copyright 2020 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
+
+// TODO(b/129481165): remove the #pragma below and fix conversion issues
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wconversion"
+
+#include <type_traits>
+#include "DisplayIdentificationTest.h"
+
+#include <binder/IPCThreadState.h>
+#include <compositionengine/Display.h>
+#include <compositionengine/DisplayColorProfile.h>
+#include <compositionengine/impl/Display.h>
+#include <compositionengine/impl/OutputCompositionState.h>
+#include <compositionengine/mock/Display.h>
+#include <compositionengine/mock/DisplayColorProfile.h>
+#include <compositionengine/mock/DisplaySurface.h>
+#include <compositionengine/mock/RenderSurface.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <gui/mock/GraphicBufferConsumer.h>
+#include <gui/mock/GraphicBufferProducer.h>
+#include <log/log.h>
+#include <private/android_filesystem_config.h>
+#include <renderengine/mock/RenderEngine.h>
+#include <ui/DebugUtils.h>
+
+#include "TestableScheduler.h"
+#include "TestableSurfaceFlinger.h"
+#include "mock/DisplayHardware/MockComposer.h"
+#include "mock/DisplayHardware/MockPowerAdvisor.h"
+#include "mock/MockEventThread.h"
+#include "mock/MockMessageQueue.h"
+#include "mock/MockNativeWindowSurface.h"
+#include "mock/MockSchedulerCallback.h"
+#include "mock/MockSurfaceInterceptor.h"
+#include "mock/MockVsyncController.h"
+#include "mock/system/window/MockNativeWindow.h"
+
+namespace android {
+
+// TODO: Do not polute the android namespace
+namespace hal = android::hardware::graphics::composer::hal;
+
+using testing::_;
+using testing::AnyNumber;
+using testing::DoAll;
+using testing::Mock;
+using testing::ResultOf;
+using testing::Return;
+using testing::SetArgPointee;
+
+using hal::ColorMode;
+using hal::Connection;
+using hal::DisplayCapability;
+using hal::DisplayType;
+using hal::Error;
+using hal::Hdr;
+using hal::HWDisplayId;
+using hal::IComposer;
+using hal::IComposerClient;
+using hal::PerFrameMetadataKey;
+using hal::PowerMode;
+
+class DisplayTransactionTest : public testing::Test {
+public:
+    ~DisplayTransactionTest() override;
+
+    // --------------------------------------------------------------------
+    // Mock/Fake injection
+
+    void injectMockScheduler();
+    void injectMockComposer(int virtualDisplayCount);
+    void injectFakeBufferQueueFactory();
+    void injectFakeNativeWindowSurfaceFactory();
+    sp<DisplayDevice> injectDefaultInternalDisplay(
+            std::function<void(TestableSurfaceFlinger::FakeDisplayDeviceInjector&)>);
+
+    // --------------------------------------------------------------------
+    // Postcondition helpers
+
+    bool hasPhysicalHwcDisplay(hal::HWDisplayId hwcDisplayId);
+    bool hasTransactionFlagSet(int flag);
+    bool hasDisplayDevice(sp<IBinder> displayToken);
+    sp<DisplayDevice> getDisplayDevice(sp<IBinder> displayToken);
+    bool hasCurrentDisplayState(sp<IBinder> displayToken);
+    const DisplayDeviceState& getCurrentDisplayState(sp<IBinder> displayToken);
+    bool hasDrawingDisplayState(sp<IBinder> displayToken);
+    const DisplayDeviceState& getDrawingDisplayState(sp<IBinder> displayToken);
+
+    // --------------------------------------------------------------------
+    // Test instances
+
+    TestableSurfaceFlinger mFlinger;
+    sp<mock::NativeWindow> mNativeWindow = new mock::NativeWindow();
+    sp<GraphicBuffer> mBuffer = new GraphicBuffer();
+    Hwc2::mock::PowerAdvisor mPowerAdvisor;
+
+    // These mocks are created by the test, but are destroyed by SurfaceFlinger
+    // by virtue of being stored into a std::unique_ptr. However we still need
+    // to keep a reference to them for use in setting up call expectations.
+    renderengine::mock::RenderEngine* mRenderEngine = new renderengine::mock::RenderEngine();
+    Hwc2::mock::Composer* mComposer = nullptr;
+    mock::MessageQueue* mMessageQueue = new mock::MessageQueue();
+    sp<mock::SurfaceInterceptor> mSurfaceInterceptor = new mock::SurfaceInterceptor;
+
+    mock::VsyncController* mVsyncController = new mock::VsyncController;
+    mock::VSyncTracker* mVSyncTracker = new mock::VSyncTracker;
+    mock::SchedulerCallback mSchedulerCallback;
+    mock::EventThread* mEventThread = new mock::EventThread;
+    mock::EventThread* mSFEventThread = new mock::EventThread;
+
+    // These mocks are created only when expected to be created via a factory.
+    sp<mock::GraphicBufferConsumer> mConsumer;
+    sp<mock::GraphicBufferProducer> mProducer;
+    surfaceflinger::mock::NativeWindowSurface* mNativeWindowSurface = nullptr;
+
+protected:
+    DisplayTransactionTest();
+};
+
+constexpr int32_t DEFAULT_REFRESH_RATE = 16'666'667;
+constexpr int32_t DEFAULT_DPI = 320;
+constexpr int DEFAULT_VIRTUAL_DISPLAY_SURFACE_FORMAT = HAL_PIXEL_FORMAT_RGB_565;
+
+constexpr int POWER_MODE_LEET = 1337; // An out of range power mode value
+
+/* ------------------------------------------------------------------------
+ * Boolean avoidance
+ *
+ * To make calls and template instantiations more readable, we define some
+ * local enums along with an implicit bool conversion.
+ */
+
+#define BOOL_SUBSTITUTE(TYPENAME) enum class TYPENAME : bool { FALSE = false, TRUE = true };
+
+BOOL_SUBSTITUTE(Async);
+BOOL_SUBSTITUTE(Critical);
+BOOL_SUBSTITUTE(Primary);
+BOOL_SUBSTITUTE(Secure);
+BOOL_SUBSTITUTE(Virtual);
+
+template <typename PhysicalDisplay>
+struct PhysicalDisplayIdType {};
+
+template <uint64_t displayId>
+using HalVirtualDisplayIdType = std::integral_constant<uint64_t, displayId>;
+
+struct GpuVirtualDisplayIdType {};
+
+template <typename>
+struct IsPhysicalDisplayId : std::bool_constant<false> {};
+
+template <typename PhysicalDisplay>
+struct IsPhysicalDisplayId<PhysicalDisplayIdType<PhysicalDisplay>> : std::bool_constant<true> {};
+
+template <typename>
+struct DisplayIdGetter;
+
+template <typename PhysicalDisplay>
+struct DisplayIdGetter<PhysicalDisplayIdType<PhysicalDisplay>> {
+    static PhysicalDisplayId get() {
+        if (!PhysicalDisplay::HAS_IDENTIFICATION_DATA) {
+            return PhysicalDisplayId::fromPort(static_cast<bool>(PhysicalDisplay::PRIMARY)
+                                                       ? LEGACY_DISPLAY_TYPE_PRIMARY
+                                                       : LEGACY_DISPLAY_TYPE_EXTERNAL);
+        }
+
+        const auto info =
+                parseDisplayIdentificationData(PhysicalDisplay::PORT,
+                                               PhysicalDisplay::GET_IDENTIFICATION_DATA());
+        return info ? info->id : PhysicalDisplayId::fromPort(PhysicalDisplay::PORT);
+    }
+};
+
+template <uint64_t displayId>
+struct DisplayIdGetter<HalVirtualDisplayIdType<displayId>> {
+    static HalVirtualDisplayId get() { return HalVirtualDisplayId(displayId); }
+};
+
+template <>
+struct DisplayIdGetter<GpuVirtualDisplayIdType> {
+    static GpuVirtualDisplayId get() { return GpuVirtualDisplayId(0); }
+};
+
+template <typename>
+struct DisplayConnectionTypeGetter {
+    static constexpr std::optional<DisplayConnectionType> value;
+};
+
+template <typename PhysicalDisplay>
+struct DisplayConnectionTypeGetter<PhysicalDisplayIdType<PhysicalDisplay>> {
+    static constexpr std::optional<DisplayConnectionType> value = PhysicalDisplay::CONNECTION_TYPE;
+};
+
+template <typename>
+struct HwcDisplayIdGetter {
+    static constexpr std::optional<HWDisplayId> value;
+};
+
+constexpr HWDisplayId HWC_VIRTUAL_DISPLAY_HWC_DISPLAY_ID = 1010;
+
+template <uint64_t displayId>
+struct HwcDisplayIdGetter<HalVirtualDisplayIdType<displayId>> {
+    static constexpr std::optional<HWDisplayId> value = HWC_VIRTUAL_DISPLAY_HWC_DISPLAY_ID;
+};
+
+template <typename PhysicalDisplay>
+struct HwcDisplayIdGetter<PhysicalDisplayIdType<PhysicalDisplay>> {
+    static constexpr std::optional<HWDisplayId> value = PhysicalDisplay::HWC_DISPLAY_ID;
+};
+
+// DisplayIdType can be:
+//     1) PhysicalDisplayIdType<...> for generated ID of physical display backed by HWC.
+//     2) HalVirtualDisplayIdType<...> for hard-coded ID of virtual display backed by HWC.
+//     3) GpuVirtualDisplayIdType for virtual display without HWC backing.
+template <typename DisplayIdType, int width, int height, Critical critical, Async async,
+          Secure secure, Primary primary, int grallocUsage>
+struct DisplayVariant {
+    using DISPLAY_ID = DisplayIdGetter<DisplayIdType>;
+    using CONNECTION_TYPE = DisplayConnectionTypeGetter<DisplayIdType>;
+    using HWC_DISPLAY_ID_OPT = HwcDisplayIdGetter<DisplayIdType>;
+
+    // The display width and height
+    static constexpr int WIDTH = width;
+    static constexpr int HEIGHT = height;
+
+    static constexpr int GRALLOC_USAGE = grallocUsage;
+
+    // Whether the display is virtual or physical
+    static constexpr Virtual VIRTUAL =
+            IsPhysicalDisplayId<DisplayIdType>{} ? Virtual::FALSE : Virtual::TRUE;
+
+    // When creating native window surfaces for the framebuffer, whether those should be critical
+    static constexpr Critical CRITICAL = critical;
+
+    // When creating native window surfaces for the framebuffer, whether those should be async
+    static constexpr Async ASYNC = async;
+
+    // Whether the display should be treated as secure
+    static constexpr Secure SECURE = secure;
+
+    // Whether the display is primary
+    static constexpr Primary PRIMARY = primary;
+
+    static auto makeFakeExistingDisplayInjector(DisplayTransactionTest* test) {
+        auto ceDisplayArgs = compositionengine::DisplayCreationArgsBuilder();
+        if (auto displayId = PhysicalDisplayId::tryCast(DISPLAY_ID::get())) {
+            ceDisplayArgs.setPhysical({*displayId, DisplayConnectionType::Internal});
+        } else {
+            // We turn off the use of HwcVirtualDisplays, to prevent Composition Engine
+            // from calling into HWComposer. This way all virtual displays will get
+            // a GpuVirtualDisplayId, even if we are in the HwcVirtualDisplayVariant.
+            // In this case we later override it by calling display.setDisplayIdForTesting().
+            ceDisplayArgs.setUseHwcVirtualDisplays(false);
+
+            GpuVirtualDisplayId desiredDisplayId = GpuVirtualDisplayId::tryCast(DISPLAY_ID::get())
+                                                           .value_or(GpuVirtualDisplayId(0));
+
+            ON_CALL(test->mFlinger.gpuVirtualDisplayIdGenerator(), nextId())
+                    .WillByDefault(Return(desiredDisplayId));
+
+            auto& generator = test->mFlinger.gpuVirtualDisplayIdGenerator();
+            ceDisplayArgs.setGpuVirtualDisplayIdGenerator(generator);
+        }
+        ceDisplayArgs.setPixels({WIDTH, HEIGHT}).setPowerAdvisor(&test->mPowerAdvisor);
+
+        auto compositionDisplay =
+                compositionengine::impl::createDisplay(test->mFlinger.getCompositionEngine(),
+                                                       ceDisplayArgs.build());
+
+        if (HalVirtualDisplayId::tryCast(DISPLAY_ID::get())) {
+            // CompositionEngine has assigned a placeholder GpuVirtualDisplayId and we need to
+            // override it with the correct HalVirtualDisplayId.
+            compositionDisplay->setDisplayIdForTesting(DISPLAY_ID::get());
+        }
+
+        auto injector =
+                TestableSurfaceFlinger::FakeDisplayDeviceInjector(test->mFlinger,
+                                                                  compositionDisplay,
+                                                                  CONNECTION_TYPE::value,
+                                                                  HWC_DISPLAY_ID_OPT::value,
+                                                                  static_cast<bool>(PRIMARY));
+
+        injector.setSecure(static_cast<bool>(SECURE));
+        injector.setNativeWindow(test->mNativeWindow);
+
+        // Creating a DisplayDevice requires getting default dimensions from the
+        // native window along with some other initial setup.
+        EXPECT_CALL(*test->mNativeWindow, query(NATIVE_WINDOW_WIDTH, _))
+                .WillRepeatedly(DoAll(SetArgPointee<1>(WIDTH), Return(0)));
+        EXPECT_CALL(*test->mNativeWindow, query(NATIVE_WINDOW_HEIGHT, _))
+                .WillRepeatedly(DoAll(SetArgPointee<1>(HEIGHT), Return(0)));
+        EXPECT_CALL(*test->mNativeWindow, perform(NATIVE_WINDOW_SET_BUFFERS_FORMAT))
+                .WillRepeatedly(Return(0));
+        EXPECT_CALL(*test->mNativeWindow, perform(NATIVE_WINDOW_API_CONNECT))
+                .WillRepeatedly(Return(0));
+        EXPECT_CALL(*test->mNativeWindow, perform(NATIVE_WINDOW_SET_USAGE64))
+                .WillRepeatedly(Return(0));
+        EXPECT_CALL(*test->mNativeWindow, perform(NATIVE_WINDOW_API_DISCONNECT))
+                .WillRepeatedly(Return(0));
+
+        return injector;
+    }
+
+    // Called by tests to set up any native window creation call expectations.
+    static void setupNativeWindowSurfaceCreationCallExpectations(DisplayTransactionTest* test) {
+        EXPECT_CALL(*test->mNativeWindowSurface, getNativeWindow())
+                .WillOnce(Return(test->mNativeWindow));
+
+        EXPECT_CALL(*test->mNativeWindow, query(NATIVE_WINDOW_WIDTH, _))
+                .WillRepeatedly(DoAll(SetArgPointee<1>(WIDTH), Return(0)));
+        EXPECT_CALL(*test->mNativeWindow, query(NATIVE_WINDOW_HEIGHT, _))
+                .WillRepeatedly(DoAll(SetArgPointee<1>(HEIGHT), Return(0)));
+        EXPECT_CALL(*test->mNativeWindow, perform(NATIVE_WINDOW_SET_BUFFERS_FORMAT))
+                .WillRepeatedly(Return(0));
+        EXPECT_CALL(*test->mNativeWindow, perform(NATIVE_WINDOW_API_CONNECT))
+                .WillRepeatedly(Return(0));
+        EXPECT_CALL(*test->mNativeWindow, perform(NATIVE_WINDOW_SET_USAGE64))
+                .WillRepeatedly(Return(0));
+        EXPECT_CALL(*test->mNativeWindow, perform(NATIVE_WINDOW_API_DISCONNECT))
+                .WillRepeatedly(Return(0));
+    }
+
+    static void setupFramebufferConsumerBufferQueueCallExpectations(DisplayTransactionTest* test) {
+        EXPECT_CALL(*test->mConsumer, consumerConnect(_, false)).WillOnce(Return(NO_ERROR));
+        EXPECT_CALL(*test->mConsumer, setConsumerName(_)).WillRepeatedly(Return(NO_ERROR));
+        EXPECT_CALL(*test->mConsumer, setConsumerUsageBits(GRALLOC_USAGE))
+                .WillRepeatedly(Return(NO_ERROR));
+        EXPECT_CALL(*test->mConsumer, setDefaultBufferSize(WIDTH, HEIGHT))
+                .WillRepeatedly(Return(NO_ERROR));
+        EXPECT_CALL(*test->mConsumer, setMaxAcquiredBufferCount(_))
+                .WillRepeatedly(Return(NO_ERROR));
+    }
+
+    static void setupFramebufferProducerBufferQueueCallExpectations(DisplayTransactionTest* test) {
+        EXPECT_CALL(*test->mProducer, allocateBuffers(0, 0, 0, 0)).WillRepeatedly(Return());
+    }
+};
+
+template <HWDisplayId hwcDisplayId, DisplayType hwcDisplayType, typename DisplayVariant,
+          typename PhysicalDisplay = void>
+struct HwcDisplayVariant {
+    // The display id supplied by the HWC
+    static constexpr HWDisplayId HWC_DISPLAY_ID = hwcDisplayId;
+
+    // The HWC display type
+    static constexpr DisplayType HWC_DISPLAY_TYPE = hwcDisplayType;
+
+    // The HWC active configuration id
+    static constexpr int HWC_ACTIVE_CONFIG_ID = 2001;
+    static constexpr PowerMode INIT_POWER_MODE = hal::PowerMode::ON;
+
+    static void injectPendingHotplugEvent(DisplayTransactionTest* test, Connection connection) {
+        test->mFlinger.mutablePendingHotplugEvents().emplace_back(
+                TestableSurfaceFlinger::HotplugEvent{HWC_DISPLAY_ID, connection});
+    }
+
+    // Called by tests to inject a HWC display setup
+    static void injectHwcDisplayWithNoDefaultCapabilities(DisplayTransactionTest* test) {
+        const auto displayId = DisplayVariant::DISPLAY_ID::get();
+        ASSERT_FALSE(GpuVirtualDisplayId::tryCast(displayId));
+        TestableSurfaceFlinger::FakeHwcDisplayInjector(displayId, HWC_DISPLAY_TYPE,
+                                                       static_cast<bool>(DisplayVariant::PRIMARY))
+                .setHwcDisplayId(HWC_DISPLAY_ID)
+                .setWidth(DisplayVariant::WIDTH)
+                .setHeight(DisplayVariant::HEIGHT)
+                .setActiveConfig(HWC_ACTIVE_CONFIG_ID)
+                .setPowerMode(INIT_POWER_MODE)
+                .inject(&test->mFlinger, test->mComposer);
+    }
+
+    // Called by tests to inject a HWC display setup
+    static void injectHwcDisplay(DisplayTransactionTest* test) {
+        EXPECT_CALL(*test->mComposer, getDisplayCapabilities(HWC_DISPLAY_ID, _))
+                .WillOnce(DoAll(SetArgPointee<1>(std::vector<DisplayCapability>({})),
+                                Return(Error::NONE)));
+        EXPECT_CALL(*test->mComposer, setPowerMode(HWC_DISPLAY_ID, INIT_POWER_MODE))
+                .WillOnce(Return(Error::NONE));
+        injectHwcDisplayWithNoDefaultCapabilities(test);
+    }
+
+    static std::shared_ptr<compositionengine::Display> injectCompositionDisplay(
+            DisplayTransactionTest* test) {
+        const ::testing::TestInfo* const test_info =
+                ::testing::UnitTest::GetInstance()->current_test_info();
+
+        auto ceDisplayArgs = compositionengine::DisplayCreationArgsBuilder()
+                                     .setPhysical({DisplayVariant::DISPLAY_ID::get(),
+                                                   PhysicalDisplay::CONNECTION_TYPE})
+                                     .setPixels({DisplayVariant::WIDTH, DisplayVariant::HEIGHT})
+                                     .setIsSecure(static_cast<bool>(DisplayVariant::SECURE))
+                                     .setPowerAdvisor(&test->mPowerAdvisor)
+                                     .setName(std::string("Injected display for ") +
+                                              test_info->test_case_name() + "." + test_info->name())
+                                     .build();
+
+        return compositionengine::impl::createDisplay(test->mFlinger.getCompositionEngine(),
+                                                      ceDisplayArgs);
+    }
+
+    static void setupHwcHotplugCallExpectations(DisplayTransactionTest* test) {
+        constexpr auto CONNECTION_TYPE =
+                PhysicalDisplay::CONNECTION_TYPE == DisplayConnectionType::Internal
+                ? IComposerClient::DisplayConnectionType::INTERNAL
+                : IComposerClient::DisplayConnectionType::EXTERNAL;
+
+        EXPECT_CALL(*test->mComposer, getDisplayConnectionType(HWC_DISPLAY_ID, _))
+                .WillOnce(DoAll(SetArgPointee<1>(CONNECTION_TYPE), Return(hal::V2_4::Error::NONE)));
+
+        EXPECT_CALL(*test->mComposer, setClientTargetSlotCount(_))
+                .WillOnce(Return(hal::Error::NONE));
+        EXPECT_CALL(*test->mComposer, getDisplayConfigs(HWC_DISPLAY_ID, _))
+                .WillOnce(DoAll(SetArgPointee<1>(std::vector<unsigned>{HWC_ACTIVE_CONFIG_ID}),
+                                Return(Error::NONE)));
+        EXPECT_CALL(*test->mComposer,
+                    getDisplayAttribute(HWC_DISPLAY_ID, HWC_ACTIVE_CONFIG_ID,
+                                        IComposerClient::Attribute::WIDTH, _))
+                .WillOnce(DoAll(SetArgPointee<3>(DisplayVariant::WIDTH), Return(Error::NONE)));
+        EXPECT_CALL(*test->mComposer,
+                    getDisplayAttribute(HWC_DISPLAY_ID, HWC_ACTIVE_CONFIG_ID,
+                                        IComposerClient::Attribute::HEIGHT, _))
+                .WillOnce(DoAll(SetArgPointee<3>(DisplayVariant::HEIGHT), Return(Error::NONE)));
+        EXPECT_CALL(*test->mComposer,
+                    getDisplayAttribute(HWC_DISPLAY_ID, HWC_ACTIVE_CONFIG_ID,
+                                        IComposerClient::Attribute::VSYNC_PERIOD, _))
+                .WillOnce(DoAll(SetArgPointee<3>(DEFAULT_REFRESH_RATE), Return(Error::NONE)));
+        EXPECT_CALL(*test->mComposer,
+                    getDisplayAttribute(HWC_DISPLAY_ID, HWC_ACTIVE_CONFIG_ID,
+                                        IComposerClient::Attribute::DPI_X, _))
+                .WillOnce(DoAll(SetArgPointee<3>(DEFAULT_DPI), Return(Error::NONE)));
+        EXPECT_CALL(*test->mComposer,
+                    getDisplayAttribute(HWC_DISPLAY_ID, HWC_ACTIVE_CONFIG_ID,
+                                        IComposerClient::Attribute::DPI_Y, _))
+                .WillOnce(DoAll(SetArgPointee<3>(DEFAULT_DPI), Return(Error::NONE)));
+        EXPECT_CALL(*test->mComposer,
+                    getDisplayAttribute(HWC_DISPLAY_ID, HWC_ACTIVE_CONFIG_ID,
+                                        IComposerClient::Attribute::CONFIG_GROUP, _))
+                .WillOnce(DoAll(SetArgPointee<3>(-1), Return(Error::NONE)));
+
+        if (PhysicalDisplay::HAS_IDENTIFICATION_DATA) {
+            EXPECT_CALL(*test->mComposer, getDisplayIdentificationData(HWC_DISPLAY_ID, _, _))
+                    .WillOnce(DoAll(SetArgPointee<1>(PhysicalDisplay::PORT),
+                                    SetArgPointee<2>(PhysicalDisplay::GET_IDENTIFICATION_DATA()),
+                                    Return(Error::NONE)));
+        } else {
+            EXPECT_CALL(*test->mComposer, getDisplayIdentificationData(HWC_DISPLAY_ID, _, _))
+                    .WillOnce(Return(Error::UNSUPPORTED));
+        }
+    }
+
+    // Called by tests to set up HWC call expectations
+    static void setupHwcGetActiveConfigCallExpectations(DisplayTransactionTest* test) {
+        EXPECT_CALL(*test->mComposer, getActiveConfig(HWC_DISPLAY_ID, _))
+                .WillRepeatedly(DoAll(SetArgPointee<1>(HWC_ACTIVE_CONFIG_ID), Return(Error::NONE)));
+    }
+};
+
+// Physical displays are expected to be synchronous, secure, and have a HWC display for output.
+constexpr uint32_t GRALLOC_USAGE_PHYSICAL_DISPLAY =
+        GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_COMPOSER | GRALLOC_USAGE_HW_FB;
+
+template <typename PhysicalDisplay, int width, int height, Critical critical>
+struct PhysicalDisplayVariant
+      : DisplayVariant<PhysicalDisplayIdType<PhysicalDisplay>, width, height, critical,
+                       Async::FALSE, Secure::TRUE, PhysicalDisplay::PRIMARY,
+                       GRALLOC_USAGE_PHYSICAL_DISPLAY>,
+        HwcDisplayVariant<PhysicalDisplay::HWC_DISPLAY_ID, DisplayType::PHYSICAL,
+                          DisplayVariant<PhysicalDisplayIdType<PhysicalDisplay>, width, height,
+                                         critical, Async::FALSE, Secure::TRUE,
+                                         PhysicalDisplay::PRIMARY, GRALLOC_USAGE_PHYSICAL_DISPLAY>,
+                          PhysicalDisplay> {};
+
+template <bool hasIdentificationData>
+struct PrimaryDisplay {
+    static constexpr auto CONNECTION_TYPE = DisplayConnectionType::Internal;
+    static constexpr Primary PRIMARY = Primary::TRUE;
+    static constexpr uint8_t PORT = 255;
+    static constexpr HWDisplayId HWC_DISPLAY_ID = 1001;
+    static constexpr bool HAS_IDENTIFICATION_DATA = hasIdentificationData;
+    static constexpr auto GET_IDENTIFICATION_DATA = getInternalEdid;
+};
+
+template <bool hasIdentificationData>
+struct ExternalDisplay {
+    static constexpr auto CONNECTION_TYPE = DisplayConnectionType::External;
+    static constexpr Primary PRIMARY = Primary::FALSE;
+    static constexpr uint8_t PORT = 254;
+    static constexpr HWDisplayId HWC_DISPLAY_ID = 1002;
+    static constexpr bool HAS_IDENTIFICATION_DATA = hasIdentificationData;
+    static constexpr auto GET_IDENTIFICATION_DATA = getExternalEdid;
+};
+
+struct TertiaryDisplay {
+    static constexpr Primary PRIMARY = Primary::FALSE;
+    static constexpr uint8_t PORT = 253;
+    static constexpr HWDisplayId HWC_DISPLAY_ID = 1003;
+    static constexpr auto GET_IDENTIFICATION_DATA = getExternalEdid;
+};
+
+// A primary display is a physical display that is critical
+using PrimaryDisplayVariant =
+        PhysicalDisplayVariant<PrimaryDisplay<false>, 3840, 2160, Critical::TRUE>;
+
+// An external display is physical display that is not critical.
+using ExternalDisplayVariant =
+        PhysicalDisplayVariant<ExternalDisplay<false>, 1920, 1280, Critical::FALSE>;
+
+using TertiaryDisplayVariant = PhysicalDisplayVariant<TertiaryDisplay, 1600, 1200, Critical::FALSE>;
+
+// A virtual display not supported by the HWC.
+constexpr uint32_t GRALLOC_USAGE_NONHWC_VIRTUAL_DISPLAY = 0;
+
+template <int width, int height, Secure secure>
+struct NonHwcVirtualDisplayVariant
+      : DisplayVariant<GpuVirtualDisplayIdType, width, height, Critical::FALSE, Async::TRUE, secure,
+                       Primary::FALSE, GRALLOC_USAGE_NONHWC_VIRTUAL_DISPLAY> {
+    using Base =
+            DisplayVariant<GpuVirtualDisplayIdType, width, height, Critical::FALSE, Async::TRUE,
+                           secure, Primary::FALSE, GRALLOC_USAGE_NONHWC_VIRTUAL_DISPLAY>;
+
+    static void injectHwcDisplay(DisplayTransactionTest*) {}
+
+    static std::shared_ptr<compositionengine::Display> injectCompositionDisplay(
+            DisplayTransactionTest* test) {
+        const ::testing::TestInfo* const test_info =
+                ::testing::UnitTest::GetInstance()->current_test_info();
+
+        ON_CALL(test->mFlinger.gpuVirtualDisplayIdGenerator(), nextId())
+                .WillByDefault(Return(Base::DISPLAY_ID::get()));
+
+        auto ceDisplayArgs = compositionengine::DisplayCreationArgsBuilder()
+                                     .setPixels({Base::WIDTH, Base::HEIGHT})
+                                     .setIsSecure(static_cast<bool>(Base::SECURE))
+                                     .setPowerAdvisor(&test->mPowerAdvisor)
+                                     .setName(std::string("Injected display for ") +
+                                              test_info->test_case_name() + "." + test_info->name())
+                                     .setGpuVirtualDisplayIdGenerator(
+                                             test->mFlinger.gpuVirtualDisplayIdGenerator())
+                                     .build();
+
+        return compositionengine::impl::createDisplay(test->mFlinger.getCompositionEngine(),
+                                                      ceDisplayArgs);
+    }
+
+    static void setupHwcGetActiveConfigCallExpectations(DisplayTransactionTest* test) {
+        EXPECT_CALL(*test->mComposer, getActiveConfig(_, _)).Times(0);
+    }
+
+    static void setupNativeWindowSurfaceCreationCallExpectations(DisplayTransactionTest* test) {
+        Base::setupNativeWindowSurfaceCreationCallExpectations(test);
+        EXPECT_CALL(*test->mNativeWindow, setSwapInterval(0)).Times(1);
+    }
+};
+
+// A virtual display supported by the HWC.
+constexpr uint32_t GRALLOC_USAGE_HWC_VIRTUAL_DISPLAY = GRALLOC_USAGE_HW_COMPOSER;
+
+template <int width, int height, Secure secure>
+struct HwcVirtualDisplayVariant
+      : DisplayVariant<HalVirtualDisplayIdType<42>, width, height, Critical::FALSE, Async::TRUE,
+                       secure, Primary::FALSE, GRALLOC_USAGE_HWC_VIRTUAL_DISPLAY>,
+        HwcDisplayVariant<HWC_VIRTUAL_DISPLAY_HWC_DISPLAY_ID, DisplayType::VIRTUAL,
+                          DisplayVariant<HalVirtualDisplayIdType<42>, width, height,
+                                         Critical::FALSE, Async::TRUE, secure, Primary::FALSE,
+                                         GRALLOC_USAGE_HWC_VIRTUAL_DISPLAY>> {
+    using Base = DisplayVariant<HalVirtualDisplayIdType<42>, width, height, Critical::FALSE,
+                                Async::TRUE, secure, Primary::FALSE, GRALLOC_USAGE_HW_COMPOSER>;
+    using Self = HwcVirtualDisplayVariant<width, height, secure>;
+
+    static std::shared_ptr<compositionengine::Display> injectCompositionDisplay(
+            DisplayTransactionTest* test) {
+        const ::testing::TestInfo* const test_info =
+                ::testing::UnitTest::GetInstance()->current_test_info();
+
+        // In order to prevent compostition engine calling into HWComposer, we
+        // 1. turn off the use of HWC virtual displays,
+        // 2. provide a GpuVirtualDisplayIdGenerator which always returns some fake ID
+        // 3. override the ID by calling setDisplayIdForTesting()
+
+        ON_CALL(test->mFlinger.gpuVirtualDisplayIdGenerator(), nextId())
+                .WillByDefault(Return(GpuVirtualDisplayId(0)));
+
+        auto ceDisplayArgs = compositionengine::DisplayCreationArgsBuilder()
+                                     .setUseHwcVirtualDisplays(false)
+                                     .setPixels({Base::WIDTH, Base::HEIGHT})
+                                     .setIsSecure(static_cast<bool>(Base::SECURE))
+                                     .setPowerAdvisor(&test->mPowerAdvisor)
+                                     .setName(std::string("Injected display for ") +
+                                              test_info->test_case_name() + "." + test_info->name())
+                                     .setGpuVirtualDisplayIdGenerator(
+                                             test->mFlinger.gpuVirtualDisplayIdGenerator())
+                                     .build();
+
+        auto compositionDisplay =
+                compositionengine::impl::createDisplay(test->mFlinger.getCompositionEngine(),
+                                                       ceDisplayArgs);
+        compositionDisplay->setDisplayIdForTesting(Base::DISPLAY_ID::get());
+
+        // Insert display data so that the HWC thinks it created the virtual display.
+        if (const auto displayId = Base::DISPLAY_ID::get();
+            HalVirtualDisplayId::tryCast(displayId)) {
+            test->mFlinger.mutableHwcDisplayData().try_emplace(displayId);
+        }
+
+        return compositionDisplay;
+    }
+
+    static void setupNativeWindowSurfaceCreationCallExpectations(DisplayTransactionTest* test) {
+        Base::setupNativeWindowSurfaceCreationCallExpectations(test);
+        EXPECT_CALL(*test->mNativeWindow, setSwapInterval(0)).Times(1);
+    }
+
+    static void setupHwcVirtualDisplayCreationCallExpectations(DisplayTransactionTest* test) {
+        EXPECT_CALL(*test->mComposer, createVirtualDisplay(Base::WIDTH, Base::HEIGHT, _, _))
+                .WillOnce(DoAll(SetArgPointee<3>(Self::HWC_DISPLAY_ID), Return(Error::NONE)));
+        EXPECT_CALL(*test->mComposer, setClientTargetSlotCount(_)).WillOnce(Return(Error::NONE));
+    }
+};
+
+// For this variant, the display is not a HWC display, so no HDR support should
+// be configured.
+struct NonHwcDisplayHdrSupportVariant {
+    static constexpr bool HDR10_PLUS_SUPPORTED = false;
+    static constexpr bool HDR10_SUPPORTED = false;
+    static constexpr bool HDR_HLG_SUPPORTED = false;
+    static constexpr bool HDR_DOLBY_VISION_SUPPORTED = false;
+    static void setupComposerCallExpectations(DisplayTransactionTest* test) {
+        EXPECT_CALL(*test->mComposer, getHdrCapabilities(_, _, _, _, _)).Times(0);
+    }
+};
+
+// For this variant, the composer should respond with am empty list of HDR
+// modes, so no HDR support should be configured.
+template <typename Display>
+struct HdrNotSupportedVariant {
+    static constexpr bool HDR10_PLUS_SUPPORTED = false;
+    static constexpr bool HDR10_SUPPORTED = false;
+    static constexpr bool HDR_HLG_SUPPORTED = false;
+    static constexpr bool HDR_DOLBY_VISION_SUPPORTED = false;
+    static void setupComposerCallExpectations(DisplayTransactionTest* test) {
+        EXPECT_CALL(*test->mComposer, getHdrCapabilities(Display::HWC_DISPLAY_ID, _, _, _, _))
+                .WillOnce(DoAll(SetArgPointee<1>(std::vector<Hdr>()), Return(Error::NONE)));
+    }
+};
+
+struct NonHwcPerFrameMetadataSupportVariant {
+    static constexpr int PER_FRAME_METADATA_KEYS = 0;
+    static void setupComposerCallExpectations(DisplayTransactionTest* test) {
+        EXPECT_CALL(*test->mComposer, getPerFrameMetadataKeys(_)).Times(0);
+    }
+};
+
+template <typename Display>
+struct NoPerFrameMetadataSupportVariant {
+    static constexpr int PER_FRAME_METADATA_KEYS = 0;
+    static void setupComposerCallExpectations(DisplayTransactionTest* test) {
+        EXPECT_CALL(*test->mComposer, getPerFrameMetadataKeys(Display::HWC_DISPLAY_ID))
+                .WillOnce(Return(std::vector<PerFrameMetadataKey>()));
+    }
+};
+
+// For this variant, SurfaceFlinger should configure itself with wide display
+// support, but the display should respond with an empty list of supported color
+// modes. Wide-color support for the display should not be configured.
+template <typename Display>
+struct WideColorNotSupportedVariant {
+    static constexpr bool WIDE_COLOR_SUPPORTED = false;
+
+    static void injectConfigChange(DisplayTransactionTest* test) {
+        test->mFlinger.mutableUseColorManagement() = true;
+        test->mFlinger.mutableHasWideColorDisplay() = true;
+    }
+
+    static void setupComposerCallExpectations(DisplayTransactionTest* test) {
+        EXPECT_CALL(*test->mComposer, getColorModes(Display::HWC_DISPLAY_ID, _))
+                .WillOnce(DoAll(SetArgPointee<1>(std::vector<ColorMode>()), Return(Error::NONE)));
+        EXPECT_CALL(*test->mComposer, setColorMode(_, _, _)).Times(0);
+    }
+};
+
+// For this variant, SurfaceFlinger should not configure itself with wide
+// display support, so the display should not be configured for wide-color
+// support.
+struct WideColorSupportNotConfiguredVariant {
+    static constexpr bool WIDE_COLOR_SUPPORTED = false;
+
+    static void injectConfigChange(DisplayTransactionTest* test) {
+        test->mFlinger.mutableHasWideColorDisplay() = false;
+        test->mFlinger.mutableUseColorManagement() = false;
+        test->mFlinger.mutableDisplayColorSetting() = DisplayColorSetting::kUnmanaged;
+    }
+
+    static void setupComposerCallExpectations(DisplayTransactionTest* test) {
+        EXPECT_CALL(*test->mComposer, getColorModes(_, _)).Times(0);
+        EXPECT_CALL(*test->mComposer, getRenderIntents(_, _, _)).Times(0);
+        EXPECT_CALL(*test->mComposer, setColorMode(_, _, _)).Times(0);
+    }
+};
+
+/* ------------------------------------------------------------------------
+ * Typical display configurations to test
+ */
+
+template <typename DisplayPolicy, typename WideColorSupportPolicy, typename HdrSupportPolicy,
+          typename PerFrameMetadataSupportPolicy>
+struct Case {
+    using Display = DisplayPolicy;
+    using WideColorSupport = WideColorSupportPolicy;
+    using HdrSupport = HdrSupportPolicy;
+    using PerFrameMetadataSupport = PerFrameMetadataSupportPolicy;
+};
+
+using SimplePrimaryDisplayCase =
+        Case<PrimaryDisplayVariant, WideColorNotSupportedVariant<PrimaryDisplayVariant>,
+             HdrNotSupportedVariant<PrimaryDisplayVariant>,
+             NoPerFrameMetadataSupportVariant<PrimaryDisplayVariant>>;
+using SimpleExternalDisplayCase =
+        Case<ExternalDisplayVariant, WideColorNotSupportedVariant<ExternalDisplayVariant>,
+             HdrNotSupportedVariant<ExternalDisplayVariant>,
+             NoPerFrameMetadataSupportVariant<ExternalDisplayVariant>>;
+using SimpleTertiaryDisplayCase =
+        Case<TertiaryDisplayVariant, WideColorNotSupportedVariant<TertiaryDisplayVariant>,
+             HdrNotSupportedVariant<TertiaryDisplayVariant>,
+             NoPerFrameMetadataSupportVariant<TertiaryDisplayVariant>>;
+
+using NonHwcVirtualDisplayCase =
+        Case<NonHwcVirtualDisplayVariant<1024, 768, Secure::FALSE>,
+             WideColorSupportNotConfiguredVariant, NonHwcDisplayHdrSupportVariant,
+             NonHwcPerFrameMetadataSupportVariant>;
+using SimpleHwcVirtualDisplayVariant = HwcVirtualDisplayVariant<1024, 768, Secure::TRUE>;
+using HwcVirtualDisplayCase =
+        Case<SimpleHwcVirtualDisplayVariant, WideColorSupportNotConfiguredVariant,
+             HdrNotSupportedVariant<SimpleHwcVirtualDisplayVariant>,
+             NoPerFrameMetadataSupportVariant<SimpleHwcVirtualDisplayVariant>>;
+
+} // namespace android
+
+// TODO(b/129481165): remove the #pragma below and fix conversion issues
+#pragma clang diagnostic pop // ignored "-Wconversion"
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_CreateDisplayTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_CreateDisplayTest.cpp
new file mode 100644
index 0000000..2362a31
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_CreateDisplayTest.cpp
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2020 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"
+
+#include "DisplayTransactionTestHelpers.h"
+
+namespace android {
+namespace {
+
+class CreateDisplayTest : public DisplayTransactionTest {};
+
+TEST_F(CreateDisplayTest, createDisplaySetsCurrentStateForNonsecureDisplay) {
+    const String8 name("virtual.test");
+
+    // --------------------------------------------------------------------
+    // Call Expectations
+
+    // The call should notify the interceptor that a display was created.
+    EXPECT_CALL(*mSurfaceInterceptor, saveDisplayCreation(_)).Times(1);
+
+    // --------------------------------------------------------------------
+    // Invocation
+
+    sp<IBinder> displayToken = mFlinger.createDisplay(name, false);
+
+    // --------------------------------------------------------------------
+    // Postconditions
+
+    // The display should have been added to the current state
+    ASSERT_TRUE(hasCurrentDisplayState(displayToken));
+    const auto& display = getCurrentDisplayState(displayToken);
+    EXPECT_TRUE(display.isVirtual());
+    EXPECT_FALSE(display.isSecure);
+    EXPECT_EQ(name.string(), display.displayName);
+
+    // --------------------------------------------------------------------
+    // Cleanup conditions
+
+    // Destroying the display invalidates the display state.
+    EXPECT_CALL(*mMessageQueue, invalidate()).Times(1);
+}
+
+TEST_F(CreateDisplayTest, createDisplaySetsCurrentStateForSecureDisplay) {
+    const String8 name("virtual.test");
+
+    // --------------------------------------------------------------------
+    // Call Expectations
+
+    // The call should notify the interceptor that a display was created.
+    EXPECT_CALL(*mSurfaceInterceptor, saveDisplayCreation(_)).Times(1);
+
+    // --------------------------------------------------------------------
+    // Invocation
+    int64_t oldId = IPCThreadState::self()->clearCallingIdentity();
+    // Set the calling identity to graphics so captureDisplay with secure is allowed.
+    IPCThreadState::self()->restoreCallingIdentity(static_cast<int64_t>(AID_GRAPHICS) << 32 |
+                                                   AID_GRAPHICS);
+    sp<IBinder> displayToken = mFlinger.createDisplay(name, true);
+    IPCThreadState::self()->restoreCallingIdentity(oldId);
+
+    // --------------------------------------------------------------------
+    // Postconditions
+
+    // The display should have been added to the current state
+    ASSERT_TRUE(hasCurrentDisplayState(displayToken));
+    const auto& display = getCurrentDisplayState(displayToken);
+    EXPECT_TRUE(display.isVirtual());
+    EXPECT_TRUE(display.isSecure);
+    EXPECT_EQ(name.string(), display.displayName);
+
+    // --------------------------------------------------------------------
+    // Cleanup conditions
+
+    // Destroying the display invalidates the display state.
+    EXPECT_CALL(*mMessageQueue, invalidate()).Times(1);
+}
+
+} // namespace
+} // namespace android
\ No newline at end of file
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_DestroyDisplayTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_DestroyDisplayTest.cpp
new file mode 100644
index 0000000..0614434
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_DestroyDisplayTest.cpp
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2020 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"
+
+#include "DisplayTransactionTestHelpers.h"
+
+namespace android {
+namespace {
+
+class DestroyDisplayTest : public DisplayTransactionTest {};
+
+TEST_F(DestroyDisplayTest, destroyDisplayClearsCurrentStateForDisplay) {
+    using Case = NonHwcVirtualDisplayCase;
+
+    // --------------------------------------------------------------------
+    // Preconditions
+
+    // A virtual display exists
+    auto existing = Case::Display::makeFakeExistingDisplayInjector(this);
+    existing.inject();
+
+    // --------------------------------------------------------------------
+    // Call Expectations
+
+    // The call should notify the interceptor that a display was created.
+    EXPECT_CALL(*mSurfaceInterceptor, saveDisplayDeletion(_)).Times(1);
+
+    // Destroying the display invalidates the display state.
+    EXPECT_CALL(*mMessageQueue, invalidate()).Times(1);
+
+    // --------------------------------------------------------------------
+    // Invocation
+
+    mFlinger.destroyDisplay(existing.token());
+
+    // --------------------------------------------------------------------
+    // Postconditions
+
+    // The display should have been removed from the current state
+    EXPECT_FALSE(hasCurrentDisplayState(existing.token()));
+
+    // Ths display should still exist in the drawing state
+    EXPECT_TRUE(hasDrawingDisplayState(existing.token()));
+
+    // The display transaction needed flasg should be set
+    EXPECT_TRUE(hasTransactionFlagSet(eDisplayTransactionNeeded));
+}
+
+TEST_F(DestroyDisplayTest, destroyDisplayHandlesUnknownDisplay) {
+    // --------------------------------------------------------------------
+    // Preconditions
+
+    sp<BBinder> displayToken = new BBinder();
+
+    // --------------------------------------------------------------------
+    // Invocation
+
+    mFlinger.destroyDisplay(displayToken);
+}
+
+} // namespace
+} // namespace android
\ No newline at end of file
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_GetDisplayNativePrimariesTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_GetDisplayNativePrimariesTest.cpp
new file mode 100644
index 0000000..0171f1b
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_GetDisplayNativePrimariesTest.cpp
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2020 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"
+
+#include "DisplayTransactionTestHelpers.h"
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+namespace android {
+namespace {
+
+class GetDisplayNativePrimaries : public DisplayTransactionTest {
+public:
+    GetDisplayNativePrimaries();
+    void populateDummyDisplayNativePrimaries(ui::DisplayPrimaries& primaries);
+    void checkDummyDisplayNativePrimaries(const ui::DisplayPrimaries& primaries);
+
+private:
+    static constexpr float mStartingTestValue = 1.0f;
+};
+
+GetDisplayNativePrimaries::GetDisplayNativePrimaries() {
+    SimplePrimaryDisplayCase::Display::injectHwcDisplay(this);
+    injectFakeNativeWindowSurfaceFactory();
+}
+
+void GetDisplayNativePrimaries::populateDummyDisplayNativePrimaries(
+        ui::DisplayPrimaries& primaries) {
+    float startingVal = mStartingTestValue;
+    primaries.red.X = startingVal++;
+    primaries.red.Y = startingVal++;
+    primaries.red.Z = startingVal++;
+    primaries.green.X = startingVal++;
+    primaries.green.Y = startingVal++;
+    primaries.green.Z = startingVal++;
+    primaries.blue.X = startingVal++;
+    primaries.blue.Y = startingVal++;
+    primaries.blue.Z = startingVal++;
+    primaries.white.X = startingVal++;
+    primaries.white.Y = startingVal++;
+    primaries.white.Z = startingVal++;
+}
+
+void GetDisplayNativePrimaries::checkDummyDisplayNativePrimaries(
+        const ui::DisplayPrimaries& primaries) {
+    float startingVal = mStartingTestValue;
+    EXPECT_EQ(primaries.red.X, startingVal++);
+    EXPECT_EQ(primaries.red.Y, startingVal++);
+    EXPECT_EQ(primaries.red.Z, startingVal++);
+    EXPECT_EQ(primaries.green.X, startingVal++);
+    EXPECT_EQ(primaries.green.Y, startingVal++);
+    EXPECT_EQ(primaries.green.Z, startingVal++);
+    EXPECT_EQ(primaries.blue.X, startingVal++);
+    EXPECT_EQ(primaries.blue.Y, startingVal++);
+    EXPECT_EQ(primaries.blue.Z, startingVal++);
+    EXPECT_EQ(primaries.white.X, startingVal++);
+    EXPECT_EQ(primaries.white.Y, startingVal++);
+    EXPECT_EQ(primaries.white.Z, startingVal++);
+}
+
+TEST_F(GetDisplayNativePrimaries, nullDisplayToken) {
+    ui::DisplayPrimaries primaries;
+    EXPECT_EQ(BAD_VALUE, mFlinger.getDisplayNativePrimaries(nullptr, primaries));
+}
+
+TEST_F(GetDisplayNativePrimaries, internalDisplayWithPrimariesData) {
+    auto injector = SimplePrimaryDisplayCase::Display::makeFakeExistingDisplayInjector(this);
+    injector.inject();
+    auto internalDisplayToken = injector.token();
+
+    ui::DisplayPrimaries expectedPrimaries;
+    populateDummyDisplayNativePrimaries(expectedPrimaries);
+    mFlinger.setInternalDisplayPrimaries(expectedPrimaries);
+
+    ui::DisplayPrimaries primaries;
+    EXPECT_EQ(NO_ERROR, mFlinger.getDisplayNativePrimaries(internalDisplayToken, primaries));
+
+    checkDummyDisplayNativePrimaries(primaries);
+}
+
+TEST_F(GetDisplayNativePrimaries, notInternalDisplayToken) {
+    sp<BBinder> notInternalDisplayToken = new BBinder();
+
+    ui::DisplayPrimaries primaries;
+    populateDummyDisplayNativePrimaries(primaries);
+    EXPECT_EQ(NAME_NOT_FOUND,
+              mFlinger.getDisplayNativePrimaries(notInternalDisplayToken, primaries));
+
+    // Check primaries argument wasn't modified in case of failure
+    checkDummyDisplayNativePrimaries(primaries);
+}
+
+} // namespace
+} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_HandleTransactionLockedTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_HandleTransactionLockedTest.cpp
new file mode 100644
index 0000000..cd3f6ab
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_HandleTransactionLockedTest.cpp
@@ -0,0 +1,734 @@
+/*
+ * Copyright 2020 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"
+
+#include "DisplayTransactionTestHelpers.h"
+
+namespace android {
+namespace {
+
+class HandleTransactionLockedTest : public DisplayTransactionTest {
+public:
+    template <typename Case>
+    void setupCommonPreconditions();
+
+    template <typename Case, bool connected>
+    static void expectHotplugReceived(mock::EventThread*);
+
+    template <typename Case>
+    void setupCommonCallExpectationsForConnectProcessing();
+
+    template <typename Case>
+    void setupCommonCallExpectationsForDisconnectProcessing();
+
+    template <typename Case>
+    void processesHotplugConnectCommon();
+
+    template <typename Case>
+    void ignoresHotplugConnectCommon();
+
+    template <typename Case>
+    void processesHotplugDisconnectCommon();
+
+    template <typename Case>
+    void verifyDisplayIsConnected(const sp<IBinder>& displayToken);
+
+    template <typename Case>
+    void verifyPhysicalDisplayIsConnected();
+
+    void verifyDisplayIsNotConnected(const sp<IBinder>& displayToken);
+};
+
+template <typename Case>
+void HandleTransactionLockedTest::setupCommonPreconditions() {
+    // Wide color displays support is configured appropriately
+    Case::WideColorSupport::injectConfigChange(this);
+
+    // SurfaceFlinger will use a test-controlled factory for BufferQueues
+    injectFakeBufferQueueFactory();
+
+    // SurfaceFlinger will use a test-controlled factory for native window
+    // surfaces.
+    injectFakeNativeWindowSurfaceFactory();
+}
+
+template <typename Case, bool connected>
+void HandleTransactionLockedTest::expectHotplugReceived(mock::EventThread* eventThread) {
+    const auto convert = [](auto physicalDisplayId) {
+        return std::make_optional(DisplayId{physicalDisplayId});
+    };
+
+    EXPECT_CALL(*eventThread,
+                onHotplugReceived(ResultOf(convert, Case::Display::DISPLAY_ID::get()), connected))
+            .Times(1);
+}
+
+template <typename Case>
+void HandleTransactionLockedTest::setupCommonCallExpectationsForConnectProcessing() {
+    Case::Display::setupHwcHotplugCallExpectations(this);
+
+    Case::Display::setupFramebufferConsumerBufferQueueCallExpectations(this);
+    Case::Display::setupFramebufferProducerBufferQueueCallExpectations(this);
+    Case::Display::setupNativeWindowSurfaceCreationCallExpectations(this);
+    Case::Display::setupHwcGetActiveConfigCallExpectations(this);
+
+    Case::WideColorSupport::setupComposerCallExpectations(this);
+    Case::HdrSupport::setupComposerCallExpectations(this);
+    Case::PerFrameMetadataSupport::setupComposerCallExpectations(this);
+
+    EXPECT_CALL(*mSurfaceInterceptor, saveDisplayCreation(_)).Times(1);
+    expectHotplugReceived<Case, true>(mEventThread);
+    expectHotplugReceived<Case, true>(mSFEventThread);
+}
+
+template <typename Case>
+void HandleTransactionLockedTest::setupCommonCallExpectationsForDisconnectProcessing() {
+    EXPECT_CALL(*mSurfaceInterceptor, saveDisplayDeletion(_)).Times(1);
+
+    expectHotplugReceived<Case, false>(mEventThread);
+    expectHotplugReceived<Case, false>(mSFEventThread);
+}
+
+template <typename Case>
+void HandleTransactionLockedTest::verifyDisplayIsConnected(const sp<IBinder>& displayToken) {
+    // The display device should have been set up in the list of displays.
+    ASSERT_TRUE(hasDisplayDevice(displayToken));
+    const auto& device = getDisplayDevice(displayToken);
+    EXPECT_EQ(static_cast<bool>(Case::Display::SECURE), device->isSecure());
+    EXPECT_EQ(static_cast<bool>(Case::Display::PRIMARY), device->isPrimary());
+
+    std::optional<DisplayDeviceState::Physical> expectedPhysical;
+    if (const auto connectionType = Case::Display::CONNECTION_TYPE::value) {
+        const auto displayId = PhysicalDisplayId::tryCast(Case::Display::DISPLAY_ID::get());
+        ASSERT_TRUE(displayId);
+        const auto hwcDisplayId = Case::Display::HWC_DISPLAY_ID_OPT::value;
+        ASSERT_TRUE(hwcDisplayId);
+        expectedPhysical = {.id = *displayId,
+                            .type = *connectionType,
+                            .hwcDisplayId = *hwcDisplayId};
+    }
+
+    // The display should have been set up in the current display state
+    ASSERT_TRUE(hasCurrentDisplayState(displayToken));
+    const auto& current = getCurrentDisplayState(displayToken);
+    EXPECT_EQ(static_cast<bool>(Case::Display::VIRTUAL), current.isVirtual());
+    EXPECT_EQ(expectedPhysical, current.physical);
+
+    // The display should have been set up in the drawing display state
+    ASSERT_TRUE(hasDrawingDisplayState(displayToken));
+    const auto& draw = getDrawingDisplayState(displayToken);
+    EXPECT_EQ(static_cast<bool>(Case::Display::VIRTUAL), draw.isVirtual());
+    EXPECT_EQ(expectedPhysical, draw.physical);
+}
+
+template <typename Case>
+void HandleTransactionLockedTest::verifyPhysicalDisplayIsConnected() {
+    // HWComposer should have an entry for the display
+    EXPECT_TRUE(hasPhysicalHwcDisplay(Case::Display::HWC_DISPLAY_ID));
+
+    // SF should have a display token.
+    const auto displayId = Case::Display::DISPLAY_ID::get();
+    ASSERT_TRUE(PhysicalDisplayId::tryCast(displayId));
+    ASSERT_TRUE(mFlinger.mutablePhysicalDisplayTokens().count(displayId) == 1);
+    auto& displayToken = mFlinger.mutablePhysicalDisplayTokens()[displayId];
+
+    verifyDisplayIsConnected<Case>(displayToken);
+}
+
+void HandleTransactionLockedTest::verifyDisplayIsNotConnected(const sp<IBinder>& displayToken) {
+    EXPECT_FALSE(hasDisplayDevice(displayToken));
+    EXPECT_FALSE(hasCurrentDisplayState(displayToken));
+    EXPECT_FALSE(hasDrawingDisplayState(displayToken));
+}
+
+template <typename Case>
+void HandleTransactionLockedTest::processesHotplugConnectCommon() {
+    // --------------------------------------------------------------------
+    // Preconditions
+
+    setupCommonPreconditions<Case>();
+
+    // A hotplug connect event is enqueued for a display
+    Case::Display::injectPendingHotplugEvent(this, Connection::CONNECTED);
+
+    // --------------------------------------------------------------------
+    // Call Expectations
+
+    setupCommonCallExpectationsForConnectProcessing<Case>();
+
+    // --------------------------------------------------------------------
+    // Invocation
+
+    mFlinger.handleTransactionLocked(eDisplayTransactionNeeded);
+
+    // --------------------------------------------------------------------
+    // Postconditions
+
+    verifyPhysicalDisplayIsConnected<Case>();
+
+    // --------------------------------------------------------------------
+    // Cleanup conditions
+
+    EXPECT_CALL(*mComposer,
+                setVsyncEnabled(Case::Display::HWC_DISPLAY_ID, IComposerClient::Vsync::DISABLE))
+            .WillOnce(Return(Error::NONE));
+    EXPECT_CALL(*mConsumer, consumerDisconnect()).WillOnce(Return(NO_ERROR));
+}
+
+template <typename Case>
+void HandleTransactionLockedTest::ignoresHotplugConnectCommon() {
+    // --------------------------------------------------------------------
+    // Preconditions
+
+    setupCommonPreconditions<Case>();
+
+    // A hotplug connect event is enqueued for a display
+    Case::Display::injectPendingHotplugEvent(this, Connection::CONNECTED);
+
+    // --------------------------------------------------------------------
+    // Invocation
+
+    mFlinger.handleTransactionLocked(eDisplayTransactionNeeded);
+
+    // --------------------------------------------------------------------
+    // Postconditions
+
+    // HWComposer should not have an entry for the display
+    EXPECT_FALSE(hasPhysicalHwcDisplay(Case::Display::HWC_DISPLAY_ID));
+}
+
+template <typename Case>
+void HandleTransactionLockedTest::processesHotplugDisconnectCommon() {
+    // --------------------------------------------------------------------
+    // Preconditions
+
+    setupCommonPreconditions<Case>();
+
+    // A hotplug disconnect event is enqueued for a display
+    Case::Display::injectPendingHotplugEvent(this, Connection::DISCONNECTED);
+
+    // The display is already completely set up.
+    Case::Display::injectHwcDisplay(this);
+    auto existing = Case::Display::makeFakeExistingDisplayInjector(this);
+    existing.inject();
+
+    // --------------------------------------------------------------------
+    // Call Expectations
+
+    EXPECT_CALL(*mComposer, getDisplayIdentificationData(Case::Display::HWC_DISPLAY_ID, _, _))
+            .Times(0);
+
+    setupCommonCallExpectationsForDisconnectProcessing<Case>();
+
+    // --------------------------------------------------------------------
+    // Invocation
+
+    mFlinger.handleTransactionLocked(eDisplayTransactionNeeded);
+
+    // --------------------------------------------------------------------
+    // Postconditions
+
+    // HWComposer should not have an entry for the display
+    EXPECT_FALSE(hasPhysicalHwcDisplay(Case::Display::HWC_DISPLAY_ID));
+
+    // SF should not have a display token.
+    const auto displayId = Case::Display::DISPLAY_ID::get();
+    ASSERT_TRUE(PhysicalDisplayId::tryCast(displayId));
+    ASSERT_TRUE(mFlinger.mutablePhysicalDisplayTokens().count(displayId) == 0);
+
+    // The existing token should have been removed
+    verifyDisplayIsNotConnected(existing.token());
+}
+
+TEST_F(HandleTransactionLockedTest, processesHotplugConnectPrimaryDisplay) {
+    processesHotplugConnectCommon<SimplePrimaryDisplayCase>();
+}
+
+TEST_F(HandleTransactionLockedTest,
+       processesHotplugConnectPrimaryDisplayWithExternalAlreadyConnected) {
+    // Inject an external display.
+    ExternalDisplayVariant::injectHwcDisplay(this);
+
+    processesHotplugConnectCommon<SimplePrimaryDisplayCase>();
+}
+
+TEST_F(HandleTransactionLockedTest, processesHotplugConnectExternalDisplay) {
+    // Inject a primary display.
+    PrimaryDisplayVariant::injectHwcDisplay(this);
+
+    processesHotplugConnectCommon<SimpleExternalDisplayCase>();
+}
+
+TEST_F(HandleTransactionLockedTest, ignoresHotplugConnectIfPrimaryAndExternalAlreadyConnected) {
+    // Inject both a primary and external display.
+    PrimaryDisplayVariant::injectHwcDisplay(this);
+    ExternalDisplayVariant::injectHwcDisplay(this);
+
+    // TODO: This is an unnecessary call.
+    EXPECT_CALL(*mComposer,
+                getDisplayIdentificationData(TertiaryDisplayVariant::HWC_DISPLAY_ID, _, _))
+            .WillOnce(DoAll(SetArgPointee<1>(TertiaryDisplay::PORT),
+                            SetArgPointee<2>(TertiaryDisplay::GET_IDENTIFICATION_DATA()),
+                            Return(Error::NONE)));
+
+    ignoresHotplugConnectCommon<SimpleTertiaryDisplayCase>();
+}
+
+TEST_F(HandleTransactionLockedTest, processesHotplugDisconnectPrimaryDisplay) {
+    processesHotplugDisconnectCommon<SimplePrimaryDisplayCase>();
+}
+
+TEST_F(HandleTransactionLockedTest, processesHotplugDisconnectExternalDisplay) {
+    processesHotplugDisconnectCommon<SimpleExternalDisplayCase>();
+}
+
+TEST_F(HandleTransactionLockedTest, processesHotplugConnectThenDisconnectPrimary) {
+    using Case = SimplePrimaryDisplayCase;
+
+    // --------------------------------------------------------------------
+    // Preconditions
+
+    setupCommonPreconditions<Case>();
+
+    // A hotplug connect event is enqueued for a display
+    Case::Display::injectPendingHotplugEvent(this, Connection::CONNECTED);
+    // A hotplug disconnect event is also enqueued for the same display
+    Case::Display::injectPendingHotplugEvent(this, Connection::DISCONNECTED);
+
+    // --------------------------------------------------------------------
+    // Call Expectations
+
+    setupCommonCallExpectationsForConnectProcessing<Case>();
+    setupCommonCallExpectationsForDisconnectProcessing<Case>();
+
+    EXPECT_CALL(*mComposer,
+                setVsyncEnabled(Case::Display::HWC_DISPLAY_ID, IComposerClient::Vsync::DISABLE))
+            .WillOnce(Return(Error::NONE));
+    EXPECT_CALL(*mConsumer, consumerDisconnect()).WillOnce(Return(NO_ERROR));
+
+    // --------------------------------------------------------------------
+    // Invocation
+
+    mFlinger.handleTransactionLocked(eDisplayTransactionNeeded);
+
+    // --------------------------------------------------------------------
+    // Postconditions
+
+    // HWComposer should not have an entry for the display
+    EXPECT_FALSE(hasPhysicalHwcDisplay(Case::Display::HWC_DISPLAY_ID));
+
+    // SF should not have a display token.
+    const auto displayId = Case::Display::DISPLAY_ID::get();
+    ASSERT_TRUE(PhysicalDisplayId::tryCast(displayId));
+    ASSERT_TRUE(mFlinger.mutablePhysicalDisplayTokens().count(displayId) == 0);
+}
+
+TEST_F(HandleTransactionLockedTest, processesHotplugDisconnectThenConnectPrimary) {
+    using Case = SimplePrimaryDisplayCase;
+
+    // --------------------------------------------------------------------
+    // Preconditions
+
+    setupCommonPreconditions<Case>();
+
+    // The display is already completely set up.
+    Case::Display::injectHwcDisplay(this);
+    auto existing = Case::Display::makeFakeExistingDisplayInjector(this);
+    existing.inject();
+
+    // A hotplug disconnect event is enqueued for a display
+    Case::Display::injectPendingHotplugEvent(this, Connection::DISCONNECTED);
+    // A hotplug connect event is also enqueued for the same display
+    Case::Display::injectPendingHotplugEvent(this, Connection::CONNECTED);
+
+    // --------------------------------------------------------------------
+    // Call Expectations
+
+    setupCommonCallExpectationsForConnectProcessing<Case>();
+    setupCommonCallExpectationsForDisconnectProcessing<Case>();
+
+    // --------------------------------------------------------------------
+    // Invocation
+
+    mFlinger.handleTransactionLocked(eDisplayTransactionNeeded);
+
+    // --------------------------------------------------------------------
+    // Postconditions
+
+    // The existing token should have been removed
+    verifyDisplayIsNotConnected(existing.token());
+    const auto displayId = Case::Display::DISPLAY_ID::get();
+    ASSERT_TRUE(PhysicalDisplayId::tryCast(displayId));
+    ASSERT_TRUE(mFlinger.mutablePhysicalDisplayTokens().count(displayId) == 1);
+    EXPECT_NE(existing.token(), mFlinger.mutablePhysicalDisplayTokens()[displayId]);
+
+    // A new display should be connected in its place
+
+    verifyPhysicalDisplayIsConnected<Case>();
+
+    // --------------------------------------------------------------------
+    // Cleanup conditions
+
+    EXPECT_CALL(*mComposer,
+                setVsyncEnabled(Case::Display::HWC_DISPLAY_ID, IComposerClient::Vsync::DISABLE))
+            .WillOnce(Return(Error::NONE));
+    EXPECT_CALL(*mConsumer, consumerDisconnect()).WillOnce(Return(NO_ERROR));
+}
+
+TEST_F(HandleTransactionLockedTest, processesVirtualDisplayAdded) {
+    using Case = HwcVirtualDisplayCase;
+
+    // --------------------------------------------------------------------
+    // Preconditions
+
+    // The HWC supports at least one virtual display
+    injectMockComposer(1);
+
+    setupCommonPreconditions<Case>();
+
+    // A virtual display was added to the current state, and it has a
+    // surface(producer)
+    sp<BBinder> displayToken = new BBinder();
+
+    DisplayDeviceState state;
+    state.isSecure = static_cast<bool>(Case::Display::SECURE);
+
+    sp<mock::GraphicBufferProducer> surface{new mock::GraphicBufferProducer()};
+    state.surface = surface;
+    mFlinger.mutableCurrentState().displays.add(displayToken, state);
+
+    // --------------------------------------------------------------------
+    // Call Expectations
+
+    Case::Display::setupFramebufferConsumerBufferQueueCallExpectations(this);
+    Case::Display::setupNativeWindowSurfaceCreationCallExpectations(this);
+
+    EXPECT_CALL(*surface, query(NATIVE_WINDOW_WIDTH, _))
+            .WillRepeatedly(DoAll(SetArgPointee<1>(Case::Display::WIDTH), Return(NO_ERROR)));
+    EXPECT_CALL(*surface, query(NATIVE_WINDOW_HEIGHT, _))
+            .WillRepeatedly(DoAll(SetArgPointee<1>(Case::Display::HEIGHT), Return(NO_ERROR)));
+    EXPECT_CALL(*surface, query(NATIVE_WINDOW_FORMAT, _))
+            .WillRepeatedly(DoAll(SetArgPointee<1>(DEFAULT_VIRTUAL_DISPLAY_SURFACE_FORMAT),
+                                  Return(NO_ERROR)));
+    EXPECT_CALL(*surface, query(NATIVE_WINDOW_CONSUMER_USAGE_BITS, _))
+            .WillRepeatedly(DoAll(SetArgPointee<1>(0), Return(NO_ERROR)));
+
+    EXPECT_CALL(*surface, setAsyncMode(true)).Times(1);
+
+    EXPECT_CALL(*mProducer, connect(_, NATIVE_WINDOW_API_EGL, false, _)).Times(1);
+    EXPECT_CALL(*mProducer, disconnect(_, _)).Times(1);
+
+    Case::Display::setupHwcVirtualDisplayCreationCallExpectations(this);
+    Case::WideColorSupport::setupComposerCallExpectations(this);
+    Case::HdrSupport::setupComposerCallExpectations(this);
+    Case::PerFrameMetadataSupport::setupComposerCallExpectations(this);
+
+    // --------------------------------------------------------------------
+    // Invocation
+
+    mFlinger.handleTransactionLocked(eDisplayTransactionNeeded);
+
+    // --------------------------------------------------------------------
+    // Postconditions
+
+    // The display device should have been set up in the list of displays.
+    verifyDisplayIsConnected<Case>(displayToken);
+
+    // --------------------------------------------------------------------
+    // Cleanup conditions
+
+    EXPECT_CALL(*mComposer, destroyVirtualDisplay(Case::Display::HWC_DISPLAY_ID))
+            .WillOnce(Return(Error::NONE));
+    EXPECT_CALL(*mConsumer, consumerDisconnect()).WillOnce(Return(NO_ERROR));
+
+    // Cleanup
+    mFlinger.mutableCurrentState().displays.removeItem(displayToken);
+    mFlinger.mutableDrawingState().displays.removeItem(displayToken);
+}
+
+TEST_F(HandleTransactionLockedTest, processesVirtualDisplayAddedWithNoSurface) {
+    using Case = HwcVirtualDisplayCase;
+
+    // --------------------------------------------------------------------
+    // Preconditions
+
+    // The HWC supports at least one virtual display
+    injectMockComposer(1);
+
+    setupCommonPreconditions<Case>();
+
+    // A virtual display was added to the current state, but it does not have a
+    // surface.
+    sp<BBinder> displayToken = new BBinder();
+
+    DisplayDeviceState state;
+    state.isSecure = static_cast<bool>(Case::Display::SECURE);
+
+    mFlinger.mutableCurrentState().displays.add(displayToken, state);
+
+    // --------------------------------------------------------------------
+    // Call Expectations
+
+    // --------------------------------------------------------------------
+    // Invocation
+
+    mFlinger.handleTransactionLocked(eDisplayTransactionNeeded);
+
+    // --------------------------------------------------------------------
+    // Postconditions
+
+    // There will not be a display device set up.
+    EXPECT_FALSE(hasDisplayDevice(displayToken));
+
+    // The drawing display state will be set from the current display state.
+    ASSERT_TRUE(hasDrawingDisplayState(displayToken));
+    const auto& draw = getDrawingDisplayState(displayToken);
+    EXPECT_EQ(static_cast<bool>(Case::Display::VIRTUAL), draw.isVirtual());
+}
+
+TEST_F(HandleTransactionLockedTest, processesVirtualDisplayRemoval) {
+    using Case = HwcVirtualDisplayCase;
+
+    // --------------------------------------------------------------------
+    // Preconditions
+
+    // A virtual display is set up but is removed from the current state.
+    const auto displayId = Case::Display::DISPLAY_ID::get();
+    ASSERT_TRUE(HalVirtualDisplayId::tryCast(displayId));
+    mFlinger.mutableHwcDisplayData().try_emplace(displayId);
+    Case::Display::injectHwcDisplay(this);
+    auto existing = Case::Display::makeFakeExistingDisplayInjector(this);
+    existing.inject();
+    mFlinger.mutableCurrentState().displays.removeItem(existing.token());
+
+    // --------------------------------------------------------------------
+    // Invocation
+
+    mFlinger.handleTransactionLocked(eDisplayTransactionNeeded);
+
+    // --------------------------------------------------------------------
+    // Postconditions
+
+    // The existing token should have been removed
+    verifyDisplayIsNotConnected(existing.token());
+}
+
+TEST_F(HandleTransactionLockedTest, processesDisplayLayerStackChanges) {
+    using Case = NonHwcVirtualDisplayCase;
+
+    constexpr uint32_t oldLayerStack = 0u;
+    constexpr uint32_t newLayerStack = 123u;
+
+    // --------------------------------------------------------------------
+    // Preconditions
+
+    // A display is set up
+    auto display = Case::Display::makeFakeExistingDisplayInjector(this);
+    display.inject();
+
+    // There is a change to the layerStack state
+    display.mutableDrawingDisplayState().layerStack = oldLayerStack;
+    display.mutableCurrentDisplayState().layerStack = newLayerStack;
+
+    // --------------------------------------------------------------------
+    // Invocation
+
+    mFlinger.handleTransactionLocked(eDisplayTransactionNeeded);
+
+    // --------------------------------------------------------------------
+    // Postconditions
+
+    EXPECT_EQ(newLayerStack, display.mutableDisplayDevice()->getLayerStack());
+}
+
+TEST_F(HandleTransactionLockedTest, processesDisplayTransformChanges) {
+    using Case = NonHwcVirtualDisplayCase;
+
+    constexpr ui::Rotation oldTransform = ui::ROTATION_0;
+    constexpr ui::Rotation newTransform = ui::ROTATION_180;
+
+    // --------------------------------------------------------------------
+    // Preconditions
+
+    // A display is set up
+    auto display = Case::Display::makeFakeExistingDisplayInjector(this);
+    display.inject();
+
+    // There is a change to the orientation state
+    display.mutableDrawingDisplayState().orientation = oldTransform;
+    display.mutableCurrentDisplayState().orientation = newTransform;
+
+    // --------------------------------------------------------------------
+    // Invocation
+
+    mFlinger.handleTransactionLocked(eDisplayTransactionNeeded);
+
+    // --------------------------------------------------------------------
+    // Postconditions
+
+    EXPECT_EQ(newTransform, display.mutableDisplayDevice()->getOrientation());
+}
+
+TEST_F(HandleTransactionLockedTest, processesDisplayLayerStackRectChanges) {
+    using Case = NonHwcVirtualDisplayCase;
+
+    const Rect oldLayerStackRect(0, 0, 0, 0);
+    const Rect newLayerStackRect(0, 0, 123, 456);
+
+    // --------------------------------------------------------------------
+    // Preconditions
+
+    // A display is set up
+    auto display = Case::Display::makeFakeExistingDisplayInjector(this);
+    display.inject();
+
+    // There is a change to the layerStackSpaceRect state
+    display.mutableDrawingDisplayState().layerStackSpaceRect = oldLayerStackRect;
+    display.mutableCurrentDisplayState().layerStackSpaceRect = newLayerStackRect;
+
+    // --------------------------------------------------------------------
+    // Invocation
+
+    mFlinger.handleTransactionLocked(eDisplayTransactionNeeded);
+
+    // --------------------------------------------------------------------
+    // Postconditions
+
+    EXPECT_EQ(newLayerStackRect, display.mutableDisplayDevice()->getLayerStackSpaceRect());
+}
+
+TEST_F(HandleTransactionLockedTest, processesDisplayFrameChanges) {
+    using Case = NonHwcVirtualDisplayCase;
+
+    const Rect oldFrame(0, 0, 0, 0);
+    const Rect newFrame(0, 0, 123, 456);
+
+    // --------------------------------------------------------------------
+    // Preconditions
+
+    // A display is set up
+    auto display = Case::Display::makeFakeExistingDisplayInjector(this);
+    display.inject();
+
+    // There is a change to the layerStackSpaceRect state
+    display.mutableDrawingDisplayState().orientedDisplaySpaceRect = oldFrame;
+    display.mutableCurrentDisplayState().orientedDisplaySpaceRect = newFrame;
+
+    // --------------------------------------------------------------------
+    // Invocation
+
+    mFlinger.handleTransactionLocked(eDisplayTransactionNeeded);
+
+    // --------------------------------------------------------------------
+    // Postconditions
+
+    EXPECT_EQ(newFrame, display.mutableDisplayDevice()->getOrientedDisplaySpaceRect());
+}
+
+TEST_F(HandleTransactionLockedTest, processesDisplayWidthChanges) {
+    using Case = NonHwcVirtualDisplayCase;
+
+    constexpr int oldWidth = 0;
+    constexpr int oldHeight = 10;
+    constexpr int newWidth = 123;
+
+    // --------------------------------------------------------------------
+    // Preconditions
+
+    // A display is set up
+    auto nativeWindow = new mock::NativeWindow();
+    auto displaySurface = new compositionengine::mock::DisplaySurface();
+    sp<GraphicBuffer> buf = new GraphicBuffer();
+    auto display = Case::Display::makeFakeExistingDisplayInjector(this);
+    display.setNativeWindow(nativeWindow);
+    display.setDisplaySurface(displaySurface);
+    // Setup injection expectations
+    EXPECT_CALL(*nativeWindow, query(NATIVE_WINDOW_WIDTH, _))
+            .WillOnce(DoAll(SetArgPointee<1>(oldWidth), Return(0)));
+    EXPECT_CALL(*nativeWindow, query(NATIVE_WINDOW_HEIGHT, _))
+            .WillOnce(DoAll(SetArgPointee<1>(oldHeight), Return(0)));
+    EXPECT_CALL(*nativeWindow, perform(NATIVE_WINDOW_SET_BUFFERS_FORMAT)).Times(1);
+    EXPECT_CALL(*nativeWindow, perform(NATIVE_WINDOW_API_CONNECT)).Times(1);
+    EXPECT_CALL(*nativeWindow, perform(NATIVE_WINDOW_SET_USAGE64)).Times(1);
+    EXPECT_CALL(*nativeWindow, perform(NATIVE_WINDOW_API_DISCONNECT)).Times(1);
+    display.inject();
+
+    // There is a change to the layerStackSpaceRect state
+    display.mutableDrawingDisplayState().width = oldWidth;
+    display.mutableDrawingDisplayState().height = oldHeight;
+    display.mutableCurrentDisplayState().width = newWidth;
+    display.mutableCurrentDisplayState().height = oldHeight;
+
+    // --------------------------------------------------------------------
+    // Call Expectations
+
+    EXPECT_CALL(*displaySurface, resizeBuffers(newWidth, oldHeight)).Times(1);
+
+    // --------------------------------------------------------------------
+    // Invocation
+
+    mFlinger.handleTransactionLocked(eDisplayTransactionNeeded);
+}
+
+TEST_F(HandleTransactionLockedTest, processesDisplayHeightChanges) {
+    using Case = NonHwcVirtualDisplayCase;
+
+    constexpr int oldWidth = 0;
+    constexpr int oldHeight = 10;
+    constexpr int newHeight = 123;
+
+    // --------------------------------------------------------------------
+    // Preconditions
+
+    // A display is set up
+    auto nativeWindow = new mock::NativeWindow();
+    auto displaySurface = new compositionengine::mock::DisplaySurface();
+    sp<GraphicBuffer> buf = new GraphicBuffer();
+    auto display = Case::Display::makeFakeExistingDisplayInjector(this);
+    display.setNativeWindow(nativeWindow);
+    display.setDisplaySurface(displaySurface);
+    // Setup injection expectations
+    EXPECT_CALL(*nativeWindow, query(NATIVE_WINDOW_WIDTH, _))
+            .WillOnce(DoAll(SetArgPointee<1>(oldWidth), Return(0)));
+    EXPECT_CALL(*nativeWindow, query(NATIVE_WINDOW_HEIGHT, _))
+            .WillOnce(DoAll(SetArgPointee<1>(oldHeight), Return(0)));
+    EXPECT_CALL(*nativeWindow, perform(NATIVE_WINDOW_SET_BUFFERS_FORMAT)).Times(1);
+    EXPECT_CALL(*nativeWindow, perform(NATIVE_WINDOW_API_CONNECT)).Times(1);
+    EXPECT_CALL(*nativeWindow, perform(NATIVE_WINDOW_SET_USAGE64)).Times(1);
+    EXPECT_CALL(*nativeWindow, perform(NATIVE_WINDOW_API_DISCONNECT)).Times(1);
+    display.inject();
+
+    // There is a change to the layerStackSpaceRect state
+    display.mutableDrawingDisplayState().width = oldWidth;
+    display.mutableDrawingDisplayState().height = oldHeight;
+    display.mutableCurrentDisplayState().width = oldWidth;
+    display.mutableCurrentDisplayState().height = newHeight;
+
+    // --------------------------------------------------------------------
+    // Call Expectations
+
+    EXPECT_CALL(*displaySurface, resizeBuffers(oldWidth, newHeight)).Times(1);
+
+    // --------------------------------------------------------------------
+    // Invocation
+
+    mFlinger.handleTransactionLocked(eDisplayTransactionNeeded);
+}
+
+} // namespace
+} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_NotifyPowerBoostTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_NotifyPowerBoostTest.cpp
new file mode 100644
index 0000000..69e0501
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_NotifyPowerBoostTest.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2020 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"
+
+#include "DisplayTransactionTestHelpers.h"
+
+#include <android/hardware/power/Boost.h>
+
+namespace android {
+namespace {
+
+using android::hardware::power::Boost;
+
+TEST_F(DisplayTransactionTest, notifyPowerBoostNotifiesTouchEvent) {
+    mFlinger.scheduler()->replaceTouchTimer(100);
+    std::this_thread::sleep_for(10ms);                  // wait for callback to be triggered
+    EXPECT_TRUE(mFlinger.scheduler()->isTouchActive()); // Starting timer activates touch
+
+    std::this_thread::sleep_for(110ms); // wait for reset touch timer to expire and trigger callback
+    EXPECT_FALSE(mFlinger.scheduler()->isTouchActive());
+
+    EXPECT_EQ(NO_ERROR, mFlinger.notifyPowerBoost(static_cast<int32_t>(Boost::CAMERA_SHOT)));
+    std::this_thread::sleep_for(10ms); // wait for callback to maybe be triggered
+    EXPECT_FALSE(mFlinger.scheduler()->isTouchActive());
+
+    std::this_thread::sleep_for(110ms); // wait for reset touch timer to expire and trigger callback
+    EXPECT_FALSE(mFlinger.scheduler()->isTouchActive());
+
+    EXPECT_EQ(NO_ERROR, mFlinger.notifyPowerBoost(static_cast<int32_t>(Boost::INTERACTION)));
+    std::this_thread::sleep_for(10ms); // wait for callback to be triggered.
+    EXPECT_TRUE(mFlinger.scheduler()->isTouchActive());
+}
+
+} // namespace
+} // namespace android
\ No newline at end of file
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_OnHotplugReceivedTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_OnHotplugReceivedTest.cpp
new file mode 100644
index 0000000..42f4cf3
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_OnHotplugReceivedTest.cpp
@@ -0,0 +1,158 @@
+/*
+ * Copyright 2020 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"
+
+#include "DisplayTransactionTestHelpers.h"
+
+namespace android {
+namespace {
+
+class OnHotplugReceivedTest : public DisplayTransactionTest {};
+
+TEST_F(OnHotplugReceivedTest, hotplugEnqueuesEventsForDisplayTransaction) {
+    constexpr int currentSequenceId = 123;
+    constexpr HWDisplayId hwcDisplayId1 = 456;
+    constexpr HWDisplayId hwcDisplayId2 = 654;
+
+    // --------------------------------------------------------------------
+    // Preconditions
+
+    // Set the current sequence id for accepted events
+    mFlinger.mutableComposerSequenceId() = currentSequenceId;
+
+    // Set the main thread id so that the current thread does not appear to be
+    // the main thread.
+    mFlinger.mutableMainThreadId() = std::thread::id();
+
+    // --------------------------------------------------------------------
+    // Call Expectations
+
+    // We expect invalidate() to be invoked once to trigger display transaction
+    // processing.
+    EXPECT_CALL(*mMessageQueue, invalidate()).Times(1);
+
+    // --------------------------------------------------------------------
+    // Invocation
+
+    // Simulate two hotplug events (a connect and a disconnect)
+    mFlinger.onHotplugReceived(currentSequenceId, hwcDisplayId1, Connection::CONNECTED);
+    mFlinger.onHotplugReceived(currentSequenceId, hwcDisplayId2, Connection::DISCONNECTED);
+
+    // --------------------------------------------------------------------
+    // Postconditions
+
+    // The display transaction needed flag should be set.
+    EXPECT_TRUE(hasTransactionFlagSet(eDisplayTransactionNeeded));
+
+    // All events should be in the pending event queue.
+    const auto& pendingEvents = mFlinger.mutablePendingHotplugEvents();
+    ASSERT_EQ(2u, pendingEvents.size());
+    EXPECT_EQ(hwcDisplayId1, pendingEvents[0].hwcDisplayId);
+    EXPECT_EQ(Connection::CONNECTED, pendingEvents[0].connection);
+    EXPECT_EQ(hwcDisplayId2, pendingEvents[1].hwcDisplayId);
+    EXPECT_EQ(Connection::DISCONNECTED, pendingEvents[1].connection);
+}
+
+TEST_F(OnHotplugReceivedTest, hotplugDiscardsUnexpectedEvents) {
+    constexpr int currentSequenceId = 123;
+    constexpr int otherSequenceId = 321;
+    constexpr HWDisplayId displayId = 456;
+
+    // --------------------------------------------------------------------
+    // Preconditions
+
+    // Set the current sequence id for accepted events
+    mFlinger.mutableComposerSequenceId() = currentSequenceId;
+
+    // Set the main thread id so that the current thread does not appear to be
+    // the main thread.
+    mFlinger.mutableMainThreadId() = std::thread::id();
+
+    // --------------------------------------------------------------------
+    // Call Expectations
+
+    // We do not expect any calls to invalidate().
+    EXPECT_CALL(*mMessageQueue, invalidate()).Times(0);
+
+    // --------------------------------------------------------------------
+    // Invocation
+
+    // Call with an unexpected sequence id
+    mFlinger.onHotplugReceived(otherSequenceId, displayId, Connection::INVALID);
+
+    // --------------------------------------------------------------------
+    // Postconditions
+
+    // The display transaction needed flag should not be set
+    EXPECT_FALSE(hasTransactionFlagSet(eDisplayTransactionNeeded));
+
+    // There should be no pending events
+    EXPECT_TRUE(mFlinger.mutablePendingHotplugEvents().empty());
+}
+
+TEST_F(OnHotplugReceivedTest, hotplugProcessesEnqueuedEventsIfCalledOnMainThread) {
+    constexpr int currentSequenceId = 123;
+    constexpr HWDisplayId displayId1 = 456;
+
+    // --------------------------------------------------------------------
+    // Note:
+    // --------------------------------------------------------------------
+    // This test case is a bit tricky. We want to verify that
+    // onHotplugReceived() calls processDisplayHotplugEventsLocked(), but we
+    // don't really want to provide coverage for everything the later function
+    // does as there are specific tests for it.
+    // --------------------------------------------------------------------
+
+    // --------------------------------------------------------------------
+    // Preconditions
+
+    // Set the current sequence id for accepted events
+    mFlinger.mutableComposerSequenceId() = currentSequenceId;
+
+    // Set the main thread id so that the current thread does appear to be the
+    // main thread.
+    mFlinger.mutableMainThreadId() = std::this_thread::get_id();
+
+    // --------------------------------------------------------------------
+    // Call Expectations
+
+    // We expect invalidate() to be invoked once to trigger display transaction
+    // processing.
+    EXPECT_CALL(*mMessageQueue, invalidate()).Times(1);
+
+    // --------------------------------------------------------------------
+    // Invocation
+
+    // Simulate a disconnect on a display id that is not connected. This should
+    // be enqueued by onHotplugReceived(), and dequeued by
+    // processDisplayHotplugEventsLocked(), but then ignored as invalid.
+    mFlinger.onHotplugReceived(currentSequenceId, displayId1, Connection::DISCONNECTED);
+
+    // --------------------------------------------------------------------
+    // Postconditions
+
+    // The display transaction needed flag should be set.
+    EXPECT_TRUE(hasTransactionFlagSet(eDisplayTransactionNeeded));
+
+    // There should be no event queued on return, as it should have been
+    // processed.
+    EXPECT_TRUE(mFlinger.mutablePendingHotplugEvents().empty());
+}
+
+} // namespace
+} // namespace android
\ No newline at end of file
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_OnInitializeDisplaysTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_OnInitializeDisplaysTest.cpp
new file mode 100644
index 0000000..7a9403b
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_OnInitializeDisplaysTest.cpp
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2020 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"
+
+#include "DisplayTransactionTestHelpers.h"
+
+namespace android {
+namespace {
+
+class OnInitializeDisplaysTest : public DisplayTransactionTest {};
+
+TEST_F(OnInitializeDisplaysTest, onInitializeDisplaysSetsUpPrimaryDisplay) {
+    using Case = SimplePrimaryDisplayCase;
+
+    // --------------------------------------------------------------------
+    // Preconditions
+
+    // A primary display is set up
+    Case::Display::injectHwcDisplay(this);
+    auto primaryDisplay = Case::Display::makeFakeExistingDisplayInjector(this);
+    primaryDisplay.inject();
+
+    // --------------------------------------------------------------------
+    // Call Expectations
+
+    // We expect the surface interceptor to possibly be used, but we treat it as
+    // disabled since it is called as a side effect rather than directly by this
+    // function.
+    EXPECT_CALL(*mSurfaceInterceptor, isEnabled()).WillOnce(Return(false));
+
+    // We expect a call to get the active display config.
+    Case::Display::setupHwcGetActiveConfigCallExpectations(this);
+
+    // We expect invalidate() to be invoked once to trigger display transaction
+    // processing.
+    EXPECT_CALL(*mMessageQueue, invalidate()).Times(1);
+
+    EXPECT_CALL(*mVSyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillRepeatedly(Return(0));
+
+    // --------------------------------------------------------------------
+    // Invocation
+
+    mFlinger.onInitializeDisplays();
+
+    // --------------------------------------------------------------------
+    // Postconditions
+
+    // The primary display should have a current state
+    ASSERT_TRUE(hasCurrentDisplayState(primaryDisplay.token()));
+    const auto& primaryDisplayState = getCurrentDisplayState(primaryDisplay.token());
+    // The layer stack state should be set to zero
+    EXPECT_EQ(0u, primaryDisplayState.layerStack);
+    // The orientation state should be set to zero
+    EXPECT_EQ(ui::ROTATION_0, primaryDisplayState.orientation);
+
+    // The orientedDisplaySpaceRect state should be set to INVALID
+    EXPECT_EQ(Rect::INVALID_RECT, primaryDisplayState.orientedDisplaySpaceRect);
+
+    // The layerStackSpaceRect state should be set to INVALID
+    EXPECT_EQ(Rect::INVALID_RECT, primaryDisplayState.layerStackSpaceRect);
+
+    // The width and height should both be zero
+    EXPECT_EQ(0u, primaryDisplayState.width);
+    EXPECT_EQ(0u, primaryDisplayState.height);
+
+    // The display should be set to PowerMode::ON
+    ASSERT_TRUE(hasDisplayDevice(primaryDisplay.token()));
+    auto displayDevice = primaryDisplay.mutableDisplayDevice();
+    EXPECT_EQ(PowerMode::ON, displayDevice->getPowerMode());
+
+    // The display refresh period should be set in the orientedDisplaySpaceRect tracker.
+    FrameStats stats;
+    mFlinger.getAnimFrameTracker().getStats(&stats);
+    EXPECT_EQ(DEFAULT_REFRESH_RATE, stats.refreshPeriodNano);
+
+    // The display transaction needed flag should be set.
+    EXPECT_TRUE(hasTransactionFlagSet(eDisplayTransactionNeeded));
+
+    // The compositor timing should be set to default values
+    const auto& compositorTiming = mFlinger.getCompositorTiming();
+    EXPECT_EQ(-DEFAULT_REFRESH_RATE, compositorTiming.deadline);
+    EXPECT_EQ(DEFAULT_REFRESH_RATE, compositorTiming.interval);
+    EXPECT_EQ(DEFAULT_REFRESH_RATE, compositorTiming.presentLatency);
+}
+
+} // namespace
+} // namespace android
\ No newline at end of file
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetDisplayStateTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetDisplayStateTest.cpp
new file mode 100644
index 0000000..be01984
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetDisplayStateTest.cpp
@@ -0,0 +1,493 @@
+/*
+ * Copyright 2020 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"
+
+#include "DisplayTransactionTestHelpers.h"
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+namespace android {
+namespace {
+
+class SetDisplayStateLockedTest : public DisplayTransactionTest {};
+
+TEST_F(SetDisplayStateLockedTest, setDisplayStateLockedDoesNothingWithUnknownDisplay) {
+    // --------------------------------------------------------------------
+    // Preconditions
+
+    // We have an unknown display token not associated with a known display
+    sp<BBinder> displayToken = new BBinder();
+
+    // The requested display state references the unknown display.
+    DisplayState state;
+    state.what = DisplayState::eLayerStackChanged;
+    state.token = displayToken;
+    state.layerStack = 456;
+
+    // --------------------------------------------------------------------
+    // Invocation
+
+    uint32_t flags = mFlinger.setDisplayStateLocked(state);
+
+    // --------------------------------------------------------------------
+    // Postconditions
+
+    // The returned flags are empty
+    EXPECT_EQ(0u, flags);
+
+    // The display token still doesn't match anything known.
+    EXPECT_FALSE(hasCurrentDisplayState(displayToken));
+}
+
+TEST_F(SetDisplayStateLockedTest, setDisplayStateLockedDoesNothingWhenNoChanges) {
+    using Case = SimplePrimaryDisplayCase;
+
+    // --------------------------------------------------------------------
+    // Preconditions
+
+    // A display is already set up
+    auto display = Case::Display::makeFakeExistingDisplayInjector(this);
+    display.inject();
+
+    // No changes are made to the display
+    DisplayState state;
+    state.what = 0;
+    state.token = display.token();
+
+    // --------------------------------------------------------------------
+    // Invocation
+
+    uint32_t flags = mFlinger.setDisplayStateLocked(state);
+
+    // --------------------------------------------------------------------
+    // Postconditions
+
+    // The returned flags are empty
+    EXPECT_EQ(0u, flags);
+}
+
+TEST_F(SetDisplayStateLockedTest, setDisplayStateLockedDoesNothingIfSurfaceDidNotChange) {
+    using Case = SimplePrimaryDisplayCase;
+
+    // --------------------------------------------------------------------
+    // Preconditions
+
+    // A display is already set up
+    auto display = Case::Display::makeFakeExistingDisplayInjector(this);
+    display.inject();
+
+    // There is a surface that can be set.
+    sp<mock::GraphicBufferProducer> surface = new mock::GraphicBufferProducer();
+
+    // The current display state has the surface set
+    display.mutableCurrentDisplayState().surface = surface;
+
+    // The incoming request sets the same surface
+    DisplayState state;
+    state.what = DisplayState::eSurfaceChanged;
+    state.token = display.token();
+    state.surface = surface;
+
+    // --------------------------------------------------------------------
+    // Invocation
+
+    uint32_t flags = mFlinger.setDisplayStateLocked(state);
+
+    // --------------------------------------------------------------------
+    // Postconditions
+
+    // The returned flags are empty
+    EXPECT_EQ(0u, flags);
+
+    // The current display state is unchanged.
+    EXPECT_EQ(surface.get(), display.getCurrentDisplayState().surface.get());
+}
+
+TEST_F(SetDisplayStateLockedTest, setDisplayStateLockedRequestsUpdateIfSurfaceChanged) {
+    using Case = SimplePrimaryDisplayCase;
+
+    // --------------------------------------------------------------------
+    // Preconditions
+
+    // A display is already set up
+    auto display = Case::Display::makeFakeExistingDisplayInjector(this);
+    display.inject();
+
+    // There is a surface that can be set.
+    sp<mock::GraphicBufferProducer> surface = new mock::GraphicBufferProducer();
+
+    // The current display state does not have a surface
+    display.mutableCurrentDisplayState().surface = nullptr;
+
+    // The incoming request sets a surface
+    DisplayState state;
+    state.what = DisplayState::eSurfaceChanged;
+    state.token = display.token();
+    state.surface = surface;
+
+    // --------------------------------------------------------------------
+    // Invocation
+
+    uint32_t flags = mFlinger.setDisplayStateLocked(state);
+
+    // --------------------------------------------------------------------
+    // Postconditions
+
+    // The returned flags indicate a transaction is needed
+    EXPECT_EQ(eDisplayTransactionNeeded, flags);
+
+    // The current display layer stack state is set to the new value
+    EXPECT_EQ(surface.get(), display.getCurrentDisplayState().surface.get());
+}
+
+TEST_F(SetDisplayStateLockedTest, setDisplayStateLockedDoesNothingIfLayerStackDidNotChange) {
+    using Case = SimplePrimaryDisplayCase;
+
+    // --------------------------------------------------------------------
+    // Preconditions
+
+    // A display is already set up
+    auto display = Case::Display::makeFakeExistingDisplayInjector(this);
+    display.inject();
+
+    // The display has a layer stack set
+    display.mutableCurrentDisplayState().layerStack = 456u;
+
+    // The incoming request sets the same layer stack
+    DisplayState state;
+    state.what = DisplayState::eLayerStackChanged;
+    state.token = display.token();
+    state.layerStack = 456u;
+
+    // --------------------------------------------------------------------
+    // Invocation
+
+    uint32_t flags = mFlinger.setDisplayStateLocked(state);
+
+    // --------------------------------------------------------------------
+    // Postconditions
+
+    // The returned flags are empty
+    EXPECT_EQ(0u, flags);
+
+    // The current display state is unchanged
+    EXPECT_EQ(456u, display.getCurrentDisplayState().layerStack);
+}
+
+TEST_F(SetDisplayStateLockedTest, setDisplayStateLockedRequestsUpdateIfLayerStackChanged) {
+    using Case = SimplePrimaryDisplayCase;
+
+    // --------------------------------------------------------------------
+    // Preconditions
+
+    // A display is set up
+    auto display = Case::Display::makeFakeExistingDisplayInjector(this);
+    display.inject();
+
+    // The display has a layer stack set
+    display.mutableCurrentDisplayState().layerStack = 654u;
+
+    // The incoming request sets a different layer stack
+    DisplayState state;
+    state.what = DisplayState::eLayerStackChanged;
+    state.token = display.token();
+    state.layerStack = 456u;
+
+    // --------------------------------------------------------------------
+    // Invocation
+
+    uint32_t flags = mFlinger.setDisplayStateLocked(state);
+
+    // --------------------------------------------------------------------
+    // Postconditions
+
+    // The returned flags indicate a transaction is needed
+    EXPECT_EQ(eDisplayTransactionNeeded, flags);
+
+    // The desired display state has been set to the new value.
+    EXPECT_EQ(456u, display.getCurrentDisplayState().layerStack);
+}
+
+TEST_F(SetDisplayStateLockedTest, setDisplayStateLockedDoesNothingIfProjectionDidNotChange) {
+    using Case = SimplePrimaryDisplayCase;
+    constexpr ui::Rotation initialOrientation = ui::ROTATION_180;
+    const Rect initialOrientedDisplayRect = {1, 2, 3, 4};
+    const Rect initialLayerStackRect = {5, 6, 7, 8};
+
+    // --------------------------------------------------------------------
+    // Preconditions
+
+    // A display is set up
+    auto display = Case::Display::makeFakeExistingDisplayInjector(this);
+    display.inject();
+
+    // The current display state projection state is all set
+    display.mutableCurrentDisplayState().orientation = initialOrientation;
+    display.mutableCurrentDisplayState().orientedDisplaySpaceRect = initialOrientedDisplayRect;
+    display.mutableCurrentDisplayState().layerStackSpaceRect = initialLayerStackRect;
+
+    // The incoming request sets the same projection state
+    DisplayState state;
+    state.what = DisplayState::eDisplayProjectionChanged;
+    state.token = display.token();
+    state.orientation = initialOrientation;
+    state.orientedDisplaySpaceRect = initialOrientedDisplayRect;
+    state.layerStackSpaceRect = initialLayerStackRect;
+
+    // --------------------------------------------------------------------
+    // Invocation
+
+    uint32_t flags = mFlinger.setDisplayStateLocked(state);
+
+    // --------------------------------------------------------------------
+    // Postconditions
+
+    // The returned flags are empty
+    EXPECT_EQ(0u, flags);
+
+    // The current display state is unchanged
+    EXPECT_EQ(initialOrientation, display.getCurrentDisplayState().orientation);
+
+    EXPECT_EQ(initialOrientedDisplayRect,
+              display.getCurrentDisplayState().orientedDisplaySpaceRect);
+    EXPECT_EQ(initialLayerStackRect, display.getCurrentDisplayState().layerStackSpaceRect);
+}
+
+TEST_F(SetDisplayStateLockedTest, setDisplayStateLockedRequestsUpdateIfOrientationChanged) {
+    using Case = SimplePrimaryDisplayCase;
+    constexpr ui::Rotation initialOrientation = ui::ROTATION_90;
+    constexpr ui::Rotation desiredOrientation = ui::ROTATION_180;
+
+    // --------------------------------------------------------------------
+    // Preconditions
+
+    // A display is set up
+    auto display = Case::Display::makeFakeExistingDisplayInjector(this);
+    display.inject();
+
+    // The current display state has an orientation set
+    display.mutableCurrentDisplayState().orientation = initialOrientation;
+
+    // The incoming request sets a different orientation
+    DisplayState state;
+    state.what = DisplayState::eDisplayProjectionChanged;
+    state.token = display.token();
+    state.orientation = desiredOrientation;
+
+    // --------------------------------------------------------------------
+    // Invocation
+
+    uint32_t flags = mFlinger.setDisplayStateLocked(state);
+
+    // --------------------------------------------------------------------
+    // Postconditions
+
+    // The returned flags indicate a transaction is needed
+    EXPECT_EQ(eDisplayTransactionNeeded, flags);
+
+    // The current display state has the new value.
+    EXPECT_EQ(desiredOrientation, display.getCurrentDisplayState().orientation);
+}
+
+TEST_F(SetDisplayStateLockedTest, setDisplayStateLockedRequestsUpdateIfFrameChanged) {
+    using Case = SimplePrimaryDisplayCase;
+    const Rect initialOrientedDisplayRect = {0, 0, 0, 0};
+    const Rect desiredOrientedDisplayRect = {5, 6, 7, 8};
+
+    // --------------------------------------------------------------------
+    // Preconditions
+
+    // A display is set up
+    auto display = Case::Display::makeFakeExistingDisplayInjector(this);
+    display.inject();
+
+    // The current display state does not have a orientedDisplaySpaceRect
+    display.mutableCurrentDisplayState().orientedDisplaySpaceRect = initialOrientedDisplayRect;
+
+    // The incoming request sets a orientedDisplaySpaceRect
+    DisplayState state;
+    state.what = DisplayState::eDisplayProjectionChanged;
+    state.token = display.token();
+    state.orientedDisplaySpaceRect = desiredOrientedDisplayRect;
+
+    // --------------------------------------------------------------------
+    // Invocation
+
+    uint32_t flags = mFlinger.setDisplayStateLocked(state);
+
+    // --------------------------------------------------------------------
+    // Postconditions
+
+    // The returned flags indicate a transaction is needed
+    EXPECT_EQ(eDisplayTransactionNeeded, flags);
+
+    // The current display state has the new value.
+    EXPECT_EQ(desiredOrientedDisplayRect,
+              display.getCurrentDisplayState().orientedDisplaySpaceRect);
+}
+
+TEST_F(SetDisplayStateLockedTest, setDisplayStateLockedRequestsUpdateIfLayerStackRectChanged) {
+    using Case = SimplePrimaryDisplayCase;
+    const Rect initialLayerStackRect = {0, 0, 0, 0};
+    const Rect desiredLayerStackRect = {5, 6, 7, 8};
+
+    // --------------------------------------------------------------------
+    // Preconditions
+
+    // A display is set up
+    auto display = Case::Display::makeFakeExistingDisplayInjector(this);
+    display.inject();
+
+    // The current display state does not have a layerStackSpaceRect
+    display.mutableCurrentDisplayState().layerStackSpaceRect = initialLayerStackRect;
+
+    // The incoming request sets a layerStackSpaceRect
+    DisplayState state;
+    state.what = DisplayState::eDisplayProjectionChanged;
+    state.token = display.token();
+    state.layerStackSpaceRect = desiredLayerStackRect;
+
+    // --------------------------------------------------------------------
+    // Invocation
+
+    uint32_t flags = mFlinger.setDisplayStateLocked(state);
+
+    // --------------------------------------------------------------------
+    // Postconditions
+
+    // The returned flags indicate a transaction is needed
+    EXPECT_EQ(eDisplayTransactionNeeded, flags);
+
+    // The current display state has the new value.
+    EXPECT_EQ(desiredLayerStackRect, display.getCurrentDisplayState().layerStackSpaceRect);
+}
+
+TEST_F(SetDisplayStateLockedTest, setDisplayStateLockedDoesNothingIfSizeDidNotChange) {
+    using Case = SimplePrimaryDisplayCase;
+    constexpr uint32_t initialWidth = 1024;
+    constexpr uint32_t initialHeight = 768;
+
+    // --------------------------------------------------------------------
+    // Preconditions
+
+    // A display is set up
+    auto display = Case::Display::makeFakeExistingDisplayInjector(this);
+    display.inject();
+
+    // The current display state has a size set
+    display.mutableCurrentDisplayState().width = initialWidth;
+    display.mutableCurrentDisplayState().height = initialHeight;
+
+    // The incoming request sets the same display size
+    DisplayState state;
+    state.what = DisplayState::eDisplaySizeChanged;
+    state.token = display.token();
+    state.width = initialWidth;
+    state.height = initialHeight;
+
+    // --------------------------------------------------------------------
+    // Invocation
+
+    uint32_t flags = mFlinger.setDisplayStateLocked(state);
+
+    // --------------------------------------------------------------------
+    // Postconditions
+
+    // The returned flags are empty
+    EXPECT_EQ(0u, flags);
+
+    // The current display state is unchanged
+    EXPECT_EQ(initialWidth, display.getCurrentDisplayState().width);
+    EXPECT_EQ(initialHeight, display.getCurrentDisplayState().height);
+}
+
+TEST_F(SetDisplayStateLockedTest, setDisplayStateLockedRequestsUpdateIfWidthChanged) {
+    using Case = SimplePrimaryDisplayCase;
+    constexpr uint32_t initialWidth = 0;
+    constexpr uint32_t desiredWidth = 1024;
+
+    // --------------------------------------------------------------------
+    // Preconditions
+
+    // A display is set up
+    auto display = Case::Display::makeFakeExistingDisplayInjector(this);
+    display.inject();
+
+    // The display does not yet have a width
+    display.mutableCurrentDisplayState().width = initialWidth;
+
+    // The incoming request sets a display width
+    DisplayState state;
+    state.what = DisplayState::eDisplaySizeChanged;
+    state.token = display.token();
+    state.width = desiredWidth;
+
+    // --------------------------------------------------------------------
+    // Invocation
+
+    uint32_t flags = mFlinger.setDisplayStateLocked(state);
+
+    // --------------------------------------------------------------------
+    // Postconditions
+
+    // The returned flags indicate a transaction is needed
+    EXPECT_EQ(eDisplayTransactionNeeded, flags);
+
+    // The current display state has the new value.
+    EXPECT_EQ(desiredWidth, display.getCurrentDisplayState().width);
+}
+
+TEST_F(SetDisplayStateLockedTest, setDisplayStateLockedRequestsUpdateIfHeightChanged) {
+    using Case = SimplePrimaryDisplayCase;
+    constexpr uint32_t initialHeight = 0;
+    constexpr uint32_t desiredHeight = 768;
+
+    // --------------------------------------------------------------------
+    // Preconditions
+
+    // A display is set up
+    auto display = Case::Display::makeFakeExistingDisplayInjector(this);
+    display.inject();
+
+    // The display does not yet have a height
+    display.mutableCurrentDisplayState().height = initialHeight;
+
+    // The incoming request sets a display height
+    DisplayState state;
+    state.what = DisplayState::eDisplaySizeChanged;
+    state.token = display.token();
+    state.height = desiredHeight;
+
+    // --------------------------------------------------------------------
+    // Invocation
+
+    uint32_t flags = mFlinger.setDisplayStateLocked(state);
+
+    // --------------------------------------------------------------------
+    // Postconditions
+
+    // The returned flags indicate a transaction is needed
+    EXPECT_EQ(eDisplayTransactionNeeded, flags);
+
+    // The current display state has the new value.
+    EXPECT_EQ(desiredHeight, display.getCurrentDisplayState().height);
+}
+
+} // namespace
+} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetPowerModeInternalTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetPowerModeInternalTest.cpp
new file mode 100644
index 0000000..2117628
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetPowerModeInternalTest.cpp
@@ -0,0 +1,498 @@
+/*
+ * Copyright 2020 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"
+
+#include "DisplayTransactionTestHelpers.h"
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+namespace android {
+namespace {
+
+// Used when we simulate a display that supports doze.
+template <typename Display>
+struct DozeIsSupportedVariant {
+    static constexpr bool DOZE_SUPPORTED = true;
+    static constexpr IComposerClient::PowerMode ACTUAL_POWER_MODE_FOR_DOZE =
+            IComposerClient::PowerMode::DOZE;
+    static constexpr IComposerClient::PowerMode ACTUAL_POWER_MODE_FOR_DOZE_SUSPEND =
+            IComposerClient::PowerMode::DOZE_SUSPEND;
+
+    static void setupComposerCallExpectations(DisplayTransactionTest* test) {
+        EXPECT_CALL(*test->mComposer, getDisplayCapabilities(Display::HWC_DISPLAY_ID, _))
+                .WillOnce(DoAll(SetArgPointee<1>(
+                                        std::vector<DisplayCapability>({DisplayCapability::DOZE})),
+                                Return(Error::NONE)));
+    }
+};
+
+template <typename Display>
+// Used when we simulate a display that does not support doze.
+struct DozeNotSupportedVariant {
+    static constexpr bool DOZE_SUPPORTED = false;
+    static constexpr IComposerClient::PowerMode ACTUAL_POWER_MODE_FOR_DOZE =
+            IComposerClient::PowerMode::ON;
+    static constexpr IComposerClient::PowerMode ACTUAL_POWER_MODE_FOR_DOZE_SUSPEND =
+            IComposerClient::PowerMode::ON;
+
+    static void setupComposerCallExpectations(DisplayTransactionTest* test) {
+        EXPECT_CALL(*test->mComposer, getDisplayCapabilities(Display::HWC_DISPLAY_ID, _))
+                .WillOnce(DoAll(SetArgPointee<1>(std::vector<DisplayCapability>({})),
+                                Return(Error::NONE)));
+    }
+};
+
+struct EventThreadBaseSupportedVariant {
+    static void setupVsyncAndEventThreadNoCallExpectations(DisplayTransactionTest* test) {
+        // The callback should not be notified to toggle VSYNC.
+        EXPECT_CALL(test->mSchedulerCallback, setVsyncEnabled(_)).Times(0);
+
+        // The event thread should not be notified.
+        EXPECT_CALL(*test->mEventThread, onScreenReleased()).Times(0);
+        EXPECT_CALL(*test->mEventThread, onScreenAcquired()).Times(0);
+    }
+};
+
+struct EventThreadNotSupportedVariant : public EventThreadBaseSupportedVariant {
+    static void setupAcquireAndEnableVsyncCallExpectations(DisplayTransactionTest* test) {
+        // These calls are only expected for the primary display.
+
+        // Instead expect no calls.
+        setupVsyncAndEventThreadNoCallExpectations(test);
+    }
+
+    static void setupReleaseAndDisableVsyncCallExpectations(DisplayTransactionTest* test) {
+        // These calls are only expected for the primary display.
+
+        // Instead expect no calls.
+        setupVsyncAndEventThreadNoCallExpectations(test);
+    }
+};
+
+struct EventThreadIsSupportedVariant : public EventThreadBaseSupportedVariant {
+    static void setupAcquireAndEnableVsyncCallExpectations(DisplayTransactionTest* test) {
+        // The callback should be notified to enable VSYNC.
+        EXPECT_CALL(test->mSchedulerCallback, setVsyncEnabled(true)).Times(1);
+
+        // The event thread should be notified that the screen was acquired.
+        EXPECT_CALL(*test->mEventThread, onScreenAcquired()).Times(1);
+    }
+
+    static void setupReleaseAndDisableVsyncCallExpectations(DisplayTransactionTest* test) {
+        // The callback should be notified to disable VSYNC.
+        EXPECT_CALL(test->mSchedulerCallback, setVsyncEnabled(false)).Times(1);
+
+        // The event thread should not be notified that the screen was released.
+        EXPECT_CALL(*test->mEventThread, onScreenReleased()).Times(1);
+    }
+};
+
+struct DispSyncIsSupportedVariant {
+    static void setupResetModelCallExpectations(DisplayTransactionTest* test) {
+        EXPECT_CALL(*test->mVsyncController, startPeriodTransition(DEFAULT_REFRESH_RATE)).Times(1);
+        EXPECT_CALL(*test->mVSyncTracker, resetModel()).Times(1);
+    }
+};
+
+struct DispSyncNotSupportedVariant {
+    static void setupResetModelCallExpectations(DisplayTransactionTest* /* test */) {}
+};
+
+// --------------------------------------------------------------------
+// Note:
+//
+// There are a large number of transitions we could test, however we only test a
+// selected subset which provides complete test coverage of the implementation.
+// --------------------------------------------------------------------
+
+template <PowerMode initialPowerMode, PowerMode targetPowerMode>
+struct TransitionVariantCommon {
+    static constexpr auto INITIAL_POWER_MODE = initialPowerMode;
+    static constexpr auto TARGET_POWER_MODE = targetPowerMode;
+
+    static void verifyPostconditions(DisplayTransactionTest*) {}
+};
+
+struct TransitionOffToOnVariant : public TransitionVariantCommon<PowerMode::OFF, PowerMode::ON> {
+    template <typename Case>
+    static void setupCallExpectations(DisplayTransactionTest* test) {
+        Case::setupComposerCallExpectations(test, IComposerClient::PowerMode::ON);
+        Case::EventThread::setupAcquireAndEnableVsyncCallExpectations(test);
+        Case::DispSync::setupResetModelCallExpectations(test);
+        Case::setupRepaintEverythingCallExpectations(test);
+    }
+
+    static void verifyPostconditions(DisplayTransactionTest* test) {
+        EXPECT_TRUE(test->mFlinger.getVisibleRegionsDirty());
+        EXPECT_TRUE(test->mFlinger.getHasPoweredOff());
+    }
+};
+
+struct TransitionOffToDozeSuspendVariant
+      : public TransitionVariantCommon<PowerMode::OFF, PowerMode::DOZE_SUSPEND> {
+    template <typename Case>
+    static void setupCallExpectations(DisplayTransactionTest* test) {
+        Case::setupComposerCallExpectations(test, Case::Doze::ACTUAL_POWER_MODE_FOR_DOZE_SUSPEND);
+        Case::EventThread::setupVsyncAndEventThreadNoCallExpectations(test);
+        Case::setupRepaintEverythingCallExpectations(test);
+    }
+
+    static void verifyPostconditions(DisplayTransactionTest* test) {
+        EXPECT_TRUE(test->mFlinger.getVisibleRegionsDirty());
+        EXPECT_TRUE(test->mFlinger.getHasPoweredOff());
+    }
+};
+
+struct TransitionOnToOffVariant : public TransitionVariantCommon<PowerMode::ON, PowerMode::OFF> {
+    template <typename Case>
+    static void setupCallExpectations(DisplayTransactionTest* test) {
+        Case::EventThread::setupReleaseAndDisableVsyncCallExpectations(test);
+        Case::setupComposerCallExpectations(test, IComposerClient::PowerMode::OFF);
+    }
+
+    static void verifyPostconditions(DisplayTransactionTest* test) {
+        EXPECT_TRUE(test->mFlinger.getVisibleRegionsDirty());
+    }
+};
+
+struct TransitionDozeSuspendToOffVariant
+      : public TransitionVariantCommon<PowerMode::DOZE_SUSPEND, PowerMode::OFF> {
+    template <typename Case>
+    static void setupCallExpectations(DisplayTransactionTest* test) {
+        Case::EventThread::setupVsyncAndEventThreadNoCallExpectations(test);
+        Case::setupComposerCallExpectations(test, IComposerClient::PowerMode::OFF);
+    }
+
+    static void verifyPostconditions(DisplayTransactionTest* test) {
+        EXPECT_TRUE(test->mFlinger.getVisibleRegionsDirty());
+    }
+};
+
+struct TransitionOnToDozeVariant : public TransitionVariantCommon<PowerMode::ON, PowerMode::DOZE> {
+    template <typename Case>
+    static void setupCallExpectations(DisplayTransactionTest* test) {
+        Case::EventThread::setupVsyncAndEventThreadNoCallExpectations(test);
+        Case::setupComposerCallExpectations(test, Case::Doze::ACTUAL_POWER_MODE_FOR_DOZE);
+    }
+};
+
+struct TransitionDozeSuspendToDozeVariant
+      : public TransitionVariantCommon<PowerMode::DOZE_SUSPEND, PowerMode::DOZE> {
+    template <typename Case>
+    static void setupCallExpectations(DisplayTransactionTest* test) {
+        Case::EventThread::setupAcquireAndEnableVsyncCallExpectations(test);
+        Case::DispSync::setupResetModelCallExpectations(test);
+        Case::setupComposerCallExpectations(test, Case::Doze::ACTUAL_POWER_MODE_FOR_DOZE);
+    }
+};
+
+struct TransitionDozeToOnVariant : public TransitionVariantCommon<PowerMode::DOZE, PowerMode::ON> {
+    template <typename Case>
+    static void setupCallExpectations(DisplayTransactionTest* test) {
+        Case::EventThread::setupVsyncAndEventThreadNoCallExpectations(test);
+        Case::setupComposerCallExpectations(test, IComposerClient::PowerMode::ON);
+    }
+};
+
+struct TransitionDozeSuspendToOnVariant
+      : public TransitionVariantCommon<PowerMode::DOZE_SUSPEND, PowerMode::ON> {
+    template <typename Case>
+    static void setupCallExpectations(DisplayTransactionTest* test) {
+        Case::EventThread::setupAcquireAndEnableVsyncCallExpectations(test);
+        Case::DispSync::setupResetModelCallExpectations(test);
+        Case::setupComposerCallExpectations(test, IComposerClient::PowerMode::ON);
+    }
+};
+
+struct TransitionOnToDozeSuspendVariant
+      : public TransitionVariantCommon<PowerMode::ON, PowerMode::DOZE_SUSPEND> {
+    template <typename Case>
+    static void setupCallExpectations(DisplayTransactionTest* test) {
+        Case::EventThread::setupReleaseAndDisableVsyncCallExpectations(test);
+        Case::setupComposerCallExpectations(test, Case::Doze::ACTUAL_POWER_MODE_FOR_DOZE_SUSPEND);
+    }
+};
+
+struct TransitionOnToUnknownVariant
+      : public TransitionVariantCommon<PowerMode::ON, static_cast<PowerMode>(POWER_MODE_LEET)> {
+    template <typename Case>
+    static void setupCallExpectations(DisplayTransactionTest* test) {
+        Case::EventThread::setupVsyncAndEventThreadNoCallExpectations(test);
+        Case::setupNoComposerPowerModeCallExpectations(test);
+    }
+};
+
+// --------------------------------------------------------------------
+// Note:
+//
+// Rather than testing the cartesian product of
+// DozeIsSupported/DozeNotSupported with all other options, we use one for one
+// display type, and the other for another display type.
+// --------------------------------------------------------------------
+
+template <typename DisplayVariant, typename DozeVariant, typename EventThreadVariant,
+          typename DispSyncVariant, typename TransitionVariant>
+struct DisplayPowerCase {
+    using Display = DisplayVariant;
+    using Doze = DozeVariant;
+    using EventThread = EventThreadVariant;
+    using DispSync = DispSyncVariant;
+    using Transition = TransitionVariant;
+
+    static auto injectDisplayWithInitialPowerMode(DisplayTransactionTest* test, PowerMode mode) {
+        Display::injectHwcDisplayWithNoDefaultCapabilities(test);
+        auto display = Display::makeFakeExistingDisplayInjector(test);
+        display.inject();
+        display.mutableDisplayDevice()->setPowerMode(mode);
+        return display;
+    }
+
+    static void setInitialPrimaryHWVsyncEnabled(DisplayTransactionTest* test, bool enabled) {
+        test->mFlinger.scheduler()->mutablePrimaryHWVsyncEnabled() = enabled;
+    }
+
+    static void setupRepaintEverythingCallExpectations(DisplayTransactionTest* test) {
+        EXPECT_CALL(*test->mMessageQueue, invalidate()).Times(1);
+    }
+
+    static void setupSurfaceInterceptorCallExpectations(DisplayTransactionTest* test,
+                                                        PowerMode mode) {
+        EXPECT_CALL(*test->mSurfaceInterceptor, isEnabled()).WillOnce(Return(true));
+        EXPECT_CALL(*test->mSurfaceInterceptor, savePowerModeUpdate(_, static_cast<int32_t>(mode)))
+                .Times(1);
+    }
+
+    static void setupComposerCallExpectations(DisplayTransactionTest* test, PowerMode mode) {
+        // Any calls to get the active config will return a default value.
+        EXPECT_CALL(*test->mComposer, getActiveConfig(Display::HWC_DISPLAY_ID, _))
+                .WillRepeatedly(DoAll(SetArgPointee<1>(Display::HWC_ACTIVE_CONFIG_ID),
+                                      Return(Error::NONE)));
+
+        // Any calls to get whether the display supports dozing will return the value set by the
+        // policy variant.
+        EXPECT_CALL(*test->mComposer, getDozeSupport(Display::HWC_DISPLAY_ID, _))
+                .WillRepeatedly(DoAll(SetArgPointee<1>(Doze::DOZE_SUPPORTED), Return(Error::NONE)));
+
+        EXPECT_CALL(*test->mComposer, setPowerMode(Display::HWC_DISPLAY_ID, mode)).Times(1);
+    }
+
+    static void setupNoComposerPowerModeCallExpectations(DisplayTransactionTest* test) {
+        EXPECT_CALL(*test->mComposer, setPowerMode(Display::HWC_DISPLAY_ID, _)).Times(0);
+    }
+};
+
+// A sample configuration for the primary display.
+// In addition to having event thread support, we emulate doze support.
+template <typename TransitionVariant>
+using PrimaryDisplayPowerCase =
+        DisplayPowerCase<PrimaryDisplayVariant, DozeIsSupportedVariant<PrimaryDisplayVariant>,
+                         EventThreadIsSupportedVariant, DispSyncIsSupportedVariant,
+                         TransitionVariant>;
+
+// A sample configuration for the external display.
+// In addition to not having event thread support, we emulate not having doze
+// support.
+template <typename TransitionVariant>
+using ExternalDisplayPowerCase =
+        DisplayPowerCase<ExternalDisplayVariant, DozeNotSupportedVariant<ExternalDisplayVariant>,
+                         EventThreadNotSupportedVariant, DispSyncNotSupportedVariant,
+                         TransitionVariant>;
+
+class SetPowerModeInternalTest : public DisplayTransactionTest {
+public:
+    template <typename Case>
+    void transitionDisplayCommon();
+};
+
+template <PowerMode PowerMode>
+struct PowerModeInitialVSyncEnabled : public std::false_type {};
+
+template <>
+struct PowerModeInitialVSyncEnabled<PowerMode::ON> : public std::true_type {};
+
+template <>
+struct PowerModeInitialVSyncEnabled<PowerMode::DOZE> : public std::true_type {};
+
+template <typename Case>
+void SetPowerModeInternalTest::transitionDisplayCommon() {
+    // --------------------------------------------------------------------
+    // Preconditions
+
+    Case::Doze::setupComposerCallExpectations(this);
+    auto display =
+            Case::injectDisplayWithInitialPowerMode(this, Case::Transition::INITIAL_POWER_MODE);
+    Case::setInitialPrimaryHWVsyncEnabled(this,
+                                          PowerModeInitialVSyncEnabled<
+                                                  Case::Transition::INITIAL_POWER_MODE>::value);
+
+    // --------------------------------------------------------------------
+    // Call Expectations
+
+    Case::setupSurfaceInterceptorCallExpectations(this, Case::Transition::TARGET_POWER_MODE);
+    Case::Transition::template setupCallExpectations<Case>(this);
+
+    // --------------------------------------------------------------------
+    // Invocation
+
+    mFlinger.setPowerModeInternal(display.mutableDisplayDevice(),
+                                  Case::Transition::TARGET_POWER_MODE);
+
+    // --------------------------------------------------------------------
+    // Postconditions
+
+    Case::Transition::verifyPostconditions(this);
+}
+
+TEST_F(SetPowerModeInternalTest, setPowerModeInternalDoesNothingIfNoChange) {
+    using Case = SimplePrimaryDisplayCase;
+
+    // --------------------------------------------------------------------
+    // Preconditions
+
+    // A primary display device is set up
+    Case::Display::injectHwcDisplay(this);
+    auto display = Case::Display::makeFakeExistingDisplayInjector(this);
+    display.inject();
+
+    // The display is already set to PowerMode::ON
+    display.mutableDisplayDevice()->setPowerMode(PowerMode::ON);
+
+    // --------------------------------------------------------------------
+    // Invocation
+
+    mFlinger.setPowerModeInternal(display.mutableDisplayDevice(), PowerMode::ON);
+
+    // --------------------------------------------------------------------
+    // Postconditions
+
+    EXPECT_EQ(PowerMode::ON, display.mutableDisplayDevice()->getPowerMode());
+}
+
+TEST_F(SetPowerModeInternalTest, setPowerModeInternalDoesNothingIfVirtualDisplay) {
+    using Case = HwcVirtualDisplayCase;
+
+    // --------------------------------------------------------------------
+    // Preconditions
+
+    // Insert display data so that the HWC thinks it created the virtual display.
+    const auto displayId = Case::Display::DISPLAY_ID::get();
+    ASSERT_TRUE(HalVirtualDisplayId::tryCast(displayId));
+    mFlinger.mutableHwcDisplayData().try_emplace(displayId);
+
+    // A virtual display device is set up
+    Case::Display::injectHwcDisplay(this);
+    auto display = Case::Display::makeFakeExistingDisplayInjector(this);
+    display.inject();
+
+    // The display is set to PowerMode::ON
+    getDisplayDevice(display.token())->setPowerMode(PowerMode::ON);
+
+    // --------------------------------------------------------------------
+    // Invocation
+
+    mFlinger.setPowerModeInternal(display.mutableDisplayDevice(), PowerMode::OFF);
+
+    // --------------------------------------------------------------------
+    // Postconditions
+
+    EXPECT_EQ(PowerMode::ON, display.mutableDisplayDevice()->getPowerMode());
+}
+
+TEST_F(SetPowerModeInternalTest, transitionsDisplayFromOffToOnPrimaryDisplay) {
+    transitionDisplayCommon<PrimaryDisplayPowerCase<TransitionOffToOnVariant>>();
+}
+
+TEST_F(SetPowerModeInternalTest, transitionsDisplayFromOffToDozeSuspendPrimaryDisplay) {
+    transitionDisplayCommon<PrimaryDisplayPowerCase<TransitionOffToDozeSuspendVariant>>();
+}
+
+TEST_F(SetPowerModeInternalTest, transitionsDisplayFromOnToOffPrimaryDisplay) {
+    transitionDisplayCommon<PrimaryDisplayPowerCase<TransitionOnToOffVariant>>();
+}
+
+TEST_F(SetPowerModeInternalTest, transitionsDisplayFromDozeSuspendToOffPrimaryDisplay) {
+    transitionDisplayCommon<PrimaryDisplayPowerCase<TransitionDozeSuspendToOffVariant>>();
+}
+
+TEST_F(SetPowerModeInternalTest, transitionsDisplayFromOnToDozePrimaryDisplay) {
+    transitionDisplayCommon<PrimaryDisplayPowerCase<TransitionOnToDozeVariant>>();
+}
+
+TEST_F(SetPowerModeInternalTest, transitionsDisplayFromDozeSuspendToDozePrimaryDisplay) {
+    transitionDisplayCommon<PrimaryDisplayPowerCase<TransitionDozeSuspendToDozeVariant>>();
+}
+
+TEST_F(SetPowerModeInternalTest, transitionsDisplayFromDozeToOnPrimaryDisplay) {
+    transitionDisplayCommon<PrimaryDisplayPowerCase<TransitionDozeToOnVariant>>();
+}
+
+TEST_F(SetPowerModeInternalTest, transitionsDisplayFromDozeSuspendToOnPrimaryDisplay) {
+    transitionDisplayCommon<PrimaryDisplayPowerCase<TransitionDozeSuspendToOnVariant>>();
+}
+
+TEST_F(SetPowerModeInternalTest, transitionsDisplayFromOnToDozeSuspendPrimaryDisplay) {
+    transitionDisplayCommon<PrimaryDisplayPowerCase<TransitionOnToDozeSuspendVariant>>();
+}
+
+TEST_F(SetPowerModeInternalTest, transitionsDisplayFromOnToUnknownPrimaryDisplay) {
+    transitionDisplayCommon<PrimaryDisplayPowerCase<TransitionOnToUnknownVariant>>();
+}
+
+TEST_F(SetPowerModeInternalTest, transitionsDisplayFromOffToOnExternalDisplay) {
+    transitionDisplayCommon<ExternalDisplayPowerCase<TransitionOffToOnVariant>>();
+}
+
+TEST_F(SetPowerModeInternalTest, transitionsDisplayFromOffToDozeSuspendExternalDisplay) {
+    transitionDisplayCommon<ExternalDisplayPowerCase<TransitionOffToDozeSuspendVariant>>();
+}
+
+TEST_F(SetPowerModeInternalTest, transitionsDisplayFromOnToOffExternalDisplay) {
+    transitionDisplayCommon<ExternalDisplayPowerCase<TransitionOnToOffVariant>>();
+}
+
+TEST_F(SetPowerModeInternalTest, transitionsDisplayFromDozeSuspendToOffExternalDisplay) {
+    transitionDisplayCommon<ExternalDisplayPowerCase<TransitionDozeSuspendToOffVariant>>();
+}
+
+TEST_F(SetPowerModeInternalTest, transitionsDisplayFromOnToDozeExternalDisplay) {
+    transitionDisplayCommon<ExternalDisplayPowerCase<TransitionOnToDozeVariant>>();
+}
+
+TEST_F(SetPowerModeInternalTest, transitionsDisplayFromDozeSuspendToDozeExternalDisplay) {
+    transitionDisplayCommon<ExternalDisplayPowerCase<TransitionDozeSuspendToDozeVariant>>();
+}
+
+TEST_F(SetPowerModeInternalTest, transitionsDisplayFromDozeToOnExternalDisplay) {
+    transitionDisplayCommon<ExternalDisplayPowerCase<TransitionDozeToOnVariant>>();
+}
+
+TEST_F(SetPowerModeInternalTest, transitionsDisplayFromDozeSuspendToOnExternalDisplay) {
+    transitionDisplayCommon<ExternalDisplayPowerCase<TransitionDozeSuspendToOnVariant>>();
+}
+
+TEST_F(SetPowerModeInternalTest, transitionsDisplayFromOnToDozeSuspendExternalDisplay) {
+    transitionDisplayCommon<ExternalDisplayPowerCase<TransitionOnToDozeSuspendVariant>>();
+}
+
+TEST_F(SetPowerModeInternalTest, transitionsDisplayFromOnToUnknownExternalDisplay) {
+    transitionDisplayCommon<ExternalDisplayPowerCase<TransitionOnToUnknownVariant>>();
+}
+
+} // namespace
+} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetupNewDisplayDeviceInternalTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetupNewDisplayDeviceInternalTest.cpp
new file mode 100644
index 0000000..61f0788
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetupNewDisplayDeviceInternalTest.cpp
@@ -0,0 +1,316 @@
+/*
+ * Copyright 2020 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"
+
+#include "DisplayTransactionTestHelpers.h"
+
+namespace android {
+namespace {
+
+using hal::RenderIntent;
+
+// For this variant, SurfaceFlinger should configure itself with wide display
+// support, and the display should respond with an non-empty list of supported
+// color modes. Wide-color support should be configured.
+template <typename Display>
+struct WideColorP3ColorimetricSupportedVariant {
+    static constexpr bool WIDE_COLOR_SUPPORTED = true;
+
+    static void injectConfigChange(DisplayTransactionTest* test) {
+        test->mFlinger.mutableUseColorManagement() = true;
+        test->mFlinger.mutableHasWideColorDisplay() = true;
+        test->mFlinger.mutableDisplayColorSetting() = DisplayColorSetting::kUnmanaged;
+    }
+
+    static void setupComposerCallExpectations(DisplayTransactionTest* test) {
+        EXPECT_CALL(*test->mNativeWindow, perform(NATIVE_WINDOW_SET_BUFFERS_DATASPACE)).Times(1);
+
+        EXPECT_CALL(*test->mComposer, getColorModes(Display::HWC_DISPLAY_ID, _))
+                .WillOnce(DoAll(SetArgPointee<1>(std::vector<ColorMode>({ColorMode::DISPLAY_P3})),
+                                Return(Error::NONE)));
+        EXPECT_CALL(*test->mComposer,
+                    getRenderIntents(Display::HWC_DISPLAY_ID, ColorMode::DISPLAY_P3, _))
+                .WillOnce(DoAll(SetArgPointee<2>(
+                                        std::vector<RenderIntent>({RenderIntent::COLORIMETRIC})),
+                                Return(Error::NONE)));
+        EXPECT_CALL(*test->mComposer,
+                    setColorMode(Display::HWC_DISPLAY_ID, ColorMode::SRGB,
+                                 RenderIntent::COLORIMETRIC))
+                .WillOnce(Return(Error::NONE));
+    }
+};
+
+template <typename Display>
+struct Hdr10PlusSupportedVariant {
+    static constexpr bool HDR10_PLUS_SUPPORTED = true;
+    static constexpr bool HDR10_SUPPORTED = true;
+    static constexpr bool HDR_HLG_SUPPORTED = false;
+    static constexpr bool HDR_DOLBY_VISION_SUPPORTED = false;
+    static void setupComposerCallExpectations(DisplayTransactionTest* test) {
+        EXPECT_CALL(*test->mComposer, getHdrCapabilities(_, _, _, _, _))
+                .WillOnce(DoAll(SetArgPointee<1>(std::vector<Hdr>({
+                                        Hdr::HDR10_PLUS,
+                                        Hdr::HDR10,
+                                })),
+                                Return(Error::NONE)));
+    }
+};
+
+// For this variant, the composer should respond with a non-empty list of HDR
+// modes containing HDR10, so HDR10 support should be configured.
+template <typename Display>
+struct Hdr10SupportedVariant {
+    static constexpr bool HDR10_PLUS_SUPPORTED = false;
+    static constexpr bool HDR10_SUPPORTED = true;
+    static constexpr bool HDR_HLG_SUPPORTED = false;
+    static constexpr bool HDR_DOLBY_VISION_SUPPORTED = false;
+    static void setupComposerCallExpectations(DisplayTransactionTest* test) {
+        EXPECT_CALL(*test->mComposer, getHdrCapabilities(Display::HWC_DISPLAY_ID, _, _, _, _))
+                .WillOnce(DoAll(SetArgPointee<1>(std::vector<Hdr>({Hdr::HDR10})),
+                                Return(Error::NONE)));
+    }
+};
+
+// For this variant, the composer should respond with a non-empty list of HDR
+// modes containing HLG, so HLG support should be configured.
+template <typename Display>
+struct HdrHlgSupportedVariant {
+    static constexpr bool HDR10_PLUS_SUPPORTED = false;
+    static constexpr bool HDR10_SUPPORTED = false;
+    static constexpr bool HDR_HLG_SUPPORTED = true;
+    static constexpr bool HDR_DOLBY_VISION_SUPPORTED = false;
+    static void setupComposerCallExpectations(DisplayTransactionTest* test) {
+        EXPECT_CALL(*test->mComposer, getHdrCapabilities(Display::HWC_DISPLAY_ID, _, _, _, _))
+                .WillOnce(
+                        DoAll(SetArgPointee<1>(std::vector<Hdr>({Hdr::HLG})), Return(Error::NONE)));
+    }
+};
+
+// For this variant, the composer should respond with a non-empty list of HDR
+// modes containing DOLBY_VISION, so DOLBY_VISION support should be configured.
+template <typename Display>
+struct HdrDolbyVisionSupportedVariant {
+    static constexpr bool HDR10_PLUS_SUPPORTED = false;
+    static constexpr bool HDR10_SUPPORTED = false;
+    static constexpr bool HDR_HLG_SUPPORTED = false;
+    static constexpr bool HDR_DOLBY_VISION_SUPPORTED = true;
+    static void setupComposerCallExpectations(DisplayTransactionTest* test) {
+        EXPECT_CALL(*test->mComposer, getHdrCapabilities(Display::HWC_DISPLAY_ID, _, _, _, _))
+                .WillOnce(DoAll(SetArgPointee<1>(std::vector<Hdr>({Hdr::DOLBY_VISION})),
+                                Return(Error::NONE)));
+    }
+};
+
+template <typename Display>
+struct Smpte2086PerFrameMetadataSupportVariant {
+    static constexpr int PER_FRAME_METADATA_KEYS = HdrMetadata::Type::SMPTE2086;
+    static void setupComposerCallExpectations(DisplayTransactionTest* test) {
+        EXPECT_CALL(*test->mComposer, getPerFrameMetadataKeys(Display::HWC_DISPLAY_ID))
+                .WillOnce(Return(std::vector<PerFrameMetadataKey>({
+                        PerFrameMetadataKey::DISPLAY_RED_PRIMARY_X,
+                        PerFrameMetadataKey::DISPLAY_RED_PRIMARY_Y,
+                        PerFrameMetadataKey::DISPLAY_GREEN_PRIMARY_X,
+                        PerFrameMetadataKey::DISPLAY_GREEN_PRIMARY_Y,
+                        PerFrameMetadataKey::DISPLAY_BLUE_PRIMARY_X,
+                        PerFrameMetadataKey::DISPLAY_BLUE_PRIMARY_Y,
+                        PerFrameMetadataKey::WHITE_POINT_X,
+                        PerFrameMetadataKey::WHITE_POINT_Y,
+                        PerFrameMetadataKey::MAX_LUMINANCE,
+                        PerFrameMetadataKey::MIN_LUMINANCE,
+                })));
+    }
+};
+
+template <typename Display>
+struct Cta861_3_PerFrameMetadataSupportVariant {
+    static constexpr int PER_FRAME_METADATA_KEYS = HdrMetadata::Type::CTA861_3;
+    static void setupComposerCallExpectations(DisplayTransactionTest* test) {
+        EXPECT_CALL(*test->mComposer, getPerFrameMetadataKeys(Display::HWC_DISPLAY_ID))
+                .WillOnce(Return(std::vector<PerFrameMetadataKey>({
+                        PerFrameMetadataKey::MAX_CONTENT_LIGHT_LEVEL,
+                        PerFrameMetadataKey::MAX_FRAME_AVERAGE_LIGHT_LEVEL,
+                })));
+    }
+};
+
+template <typename Display>
+struct Hdr10_Plus_PerFrameMetadataSupportVariant {
+    static constexpr int PER_FRAME_METADATA_KEYS = HdrMetadata::Type::HDR10PLUS;
+    static void setupComposerCallExpectations(DisplayTransactionTest* test) {
+        EXPECT_CALL(*test->mComposer, getPerFrameMetadataKeys(Display::HWC_DISPLAY_ID))
+                .WillOnce(Return(std::vector<PerFrameMetadataKey>({
+                        PerFrameMetadataKey::HDR10_PLUS_SEI,
+                })));
+    }
+};
+
+using WideColorP3ColorimetricDisplayCase =
+        Case<PrimaryDisplayVariant, WideColorP3ColorimetricSupportedVariant<PrimaryDisplayVariant>,
+             HdrNotSupportedVariant<PrimaryDisplayVariant>,
+             NoPerFrameMetadataSupportVariant<PrimaryDisplayVariant>>;
+using Hdr10PlusDisplayCase =
+        Case<PrimaryDisplayVariant, WideColorNotSupportedVariant<PrimaryDisplayVariant>,
+             Hdr10SupportedVariant<PrimaryDisplayVariant>,
+             Hdr10_Plus_PerFrameMetadataSupportVariant<PrimaryDisplayVariant>>;
+using Hdr10DisplayCase =
+        Case<PrimaryDisplayVariant, WideColorNotSupportedVariant<PrimaryDisplayVariant>,
+             Hdr10SupportedVariant<PrimaryDisplayVariant>,
+             NoPerFrameMetadataSupportVariant<PrimaryDisplayVariant>>;
+using HdrHlgDisplayCase =
+        Case<PrimaryDisplayVariant, WideColorNotSupportedVariant<PrimaryDisplayVariant>,
+             HdrHlgSupportedVariant<PrimaryDisplayVariant>,
+             NoPerFrameMetadataSupportVariant<PrimaryDisplayVariant>>;
+using HdrDolbyVisionDisplayCase =
+        Case<PrimaryDisplayVariant, WideColorNotSupportedVariant<PrimaryDisplayVariant>,
+             HdrDolbyVisionSupportedVariant<PrimaryDisplayVariant>,
+             NoPerFrameMetadataSupportVariant<PrimaryDisplayVariant>>;
+using HdrSmpte2086DisplayCase =
+        Case<PrimaryDisplayVariant, WideColorNotSupportedVariant<PrimaryDisplayVariant>,
+             HdrNotSupportedVariant<PrimaryDisplayVariant>,
+             Smpte2086PerFrameMetadataSupportVariant<PrimaryDisplayVariant>>;
+using HdrCta861_3_DisplayCase =
+        Case<PrimaryDisplayVariant, WideColorNotSupportedVariant<PrimaryDisplayVariant>,
+             HdrNotSupportedVariant<PrimaryDisplayVariant>,
+             Cta861_3_PerFrameMetadataSupportVariant<PrimaryDisplayVariant>>;
+
+class SetupNewDisplayDeviceInternalTest : public DisplayTransactionTest {
+public:
+    template <typename T>
+    void setupNewDisplayDeviceInternalTest();
+};
+
+template <typename Case>
+void SetupNewDisplayDeviceInternalTest::setupNewDisplayDeviceInternalTest() {
+    const sp<BBinder> displayToken = new BBinder();
+    const sp<compositionengine::mock::DisplaySurface> displaySurface =
+            new compositionengine::mock::DisplaySurface();
+    const sp<mock::GraphicBufferProducer> producer = new mock::GraphicBufferProducer();
+
+    // --------------------------------------------------------------------
+    // Preconditions
+
+    // Wide color displays support is configured appropriately
+    Case::WideColorSupport::injectConfigChange(this);
+
+    // The display is setup with the HWC.
+    Case::Display::injectHwcDisplay(this);
+
+    // SurfaceFlinger will use a test-controlled factory for native window
+    // surfaces.
+    injectFakeNativeWindowSurfaceFactory();
+
+    // A compositionengine::Display has already been created
+    auto compositionDisplay = Case::Display::injectCompositionDisplay(this);
+
+    // --------------------------------------------------------------------
+    // Call Expectations
+
+    // Various native window calls will be made.
+    Case::Display::setupNativeWindowSurfaceCreationCallExpectations(this);
+    Case::Display::setupHwcGetActiveConfigCallExpectations(this);
+    Case::WideColorSupport::setupComposerCallExpectations(this);
+    Case::HdrSupport::setupComposerCallExpectations(this);
+    Case::PerFrameMetadataSupport::setupComposerCallExpectations(this);
+
+    // --------------------------------------------------------------------
+    // Invocation
+
+    DisplayDeviceState state;
+    if (const auto connectionType = Case::Display::CONNECTION_TYPE::value) {
+        const auto displayId = PhysicalDisplayId::tryCast(Case::Display::DISPLAY_ID::get());
+        ASSERT_TRUE(displayId);
+        const auto hwcDisplayId = Case::Display::HWC_DISPLAY_ID_OPT::value;
+        ASSERT_TRUE(hwcDisplayId);
+        state.physical = {.id = *displayId, .type = *connectionType, .hwcDisplayId = *hwcDisplayId};
+    }
+
+    state.isSecure = static_cast<bool>(Case::Display::SECURE);
+
+    auto device = mFlinger.setupNewDisplayDeviceInternal(displayToken, compositionDisplay, state,
+                                                         displaySurface, producer);
+
+    // --------------------------------------------------------------------
+    // Postconditions
+
+    ASSERT_TRUE(device != nullptr);
+    EXPECT_EQ(Case::Display::DISPLAY_ID::get(), device->getId());
+    EXPECT_EQ(Case::Display::CONNECTION_TYPE::value, device->getConnectionType());
+    EXPECT_EQ(static_cast<bool>(Case::Display::VIRTUAL), device->isVirtual());
+    EXPECT_EQ(static_cast<bool>(Case::Display::SECURE), device->isSecure());
+    EXPECT_EQ(static_cast<bool>(Case::Display::PRIMARY), device->isPrimary());
+    EXPECT_EQ(Case::Display::WIDTH, device->getWidth());
+    EXPECT_EQ(Case::Display::HEIGHT, device->getHeight());
+    EXPECT_EQ(Case::WideColorSupport::WIDE_COLOR_SUPPORTED, device->hasWideColorGamut());
+    EXPECT_EQ(Case::HdrSupport::HDR10_PLUS_SUPPORTED, device->hasHDR10PlusSupport());
+    EXPECT_EQ(Case::HdrSupport::HDR10_SUPPORTED, device->hasHDR10Support());
+    EXPECT_EQ(Case::HdrSupport::HDR_HLG_SUPPORTED, device->hasHLGSupport());
+    EXPECT_EQ(Case::HdrSupport::HDR_DOLBY_VISION_SUPPORTED, device->hasDolbyVisionSupport());
+    // Note: This is not Case::Display::HWC_ACTIVE_CONFIG_ID as the ids are
+    // remapped, and the test only ever sets up one config. If there were an error
+    // looking up the remapped index, device->getActiveConfig() would be -1 instead.
+    EXPECT_EQ(0, device->getActiveConfig().value());
+    EXPECT_EQ(Case::PerFrameMetadataSupport::PER_FRAME_METADATA_KEYS,
+              device->getSupportedPerFrameMetadata());
+}
+
+TEST_F(SetupNewDisplayDeviceInternalTest, createSimplePrimaryDisplay) {
+    setupNewDisplayDeviceInternalTest<SimplePrimaryDisplayCase>();
+}
+
+TEST_F(SetupNewDisplayDeviceInternalTest, createSimpleExternalDisplay) {
+    setupNewDisplayDeviceInternalTest<SimpleExternalDisplayCase>();
+}
+
+TEST_F(SetupNewDisplayDeviceInternalTest, createNonHwcVirtualDisplay) {
+    setupNewDisplayDeviceInternalTest<NonHwcVirtualDisplayCase>();
+}
+
+TEST_F(SetupNewDisplayDeviceInternalTest, createHwcVirtualDisplay) {
+    setupNewDisplayDeviceInternalTest<HwcVirtualDisplayCase>();
+}
+
+TEST_F(SetupNewDisplayDeviceInternalTest, createWideColorP3Display) {
+    setupNewDisplayDeviceInternalTest<WideColorP3ColorimetricDisplayCase>();
+}
+
+TEST_F(SetupNewDisplayDeviceInternalTest, createHdr10PlusDisplay) {
+    setupNewDisplayDeviceInternalTest<Hdr10PlusDisplayCase>();
+}
+
+TEST_F(SetupNewDisplayDeviceInternalTest, createHdr10Display) {
+    setupNewDisplayDeviceInternalTest<Hdr10DisplayCase>();
+}
+
+TEST_F(SetupNewDisplayDeviceInternalTest, createHdrHlgDisplay) {
+    setupNewDisplayDeviceInternalTest<HdrHlgDisplayCase>();
+}
+
+TEST_F(SetupNewDisplayDeviceInternalTest, createHdrDolbyVisionDisplay) {
+    setupNewDisplayDeviceInternalTest<HdrDolbyVisionDisplayCase>();
+}
+
+TEST_F(SetupNewDisplayDeviceInternalTest, createHdrSmpte2086DisplayCase) {
+    setupNewDisplayDeviceInternalTest<HdrSmpte2086DisplayCase>();
+}
+
+TEST_F(SetupNewDisplayDeviceInternalTest, createHdrCta816_3_DisplayCase) {
+    setupNewDisplayDeviceInternalTest<HdrCta861_3_DisplayCase>();
+}
+
+} // namespace
+} // namespace android