SF: Move preComposition to CompositionEngine

This moves SurfaceFlinger::preComposition() to
CompositionEngine::preComposition().

As part of the move, CompositionRefreshArgs is also introduced, and to
start contains an array of outputs (not yet used), and potentially
visible layers.

Test: atest libsurfaceflinger_unittest libcompositionengine_test
Bug: 121291683
Change-Id: I0888bd6de1214381222bbae0da93bf966392b303
diff --git a/services/surfaceflinger/CompositionEngine/tests/CompositionEngineTest.cpp b/services/surfaceflinger/CompositionEngine/tests/CompositionEngineTest.cpp
index 3766f27..0dbf8f0 100644
--- a/services/surfaceflinger/CompositionEngine/tests/CompositionEngineTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/CompositionEngineTest.cpp
@@ -14,7 +14,11 @@
  * limitations under the License.
  */
 
+#include <compositionengine/CompositionRefreshArgs.h>
 #include <compositionengine/impl/CompositionEngine.h>
+#include <compositionengine/mock/Layer.h>
+#include <compositionengine/mock/LayerFE.h>
+#include <compositionengine/mock/Output.h>
 #include <gtest/gtest.h>
 #include <renderengine/mock/RenderEngine.h>
 
@@ -23,19 +27,19 @@
 namespace android::compositionengine {
 namespace {
 
+using ::testing::_;
+using ::testing::Return;
+using ::testing::SaveArg;
 using ::testing::StrictMock;
 
 class CompositionEngineTest : public testing::Test {
 public:
-    ~CompositionEngineTest() override;
-    mock::HWComposer* mHwc = new StrictMock<mock::HWComposer>();
+    android::mock::HWComposer* mHwc = new StrictMock<android::mock::HWComposer>();
     renderengine::mock::RenderEngine* mRenderEngine =
             new StrictMock<renderengine::mock::RenderEngine>();
     impl::CompositionEngine mEngine;
 };
 
-CompositionEngineTest::~CompositionEngineTest() = default;
-
 TEST_F(CompositionEngineTest, canInstantiateCompositionEngine) {
     auto engine = impl::createCompositionEngine();
     EXPECT_TRUE(engine.get() != nullptr);
@@ -53,5 +57,84 @@
     EXPECT_EQ(mRenderEngine, &mEngine.getRenderEngine());
 }
 
+/*
+ * CompositionEngine::preComposition
+ */
+
+class PreCompositionTest : public CompositionEngineTest {
+public:
+    PreCompositionTest() {
+        EXPECT_CALL(*mLayer1, getLayerFE()).WillRepeatedly(Return(mLayer1FE));
+        EXPECT_CALL(*mLayer2, getLayerFE()).WillRepeatedly(Return(mLayer2FE));
+        EXPECT_CALL(*mLayer3, getLayerFE()).WillRepeatedly(Return(mLayer3FE));
+        // getLayerFE() can return nullptr. Ensure that this is handled.
+        EXPECT_CALL(*mLayer4, getLayerFE()).WillRepeatedly(Return(nullptr));
+
+        mRefreshArgs.outputs = {mOutput};
+        mRefreshArgs.layers = {mLayer1, mLayer2, mLayer3, mLayer4};
+    }
+
+    std::shared_ptr<mock::Output> mOutput{std::make_shared<StrictMock<mock::Output>>()};
+    std::shared_ptr<mock::Layer> mLayer1{std::make_shared<StrictMock<mock::Layer>>()};
+    std::shared_ptr<mock::Layer> mLayer2{std::make_shared<StrictMock<mock::Layer>>()};
+    std::shared_ptr<mock::Layer> mLayer3{std::make_shared<StrictMock<mock::Layer>>()};
+    std::shared_ptr<mock::Layer> mLayer4{std::make_shared<StrictMock<mock::Layer>>()};
+    sp<StrictMock<mock::LayerFE>> mLayer1FE{new StrictMock<mock::LayerFE>()};
+    sp<StrictMock<mock::LayerFE>> mLayer2FE{new StrictMock<mock::LayerFE>()};
+    sp<StrictMock<mock::LayerFE>> mLayer3FE{new StrictMock<mock::LayerFE>()};
+
+    CompositionRefreshArgs mRefreshArgs;
+};
+
+TEST_F(PreCompositionTest, preCompositionSetsFrameTimestamp) {
+    const nsecs_t before = systemTime(SYSTEM_TIME_MONOTONIC);
+    CompositionRefreshArgs emptyArgs;
+    mEngine.preComposition(emptyArgs);
+    const nsecs_t after = systemTime(SYSTEM_TIME_MONOTONIC);
+
+    // The frame timestamp should be between the before and after timestamps
+    EXPECT_GE(mEngine.getLastFrameRefreshTimestamp(), before);
+    EXPECT_LE(mEngine.getLastFrameRefreshTimestamp(), after);
+}
+
+TEST_F(PreCompositionTest, preCompositionInvokesLayerPreCompositionWithFrameTimestamp) {
+    nsecs_t ts1 = 0;
+    nsecs_t ts2 = 0;
+    nsecs_t ts3 = 0;
+    EXPECT_CALL(*mLayer1FE, onPreComposition(_)).WillOnce(DoAll(SaveArg<0>(&ts1), Return(false)));
+    EXPECT_CALL(*mLayer2FE, onPreComposition(_)).WillOnce(DoAll(SaveArg<0>(&ts2), Return(false)));
+    EXPECT_CALL(*mLayer3FE, onPreComposition(_)).WillOnce(DoAll(SaveArg<0>(&ts3), Return(false)));
+
+    mEngine.preComposition(mRefreshArgs);
+
+    // Each of the onPreComposition calls should used the same refresh timestamp
+    EXPECT_EQ(ts1, mEngine.getLastFrameRefreshTimestamp());
+    EXPECT_EQ(ts2, mEngine.getLastFrameRefreshTimestamp());
+    EXPECT_EQ(ts3, mEngine.getLastFrameRefreshTimestamp());
+}
+
+TEST_F(PreCompositionTest, preCompositionDefaultsToNoUpdateNeeded) {
+    EXPECT_CALL(*mLayer1FE, onPreComposition(_)).WillOnce(Return(false));
+    EXPECT_CALL(*mLayer2FE, onPreComposition(_)).WillOnce(Return(false));
+    EXPECT_CALL(*mLayer3FE, onPreComposition(_)).WillOnce(Return(false));
+
+    mEngine.setNeedsAnotherUpdateForTest(true);
+
+    mEngine.preComposition(mRefreshArgs);
+
+    // The call should have cleared the needsAnotherUpdate flag
+    EXPECT_FALSE(mEngine.needsAnotherUpdate());
+}
+
+TEST_F(PreCompositionTest, preCompositionSetsNeedsAnotherUpdateIfAtLeastOneLayerRequestsIt) {
+    EXPECT_CALL(*mLayer1FE, onPreComposition(_)).WillOnce(Return(true));
+    EXPECT_CALL(*mLayer2FE, onPreComposition(_)).WillOnce(Return(false));
+    EXPECT_CALL(*mLayer3FE, onPreComposition(_)).WillOnce(Return(false));
+
+    mEngine.preComposition(mRefreshArgs);
+
+    EXPECT_TRUE(mEngine.needsAnotherUpdate());
+}
+
 } // namespace
 } // namespace android::compositionengine