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