• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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