• 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 #undef LOG_TAG
20 #define LOG_TAG "SurfaceFlinger"
21 
22 #include <numeric>
23 #include <optional>
24 
25 #include <ftl/small_map.h>
26 #include <gui/TraceUtils.h>
27 #include <ui/DisplayMap.h>
28 #include <ui/FloatRect.h>
29 
30 #include "DisplayHardware/HWC2.h"
31 #include "DisplayHardware/Hal.h"
32 #include "LayerLog.h"
33 #include "LayerSnapshotBuilder.h"
34 #include "TimeStats/TimeStats.h"
35 #include "Tracing/TransactionTracing.h"
36 
37 namespace android::surfaceflinger::frontend {
38 
39 using namespace ftl::flag_operators;
40 
41 namespace {
42 
getMaxDisplayBounds(const DisplayInfos & displays)43 FloatRect getMaxDisplayBounds(const DisplayInfos& displays) {
44     const ui::Size maxSize = [&displays] {
45         if (displays.empty()) return ui::Size{5000, 5000};
46 
47         return std::accumulate(displays.begin(), displays.end(), ui::kEmptySize,
48                                [](ui::Size size, const auto& pair) -> ui::Size {
49                                    const auto& display = pair.second;
50                                    return {std::max(size.getWidth(), display.info.logicalWidth),
51                                            std::max(size.getHeight(), display.info.logicalHeight)};
52                                });
53     }();
54 
55     // Ignore display bounds for now since they will be computed later. Use a large Rect bound
56     // to ensure it's bigger than an actual display will be.
57     const float xMax = static_cast<float>(maxSize.getWidth()) * 10.f;
58     const float yMax = static_cast<float>(maxSize.getHeight()) * 10.f;
59 
60     return {-xMax, -yMax, xMax, yMax};
61 }
62 
63 // Applies the given transform to the region, while protecting against overflows caused by any
64 // offsets. If applying the offset in the transform to any of the Rects in the region would result
65 // in an overflow, they are not added to the output Region.
transformTouchableRegionSafely(const ui::Transform & t,const Region & r,const std::string & debugWindowName)66 Region transformTouchableRegionSafely(const ui::Transform& t, const Region& r,
67                                       const std::string& debugWindowName) {
68     // Round the translation using the same rounding strategy used by ui::Transform.
69     const auto tx = static_cast<int32_t>(t.tx() + 0.5);
70     const auto ty = static_cast<int32_t>(t.ty() + 0.5);
71 
72     ui::Transform transformWithoutOffset = t;
73     transformWithoutOffset.set(0.f, 0.f);
74 
75     const Region transformed = transformWithoutOffset.transform(r);
76 
77     // Apply the translation to each of the Rects in the region while discarding any that overflow.
78     Region ret;
79     for (const auto& rect : transformed) {
80         Rect newRect;
81         if (__builtin_add_overflow(rect.left, tx, &newRect.left) ||
82             __builtin_add_overflow(rect.top, ty, &newRect.top) ||
83             __builtin_add_overflow(rect.right, tx, &newRect.right) ||
84             __builtin_add_overflow(rect.bottom, ty, &newRect.bottom)) {
85             ALOGE("Applying transform to touchable region of window '%s' resulted in an overflow.",
86                   debugWindowName.c_str());
87             continue;
88         }
89         ret.orSelf(newRect);
90     }
91     return ret;
92 }
93 
94 /*
95  * We don't want to send the layer's transform to input, but rather the
96  * parent's transform. This is because Layer's transform is
97  * information about how the buffer is placed on screen. The parent's
98  * transform makes more sense to send since it's information about how the
99  * layer is placed on screen. This transform is used by input to determine
100  * how to go from screen space back to window space.
101  */
getInputTransform(const LayerSnapshot & snapshot)102 ui::Transform getInputTransform(const LayerSnapshot& snapshot) {
103     if (!snapshot.hasBufferOrSidebandStream()) {
104         return snapshot.geomLayerTransform;
105     }
106     return snapshot.parentTransform;
107 }
108 
109 /**
110  * Returns the bounds used to fill the input frame and the touchable region.
111  *
112  * Similar to getInputTransform, we need to update the bounds to include the transform.
113  * This is because bounds don't include the buffer transform, where the input assumes
114  * that's already included.
115  */
getInputBounds(const LayerSnapshot & snapshot,bool fillParentBounds)116 std::pair<FloatRect, bool> getInputBounds(const LayerSnapshot& snapshot, bool fillParentBounds) {
117     FloatRect inputBounds = snapshot.croppedBufferSize.toFloatRect();
118     if (snapshot.hasBufferOrSidebandStream() && snapshot.croppedBufferSize.isValid() &&
119         snapshot.localTransform.getType() != ui::Transform::IDENTITY) {
120         inputBounds = snapshot.localTransform.transform(inputBounds);
121     }
122 
123     bool inputBoundsValid = snapshot.croppedBufferSize.isValid();
124     if (!inputBoundsValid) {
125         /**
126          * Input bounds are based on the layer crop or buffer size. But if we are using
127          * the layer bounds as the input bounds (replaceTouchableRegionWithCrop flag) then
128          * we can use the parent bounds as the input bounds if the layer does not have buffer
129          * or a crop. We want to unify this logic but because of compat reasons we cannot always
130          * use the parent bounds. A layer without a buffer can get input. So when a window is
131          * initially added, its touchable region can fill its parent layer bounds and that can
132          * have negative consequences.
133          */
134         inputBounds = fillParentBounds ? snapshot.geomLayerBounds : FloatRect{};
135     }
136 
137     // Clamp surface inset to the input bounds.
138     const float inset = static_cast<float>(snapshot.inputInfo.surfaceInset);
139     const float xSurfaceInset = std::clamp(inset, 0.f, inputBounds.getWidth() / 2.f);
140     const float ySurfaceInset = std::clamp(inset, 0.f, inputBounds.getHeight() / 2.f);
141 
142     // Apply the insets to the input bounds.
143     inputBounds.left += xSurfaceInset;
144     inputBounds.top += ySurfaceInset;
145     inputBounds.right -= xSurfaceInset;
146     inputBounds.bottom -= ySurfaceInset;
147     return {inputBounds, inputBoundsValid};
148 }
149 
getInputBoundsInDisplaySpace(const LayerSnapshot & snapshot,const FloatRect & insetBounds,const ui::Transform & screenToDisplay)150 Rect getInputBoundsInDisplaySpace(const LayerSnapshot& snapshot, const FloatRect& insetBounds,
151                                   const ui::Transform& screenToDisplay) {
152     // InputDispatcher works in the display device's coordinate space. Here, we calculate the
153     // frame and transform used for the layer, which determines the bounds and the coordinate space
154     // within which the layer will receive input.
155 
156     // Coordinate space definitions:
157     //   - display: The display device's coordinate space. Correlates to pixels on the display.
158     //   - screen: The post-rotation coordinate space for the display, a.k.a. logical display space.
159     //   - layer: The coordinate space of this layer.
160     //   - input: The coordinate space in which this layer will receive input events. This could be
161     //            different than layer space if a surfaceInset is used, which changes the origin
162     //            of the input space.
163 
164     // Crop the input bounds to ensure it is within the parent's bounds.
165     const FloatRect croppedInsetBoundsInLayer = snapshot.geomLayerBounds.intersect(insetBounds);
166 
167     const ui::Transform layerToScreen = getInputTransform(snapshot);
168     const ui::Transform layerToDisplay = screenToDisplay * layerToScreen;
169 
170     return Rect{layerToDisplay.transform(croppedInsetBoundsInLayer)};
171 }
172 
fillInputFrameInfo(gui::WindowInfo & info,const ui::Transform & screenToDisplay,const LayerSnapshot & snapshot)173 void fillInputFrameInfo(gui::WindowInfo& info, const ui::Transform& screenToDisplay,
174                         const LayerSnapshot& snapshot) {
175     auto [inputBounds, inputBoundsValid] = getInputBounds(snapshot, /*fillParentBounds=*/false);
176     if (!inputBoundsValid) {
177         info.touchableRegion.clear();
178     }
179 
180     const Rect roundedFrameInDisplay =
181             getInputBoundsInDisplaySpace(snapshot, inputBounds, screenToDisplay);
182     info.frameLeft = roundedFrameInDisplay.left;
183     info.frameTop = roundedFrameInDisplay.top;
184     info.frameRight = roundedFrameInDisplay.right;
185     info.frameBottom = roundedFrameInDisplay.bottom;
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     Rect 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     snapshot.isVisible = visible;
263 
264     // TODO(b/238781169) we are ignoring this compat for now, since we will have
265     // to remove any optimization based on visibility.
266 
267     // For compatibility reasons we let layers which can receive input
268     // receive input before they have actually submitted a buffer. Because
269     // of this we use canReceiveInput instead of isVisible to check the
270     // policy-visibility, ignoring the buffer state. However for layers with
271     // hasInputInfo()==false we can use the real visibility state.
272     // We are just using these layers for occlusion detection in
273     // InputDispatcher, and obviously if they aren't visible they can't occlude
274     // anything.
275     const bool visibleForInput =
276             snapshot.hasInputInfo() ? snapshot.canReceiveInput() : snapshot.isVisible;
277     snapshot.inputInfo.setInputConfig(gui::WindowInfo::InputConfig::NOT_VISIBLE, !visibleForInput);
278     LLOGV(snapshot.sequence, "updating visibility %s %s", visible ? "true" : "false",
279           snapshot.getDebugString().c_str());
280 }
281 
needsInputInfo(const LayerSnapshot & snapshot,const RequestedLayerState & requested)282 bool needsInputInfo(const LayerSnapshot& snapshot, const RequestedLayerState& requested) {
283     if (requested.potentialCursor) {
284         return false;
285     }
286 
287     if (snapshot.inputInfo.token != nullptr) {
288         return true;
289     }
290 
291     if (snapshot.hasBufferOrSidebandStream()) {
292         return true;
293     }
294 
295     return requested.windowInfoHandle &&
296             requested.windowInfoHandle->getInfo()->inputConfig.test(
297                     gui::WindowInfo::InputConfig::NO_INPUT_CHANNEL);
298 }
299 
updateMetadata(LayerSnapshot & snapshot,const RequestedLayerState & requested,const LayerSnapshotBuilder::Args & args)300 void updateMetadata(LayerSnapshot& snapshot, const RequestedLayerState& requested,
301                     const LayerSnapshotBuilder::Args& args) {
302     snapshot.metadata.clear();
303     for (const auto& [key, mandatory] : args.supportedLayerGenericMetadata) {
304         auto compatIter = args.genericLayerMetadataKeyMap.find(key);
305         if (compatIter == std::end(args.genericLayerMetadataKeyMap)) {
306             continue;
307         }
308         const uint32_t id = compatIter->second;
309         auto it = requested.metadata.mMap.find(id);
310         if (it == std::end(requested.metadata.mMap)) {
311             continue;
312         }
313 
314         snapshot.metadata.emplace(key,
315                                   compositionengine::GenericLayerMetadataEntry{mandatory,
316                                                                                it->second});
317     }
318 }
319 
clearChanges(LayerSnapshot & snapshot)320 void clearChanges(LayerSnapshot& snapshot) {
321     snapshot.changes.clear();
322     snapshot.clientChanges = 0;
323     snapshot.contentDirty = false;
324     snapshot.hasReadyFrame = false;
325     snapshot.sidebandStreamHasFrame = false;
326     snapshot.surfaceDamage.clear();
327 }
328 
329 // TODO (b/259407931): Remove.
getPrimaryDisplayRotationFlags(const ui::DisplayMap<ui::LayerStack,frontend::DisplayInfo> & displays)330 uint32_t getPrimaryDisplayRotationFlags(
331         const ui::DisplayMap<ui::LayerStack, frontend::DisplayInfo>& displays) {
332     for (auto& [_, display] : displays) {
333         if (display.isPrimary) {
334             return display.rotationFlags;
335         }
336     }
337     return 0;
338 }
339 
340 } // namespace
341 
getRootSnapshot()342 LayerSnapshot LayerSnapshotBuilder::getRootSnapshot() {
343     LayerSnapshot snapshot;
344     snapshot.path = LayerHierarchy::TraversalPath::ROOT;
345     snapshot.changes = ftl::Flags<RequestedLayerState::Changes>();
346     snapshot.clientChanges = 0;
347     snapshot.isHiddenByPolicyFromParent = false;
348     snapshot.isHiddenByPolicyFromRelativeParent = false;
349     snapshot.parentTransform.reset();
350     snapshot.geomLayerTransform.reset();
351     snapshot.geomInverseLayerTransform.reset();
352     snapshot.geomLayerBounds = getMaxDisplayBounds({});
353     snapshot.roundedCorner = RoundedCornerState();
354     snapshot.stretchEffect = {};
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.shadowRadius = 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.isTrustedOverlay = false;
366     snapshot.gameMode = gui::GameMode::Unsupported;
367     snapshot.frameRate = {};
368     snapshot.fixedTransformHint = ui::Transform::ROT_INVALID;
369     return snapshot;
370 }
371 
LayerSnapshotBuilder()372 LayerSnapshotBuilder::LayerSnapshotBuilder() : mRootSnapshot(getRootSnapshot()) {}
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     ATRACE_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     ATRACE_NAME("UpdateSnapshots");
424     if (args.parentCrop) {
425         mRootSnapshot.geomLayerBounds = *args.parentCrop;
426     } else if (args.forceUpdate == ForceUpdateFlags::ALL || args.displayChanges) {
427         mRootSnapshot.geomLayerBounds = getMaxDisplayBounds(args.displays);
428     }
429     if (args.displayChanges) {
430         mRootSnapshot.changes = RequestedLayerState::Changes::AffectsChildren |
431                 RequestedLayerState::Changes::Geometry;
432     }
433     if (args.forceUpdate == ForceUpdateFlags::HIERARCHY) {
434         mRootSnapshot.changes |=
435                 RequestedLayerState::Changes::Hierarchy | RequestedLayerState::Changes::Visibility;
436         mRootSnapshot.clientChanges |= layer_state_t::eReparent;
437     }
438 
439     for (auto& snapshot : mSnapshots) {
440         if (snapshot->reachablilty == LayerSnapshot::Reachablilty::Reachable) {
441             snapshot->reachablilty = LayerSnapshot::Reachablilty::Unreachable;
442         }
443     }
444 
445     LayerHierarchy::TraversalPath root = LayerHierarchy::TraversalPath::ROOT;
446     if (args.root.getLayer()) {
447         // The hierarchy can have a root layer when used for screenshots otherwise, it will have
448         // multiple children.
449         LayerHierarchy::ScopedAddToTraversalPath addChildToPath(root, args.root.getLayer()->id,
450                                                                 LayerHierarchy::Variant::Attached);
451         updateSnapshotsInHierarchy(args, args.root, root, mRootSnapshot, /*depth=*/0);
452     } else {
453         for (auto& [childHierarchy, variant] : args.root.mChildren) {
454             LayerHierarchy::ScopedAddToTraversalPath addChildToPath(root,
455                                                                     childHierarchy->getLayer()->id,
456                                                                     variant);
457             updateSnapshotsInHierarchy(args, *childHierarchy, root, mRootSnapshot, /*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     clearChanges(mRootSnapshot);
467 
468     // Destroy unreachable snapshots for clone layers. And destroy snapshots for non-clone
469     // layers if the layer have been destroyed.
470     // TODO(b/238781169) consider making clone layer ids stable as well
471     if (!hasUnreachableSnapshots && args.layerLifecycleManager.getDestroyedLayers().empty()) {
472         return;
473     }
474 
475     std::unordered_set<uint32_t> destroyedLayerIds;
476     for (auto& destroyedLayer : args.layerLifecycleManager.getDestroyedLayers()) {
477         destroyedLayerIds.insert(destroyedLayer->id);
478     }
479 
480     auto it = mSnapshots.begin();
481     while (it < mSnapshots.end()) {
482         auto& traversalPath = it->get()->path;
483         const bool unreachable =
484                 it->get()->reachablilty == LayerSnapshot::Reachablilty::Unreachable;
485         const bool isClone = traversalPath.isClone();
486         const bool layerIsDestroyed =
487                 destroyedLayerIds.find(traversalPath.id) != destroyedLayerIds.end();
488         const bool destroySnapshot = (unreachable && isClone) || layerIsDestroyed;
489 
490         if (!destroySnapshot) {
491             it++;
492             continue;
493         }
494 
495         mPathToSnapshot.erase(traversalPath);
496 
497         auto range = mIdToSnapshots.equal_range(traversalPath.id);
498         auto matchingSnapshot =
499                 std::find_if(range.first, range.second, [&traversalPath](auto& snapshotWithId) {
500                     return snapshotWithId.second->path == traversalPath;
501                 });
502         mIdToSnapshots.erase(matchingSnapshot);
503         mNeedsTouchableRegionCrop.erase(traversalPath);
504         mSnapshots.back()->globalZ = it->get()->globalZ;
505         std::iter_swap(it, mSnapshots.end() - 1);
506         mSnapshots.erase(mSnapshots.end() - 1);
507     }
508 }
509 
update(const Args & args)510 void LayerSnapshotBuilder::update(const Args& args) {
511     for (auto& snapshot : mSnapshots) {
512         clearChanges(*snapshot);
513     }
514 
515     if (tryFastUpdate(args)) {
516         return;
517     }
518     updateSnapshots(args);
519 }
520 
updateSnapshotsInHierarchy(const Args & args,const LayerHierarchy & hierarchy,LayerHierarchy::TraversalPath & traversalPath,const LayerSnapshot & parentSnapshot,int depth)521 const LayerSnapshot& LayerSnapshotBuilder::updateSnapshotsInHierarchy(
522         const Args& args, const LayerHierarchy& hierarchy,
523         LayerHierarchy::TraversalPath& traversalPath, const LayerSnapshot& parentSnapshot,
524         int depth) {
525     if (depth > 50) {
526         TransactionTraceWriter::getInstance().invoke("layer_builder_stack_overflow_",
527                                                      /*overwrite=*/false);
528         LOG_ALWAYS_FATAL("Cycle detected in LayerSnapshotBuilder. See "
529                          "builder_stack_overflow_transactions.winscope");
530     }
531 
532     const RequestedLayerState* layer = hierarchy.getLayer();
533     LayerSnapshot* snapshot = getSnapshot(traversalPath);
534     const bool newSnapshot = snapshot == nullptr;
535     uint32_t primaryDisplayRotationFlags = getPrimaryDisplayRotationFlags(args.displays);
536     if (newSnapshot) {
537         snapshot = createSnapshot(traversalPath, *layer, parentSnapshot);
538         snapshot->merge(*layer, /*forceUpdate=*/true, /*displayChanges=*/true, args.forceFullDamage,
539                         primaryDisplayRotationFlags);
540         snapshot->changes |= RequestedLayerState::Changes::Created;
541     }
542     scheduler::LayerInfo::FrameRate oldFrameRate = snapshot->frameRate;
543     if (traversalPath.isRelative()) {
544         bool parentIsRelative = traversalPath.variant == LayerHierarchy::Variant::Relative;
545         updateRelativeState(*snapshot, parentSnapshot, parentIsRelative, args);
546     } else {
547         if (traversalPath.isAttached()) {
548             resetRelativeState(*snapshot);
549         }
550         updateSnapshot(*snapshot, args, *layer, parentSnapshot, traversalPath);
551     }
552 
553     for (auto& [childHierarchy, variant] : hierarchy.mChildren) {
554         LayerHierarchy::ScopedAddToTraversalPath addChildToPath(traversalPath,
555                                                                 childHierarchy->getLayer()->id,
556                                                                 variant);
557         const LayerSnapshot& childSnapshot =
558                 updateSnapshotsInHierarchy(args, *childHierarchy, traversalPath, *snapshot,
559                                            depth + 1);
560         updateChildState(*snapshot, childSnapshot, args);
561     }
562 
563     if (oldFrameRate == snapshot->frameRate) {
564         snapshot->changes.clear(RequestedLayerState::Changes::FrameRate);
565     }
566     return *snapshot;
567 }
568 
getSnapshot(uint32_t layerId) const569 LayerSnapshot* LayerSnapshotBuilder::getSnapshot(uint32_t layerId) const {
570     if (layerId == UNASSIGNED_LAYER_ID) {
571         return nullptr;
572     }
573     LayerHierarchy::TraversalPath path{.id = layerId};
574     return getSnapshot(path);
575 }
576 
getSnapshot(const LayerHierarchy::TraversalPath & id) const577 LayerSnapshot* LayerSnapshotBuilder::getSnapshot(const LayerHierarchy::TraversalPath& id) const {
578     auto it = mPathToSnapshot.find(id);
579     return it == mPathToSnapshot.end() ? nullptr : it->second;
580 }
581 
createSnapshot(const LayerHierarchy::TraversalPath & path,const RequestedLayerState & layer,const LayerSnapshot & parentSnapshot)582 LayerSnapshot* LayerSnapshotBuilder::createSnapshot(const LayerHierarchy::TraversalPath& path,
583                                                     const RequestedLayerState& layer,
584                                                     const LayerSnapshot& parentSnapshot) {
585     mSnapshots.emplace_back(std::make_unique<LayerSnapshot>(layer, path));
586     LayerSnapshot* snapshot = mSnapshots.back().get();
587     snapshot->globalZ = static_cast<size_t>(mSnapshots.size()) - 1;
588     if (path.isClone() && path.variant != LayerHierarchy::Variant::Mirror) {
589         snapshot->mirrorRootPath = parentSnapshot.mirrorRootPath;
590     }
591     mPathToSnapshot[path] = snapshot;
592 
593     mIdToSnapshots.emplace(path.id, snapshot);
594     return snapshot;
595 }
596 
sortSnapshotsByZ(const Args & args)597 bool LayerSnapshotBuilder::sortSnapshotsByZ(const Args& args) {
598     if (!mResortSnapshots && args.forceUpdate == ForceUpdateFlags::NONE &&
599         !args.layerLifecycleManager.getGlobalChanges().any(
600                 RequestedLayerState::Changes::Hierarchy |
601                 RequestedLayerState::Changes::Visibility)) {
602         // We are not force updating and there are no hierarchy or visibility changes. Avoid sorting
603         // the snapshots.
604         return false;
605     }
606     mResortSnapshots = false;
607 
608     size_t globalZ = 0;
609     args.root.traverseInZOrder(
610             [this, &globalZ](const LayerHierarchy&,
611                              const LayerHierarchy::TraversalPath& traversalPath) -> bool {
612                 LayerSnapshot* snapshot = getSnapshot(traversalPath);
613                 if (!snapshot) {
614                     return true;
615                 }
616 
617                 if (snapshot->getIsVisible() || snapshot->hasInputInfo()) {
618                     updateVisibility(*snapshot, snapshot->getIsVisible());
619                     size_t oldZ = snapshot->globalZ;
620                     size_t newZ = globalZ++;
621                     snapshot->globalZ = newZ;
622                     if (oldZ == newZ) {
623                         return true;
624                     }
625                     mSnapshots[newZ]->globalZ = oldZ;
626                     LLOGV(snapshot->sequence, "Made visible z=%zu -> %zu %s", oldZ, newZ,
627                           snapshot->getDebugString().c_str());
628                     std::iter_swap(mSnapshots.begin() + static_cast<ssize_t>(oldZ),
629                                    mSnapshots.begin() + static_cast<ssize_t>(newZ));
630                 }
631                 return true;
632             });
633     mNumInterestingSnapshots = (int)globalZ;
634     bool hasUnreachableSnapshots = false;
635     while (globalZ < mSnapshots.size()) {
636         mSnapshots[globalZ]->globalZ = globalZ;
637         /* mark unreachable snapshots as explicitly invisible */
638         updateVisibility(*mSnapshots[globalZ], false);
639         if (mSnapshots[globalZ]->reachablilty == LayerSnapshot::Reachablilty::Unreachable) {
640             hasUnreachableSnapshots = true;
641         }
642         globalZ++;
643     }
644     return hasUnreachableSnapshots;
645 }
646 
updateRelativeState(LayerSnapshot & snapshot,const LayerSnapshot & parentSnapshot,bool parentIsRelative,const Args & args)647 void LayerSnapshotBuilder::updateRelativeState(LayerSnapshot& snapshot,
648                                                const LayerSnapshot& parentSnapshot,
649                                                bool parentIsRelative, const Args& args) {
650     if (parentIsRelative) {
651         snapshot.isHiddenByPolicyFromRelativeParent =
652                 parentSnapshot.isHiddenByPolicyFromParent || parentSnapshot.invalidTransform;
653         if (args.includeMetadata) {
654             snapshot.relativeLayerMetadata = parentSnapshot.layerMetadata;
655         }
656     } else {
657         snapshot.isHiddenByPolicyFromRelativeParent =
658                 parentSnapshot.isHiddenByPolicyFromRelativeParent;
659         if (args.includeMetadata) {
660             snapshot.relativeLayerMetadata = parentSnapshot.relativeLayerMetadata;
661         }
662     }
663     if (snapshot.reachablilty == LayerSnapshot::Reachablilty::Unreachable) {
664         snapshot.reachablilty = LayerSnapshot::Reachablilty::ReachableByRelativeParent;
665     }
666 }
667 
updateChildState(LayerSnapshot & snapshot,const LayerSnapshot & childSnapshot,const Args & args)668 void LayerSnapshotBuilder::updateChildState(LayerSnapshot& snapshot,
669                                             const LayerSnapshot& childSnapshot, const Args& args) {
670     if (snapshot.childState.hasValidFrameRate) {
671         return;
672     }
673     if (args.forceUpdate == ForceUpdateFlags::ALL ||
674         childSnapshot.changes.test(RequestedLayerState::Changes::FrameRate)) {
675         // We return whether this layer ot its children has a vote. We ignore ExactOrMultiple votes
676         // for the same reason we are allowing touch boost for those layers. See
677         // RefreshRateSelector::rankFrameRates for details.
678         using FrameRateCompatibility = scheduler::LayerInfo::FrameRateCompatibility;
679         const auto layerVotedWithDefaultCompatibility = childSnapshot.frameRate.rate.isValid() &&
680                 childSnapshot.frameRate.type == FrameRateCompatibility::Default;
681         const auto layerVotedWithNoVote =
682                 childSnapshot.frameRate.type == FrameRateCompatibility::NoVote;
683         const auto layerVotedWithExactCompatibility = childSnapshot.frameRate.rate.isValid() &&
684                 childSnapshot.frameRate.type == FrameRateCompatibility::Exact;
685 
686         snapshot.childState.hasValidFrameRate |= layerVotedWithDefaultCompatibility ||
687                 layerVotedWithNoVote || layerVotedWithExactCompatibility;
688 
689         // If we don't have a valid frame rate, but the children do, we set this
690         // layer as NoVote to allow the children to control the refresh rate
691         if (!snapshot.frameRate.rate.isValid() &&
692             snapshot.frameRate.type != FrameRateCompatibility::NoVote &&
693             snapshot.childState.hasValidFrameRate) {
694             snapshot.frameRate =
695                     scheduler::LayerInfo::FrameRate(Fps(), FrameRateCompatibility::NoVote);
696             snapshot.changes |= childSnapshot.changes & RequestedLayerState::Changes::FrameRate;
697         }
698     }
699 }
700 
resetRelativeState(LayerSnapshot & snapshot)701 void LayerSnapshotBuilder::resetRelativeState(LayerSnapshot& snapshot) {
702     snapshot.isHiddenByPolicyFromRelativeParent = false;
703     snapshot.relativeLayerMetadata.mMap.clear();
704 }
705 
updateSnapshot(LayerSnapshot & snapshot,const Args & args,const RequestedLayerState & requested,const LayerSnapshot & parentSnapshot,const LayerHierarchy::TraversalPath & path)706 void LayerSnapshotBuilder::updateSnapshot(LayerSnapshot& snapshot, const Args& args,
707                                           const RequestedLayerState& requested,
708                                           const LayerSnapshot& parentSnapshot,
709                                           const LayerHierarchy::TraversalPath& path) {
710     // Always update flags and visibility
711     ftl::Flags<RequestedLayerState::Changes> parentChanges = parentSnapshot.changes &
712             (RequestedLayerState::Changes::Hierarchy | RequestedLayerState::Changes::Geometry |
713              RequestedLayerState::Changes::Visibility | RequestedLayerState::Changes::Metadata |
714              RequestedLayerState::Changes::AffectsChildren |
715              RequestedLayerState::Changes::FrameRate | RequestedLayerState::Changes::GameMode);
716     snapshot.changes |= parentChanges;
717     if (args.displayChanges) snapshot.changes |= RequestedLayerState::Changes::Geometry;
718     snapshot.reachablilty = LayerSnapshot::Reachablilty::Reachable;
719     snapshot.clientChanges |= (parentSnapshot.clientChanges & layer_state_t::AFFECTS_CHILDREN);
720     snapshot.isHiddenByPolicyFromParent = parentSnapshot.isHiddenByPolicyFromParent ||
721             parentSnapshot.invalidTransform || requested.isHiddenByPolicy() ||
722             (args.excludeLayerIds.find(path.id) != args.excludeLayerIds.end());
723 
724     const bool forceUpdate = args.forceUpdate == ForceUpdateFlags::ALL ||
725             snapshot.clientChanges & layer_state_t::eReparent ||
726             snapshot.changes.any(RequestedLayerState::Changes::Visibility |
727                                  RequestedLayerState::Changes::Created);
728 
729     if (forceUpdate || snapshot.clientChanges & layer_state_t::eLayerStackChanged) {
730         // If root layer, use the layer stack otherwise get the parent's layer stack.
731         snapshot.outputFilter.layerStack =
732                 parentSnapshot.path == LayerHierarchy::TraversalPath::ROOT
733                 ? requested.layerStack
734                 : parentSnapshot.outputFilter.layerStack;
735     }
736 
737     if (snapshot.isHiddenByPolicyFromParent &&
738         !snapshot.changes.test(RequestedLayerState::Changes::Created)) {
739         if (forceUpdate ||
740             snapshot.changes.any(RequestedLayerState::Changes::Geometry |
741                                  RequestedLayerState::Changes::Input)) {
742             updateInput(snapshot, requested, parentSnapshot, path, args);
743         }
744         return;
745     }
746 
747     if (forceUpdate || snapshot.changes.any(RequestedLayerState::Changes::Mirror)) {
748         // Display mirrors are always placed in a VirtualDisplay so we never want to capture layers
749         // marked as skip capture
750         snapshot.handleSkipScreenshotFlag = parentSnapshot.handleSkipScreenshotFlag ||
751                 (requested.layerStackToMirror != ui::INVALID_LAYER_STACK);
752     }
753 
754     if (forceUpdate || snapshot.clientChanges & layer_state_t::eAlphaChanged) {
755         snapshot.color.a = parentSnapshot.color.a * requested.color.a;
756         snapshot.alpha = snapshot.color.a;
757         snapshot.inputInfo.alpha = snapshot.color.a;
758     }
759 
760     if (forceUpdate || snapshot.clientChanges & layer_state_t::eFlagsChanged) {
761         snapshot.isSecure =
762                 parentSnapshot.isSecure || (requested.flags & layer_state_t::eLayerSecure);
763         snapshot.outputFilter.toInternalDisplay = parentSnapshot.outputFilter.toInternalDisplay ||
764                 (requested.flags & layer_state_t::eLayerSkipScreenshot);
765     }
766 
767     if (forceUpdate || snapshot.clientChanges & layer_state_t::eTrustedOverlayChanged) {
768         snapshot.isTrustedOverlay = parentSnapshot.isTrustedOverlay || requested.isTrustedOverlay;
769     }
770 
771     if (forceUpdate || snapshot.clientChanges & layer_state_t::eStretchChanged) {
772         snapshot.stretchEffect = (requested.stretchEffect.hasEffect())
773                 ? requested.stretchEffect
774                 : parentSnapshot.stretchEffect;
775     }
776 
777     if (forceUpdate || snapshot.clientChanges & layer_state_t::eColorTransformChanged) {
778         if (!parentSnapshot.colorTransformIsIdentity) {
779             snapshot.colorTransform = parentSnapshot.colorTransform * requested.colorTransform;
780             snapshot.colorTransformIsIdentity = false;
781         } else {
782             snapshot.colorTransform = requested.colorTransform;
783             snapshot.colorTransformIsIdentity = !requested.hasColorTransform;
784         }
785     }
786 
787     if (forceUpdate || snapshot.changes.test(RequestedLayerState::Changes::GameMode)) {
788         snapshot.gameMode = requested.metadata.has(gui::METADATA_GAME_MODE)
789                 ? requested.gameMode
790                 : parentSnapshot.gameMode;
791         updateMetadata(snapshot, requested, args);
792         if (args.includeMetadata) {
793             snapshot.layerMetadata = parentSnapshot.layerMetadata;
794             snapshot.layerMetadata.merge(requested.metadata);
795         }
796     }
797 
798     if (forceUpdate || snapshot.clientChanges & layer_state_t::eFixedTransformHintChanged ||
799         args.displayChanges) {
800         snapshot.fixedTransformHint = requested.fixedTransformHint != ui::Transform::ROT_INVALID
801                 ? requested.fixedTransformHint
802                 : parentSnapshot.fixedTransformHint;
803 
804         if (snapshot.fixedTransformHint != ui::Transform::ROT_INVALID) {
805             snapshot.transformHint = snapshot.fixedTransformHint;
806         } else {
807             const auto display = args.displays.get(snapshot.outputFilter.layerStack);
808             snapshot.transformHint = display.has_value()
809                     ? std::make_optional<>(display->get().transformHint)
810                     : std::nullopt;
811         }
812     }
813 
814     if (forceUpdate || snapshot.changes.any(RequestedLayerState::Changes::FrameRate)) {
815         snapshot.frameRate = (requested.requestedFrameRate.rate.isValid() ||
816                               (requested.requestedFrameRate.type ==
817                                scheduler::LayerInfo::FrameRateCompatibility::NoVote))
818                 ? requested.requestedFrameRate
819                 : parentSnapshot.frameRate;
820     }
821 
822     if (forceUpdate ||
823         snapshot.clientChanges &
824                 (layer_state_t::eBackgroundBlurRadiusChanged | layer_state_t::eBlurRegionsChanged |
825                  layer_state_t::eAlphaChanged)) {
826         snapshot.backgroundBlurRadius = args.supportsBlur
827                 ? static_cast<int>(parentSnapshot.color.a * (float)requested.backgroundBlurRadius)
828                 : 0;
829         snapshot.blurRegions = requested.blurRegions;
830         for (auto& region : snapshot.blurRegions) {
831             region.alpha = region.alpha * snapshot.color.a;
832         }
833     }
834 
835     if (forceUpdate || snapshot.changes.any(RequestedLayerState::Changes::Geometry)) {
836         uint32_t primaryDisplayRotationFlags = getPrimaryDisplayRotationFlags(args.displays);
837         updateLayerBounds(snapshot, requested, parentSnapshot, primaryDisplayRotationFlags);
838     }
839 
840     if (forceUpdate || snapshot.clientChanges & layer_state_t::eCornerRadiusChanged ||
841         snapshot.changes.any(RequestedLayerState::Changes::Geometry)) {
842         updateRoundedCorner(snapshot, requested, parentSnapshot);
843     }
844 
845     if (forceUpdate || snapshot.clientChanges & layer_state_t::eShadowRadiusChanged ||
846         snapshot.changes.any(RequestedLayerState::Changes::Geometry)) {
847         updateShadows(snapshot, requested, args.globalShadowSettings);
848     }
849 
850     if (forceUpdate ||
851         snapshot.changes.any(RequestedLayerState::Changes::Geometry |
852                              RequestedLayerState::Changes::Input)) {
853         updateInput(snapshot, requested, parentSnapshot, path, args);
854     }
855 
856     // computed snapshot properties
857     snapshot.forceClientComposition = snapshot.isHdrY410 || snapshot.shadowSettings.length > 0 ||
858             requested.blurRegions.size() > 0 || snapshot.stretchEffect.hasEffect();
859     snapshot.contentOpaque = snapshot.isContentOpaque();
860     snapshot.isOpaque = snapshot.contentOpaque && !snapshot.roundedCorner.hasRoundedCorners() &&
861             snapshot.color.a == 1.f;
862     snapshot.blendMode = getBlendMode(snapshot, requested);
863     LLOGV(snapshot.sequence,
864           "%supdated %s changes:%s parent:%s requested:%s requested:%s from parent %s",
865           args.forceUpdate == ForceUpdateFlags::ALL ? "Force " : "",
866           snapshot.getDebugString().c_str(), snapshot.changes.string().c_str(),
867           parentSnapshot.changes.string().c_str(), requested.changes.string().c_str(),
868           std::to_string(requested.what).c_str(), parentSnapshot.getDebugString().c_str());
869 }
870 
updateRoundedCorner(LayerSnapshot & snapshot,const RequestedLayerState & requested,const LayerSnapshot & parentSnapshot)871 void LayerSnapshotBuilder::updateRoundedCorner(LayerSnapshot& snapshot,
872                                                const RequestedLayerState& requested,
873                                                const LayerSnapshot& parentSnapshot) {
874     snapshot.roundedCorner = RoundedCornerState();
875     RoundedCornerState parentRoundedCorner;
876     if (parentSnapshot.roundedCorner.hasRoundedCorners()) {
877         parentRoundedCorner = parentSnapshot.roundedCorner;
878         ui::Transform t = snapshot.localTransform.inverse();
879         parentRoundedCorner.cropRect = t.transform(parentRoundedCorner.cropRect);
880         parentRoundedCorner.radius.x *= t.getScaleX();
881         parentRoundedCorner.radius.y *= t.getScaleY();
882     }
883 
884     FloatRect layerCropRect = snapshot.croppedBufferSize.toFloatRect();
885     const vec2 radius(requested.cornerRadius, requested.cornerRadius);
886     RoundedCornerState layerSettings(layerCropRect, radius);
887     const bool layerSettingsValid = layerSettings.hasRoundedCorners() && !layerCropRect.isEmpty();
888     const bool parentRoundedCornerValid = parentRoundedCorner.hasRoundedCorners();
889     if (layerSettingsValid && parentRoundedCornerValid) {
890         // If the parent and the layer have rounded corner settings, use the parent settings if
891         // the parent crop is entirely inside the layer crop. This has limitations and cause
892         // rendering artifacts. See b/200300845 for correct fix.
893         if (parentRoundedCorner.cropRect.left > layerCropRect.left &&
894             parentRoundedCorner.cropRect.top > layerCropRect.top &&
895             parentRoundedCorner.cropRect.right < layerCropRect.right &&
896             parentRoundedCorner.cropRect.bottom < layerCropRect.bottom) {
897             snapshot.roundedCorner = parentRoundedCorner;
898         } else {
899             snapshot.roundedCorner = layerSettings;
900         }
901     } else if (layerSettingsValid) {
902         snapshot.roundedCorner = layerSettings;
903     } else if (parentRoundedCornerValid) {
904         snapshot.roundedCorner = parentRoundedCorner;
905     }
906 }
907 
updateLayerBounds(LayerSnapshot & snapshot,const RequestedLayerState & requested,const LayerSnapshot & parentSnapshot,uint32_t primaryDisplayRotationFlags)908 void LayerSnapshotBuilder::updateLayerBounds(LayerSnapshot& snapshot,
909                                              const RequestedLayerState& requested,
910                                              const LayerSnapshot& parentSnapshot,
911                                              uint32_t primaryDisplayRotationFlags) {
912     snapshot.geomLayerTransform = parentSnapshot.geomLayerTransform * snapshot.localTransform;
913     const bool transformWasInvalid = snapshot.invalidTransform;
914     snapshot.invalidTransform = !LayerSnapshot::isTransformValid(snapshot.geomLayerTransform);
915     if (snapshot.invalidTransform) {
916         auto& t = snapshot.geomLayerTransform;
917         auto& requestedT = requested.requestedTransform;
918         std::string transformDebug =
919                 base::StringPrintf(" transform={%f,%f,%f,%f}  requestedTransform={%f,%f,%f,%f}",
920                                    t.dsdx(), t.dsdy(), t.dtdx(), t.dtdy(), requestedT.dsdx(),
921                                    requestedT.dsdy(), requestedT.dtdx(), requestedT.dtdy());
922         std::string bufferDebug;
923         if (requested.externalTexture) {
924             auto unRotBuffer = requested.getUnrotatedBufferSize(primaryDisplayRotationFlags);
925             auto& destFrame = requested.destinationFrame;
926             bufferDebug = base::StringPrintf(" buffer={%d,%d}  displayRot=%d"
927                                              " destFrame={%d,%d,%d,%d} unRotBuffer={%d,%d}",
928                                              requested.externalTexture->getWidth(),
929                                              requested.externalTexture->getHeight(),
930                                              primaryDisplayRotationFlags, destFrame.left,
931                                              destFrame.top, destFrame.right, destFrame.bottom,
932                                              unRotBuffer.getHeight(), unRotBuffer.getWidth());
933         }
934         ALOGW("Resetting transform for %s because it is invalid.%s%s",
935               snapshot.getDebugString().c_str(), transformDebug.c_str(), bufferDebug.c_str());
936         snapshot.geomLayerTransform.reset();
937     }
938     if (transformWasInvalid != snapshot.invalidTransform) {
939         // If transform is invalid, the layer will be hidden.
940         mResortSnapshots = true;
941     }
942     snapshot.geomInverseLayerTransform = snapshot.geomLayerTransform.inverse();
943 
944     FloatRect parentBounds = parentSnapshot.geomLayerBounds;
945     parentBounds = snapshot.localTransform.inverse().transform(parentBounds);
946     snapshot.geomLayerBounds =
947             (requested.externalTexture) ? snapshot.bufferSize.toFloatRect() : parentBounds;
948     if (!requested.crop.isEmpty()) {
949         snapshot.geomLayerBounds = snapshot.geomLayerBounds.intersect(requested.crop.toFloatRect());
950     }
951     snapshot.geomLayerBounds = snapshot.geomLayerBounds.intersect(parentBounds);
952     snapshot.transformedBounds = snapshot.geomLayerTransform.transform(snapshot.geomLayerBounds);
953     const Rect geomLayerBoundsWithoutTransparentRegion =
954             RequestedLayerState::reduce(Rect(snapshot.geomLayerBounds),
955                                         requested.transparentRegion);
956     snapshot.transformedBoundsWithoutTransparentRegion =
957             snapshot.geomLayerTransform.transform(geomLayerBoundsWithoutTransparentRegion);
958     snapshot.parentTransform = parentSnapshot.geomLayerTransform;
959 
960     // Subtract the transparent region and snap to the bounds
961     const Rect bounds =
962             RequestedLayerState::reduce(snapshot.croppedBufferSize, requested.transparentRegion);
963     if (requested.potentialCursor) {
964         snapshot.cursorFrame = snapshot.geomLayerTransform.transform(bounds);
965     }
966 }
967 
updateShadows(LayerSnapshot & snapshot,const RequestedLayerState &,const renderengine::ShadowSettings & globalShadowSettings)968 void LayerSnapshotBuilder::updateShadows(LayerSnapshot& snapshot, const RequestedLayerState&,
969                                          const renderengine::ShadowSettings& globalShadowSettings) {
970     if (snapshot.shadowRadius > 0.f) {
971         snapshot.shadowSettings = globalShadowSettings;
972 
973         // Note: this preserves existing behavior of shadowing the entire layer and not cropping
974         // it if transparent regions are present. This may not be necessary since shadows are
975         // typically cast by layers without transparent regions.
976         snapshot.shadowSettings.boundaries = snapshot.geomLayerBounds;
977 
978         // If the casting layer is translucent, we need to fill in the shadow underneath the
979         // layer. Otherwise the generated shadow will only be shown around the casting layer.
980         snapshot.shadowSettings.casterIsTranslucent =
981                 !snapshot.isContentOpaque() || (snapshot.alpha < 1.0f);
982         snapshot.shadowSettings.ambientColor *= snapshot.alpha;
983         snapshot.shadowSettings.spotColor *= snapshot.alpha;
984     }
985 }
986 
updateInput(LayerSnapshot & snapshot,const RequestedLayerState & requested,const LayerSnapshot & parentSnapshot,const LayerHierarchy::TraversalPath & path,const Args & args)987 void LayerSnapshotBuilder::updateInput(LayerSnapshot& snapshot,
988                                        const RequestedLayerState& requested,
989                                        const LayerSnapshot& parentSnapshot,
990                                        const LayerHierarchy::TraversalPath& path,
991                                        const Args& args) {
992     if (requested.windowInfoHandle) {
993         snapshot.inputInfo = *requested.windowInfoHandle->getInfo();
994     } else {
995         snapshot.inputInfo = {};
996         // b/271132344 revisit this and see if we can always use the layers uid/pid
997         snapshot.inputInfo.name = requested.name;
998         snapshot.inputInfo.ownerUid = gui::Uid{requested.ownerUid};
999         snapshot.inputInfo.ownerPid = gui::Pid{requested.ownerPid};
1000     }
1001     snapshot.touchCropId = requested.touchCropId;
1002 
1003     snapshot.inputInfo.id = static_cast<int32_t>(snapshot.uniqueSequence);
1004     snapshot.inputInfo.displayId = static_cast<int32_t>(snapshot.outputFilter.layerStack.id);
1005     updateVisibility(snapshot, snapshot.isVisible);
1006     if (!needsInputInfo(snapshot, requested)) {
1007         return;
1008     }
1009 
1010     static frontend::DisplayInfo sDefaultInfo = {.isSecure = false};
1011     const std::optional<frontend::DisplayInfo> displayInfoOpt =
1012             args.displays.get(snapshot.outputFilter.layerStack);
1013     bool noValidDisplay = !displayInfoOpt.has_value();
1014     auto displayInfo = displayInfoOpt.value_or(sDefaultInfo);
1015 
1016     if (!requested.windowInfoHandle) {
1017         snapshot.inputInfo.inputConfig = gui::WindowInfo::InputConfig::NO_INPUT_CHANNEL;
1018     }
1019     fillInputFrameInfo(snapshot.inputInfo, displayInfo.transform, snapshot);
1020 
1021     if (noValidDisplay) {
1022         // Do not let the window receive touches if it is not associated with a valid display
1023         // transform. We still allow the window to receive keys and prevent ANRs.
1024         snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::NOT_TOUCHABLE;
1025     }
1026 
1027     snapshot.inputInfo.alpha = snapshot.color.a;
1028     snapshot.inputInfo.touchOcclusionMode = requested.hasInputInfo()
1029             ? requested.windowInfoHandle->getInfo()->touchOcclusionMode
1030             : parentSnapshot.inputInfo.touchOcclusionMode;
1031     if (requested.dropInputMode == gui::DropInputMode::ALL ||
1032         parentSnapshot.dropInputMode == gui::DropInputMode::ALL) {
1033         snapshot.dropInputMode = gui::DropInputMode::ALL;
1034     } else if (requested.dropInputMode == gui::DropInputMode::OBSCURED ||
1035                parentSnapshot.dropInputMode == gui::DropInputMode::OBSCURED) {
1036         snapshot.dropInputMode = gui::DropInputMode::OBSCURED;
1037     } else {
1038         snapshot.dropInputMode = gui::DropInputMode::NONE;
1039     }
1040 
1041     handleDropInputMode(snapshot, parentSnapshot);
1042 
1043     // If the window will be blacked out on a display because the display does not have the secure
1044     // flag and the layer has the secure flag set, then drop input.
1045     if (!displayInfo.isSecure && snapshot.isSecure) {
1046         snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::DROP_INPUT;
1047     }
1048 
1049     if (requested.touchCropId != UNASSIGNED_LAYER_ID || path.isClone()) {
1050         mNeedsTouchableRegionCrop.insert(path);
1051     }
1052     auto cropLayerSnapshot = getSnapshot(requested.touchCropId);
1053     if (!cropLayerSnapshot && snapshot.inputInfo.replaceTouchableRegionWithCrop) {
1054         FloatRect inputBounds = getInputBounds(snapshot, /*fillParentBounds=*/true).first;
1055         Rect inputBoundsInDisplaySpace =
1056                 getInputBoundsInDisplaySpace(snapshot, inputBounds, displayInfo.transform);
1057         snapshot.inputInfo.touchableRegion = Region(inputBoundsInDisplaySpace);
1058     }
1059 
1060     // Inherit the trusted state from the parent hierarchy, but don't clobber the trusted state
1061     // if it was set by WM for a known system overlay
1062     if (snapshot.isTrustedOverlay) {
1063         snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::TRUSTED_OVERLAY;
1064     }
1065 
1066     // If the layer is a clone, we need to crop the input region to cloned root to prevent
1067     // touches from going outside the cloned area.
1068     if (path.isClone()) {
1069         snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::CLONE;
1070         // Cloned layers shouldn't handle watch outside since their z order is not determined by
1071         // WM or the client.
1072         snapshot.inputInfo.inputConfig.clear(gui::WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH);
1073     }
1074 }
1075 
getSnapshots()1076 std::vector<std::unique_ptr<LayerSnapshot>>& LayerSnapshotBuilder::getSnapshots() {
1077     return mSnapshots;
1078 }
1079 
forEachVisibleSnapshot(const ConstVisitor & visitor) const1080 void LayerSnapshotBuilder::forEachVisibleSnapshot(const ConstVisitor& visitor) const {
1081     for (int i = 0; i < mNumInterestingSnapshots; i++) {
1082         LayerSnapshot& snapshot = *mSnapshots[(size_t)i];
1083         if (!snapshot.isVisible) continue;
1084         visitor(snapshot);
1085     }
1086 }
1087 
1088 // Visit each visible snapshot in z-order
forEachVisibleSnapshot(const ConstVisitor & visitor,const LayerHierarchy & root) const1089 void LayerSnapshotBuilder::forEachVisibleSnapshot(const ConstVisitor& visitor,
1090                                                   const LayerHierarchy& root) const {
1091     root.traverseInZOrder(
1092             [this, visitor](const LayerHierarchy&,
1093                             const LayerHierarchy::TraversalPath& traversalPath) -> bool {
1094                 LayerSnapshot* snapshot = getSnapshot(traversalPath);
1095                 if (snapshot && snapshot->isVisible) {
1096                     visitor(*snapshot);
1097                 }
1098                 return true;
1099             });
1100 }
1101 
forEachVisibleSnapshot(const Visitor & visitor)1102 void LayerSnapshotBuilder::forEachVisibleSnapshot(const Visitor& visitor) {
1103     for (int i = 0; i < mNumInterestingSnapshots; i++) {
1104         std::unique_ptr<LayerSnapshot>& snapshot = mSnapshots.at((size_t)i);
1105         if (!snapshot->isVisible) continue;
1106         visitor(snapshot);
1107     }
1108 }
1109 
forEachInputSnapshot(const ConstVisitor & visitor) const1110 void LayerSnapshotBuilder::forEachInputSnapshot(const ConstVisitor& visitor) const {
1111     for (int i = mNumInterestingSnapshots - 1; i >= 0; i--) {
1112         LayerSnapshot& snapshot = *mSnapshots[(size_t)i];
1113         if (!snapshot.hasInputInfo()) continue;
1114         visitor(snapshot);
1115     }
1116 }
1117 
updateTouchableRegionCrop(const Args & args)1118 void LayerSnapshotBuilder::updateTouchableRegionCrop(const Args& args) {
1119     if (mNeedsTouchableRegionCrop.empty()) {
1120         return;
1121     }
1122 
1123     static constexpr ftl::Flags<RequestedLayerState::Changes> AFFECTS_INPUT =
1124             RequestedLayerState::Changes::Visibility | RequestedLayerState::Changes::Created |
1125             RequestedLayerState::Changes::Hierarchy | RequestedLayerState::Changes::Geometry |
1126             RequestedLayerState::Changes::Input;
1127 
1128     if (args.forceUpdate != ForceUpdateFlags::ALL &&
1129         !args.layerLifecycleManager.getGlobalChanges().any(AFFECTS_INPUT) && !args.displayChanges) {
1130         return;
1131     }
1132 
1133     for (auto& path : mNeedsTouchableRegionCrop) {
1134         frontend::LayerSnapshot* snapshot = getSnapshot(path);
1135         if (!snapshot) {
1136             continue;
1137         }
1138         LLOGV(snapshot->sequence, "updateTouchableRegionCrop=%s",
1139               snapshot->getDebugString().c_str());
1140         const std::optional<frontend::DisplayInfo> displayInfoOpt =
1141                 args.displays.get(snapshot->outputFilter.layerStack);
1142         static frontend::DisplayInfo sDefaultInfo = {.isSecure = false};
1143         auto displayInfo = displayInfoOpt.value_or(sDefaultInfo);
1144 
1145         bool needsUpdate =
1146                 args.forceUpdate == ForceUpdateFlags::ALL || snapshot->changes.any(AFFECTS_INPUT);
1147         auto cropLayerSnapshot = getSnapshot(snapshot->touchCropId);
1148         needsUpdate =
1149                 needsUpdate || (cropLayerSnapshot && cropLayerSnapshot->changes.any(AFFECTS_INPUT));
1150         auto clonedRootSnapshot = path.isClone() ? getSnapshot(snapshot->mirrorRootPath) : nullptr;
1151         needsUpdate = needsUpdate ||
1152                 (clonedRootSnapshot && clonedRootSnapshot->changes.any(AFFECTS_INPUT));
1153 
1154         if (!needsUpdate) {
1155             continue;
1156         }
1157 
1158         if (snapshot->inputInfo.replaceTouchableRegionWithCrop) {
1159             Rect inputBoundsInDisplaySpace;
1160             if (!cropLayerSnapshot) {
1161                 FloatRect inputBounds = getInputBounds(*snapshot, /*fillParentBounds=*/true).first;
1162                 inputBoundsInDisplaySpace =
1163                         getInputBoundsInDisplaySpace(*snapshot, inputBounds, displayInfo.transform);
1164             } else {
1165                 FloatRect inputBounds =
1166                         getInputBounds(*cropLayerSnapshot, /*fillParentBounds=*/true).first;
1167                 inputBoundsInDisplaySpace =
1168                         getInputBoundsInDisplaySpace(*cropLayerSnapshot, inputBounds,
1169                                                      displayInfo.transform);
1170             }
1171             snapshot->inputInfo.touchableRegion = Region(inputBoundsInDisplaySpace);
1172         } else if (cropLayerSnapshot) {
1173             FloatRect inputBounds =
1174                     getInputBounds(*cropLayerSnapshot, /*fillParentBounds=*/true).first;
1175             Rect inputBoundsInDisplaySpace =
1176                     getInputBoundsInDisplaySpace(*cropLayerSnapshot, inputBounds,
1177                                                  displayInfo.transform);
1178             snapshot->inputInfo.touchableRegion = snapshot->inputInfo.touchableRegion.intersect(
1179                     displayInfo.transform.transform(inputBoundsInDisplaySpace));
1180         }
1181 
1182         // If the layer is a clone, we need to crop the input region to cloned root to prevent
1183         // touches from going outside the cloned area.
1184         if (clonedRootSnapshot) {
1185             const Rect rect =
1186                     displayInfo.transform.transform(Rect{clonedRootSnapshot->transformedBounds});
1187             snapshot->inputInfo.touchableRegion =
1188                     snapshot->inputInfo.touchableRegion.intersect(rect);
1189         }
1190     }
1191 }
1192 
1193 } // namespace android::surfaceflinger::frontend
1194