1 /*
2 * Copyright 2024 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
17 #include <gmock/gmock.h>
18 #include <gtest/gtest.h>
19
20 #include <android/gui/ActivePicture.h>
21 #include <android/gui/IActivePictureListener.h>
22 #include <compositionengine/mock/CompositionEngine.h>
23 #include <mock/DisplayHardware/MockComposer.h>
24 #include <mock/MockLayer.h>
25 #include <renderengine/mock/RenderEngine.h>
26
27 #include "ActivePictureTracker.h"
28 #include "LayerFE.h"
29 #include "TestableSurfaceFlinger.h"
30
31 namespace android {
32
33 using android::compositionengine::LayerFECompositionState;
34 using android::gui::ActivePicture;
35 using android::gui::IActivePictureListener;
36 using android::mock::MockLayer;
37 using surfaceflinger::frontend::LayerSnapshot;
38 using testing::_;
39 using testing::NiceMock;
40 using testing::Return;
41 using testing::SizeIs;
42 using testing::StrictMock;
43
44 class TestableLayerFE : public LayerFE {
45 public:
TestableLayerFE()46 TestableLayerFE() : LayerFE("TestableLayerFE"), snapshot(*(new LayerSnapshot)) {
47 mSnapshot = std::unique_ptr<LayerSnapshot>(&snapshot);
48 }
49
50 LayerSnapshot& snapshot;
51 };
52
53 class MockActivePictureListener : public gui::BnActivePictureListener {
54 public:
operator ActivePictureTracker::Listeners const()55 operator ActivePictureTracker::Listeners const() {
56 return {sp<IActivePictureListener>::fromExisting(this)};
57 }
58
59 MOCK_METHOD(binder::Status, onActivePicturesChanged, (const std::vector<ActivePicture>&),
60 (override));
61 };
62
63 class ActivePictureTrackerTest : public testing::Test {
64 protected:
65 const static ActivePictureTracker::Listeners NO_LISTENERS;
66
flinger()67 SurfaceFlinger* flinger() {
68 if (!mFlingerSetup) {
69 mFlinger.setupMockScheduler();
70 mFlinger.setupComposer(std::make_unique<Hwc2::mock::Composer>());
71 mFlinger.setupRenderEngine(std::make_unique<renderengine::mock::RenderEngine>());
72 mFlingerSetup = true;
73 }
74 return mFlinger.flinger();
75 }
76
createMockLayer(int layerId,int ownerUid)77 sp<NiceMock<MockLayer>> createMockLayer(int layerId, int ownerUid) {
78 auto layer = sp<NiceMock<MockLayer>>::make(flinger(), layerId);
79 EXPECT_CALL(*layer, getOwnerUid()).WillRepeatedly(Return(uid_t(ownerUid)));
80 return layer;
81 }
82
createMockListener()83 sp<StrictMock<MockActivePictureListener>> createMockListener() {
84 return sp<StrictMock<MockActivePictureListener>>::make();
85 }
86
87 ActivePictureTracker::Listeners mListenersToAdd;
88 ActivePictureTracker::Listeners mListenersToRemove;
89
90 private:
91 TestableSurfaceFlinger mFlinger;
92 bool mFlingerSetup = false;
93 };
94
95 const ActivePictureTracker::Listeners ActivePictureTrackerTest::NO_LISTENERS;
96
97 // Hack to workaround initializer lists not working for parcelables because parcelables inherit from
98 // Parcelable, which has a virtual destructor.
UnorderedElementsAre(std::initializer_list<std::tuple<int32_t,int32_t,int64_t>> tuples)99 auto UnorderedElementsAre(std::initializer_list<std::tuple<int32_t, int32_t, int64_t>> tuples) {
100 std::vector<ActivePicture> activePictures;
101 for (auto tuple : tuples) {
102 ActivePicture ap;
103 ap.layerId = std::get<0>(tuple);
104 ap.ownerUid = std::get<1>(tuple);
105 ap.pictureProfileId = std::get<2>(tuple);
106 activePictures.push_back(ap);
107 }
108 return testing::UnorderedElementsAreArray(activePictures);
109 }
110
111 // Parcelables don't define this for matchers, which is unfortunate
PrintTo(const ActivePicture & activePicture,std::ostream * os)112 void PrintTo(const ActivePicture& activePicture, std::ostream* os) {
113 *os << activePicture.toString();
114 }
115
TEST_F(ActivePictureTrackerTest,whenListenerAdded_called)116 TEST_F(ActivePictureTrackerTest, whenListenerAdded_called) {
117 ActivePictureTracker tracker;
118 auto listener = createMockListener();
119 EXPECT_CALL(*listener, onActivePicturesChanged(SizeIs(0))).Times(1);
120 tracker.updateAndNotifyListeners(*listener, NO_LISTENERS);
121 }
122
TEST_F(ActivePictureTrackerTest,whenListenerAdded_withListenerAlreadyAdded_notCalled)123 TEST_F(ActivePictureTrackerTest, whenListenerAdded_withListenerAlreadyAdded_notCalled) {
124 ActivePictureTracker tracker;
125 auto listener = createMockListener();
126 {
127 EXPECT_CALL(*listener, onActivePicturesChanged(SizeIs(0))).Times(1);
128 tracker.updateAndNotifyListeners(*listener, NO_LISTENERS);
129 }
130 {
131 EXPECT_CALL(*listener, onActivePicturesChanged(_)).Times(0);
132 tracker.updateAndNotifyListeners(*listener, NO_LISTENERS);
133 }
134 }
135
TEST_F(ActivePictureTrackerTest,whenListenerAdded_withUncommittedProfile_calledWithNone)136 TEST_F(ActivePictureTrackerTest, whenListenerAdded_withUncommittedProfile_calledWithNone) {
137 auto layer = createMockLayer(100, 10);
138 TestableLayerFE layerFE;
139
140 ActivePictureTracker tracker;
141 {
142 layerFE.snapshot.pictureProfileHandle = PictureProfileHandle(1);
143 tracker.onLayerComposed(*layer, layerFE, layerFE.stealCompositionResult());
144 tracker.updateAndNotifyListeners(NO_LISTENERS, NO_LISTENERS);
145 }
146 {
147 auto listener = createMockListener();
148 EXPECT_CALL(*listener, onActivePicturesChanged(SizeIs(0))).Times(1);
149 tracker.updateAndNotifyListeners(*listener, NO_LISTENERS);
150 }
151 }
152
TEST_F(ActivePictureTrackerTest,whenListenerAdded_withCommittedProfile_calledWithActivePicture)153 TEST_F(ActivePictureTrackerTest, whenListenerAdded_withCommittedProfile_calledWithActivePicture) {
154 auto layer = createMockLayer(100, 10);
155 TestableLayerFE layerFE;
156
157 ActivePictureTracker tracker;
158 {
159 layerFE.snapshot.pictureProfileHandle = PictureProfileHandle(1);
160 layerFE.onPictureProfileCommitted();
161 tracker.onLayerComposed(*layer, layerFE, layerFE.stealCompositionResult());
162
163 auto listener = createMockListener();
164 EXPECT_CALL(*listener, onActivePicturesChanged(_))
165 .WillOnce([](const std::vector<gui::ActivePicture>& activePictures) {
166 EXPECT_THAT(activePictures, UnorderedElementsAre({{100, 10, 1}}));
167 return binder::Status::ok();
168 });
169 tracker.updateAndNotifyListeners(*listener, NO_LISTENERS);
170 }
171 }
172
TEST_F(ActivePictureTrackerTest,whenProfileAdded_calledWithActivePicture)173 TEST_F(ActivePictureTrackerTest, whenProfileAdded_calledWithActivePicture) {
174 auto layer = createMockLayer(100, 10);
175 TestableLayerFE layerFE;
176
177 ActivePictureTracker tracker;
178 auto listener = createMockListener();
179 {
180 tracker.onLayerComposed(*layer, layerFE, layerFE.stealCompositionResult());
181
182 EXPECT_CALL(*listener, onActivePicturesChanged(SizeIs(0))).Times(1);
183 tracker.updateAndNotifyListeners(*listener, NO_LISTENERS);
184 }
185 {
186 layerFE.snapshot.pictureProfileHandle = PictureProfileHandle(1);
187 layerFE.onPictureProfileCommitted();
188 tracker.onLayerComposed(*layer, layerFE, layerFE.stealCompositionResult());
189
190 EXPECT_CALL(*listener, onActivePicturesChanged(_))
191 .WillOnce([](const std::vector<gui::ActivePicture>& activePictures) {
192 EXPECT_THAT(activePictures, UnorderedElementsAre({{100, 10, 1}}));
193 return binder::Status::ok();
194 });
195 tracker.updateAndNotifyListeners(NO_LISTENERS, NO_LISTENERS);
196 }
197 }
198
TEST_F(ActivePictureTrackerTest,whenContinuesUsingProfile_notCalled)199 TEST_F(ActivePictureTrackerTest, whenContinuesUsingProfile_notCalled) {
200 auto layer = createMockLayer(100, 10);
201 TestableLayerFE layerFE;
202
203 ActivePictureTracker tracker;
204 auto listener = createMockListener();
205 {
206 layerFE.snapshot.pictureProfileHandle = PictureProfileHandle(1);
207 layerFE.onPictureProfileCommitted();
208 tracker.onLayerComposed(*layer, layerFE, layerFE.stealCompositionResult());
209
210 EXPECT_CALL(*listener, onActivePicturesChanged(SizeIs(1))).Times(1);
211 tracker.updateAndNotifyListeners(*listener, NO_LISTENERS);
212 }
213 {
214 layerFE.snapshot.pictureProfileHandle = PictureProfileHandle(1);
215 layerFE.onPictureProfileCommitted();
216 tracker.onLayerComposed(*layer, layerFE, layerFE.stealCompositionResult());
217
218 EXPECT_CALL(*listener, onActivePicturesChanged(_)).Times(0);
219 tracker.updateAndNotifyListeners(NO_LISTENERS, NO_LISTENERS);
220 }
221 }
222
TEST_F(ActivePictureTrackerTest,whenProfileIsRemoved_calledWithNoActivePictures)223 TEST_F(ActivePictureTrackerTest, whenProfileIsRemoved_calledWithNoActivePictures) {
224 auto layer = createMockLayer(100, 10);
225 TestableLayerFE layerFE;
226
227 ActivePictureTracker tracker;
228 auto listener = createMockListener();
229 {
230 layerFE.snapshot.pictureProfileHandle = PictureProfileHandle(1);
231 layerFE.onPictureProfileCommitted();
232 tracker.onLayerComposed(*layer, layerFE, layerFE.stealCompositionResult());
233
234 EXPECT_CALL(*listener, onActivePicturesChanged(SizeIs(1))).Times(1);
235 tracker.updateAndNotifyListeners(*listener, NO_LISTENERS);
236 }
237 {
238 layerFE.snapshot.pictureProfileHandle = PictureProfileHandle::NONE;
239 tracker.onLayerComposed(*layer, layerFE, layerFE.stealCompositionResult());
240
241 EXPECT_CALL(*listener, onActivePicturesChanged(SizeIs(0))).Times(1);
242 tracker.updateAndNotifyListeners(NO_LISTENERS, NO_LISTENERS);
243 }
244 }
245
TEST_F(ActivePictureTrackerTest,whenProfileIsNotCommitted_calledWithNoActivePictures)246 TEST_F(ActivePictureTrackerTest, whenProfileIsNotCommitted_calledWithNoActivePictures) {
247 auto layer = createMockLayer(100, 10);
248 TestableLayerFE layerFE;
249
250 ActivePictureTracker tracker;
251 auto listener = createMockListener();
252 {
253 layerFE.snapshot.pictureProfileHandle = PictureProfileHandle(1);
254 layerFE.onPictureProfileCommitted();
255 tracker.onLayerComposed(*layer, layerFE, layerFE.stealCompositionResult());
256
257 EXPECT_CALL(*listener, onActivePicturesChanged(SizeIs(1))).Times(1);
258 tracker.updateAndNotifyListeners(*listener, NO_LISTENERS);
259 }
260 {
261 layerFE.snapshot.pictureProfileHandle = PictureProfileHandle(1);
262 tracker.onLayerComposed(*layer, layerFE, layerFE.stealCompositionResult());
263
264 EXPECT_CALL(*listener, onActivePicturesChanged(SizeIs(0))).Times(1);
265 tracker.updateAndNotifyListeners(NO_LISTENERS, NO_LISTENERS);
266 }
267 }
268
TEST_F(ActivePictureTrackerTest,whenProfileChanges_calledWithDifferentProfile)269 TEST_F(ActivePictureTrackerTest, whenProfileChanges_calledWithDifferentProfile) {
270 auto layer = createMockLayer(100, 10);
271 TestableLayerFE layerFE;
272
273 ActivePictureTracker tracker;
274 auto listener = createMockListener();
275 {
276 layerFE.snapshot.pictureProfileHandle = PictureProfileHandle(1);
277 layerFE.onPictureProfileCommitted();
278 tracker.onLayerComposed(*layer, layerFE, layerFE.stealCompositionResult());
279
280 EXPECT_CALL(*listener, onActivePicturesChanged(SizeIs(1)))
281 .WillOnce([](const std::vector<gui::ActivePicture>& activePictures) {
282 EXPECT_THAT(activePictures, UnorderedElementsAre({{100, 10, 1}}));
283 return binder::Status::ok();
284 });
285 tracker.updateAndNotifyListeners(*listener, NO_LISTENERS);
286 }
287 {
288 layerFE.snapshot.pictureProfileHandle = PictureProfileHandle(2);
289 layerFE.onPictureProfileCommitted();
290 tracker.onLayerComposed(*layer, layerFE, layerFE.stealCompositionResult());
291
292 EXPECT_CALL(*listener, onActivePicturesChanged(SizeIs(1)))
293 .WillOnce([](const std::vector<gui::ActivePicture>& activePictures) {
294 EXPECT_THAT(activePictures, UnorderedElementsAre({{100, 10, 2}}));
295 return binder::Status::ok();
296 });
297 tracker.updateAndNotifyListeners(NO_LISTENERS, NO_LISTENERS);
298 }
299 }
300
TEST_F(ActivePictureTrackerTest,whenMultipleCommittedProfiles_calledWithMultipleActivePictures)301 TEST_F(ActivePictureTrackerTest, whenMultipleCommittedProfiles_calledWithMultipleActivePictures) {
302 auto layer1 = createMockLayer(100, 10);
303 TestableLayerFE layerFE1;
304
305 auto layer2 = createMockLayer(200, 20);
306 TestableLayerFE layerFE2;
307
308 ActivePictureTracker tracker;
309 auto listener = createMockListener();
310 {
311 layerFE1.snapshot.pictureProfileHandle = PictureProfileHandle(1);
312 layerFE1.onPictureProfileCommitted();
313 tracker.onLayerComposed(*layer1, layerFE1, layerFE1.stealCompositionResult());
314
315 layerFE2.snapshot.pictureProfileHandle = PictureProfileHandle(2);
316 layerFE2.onPictureProfileCommitted();
317 tracker.onLayerComposed(*layer2, layerFE2, layerFE2.stealCompositionResult());
318
319 EXPECT_CALL(*listener, onActivePicturesChanged(SizeIs(2)))
320 .WillOnce([](const std::vector<gui::ActivePicture>& activePictures) {
321 EXPECT_THAT(activePictures, UnorderedElementsAre({{100, 10, 1}, {200, 20, 2}}));
322 return binder::Status::ok();
323 });
324 tracker.updateAndNotifyListeners(*listener, NO_LISTENERS);
325 }
326 }
327
TEST_F(ActivePictureTrackerTest,whenNonCommittedProfileChanges_notCalled)328 TEST_F(ActivePictureTrackerTest, whenNonCommittedProfileChanges_notCalled) {
329 auto layer1 = createMockLayer(100, 10);
330 TestableLayerFE layerFE1;
331
332 auto layer2 = createMockLayer(200, 20);
333 TestableLayerFE layerFE2;
334
335 ActivePictureTracker tracker;
336 auto listener = createMockListener();
337 {
338 layerFE1.snapshot.pictureProfileHandle = PictureProfileHandle(1);
339 layerFE1.onPictureProfileCommitted();
340 tracker.onLayerComposed(*layer1, layerFE1, layerFE1.stealCompositionResult());
341
342 layerFE2.snapshot.pictureProfileHandle = PictureProfileHandle(1);
343 tracker.onLayerComposed(*layer2, layerFE2, layerFE2.stealCompositionResult());
344
345 EXPECT_CALL(*listener, onActivePicturesChanged(SizeIs(1))).Times(1);
346 tracker.updateAndNotifyListeners(*listener, NO_LISTENERS);
347 }
348 {
349 layerFE1.snapshot.pictureProfileHandle = PictureProfileHandle(1);
350 layerFE1.onPictureProfileCommitted();
351 tracker.onLayerComposed(*layer1, layerFE1, layerFE1.stealCompositionResult());
352
353 layerFE2.snapshot.pictureProfileHandle = PictureProfileHandle(2);
354 tracker.onLayerComposed(*layer2, layerFE2, layerFE2.stealCompositionResult());
355
356 EXPECT_CALL(*listener, onActivePicturesChanged(_)).Times(0);
357 tracker.updateAndNotifyListeners(*listener, NO_LISTENERS);
358 }
359 }
360
TEST_F(ActivePictureTrackerTest,whenDifferentLayerUsesSameProfile_called)361 TEST_F(ActivePictureTrackerTest, whenDifferentLayerUsesSameProfile_called) {
362 auto layer1 = createMockLayer(100, 10);
363 TestableLayerFE layerFE1;
364
365 auto layer2 = createMockLayer(200, 20);
366 TestableLayerFE layerFE2;
367
368 ActivePictureTracker tracker;
369 auto listener = createMockListener();
370 {
371 layerFE1.snapshot.pictureProfileHandle = PictureProfileHandle(1);
372 layerFE1.onPictureProfileCommitted();
373 tracker.onLayerComposed(*layer1, layerFE1, layerFE1.stealCompositionResult());
374
375 layerFE2.snapshot.pictureProfileHandle = PictureProfileHandle(2);
376 layerFE2.onPictureProfileCommitted();
377 tracker.onLayerComposed(*layer2, layerFE2, layerFE2.stealCompositionResult());
378
379 EXPECT_CALL(*listener, onActivePicturesChanged(_))
380 .WillOnce([](const std::vector<gui::ActivePicture>& activePictures) {
381 EXPECT_THAT(activePictures, UnorderedElementsAre({{100, 10, 1}, {200, 20, 2}}));
382 return binder::Status::ok();
383 });
384 tracker.updateAndNotifyListeners(*listener, NO_LISTENERS);
385 }
386 {
387 layerFE1.snapshot.pictureProfileHandle = PictureProfileHandle(2);
388 layerFE1.onPictureProfileCommitted();
389 tracker.onLayerComposed(*layer1, layerFE1, layerFE1.stealCompositionResult());
390
391 layerFE2.snapshot.pictureProfileHandle = PictureProfileHandle(1);
392 layerFE2.onPictureProfileCommitted();
393 tracker.onLayerComposed(*layer2, layerFE2, layerFE2.stealCompositionResult());
394
395 EXPECT_CALL(*listener, onActivePicturesChanged(_))
396 .WillOnce([](const std::vector<gui::ActivePicture>& activePictures) {
397 EXPECT_THAT(activePictures, UnorderedElementsAre({{100, 10, 2}, {200, 20, 1}}));
398 return binder::Status::ok();
399 });
400 tracker.updateAndNotifyListeners(NO_LISTENERS, NO_LISTENERS);
401 }
402 }
403
TEST_F(ActivePictureTrackerTest,whenSameUidDifferentLayerUsesSameProfile_called)404 TEST_F(ActivePictureTrackerTest, whenSameUidDifferentLayerUsesSameProfile_called) {
405 auto layer1 = createMockLayer(100, 10);
406 TestableLayerFE layerFE1;
407
408 auto layer2 = createMockLayer(200, 10);
409 TestableLayerFE layerFE2;
410
411 ActivePictureTracker tracker;
412 auto listener = createMockListener();
413 {
414 layerFE1.snapshot.pictureProfileHandle = PictureProfileHandle(1);
415 layerFE1.onPictureProfileCommitted();
416 tracker.onLayerComposed(*layer1, layerFE1, layerFE1.stealCompositionResult());
417
418 layerFE2.snapshot.pictureProfileHandle = PictureProfileHandle(2);
419 layerFE2.onPictureProfileCommitted();
420 tracker.onLayerComposed(*layer2, layerFE2, layerFE2.stealCompositionResult());
421
422 EXPECT_CALL(*listener, onActivePicturesChanged(_))
423 .WillOnce([](const std::vector<gui::ActivePicture>& activePictures) {
424 EXPECT_THAT(activePictures, UnorderedElementsAre({{100, 10, 1}, {200, 10, 2}}));
425 return binder::Status::ok();
426 });
427 tracker.updateAndNotifyListeners(*listener, NO_LISTENERS);
428 }
429 {
430 layerFE1.snapshot.pictureProfileHandle = PictureProfileHandle(2);
431 layerFE1.onPictureProfileCommitted();
432 tracker.onLayerComposed(*layer1, layerFE1, layerFE1.stealCompositionResult());
433
434 layerFE2.snapshot.pictureProfileHandle = PictureProfileHandle(1);
435 layerFE2.onPictureProfileCommitted();
436 tracker.onLayerComposed(*layer2, layerFE2, layerFE2.stealCompositionResult());
437
438 EXPECT_CALL(*listener, onActivePicturesChanged(_))
439 .WillOnce([](const std::vector<gui::ActivePicture>& activePictures) {
440 EXPECT_THAT(activePictures, UnorderedElementsAre({{100, 10, 2}, {200, 10, 1}}));
441 return binder::Status::ok();
442 });
443 tracker.updateAndNotifyListeners(NO_LISTENERS, NO_LISTENERS);
444 }
445 }
446
TEST_F(ActivePictureTrackerTest,whenNewLayerUsesSameProfile_called)447 TEST_F(ActivePictureTrackerTest, whenNewLayerUsesSameProfile_called) {
448 auto layer1 = createMockLayer(100, 10);
449 TestableLayerFE layerFE1;
450
451 ActivePictureTracker tracker;
452 auto listener = createMockListener();
453 {
454 layerFE1.snapshot.pictureProfileHandle = PictureProfileHandle(1);
455 layerFE1.onPictureProfileCommitted();
456 tracker.onLayerComposed(*layer1, layerFE1, layerFE1.stealCompositionResult());
457
458 EXPECT_CALL(*listener, onActivePicturesChanged(SizeIs(1))).Times(1);
459 tracker.updateAndNotifyListeners(*listener, NO_LISTENERS);
460 }
461
462 auto layer2 = createMockLayer(200, 10);
463 TestableLayerFE layerFE2;
464 {
465 layerFE1.snapshot.pictureProfileHandle = PictureProfileHandle(1);
466 layerFE1.onPictureProfileCommitted();
467 tracker.onLayerComposed(*layer1, layerFE1, layerFE1.stealCompositionResult());
468
469 layerFE2.snapshot.pictureProfileHandle = PictureProfileHandle(1);
470 layerFE2.onPictureProfileCommitted();
471 tracker.onLayerComposed(*layer2, layerFE2, layerFE2.stealCompositionResult());
472
473 EXPECT_CALL(*listener, onActivePicturesChanged(_))
474 .WillOnce([](const std::vector<gui::ActivePicture>& activePictures) {
475 EXPECT_THAT(activePictures, UnorderedElementsAre({{100, 10, 1}, {200, 10, 1}}));
476 return binder::Status::ok();
477 });
478 tracker.updateAndNotifyListeners(NO_LISTENERS, NO_LISTENERS);
479 }
480 }
481
482 } // namespace android
483