1 /*
2 * Copyright 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 // #define LOG_NDEBUG 0
18 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
19 #include "FrontEnd/LayerSnapshot.h"
20 #include "ui/Transform.h"
21 #undef LOG_TAG
22 #define LOG_TAG "SurfaceFlinger"
23
24 #include <numeric>
25 #include <optional>
26
27 #include <common/FlagManager.h>
28 #include <common/trace.h>
29 #include <ftl/small_map.h>
30 #include <math/vec2.h>
31 #include <ui/DisplayMap.h>
32 #include <ui/FloatRect.h>
33
34 #include "DisplayHardware/HWC2.h"
35 #include "DisplayHardware/Hal.h"
36 #include "Layer.h" // eFrameRateSelectionPriority constants
37 #include "LayerLog.h"
38 #include "LayerSnapshotBuilder.h"
39 #include "TimeStats/TimeStats.h"
40 #include "Tracing/TransactionTracing.h"
41
42 namespace android::surfaceflinger::frontend {
43
44 using namespace ftl::flag_operators;
45
46 namespace {
47
getMaxDisplayBounds(const DisplayInfos & displays)48 FloatRect getMaxDisplayBounds(const DisplayInfos& displays) {
49 const ui::Size maxSize = [&displays] {
50 if (displays.empty()) return ui::Size{5000, 5000};
51
52 return std::accumulate(displays.begin(), displays.end(), ui::kEmptySize,
53 [](ui::Size size, const auto& pair) -> ui::Size {
54 const auto& display = pair.second;
55 return {std::max(size.getWidth(), display.info.logicalWidth),
56 std::max(size.getHeight(), display.info.logicalHeight)};
57 });
58 }();
59
60 // Ignore display bounds for now since they will be computed later. Use a large Rect bound
61 // to ensure it's bigger than an actual display will be.
62 const float xMax = static_cast<float>(maxSize.getWidth()) * 10.f;
63 const float yMax = static_cast<float>(maxSize.getHeight()) * 10.f;
64
65 return {-xMax, -yMax, xMax, yMax};
66 }
67
68 // Applies the given transform to the region, while protecting against overflows caused by any
69 // offsets. If applying the offset in the transform to any of the Rects in the region would result
70 // in an overflow, they are not added to the output Region.
transformTouchableRegionSafely(const ui::Transform & t,const Region & r,const std::string & debugWindowName)71 Region transformTouchableRegionSafely(const ui::Transform& t, const Region& r,
72 const std::string& debugWindowName) {
73 // Round the translation using the same rounding strategy used by ui::Transform.
74 const auto tx = static_cast<int32_t>(t.tx() + 0.5);
75 const auto ty = static_cast<int32_t>(t.ty() + 0.5);
76
77 ui::Transform transformWithoutOffset = t;
78 transformWithoutOffset.set(0.f, 0.f);
79
80 const Region transformed = transformWithoutOffset.transform(r);
81
82 // Apply the translation to each of the Rects in the region while discarding any that overflow.
83 Region ret;
84 for (const auto& rect : transformed) {
85 Rect newRect;
86 if (__builtin_add_overflow(rect.left, tx, &newRect.left) ||
87 __builtin_add_overflow(rect.top, ty, &newRect.top) ||
88 __builtin_add_overflow(rect.right, tx, &newRect.right) ||
89 __builtin_add_overflow(rect.bottom, ty, &newRect.bottom)) {
90 ALOGE("Applying transform to touchable region of window '%s' resulted in an overflow.",
91 debugWindowName.c_str());
92 continue;
93 }
94 ret.orSelf(newRect);
95 }
96 return ret;
97 }
98
99 /*
100 * We don't want to send the layer's transform to input, but rather the
101 * parent's transform. This is because Layer's transform is
102 * information about how the buffer is placed on screen. The parent's
103 * transform makes more sense to send since it's information about how the
104 * layer is placed on screen. This transform is used by input to determine
105 * how to go from screen space back to window space.
106 */
getInputTransform(const LayerSnapshot & snapshot)107 ui::Transform getInputTransform(const LayerSnapshot& snapshot) {
108 if (!snapshot.hasBufferOrSidebandStream()) {
109 return snapshot.geomLayerTransform;
110 }
111 return snapshot.parentTransform;
112 }
113
114 /**
115 * Returns the bounds used to fill the input frame and the touchable region.
116 *
117 * Similar to getInputTransform, we need to update the bounds to include the transform.
118 * This is because bounds don't include the buffer transform, where the input assumes
119 * that's already included.
120 */
getInputBounds(const LayerSnapshot & snapshot,bool fillParentBounds)121 std::pair<FloatRect, bool> getInputBounds(const LayerSnapshot& snapshot, bool fillParentBounds) {
122 FloatRect inputBounds = snapshot.croppedBufferSize;
123 if (snapshot.hasBufferOrSidebandStream() && snapshot.croppedBufferSize.isValid() &&
124 snapshot.localTransform.getType() != ui::Transform::IDENTITY) {
125 inputBounds = snapshot.localTransform.transform(inputBounds);
126 }
127
128 bool inputBoundsValid = snapshot.croppedBufferSize.isValid();
129 if (!inputBoundsValid) {
130 /**
131 * Input bounds are based on the layer crop or buffer size. But if we are using
132 * the layer bounds as the input bounds (replaceTouchableRegionWithCrop flag) then
133 * we can use the parent bounds as the input bounds if the layer does not have buffer
134 * or a crop. We want to unify this logic but because of compat reasons we cannot always
135 * use the parent bounds. A layer without a buffer can get input. So when a window is
136 * initially added, its touchable region can fill its parent layer bounds and that can
137 * have negative consequences.
138 */
139 inputBounds = fillParentBounds ? snapshot.geomLayerBounds : FloatRect{};
140 }
141
142 // Clamp surface inset to the input bounds.
143 const float inset = static_cast<float>(snapshot.inputInfo.surfaceInset);
144 const float xSurfaceInset = std::clamp(inset, 0.f, inputBounds.getWidth() / 2.f);
145 const float ySurfaceInset = std::clamp(inset, 0.f, inputBounds.getHeight() / 2.f);
146
147 // Apply the insets to the input bounds.
148 inputBounds.left += xSurfaceInset;
149 inputBounds.top += ySurfaceInset;
150 inputBounds.right -= xSurfaceInset;
151 inputBounds.bottom -= ySurfaceInset;
152 return {inputBounds, inputBoundsValid};
153 }
154
getInputBoundsInDisplaySpace(const LayerSnapshot & snapshot,const FloatRect & insetBounds,const ui::Transform & screenToDisplay)155 Rect getInputBoundsInDisplaySpace(const LayerSnapshot& snapshot, const FloatRect& insetBounds,
156 const ui::Transform& screenToDisplay) {
157 // InputDispatcher works in the display device's coordinate space. Here, we calculate the
158 // frame and transform used for the layer, which determines the bounds and the coordinate space
159 // within which the layer will receive input.
160
161 // Coordinate space definitions:
162 // - display: The display device's coordinate space. Correlates to pixels on the display.
163 // - screen: The post-rotation coordinate space for the display, a.k.a. logical display space.
164 // - layer: The coordinate space of this layer.
165 // - input: The coordinate space in which this layer will receive input events. This could be
166 // different than layer space if a surfaceInset is used, which changes the origin
167 // of the input space.
168
169 // Crop the input bounds to ensure it is within the parent's bounds.
170 const FloatRect croppedInsetBoundsInLayer = snapshot.geomLayerBounds.intersect(insetBounds);
171
172 const ui::Transform layerToScreen = getInputTransform(snapshot);
173 const ui::Transform layerToDisplay = screenToDisplay * layerToScreen;
174
175 return Rect{layerToDisplay.transform(croppedInsetBoundsInLayer)};
176 }
177
fillInputFrameInfo(gui::WindowInfo & info,const ui::Transform & screenToDisplay,const LayerSnapshot & snapshot)178 void fillInputFrameInfo(gui::WindowInfo& info, const ui::Transform& screenToDisplay,
179 const LayerSnapshot& snapshot) {
180 auto [inputBounds, inputBoundsValid] = getInputBounds(snapshot, /*fillParentBounds=*/false);
181 if (!inputBoundsValid) {
182 info.touchableRegion.clear();
183 }
184
185 info.frame = getInputBoundsInDisplaySpace(snapshot, inputBounds, screenToDisplay);
186
187 ui::Transform inputToLayer;
188 inputToLayer.set(inputBounds.left, inputBounds.top);
189 const ui::Transform layerToScreen = getInputTransform(snapshot);
190 const ui::Transform inputToDisplay = screenToDisplay * layerToScreen * inputToLayer;
191
192 // InputDispatcher expects a display-to-input transform.
193 info.transform = inputToDisplay.inverse();
194
195 // The touchable region is specified in the input coordinate space. Change it to display space.
196 info.touchableRegion =
197 transformTouchableRegionSafely(inputToDisplay, info.touchableRegion, snapshot.name);
198 }
199
handleDropInputMode(LayerSnapshot & snapshot,const LayerSnapshot & parentSnapshot)200 void handleDropInputMode(LayerSnapshot& snapshot, const LayerSnapshot& parentSnapshot) {
201 if (snapshot.inputInfo.inputConfig.test(gui::WindowInfo::InputConfig::NO_INPUT_CHANNEL)) {
202 return;
203 }
204
205 // Check if we need to drop input unconditionally
206 const gui::DropInputMode dropInputMode = snapshot.dropInputMode;
207 if (dropInputMode == gui::DropInputMode::ALL) {
208 snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::DROP_INPUT;
209 ALOGV("Dropping input for %s as requested by policy.", snapshot.name.c_str());
210 return;
211 }
212
213 // Check if we need to check if the window is obscured by parent
214 if (dropInputMode != gui::DropInputMode::OBSCURED) {
215 return;
216 }
217
218 // Check if the parent has set an alpha on the layer
219 if (parentSnapshot.color.a != 1.0_hf) {
220 snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::DROP_INPUT;
221 ALOGV("Dropping input for %s as requested by policy because alpha=%f",
222 snapshot.name.c_str(), static_cast<float>(parentSnapshot.color.a));
223 }
224
225 // Check if the parent has cropped the buffer
226 FloatRect bufferSize = snapshot.croppedBufferSize;
227 if (!bufferSize.isValid()) {
228 snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED;
229 return;
230 }
231
232 // Screenbounds are the layer bounds cropped by parents, transformed to screenspace.
233 // To check if the layer has been cropped, we take the buffer bounds, apply the local
234 // layer crop and apply the same set of transforms to move to screenspace. If the bounds
235 // match then the layer has not been cropped by its parents.
236 Rect bufferInScreenSpace(snapshot.geomLayerTransform.transform(bufferSize));
237 bool croppedByParent = bufferInScreenSpace != Rect{snapshot.transformedBounds};
238
239 if (croppedByParent) {
240 snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::DROP_INPUT;
241 ALOGV("Dropping input for %s as requested by policy because buffer is cropped by parent",
242 snapshot.name.c_str());
243 } else {
244 // If the layer is not obscured by its parents (by setting an alpha or crop), then only drop
245 // input if the window is obscured. This check should be done in surfaceflinger but the
246 // logic currently resides in inputflinger. So pass the if_obscured check to input to only
247 // drop input events if the window is obscured.
248 snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED;
249 }
250 }
251
getBlendMode(const LayerSnapshot & snapshot,const RequestedLayerState & requested)252 auto getBlendMode(const LayerSnapshot& snapshot, const RequestedLayerState& requested) {
253 auto blendMode = Hwc2::IComposerClient::BlendMode::NONE;
254 if (snapshot.alpha != 1.0f || !snapshot.isContentOpaque()) {
255 blendMode = requested.premultipliedAlpha ? Hwc2::IComposerClient::BlendMode::PREMULTIPLIED
256 : Hwc2::IComposerClient::BlendMode::COVERAGE;
257 }
258 return blendMode;
259 }
260
updateVisibility(LayerSnapshot & snapshot,bool visible)261 void updateVisibility(LayerSnapshot& snapshot, bool visible) {
262 if (snapshot.isVisible != visible) {
263 snapshot.changes |= RequestedLayerState::Changes::Visibility;
264 }
265 snapshot.isVisible = visible;
266
267 // TODO(b/238781169) we are ignoring this compat for now, since we will have
268 // to remove any optimization based on visibility.
269
270 // For compatibility reasons we let layers which can receive input
271 // receive input before they have actually submitted a buffer. Because
272 // of this we use canReceiveInput instead of isVisible to check the
273 // policy-visibility, ignoring the buffer state. However for layers with
274 // hasInputInfo()==false we can use the real visibility state.
275 // We are just using these layers for occlusion detection in
276 // InputDispatcher, and obviously if they aren't visible they can't occlude
277 // anything.
278 const bool visibleForInput =
279 snapshot.hasInputInfo() ? snapshot.canReceiveInput() : snapshot.isVisible;
280 snapshot.inputInfo.setInputConfig(gui::WindowInfo::InputConfig::NOT_VISIBLE, !visibleForInput);
281
282 LLOGV(snapshot.sequence, "updating visibility %s %s", visible ? "true" : "false",
283 snapshot.getDebugString().c_str());
284 }
285
updateMetadata(LayerSnapshot & snapshot,const RequestedLayerState & requested,const LayerSnapshotBuilder::Args & args)286 void updateMetadata(LayerSnapshot& snapshot, const RequestedLayerState& requested,
287 const LayerSnapshotBuilder::Args& args) {
288 snapshot.metadata.clear();
289 for (const auto& [key, mandatory] : args.supportedLayerGenericMetadata) {
290 auto compatIter = args.genericLayerMetadataKeyMap.find(key);
291 if (compatIter == std::end(args.genericLayerMetadataKeyMap)) {
292 continue;
293 }
294 const uint32_t id = compatIter->second;
295 auto it = requested.metadata.mMap.find(id);
296 if (it == std::end(requested.metadata.mMap)) {
297 continue;
298 }
299
300 snapshot.metadata.emplace(key,
301 compositionengine::GenericLayerMetadataEntry{mandatory,
302 it->second});
303 }
304 }
305
updateMetadataAndGameMode(LayerSnapshot & snapshot,const RequestedLayerState & requested,const LayerSnapshotBuilder::Args & args,const LayerSnapshot & parentSnapshot)306 void updateMetadataAndGameMode(LayerSnapshot& snapshot, const RequestedLayerState& requested,
307 const LayerSnapshotBuilder::Args& args,
308 const LayerSnapshot& parentSnapshot) {
309 snapshot.gameMode = requested.metadata.has(gui::METADATA_GAME_MODE) ? requested.gameMode
310 : parentSnapshot.gameMode;
311 updateMetadata(snapshot, requested, args);
312 if (args.includeMetadata) {
313 snapshot.layerMetadata = parentSnapshot.layerMetadata;
314 snapshot.layerMetadata.merge(requested.metadata);
315 }
316 }
317
clearChanges(LayerSnapshot & snapshot)318 void clearChanges(LayerSnapshot& snapshot) {
319 snapshot.changes.clear();
320 snapshot.clientChanges = 0;
321 snapshot.contentDirty = snapshot.autoRefresh;
322 snapshot.hasReadyFrame = snapshot.autoRefresh;
323 snapshot.sidebandStreamHasFrame = false;
324 snapshot.surfaceDamage.clear();
325 }
326
327 // TODO (b/259407931): Remove.
getPrimaryDisplayRotationFlags(const ui::DisplayMap<ui::LayerStack,frontend::DisplayInfo> & displays)328 uint32_t getPrimaryDisplayRotationFlags(
329 const ui::DisplayMap<ui::LayerStack, frontend::DisplayInfo>& displays) {
330 for (auto& [_, display] : displays) {
331 if (display.isPrimary) {
332 return display.rotationFlags;
333 }
334 }
335 return 0;
336 }
337
338 } // namespace
339
getRootSnapshot()340 LayerSnapshot LayerSnapshotBuilder::getRootSnapshot() {
341 LayerSnapshot snapshot;
342 snapshot.path = LayerHierarchy::TraversalPath::ROOT;
343 snapshot.changes = ftl::Flags<RequestedLayerState::Changes>();
344 snapshot.clientChanges = 0;
345 snapshot.isHiddenByPolicyFromParent = false;
346 snapshot.isHiddenByPolicyFromRelativeParent = false;
347 snapshot.parentTransform.reset();
348 snapshot.geomLayerTransform.reset();
349 snapshot.geomInverseLayerTransform.reset();
350 snapshot.geomLayerBounds = getMaxDisplayBounds({});
351 snapshot.roundedCorner = RoundedCornerState();
352 snapshot.stretchEffect = {};
353 snapshot.edgeExtensionEffect = {};
354 snapshot.outputFilter.layerStack = ui::DEFAULT_LAYER_STACK;
355 snapshot.outputFilter.toInternalDisplay = false;
356 snapshot.isSecure = false;
357 snapshot.color.a = 1.0_hf;
358 snapshot.colorTransformIsIdentity = true;
359 snapshot.shadowSettings.length = 0.f;
360 snapshot.layerMetadata.mMap.clear();
361 snapshot.relativeLayerMetadata.mMap.clear();
362 snapshot.inputInfo.touchOcclusionMode = gui::TouchOcclusionMode::BLOCK_UNTRUSTED;
363 snapshot.dropInputMode = gui::DropInputMode::NONE;
364 snapshot.trustedOverlay = gui::TrustedOverlay::UNSET;
365 snapshot.gameMode = gui::GameMode::Unsupported;
366 snapshot.frameRate = {};
367 snapshot.fixedTransformHint = ui::Transform::ROT_INVALID;
368 snapshot.ignoreLocalTransform = false;
369 return snapshot;
370 }
371
LayerSnapshotBuilder()372 LayerSnapshotBuilder::LayerSnapshotBuilder() {}
373
LayerSnapshotBuilder(Args args)374 LayerSnapshotBuilder::LayerSnapshotBuilder(Args args) : LayerSnapshotBuilder() {
375 args.forceUpdate = ForceUpdateFlags::ALL;
376 updateSnapshots(args);
377 }
378
tryFastUpdate(const Args & args)379 bool LayerSnapshotBuilder::tryFastUpdate(const Args& args) {
380 const bool forceUpdate = args.forceUpdate != ForceUpdateFlags::NONE;
381
382 if (args.layerLifecycleManager.getGlobalChanges().get() == 0 && !forceUpdate &&
383 !args.displayChanges) {
384 return true;
385 }
386
387 // There are only content changes which do not require any child layer snapshots to be updated.
388 ALOGV("%s", __func__);
389 SFTRACE_NAME("FastPath");
390
391 uint32_t primaryDisplayRotationFlags = getPrimaryDisplayRotationFlags(args.displays);
392 if (forceUpdate || args.displayChanges) {
393 for (auto& snapshot : mSnapshots) {
394 const RequestedLayerState* requested =
395 args.layerLifecycleManager.getLayerFromId(snapshot->path.id);
396 if (!requested) continue;
397 snapshot->merge(*requested, forceUpdate, args.displayChanges, args.forceFullDamage,
398 primaryDisplayRotationFlags);
399 }
400 return false;
401 }
402
403 // Walk through all the updated requested layer states and update the corresponding snapshots.
404 for (const RequestedLayerState* requested : args.layerLifecycleManager.getChangedLayers()) {
405 auto range = mIdToSnapshots.equal_range(requested->id);
406 for (auto it = range.first; it != range.second; it++) {
407 it->second->merge(*requested, forceUpdate, args.displayChanges, args.forceFullDamage,
408 primaryDisplayRotationFlags);
409 }
410 }
411
412 if ((args.layerLifecycleManager.getGlobalChanges().get() &
413 ~(RequestedLayerState::Changes::Content | RequestedLayerState::Changes::Buffer).get()) !=
414 0) {
415 // We have changes that require us to walk the hierarchy and update child layers.
416 // No fast path for you.
417 return false;
418 }
419 return true;
420 }
421
updateSnapshots(const Args & args)422 void LayerSnapshotBuilder::updateSnapshots(const Args& args) {
423 SFTRACE_NAME("UpdateSnapshots");
424 LayerSnapshot rootSnapshot = args.rootSnapshot;
425 if (args.parentCrop) {
426 rootSnapshot.geomLayerBounds = *args.parentCrop;
427 } else if (args.forceUpdate == ForceUpdateFlags::ALL || args.displayChanges) {
428 rootSnapshot.geomLayerBounds = getMaxDisplayBounds(args.displays);
429 }
430 if (args.displayChanges) {
431 rootSnapshot.changes = RequestedLayerState::Changes::AffectsChildren |
432 RequestedLayerState::Changes::Geometry;
433 }
434 if (args.forceUpdate == ForceUpdateFlags::HIERARCHY) {
435 rootSnapshot.changes |=
436 RequestedLayerState::Changes::Hierarchy | RequestedLayerState::Changes::Visibility;
437 rootSnapshot.clientChanges |= layer_state_t::eReparent;
438 }
439
440 for (auto& snapshot : mSnapshots) {
441 if (snapshot->reachablilty == LayerSnapshot::Reachablilty::Reachable) {
442 snapshot->reachablilty = LayerSnapshot::Reachablilty::Unreachable;
443 }
444 }
445
446 LayerHierarchy::TraversalPath root = LayerHierarchy::TraversalPath::ROOT;
447 if (args.root.getLayer()) {
448 // The hierarchy can have a root layer when used for screenshots otherwise, it will have
449 // multiple children.
450 LayerHierarchy::TraversalPath childPath =
451 root.makeChild(args.root.getLayer()->id, LayerHierarchy::Variant::Attached);
452 updateSnapshotsInHierarchy(args, args.root, childPath, rootSnapshot, /*depth=*/0);
453 } else {
454 for (auto& [childHierarchy, variant] : args.root.mChildren) {
455 LayerHierarchy::TraversalPath childPath =
456 root.makeChild(childHierarchy->getLayer()->id, variant);
457 updateSnapshotsInHierarchy(args, *childHierarchy, childPath, rootSnapshot, /*depth=*/0);
458 }
459 }
460
461 // Update touchable region crops outside the main update pass. This is because a layer could be
462 // cropped by any other layer and it requires both snapshots to be updated.
463 updateTouchableRegionCrop(args);
464
465 const bool hasUnreachableSnapshots = sortSnapshotsByZ(args);
466
467 // Destroy unreachable snapshots for clone layers. And destroy snapshots for non-clone
468 // layers if the layer have been destroyed.
469 // TODO(b/238781169) consider making clone layer ids stable as well
470 if (!hasUnreachableSnapshots && args.layerLifecycleManager.getDestroyedLayers().empty()) {
471 return;
472 }
473
474 std::unordered_set<uint32_t> destroyedLayerIds;
475 for (auto& destroyedLayer : args.layerLifecycleManager.getDestroyedLayers()) {
476 destroyedLayerIds.insert(destroyedLayer->id);
477 }
478
479 auto it = mSnapshots.begin();
480 while (it < mSnapshots.end()) {
481 auto& traversalPath = it->get()->path;
482 const bool unreachable =
483 it->get()->reachablilty == LayerSnapshot::Reachablilty::Unreachable;
484 const bool isClone = traversalPath.isClone();
485 const bool layerIsDestroyed =
486 destroyedLayerIds.find(traversalPath.id) != destroyedLayerIds.end();
487 const bool destroySnapshot = (unreachable && isClone) || layerIsDestroyed;
488
489 if (!destroySnapshot) {
490 it++;
491 continue;
492 }
493
494 mPathToSnapshot.erase(traversalPath);
495
496 auto range = mIdToSnapshots.equal_range(traversalPath.id);
497 auto matchingSnapshot =
498 std::find_if(range.first, range.second, [&traversalPath](auto& snapshotWithId) {
499 return snapshotWithId.second->path == traversalPath;
500 });
501 mIdToSnapshots.erase(matchingSnapshot);
502 mNeedsTouchableRegionCrop.erase(traversalPath);
503 mSnapshots.back()->globalZ = it->get()->globalZ;
504 std::iter_swap(it, mSnapshots.end() - 1);
505 mSnapshots.erase(mSnapshots.end() - 1);
506 }
507 }
508
update(const Args & args)509 void LayerSnapshotBuilder::update(const Args& args) {
510 for (auto& snapshot : mSnapshots) {
511 clearChanges(*snapshot);
512 }
513
514 if (tryFastUpdate(args)) {
515 return;
516 }
517 updateSnapshots(args);
518 }
519
updateSnapshotsInHierarchy(const Args & args,const LayerHierarchy & hierarchy,const LayerHierarchy::TraversalPath & traversalPath,const LayerSnapshot & parentSnapshot,int depth)520 const LayerSnapshot& LayerSnapshotBuilder::updateSnapshotsInHierarchy(
521 const Args& args, const LayerHierarchy& hierarchy,
522 const LayerHierarchy::TraversalPath& traversalPath, const LayerSnapshot& parentSnapshot,
523 int depth) {
524 LLOG_ALWAYS_FATAL_WITH_TRACE_IF(depth > 50,
525 "Cycle detected in LayerSnapshotBuilder. See "
526 "builder_stack_overflow_transactions.winscope");
527
528 const RequestedLayerState* layer = hierarchy.getLayer();
529 LayerSnapshot* snapshot = getSnapshot(traversalPath);
530 const bool newSnapshot = snapshot == nullptr;
531 uint32_t primaryDisplayRotationFlags = getPrimaryDisplayRotationFlags(args.displays);
532 if (newSnapshot) {
533 snapshot = createSnapshot(traversalPath, *layer, parentSnapshot);
534 snapshot->merge(*layer, /*forceUpdate=*/true, /*displayChanges=*/true, args.forceFullDamage,
535 primaryDisplayRotationFlags);
536 snapshot->changes |= RequestedLayerState::Changes::Created;
537 }
538
539 if (traversalPath.isRelative()) {
540 bool parentIsRelative = traversalPath.variant == LayerHierarchy::Variant::Relative;
541 updateRelativeState(*snapshot, parentSnapshot, parentIsRelative, args);
542 } else {
543 if (traversalPath.isAttached()) {
544 resetRelativeState(*snapshot);
545 }
546 updateSnapshot(*snapshot, args, *layer, parentSnapshot, traversalPath);
547 }
548
549 bool childHasValidFrameRate = false;
550 for (auto& [childHierarchy, variant] : hierarchy.mChildren) {
551 LayerHierarchy::TraversalPath childPath =
552 traversalPath.makeChild(childHierarchy->getLayer()->id, variant);
553 const LayerSnapshot& childSnapshot =
554 updateSnapshotsInHierarchy(args, *childHierarchy, childPath, *snapshot, depth + 1);
555 updateFrameRateFromChildSnapshot(*snapshot, childSnapshot, *childHierarchy->getLayer(),
556 args, &childHasValidFrameRate);
557 }
558
559 return *snapshot;
560 }
561
getSnapshot(uint32_t layerId) const562 LayerSnapshot* LayerSnapshotBuilder::getSnapshot(uint32_t layerId) const {
563 if (layerId == UNASSIGNED_LAYER_ID) {
564 return nullptr;
565 }
566 LayerHierarchy::TraversalPath path{.id = layerId};
567 return getSnapshot(path);
568 }
569
getSnapshot(const LayerHierarchy::TraversalPath & id) const570 LayerSnapshot* LayerSnapshotBuilder::getSnapshot(const LayerHierarchy::TraversalPath& id) const {
571 auto it = mPathToSnapshot.find(id);
572 return it == mPathToSnapshot.end() ? nullptr : it->second;
573 }
574
createSnapshot(const LayerHierarchy::TraversalPath & path,const RequestedLayerState & layer,const LayerSnapshot & parentSnapshot)575 LayerSnapshot* LayerSnapshotBuilder::createSnapshot(const LayerHierarchy::TraversalPath& path,
576 const RequestedLayerState& layer,
577 const LayerSnapshot& parentSnapshot) {
578 mSnapshots.emplace_back(std::make_unique<LayerSnapshot>(layer, path));
579 LayerSnapshot* snapshot = mSnapshots.back().get();
580 snapshot->globalZ = static_cast<size_t>(mSnapshots.size()) - 1;
581 if (path.isClone() && !LayerHierarchy::isMirror(path.variant)) {
582 snapshot->mirrorRootPath = parentSnapshot.mirrorRootPath;
583 }
584 snapshot->ignoreLocalTransform =
585 path.isClone() && path.variant == LayerHierarchy::Variant::Detached_Mirror;
586 mPathToSnapshot[path] = snapshot;
587
588 mIdToSnapshots.emplace(path.id, snapshot);
589 return snapshot;
590 }
591
sortSnapshotsByZ(const Args & args)592 bool LayerSnapshotBuilder::sortSnapshotsByZ(const Args& args) {
593 if (!mResortSnapshots && args.forceUpdate == ForceUpdateFlags::NONE &&
594 !args.layerLifecycleManager.getGlobalChanges().any(
595 RequestedLayerState::Changes::Hierarchy | RequestedLayerState::Changes::Visibility |
596 RequestedLayerState::Changes::Input)) {
597 // We are not force updating and there are no hierarchy or visibility changes. Avoid sorting
598 // the snapshots.
599 return false;
600 }
601 mResortSnapshots = false;
602
603 size_t globalZ = 0;
604 args.root.traverseInZOrder(
605 [this, &globalZ](const LayerHierarchy&,
606 const LayerHierarchy::TraversalPath& traversalPath) -> bool {
607 LayerSnapshot* snapshot = getSnapshot(traversalPath);
608 if (!snapshot) {
609 return true;
610 }
611
612 if (snapshot->getIsVisible() || snapshot->hasInputInfo()) {
613 updateVisibility(*snapshot, snapshot->getIsVisible());
614 size_t oldZ = snapshot->globalZ;
615 size_t newZ = globalZ++;
616 snapshot->globalZ = newZ;
617 if (oldZ == newZ) {
618 return true;
619 }
620 mSnapshots[newZ]->globalZ = oldZ;
621 LLOGV(snapshot->sequence, "Made visible z=%zu -> %zu %s", oldZ, newZ,
622 snapshot->getDebugString().c_str());
623 std::iter_swap(mSnapshots.begin() + static_cast<ssize_t>(oldZ),
624 mSnapshots.begin() + static_cast<ssize_t>(newZ));
625 }
626 return true;
627 });
628 mNumInterestingSnapshots = (int)globalZ;
629 bool hasUnreachableSnapshots = false;
630 while (globalZ < mSnapshots.size()) {
631 mSnapshots[globalZ]->globalZ = globalZ;
632 /* mark unreachable snapshots as explicitly invisible */
633 updateVisibility(*mSnapshots[globalZ], false);
634 if (mSnapshots[globalZ]->reachablilty == LayerSnapshot::Reachablilty::Unreachable) {
635 hasUnreachableSnapshots = true;
636 }
637 globalZ++;
638 }
639 return hasUnreachableSnapshots;
640 }
641
updateRelativeState(LayerSnapshot & snapshot,const LayerSnapshot & parentSnapshot,bool parentIsRelative,const Args & args)642 void LayerSnapshotBuilder::updateRelativeState(LayerSnapshot& snapshot,
643 const LayerSnapshot& parentSnapshot,
644 bool parentIsRelative, const Args& args) {
645 if (parentIsRelative) {
646 snapshot.isHiddenByPolicyFromRelativeParent =
647 parentSnapshot.isHiddenByPolicyFromParent || parentSnapshot.invalidTransform;
648 if (args.includeMetadata) {
649 snapshot.relativeLayerMetadata = parentSnapshot.layerMetadata;
650 }
651 } else {
652 snapshot.isHiddenByPolicyFromRelativeParent =
653 parentSnapshot.isHiddenByPolicyFromRelativeParent;
654 if (args.includeMetadata) {
655 snapshot.relativeLayerMetadata = parentSnapshot.relativeLayerMetadata;
656 }
657 }
658 if (snapshot.reachablilty == LayerSnapshot::Reachablilty::Unreachable) {
659 snapshot.reachablilty = LayerSnapshot::Reachablilty::ReachableByRelativeParent;
660 }
661 }
662
updateFrameRateFromChildSnapshot(LayerSnapshot & snapshot,const LayerSnapshot & childSnapshot,const RequestedLayerState &,const Args & args,bool * outChildHasValidFrameRate)663 void LayerSnapshotBuilder::updateFrameRateFromChildSnapshot(
664 LayerSnapshot& snapshot, const LayerSnapshot& childSnapshot,
665 const RequestedLayerState& /* requestedChildState */, const Args& args,
666 bool* outChildHasValidFrameRate) {
667 if (args.forceUpdate == ForceUpdateFlags::NONE &&
668 !args.layerLifecycleManager.getGlobalChanges().any(
669 RequestedLayerState::Changes::Hierarchy) &&
670 !childSnapshot.changes.any(RequestedLayerState::Changes::FrameRate) &&
671 !snapshot.changes.any(RequestedLayerState::Changes::FrameRate)) {
672 return;
673 }
674
675 using FrameRateCompatibility = scheduler::FrameRateCompatibility;
676 if (snapshot.inheritedFrameRate.isValid() || *outChildHasValidFrameRate) {
677 // we already have a valid framerate.
678 return;
679 }
680
681 // We return whether this layer or its children has a vote. We ignore ExactOrMultiple votes
682 // for the same reason we are allowing touch boost for those layers. See
683 // RefreshRateSelector::rankFrameRates for details.
684 const auto layerVotedWithDefaultCompatibility = childSnapshot.frameRate.vote.rate.isValid() &&
685 childSnapshot.frameRate.vote.type == FrameRateCompatibility::Default;
686 const auto layerVotedWithNoVote =
687 childSnapshot.frameRate.vote.type == FrameRateCompatibility::NoVote;
688 const auto layerVotedWithCategory =
689 childSnapshot.frameRate.category != FrameRateCategory::Default;
690 const auto layerVotedWithExactCompatibility = childSnapshot.frameRate.vote.rate.isValid() &&
691 childSnapshot.frameRate.vote.type == FrameRateCompatibility::Exact;
692
693 *outChildHasValidFrameRate |= layerVotedWithDefaultCompatibility || layerVotedWithNoVote ||
694 layerVotedWithCategory || layerVotedWithExactCompatibility;
695
696 // If we don't have a valid frame rate, but the children do, we set this
697 // layer as NoVote to allow the children to control the refresh rate
698 static const auto noVote =
699 scheduler::LayerInfo::FrameRate(Fps(), FrameRateCompatibility::NoVote);
700 if (*outChildHasValidFrameRate) {
701 snapshot.frameRate = noVote;
702 snapshot.changes |= RequestedLayerState::Changes::FrameRate;
703 } else if (snapshot.frameRate != snapshot.inheritedFrameRate) {
704 snapshot.frameRate = snapshot.inheritedFrameRate;
705 snapshot.changes |= RequestedLayerState::Changes::FrameRate;
706 }
707 }
708
resetRelativeState(LayerSnapshot & snapshot)709 void LayerSnapshotBuilder::resetRelativeState(LayerSnapshot& snapshot) {
710 snapshot.isHiddenByPolicyFromRelativeParent = false;
711 snapshot.relativeLayerMetadata.mMap.clear();
712 }
713
updateSnapshot(LayerSnapshot & snapshot,const Args & args,const RequestedLayerState & requested,const LayerSnapshot & parentSnapshot,const LayerHierarchy::TraversalPath & path)714 void LayerSnapshotBuilder::updateSnapshot(LayerSnapshot& snapshot, const Args& args,
715 const RequestedLayerState& requested,
716 const LayerSnapshot& parentSnapshot,
717 const LayerHierarchy::TraversalPath& path) {
718 // Always update flags and visibility
719 ftl::Flags<RequestedLayerState::Changes> parentChanges = parentSnapshot.changes &
720 (RequestedLayerState::Changes::Hierarchy | RequestedLayerState::Changes::Geometry |
721 RequestedLayerState::Changes::Visibility | RequestedLayerState::Changes::Metadata |
722 RequestedLayerState::Changes::AffectsChildren | RequestedLayerState::Changes::Input |
723 RequestedLayerState::Changes::FrameRate | RequestedLayerState::Changes::GameMode);
724 snapshot.changes |= parentChanges;
725 if (args.displayChanges) snapshot.changes |= RequestedLayerState::Changes::Geometry;
726 snapshot.reachablilty = LayerSnapshot::Reachablilty::Reachable;
727 snapshot.clientChanges |= (parentSnapshot.clientChanges & layer_state_t::AFFECTS_CHILDREN);
728 // mark the content as dirty if the parent state changes can dirty the child's content (for
729 // example alpha)
730 snapshot.contentDirty |= (snapshot.clientChanges & layer_state_t::CONTENT_DIRTY) != 0;
731 snapshot.isHiddenByPolicyFromParent = parentSnapshot.isHiddenByPolicyFromParent ||
732 parentSnapshot.invalidTransform || requested.isHiddenByPolicy() ||
733 (args.excludeLayerIds.find(path.id) != args.excludeLayerIds.end());
734 const bool forceUpdate = args.forceUpdate == ForceUpdateFlags::ALL ||
735 snapshot.clientChanges & layer_state_t::eReparent ||
736 snapshot.changes.any(RequestedLayerState::Changes::Visibility |
737 RequestedLayerState::Changes::Created);
738
739 if (forceUpdate || snapshot.clientChanges & layer_state_t::eLayerStackChanged) {
740 // If root layer, use the layer stack otherwise get the parent's layer stack.
741 snapshot.outputFilter.layerStack =
742 parentSnapshot.path == LayerHierarchy::TraversalPath::ROOT
743 ? requested.layerStack
744 : parentSnapshot.outputFilter.layerStack;
745 }
746
747 if (forceUpdate || snapshot.clientChanges & layer_state_t::eTrustedOverlayChanged) {
748 switch (requested.trustedOverlay) {
749 case gui::TrustedOverlay::UNSET:
750 snapshot.trustedOverlay = parentSnapshot.trustedOverlay;
751 break;
752 case gui::TrustedOverlay::DISABLED:
753 snapshot.trustedOverlay = FlagManager::getInstance().override_trusted_overlay()
754 ? requested.trustedOverlay
755 : parentSnapshot.trustedOverlay;
756 break;
757 case gui::TrustedOverlay::ENABLED:
758 snapshot.trustedOverlay = requested.trustedOverlay;
759 break;
760 }
761 }
762
763 if (snapshot.isHiddenByPolicyFromParent &&
764 !snapshot.changes.test(RequestedLayerState::Changes::Created)) {
765 if (forceUpdate ||
766 snapshot.changes.any(RequestedLayerState::Changes::Geometry |
767 RequestedLayerState::Changes::BufferSize |
768 RequestedLayerState::Changes::Input)) {
769 updateInput(snapshot, requested, parentSnapshot, path, args);
770 }
771 if (forceUpdate ||
772 (args.includeMetadata &&
773 snapshot.changes.any(RequestedLayerState::Changes::Metadata |
774 RequestedLayerState::Changes::Geometry))) {
775 updateMetadataAndGameMode(snapshot, requested, args, parentSnapshot);
776 }
777 return;
778 }
779
780 if (forceUpdate || snapshot.changes.any(RequestedLayerState::Changes::Mirror)) {
781 // Display mirrors are always placed in a VirtualDisplay so we never want to capture layers
782 // marked as skip capture
783 snapshot.handleSkipScreenshotFlag = parentSnapshot.handleSkipScreenshotFlag ||
784 (requested.layerStackToMirror != ui::INVALID_LAYER_STACK);
785 }
786
787 if (forceUpdate || snapshot.clientChanges & layer_state_t::eAlphaChanged) {
788 snapshot.color.a = parentSnapshot.color.a * requested.color.a;
789 snapshot.alpha = snapshot.color.a;
790 snapshot.inputInfo.alpha = snapshot.color.a;
791 }
792
793 if (forceUpdate || snapshot.clientChanges & layer_state_t::eFlagsChanged) {
794 snapshot.isSecure =
795 parentSnapshot.isSecure || (requested.flags & layer_state_t::eLayerSecure);
796 snapshot.outputFilter.toInternalDisplay = parentSnapshot.outputFilter.toInternalDisplay ||
797 (requested.flags & layer_state_t::eLayerSkipScreenshot);
798 }
799
800 if (forceUpdate || snapshot.clientChanges & layer_state_t::eStretchChanged) {
801 snapshot.stretchEffect = (requested.stretchEffect.hasEffect())
802 ? requested.stretchEffect
803 : parentSnapshot.stretchEffect;
804 }
805
806 if (forceUpdate ||
807 (snapshot.clientChanges | parentSnapshot.clientChanges) &
808 layer_state_t::eEdgeExtensionChanged) {
809 if (requested.edgeExtensionParameters.extendLeft ||
810 requested.edgeExtensionParameters.extendRight ||
811 requested.edgeExtensionParameters.extendTop ||
812 requested.edgeExtensionParameters.extendBottom) {
813 // This is the root layer to which the extension is applied
814 snapshot.edgeExtensionEffect =
815 EdgeExtensionEffect(requested.edgeExtensionParameters.extendLeft,
816 requested.edgeExtensionParameters.extendRight,
817 requested.edgeExtensionParameters.extendTop,
818 requested.edgeExtensionParameters.extendBottom);
819 } else if (parentSnapshot.clientChanges & layer_state_t::eEdgeExtensionChanged) {
820 // Extension is inherited
821 snapshot.edgeExtensionEffect = parentSnapshot.edgeExtensionEffect;
822 } else {
823 // There is no edge extension
824 snapshot.edgeExtensionEffect.reset();
825 }
826 if (snapshot.edgeExtensionEffect.hasEffect()) {
827 snapshot.clientChanges |= layer_state_t::eEdgeExtensionChanged;
828 snapshot.changes |= RequestedLayerState::Changes::Geometry;
829 }
830 }
831
832 if (forceUpdate || snapshot.clientChanges & layer_state_t::eColorTransformChanged) {
833 if (!parentSnapshot.colorTransformIsIdentity) {
834 snapshot.colorTransform = parentSnapshot.colorTransform * requested.colorTransform;
835 snapshot.colorTransformIsIdentity = false;
836 } else {
837 snapshot.colorTransform = requested.colorTransform;
838 snapshot.colorTransformIsIdentity = !requested.hasColorTransform;
839 }
840 }
841
842 if (forceUpdate ||
843 snapshot.changes.any(RequestedLayerState::Changes::Metadata |
844 RequestedLayerState::Changes::Hierarchy)) {
845 updateMetadataAndGameMode(snapshot, requested, args, parentSnapshot);
846 }
847
848 if (forceUpdate || snapshot.clientChanges & layer_state_t::eFixedTransformHintChanged ||
849 args.displayChanges) {
850 snapshot.fixedTransformHint = requested.fixedTransformHint != ui::Transform::ROT_INVALID
851 ? requested.fixedTransformHint
852 : parentSnapshot.fixedTransformHint;
853
854 if (snapshot.fixedTransformHint != ui::Transform::ROT_INVALID) {
855 snapshot.transformHint = snapshot.fixedTransformHint;
856 } else {
857 const auto display = args.displays.get(snapshot.outputFilter.layerStack);
858 snapshot.transformHint = display.has_value()
859 ? std::make_optional<>(display->get().transformHint)
860 : std::nullopt;
861 }
862 }
863
864 if (forceUpdate ||
865 args.layerLifecycleManager.getGlobalChanges().any(
866 RequestedLayerState::Changes::Hierarchy) ||
867 snapshot.changes.any(RequestedLayerState::Changes::FrameRate |
868 RequestedLayerState::Changes::Hierarchy)) {
869 const bool shouldOverrideChildren = parentSnapshot.frameRateSelectionStrategy ==
870 scheduler::LayerInfo::FrameRateSelectionStrategy::OverrideChildren;
871 const bool propagationAllowed = parentSnapshot.frameRateSelectionStrategy !=
872 scheduler::LayerInfo::FrameRateSelectionStrategy::Self;
873 if ((!requested.requestedFrameRate.isValid() && propagationAllowed) ||
874 shouldOverrideChildren) {
875 snapshot.inheritedFrameRate = parentSnapshot.inheritedFrameRate;
876 } else {
877 snapshot.inheritedFrameRate = requested.requestedFrameRate;
878 }
879 // Set the framerate as the inherited frame rate and allow children to override it if
880 // needed.
881 snapshot.frameRate = snapshot.inheritedFrameRate;
882 snapshot.changes |= RequestedLayerState::Changes::FrameRate;
883 }
884
885 if (forceUpdate || snapshot.clientChanges & layer_state_t::eFrameRateSelectionStrategyChanged) {
886 if (parentSnapshot.frameRateSelectionStrategy ==
887 scheduler::LayerInfo::FrameRateSelectionStrategy::OverrideChildren) {
888 snapshot.frameRateSelectionStrategy =
889 scheduler::LayerInfo::FrameRateSelectionStrategy::OverrideChildren;
890 } else {
891 const auto strategy = scheduler::LayerInfo::convertFrameRateSelectionStrategy(
892 requested.frameRateSelectionStrategy);
893 snapshot.frameRateSelectionStrategy = strategy;
894 }
895 }
896
897 if (forceUpdate || snapshot.clientChanges & layer_state_t::eFrameRateSelectionPriority) {
898 snapshot.frameRateSelectionPriority =
899 (requested.frameRateSelectionPriority == Layer::PRIORITY_UNSET)
900 ? parentSnapshot.frameRateSelectionPriority
901 : requested.frameRateSelectionPriority;
902 }
903
904 if (forceUpdate ||
905 snapshot.clientChanges &
906 (layer_state_t::eBackgroundBlurRadiusChanged | layer_state_t::eBlurRegionsChanged |
907 layer_state_t::eAlphaChanged)) {
908 snapshot.backgroundBlurRadius = args.supportsBlur
909 ? static_cast<int>(parentSnapshot.color.a * (float)requested.backgroundBlurRadius)
910 : 0;
911 snapshot.blurRegions = requested.blurRegions;
912 for (auto& region : snapshot.blurRegions) {
913 region.alpha = region.alpha * snapshot.color.a;
914 }
915 }
916
917 if (forceUpdate || snapshot.changes.any(RequestedLayerState::Changes::Geometry)) {
918 uint32_t primaryDisplayRotationFlags = getPrimaryDisplayRotationFlags(args.displays);
919 updateLayerBounds(snapshot, requested, parentSnapshot, primaryDisplayRotationFlags);
920 }
921
922 if (snapshot.edgeExtensionEffect.hasEffect()) {
923 updateBoundsForEdgeExtension(snapshot);
924 }
925
926 if (forceUpdate || snapshot.clientChanges & layer_state_t::eCornerRadiusChanged ||
927 snapshot.changes.any(RequestedLayerState::Changes::Geometry |
928 RequestedLayerState::Changes::BufferUsageFlags) ||
929 snapshot.clientChanges & layer_state_t::eClientDrawnCornerRadiusChanged) {
930 updateRoundedCorner(snapshot, requested, parentSnapshot, args);
931 }
932
933 if (forceUpdate || snapshot.clientChanges & layer_state_t::eShadowRadiusChanged ||
934 snapshot.changes.any(RequestedLayerState::Changes::Geometry)) {
935 updateShadows(snapshot, requested, args.globalShadowSettings);
936 }
937
938 if (forceUpdate ||
939 snapshot.clientChanges &
940 (layer_state_t::eBorderSettingsChanged | layer_state_t::eAlphaChanged)) {
941 snapshot.borderSettings = requested.borderSettings;
942
943 // Multiply outline alpha by snapshot alpha.
944 uint32_t c = static_cast<uint32_t>(snapshot.borderSettings.color);
945 float alpha = snapshot.alpha * (c >> 24) / 255.0f;
946 uint32_t a = static_cast<uint32_t>(alpha * 255 + 0.5f);
947 snapshot.borderSettings.color = static_cast<int32_t>((c & ~0xff000000) | (a << 24));
948 }
949
950 if (forceUpdate ||
951 snapshot.changes.any(RequestedLayerState::Changes::Geometry |
952 RequestedLayerState::Changes::Input)) {
953 updateInput(snapshot, requested, parentSnapshot, path, args);
954 }
955
956 // computed snapshot properties
957 snapshot.forceClientComposition = snapshot.shadowSettings.length > 0 ||
958 snapshot.stretchEffect.hasEffect() || snapshot.edgeExtensionEffect.hasEffect() ||
959 snapshot.borderSettings.strokeWidth > 0;
960
961 snapshot.contentOpaque = snapshot.isContentOpaque();
962 snapshot.isOpaque = snapshot.contentOpaque && !snapshot.roundedCorner.hasRoundedCorners() &&
963 snapshot.color.a == 1.f;
964 snapshot.blendMode = getBlendMode(snapshot, requested);
965 LLOGV(snapshot.sequence,
966 "%supdated %s changes:%s parent:%s requested:%s requested:%s from parent %s",
967 args.forceUpdate == ForceUpdateFlags::ALL ? "Force " : "",
968 snapshot.getDebugString().c_str(), snapshot.changes.string().c_str(),
969 parentSnapshot.changes.string().c_str(), requested.changes.string().c_str(),
970 std::to_string(requested.what).c_str(), parentSnapshot.getDebugString().c_str());
971 }
972
updateRoundedCorner(LayerSnapshot & snapshot,const RequestedLayerState & requested,const LayerSnapshot & parentSnapshot,const Args & args)973 void LayerSnapshotBuilder::updateRoundedCorner(LayerSnapshot& snapshot,
974 const RequestedLayerState& requested,
975 const LayerSnapshot& parentSnapshot,
976 const Args& args) {
977 if (args.skipRoundCornersWhenProtected && requested.isProtected()) {
978 snapshot.roundedCorner = RoundedCornerState();
979 return;
980 }
981 snapshot.roundedCorner = RoundedCornerState();
982 RoundedCornerState parentRoundedCorner;
983 if (parentSnapshot.roundedCorner.hasRequestedRadius()) {
984 parentRoundedCorner = parentSnapshot.roundedCorner;
985 ui::Transform t = snapshot.localTransform.inverse();
986 parentRoundedCorner.cropRect = t.transform(parentRoundedCorner.cropRect);
987 parentRoundedCorner.radius.x *= t.getScaleX();
988 parentRoundedCorner.radius.y *= t.getScaleY();
989 parentRoundedCorner.requestedRadius.x *= t.getScaleX();
990 parentRoundedCorner.requestedRadius.y *= t.getScaleY();
991 }
992
993 FloatRect layerCropRect = snapshot.croppedBufferSize;
994 const vec2 requestedRadius(requested.cornerRadius, requested.cornerRadius);
995 const vec2 clientDrawnRadius(requested.clientDrawnCornerRadius,
996 requested.clientDrawnCornerRadius);
997 RoundedCornerState layerSettings;
998 layerSettings.cropRect = layerCropRect;
999 layerSettings.requestedRadius = requestedRadius;
1000 layerSettings.clientDrawnRadius = clientDrawnRadius;
1001
1002 const bool layerSettingsValid = layerSettings.hasRequestedRadius() && !layerCropRect.isEmpty();
1003 const bool parentRoundedCornerValid = parentRoundedCorner.hasRequestedRadius();
1004 if (layerSettingsValid && parentRoundedCornerValid) {
1005 // If the parent and the layer have rounded corner settings, use the parent settings if
1006 // the parent crop is entirely inside the layer crop. This has limitations and cause
1007 // rendering artifacts. See b/200300845 for correct fix.
1008 if (parentRoundedCorner.cropRect.left > layerCropRect.left &&
1009 parentRoundedCorner.cropRect.top > layerCropRect.top &&
1010 parentRoundedCorner.cropRect.right < layerCropRect.right &&
1011 parentRoundedCorner.cropRect.bottom < layerCropRect.bottom) {
1012 snapshot.roundedCorner = parentRoundedCorner;
1013 } else {
1014 snapshot.roundedCorner = layerSettings;
1015 }
1016 } else if (layerSettingsValid) {
1017 snapshot.roundedCorner = layerSettings;
1018 } else if (parentRoundedCornerValid) {
1019 snapshot.roundedCorner = parentRoundedCorner;
1020 }
1021
1022 if (snapshot.roundedCorner.requestedRadius.x == requested.clientDrawnCornerRadius) {
1023 // If the client drawn radius matches the requested radius, then surfaceflinger
1024 // does not need to draw rounded corners for this layer
1025 snapshot.roundedCorner.radius = vec2(0.f, 0.f);
1026 } else {
1027 snapshot.roundedCorner.radius = snapshot.roundedCorner.requestedRadius;
1028 }
1029 }
1030
1031 /**
1032 * According to the edges that we are requested to extend, we increase the bounds to the maximum
1033 * extension allowed by the crop (parent crop + requested crop). The animation that called
1034 * Transition#setEdgeExtensionEffect is in charge of setting the requested crop.
1035 * @param snapshot
1036 */
updateBoundsForEdgeExtension(LayerSnapshot & snapshot)1037 void LayerSnapshotBuilder::updateBoundsForEdgeExtension(LayerSnapshot& snapshot) {
1038 EdgeExtensionEffect& effect = snapshot.edgeExtensionEffect;
1039
1040 if (effect.extendsEdge(LEFT)) {
1041 snapshot.geomLayerBounds.left = snapshot.geomLayerCrop.left;
1042 }
1043 if (effect.extendsEdge(RIGHT)) {
1044 snapshot.geomLayerBounds.right = snapshot.geomLayerCrop.right;
1045 }
1046 if (effect.extendsEdge(TOP)) {
1047 snapshot.geomLayerBounds.top = snapshot.geomLayerCrop.top;
1048 }
1049 if (effect.extendsEdge(BOTTOM)) {
1050 snapshot.geomLayerBounds.bottom = snapshot.geomLayerCrop.bottom;
1051 }
1052
1053 snapshot.transformedBounds = snapshot.geomLayerTransform.transform(snapshot.geomLayerBounds);
1054 }
1055
updateLayerBounds(LayerSnapshot & snapshot,const RequestedLayerState & requested,const LayerSnapshot & parentSnapshot,uint32_t primaryDisplayRotationFlags)1056 void LayerSnapshotBuilder::updateLayerBounds(LayerSnapshot& snapshot,
1057 const RequestedLayerState& requested,
1058 const LayerSnapshot& parentSnapshot,
1059 uint32_t primaryDisplayRotationFlags) {
1060 snapshot.geomLayerTransform = parentSnapshot.geomLayerTransform * snapshot.localTransform;
1061 const bool transformWasInvalid = snapshot.invalidTransform;
1062 snapshot.invalidTransform = !LayerSnapshot::isTransformValid(snapshot.geomLayerTransform);
1063 if (snapshot.invalidTransform) {
1064 auto& t = snapshot.geomLayerTransform;
1065 auto& requestedT = requested.requestedTransform;
1066 std::string transformDebug =
1067 base::StringPrintf(" transform={%f,%f,%f,%f} requestedTransform={%f,%f,%f,%f}",
1068 t.dsdx(), t.dsdy(), t.dtdx(), t.dtdy(), requestedT.dsdx(),
1069 requestedT.dsdy(), requestedT.dtdx(), requestedT.dtdy());
1070 std::string bufferDebug;
1071 if (requested.externalTexture) {
1072 auto unRotBuffer = requested.getUnrotatedBufferSize(primaryDisplayRotationFlags);
1073 auto& destFrame = requested.destinationFrame;
1074 bufferDebug = base::StringPrintf(" buffer={%d,%d} displayRot=%d"
1075 " destFrame={%d,%d,%d,%d} unRotBuffer={%d,%d}",
1076 requested.externalTexture->getWidth(),
1077 requested.externalTexture->getHeight(),
1078 primaryDisplayRotationFlags, destFrame.left,
1079 destFrame.top, destFrame.right, destFrame.bottom,
1080 unRotBuffer.getHeight(), unRotBuffer.getWidth());
1081 }
1082 ALOGW("Resetting transform for %s because it is invalid.%s%s",
1083 snapshot.getDebugString().c_str(), transformDebug.c_str(), bufferDebug.c_str());
1084 snapshot.geomLayerTransform.reset();
1085 }
1086 if (transformWasInvalid != snapshot.invalidTransform) {
1087 // If transform is invalid, the layer will be hidden.
1088 mResortSnapshots = true;
1089 }
1090 snapshot.geomInverseLayerTransform = snapshot.geomLayerTransform.inverse();
1091
1092 FloatRect parentBounds = parentSnapshot.geomLayerBounds;
1093 parentBounds = snapshot.localTransform.inverse().transform(parentBounds);
1094 snapshot.geomLayerBounds =
1095 requested.externalTexture ? snapshot.bufferSize.toFloatRect() : parentBounds;
1096 snapshot.geomLayerCrop = parentBounds;
1097 if (!requested.crop.isEmpty()) {
1098 snapshot.geomLayerCrop = snapshot.geomLayerCrop.intersect(requested.crop);
1099 }
1100 snapshot.geomLayerBounds = snapshot.geomLayerBounds.intersect(snapshot.geomLayerCrop);
1101 snapshot.transformedBounds = snapshot.geomLayerTransform.transform(snapshot.geomLayerBounds);
1102 const Rect geomLayerBoundsWithoutTransparentRegion =
1103 RequestedLayerState::reduce(Rect(snapshot.geomLayerBounds),
1104 requested.getTransparentRegion());
1105 snapshot.transformedBoundsWithoutTransparentRegion =
1106 snapshot.geomLayerTransform.transform(geomLayerBoundsWithoutTransparentRegion);
1107 snapshot.parentTransform = parentSnapshot.geomLayerTransform;
1108
1109 if (requested.potentialCursor) {
1110 // Subtract the transparent region and snap to the bounds
1111 const Rect bounds = RequestedLayerState::reduce(Rect(snapshot.croppedBufferSize),
1112 requested.getTransparentRegion());
1113 snapshot.cursorFrame = snapshot.geomLayerTransform.transform(bounds);
1114 }
1115 }
1116
updateShadows(LayerSnapshot & snapshot,const RequestedLayerState &,const ShadowSettings & globalShadowSettings)1117 void LayerSnapshotBuilder::updateShadows(LayerSnapshot& snapshot, const RequestedLayerState&,
1118 const ShadowSettings& globalShadowSettings) {
1119 if (snapshot.shadowSettings.length > 0.f) {
1120 snapshot.shadowSettings.ambientColor = globalShadowSettings.ambientColor;
1121 snapshot.shadowSettings.spotColor = globalShadowSettings.spotColor;
1122 snapshot.shadowSettings.lightPos = globalShadowSettings.lightPos;
1123 snapshot.shadowSettings.lightRadius = globalShadowSettings.lightRadius;
1124
1125 // Note: this preserves existing behavior of shadowing the entire layer and not cropping
1126 // it if transparent regions are present. This may not be necessary since shadows are
1127 // typically cast by layers without transparent regions.
1128 snapshot.shadowSettings.boundaries = snapshot.geomLayerBounds;
1129
1130 // If the casting layer is translucent, we need to fill in the shadow underneath the
1131 // layer. Otherwise the generated shadow will only be shown around the casting layer.
1132 snapshot.shadowSettings.casterIsTranslucent =
1133 !snapshot.isContentOpaque() || (snapshot.alpha < 1.0f);
1134 snapshot.shadowSettings.ambientColor *= snapshot.alpha;
1135 snapshot.shadowSettings.spotColor *= snapshot.alpha;
1136 }
1137 }
1138
updateInput(LayerSnapshot & snapshot,const RequestedLayerState & requested,const LayerSnapshot & parentSnapshot,const LayerHierarchy::TraversalPath & path,const Args & args)1139 void LayerSnapshotBuilder::updateInput(LayerSnapshot& snapshot,
1140 const RequestedLayerState& requested,
1141 const LayerSnapshot& parentSnapshot,
1142 const LayerHierarchy::TraversalPath& path,
1143 const Args& args) {
1144 using InputConfig = gui::WindowInfo::InputConfig;
1145
1146 snapshot.inputInfo = requested.getWindowInfo();
1147 snapshot.touchCropId = requested.touchCropId;
1148
1149 snapshot.inputInfo.id = static_cast<int32_t>(snapshot.uniqueSequence);
1150 snapshot.inputInfo.displayId =
1151 ui::LogicalDisplayId{static_cast<int32_t>(snapshot.outputFilter.layerStack.id)};
1152 snapshot.inputInfo.touchOcclusionMode = requested.hasInputInfo()
1153 ? requested.getWindowInfo().touchOcclusionMode
1154 : parentSnapshot.inputInfo.touchOcclusionMode;
1155 snapshot.inputInfo.canOccludePresentation = parentSnapshot.inputInfo.canOccludePresentation ||
1156 (requested.flags & layer_state_t::eCanOccludePresentation);
1157 if (requested.dropInputMode == gui::DropInputMode::ALL ||
1158 parentSnapshot.dropInputMode == gui::DropInputMode::ALL) {
1159 snapshot.dropInputMode = gui::DropInputMode::ALL;
1160 } else if (requested.dropInputMode == gui::DropInputMode::OBSCURED ||
1161 parentSnapshot.dropInputMode == gui::DropInputMode::OBSCURED) {
1162 snapshot.dropInputMode = gui::DropInputMode::OBSCURED;
1163 } else {
1164 snapshot.dropInputMode = gui::DropInputMode::NONE;
1165 }
1166
1167 if (snapshot.isSecure ||
1168 parentSnapshot.inputInfo.inputConfig.test(InputConfig::SENSITIVE_FOR_PRIVACY)) {
1169 snapshot.inputInfo.inputConfig |= InputConfig::SENSITIVE_FOR_PRIVACY;
1170 }
1171
1172 updateVisibility(snapshot, snapshot.isVisible);
1173 if (!requested.needsInputInfo()) {
1174 return;
1175 }
1176
1177 static frontend::DisplayInfo sDefaultInfo = {.isSecure = false};
1178 const std::optional<frontend::DisplayInfo> displayInfoOpt =
1179 args.displays.get(snapshot.outputFilter.layerStack);
1180 bool noValidDisplay = !displayInfoOpt.has_value();
1181 auto displayInfo = displayInfoOpt.value_or(sDefaultInfo);
1182
1183 if (!requested.hasInputInfo()) {
1184 snapshot.inputInfo.inputConfig |= InputConfig::NO_INPUT_CHANNEL;
1185 }
1186 fillInputFrameInfo(snapshot.inputInfo, displayInfo.transform, snapshot);
1187
1188 if (noValidDisplay) {
1189 // Do not let the window receive touches if it is not associated with a valid display
1190 // transform. We still allow the window to receive keys and prevent ANRs.
1191 snapshot.inputInfo.inputConfig |= InputConfig::NOT_TOUCHABLE;
1192 }
1193
1194 snapshot.inputInfo.alpha = snapshot.color.a;
1195
1196 handleDropInputMode(snapshot, parentSnapshot);
1197
1198 // If the window will be blacked out on a display because the display does not have the secure
1199 // flag and the layer has the secure flag set, then drop input.
1200 if (!displayInfo.isSecure && snapshot.isSecure) {
1201 snapshot.inputInfo.inputConfig |= InputConfig::DROP_INPUT;
1202 }
1203
1204 if (requested.touchCropId != UNASSIGNED_LAYER_ID || path.isClone()) {
1205 mNeedsTouchableRegionCrop.insert(path);
1206 }
1207 auto cropLayerSnapshot = getSnapshot(requested.touchCropId);
1208 if (!cropLayerSnapshot && snapshot.inputInfo.replaceTouchableRegionWithCrop) {
1209 FloatRect inputBounds = getInputBounds(snapshot, /*fillParentBounds=*/true).first;
1210 Rect inputBoundsInDisplaySpace =
1211 getInputBoundsInDisplaySpace(snapshot, inputBounds, displayInfo.transform);
1212 snapshot.inputInfo.touchableRegion = Region(inputBoundsInDisplaySpace);
1213 }
1214
1215 // Inherit the trusted state from the parent hierarchy, but don't clobber the trusted state
1216 // if it was set by WM for a known system overlay
1217 if (snapshot.trustedOverlay == gui::TrustedOverlay::ENABLED) {
1218 snapshot.inputInfo.inputConfig |= InputConfig::TRUSTED_OVERLAY;
1219 }
1220
1221 snapshot.inputInfo.contentSize = {snapshot.croppedBufferSize.getHeight(),
1222 snapshot.croppedBufferSize.getWidth()};
1223
1224 snapshot.inputInfo.cloneLayerStackTransform.reset();
1225
1226 if (path.isClone()) {
1227 snapshot.inputInfo.inputConfig |= InputConfig::CLONE;
1228 // Cloned layers shouldn't handle watch outside since their z order is not determined by
1229 // WM or the client.
1230 snapshot.inputInfo.inputConfig.clear(InputConfig::WATCH_OUTSIDE_TOUCH);
1231
1232 // Compute the transform that maps the clone's display to the layer stack space of the
1233 // cloned window.
1234 const LayerSnapshot* clonedSnapshot = getSnapshot(path.getClonedFrom());
1235 if (clonedSnapshot != nullptr) {
1236 const auto& [clonedInputBounds, s] =
1237 getInputBounds(*clonedSnapshot, /*fillParentBounds=*/false);
1238 ui::Transform inputToLayer;
1239 inputToLayer.set(clonedInputBounds.left, clonedInputBounds.top);
1240 const ui::Transform& layerToLayerStack = getInputTransform(*clonedSnapshot);
1241 const auto& displayToInput = snapshot.inputInfo.transform;
1242 snapshot.inputInfo.cloneLayerStackTransform =
1243 layerToLayerStack * inputToLayer * displayToInput;
1244 }
1245 }
1246 }
1247
getSnapshots()1248 std::vector<std::unique_ptr<LayerSnapshot>>& LayerSnapshotBuilder::getSnapshots() {
1249 return mSnapshots;
1250 }
1251
forEachVisibleSnapshot(const ConstVisitor & visitor) const1252 void LayerSnapshotBuilder::forEachVisibleSnapshot(const ConstVisitor& visitor) const {
1253 for (int i = 0; i < mNumInterestingSnapshots; i++) {
1254 LayerSnapshot& snapshot = *mSnapshots[(size_t)i];
1255 if (!snapshot.isVisible) continue;
1256 visitor(snapshot);
1257 }
1258 }
1259
1260 // Visit each visible snapshot in z-order
forEachVisibleSnapshot(const ConstVisitor & visitor,const LayerHierarchy & root) const1261 void LayerSnapshotBuilder::forEachVisibleSnapshot(const ConstVisitor& visitor,
1262 const LayerHierarchy& root) const {
1263 root.traverseInZOrder(
1264 [this, visitor](const LayerHierarchy&,
1265 const LayerHierarchy::TraversalPath& traversalPath) -> bool {
1266 LayerSnapshot* snapshot = getSnapshot(traversalPath);
1267 if (snapshot && snapshot->isVisible) {
1268 visitor(*snapshot);
1269 }
1270 return true;
1271 });
1272 }
1273
forEachVisibleSnapshot(const Visitor & visitor)1274 void LayerSnapshotBuilder::forEachVisibleSnapshot(const Visitor& visitor) {
1275 for (int i = 0; i < mNumInterestingSnapshots; i++) {
1276 std::unique_ptr<LayerSnapshot>& snapshot = mSnapshots.at((size_t)i);
1277 if (!snapshot->isVisible) continue;
1278 visitor(snapshot);
1279 }
1280 }
1281
forEachSnapshot(const Visitor & visitor,const ConstPredicate & predicate)1282 void LayerSnapshotBuilder::forEachSnapshot(const Visitor& visitor,
1283 const ConstPredicate& predicate) {
1284 for (int i = 0; i < mNumInterestingSnapshots; i++) {
1285 std::unique_ptr<LayerSnapshot>& snapshot = mSnapshots.at((size_t)i);
1286 if (!predicate(*snapshot)) continue;
1287 visitor(snapshot);
1288 }
1289 }
1290
forEachSnapshot(const ConstVisitor & visitor) const1291 void LayerSnapshotBuilder::forEachSnapshot(const ConstVisitor& visitor) const {
1292 for (auto& snapshot : mSnapshots) {
1293 visitor(*snapshot);
1294 }
1295 }
1296
forEachInputSnapshot(const ConstVisitor & visitor) const1297 void LayerSnapshotBuilder::forEachInputSnapshot(const ConstVisitor& visitor) const {
1298 for (int i = mNumInterestingSnapshots - 1; i >= 0; i--) {
1299 LayerSnapshot& snapshot = *mSnapshots[(size_t)i];
1300 if (!snapshot.hasInputInfo()) continue;
1301 if (FlagManager::getInstance().skip_invisible_windows_in_input() &&
1302 snapshot.inputInfo.inputConfig.test(gui::WindowInfo::InputConfig::NOT_VISIBLE)) {
1303 continue;
1304 }
1305 visitor(snapshot);
1306 }
1307 }
1308
updateTouchableRegionCrop(const Args & args)1309 void LayerSnapshotBuilder::updateTouchableRegionCrop(const Args& args) {
1310 if (mNeedsTouchableRegionCrop.empty()) {
1311 return;
1312 }
1313
1314 static constexpr ftl::Flags<RequestedLayerState::Changes> AFFECTS_INPUT =
1315 RequestedLayerState::Changes::Visibility | RequestedLayerState::Changes::Created |
1316 RequestedLayerState::Changes::Hierarchy | RequestedLayerState::Changes::Geometry |
1317 RequestedLayerState::Changes::Input;
1318
1319 if (args.forceUpdate != ForceUpdateFlags::ALL &&
1320 !args.layerLifecycleManager.getGlobalChanges().any(AFFECTS_INPUT) && !args.displayChanges) {
1321 return;
1322 }
1323
1324 for (auto& path : mNeedsTouchableRegionCrop) {
1325 frontend::LayerSnapshot* snapshot = getSnapshot(path);
1326 if (!snapshot) {
1327 continue;
1328 }
1329 LLOGV(snapshot->sequence, "updateTouchableRegionCrop=%s",
1330 snapshot->getDebugString().c_str());
1331 const std::optional<frontend::DisplayInfo> displayInfoOpt =
1332 args.displays.get(snapshot->outputFilter.layerStack);
1333 static frontend::DisplayInfo sDefaultInfo = {.isSecure = false};
1334 auto displayInfo = displayInfoOpt.value_or(sDefaultInfo);
1335
1336 bool needsUpdate =
1337 args.forceUpdate == ForceUpdateFlags::ALL || snapshot->changes.any(AFFECTS_INPUT);
1338 auto cropLayerSnapshot = getSnapshot(snapshot->touchCropId);
1339 needsUpdate =
1340 needsUpdate || (cropLayerSnapshot && cropLayerSnapshot->changes.any(AFFECTS_INPUT));
1341 auto clonedRootSnapshot = path.isClone() ? getSnapshot(snapshot->mirrorRootPath) : nullptr;
1342 needsUpdate = needsUpdate ||
1343 (clonedRootSnapshot && clonedRootSnapshot->changes.any(AFFECTS_INPUT));
1344
1345 if (!needsUpdate) {
1346 continue;
1347 }
1348
1349 if (snapshot->inputInfo.replaceTouchableRegionWithCrop) {
1350 Rect inputBoundsInDisplaySpace;
1351 if (!cropLayerSnapshot) {
1352 FloatRect inputBounds = getInputBounds(*snapshot, /*fillParentBounds=*/true).first;
1353 inputBoundsInDisplaySpace =
1354 getInputBoundsInDisplaySpace(*snapshot, inputBounds, displayInfo.transform);
1355 } else {
1356 FloatRect inputBounds =
1357 getInputBounds(*cropLayerSnapshot, /*fillParentBounds=*/true).first;
1358 inputBoundsInDisplaySpace =
1359 getInputBoundsInDisplaySpace(*cropLayerSnapshot, inputBounds,
1360 displayInfo.transform);
1361 }
1362 snapshot->inputInfo.touchableRegion = Region(inputBoundsInDisplaySpace);
1363 } else if (cropLayerSnapshot) {
1364 FloatRect inputBounds =
1365 getInputBounds(*cropLayerSnapshot, /*fillParentBounds=*/true).first;
1366 Rect inputBoundsInDisplaySpace =
1367 getInputBoundsInDisplaySpace(*cropLayerSnapshot, inputBounds,
1368 displayInfo.transform);
1369 snapshot->inputInfo.touchableRegion =
1370 snapshot->inputInfo.touchableRegion.intersect(inputBoundsInDisplaySpace);
1371 }
1372
1373 // If the layer is a clone, we need to crop the input region to cloned root to prevent
1374 // touches from going outside the cloned area.
1375 if (clonedRootSnapshot) {
1376 const Rect rect =
1377 displayInfo.transform.transform(Rect{clonedRootSnapshot->transformedBounds});
1378 snapshot->inputInfo.touchableRegion =
1379 snapshot->inputInfo.touchableRegion.intersect(rect);
1380 }
1381 }
1382 }
1383
1384 } // namespace android::surfaceflinger::frontend
1385