1 /*
2 * Copyright (C) 2022 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 // TODO(b/129481165): remove the #pragma below and fix conversion issues
18 #pragma clang diagnostic push
19 #pragma clang diagnostic ignored "-Wconversion"
20
21 #include <gui/BufferItemConsumer.h>
22 #include <ui/Transform.h>
23 #include <thread>
24 #include "TransactionTestHarnesses.h"
25
26 namespace android {
27 struct PresentationCallbackHelper {
callbackArrivedandroid::PresentationCallbackHelper28 void callbackArrived(bool state) {
29 std::unique_lock l(mMutex);
30 mGotCallback = true;
31 mState = state;
32 mCondition.notify_all();
33 }
awaitCallbackandroid::PresentationCallbackHelper34 bool awaitCallback() {
35 std::unique_lock l(mMutex);
36 mGotCallback = false;
37 mCondition.wait_for(l, 5000ms);
38 EXPECT_TRUE(mGotCallback);
39 return mState;
40 }
41
42 bool mState;
43 bool mGotCallback;
44 std::mutex mMutex;
45 std::condition_variable mCondition;
46 };
47
thresh()48 TrustedPresentationThresholds thresh() {
49 TrustedPresentationThresholds thresholds;
50 thresholds.minAlpha = 1.0;
51 thresholds.minFractionRendered = 1.0;
52 thresholds.stabilityRequirementMs = 100;
53 return thresholds;
54 }
55
56 class LayerTrustedPresentationListenerTest : public LayerTransactionTest {
57 public:
SetUp()58 void SetUp() override {
59 LayerTransactionTest::SetUp();
60 mainLayer = makeLayer();
61 thresholds = thresh();
62 }
63
TearDown()64 void TearDown() override {
65 LayerTransactionTest::TearDown();
66 mCallback = nullptr;
67 t.reparent(mainLayer, nullptr).apply();
68 mainLayer = nullptr;
69 }
70
thresholdsPrepared()71 void thresholdsPrepared() {
72 t.show(mainLayer)
73 .setLayer(mainLayer, INT32_MAX)
74 .setTrustedPresentationCallback(
75 mainLayer,
76 [&](void* context, bool state) {
77 PresentationCallbackHelper* helper =
78 (PresentationCallbackHelper*)context;
79 helper->callbackArrived(state);
80 },
81 thresholds, &pch, mCallback)
82 .setPosition(mainLayer, 100, 100)
83 .apply();
84 }
85
makeLayer()86 sp<SurfaceControl> makeLayer() {
87 sp<SurfaceControl> layer =
88 createLayer("test", 100, 100, ISurfaceComposerClient::eFXSurfaceBufferState,
89 mBlackBgSurface.get());
90 fillBufferLayerColor(layer, Color::RED, 100, 100);
91 return layer;
92 }
93 sp<SurfaceControl> mainLayer;
94 PresentationCallbackHelper pch;
95 SurfaceComposerClient::Transaction t;
96 TrustedPresentationThresholds thresholds;
97 sp<SurfaceComposerClient::PresentationCallbackRAII> mCallback;
98 };
99
100 // The layer is fully presented with the default test setup.
TEST_F(LayerTrustedPresentationListenerTest,callback_arrives)101 TEST_F(LayerTrustedPresentationListenerTest, callback_arrives) {
102 thresholdsPrepared();
103 EXPECT_TRUE(pch.awaitCallback());
104 }
105
106 // A hidden layer can't be considered presented!
TEST_F(LayerTrustedPresentationListenerTest,hiding_layer_clears_state)107 TEST_F(LayerTrustedPresentationListenerTest, hiding_layer_clears_state) {
108 thresholdsPrepared();
109 EXPECT_TRUE(pch.awaitCallback());
110 t.hide(mainLayer).apply();
111 EXPECT_FALSE(pch.awaitCallback());
112 }
113
114 // A fully obscured layer can't be considered presented!
TEST_F(LayerTrustedPresentationListenerTest,obscuring_clears_state)115 TEST_F(LayerTrustedPresentationListenerTest, obscuring_clears_state) {
116 thresholdsPrepared();
117 EXPECT_TRUE(pch.awaitCallback());
118
119 auto otherLayer = makeLayer();
120 t.show(otherLayer)
121 .setPosition(otherLayer, 100, 100)
122 .setLayer(otherLayer, INT32_MAX)
123 .setLayer(mainLayer, INT32_MAX - 1)
124 .apply();
125 EXPECT_FALSE(pch.awaitCallback());
126 }
127
128 // Even if the layer obscuring us has an Alpha channel, we are still considered
129 // obscured.
TEST_F(LayerTrustedPresentationListenerTest,obscuring_with_transparency_clears_state)130 TEST_F(LayerTrustedPresentationListenerTest, obscuring_with_transparency_clears_state) {
131 thresholdsPrepared();
132 EXPECT_TRUE(pch.awaitCallback());
133
134 auto otherLayer = makeLayer();
135 t.show(otherLayer)
136 .setPosition(otherLayer, 100, 100)
137 .setLayer(otherLayer, INT32_MAX)
138 .setFlags(otherLayer, 0, layer_state_t::eLayerOpaque)
139 .setLayer(mainLayer, INT32_MAX - 1)
140 .apply();
141 EXPECT_FALSE(pch.awaitCallback());
142 }
143
144 // We can't be presented if our alpha is below the threshold.
TEST_F(LayerTrustedPresentationListenerTest,alpha_below_threshold)145 TEST_F(LayerTrustedPresentationListenerTest, alpha_below_threshold) {
146 thresholdsPrepared();
147 EXPECT_TRUE(pch.awaitCallback());
148 t.setAlpha(mainLayer, 0.9).apply();
149 EXPECT_FALSE(pch.awaitCallback());
150 t.setAlpha(mainLayer, 1.0).apply();
151 EXPECT_TRUE(pch.awaitCallback());
152 }
153
154 // Verify that the passed in threshold is actually respected!
TEST_F(LayerTrustedPresentationListenerTest,alpha_below_other_threshold)155 TEST_F(LayerTrustedPresentationListenerTest, alpha_below_other_threshold) {
156 thresholds.minAlpha = 0.8;
157 thresholdsPrepared();
158 EXPECT_TRUE(pch.awaitCallback());
159 t.setAlpha(mainLayer, 0.8).apply();
160 EXPECT_FALSE(pch.awaitCallback());
161 t.setAlpha(mainLayer, 0.9).apply();
162 EXPECT_TRUE(pch.awaitCallback());
163 }
164
165 // (86*86)/(100*100) = 0.73...so a crop of 86x86 is below the threshold
166 // (87*87)/(100*100) = 0.76...so a crop of 87x87 is above the threshold!
TEST_F(LayerTrustedPresentationListenerTest,crop_below_threshold)167 TEST_F(LayerTrustedPresentationListenerTest, crop_below_threshold) {
168 thresholds.minFractionRendered = 0.75;
169 thresholdsPrepared();
170 EXPECT_TRUE(pch.awaitCallback());
171 t.setCrop(mainLayer, Rect(0, 0, 86, 86)).apply();
172 EXPECT_FALSE(pch.awaitCallback());
173 t.setCrop(mainLayer, Rect(0, 0, 87, 87)).apply();
174 EXPECT_TRUE(pch.awaitCallback());
175 }
176
TEST_F(LayerTrustedPresentationListenerTest,scale_below_threshold)177 TEST_F(LayerTrustedPresentationListenerTest, scale_below_threshold) {
178 thresholds.minFractionRendered = 0.64;
179 thresholdsPrepared();
180 EXPECT_TRUE(pch.awaitCallback());
181 // 0.8 = sqrt(0.64)
182 t.setMatrix(mainLayer, 0.79, 0, 0, 0.79).apply();
183 EXPECT_FALSE(pch.awaitCallback());
184 t.setMatrix(mainLayer, 0.81, 0, 0, 0.81).apply();
185 EXPECT_TRUE(pch.awaitCallback());
186 }
187
TEST_F(LayerTrustedPresentationListenerTest,obscuring_with_threshold_1)188 TEST_F(LayerTrustedPresentationListenerTest, obscuring_with_threshold_1) {
189 thresholds.minFractionRendered = 0.75;
190 thresholdsPrepared();
191 EXPECT_TRUE(pch.awaitCallback());
192
193 auto otherLayer = makeLayer();
194 t.show(otherLayer)
195 .setPosition(otherLayer, 100, 100)
196 .setLayer(otherLayer, INT32_MAX)
197 .setLayer(mainLayer, INT32_MAX - 1)
198 .apply();
199 EXPECT_FALSE(pch.awaitCallback());
200 t.setMatrix(otherLayer, 0.49, 0, 0, 0.49).apply();
201 EXPECT_TRUE(pch.awaitCallback());
202 t.setMatrix(otherLayer, 0.51, 0, 0, 0.51).apply();
203 EXPECT_FALSE(pch.awaitCallback());
204 }
205
TEST_F(LayerTrustedPresentationListenerTest,obscuring_with_threshold_2)206 TEST_F(LayerTrustedPresentationListenerTest, obscuring_with_threshold_2) {
207 thresholds.minFractionRendered = 0.9;
208 thresholdsPrepared();
209 EXPECT_TRUE(pch.awaitCallback());
210
211 auto otherLayer = makeLayer();
212 t.show(otherLayer)
213 .setPosition(otherLayer, 100, 100)
214 .setLayer(otherLayer, INT32_MAX)
215 .setLayer(mainLayer, INT32_MAX - 1)
216 .apply();
217 EXPECT_FALSE(pch.awaitCallback());
218 t.setMatrix(otherLayer, 0.3, 0, 0, 0.3).apply();
219 EXPECT_TRUE(pch.awaitCallback());
220 t.setMatrix(otherLayer, 0.33, 0, 0, 0.33).apply();
221 EXPECT_FALSE(pch.awaitCallback());
222 }
223
TEST_F(LayerTrustedPresentationListenerTest,obscuring_with_alpha)224 TEST_F(LayerTrustedPresentationListenerTest, obscuring_with_alpha) {
225 thresholds.minFractionRendered = 0.9;
226 thresholdsPrepared();
227 EXPECT_TRUE(pch.awaitCallback());
228
229 auto otherLayer = makeLayer();
230 t.show(otherLayer)
231 .setPosition(otherLayer, 100, 100)
232 .setLayer(otherLayer, INT32_MAX)
233 .setLayer(mainLayer, INT32_MAX - 1)
234 .setAlpha(otherLayer, 0.01)
235 .apply();
236 EXPECT_FALSE(pch.awaitCallback());
237 t.setAlpha(otherLayer, 0.0).apply();
238 EXPECT_TRUE(pch.awaitCallback());
239 }
240
TEST_F(LayerTrustedPresentationListenerTest,obscuring_with_display_overlay)241 TEST_F(LayerTrustedPresentationListenerTest, obscuring_with_display_overlay) {
242 auto otherLayer = makeLayer();
243 t.show(otherLayer)
244 .setPosition(otherLayer, 100, 100)
245 .setLayer(otherLayer, INT32_MAX)
246 .setFlags(otherLayer, layer_state_t::eLayerSkipScreenshot,
247 layer_state_t::eLayerSkipScreenshot)
248 .setLayer(mainLayer, INT32_MAX - 1)
249 .show(mainLayer)
250 .setPosition(mainLayer, 100, 100)
251 .setTrustedPresentationCallback(
252 mainLayer,
253 [&](void* context, bool state) {
254 PresentationCallbackHelper* helper = (PresentationCallbackHelper*)context;
255 helper->callbackArrived(state);
256 },
257 thresholds, &pch, mCallback)
258 .apply();
259 EXPECT_TRUE(pch.awaitCallback());
260 }
261
TEST_F(LayerTrustedPresentationListenerTest,obscuring_with_non_overlapping_bounds)262 TEST_F(LayerTrustedPresentationListenerTest, obscuring_with_non_overlapping_bounds) {
263 thresholds.minFractionRendered = 0.5;
264 auto otherLayer1 = makeLayer();
265 auto otherLayer2 = makeLayer();
266 t.show(otherLayer1)
267 .show(otherLayer2)
268 .setPosition(otherLayer1, 100, 25)
269 .setLayer(otherLayer1, INT32_MAX)
270 .setPosition(otherLayer2, 100, 175)
271 .setLayer(otherLayer2, INT32_MAX)
272 .setLayer(mainLayer, INT32_MAX - 1)
273 .show(mainLayer)
274 .setPosition(mainLayer, 100, 100)
275 .setTrustedPresentationCallback(
276 mainLayer,
277 [&](void* context, bool state) {
278 PresentationCallbackHelper* helper = (PresentationCallbackHelper*)context;
279 helper->callbackArrived(state);
280 },
281 thresholds, &pch, mCallback)
282 .apply();
283
284 EXPECT_TRUE(pch.awaitCallback());
285 }
286
287 } // namespace android
288