blob: 7213ffadccdd7c0ada0396ae5edcd0fe5e073306 [file] [log] [blame]
Vishnu Nair8fc721b2022-12-22 20:06:32 +00001/*
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 "LayerSnapshotBuilder"
21
Vishnu Nair8fc721b2022-12-22 20:06:32 +000022#include <numeric>
Vishnu Nairb76d99a2023-03-19 18:22:31 -070023#include <optional>
24
Dominik Laskowski6b049ff2023-01-29 15:46:45 -050025#include <ftl/small_map.h>
Vishnu Nairb76d99a2023-03-19 18:22:31 -070026#include <gui/TraceUtils.h>
Dominik Laskowski6b049ff2023-01-29 15:46:45 -050027#include <ui/FloatRect.h>
28
Vishnu Nair8fc721b2022-12-22 20:06:32 +000029#include "DisplayHardware/HWC2.h"
30#include "DisplayHardware/Hal.h"
Vishnu Naircfb2d252023-01-19 04:44:02 +000031#include "LayerLog.h"
Vishnu Nairb76d99a2023-03-19 18:22:31 -070032#include "LayerSnapshotBuilder.h"
Vishnu Naircfb2d252023-01-19 04:44:02 +000033#include "TimeStats/TimeStats.h"
Vishnu Naird1f74982023-06-15 20:16:51 -070034#include "Tracing/TransactionTracing.h"
Vishnu Nair8fc721b2022-12-22 20:06:32 +000035
36namespace android::surfaceflinger::frontend {
37
38using namespace ftl::flag_operators;
39
40namespace {
Dominik Laskowski6b049ff2023-01-29 15:46:45 -050041
42FloatRect getMaxDisplayBounds(const DisplayInfos& displays) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +000043 const ui::Size maxSize = [&displays] {
44 if (displays.empty()) return ui::Size{5000, 5000};
45
46 return std::accumulate(displays.begin(), displays.end(), ui::kEmptySize,
47 [](ui::Size size, const auto& pair) -> ui::Size {
48 const auto& display = pair.second;
49 return {std::max(size.getWidth(), display.info.logicalWidth),
50 std::max(size.getHeight(), display.info.logicalHeight)};
51 });
52 }();
53
54 // Ignore display bounds for now since they will be computed later. Use a large Rect bound
55 // to ensure it's bigger than an actual display will be.
56 const float xMax = static_cast<float>(maxSize.getWidth()) * 10.f;
57 const float yMax = static_cast<float>(maxSize.getHeight()) * 10.f;
58
59 return {-xMax, -yMax, xMax, yMax};
60}
61
62// Applies the given transform to the region, while protecting against overflows caused by any
63// offsets. If applying the offset in the transform to any of the Rects in the region would result
64// in an overflow, they are not added to the output Region.
65Region transformTouchableRegionSafely(const ui::Transform& t, const Region& r,
66 const std::string& debugWindowName) {
67 // Round the translation using the same rounding strategy used by ui::Transform.
68 const auto tx = static_cast<int32_t>(t.tx() + 0.5);
69 const auto ty = static_cast<int32_t>(t.ty() + 0.5);
70
71 ui::Transform transformWithoutOffset = t;
72 transformWithoutOffset.set(0.f, 0.f);
73
74 const Region transformed = transformWithoutOffset.transform(r);
75
76 // Apply the translation to each of the Rects in the region while discarding any that overflow.
77 Region ret;
78 for (const auto& rect : transformed) {
79 Rect newRect;
80 if (__builtin_add_overflow(rect.left, tx, &newRect.left) ||
81 __builtin_add_overflow(rect.top, ty, &newRect.top) ||
82 __builtin_add_overflow(rect.right, tx, &newRect.right) ||
83 __builtin_add_overflow(rect.bottom, ty, &newRect.bottom)) {
84 ALOGE("Applying transform to touchable region of window '%s' resulted in an overflow.",
85 debugWindowName.c_str());
86 continue;
87 }
88 ret.orSelf(newRect);
89 }
90 return ret;
91}
92
93/*
94 * We don't want to send the layer's transform to input, but rather the
95 * parent's transform. This is because Layer's transform is
96 * information about how the buffer is placed on screen. The parent's
97 * transform makes more sense to send since it's information about how the
98 * layer is placed on screen. This transform is used by input to determine
99 * how to go from screen space back to window space.
100 */
101ui::Transform getInputTransform(const LayerSnapshot& snapshot) {
102 if (!snapshot.hasBufferOrSidebandStream()) {
103 return snapshot.geomLayerTransform;
104 }
105 return snapshot.parentTransform;
106}
107
108/**
Vishnu Nairfed7c122023-03-18 01:54:43 +0000109 * Returns the bounds used to fill the input frame and the touchable region.
110 *
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000111 * Similar to getInputTransform, we need to update the bounds to include the transform.
112 * This is because bounds don't include the buffer transform, where the input assumes
113 * that's already included.
114 */
Vishnu Nairfed7c122023-03-18 01:54:43 +0000115std::pair<FloatRect, bool> getInputBounds(const LayerSnapshot& snapshot, bool fillParentBounds) {
116 FloatRect inputBounds = snapshot.croppedBufferSize.toFloatRect();
117 if (snapshot.hasBufferOrSidebandStream() && snapshot.croppedBufferSize.isValid() &&
118 snapshot.localTransform.getType() != ui::Transform::IDENTITY) {
119 inputBounds = snapshot.localTransform.transform(inputBounds);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000120 }
121
Vishnu Nairfed7c122023-03-18 01:54:43 +0000122 bool inputBoundsValid = snapshot.croppedBufferSize.isValid();
123 if (!inputBoundsValid) {
124 /**
125 * Input bounds are based on the layer crop or buffer size. But if we are using
126 * the layer bounds as the input bounds (replaceTouchableRegionWithCrop flag) then
127 * we can use the parent bounds as the input bounds if the layer does not have buffer
128 * or a crop. We want to unify this logic but because of compat reasons we cannot always
129 * use the parent bounds. A layer without a buffer can get input. So when a window is
130 * initially added, its touchable region can fill its parent layer bounds and that can
131 * have negative consequences.
132 */
133 inputBounds = fillParentBounds ? snapshot.geomLayerBounds : FloatRect{};
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000134 }
Vishnu Nairfed7c122023-03-18 01:54:43 +0000135
136 // Clamp surface inset to the input bounds.
137 const float inset = static_cast<float>(snapshot.inputInfo.surfaceInset);
138 const float xSurfaceInset = std::clamp(inset, 0.f, inputBounds.getWidth() / 2.f);
139 const float ySurfaceInset = std::clamp(inset, 0.f, inputBounds.getHeight() / 2.f);
140
141 // Apply the insets to the input bounds.
142 inputBounds.left += xSurfaceInset;
143 inputBounds.top += ySurfaceInset;
144 inputBounds.right -= xSurfaceInset;
145 inputBounds.bottom -= ySurfaceInset;
146 return {inputBounds, inputBoundsValid};
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000147}
148
Vishnu Nairfed7c122023-03-18 01:54:43 +0000149Rect getInputBoundsInDisplaySpace(const LayerSnapshot& snapshot, const FloatRect& insetBounds,
150 const ui::Transform& screenToDisplay) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000151 // InputDispatcher works in the display device's coordinate space. Here, we calculate the
152 // frame and transform used for the layer, which determines the bounds and the coordinate space
153 // within which the layer will receive input.
Vishnu Nairfed7c122023-03-18 01:54:43 +0000154
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000155 // Coordinate space definitions:
156 // - display: The display device's coordinate space. Correlates to pixels on the display.
157 // - screen: The post-rotation coordinate space for the display, a.k.a. logical display space.
158 // - layer: The coordinate space of this layer.
159 // - input: The coordinate space in which this layer will receive input events. This could be
160 // different than layer space if a surfaceInset is used, which changes the origin
161 // of the input space.
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000162
163 // Crop the input bounds to ensure it is within the parent's bounds.
Vishnu Nairfed7c122023-03-18 01:54:43 +0000164 const FloatRect croppedInsetBoundsInLayer = snapshot.geomLayerBounds.intersect(insetBounds);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000165
166 const ui::Transform layerToScreen = getInputTransform(snapshot);
167 const ui::Transform layerToDisplay = screenToDisplay * layerToScreen;
168
Vishnu Nairfed7c122023-03-18 01:54:43 +0000169 return Rect{layerToDisplay.transform(croppedInsetBoundsInLayer)};
170}
171
172void fillInputFrameInfo(gui::WindowInfo& info, const ui::Transform& screenToDisplay,
173 const LayerSnapshot& snapshot) {
174 auto [inputBounds, inputBoundsValid] = getInputBounds(snapshot, /*fillParentBounds=*/false);
175 if (!inputBoundsValid) {
176 info.touchableRegion.clear();
177 }
178
179 const Rect roundedFrameInDisplay =
180 getInputBoundsInDisplaySpace(snapshot, inputBounds, screenToDisplay);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000181 info.frameLeft = roundedFrameInDisplay.left;
182 info.frameTop = roundedFrameInDisplay.top;
183 info.frameRight = roundedFrameInDisplay.right;
184 info.frameBottom = roundedFrameInDisplay.bottom;
185
186 ui::Transform inputToLayer;
Vishnu Nairfed7c122023-03-18 01:54:43 +0000187 inputToLayer.set(inputBounds.left, inputBounds.top);
188 const ui::Transform layerToScreen = getInputTransform(snapshot);
189 const ui::Transform inputToDisplay = screenToDisplay * layerToScreen * inputToLayer;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000190
191 // InputDispatcher expects a display-to-input transform.
192 info.transform = inputToDisplay.inverse();
193
194 // The touchable region is specified in the input coordinate space. Change it to display space.
195 info.touchableRegion =
196 transformTouchableRegionSafely(inputToDisplay, info.touchableRegion, snapshot.name);
197}
198
199void handleDropInputMode(LayerSnapshot& snapshot, const LayerSnapshot& parentSnapshot) {
200 if (snapshot.inputInfo.inputConfig.test(gui::WindowInfo::InputConfig::NO_INPUT_CHANNEL)) {
201 return;
202 }
203
204 // Check if we need to drop input unconditionally
205 const gui::DropInputMode dropInputMode = snapshot.dropInputMode;
206 if (dropInputMode == gui::DropInputMode::ALL) {
207 snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::DROP_INPUT;
208 ALOGV("Dropping input for %s as requested by policy.", snapshot.name.c_str());
209 return;
210 }
211
212 // Check if we need to check if the window is obscured by parent
213 if (dropInputMode != gui::DropInputMode::OBSCURED) {
214 return;
215 }
216
217 // Check if the parent has set an alpha on the layer
218 if (parentSnapshot.color.a != 1.0_hf) {
219 snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::DROP_INPUT;
220 ALOGV("Dropping input for %s as requested by policy because alpha=%f",
221 snapshot.name.c_str(), static_cast<float>(parentSnapshot.color.a));
222 }
223
224 // Check if the parent has cropped the buffer
225 Rect bufferSize = snapshot.croppedBufferSize;
226 if (!bufferSize.isValid()) {
227 snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED;
228 return;
229 }
230
231 // Screenbounds are the layer bounds cropped by parents, transformed to screenspace.
232 // To check if the layer has been cropped, we take the buffer bounds, apply the local
233 // layer crop and apply the same set of transforms to move to screenspace. If the bounds
234 // match then the layer has not been cropped by its parents.
235 Rect bufferInScreenSpace(snapshot.geomLayerTransform.transform(bufferSize));
236 bool croppedByParent = bufferInScreenSpace != Rect{snapshot.transformedBounds};
237
238 if (croppedByParent) {
239 snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::DROP_INPUT;
240 ALOGV("Dropping input for %s as requested by policy because buffer is cropped by parent",
241 snapshot.name.c_str());
242 } else {
243 // If the layer is not obscured by its parents (by setting an alpha or crop), then only drop
244 // input if the window is obscured. This check should be done in surfaceflinger but the
245 // logic currently resides in inputflinger. So pass the if_obscured check to input to only
246 // drop input events if the window is obscured.
247 snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED;
248 }
249}
250
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000251auto getBlendMode(const LayerSnapshot& snapshot, const RequestedLayerState& requested) {
252 auto blendMode = Hwc2::IComposerClient::BlendMode::NONE;
253 if (snapshot.alpha != 1.0f || !snapshot.isContentOpaque()) {
254 blendMode = requested.premultipliedAlpha ? Hwc2::IComposerClient::BlendMode::PREMULTIPLIED
255 : Hwc2::IComposerClient::BlendMode::COVERAGE;
256 }
257 return blendMode;
258}
259
Vishnu Naircfb2d252023-01-19 04:44:02 +0000260void updateSurfaceDamage(const RequestedLayerState& requested, bool hasReadyFrame,
261 bool forceFullDamage, Region& outSurfaceDamageRegion) {
262 if (!hasReadyFrame) {
263 outSurfaceDamageRegion.clear();
264 return;
265 }
266 if (forceFullDamage) {
267 outSurfaceDamageRegion = Region::INVALID_REGION;
268 } else {
269 outSurfaceDamageRegion = requested.surfaceDamageRegion;
270 }
271}
272
Vishnu Nair80a5a702023-02-11 01:21:51 +0000273void updateVisibility(LayerSnapshot& snapshot, bool visible) {
274 snapshot.isVisible = visible;
Vishnu Naircfb2d252023-01-19 04:44:02 +0000275
276 // TODO(b/238781169) we are ignoring this compat for now, since we will have
277 // to remove any optimization based on visibility.
278
279 // For compatibility reasons we let layers which can receive input
280 // receive input before they have actually submitted a buffer. Because
281 // of this we use canReceiveInput instead of isVisible to check the
282 // policy-visibility, ignoring the buffer state. However for layers with
283 // hasInputInfo()==false we can use the real visibility state.
284 // We are just using these layers for occlusion detection in
285 // InputDispatcher, and obviously if they aren't visible they can't occlude
286 // anything.
Vishnu Nair80a5a702023-02-11 01:21:51 +0000287 const bool visibleForInput =
Vishnu Nair40d02282023-02-28 21:11:40 +0000288 snapshot.hasInputInfo() ? snapshot.canReceiveInput() : snapshot.isVisible;
Vishnu Nair80a5a702023-02-11 01:21:51 +0000289 snapshot.inputInfo.setInputConfig(gui::WindowInfo::InputConfig::NOT_VISIBLE, !visibleForInput);
Vishnu Naircfb2d252023-01-19 04:44:02 +0000290}
291
292bool needsInputInfo(const LayerSnapshot& snapshot, const RequestedLayerState& requested) {
293 if (requested.potentialCursor) {
294 return false;
295 }
296
297 if (snapshot.inputInfo.token != nullptr) {
298 return true;
299 }
300
301 if (snapshot.hasBufferOrSidebandStream()) {
302 return true;
303 }
304
305 return requested.windowInfoHandle &&
306 requested.windowInfoHandle->getInfo()->inputConfig.test(
307 gui::WindowInfo::InputConfig::NO_INPUT_CHANNEL);
308}
309
Vishnu Nairc765c6c2023-02-23 00:08:01 +0000310void updateMetadata(LayerSnapshot& snapshot, const RequestedLayerState& requested,
311 const LayerSnapshotBuilder::Args& args) {
312 snapshot.metadata.clear();
313 for (const auto& [key, mandatory] : args.supportedLayerGenericMetadata) {
314 auto compatIter = args.genericLayerMetadataKeyMap.find(key);
315 if (compatIter == std::end(args.genericLayerMetadataKeyMap)) {
316 continue;
317 }
318 const uint32_t id = compatIter->second;
319 auto it = requested.metadata.mMap.find(id);
320 if (it == std::end(requested.metadata.mMap)) {
321 continue;
322 }
323
324 snapshot.metadata.emplace(key,
325 compositionengine::GenericLayerMetadataEntry{mandatory,
326 it->second});
327 }
328}
329
Vishnu Naircfb2d252023-01-19 04:44:02 +0000330void clearChanges(LayerSnapshot& snapshot) {
331 snapshot.changes.clear();
332 snapshot.contentDirty = false;
333 snapshot.hasReadyFrame = false;
334 snapshot.sidebandStreamHasFrame = false;
335 snapshot.surfaceDamage.clear();
336}
337
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000338} // namespace
339
340LayerSnapshot LayerSnapshotBuilder::getRootSnapshot() {
341 LayerSnapshot snapshot;
Vishnu Nair92990e22023-02-24 20:01:05 +0000342 snapshot.path = LayerHierarchy::TraversalPath::ROOT;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000343 snapshot.changes = ftl::Flags<RequestedLayerState::Changes>();
344 snapshot.isHiddenByPolicyFromParent = false;
345 snapshot.isHiddenByPolicyFromRelativeParent = false;
346 snapshot.parentTransform.reset();
347 snapshot.geomLayerTransform.reset();
348 snapshot.geomInverseLayerTransform.reset();
349 snapshot.geomLayerBounds = getMaxDisplayBounds({});
350 snapshot.roundedCorner = RoundedCornerState();
351 snapshot.stretchEffect = {};
352 snapshot.outputFilter.layerStack = ui::DEFAULT_LAYER_STACK;
353 snapshot.outputFilter.toInternalDisplay = false;
354 snapshot.isSecure = false;
355 snapshot.color.a = 1.0_hf;
356 snapshot.colorTransformIsIdentity = true;
357 snapshot.shadowRadius = 0.f;
358 snapshot.layerMetadata.mMap.clear();
359 snapshot.relativeLayerMetadata.mMap.clear();
360 snapshot.inputInfo.touchOcclusionMode = gui::TouchOcclusionMode::BLOCK_UNTRUSTED;
361 snapshot.dropInputMode = gui::DropInputMode::NONE;
362 snapshot.isTrustedOverlay = false;
Vishnu Naircfb2d252023-01-19 04:44:02 +0000363 snapshot.gameMode = gui::GameMode::Unsupported;
364 snapshot.frameRate = {};
365 snapshot.fixedTransformHint = ui::Transform::ROT_INVALID;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000366 return snapshot;
367}
368
369LayerSnapshotBuilder::LayerSnapshotBuilder() : mRootSnapshot(getRootSnapshot()) {}
370
371LayerSnapshotBuilder::LayerSnapshotBuilder(Args args) : LayerSnapshotBuilder() {
Vishnu Naird47bcee2023-02-24 18:08:51 +0000372 args.forceUpdate = ForceUpdateFlags::ALL;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000373 updateSnapshots(args);
374}
375
376bool LayerSnapshotBuilder::tryFastUpdate(const Args& args) {
Vishnu Naird47bcee2023-02-24 18:08:51 +0000377 if (args.forceUpdate != ForceUpdateFlags::NONE || args.displayChanges) {
Vishnu Naircfb2d252023-01-19 04:44:02 +0000378 // force update requested, or we have display changes, so skip the fast path
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000379 return false;
380 }
381
382 if (args.layerLifecycleManager.getGlobalChanges().get() == 0) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000383 return true;
384 }
385
386 if (args.layerLifecycleManager.getGlobalChanges() != RequestedLayerState::Changes::Content) {
387 // We have changes that require us to walk the hierarchy and update child layers.
388 // No fast path for you.
389 return false;
390 }
391
392 // There are only content changes which do not require any child layer snapshots to be updated.
393 ALOGV("%s", __func__);
394 ATRACE_NAME("FastPath");
395
396 // Collect layers with changes
397 ftl::SmallMap<uint32_t, RequestedLayerState*, 10> layersWithChanges;
398 for (auto& layer : args.layerLifecycleManager.getLayers()) {
399 if (layer->changes.test(RequestedLayerState::Changes::Content)) {
400 layersWithChanges.emplace_or_replace(layer->id, layer.get());
401 }
402 }
403
404 // Walk through the snapshots, clearing previous change flags and updating the snapshots
405 // if needed.
406 for (auto& snapshot : mSnapshots) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000407 auto it = layersWithChanges.find(snapshot->path.id);
408 if (it != layersWithChanges.end()) {
409 ALOGV("%s fast path snapshot changes = %s", __func__,
410 mRootSnapshot.changes.string().c_str());
411 LayerHierarchy::TraversalPath root = LayerHierarchy::TraversalPath::ROOT;
Vishnu Nair92990e22023-02-24 20:01:05 +0000412 updateSnapshot(*snapshot, args, *it->second, mRootSnapshot, root);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000413 }
414 }
415 return true;
416}
417
418void LayerSnapshotBuilder::updateSnapshots(const Args& args) {
419 ATRACE_NAME("UpdateSnapshots");
Vishnu Nair3af0ec02023-02-10 04:13:48 +0000420 if (args.parentCrop) {
421 mRootSnapshot.geomLayerBounds = *args.parentCrop;
Vishnu Naird47bcee2023-02-24 18:08:51 +0000422 } else if (args.forceUpdate == ForceUpdateFlags::ALL || args.displayChanges) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000423 mRootSnapshot.geomLayerBounds = getMaxDisplayBounds(args.displays);
424 }
425 if (args.displayChanges) {
426 mRootSnapshot.changes = RequestedLayerState::Changes::AffectsChildren |
427 RequestedLayerState::Changes::Geometry;
428 }
Vishnu Naird47bcee2023-02-24 18:08:51 +0000429 if (args.forceUpdate == ForceUpdateFlags::HIERARCHY) {
430 mRootSnapshot.changes |=
431 RequestedLayerState::Changes::Hierarchy | RequestedLayerState::Changes::Visibility;
432 }
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000433 LayerHierarchy::TraversalPath root = LayerHierarchy::TraversalPath::ROOT;
Vishnu Naird47bcee2023-02-24 18:08:51 +0000434 if (args.root.getLayer()) {
435 // The hierarchy can have a root layer when used for screenshots otherwise, it will have
436 // multiple children.
437 LayerHierarchy::ScopedAddToTraversalPath addChildToPath(root, args.root.getLayer()->id,
438 LayerHierarchy::Variant::Attached);
Vishnu Naird1f74982023-06-15 20:16:51 -0700439 updateSnapshotsInHierarchy(args, args.root, root, mRootSnapshot, /*depth=*/0);
Vishnu Naird47bcee2023-02-24 18:08:51 +0000440 } else {
441 for (auto& [childHierarchy, variant] : args.root.mChildren) {
442 LayerHierarchy::ScopedAddToTraversalPath addChildToPath(root,
443 childHierarchy->getLayer()->id,
444 variant);
Vishnu Naird1f74982023-06-15 20:16:51 -0700445 updateSnapshotsInHierarchy(args, *childHierarchy, root, mRootSnapshot, /*depth=*/0);
Vishnu Naird47bcee2023-02-24 18:08:51 +0000446 }
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000447 }
448
Vishnu Nair29354ec2023-03-28 18:51:28 -0700449 // Update touchable region crops outside the main update pass. This is because a layer could be
450 // cropped by any other layer and it requires both snapshots to be updated.
451 updateTouchableRegionCrop(args);
452
Vishnu Nairfccd6362023-02-24 23:39:53 +0000453 const bool hasUnreachableSnapshots = sortSnapshotsByZ(args);
Vishnu Naircfb2d252023-01-19 04:44:02 +0000454 clearChanges(mRootSnapshot);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000455
Vishnu Nair29354ec2023-03-28 18:51:28 -0700456 // Destroy unreachable snapshots for clone layers. And destroy snapshots for non-clone
457 // layers if the layer have been destroyed.
458 // TODO(b/238781169) consider making clone layer ids stable as well
459 if (!hasUnreachableSnapshots && args.layerLifecycleManager.getDestroyedLayers().empty()) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000460 return;
461 }
462
Vishnu Nair29354ec2023-03-28 18:51:28 -0700463 std::unordered_set<uint32_t> destroyedLayerIds;
464 for (auto& destroyedLayer : args.layerLifecycleManager.getDestroyedLayers()) {
465 destroyedLayerIds.insert(destroyedLayer->id);
466 }
467
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000468 auto it = mSnapshots.begin();
469 while (it < mSnapshots.end()) {
470 auto& traversalPath = it->get()->path;
Vishnu Nair29354ec2023-03-28 18:51:28 -0700471 if (!it->get()->unreachable &&
472 destroyedLayerIds.find(traversalPath.id) == destroyedLayerIds.end()) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000473 it++;
474 continue;
475 }
476
477 mIdToSnapshot.erase(traversalPath);
Vishnu Nair29354ec2023-03-28 18:51:28 -0700478 mNeedsTouchableRegionCrop.erase(traversalPath);
Vishnu Naircfb2d252023-01-19 04:44:02 +0000479 mSnapshots.back()->globalZ = it->get()->globalZ;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000480 std::iter_swap(it, mSnapshots.end() - 1);
481 mSnapshots.erase(mSnapshots.end() - 1);
482 }
483}
484
485void LayerSnapshotBuilder::update(const Args& args) {
Vishnu Nair92990e22023-02-24 20:01:05 +0000486 for (auto& snapshot : mSnapshots) {
487 clearChanges(*snapshot);
488 }
489
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000490 if (tryFastUpdate(args)) {
491 return;
492 }
493 updateSnapshots(args);
494}
495
Vishnu Naircfb2d252023-01-19 04:44:02 +0000496const LayerSnapshot& LayerSnapshotBuilder::updateSnapshotsInHierarchy(
497 const Args& args, const LayerHierarchy& hierarchy,
Vishnu Naird1f74982023-06-15 20:16:51 -0700498 LayerHierarchy::TraversalPath& traversalPath, const LayerSnapshot& parentSnapshot,
499 int depth) {
500 if (depth > 50) {
501 TransactionTraceWriter::getInstance().invoke("layer_builder_stack_overflow_",
502 /*overwrite=*/false);
503 LOG_ALWAYS_FATAL("Cycle detected in LayerSnapshotBuilder. See "
504 "builder_stack_overflow_transactions.winscope");
505 }
506
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000507 const RequestedLayerState* layer = hierarchy.getLayer();
Vishnu Naircfb2d252023-01-19 04:44:02 +0000508 LayerSnapshot* snapshot = getSnapshot(traversalPath);
509 const bool newSnapshot = snapshot == nullptr;
510 if (newSnapshot) {
Vishnu Nair92990e22023-02-24 20:01:05 +0000511 snapshot = createSnapshot(traversalPath, *layer, parentSnapshot);
Vishnu Naircfb2d252023-01-19 04:44:02 +0000512 }
Vishnu Naird47bcee2023-02-24 18:08:51 +0000513 scheduler::LayerInfo::FrameRate oldFrameRate = snapshot->frameRate;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000514 if (traversalPath.isRelative()) {
515 bool parentIsRelative = traversalPath.variant == LayerHierarchy::Variant::Relative;
516 updateRelativeState(*snapshot, parentSnapshot, parentIsRelative, args);
517 } else {
518 if (traversalPath.isAttached()) {
519 resetRelativeState(*snapshot);
520 }
Vishnu Nair92990e22023-02-24 20:01:05 +0000521 updateSnapshot(*snapshot, args, *layer, parentSnapshot, traversalPath);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000522 }
523
524 for (auto& [childHierarchy, variant] : hierarchy.mChildren) {
525 LayerHierarchy::ScopedAddToTraversalPath addChildToPath(traversalPath,
526 childHierarchy->getLayer()->id,
527 variant);
Vishnu Naircfb2d252023-01-19 04:44:02 +0000528 const LayerSnapshot& childSnapshot =
Vishnu Naird1f74982023-06-15 20:16:51 -0700529 updateSnapshotsInHierarchy(args, *childHierarchy, traversalPath, *snapshot,
530 depth + 1);
Vishnu Naircfb2d252023-01-19 04:44:02 +0000531 updateChildState(*snapshot, childSnapshot, args);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000532 }
Vishnu Naird47bcee2023-02-24 18:08:51 +0000533
534 if (oldFrameRate == snapshot->frameRate) {
535 snapshot->changes.clear(RequestedLayerState::Changes::FrameRate);
536 }
Vishnu Naircfb2d252023-01-19 04:44:02 +0000537 return *snapshot;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000538}
539
540LayerSnapshot* LayerSnapshotBuilder::getSnapshot(uint32_t layerId) const {
541 if (layerId == UNASSIGNED_LAYER_ID) {
542 return nullptr;
543 }
544 LayerHierarchy::TraversalPath path{.id = layerId};
545 return getSnapshot(path);
546}
547
548LayerSnapshot* LayerSnapshotBuilder::getSnapshot(const LayerHierarchy::TraversalPath& id) const {
549 auto it = mIdToSnapshot.find(id);
550 return it == mIdToSnapshot.end() ? nullptr : it->second;
551}
552
Vishnu Nair92990e22023-02-24 20:01:05 +0000553LayerSnapshot* LayerSnapshotBuilder::createSnapshot(const LayerHierarchy::TraversalPath& path,
554 const RequestedLayerState& layer,
555 const LayerSnapshot& parentSnapshot) {
556 mSnapshots.emplace_back(std::make_unique<LayerSnapshot>(layer, path));
Vishnu Naircfb2d252023-01-19 04:44:02 +0000557 LayerSnapshot* snapshot = mSnapshots.back().get();
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000558 snapshot->globalZ = static_cast<size_t>(mSnapshots.size()) - 1;
Vishnu Nair92990e22023-02-24 20:01:05 +0000559 if (path.isClone() && path.variant != LayerHierarchy::Variant::Mirror) {
560 snapshot->mirrorRootPath = parentSnapshot.mirrorRootPath;
561 }
562 mIdToSnapshot[path] = snapshot;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000563 return snapshot;
564}
565
Vishnu Nairfccd6362023-02-24 23:39:53 +0000566bool LayerSnapshotBuilder::sortSnapshotsByZ(const Args& args) {
Vishnu Naird47bcee2023-02-24 18:08:51 +0000567 if (!mResortSnapshots && args.forceUpdate == ForceUpdateFlags::NONE &&
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000568 !args.layerLifecycleManager.getGlobalChanges().any(
569 RequestedLayerState::Changes::Hierarchy |
570 RequestedLayerState::Changes::Visibility)) {
571 // We are not force updating and there are no hierarchy or visibility changes. Avoid sorting
572 // the snapshots.
Vishnu Nairfccd6362023-02-24 23:39:53 +0000573 return false;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000574 }
Vishnu Naircfb2d252023-01-19 04:44:02 +0000575 mResortSnapshots = false;
576
Vishnu Nairfccd6362023-02-24 23:39:53 +0000577 for (auto& snapshot : mSnapshots) {
Vishnu Nair29354ec2023-03-28 18:51:28 -0700578 snapshot->unreachable = snapshot->path.isClone();
Vishnu Nairfccd6362023-02-24 23:39:53 +0000579 }
580
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000581 size_t globalZ = 0;
582 args.root.traverseInZOrder(
583 [this, &globalZ](const LayerHierarchy&,
584 const LayerHierarchy::TraversalPath& traversalPath) -> bool {
585 LayerSnapshot* snapshot = getSnapshot(traversalPath);
586 if (!snapshot) {
587 return false;
588 }
589
Vishnu Nairfccd6362023-02-24 23:39:53 +0000590 snapshot->unreachable = false;
Vishnu Naircfb2d252023-01-19 04:44:02 +0000591 if (snapshot->getIsVisible() || snapshot->hasInputInfo()) {
Vishnu Nair80a5a702023-02-11 01:21:51 +0000592 updateVisibility(*snapshot, snapshot->getIsVisible());
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000593 size_t oldZ = snapshot->globalZ;
594 size_t newZ = globalZ++;
595 snapshot->globalZ = newZ;
596 if (oldZ == newZ) {
597 return true;
598 }
599 mSnapshots[newZ]->globalZ = oldZ;
Vishnu Naircfb2d252023-01-19 04:44:02 +0000600 LLOGV(snapshot->sequence, "Made visible z=%zu -> %zu %s", oldZ, newZ,
601 snapshot->getDebugString().c_str());
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000602 std::iter_swap(mSnapshots.begin() + static_cast<ssize_t>(oldZ),
603 mSnapshots.begin() + static_cast<ssize_t>(newZ));
604 }
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000605 return true;
606 });
Vishnu Naircfb2d252023-01-19 04:44:02 +0000607 mNumInterestingSnapshots = (int)globalZ;
Vishnu Nairfccd6362023-02-24 23:39:53 +0000608 bool hasUnreachableSnapshots = false;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000609 while (globalZ < mSnapshots.size()) {
610 mSnapshots[globalZ]->globalZ = globalZ;
Vishnu Nair80a5a702023-02-11 01:21:51 +0000611 /* mark unreachable snapshots as explicitly invisible */
612 updateVisibility(*mSnapshots[globalZ], false);
Vishnu Nairfccd6362023-02-24 23:39:53 +0000613 if (mSnapshots[globalZ]->unreachable) {
614 hasUnreachableSnapshots = true;
615 }
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000616 globalZ++;
617 }
Vishnu Nairfccd6362023-02-24 23:39:53 +0000618 return hasUnreachableSnapshots;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000619}
620
621void LayerSnapshotBuilder::updateRelativeState(LayerSnapshot& snapshot,
622 const LayerSnapshot& parentSnapshot,
623 bool parentIsRelative, const Args& args) {
624 if (parentIsRelative) {
Vishnu Naircfb2d252023-01-19 04:44:02 +0000625 snapshot.isHiddenByPolicyFromRelativeParent =
626 parentSnapshot.isHiddenByPolicyFromParent || parentSnapshot.invalidTransform;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000627 if (args.includeMetadata) {
628 snapshot.relativeLayerMetadata = parentSnapshot.layerMetadata;
629 }
630 } else {
631 snapshot.isHiddenByPolicyFromRelativeParent =
632 parentSnapshot.isHiddenByPolicyFromRelativeParent;
633 if (args.includeMetadata) {
634 snapshot.relativeLayerMetadata = parentSnapshot.relativeLayerMetadata;
635 }
636 }
637 snapshot.isVisible = snapshot.getIsVisible();
638}
639
Vishnu Naircfb2d252023-01-19 04:44:02 +0000640void LayerSnapshotBuilder::updateChildState(LayerSnapshot& snapshot,
641 const LayerSnapshot& childSnapshot, const Args& args) {
642 if (snapshot.childState.hasValidFrameRate) {
643 return;
644 }
Vishnu Naird47bcee2023-02-24 18:08:51 +0000645 if (args.forceUpdate == ForceUpdateFlags::ALL ||
646 childSnapshot.changes.test(RequestedLayerState::Changes::FrameRate)) {
Vishnu Naircfb2d252023-01-19 04:44:02 +0000647 // We return whether this layer ot its children has a vote. We ignore ExactOrMultiple votes
648 // for the same reason we are allowing touch boost for those layers. See
649 // RefreshRateSelector::rankFrameRates for details.
650 using FrameRateCompatibility = scheduler::LayerInfo::FrameRateCompatibility;
651 const auto layerVotedWithDefaultCompatibility = childSnapshot.frameRate.rate.isValid() &&
652 childSnapshot.frameRate.type == FrameRateCompatibility::Default;
653 const auto layerVotedWithNoVote =
654 childSnapshot.frameRate.type == FrameRateCompatibility::NoVote;
655 const auto layerVotedWithExactCompatibility = childSnapshot.frameRate.rate.isValid() &&
656 childSnapshot.frameRate.type == FrameRateCompatibility::Exact;
657
658 snapshot.childState.hasValidFrameRate |= layerVotedWithDefaultCompatibility ||
659 layerVotedWithNoVote || layerVotedWithExactCompatibility;
660
661 // If we don't have a valid frame rate, but the children do, we set this
662 // layer as NoVote to allow the children to control the refresh rate
663 if (!snapshot.frameRate.rate.isValid() &&
664 snapshot.frameRate.type != FrameRateCompatibility::NoVote &&
665 snapshot.childState.hasValidFrameRate) {
666 snapshot.frameRate =
667 scheduler::LayerInfo::FrameRate(Fps(), FrameRateCompatibility::NoVote);
668 snapshot.changes |= childSnapshot.changes & RequestedLayerState::Changes::FrameRate;
669 }
670 }
671}
672
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000673void LayerSnapshotBuilder::resetRelativeState(LayerSnapshot& snapshot) {
674 snapshot.isHiddenByPolicyFromRelativeParent = false;
675 snapshot.relativeLayerMetadata.mMap.clear();
676}
677
Leon Scroggins III85d4b222023-05-09 13:58:18 -0400678// TODO (b/259407931): Remove.
Dominik Laskowski6b049ff2023-01-29 15:46:45 -0500679uint32_t getPrimaryDisplayRotationFlags(const DisplayInfos& displays) {
Vishnu Nairb76d99a2023-03-19 18:22:31 -0700680 for (auto& [_, display] : displays) {
681 if (display.isPrimary) {
682 return display.rotationFlags;
683 }
684 }
685 return 0;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000686}
687
688void LayerSnapshotBuilder::updateSnapshot(LayerSnapshot& snapshot, const Args& args,
689 const RequestedLayerState& requested,
690 const LayerSnapshot& parentSnapshot,
Vishnu Nair92990e22023-02-24 20:01:05 +0000691 const LayerHierarchy::TraversalPath& path) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000692 // Always update flags and visibility
693 ftl::Flags<RequestedLayerState::Changes> parentChanges = parentSnapshot.changes &
694 (RequestedLayerState::Changes::Hierarchy | RequestedLayerState::Changes::Geometry |
695 RequestedLayerState::Changes::Visibility | RequestedLayerState::Changes::Metadata |
Vishnu Naird47bcee2023-02-24 18:08:51 +0000696 RequestedLayerState::Changes::AffectsChildren |
697 RequestedLayerState::Changes::FrameRate);
Vishnu Nair92990e22023-02-24 20:01:05 +0000698 snapshot.changes |= parentChanges | requested.changes;
Vishnu Naircfb2d252023-01-19 04:44:02 +0000699 snapshot.isHiddenByPolicyFromParent = parentSnapshot.isHiddenByPolicyFromParent ||
Vishnu Nair3af0ec02023-02-10 04:13:48 +0000700 parentSnapshot.invalidTransform || requested.isHiddenByPolicy() ||
701 (args.excludeLayerIds.find(path.id) != args.excludeLayerIds.end());
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000702 snapshot.contentDirty = requested.what & layer_state_t::CONTENT_DIRTY;
Vishnu Naircfb2d252023-01-19 04:44:02 +0000703 // TODO(b/238781169) scope down the changes to only buffer updates.
Vishnu Naird47bcee2023-02-24 18:08:51 +0000704 snapshot.hasReadyFrame = requested.hasReadyFrame();
705 snapshot.sidebandStreamHasFrame = requested.hasSidebandStreamFrame();
Vishnu Naircfb2d252023-01-19 04:44:02 +0000706 updateSurfaceDamage(requested, snapshot.hasReadyFrame, args.forceFullDamage,
707 snapshot.surfaceDamage);
Vishnu Nair92990e22023-02-24 20:01:05 +0000708 snapshot.outputFilter.layerStack = parentSnapshot.path == LayerHierarchy::TraversalPath::ROOT
709 ? requested.layerStack
710 : parentSnapshot.outputFilter.layerStack;
Vishnu Nair80a5a702023-02-11 01:21:51 +0000711
Vishnu Nairb76d99a2023-03-19 18:22:31 -0700712 uint32_t primaryDisplayRotationFlags = getPrimaryDisplayRotationFlags(args.displays);
Vishnu Nair92990e22023-02-24 20:01:05 +0000713 const bool forceUpdate = args.forceUpdate == ForceUpdateFlags::ALL ||
714 snapshot.changes.any(RequestedLayerState::Changes::Visibility |
715 RequestedLayerState::Changes::Created);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000716
Vishnu Naircfb2d252023-01-19 04:44:02 +0000717 // always update the buffer regardless of visibility
Vishnu Nair80a5a702023-02-11 01:21:51 +0000718 if (forceUpdate || requested.what & layer_state_t::BUFFER_CHANGES || args.displayChanges) {
Vishnu Naircfb2d252023-01-19 04:44:02 +0000719 snapshot.acquireFence =
720 (requested.externalTexture &&
721 requested.bufferData->flags.test(BufferData::BufferDataChange::fenceChanged))
722 ? requested.bufferData->acquireFence
723 : Fence::NO_FENCE;
724 snapshot.buffer =
725 requested.externalTexture ? requested.externalTexture->getBuffer() : nullptr;
Vishnu Nairb76d99a2023-03-19 18:22:31 -0700726 snapshot.bufferSize = requested.getBufferSize(primaryDisplayRotationFlags);
Vishnu Naircfb2d252023-01-19 04:44:02 +0000727 snapshot.geomBufferSize = snapshot.bufferSize;
728 snapshot.croppedBufferSize = requested.getCroppedBufferSize(snapshot.bufferSize);
729 snapshot.dataspace = requested.dataspace;
730 snapshot.externalTexture = requested.externalTexture;
731 snapshot.frameNumber = (requested.bufferData) ? requested.bufferData->frameNumber : 0;
732 snapshot.geomBufferTransform = requested.bufferTransform;
733 snapshot.geomBufferUsesDisplayInverseTransform = requested.transformToDisplayInverse;
734 snapshot.geomContentCrop = requested.getBufferCrop();
735 snapshot.geomUsesSourceCrop = snapshot.hasBufferOrSidebandStream();
736 snapshot.hasProtectedContent = requested.externalTexture &&
737 requested.externalTexture->getUsage() & GRALLOC_USAGE_PROTECTED;
738 snapshot.isHdrY410 = requested.dataspace == ui::Dataspace::BT2020_ITU_PQ &&
739 requested.api == NATIVE_WINDOW_API_MEDIA &&
740 requested.bufferData->getPixelFormat() == HAL_PIXEL_FORMAT_RGBA_1010102;
741 snapshot.sidebandStream = requested.sidebandStream;
742 snapshot.transparentRegionHint = requested.transparentRegion;
743 snapshot.color.rgb = requested.getColor().rgb;
Sally Qi963049b2023-03-23 14:06:21 -0700744 snapshot.currentHdrSdrRatio = requested.currentHdrSdrRatio;
745 snapshot.desiredHdrSdrRatio = requested.desiredHdrSdrRatio;
Vishnu Naircfb2d252023-01-19 04:44:02 +0000746 }
747
Vishnu Nair92990e22023-02-24 20:01:05 +0000748 if (snapshot.isHiddenByPolicyFromParent &&
749 !snapshot.changes.test(RequestedLayerState::Changes::Created)) {
Vishnu Naircfb2d252023-01-19 04:44:02 +0000750 if (forceUpdate ||
751 snapshot.changes.any(RequestedLayerState::Changes::Hierarchy |
752 RequestedLayerState::Changes::Geometry |
753 RequestedLayerState::Changes::Input)) {
754 updateInput(snapshot, requested, parentSnapshot, path, args);
755 }
756 return;
757 }
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000758
759 if (forceUpdate || snapshot.changes.any(RequestedLayerState::Changes::AffectsChildren)) {
760 // If root layer, use the layer stack otherwise get the parent's layer stack.
761 snapshot.color.a = parentSnapshot.color.a * requested.color.a;
762 snapshot.alpha = snapshot.color.a;
Vishnu Nair29354ec2023-03-28 18:51:28 -0700763 snapshot.inputInfo.alpha = snapshot.color.a;
764
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000765 snapshot.isSecure =
766 parentSnapshot.isSecure || (requested.flags & layer_state_t::eLayerSecure);
767 snapshot.isTrustedOverlay = parentSnapshot.isTrustedOverlay || requested.isTrustedOverlay;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000768 snapshot.outputFilter.toInternalDisplay = parentSnapshot.outputFilter.toInternalDisplay ||
769 (requested.flags & layer_state_t::eLayerSkipScreenshot);
770 snapshot.stretchEffect = (requested.stretchEffect.hasEffect())
771 ? requested.stretchEffect
772 : parentSnapshot.stretchEffect;
773 if (!parentSnapshot.colorTransformIsIdentity) {
774 snapshot.colorTransform = parentSnapshot.colorTransform * requested.colorTransform;
775 snapshot.colorTransformIsIdentity = false;
776 } else {
777 snapshot.colorTransform = requested.colorTransform;
778 snapshot.colorTransformIsIdentity = !requested.hasColorTransform;
779 }
Vishnu Naircfb2d252023-01-19 04:44:02 +0000780 snapshot.gameMode = requested.metadata.has(gui::METADATA_GAME_MODE)
781 ? requested.gameMode
782 : parentSnapshot.gameMode;
Vishnu Naira9c43762023-01-27 19:10:25 +0000783 // Display mirrors are always placed in a VirtualDisplay so we never want to capture layers
784 // marked as skip capture
785 snapshot.handleSkipScreenshotFlag = parentSnapshot.handleSkipScreenshotFlag ||
786 (requested.layerStackToMirror != ui::INVALID_LAYER_STACK);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000787 }
788
Vishnu Nairb76d99a2023-03-19 18:22:31 -0700789 if (forceUpdate || snapshot.changes.any(RequestedLayerState::Changes::AffectsChildren) ||
790 args.displayChanges) {
791 snapshot.fixedTransformHint = requested.fixedTransformHint != ui::Transform::ROT_INVALID
792 ? requested.fixedTransformHint
793 : parentSnapshot.fixedTransformHint;
794
795 if (snapshot.fixedTransformHint != ui::Transform::ROT_INVALID) {
796 snapshot.transformHint = snapshot.fixedTransformHint;
797 } else {
798 const auto display = args.displays.get(snapshot.outputFilter.layerStack);
799 snapshot.transformHint = display.has_value()
800 ? std::make_optional<>(display->get().transformHint)
801 : std::nullopt;
802 }
803 }
804
Vishnu Naird47bcee2023-02-24 18:08:51 +0000805 if (forceUpdate ||
806 snapshot.changes.any(RequestedLayerState::Changes::FrameRate |
807 RequestedLayerState::Changes::Hierarchy)) {
808 snapshot.frameRate = (requested.requestedFrameRate.rate.isValid() ||
809 (requested.requestedFrameRate.type ==
810 scheduler::LayerInfo::FrameRateCompatibility::NoVote))
811 ? requested.requestedFrameRate
812 : parentSnapshot.frameRate;
813 }
814
Vishnu Nairc765c6c2023-02-23 00:08:01 +0000815 if (forceUpdate || requested.what & layer_state_t::eMetadataChanged) {
816 updateMetadata(snapshot, requested, args);
817 }
818
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000819 if (forceUpdate || requested.changes.get() != 0) {
820 snapshot.compositionType = requested.getCompositionType();
821 snapshot.dimmingEnabled = requested.dimmingEnabled;
822 snapshot.layerOpaqueFlagSet =
823 (requested.flags & layer_state_t::eLayerOpaque) == layer_state_t::eLayerOpaque;
Alec Mourif4af03e2023-02-11 00:25:24 +0000824 snapshot.cachingHint = requested.cachingHint;
Vishnu Nairef68d6d2023-02-28 06:18:27 +0000825 snapshot.frameRateSelectionPriority = requested.frameRateSelectionPriority;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000826 }
827
Vishnu Nair444f3952023-04-11 13:01:02 -0700828 if (forceUpdate || snapshot.changes.any(RequestedLayerState::Changes::Content) ||
829 snapshot.changes.any(RequestedLayerState::Changes::AffectsChildren)) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000830 snapshot.color.rgb = requested.getColor().rgb;
831 snapshot.isColorspaceAgnostic = requested.colorSpaceAgnostic;
Vishnu Nair80a5a702023-02-11 01:21:51 +0000832 snapshot.backgroundBlurRadius = args.supportsBlur
833 ? static_cast<int>(parentSnapshot.color.a * (float)requested.backgroundBlurRadius)
834 : 0;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000835 snapshot.blurRegions = requested.blurRegions;
Vishnu Nair80a5a702023-02-11 01:21:51 +0000836 for (auto& region : snapshot.blurRegions) {
837 region.alpha = region.alpha * snapshot.color.a;
838 }
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000839 snapshot.hdrMetadata = requested.hdrMetadata;
840 }
841
842 if (forceUpdate ||
843 snapshot.changes.any(RequestedLayerState::Changes::Hierarchy |
844 RequestedLayerState::Changes::Geometry)) {
Vishnu Nairb76d99a2023-03-19 18:22:31 -0700845 updateLayerBounds(snapshot, requested, parentSnapshot, primaryDisplayRotationFlags);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000846 updateRoundedCorner(snapshot, requested, parentSnapshot);
847 }
848
849 if (forceUpdate ||
850 snapshot.changes.any(RequestedLayerState::Changes::Hierarchy |
851 RequestedLayerState::Changes::Geometry |
852 RequestedLayerState::Changes::Input)) {
Vishnu Naircfb2d252023-01-19 04:44:02 +0000853 updateInput(snapshot, requested, parentSnapshot, path, args);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000854 }
855
856 // computed snapshot properties
857 updateShadows(snapshot, requested, args.globalShadowSettings);
858 if (args.includeMetadata) {
859 snapshot.layerMetadata = parentSnapshot.layerMetadata;
860 snapshot.layerMetadata.merge(requested.metadata);
861 }
862 snapshot.forceClientComposition = snapshot.isHdrY410 || snapshot.shadowSettings.length > 0 ||
863 requested.blurRegions.size() > 0 || snapshot.stretchEffect.hasEffect();
Vishnu Nairc765c6c2023-02-23 00:08:01 +0000864 snapshot.contentOpaque = snapshot.isContentOpaque();
865 snapshot.isOpaque = snapshot.contentOpaque && !snapshot.roundedCorner.hasRoundedCorners() &&
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000866 snapshot.color.a == 1.f;
867 snapshot.blendMode = getBlendMode(snapshot, requested);
Vishnu Naircfb2d252023-01-19 04:44:02 +0000868 LLOGV(snapshot.sequence,
Vishnu Nair92990e22023-02-24 20:01:05 +0000869 "%supdated %s changes:%s parent:%s requested:%s requested:%s from parent %s",
870 args.forceUpdate == ForceUpdateFlags::ALL ? "Force " : "",
871 snapshot.getDebugString().c_str(), snapshot.changes.string().c_str(),
872 parentSnapshot.changes.string().c_str(), requested.changes.string().c_str(),
873 std::to_string(requested.what).c_str(), parentSnapshot.getDebugString().c_str());
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000874}
875
876void LayerSnapshotBuilder::updateRoundedCorner(LayerSnapshot& snapshot,
877 const RequestedLayerState& requested,
878 const LayerSnapshot& parentSnapshot) {
879 snapshot.roundedCorner = RoundedCornerState();
880 RoundedCornerState parentRoundedCorner;
881 if (parentSnapshot.roundedCorner.hasRoundedCorners()) {
882 parentRoundedCorner = parentSnapshot.roundedCorner;
883 ui::Transform t = snapshot.localTransform.inverse();
884 parentRoundedCorner.cropRect = t.transform(parentRoundedCorner.cropRect);
885 parentRoundedCorner.radius.x *= t.getScaleX();
886 parentRoundedCorner.radius.y *= t.getScaleY();
887 }
888
889 FloatRect layerCropRect = snapshot.croppedBufferSize.toFloatRect();
890 const vec2 radius(requested.cornerRadius, requested.cornerRadius);
891 RoundedCornerState layerSettings(layerCropRect, radius);
892 const bool layerSettingsValid = layerSettings.hasRoundedCorners() && !layerCropRect.isEmpty();
893 const bool parentRoundedCornerValid = parentRoundedCorner.hasRoundedCorners();
894 if (layerSettingsValid && parentRoundedCornerValid) {
895 // If the parent and the layer have rounded corner settings, use the parent settings if
896 // the parent crop is entirely inside the layer crop. This has limitations and cause
897 // rendering artifacts. See b/200300845 for correct fix.
898 if (parentRoundedCorner.cropRect.left > layerCropRect.left &&
899 parentRoundedCorner.cropRect.top > layerCropRect.top &&
900 parentRoundedCorner.cropRect.right < layerCropRect.right &&
901 parentRoundedCorner.cropRect.bottom < layerCropRect.bottom) {
902 snapshot.roundedCorner = parentRoundedCorner;
903 } else {
904 snapshot.roundedCorner = layerSettings;
905 }
906 } else if (layerSettingsValid) {
907 snapshot.roundedCorner = layerSettings;
908 } else if (parentRoundedCornerValid) {
909 snapshot.roundedCorner = parentRoundedCorner;
910 }
911}
912
913void LayerSnapshotBuilder::updateLayerBounds(LayerSnapshot& snapshot,
914 const RequestedLayerState& requested,
915 const LayerSnapshot& parentSnapshot,
Vishnu Nairb76d99a2023-03-19 18:22:31 -0700916 uint32_t primaryDisplayRotationFlags) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000917 snapshot.croppedBufferSize = requested.getCroppedBufferSize(snapshot.bufferSize);
918 snapshot.geomCrop = requested.crop;
Vishnu Nairb76d99a2023-03-19 18:22:31 -0700919 snapshot.localTransform = requested.getTransform(primaryDisplayRotationFlags);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000920 snapshot.localTransformInverse = snapshot.localTransform.inverse();
921 snapshot.geomLayerTransform = parentSnapshot.geomLayerTransform * snapshot.localTransform;
Vishnu Naircfb2d252023-01-19 04:44:02 +0000922 const bool transformWasInvalid = snapshot.invalidTransform;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000923 snapshot.invalidTransform = !LayerSnapshot::isTransformValid(snapshot.geomLayerTransform);
924 if (snapshot.invalidTransform) {
Vishnu Naircfb2d252023-01-19 04:44:02 +0000925 auto& t = snapshot.geomLayerTransform;
926 auto& requestedT = requested.requestedTransform;
927 std::string transformDebug =
928 base::StringPrintf(" transform={%f,%f,%f,%f} requestedTransform={%f,%f,%f,%f}",
929 t.dsdx(), t.dsdy(), t.dtdx(), t.dtdy(), requestedT.dsdx(),
930 requestedT.dsdy(), requestedT.dtdx(), requestedT.dtdy());
931 std::string bufferDebug;
932 if (requested.externalTexture) {
Vishnu Nairb76d99a2023-03-19 18:22:31 -0700933 auto unRotBuffer = requested.getUnrotatedBufferSize(primaryDisplayRotationFlags);
Vishnu Naircfb2d252023-01-19 04:44:02 +0000934 auto& destFrame = requested.destinationFrame;
935 bufferDebug = base::StringPrintf(" buffer={%d,%d} displayRot=%d"
936 " destFrame={%d,%d,%d,%d} unRotBuffer={%d,%d}",
937 requested.externalTexture->getWidth(),
938 requested.externalTexture->getHeight(),
Vishnu Nairb76d99a2023-03-19 18:22:31 -0700939 primaryDisplayRotationFlags, destFrame.left,
940 destFrame.top, destFrame.right, destFrame.bottom,
Vishnu Naircfb2d252023-01-19 04:44:02 +0000941 unRotBuffer.getHeight(), unRotBuffer.getWidth());
942 }
943 ALOGW("Resetting transform for %s because it is invalid.%s%s",
944 snapshot.getDebugString().c_str(), transformDebug.c_str(), bufferDebug.c_str());
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000945 snapshot.geomLayerTransform.reset();
946 }
Vishnu Naircfb2d252023-01-19 04:44:02 +0000947 if (transformWasInvalid != snapshot.invalidTransform) {
948 // If transform is invalid, the layer will be hidden.
949 mResortSnapshots = true;
950 }
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000951 snapshot.geomInverseLayerTransform = snapshot.geomLayerTransform.inverse();
952
953 FloatRect parentBounds = parentSnapshot.geomLayerBounds;
954 parentBounds = snapshot.localTransform.inverse().transform(parentBounds);
955 snapshot.geomLayerBounds =
956 (requested.externalTexture) ? snapshot.bufferSize.toFloatRect() : parentBounds;
957 if (!requested.crop.isEmpty()) {
958 snapshot.geomLayerBounds = snapshot.geomLayerBounds.intersect(requested.crop.toFloatRect());
959 }
960 snapshot.geomLayerBounds = snapshot.geomLayerBounds.intersect(parentBounds);
961 snapshot.transformedBounds = snapshot.geomLayerTransform.transform(snapshot.geomLayerBounds);
Vishnu Naircfb2d252023-01-19 04:44:02 +0000962 const Rect geomLayerBoundsWithoutTransparentRegion =
963 RequestedLayerState::reduce(Rect(snapshot.geomLayerBounds),
964 requested.transparentRegion);
965 snapshot.transformedBoundsWithoutTransparentRegion =
966 snapshot.geomLayerTransform.transform(geomLayerBoundsWithoutTransparentRegion);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000967 snapshot.parentTransform = parentSnapshot.geomLayerTransform;
968
969 // Subtract the transparent region and snap to the bounds
Vishnu Naircfb2d252023-01-19 04:44:02 +0000970 const Rect bounds =
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000971 RequestedLayerState::reduce(snapshot.croppedBufferSize, requested.transparentRegion);
Vishnu Naircfb2d252023-01-19 04:44:02 +0000972 if (requested.potentialCursor) {
973 snapshot.cursorFrame = snapshot.geomLayerTransform.transform(bounds);
974 }
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000975}
976
977void LayerSnapshotBuilder::updateShadows(LayerSnapshot& snapshot,
978 const RequestedLayerState& requested,
979 const renderengine::ShadowSettings& globalShadowSettings) {
980 snapshot.shadowRadius = requested.shadowRadius;
981 snapshot.shadowSettings.length = requested.shadowRadius;
982 if (snapshot.shadowRadius > 0.f) {
983 snapshot.shadowSettings = globalShadowSettings;
984
985 // Note: this preserves existing behavior of shadowing the entire layer and not cropping
986 // it if transparent regions are present. This may not be necessary since shadows are
987 // typically cast by layers without transparent regions.
988 snapshot.shadowSettings.boundaries = snapshot.geomLayerBounds;
989
990 // If the casting layer is translucent, we need to fill in the shadow underneath the
991 // layer. Otherwise the generated shadow will only be shown around the casting layer.
992 snapshot.shadowSettings.casterIsTranslucent =
993 !snapshot.isContentOpaque() || (snapshot.alpha < 1.0f);
994 snapshot.shadowSettings.ambientColor *= snapshot.alpha;
995 snapshot.shadowSettings.spotColor *= snapshot.alpha;
996 }
997}
998
999void LayerSnapshotBuilder::updateInput(LayerSnapshot& snapshot,
1000 const RequestedLayerState& requested,
1001 const LayerSnapshot& parentSnapshot,
Vishnu Naircfb2d252023-01-19 04:44:02 +00001002 const LayerHierarchy::TraversalPath& path,
1003 const Args& args) {
1004 if (requested.windowInfoHandle) {
1005 snapshot.inputInfo = *requested.windowInfoHandle->getInfo();
1006 } else {
1007 snapshot.inputInfo = {};
Vishnu Nair40d02282023-02-28 21:11:40 +00001008 // b/271132344 revisit this and see if we can always use the layers uid/pid
1009 snapshot.inputInfo.name = requested.name;
1010 snapshot.inputInfo.ownerUid = static_cast<int32_t>(requested.ownerUid);
1011 snapshot.inputInfo.ownerPid = requested.ownerPid;
Vishnu Naircfb2d252023-01-19 04:44:02 +00001012 }
Vishnu Nair29354ec2023-03-28 18:51:28 -07001013 snapshot.touchCropId = requested.touchCropId;
Vishnu Naircfb2d252023-01-19 04:44:02 +00001014
Vishnu Nair93b8b792023-02-27 19:40:24 +00001015 snapshot.inputInfo.id = static_cast<int32_t>(snapshot.uniqueSequence);
Vishnu Naird47bcee2023-02-24 18:08:51 +00001016 snapshot.inputInfo.displayId = static_cast<int32_t>(snapshot.outputFilter.layerStack.id);
Vishnu Nair29354ec2023-03-28 18:51:28 -07001017 updateVisibility(snapshot, snapshot.isVisible);
Vishnu Naircfb2d252023-01-19 04:44:02 +00001018 if (!needsInputInfo(snapshot, requested)) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +00001019 return;
1020 }
1021
Vishnu Naircfb2d252023-01-19 04:44:02 +00001022 static frontend::DisplayInfo sDefaultInfo = {.isSecure = false};
1023 const std::optional<frontend::DisplayInfo> displayInfoOpt =
1024 args.displays.get(snapshot.outputFilter.layerStack);
1025 bool noValidDisplay = !displayInfoOpt.has_value();
1026 auto displayInfo = displayInfoOpt.value_or(sDefaultInfo);
1027
1028 if (!requested.windowInfoHandle) {
1029 snapshot.inputInfo.inputConfig = gui::WindowInfo::InputConfig::NO_INPUT_CHANNEL;
1030 }
Vishnu Nair8fc721b2022-12-22 20:06:32 +00001031 fillInputFrameInfo(snapshot.inputInfo, displayInfo.transform, snapshot);
1032
1033 if (noValidDisplay) {
1034 // Do not let the window receive touches if it is not associated with a valid display
1035 // transform. We still allow the window to receive keys and prevent ANRs.
1036 snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::NOT_TOUCHABLE;
1037 }
1038
Vishnu Nair8fc721b2022-12-22 20:06:32 +00001039 snapshot.inputInfo.alpha = snapshot.color.a;
Vishnu Nair40d02282023-02-28 21:11:40 +00001040 snapshot.inputInfo.touchOcclusionMode = requested.hasInputInfo()
1041 ? requested.windowInfoHandle->getInfo()->touchOcclusionMode
1042 : parentSnapshot.inputInfo.touchOcclusionMode;
Vishnu Nair8fc721b2022-12-22 20:06:32 +00001043 if (requested.dropInputMode == gui::DropInputMode::ALL ||
1044 parentSnapshot.dropInputMode == gui::DropInputMode::ALL) {
1045 snapshot.dropInputMode = gui::DropInputMode::ALL;
1046 } else if (requested.dropInputMode == gui::DropInputMode::OBSCURED ||
1047 parentSnapshot.dropInputMode == gui::DropInputMode::OBSCURED) {
1048 snapshot.dropInputMode = gui::DropInputMode::OBSCURED;
1049 } else {
1050 snapshot.dropInputMode = gui::DropInputMode::NONE;
1051 }
1052
1053 handleDropInputMode(snapshot, parentSnapshot);
1054
1055 // If the window will be blacked out on a display because the display does not have the secure
1056 // flag and the layer has the secure flag set, then drop input.
1057 if (!displayInfo.isSecure && snapshot.isSecure) {
1058 snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::DROP_INPUT;
1059 }
1060
1061 auto cropLayerSnapshot = getSnapshot(requested.touchCropId);
Vishnu Nair29354ec2023-03-28 18:51:28 -07001062 if (cropLayerSnapshot) {
1063 mNeedsTouchableRegionCrop.insert(path);
1064 } else if (snapshot.inputInfo.replaceTouchableRegionWithCrop) {
1065 FloatRect inputBounds = getInputBounds(snapshot, /*fillParentBounds=*/true).first;
Vishnu Nairfed7c122023-03-18 01:54:43 +00001066 Rect inputBoundsInDisplaySpace =
Vishnu Nair29354ec2023-03-28 18:51:28 -07001067 getInputBoundsInDisplaySpace(snapshot, inputBounds, displayInfo.transform);
1068 snapshot.inputInfo.touchableRegion = Region(inputBoundsInDisplaySpace);
Vishnu Nair8fc721b2022-12-22 20:06:32 +00001069 }
1070
1071 // Inherit the trusted state from the parent hierarchy, but don't clobber the trusted state
1072 // if it was set by WM for a known system overlay
1073 if (snapshot.isTrustedOverlay) {
1074 snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::TRUSTED_OVERLAY;
1075 }
1076
1077 // If the layer is a clone, we need to crop the input region to cloned root to prevent
1078 // touches from going outside the cloned area.
1079 if (path.isClone()) {
1080 snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::CLONE;
Vishnu Nair444f3952023-04-11 13:01:02 -07001081 // Cloned layers shouldn't handle watch outside since their z order is not determined by
1082 // WM or the client.
1083 snapshot.inputInfo.inputConfig.clear(gui::WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH);
1084
Vishnu Nair29354ec2023-03-28 18:51:28 -07001085 mNeedsTouchableRegionCrop.insert(path);
Vishnu Nair8fc721b2022-12-22 20:06:32 +00001086 }
1087}
1088
1089std::vector<std::unique_ptr<LayerSnapshot>>& LayerSnapshotBuilder::getSnapshots() {
1090 return mSnapshots;
1091}
1092
Vishnu Naircfb2d252023-01-19 04:44:02 +00001093void LayerSnapshotBuilder::forEachVisibleSnapshot(const ConstVisitor& visitor) const {
1094 for (int i = 0; i < mNumInterestingSnapshots; i++) {
1095 LayerSnapshot& snapshot = *mSnapshots[(size_t)i];
1096 if (!snapshot.isVisible) continue;
1097 visitor(snapshot);
1098 }
1099}
1100
Vishnu Nair3af0ec02023-02-10 04:13:48 +00001101// Visit each visible snapshot in z-order
1102void LayerSnapshotBuilder::forEachVisibleSnapshot(const ConstVisitor& visitor,
1103 const LayerHierarchy& root) const {
1104 root.traverseInZOrder(
1105 [this, visitor](const LayerHierarchy&,
1106 const LayerHierarchy::TraversalPath& traversalPath) -> bool {
1107 LayerSnapshot* snapshot = getSnapshot(traversalPath);
1108 if (snapshot && snapshot->isVisible) {
1109 visitor(*snapshot);
1110 }
1111 return true;
1112 });
1113}
1114
Vishnu Naircfb2d252023-01-19 04:44:02 +00001115void LayerSnapshotBuilder::forEachVisibleSnapshot(const Visitor& visitor) {
1116 for (int i = 0; i < mNumInterestingSnapshots; i++) {
1117 std::unique_ptr<LayerSnapshot>& snapshot = mSnapshots.at((size_t)i);
1118 if (!snapshot->isVisible) continue;
1119 visitor(snapshot);
1120 }
1121}
1122
1123void LayerSnapshotBuilder::forEachInputSnapshot(const ConstVisitor& visitor) const {
1124 for (int i = mNumInterestingSnapshots - 1; i >= 0; i--) {
1125 LayerSnapshot& snapshot = *mSnapshots[(size_t)i];
1126 if (!snapshot.hasInputInfo()) continue;
1127 visitor(snapshot);
1128 }
1129}
1130
Vishnu Nair29354ec2023-03-28 18:51:28 -07001131void LayerSnapshotBuilder::updateTouchableRegionCrop(const Args& args) {
1132 if (mNeedsTouchableRegionCrop.empty()) {
1133 return;
1134 }
1135
1136 static constexpr ftl::Flags<RequestedLayerState::Changes> AFFECTS_INPUT =
1137 RequestedLayerState::Changes::Visibility | RequestedLayerState::Changes::Created |
1138 RequestedLayerState::Changes::Hierarchy | RequestedLayerState::Changes::Geometry |
1139 RequestedLayerState::Changes::Input;
1140
1141 if (args.forceUpdate != ForceUpdateFlags::ALL &&
1142 !args.layerLifecycleManager.getGlobalChanges().any(AFFECTS_INPUT)) {
1143 return;
1144 }
1145
1146 for (auto& path : mNeedsTouchableRegionCrop) {
1147 frontend::LayerSnapshot* snapshot = getSnapshot(path);
1148 if (!snapshot) {
1149 continue;
1150 }
1151 const std::optional<frontend::DisplayInfo> displayInfoOpt =
1152 args.displays.get(snapshot->outputFilter.layerStack);
1153 static frontend::DisplayInfo sDefaultInfo = {.isSecure = false};
1154 auto displayInfo = displayInfoOpt.value_or(sDefaultInfo);
1155
1156 bool needsUpdate =
1157 args.forceUpdate == ForceUpdateFlags::ALL || snapshot->changes.any(AFFECTS_INPUT);
1158 auto cropLayerSnapshot = getSnapshot(snapshot->touchCropId);
1159 needsUpdate =
1160 needsUpdate || (cropLayerSnapshot && cropLayerSnapshot->changes.any(AFFECTS_INPUT));
1161 auto clonedRootSnapshot = path.isClone() ? getSnapshot(snapshot->mirrorRootPath) : nullptr;
1162 needsUpdate = needsUpdate ||
1163 (clonedRootSnapshot && clonedRootSnapshot->changes.any(AFFECTS_INPUT));
1164
1165 if (!needsUpdate) {
1166 continue;
1167 }
1168
1169 if (snapshot->inputInfo.replaceTouchableRegionWithCrop) {
1170 Rect inputBoundsInDisplaySpace;
1171 if (!cropLayerSnapshot) {
1172 FloatRect inputBounds = getInputBounds(*snapshot, /*fillParentBounds=*/true).first;
1173 inputBoundsInDisplaySpace =
1174 getInputBoundsInDisplaySpace(*snapshot, inputBounds, displayInfo.transform);
1175 } else {
1176 FloatRect inputBounds =
1177 getInputBounds(*cropLayerSnapshot, /*fillParentBounds=*/true).first;
1178 inputBoundsInDisplaySpace =
1179 getInputBoundsInDisplaySpace(*cropLayerSnapshot, inputBounds,
1180 displayInfo.transform);
1181 }
1182 snapshot->inputInfo.touchableRegion = Region(inputBoundsInDisplaySpace);
1183 } else if (cropLayerSnapshot) {
1184 FloatRect inputBounds =
1185 getInputBounds(*cropLayerSnapshot, /*fillParentBounds=*/true).first;
1186 Rect inputBoundsInDisplaySpace =
1187 getInputBoundsInDisplaySpace(*cropLayerSnapshot, inputBounds,
1188 displayInfo.transform);
1189 snapshot->inputInfo.touchableRegion = snapshot->inputInfo.touchableRegion.intersect(
1190 displayInfo.transform.transform(inputBoundsInDisplaySpace));
1191 }
1192
1193 // If the layer is a clone, we need to crop the input region to cloned root to prevent
1194 // touches from going outside the cloned area.
1195 if (clonedRootSnapshot) {
1196 const Rect rect =
1197 displayInfo.transform.transform(Rect{clonedRootSnapshot->transformedBounds});
1198 snapshot->inputInfo.touchableRegion =
1199 snapshot->inputInfo.touchableRegion.intersect(rect);
1200 }
1201 }
1202}
1203
Vishnu Nair8fc721b2022-12-22 20:06:32 +00001204} // namespace android::surfaceflinger::frontend