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