blob: bcaa5294270c0a612b31d3448a3de6c7a681448d [file] [log] [blame]
Lloyd Pique70d91362018-10-18 16:02:55 -07001/*
2 * Copyright 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Ady Abrahamb0dbdaa2020-01-06 16:19:42 -080017// TODO(b/129481165): remove the #pragma below and fix conversion issues
18#pragma clang diagnostic push
19#pragma clang diagnostic ignored "-Wconversion"
20
Lloyd Piqueab039b52019-02-13 14:22:42 -080021#include <compositionengine/CompositionRefreshArgs.h>
Lloyd Piqueaed56ab2019-11-13 22:34:11 -080022#include <compositionengine/LayerFECompositionState.h>
Lloyd Pique70d91362018-10-18 16:02:55 -070023#include <compositionengine/impl/CompositionEngine.h>
Lloyd Piqueab039b52019-02-13 14:22:42 -080024#include <compositionengine/mock/Layer.h>
25#include <compositionengine/mock/LayerFE.h>
26#include <compositionengine/mock/Output.h>
Lloyd Piqueaed56ab2019-11-13 22:34:11 -080027#include <compositionengine/mock/OutputLayer.h>
Lloyd Pique70d91362018-10-18 16:02:55 -070028#include <gtest/gtest.h>
Lloyd Piqueb97e04f2018-10-18 17:07:05 -070029#include <renderengine/mock/RenderEngine.h>
Lloyd Pique70d91362018-10-18 16:02:55 -070030
Lloyd Pique441d5042018-10-18 16:49:51 -070031#include "MockHWComposer.h"
Alec Mourie4034bb2019-11-19 12:45:54 -080032#include "TimeStats/TimeStats.h"
Lloyd Pique441d5042018-10-18 16:49:51 -070033
Lloyd Pique70d91362018-10-18 16:02:55 -070034namespace android::compositionengine {
35namespace {
36
Lloyd Piqueab039b52019-02-13 14:22:42 -080037using ::testing::_;
Lloyd Piquee82ed2d2019-11-13 19:28:12 -080038using ::testing::InSequence;
39using ::testing::Ref;
Lloyd Piqueab039b52019-02-13 14:22:42 -080040using ::testing::Return;
Lloyd Piqueaed56ab2019-11-13 22:34:11 -080041using ::testing::ReturnRef;
Lloyd Piqueab039b52019-02-13 14:22:42 -080042using ::testing::SaveArg;
Lloyd Pique441d5042018-10-18 16:49:51 -070043using ::testing::StrictMock;
44
Lloyd Piquee82ed2d2019-11-13 19:28:12 -080045struct CompositionEngineTest : public testing::Test {
Lloyd Piqueab039b52019-02-13 14:22:42 -080046 android::mock::HWComposer* mHwc = new StrictMock<android::mock::HWComposer>();
Lloyd Piqueb97e04f2018-10-18 17:07:05 -070047 renderengine::mock::RenderEngine* mRenderEngine =
48 new StrictMock<renderengine::mock::RenderEngine>();
Alec Mourie4034bb2019-11-19 12:45:54 -080049 std::shared_ptr<TimeStats> mTimeStats;
50
Lloyd Pique441d5042018-10-18 16:49:51 -070051 impl::CompositionEngine mEngine;
Lloyd Piquee82ed2d2019-11-13 19:28:12 -080052 CompositionRefreshArgs mRefreshArgs;
53
54 std::shared_ptr<mock::Output> mOutput1{std::make_shared<StrictMock<mock::Output>>()};
55 std::shared_ptr<mock::Output> mOutput2{std::make_shared<StrictMock<mock::Output>>()};
56 std::shared_ptr<mock::Output> mOutput3{std::make_shared<StrictMock<mock::Output>>()};
57
58 std::shared_ptr<mock::Layer> mLayer1{std::make_shared<StrictMock<mock::Layer>>()};
59 std::shared_ptr<mock::Layer> mLayer2{std::make_shared<StrictMock<mock::Layer>>()};
60 std::shared_ptr<mock::Layer> mLayer3{std::make_shared<StrictMock<mock::Layer>>()};
61 std::shared_ptr<mock::Layer> mLayer4{std::make_shared<StrictMock<mock::Layer>>()};
Lloyd Pique70d91362018-10-18 16:02:55 -070062};
63
Lloyd Pique70d91362018-10-18 16:02:55 -070064TEST_F(CompositionEngineTest, canInstantiateCompositionEngine) {
65 auto engine = impl::createCompositionEngine();
66 EXPECT_TRUE(engine.get() != nullptr);
67}
68
Lloyd Pique441d5042018-10-18 16:49:51 -070069TEST_F(CompositionEngineTest, canSetHWComposer) {
70 mEngine.setHwComposer(std::unique_ptr<android::HWComposer>(mHwc));
71
72 EXPECT_EQ(mHwc, &mEngine.getHwComposer());
73}
74
Lloyd Piqueb97e04f2018-10-18 17:07:05 -070075TEST_F(CompositionEngineTest, canSetRenderEngine) {
76 mEngine.setRenderEngine(std::unique_ptr<renderengine::RenderEngine>(mRenderEngine));
77
78 EXPECT_EQ(mRenderEngine, &mEngine.getRenderEngine());
79}
80
Alec Mourie4034bb2019-11-19 12:45:54 -080081TEST_F(CompositionEngineTest, canSetTimeStats) {
82 mEngine.setTimeStats(mTimeStats);
83
84 EXPECT_EQ(mTimeStats.get(), &mEngine.getTimeStats());
85}
86
Lloyd Piqueab039b52019-02-13 14:22:42 -080087/*
Lloyd Piquee82ed2d2019-11-13 19:28:12 -080088 * CompositionEngine::present
89 */
90
91struct CompositionEnginePresentTest : public CompositionEngineTest {
92 struct CompositionEnginePartialMock : public impl::CompositionEngine {
93 // These are the overridable functions CompositionEngine::present() may
94 // call, and have separate test coverage.
95 MOCK_METHOD1(preComposition, void(CompositionRefreshArgs&));
96 };
97
98 StrictMock<CompositionEnginePartialMock> mEngine;
99};
100
101TEST_F(CompositionEnginePresentTest, worksWithEmptyRequest) {
102 // present() always calls preComposition()
103 EXPECT_CALL(mEngine, preComposition(Ref(mRefreshArgs)));
104
105 mEngine.present(mRefreshArgs);
106}
107
108TEST_F(CompositionEnginePresentTest, worksAsExpected) {
109 // Expect calls to in a certain sequence
110 InSequence seq;
111
112 // present() always calls preComposition()
113 EXPECT_CALL(mEngine, preComposition(Ref(mRefreshArgs)));
114
115 // The first step in presenting is to make sure all outputs are prepared.
116 EXPECT_CALL(*mOutput1, prepare(Ref(mRefreshArgs), _));
117 EXPECT_CALL(*mOutput2, prepare(Ref(mRefreshArgs), _));
118 EXPECT_CALL(*mOutput3, prepare(Ref(mRefreshArgs), _));
119
120 // The next step in presenting is to make sure all outputs have the latest
121 // state from the front-end (SurfaceFlinger).
122 EXPECT_CALL(*mOutput1, updateLayerStateFromFE(Ref(mRefreshArgs)));
123 EXPECT_CALL(*mOutput2, updateLayerStateFromFE(Ref(mRefreshArgs)));
124 EXPECT_CALL(*mOutput3, updateLayerStateFromFE(Ref(mRefreshArgs)));
125
126 // The last step is to actually present each output.
127 EXPECT_CALL(*mOutput1, present(Ref(mRefreshArgs)));
128 EXPECT_CALL(*mOutput2, present(Ref(mRefreshArgs)));
129 EXPECT_CALL(*mOutput3, present(Ref(mRefreshArgs)));
130
131 mRefreshArgs.outputs = {mOutput1, mOutput2, mOutput3};
132 mEngine.present(mRefreshArgs);
133}
134
135/*
Lloyd Piqueaed56ab2019-11-13 22:34:11 -0800136 * CompositionEngine::updateCursorAsync
137 */
138
139struct CompositionEngineUpdateCursorAsyncTest : public CompositionEngineTest {
140public:
141 CompositionEngineUpdateCursorAsyncTest() {
Lloyd Pique0a456232020-01-16 17:51:13 -0800142 EXPECT_CALL(*mOutput1, getOutputLayerCount()).WillRepeatedly(Return(0u));
Lloyd Piqueaed56ab2019-11-13 22:34:11 -0800143 EXPECT_CALL(*mOutput1, getOutputLayerOrderedByZByIndex(_)).Times(0);
144
Lloyd Pique0a456232020-01-16 17:51:13 -0800145 EXPECT_CALL(*mOutput2, getOutputLayerCount()).WillRepeatedly(Return(1u));
Lloyd Piqueaed56ab2019-11-13 22:34:11 -0800146 EXPECT_CALL(*mOutput2, getOutputLayerOrderedByZByIndex(0))
147 .WillRepeatedly(Return(&mOutput2OutputLayer1));
148
Lloyd Pique0a456232020-01-16 17:51:13 -0800149 EXPECT_CALL(*mOutput3, getOutputLayerCount()).WillRepeatedly(Return(2u));
Lloyd Piqueaed56ab2019-11-13 22:34:11 -0800150 EXPECT_CALL(*mOutput3, getOutputLayerOrderedByZByIndex(0))
151 .WillRepeatedly(Return(&mOutput3OutputLayer1));
152 EXPECT_CALL(*mOutput3, getOutputLayerOrderedByZByIndex(1))
153 .WillRepeatedly(Return(&mOutput3OutputLayer2));
154
155 EXPECT_CALL(mOutput2OutputLayer1, getLayerFE()).WillRepeatedly(ReturnRef(mOutput2Layer1FE));
156 EXPECT_CALL(mOutput3OutputLayer1, getLayerFE()).WillRepeatedly(ReturnRef(mOutput3Layer1FE));
157 EXPECT_CALL(mOutput3OutputLayer2, getLayerFE()).WillRepeatedly(ReturnRef(mOutput3Layer2FE));
158
159 EXPECT_CALL(mOutput2OutputLayer1, getLayer()).WillRepeatedly(ReturnRef(mOutput2Layer1));
160 EXPECT_CALL(mOutput3OutputLayer1, getLayer()).WillRepeatedly(ReturnRef(mOutput3Layer1));
161 EXPECT_CALL(mOutput3OutputLayer2, getLayer()).WillRepeatedly(ReturnRef(mOutput3Layer2));
162
163 EXPECT_CALL(mOutput2Layer1, editFEState()).WillRepeatedly(ReturnRef(mOutput2Layer1FEState));
164 EXPECT_CALL(mOutput3Layer1, editFEState()).WillRepeatedly(ReturnRef(mOutput3Layer1FEState));
165 EXPECT_CALL(mOutput3Layer2, editFEState()).WillRepeatedly(ReturnRef(mOutput3Layer2FEState));
166 }
167
168 StrictMock<mock::OutputLayer> mOutput2OutputLayer1;
169 StrictMock<mock::OutputLayer> mOutput3OutputLayer1;
170 StrictMock<mock::OutputLayer> mOutput3OutputLayer2;
171
172 StrictMock<mock::LayerFE> mOutput2Layer1FE;
173 StrictMock<mock::LayerFE> mOutput3Layer1FE;
174 StrictMock<mock::LayerFE> mOutput3Layer2FE;
175
176 StrictMock<mock::Layer> mOutput2Layer1;
177 StrictMock<mock::Layer> mOutput3Layer1;
178 StrictMock<mock::Layer> mOutput3Layer2;
179
180 LayerFECompositionState mOutput2Layer1FEState;
181 LayerFECompositionState mOutput3Layer1FEState;
182 LayerFECompositionState mOutput3Layer2FEState;
183};
184
185TEST_F(CompositionEngineUpdateCursorAsyncTest, handlesNoOutputs) {
186 mEngine.updateCursorAsync(mRefreshArgs);
187}
188
189TEST_F(CompositionEngineUpdateCursorAsyncTest, handlesNoLayersBeingCursorLayers) {
190 EXPECT_CALL(mOutput2OutputLayer1, isHardwareCursor()).WillRepeatedly(Return(false));
191 EXPECT_CALL(mOutput3OutputLayer1, isHardwareCursor()).WillRepeatedly(Return(false));
192 EXPECT_CALL(mOutput3OutputLayer2, isHardwareCursor()).WillRepeatedly(Return(false));
193
194 mRefreshArgs.outputs = {mOutput1, mOutput2, mOutput3};
195
196 mEngine.updateCursorAsync(mRefreshArgs);
197}
198
199TEST_F(CompositionEngineUpdateCursorAsyncTest, handlesMultipleLayersBeingCursorLayers) {
200 {
201 InSequence seq;
202 EXPECT_CALL(mOutput2OutputLayer1, isHardwareCursor()).WillRepeatedly(Return(true));
203 EXPECT_CALL(mOutput2Layer1FE, latchCursorCompositionState(Ref(mOutput2Layer1FEState)));
204 EXPECT_CALL(mOutput2OutputLayer1, writeCursorPositionToHWC());
205 }
206
207 {
208 InSequence seq;
209 EXPECT_CALL(mOutput3OutputLayer1, isHardwareCursor()).WillRepeatedly(Return(true));
210 EXPECT_CALL(mOutput3Layer1FE, latchCursorCompositionState(Ref(mOutput3Layer1FEState)));
211 EXPECT_CALL(mOutput3OutputLayer1, writeCursorPositionToHWC());
212 }
213
214 {
215 InSequence seq;
216 EXPECT_CALL(mOutput3OutputLayer2, isHardwareCursor()).WillRepeatedly(Return(true));
217 EXPECT_CALL(mOutput3Layer2FE, latchCursorCompositionState(Ref(mOutput3Layer2FEState)));
218 EXPECT_CALL(mOutput3OutputLayer2, writeCursorPositionToHWC());
219 }
220
221 mRefreshArgs.outputs = {mOutput1, mOutput2, mOutput3};
222
223 mEngine.updateCursorAsync(mRefreshArgs);
224}
225
226/*
Lloyd Piqueab039b52019-02-13 14:22:42 -0800227 * CompositionEngine::preComposition
228 */
229
Lloyd Piquee82ed2d2019-11-13 19:28:12 -0800230struct CompositionTestPreComposition : public CompositionEngineTest {
231 CompositionTestPreComposition() {
Lloyd Piqueab039b52019-02-13 14:22:42 -0800232 EXPECT_CALL(*mLayer1, getLayerFE()).WillRepeatedly(Return(mLayer1FE));
233 EXPECT_CALL(*mLayer2, getLayerFE()).WillRepeatedly(Return(mLayer2FE));
234 EXPECT_CALL(*mLayer3, getLayerFE()).WillRepeatedly(Return(mLayer3FE));
235 // getLayerFE() can return nullptr. Ensure that this is handled.
236 EXPECT_CALL(*mLayer4, getLayerFE()).WillRepeatedly(Return(nullptr));
Lloyd Piqueab039b52019-02-13 14:22:42 -0800237 }
238
Lloyd Piqueab039b52019-02-13 14:22:42 -0800239 sp<StrictMock<mock::LayerFE>> mLayer1FE{new StrictMock<mock::LayerFE>()};
240 sp<StrictMock<mock::LayerFE>> mLayer2FE{new StrictMock<mock::LayerFE>()};
241 sp<StrictMock<mock::LayerFE>> mLayer3FE{new StrictMock<mock::LayerFE>()};
Lloyd Piqueab039b52019-02-13 14:22:42 -0800242};
243
Lloyd Piquee82ed2d2019-11-13 19:28:12 -0800244TEST_F(CompositionTestPreComposition, preCompositionSetsFrameTimestamp) {
Lloyd Piqueab039b52019-02-13 14:22:42 -0800245 const nsecs_t before = systemTime(SYSTEM_TIME_MONOTONIC);
Lloyd Piquee82ed2d2019-11-13 19:28:12 -0800246 mEngine.preComposition(mRefreshArgs);
Lloyd Piqueab039b52019-02-13 14:22:42 -0800247 const nsecs_t after = systemTime(SYSTEM_TIME_MONOTONIC);
248
249 // The frame timestamp should be between the before and after timestamps
250 EXPECT_GE(mEngine.getLastFrameRefreshTimestamp(), before);
251 EXPECT_LE(mEngine.getLastFrameRefreshTimestamp(), after);
252}
253
Lloyd Piquee82ed2d2019-11-13 19:28:12 -0800254TEST_F(CompositionTestPreComposition, preCompositionInvokesLayerPreCompositionWithFrameTimestamp) {
Lloyd Piqueab039b52019-02-13 14:22:42 -0800255 nsecs_t ts1 = 0;
256 nsecs_t ts2 = 0;
257 nsecs_t ts3 = 0;
258 EXPECT_CALL(*mLayer1FE, onPreComposition(_)).WillOnce(DoAll(SaveArg<0>(&ts1), Return(false)));
259 EXPECT_CALL(*mLayer2FE, onPreComposition(_)).WillOnce(DoAll(SaveArg<0>(&ts2), Return(false)));
260 EXPECT_CALL(*mLayer3FE, onPreComposition(_)).WillOnce(DoAll(SaveArg<0>(&ts3), Return(false)));
261
Lloyd Piquee82ed2d2019-11-13 19:28:12 -0800262 mRefreshArgs.outputs = {mOutput1};
263 mRefreshArgs.layers = {mLayer1, mLayer2, mLayer3, mLayer4};
264
Lloyd Piqueab039b52019-02-13 14:22:42 -0800265 mEngine.preComposition(mRefreshArgs);
266
267 // Each of the onPreComposition calls should used the same refresh timestamp
268 EXPECT_EQ(ts1, mEngine.getLastFrameRefreshTimestamp());
269 EXPECT_EQ(ts2, mEngine.getLastFrameRefreshTimestamp());
270 EXPECT_EQ(ts3, mEngine.getLastFrameRefreshTimestamp());
271}
272
Lloyd Piquee82ed2d2019-11-13 19:28:12 -0800273TEST_F(CompositionTestPreComposition, preCompositionDefaultsToNoUpdateNeeded) {
Lloyd Piqueab039b52019-02-13 14:22:42 -0800274 EXPECT_CALL(*mLayer1FE, onPreComposition(_)).WillOnce(Return(false));
275 EXPECT_CALL(*mLayer2FE, onPreComposition(_)).WillOnce(Return(false));
276 EXPECT_CALL(*mLayer3FE, onPreComposition(_)).WillOnce(Return(false));
277
278 mEngine.setNeedsAnotherUpdateForTest(true);
279
Lloyd Piquee82ed2d2019-11-13 19:28:12 -0800280 mRefreshArgs.outputs = {mOutput1};
281 mRefreshArgs.layers = {mLayer1, mLayer2, mLayer3, mLayer4};
282
Lloyd Piqueab039b52019-02-13 14:22:42 -0800283 mEngine.preComposition(mRefreshArgs);
284
285 // The call should have cleared the needsAnotherUpdate flag
286 EXPECT_FALSE(mEngine.needsAnotherUpdate());
287}
288
Lloyd Piquee82ed2d2019-11-13 19:28:12 -0800289TEST_F(CompositionTestPreComposition,
290 preCompositionSetsNeedsAnotherUpdateIfAtLeastOneLayerRequestsIt) {
Lloyd Piqueab039b52019-02-13 14:22:42 -0800291 EXPECT_CALL(*mLayer1FE, onPreComposition(_)).WillOnce(Return(true));
292 EXPECT_CALL(*mLayer2FE, onPreComposition(_)).WillOnce(Return(false));
293 EXPECT_CALL(*mLayer3FE, onPreComposition(_)).WillOnce(Return(false));
294
Lloyd Piquee82ed2d2019-11-13 19:28:12 -0800295 mRefreshArgs.outputs = {mOutput1};
296 mRefreshArgs.layers = {mLayer1, mLayer2, mLayer3, mLayer4};
297
Lloyd Piqueab039b52019-02-13 14:22:42 -0800298 mEngine.preComposition(mRefreshArgs);
299
300 EXPECT_TRUE(mEngine.needsAnotherUpdate());
301}
302
Lloyd Pique70d91362018-10-18 16:02:55 -0700303} // namespace
304} // namespace android::compositionengine
Ady Abrahamb0dbdaa2020-01-06 16:19:42 -0800305
306// TODO(b/129481165): remove the #pragma below and fix conversion issues
307#pragma clang diagnostic pop // ignored "-Wconversion"