SF: Move management of HWC layers to compositionengine::OutputLayer

OutputLayer creates a HWC layer (if appropriate) on initialization, and
the HWC layer is destroyed with the OutputLayer.

Removes all explicit calls to create/destroy the HWC layers from the front-end
Layer code, and a few other places.

A call is also added to destroy all OutputLayers before switching in or
out of VrComposer mode. This change already marked the geometry as dirty
-- this just ensures all the HWC layers are recreated.

Test: atest libsurfaceflinger_unittest libcompositionengine_test
Test: atest dvr_display-test
Test: atest CtsViewTestCases
Bug: 121291683
Bug: 124537779
Change-Id: Ib7aec9e998ed5481d2753d19b061ba922e54bfe0
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h
index 2201bdd..785a6d7 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h
@@ -36,6 +36,10 @@
  * Used by LayerFE::getCompositionState
  */
 struct LayerFECompositionState {
+    // TODO(lpique): b/121291683 Remove this one we are sure we don't need the
+    // value recomputed / set every frame.
+    Region geomVisibleRegion;
+
     /*
      * Presentation
      */
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
index 84b2423..54e6bd6 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
@@ -17,6 +17,7 @@
 #pragma once
 
 #include <cstdint>
+#include <optional>
 #include <string>
 
 #include <math/mat4.h>
@@ -25,6 +26,8 @@
 #include <ui/Transform.h>
 #include <utils/StrongPointer.h>
 
+#include "DisplayHardware/DisplayIdentification.h"
+
 namespace android::compositionengine {
 
 class DisplayColorProfile;
@@ -117,7 +120,8 @@
     // Gets the OutputLayer corresponding to the input Layer instance from the
     // current ordered set of output layers. If there is no such layer, a new
     // one is created and returned.
-    virtual std::unique_ptr<OutputLayer> getOrCreateOutputLayer(std::shared_ptr<Layer>,
+    virtual std::unique_ptr<OutputLayer> getOrCreateOutputLayer(std::optional<DisplayId>,
+                                                                std::shared_ptr<Layer>,
                                                                 sp<LayerFE>) = 0;
 
     // Sets the new ordered set of output layers for this output
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h
index 48cb581..e7a17c4 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h
@@ -16,14 +16,18 @@
 
 #pragma once
 
+#include <optional>
 #include <string>
 
 #include <utils/StrongPointer.h>
 
+#include "DisplayHardware/DisplayIdentification.h"
+
 namespace android {
 
 namespace compositionengine {
 
+class CompositionEngine;
 class Output;
 class Layer;
 class LayerFE;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
index 3fd057c..b1d1f42 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
@@ -67,7 +67,8 @@
     compositionengine::OutputLayer* getOutputLayerForLayer(
             compositionengine::Layer*) const override;
     std::unique_ptr<compositionengine::OutputLayer> getOrCreateOutputLayer(
-            std::shared_ptr<compositionengine::Layer>, sp<LayerFE>) override;
+            std::optional<DisplayId>, std::shared_ptr<compositionengine::Layer>,
+            sp<LayerFE>) override;
     void setOutputLayersOrderedByZ(OutputLayers&&) override;
     const OutputLayers& getOutputLayersOrderedByZ() const override;
 
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h
index 5798540..d8f0cdd 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h
@@ -22,6 +22,8 @@
 #include <compositionengine/OutputLayer.h>
 #include <compositionengine/impl/OutputLayerCompositionState.h>
 
+#include "DisplayHardware/DisplayIdentification.h"
+
 namespace android::compositionengine::impl {
 
 class OutputLayer : public compositionengine::OutputLayer {
@@ -30,6 +32,8 @@
                 sp<compositionengine::LayerFE>);
     ~OutputLayer() override;
 
+    void initialize(const CompositionEngine&, std::optional<DisplayId>);
+
     const compositionengine::Output& getOutput() const override;
     compositionengine::Layer& getLayer() const override;
     compositionengine::LayerFE& getLayerFE() const override;
@@ -48,7 +52,7 @@
 };
 
 std::unique_ptr<compositionengine::OutputLayer> createOutputLayer(
-        const compositionengine::Output&, std::shared_ptr<compositionengine::Layer>,
-        sp<compositionengine::LayerFE>);
+        const CompositionEngine&, std::optional<DisplayId>, const compositionengine::Output&,
+        std::shared_ptr<compositionengine::Layer>, sp<compositionengine::LayerFE>);
 
 } // namespace android::compositionengine::impl
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h
index 2972ad7..d0e7b19 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h
@@ -61,9 +61,9 @@
 
     MOCK_CONST_METHOD1(getOutputLayerForLayer,
                        compositionengine::OutputLayer*(compositionengine::Layer*));
-    MOCK_METHOD2(getOrCreateOutputLayer,
+    MOCK_METHOD3(getOrCreateOutputLayer,
                  std::unique_ptr<compositionengine::OutputLayer>(
-                         std::shared_ptr<compositionengine::Layer>,
+                         std::optional<DisplayId>, std::shared_ptr<compositionengine::Layer>,
                          sp<compositionengine::LayerFE>));
     MOCK_METHOD1(setOutputLayersOrderedByZ, void(OutputLayers&&));
     MOCK_CONST_METHOD0(getOutputLayersOrderedByZ, OutputLayers&());
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h
index 6bd61ee..54c7407 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h
@@ -16,6 +16,7 @@
 
 #pragma once
 
+#include <compositionengine/CompositionEngine.h>
 #include <compositionengine/Layer.h>
 #include <compositionengine/LayerFE.h>
 #include <compositionengine/Output.h>
diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp
index f97add4..ad4c7bf 100644
--- a/services/surfaceflinger/CompositionEngine/src/Output.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp
@@ -217,13 +217,14 @@
 }
 
 std::unique_ptr<compositionengine::OutputLayer> Output::getOrCreateOutputLayer(
-        std::shared_ptr<compositionengine::Layer> layer, sp<compositionengine::LayerFE> layerFE) {
+        std::optional<DisplayId> displayId, std::shared_ptr<compositionengine::Layer> layer,
+        sp<compositionengine::LayerFE> layerFE) {
     for (auto& outputLayer : mOutputLayersOrderedByZ) {
         if (outputLayer && &outputLayer->getLayer() == layer.get()) {
             return std::move(outputLayer);
         }
     }
-    return createOutputLayer(*this, layer, layerFE);
+    return createOutputLayer(mCompositionEngine, displayId, *this, layer, layerFE);
 }
 
 void Output::setOutputLayersOrderedByZ(OutputLayers&& layers) {
diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
index 78c1403..10da49d 100644
--- a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
@@ -15,11 +15,14 @@
  */
 
 #include <android-base/stringprintf.h>
+#include <compositionengine/CompositionEngine.h>
 #include <compositionengine/Layer.h>
 #include <compositionengine/LayerFE.h>
 #include <compositionengine/Output.h>
 #include <compositionengine/impl/OutputLayer.h>
 
+#include "DisplayHardware/HWComposer.h"
+
 namespace android::compositionengine {
 
 OutputLayer::~OutputLayer() = default;
@@ -27,9 +30,12 @@
 namespace impl {
 
 std::unique_ptr<compositionengine::OutputLayer> createOutputLayer(
-        const compositionengine::Output& display, std::shared_ptr<compositionengine::Layer> layer,
+        const CompositionEngine& compositionEngine, std::optional<DisplayId> displayId,
+        const compositionengine::Output& output, std::shared_ptr<compositionengine::Layer> layer,
         sp<compositionengine::LayerFE> layerFE) {
-    return std::make_unique<OutputLayer>(display, layer, layerFE);
+    auto result = std::make_unique<OutputLayer>(output, layer, layerFE);
+    result->initialize(compositionEngine, displayId);
+    return result;
 }
 
 OutputLayer::OutputLayer(const Output& output, std::shared_ptr<Layer> layer, sp<LayerFE> layerFE)
@@ -37,6 +43,20 @@
 
 OutputLayer::~OutputLayer() = default;
 
+void OutputLayer::initialize(const CompositionEngine& compositionEngine,
+                             std::optional<DisplayId> displayId) {
+    if (!displayId) {
+        return;
+    }
+
+    auto& hwc = compositionEngine.getHwComposer();
+
+    mState.hwc.emplace(std::shared_ptr<HWC2::Layer>(hwc.createLayer(*displayId),
+                                                    [&hwc, displayId](HWC2::Layer* layer) {
+                                                        hwc.destroyLayer(*displayId, layer);
+                                                    }));
+}
+
 const compositionengine::Output& OutputLayer::getOutput() const {
     return mOutput;
 }
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
index 0a929ac..f7dcf6f 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
@@ -15,16 +15,22 @@
  */
 
 #include <compositionengine/impl/OutputLayer.h>
+#include <compositionengine/mock/CompositionEngine.h>
 #include <compositionengine/mock/Layer.h>
 #include <compositionengine/mock/LayerFE.h>
 #include <compositionengine/mock/Output.h>
 #include <gtest/gtest.h>
 
+#include "MockHWC2.h"
+#include "MockHWComposer.h"
+
 namespace android::compositionengine {
 namespace {
 
 using testing::StrictMock;
 
+constexpr DisplayId DEFAULT_DISPLAY_ID = DisplayId{42};
+
 class OutputLayerTest : public testing::Test {
 public:
     ~OutputLayerTest() override = default;
@@ -43,5 +49,37 @@
 
 TEST_F(OutputLayerTest, canInstantiateOutputLayer) {}
 
+/* ------------------------------------------------------------------------
+ * OutputLayer::initialize()
+ */
+
+TEST_F(OutputLayerTest, initializingOutputLayerWithoutHwcDoesNothingInteresting) {
+    StrictMock<compositionengine::mock::CompositionEngine> compositionEngine;
+
+    mOutputLayer.initialize(compositionEngine, std::nullopt);
+
+    EXPECT_FALSE(mOutputLayer.getState().hwc);
+}
+
+TEST_F(OutputLayerTest, initializingOutputLayerWithHwcDisplayCreatesHwcLayer) {
+    StrictMock<compositionengine::mock::CompositionEngine> compositionEngine;
+    StrictMock<android::mock::HWComposer> hwc;
+    StrictMock<HWC2::mock::Layer> hwcLayer;
+
+    EXPECT_CALL(compositionEngine, getHwComposer()).WillOnce(ReturnRef(hwc));
+    EXPECT_CALL(hwc, createLayer(DEFAULT_DISPLAY_ID)).WillOnce(Return(&hwcLayer));
+
+    mOutputLayer.initialize(compositionEngine, DEFAULT_DISPLAY_ID);
+
+    const auto& state = mOutputLayer.getState();
+    ASSERT_TRUE(state.hwc);
+
+    const auto& hwcState = *state.hwc;
+    EXPECT_EQ(&hwcLayer, hwcState.hwcLayer.get());
+
+    EXPECT_CALL(hwc, destroyLayer(DEFAULT_DISPLAY_ID, &hwcLayer));
+    mOutputLayer.editState().hwc.reset();
+}
+
 } // namespace
 } // namespace android::compositionengine
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
index cb71821..a84af3a 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
@@ -338,7 +338,7 @@
         // If there is no OutputLayer corresponding to the input layer, a
         // new OutputLayer is constructed and returned.
         EXPECT_CALL(*existingOutputLayer, getLayer()).WillOnce(ReturnRef(otherLayer));
-        auto result = mOutput.getOrCreateOutputLayer(layer, layerFE);
+        auto result = mOutput.getOrCreateOutputLayer(std::nullopt, layer, layerFE);
         EXPECT_NE(existingOutputLayer, result.get());
         EXPECT_TRUE(result.get() != nullptr);
         EXPECT_EQ(layer.get(), &result->getLayer());
@@ -354,7 +354,7 @@
         // If there is an existing OutputLayer for the requested layer, an owned
         // pointer is returned
         EXPECT_CALL(*existingOutputLayer, getLayer()).WillOnce(ReturnRef(*layer));
-        auto result = mOutput.getOrCreateOutputLayer(layer, layerFE);
+        auto result = mOutput.getOrCreateOutputLayer(std::nullopt, layer, layerFE);
         EXPECT_EQ(existingOutputLayer, result.get());
 
         // The corresponding entry in the ordered array should be cleared.