SF: Intro CE::OutputLayer
Introduce compositionengine::OutputLayer, for representing the
composition state of a layer on an output (display)
This change just introduces the OutputLayer class, and modifies
SurfaceFlinger.cpp to create them properly. The new class does not yet
have any state.
Test: atest libsurfaceflinger_unittest libcompositionengine_test
Bug: 121291683
Change-Id: Ic8fe0fee61470b36539287883d4901b25208b634
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
new file mode 100644
index 0000000..0a929ac
--- /dev/null
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <compositionengine/impl/OutputLayer.h>
+#include <compositionengine/mock/Layer.h>
+#include <compositionengine/mock/LayerFE.h>
+#include <compositionengine/mock/Output.h>
+#include <gtest/gtest.h>
+
+namespace android::compositionengine {
+namespace {
+
+using testing::StrictMock;
+
+class OutputLayerTest : public testing::Test {
+public:
+ ~OutputLayerTest() override = default;
+
+ compositionengine::mock::Output mOutput;
+ std::shared_ptr<compositionengine::mock::Layer> mLayer{
+ new StrictMock<compositionengine::mock::Layer>()};
+ sp<compositionengine::mock::LayerFE> mLayerFE{
+ new StrictMock<compositionengine::mock::LayerFE>()};
+ impl::OutputLayer mOutputLayer{mOutput, mLayer, mLayerFE};
+};
+
+/* ------------------------------------------------------------------------
+ * Basic construction
+ */
+
+TEST_F(OutputLayerTest, canInstantiateOutputLayer) {}
+
+} // namespace
+} // namespace android::compositionengine
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
index 0df1dab..314d98b 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
@@ -19,6 +19,9 @@
#include <compositionengine/impl/Output.h>
#include <compositionengine/mock/CompositionEngine.h>
#include <compositionengine/mock/DisplayColorProfile.h>
+#include <compositionengine/mock/Layer.h>
+#include <compositionengine/mock/LayerFE.h>
+#include <compositionengine/mock/OutputLayer.h>
#include <compositionengine/mock/RenderSurface.h>
#include <gtest/gtest.h>
#include <ui/Rect.h>
@@ -267,5 +270,84 @@
EXPECT_FALSE(mOutput.belongsInOutput(layerStack2, false));
}
+/* ------------------------------------------------------------------------
+ * Output::getOutputLayerForLayer()
+ */
+
+TEST_F(OutputTest, getOutputLayerForLayerWorks) {
+ mock::OutputLayer* outputLayer1 = new StrictMock<mock::OutputLayer>();
+ mock::OutputLayer* outputLayer2 = new StrictMock<mock::OutputLayer>();
+
+ Output::OutputLayers outputLayers;
+ outputLayers.emplace_back(std::unique_ptr<OutputLayer>(outputLayer1));
+ outputLayers.emplace_back(nullptr);
+ outputLayers.emplace_back(std::unique_ptr<OutputLayer>(outputLayer2));
+ mOutput.setOutputLayersOrderedByZ(std::move(outputLayers));
+
+ StrictMock<mock::Layer> layer;
+ StrictMock<mock::Layer> otherLayer;
+
+ // If the input layer matches the first OutputLayer, it will be returned.
+ EXPECT_CALL(*outputLayer1, getLayer()).WillOnce(ReturnRef(layer));
+ EXPECT_EQ(outputLayer1, mOutput.getOutputLayerForLayer(&layer));
+
+ // If the input layer matches the second OutputLayer, it will be returned.
+ EXPECT_CALL(*outputLayer1, getLayer()).WillOnce(ReturnRef(otherLayer));
+ EXPECT_CALL(*outputLayer2, getLayer()).WillOnce(ReturnRef(layer));
+ EXPECT_EQ(outputLayer2, mOutput.getOutputLayerForLayer(&layer));
+
+ // If the input layer does not match an output layer, null will be returned.
+ EXPECT_CALL(*outputLayer1, getLayer()).WillOnce(ReturnRef(otherLayer));
+ EXPECT_CALL(*outputLayer2, getLayer()).WillOnce(ReturnRef(otherLayer));
+ EXPECT_EQ(nullptr, mOutput.getOutputLayerForLayer(&layer));
+}
+
+/* ------------------------------------------------------------------------
+ * Output::getOrCreateOutputLayer()
+ */
+
+TEST_F(OutputTest, getOrCreateOutputLayerWorks) {
+ mock::OutputLayer* existingOutputLayer = new StrictMock<mock::OutputLayer>();
+
+ Output::OutputLayers outputLayers;
+ outputLayers.emplace_back(nullptr);
+ outputLayers.emplace_back(std::unique_ptr<OutputLayer>(existingOutputLayer));
+ mOutput.setOutputLayersOrderedByZ(std::move(outputLayers));
+
+ std::shared_ptr<mock::Layer> layer{new StrictMock<mock::Layer>()};
+ sp<LayerFE> layerFE{new StrictMock<mock::LayerFE>()};
+
+ StrictMock<mock::Layer> otherLayer;
+
+ {
+ // 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);
+ EXPECT_NE(existingOutputLayer, result.get());
+ EXPECT_TRUE(result.get() != nullptr);
+ EXPECT_EQ(layer.get(), &result->getLayer());
+ EXPECT_EQ(layerFE.get(), &result->getLayerFE());
+
+ // The entries in the ordered array should be unchanged.
+ auto& outputLayers = mOutput.getOutputLayersOrderedByZ();
+ EXPECT_EQ(nullptr, outputLayers[0].get());
+ EXPECT_EQ(existingOutputLayer, outputLayers[1].get());
+ }
+
+ {
+ // 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);
+ EXPECT_EQ(existingOutputLayer, result.get());
+
+ // The corresponding entry in the ordered array should be cleared.
+ auto& outputLayers = mOutput.getOutputLayersOrderedByZ();
+ EXPECT_EQ(nullptr, outputLayers[0].get());
+ EXPECT_EQ(nullptr, outputLayers[1].get());
+ }
+}
+
} // namespace
} // namespace android::compositionengine