blob: 7e678b98fa403cf887b85f00e18bf873b8387705 [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
Vishnu Naira02943f2023-06-03 13:44:46 -070020#define LOG_TAG "SurfaceFlinger"
Vishnu Nair8fc721b2022-12-22 20:06:32 +000021
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>
Vishnu Naira02943f2023-06-03 13:44:46 -070027#include <ui/DisplayMap.h>
Dominik Laskowski6b049ff2023-01-29 15:46:45 -050028#include <ui/FloatRect.h>
29
Vishnu Nair8fc721b2022-12-22 20:06:32 +000030#include "DisplayHardware/HWC2.h"
31#include "DisplayHardware/Hal.h"
Vishnu Nair3d8565a2023-06-30 07:23:24 +000032#include "Layer.h" // eFrameRateSelectionPriority constants
Vishnu Naircfb2d252023-01-19 04:44:02 +000033#include "LayerLog.h"
Vishnu Nairb76d99a2023-03-19 18:22:31 -070034#include "LayerSnapshotBuilder.h"
Vishnu Naircfb2d252023-01-19 04:44:02 +000035#include "TimeStats/TimeStats.h"
Vishnu Naird1f74982023-06-15 20:16:51 -070036#include "Tracing/TransactionTracing.h"
Vishnu Nair8fc721b2022-12-22 20:06:32 +000037
38namespace android::surfaceflinger::frontend {
39
40using namespace ftl::flag_operators;
41
42namespace {
Dominik Laskowski6b049ff2023-01-29 15:46:45 -050043
44FloatRect getMaxDisplayBounds(const DisplayInfos& displays) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +000045 const ui::Size maxSize = [&displays] {
46 if (displays.empty()) return ui::Size{5000, 5000};
47
48 return std::accumulate(displays.begin(), displays.end(), ui::kEmptySize,
49 [](ui::Size size, const auto& pair) -> ui::Size {
50 const auto& display = pair.second;
51 return {std::max(size.getWidth(), display.info.logicalWidth),
52 std::max(size.getHeight(), display.info.logicalHeight)};
53 });
54 }();
55
56 // Ignore display bounds for now since they will be computed later. Use a large Rect bound
57 // to ensure it's bigger than an actual display will be.
58 const float xMax = static_cast<float>(maxSize.getWidth()) * 10.f;
59 const float yMax = static_cast<float>(maxSize.getHeight()) * 10.f;
60
61 return {-xMax, -yMax, xMax, yMax};
62}
63
64// Applies the given transform to the region, while protecting against overflows caused by any
65// offsets. If applying the offset in the transform to any of the Rects in the region would result
66// in an overflow, they are not added to the output Region.
67Region transformTouchableRegionSafely(const ui::Transform& t, const Region& r,
68 const std::string& debugWindowName) {
69 // Round the translation using the same rounding strategy used by ui::Transform.
70 const auto tx = static_cast<int32_t>(t.tx() + 0.5);
71 const auto ty = static_cast<int32_t>(t.ty() + 0.5);
72
73 ui::Transform transformWithoutOffset = t;
74 transformWithoutOffset.set(0.f, 0.f);
75
76 const Region transformed = transformWithoutOffset.transform(r);
77
78 // Apply the translation to each of the Rects in the region while discarding any that overflow.
79 Region ret;
80 for (const auto& rect : transformed) {
81 Rect newRect;
82 if (__builtin_add_overflow(rect.left, tx, &newRect.left) ||
83 __builtin_add_overflow(rect.top, ty, &newRect.top) ||
84 __builtin_add_overflow(rect.right, tx, &newRect.right) ||
85 __builtin_add_overflow(rect.bottom, ty, &newRect.bottom)) {
86 ALOGE("Applying transform to touchable region of window '%s' resulted in an overflow.",
87 debugWindowName.c_str());
88 continue;
89 }
90 ret.orSelf(newRect);
91 }
92 return ret;
93}
94
95/*
96 * We don't want to send the layer's transform to input, but rather the
97 * parent's transform. This is because Layer's transform is
98 * information about how the buffer is placed on screen. The parent's
99 * transform makes more sense to send since it's information about how the
100 * layer is placed on screen. This transform is used by input to determine
101 * how to go from screen space back to window space.
102 */
103ui::Transform getInputTransform(const LayerSnapshot& snapshot) {
104 if (!snapshot.hasBufferOrSidebandStream()) {
105 return snapshot.geomLayerTransform;
106 }
107 return snapshot.parentTransform;
108}
109
110/**
Vishnu Nairfed7c122023-03-18 01:54:43 +0000111 * Returns the bounds used to fill the input frame and the touchable region.
112 *
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000113 * Similar to getInputTransform, we need to update the bounds to include the transform.
114 * This is because bounds don't include the buffer transform, where the input assumes
115 * that's already included.
116 */
Vishnu Nairfed7c122023-03-18 01:54:43 +0000117std::pair<FloatRect, bool> getInputBounds(const LayerSnapshot& snapshot, bool fillParentBounds) {
118 FloatRect inputBounds = snapshot.croppedBufferSize.toFloatRect();
119 if (snapshot.hasBufferOrSidebandStream() && snapshot.croppedBufferSize.isValid() &&
120 snapshot.localTransform.getType() != ui::Transform::IDENTITY) {
121 inputBounds = snapshot.localTransform.transform(inputBounds);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000122 }
123
Vishnu Nairfed7c122023-03-18 01:54:43 +0000124 bool inputBoundsValid = snapshot.croppedBufferSize.isValid();
125 if (!inputBoundsValid) {
126 /**
127 * Input bounds are based on the layer crop or buffer size. But if we are using
128 * the layer bounds as the input bounds (replaceTouchableRegionWithCrop flag) then
129 * we can use the parent bounds as the input bounds if the layer does not have buffer
130 * or a crop. We want to unify this logic but because of compat reasons we cannot always
131 * use the parent bounds. A layer without a buffer can get input. So when a window is
132 * initially added, its touchable region can fill its parent layer bounds and that can
133 * have negative consequences.
134 */
135 inputBounds = fillParentBounds ? snapshot.geomLayerBounds : FloatRect{};
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000136 }
Vishnu Nairfed7c122023-03-18 01:54:43 +0000137
138 // Clamp surface inset to the input bounds.
139 const float inset = static_cast<float>(snapshot.inputInfo.surfaceInset);
140 const float xSurfaceInset = std::clamp(inset, 0.f, inputBounds.getWidth() / 2.f);
141 const float ySurfaceInset = std::clamp(inset, 0.f, inputBounds.getHeight() / 2.f);
142
143 // Apply the insets to the input bounds.
144 inputBounds.left += xSurfaceInset;
145 inputBounds.top += ySurfaceInset;
146 inputBounds.right -= xSurfaceInset;
147 inputBounds.bottom -= ySurfaceInset;
148 return {inputBounds, inputBoundsValid};
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000149}
150
Vishnu Nairfed7c122023-03-18 01:54:43 +0000151Rect getInputBoundsInDisplaySpace(const LayerSnapshot& snapshot, const FloatRect& insetBounds,
152 const ui::Transform& screenToDisplay) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000153 // InputDispatcher works in the display device's coordinate space. Here, we calculate the
154 // frame and transform used for the layer, which determines the bounds and the coordinate space
155 // within which the layer will receive input.
Vishnu Nairfed7c122023-03-18 01:54:43 +0000156
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000157 // Coordinate space definitions:
158 // - display: The display device's coordinate space. Correlates to pixels on the display.
159 // - screen: The post-rotation coordinate space for the display, a.k.a. logical display space.
160 // - layer: The coordinate space of this layer.
161 // - input: The coordinate space in which this layer will receive input events. This could be
162 // different than layer space if a surfaceInset is used, which changes the origin
163 // of the input space.
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000164
165 // Crop the input bounds to ensure it is within the parent's bounds.
Vishnu Nairfed7c122023-03-18 01:54:43 +0000166 const FloatRect croppedInsetBoundsInLayer = snapshot.geomLayerBounds.intersect(insetBounds);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000167
168 const ui::Transform layerToScreen = getInputTransform(snapshot);
169 const ui::Transform layerToDisplay = screenToDisplay * layerToScreen;
170
Vishnu Nairfed7c122023-03-18 01:54:43 +0000171 return Rect{layerToDisplay.transform(croppedInsetBoundsInLayer)};
172}
173
174void fillInputFrameInfo(gui::WindowInfo& info, const ui::Transform& screenToDisplay,
175 const LayerSnapshot& snapshot) {
176 auto [inputBounds, inputBoundsValid] = getInputBounds(snapshot, /*fillParentBounds=*/false);
177 if (!inputBoundsValid) {
178 info.touchableRegion.clear();
179 }
180
181 const Rect roundedFrameInDisplay =
182 getInputBoundsInDisplaySpace(snapshot, inputBounds, screenToDisplay);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000183 info.frameLeft = roundedFrameInDisplay.left;
184 info.frameTop = roundedFrameInDisplay.top;
185 info.frameRight = roundedFrameInDisplay.right;
186 info.frameBottom = roundedFrameInDisplay.bottom;
187
188 ui::Transform inputToLayer;
Vishnu Nairfed7c122023-03-18 01:54:43 +0000189 inputToLayer.set(inputBounds.left, inputBounds.top);
190 const ui::Transform layerToScreen = getInputTransform(snapshot);
191 const ui::Transform inputToDisplay = screenToDisplay * layerToScreen * inputToLayer;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000192
193 // InputDispatcher expects a display-to-input transform.
194 info.transform = inputToDisplay.inverse();
195
196 // The touchable region is specified in the input coordinate space. Change it to display space.
197 info.touchableRegion =
198 transformTouchableRegionSafely(inputToDisplay, info.touchableRegion, snapshot.name);
199}
200
201void handleDropInputMode(LayerSnapshot& snapshot, const LayerSnapshot& parentSnapshot) {
202 if (snapshot.inputInfo.inputConfig.test(gui::WindowInfo::InputConfig::NO_INPUT_CHANNEL)) {
203 return;
204 }
205
206 // Check if we need to drop input unconditionally
207 const gui::DropInputMode dropInputMode = snapshot.dropInputMode;
208 if (dropInputMode == gui::DropInputMode::ALL) {
209 snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::DROP_INPUT;
210 ALOGV("Dropping input for %s as requested by policy.", snapshot.name.c_str());
211 return;
212 }
213
214 // Check if we need to check if the window is obscured by parent
215 if (dropInputMode != gui::DropInputMode::OBSCURED) {
216 return;
217 }
218
219 // Check if the parent has set an alpha on the layer
220 if (parentSnapshot.color.a != 1.0_hf) {
221 snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::DROP_INPUT;
222 ALOGV("Dropping input for %s as requested by policy because alpha=%f",
223 snapshot.name.c_str(), static_cast<float>(parentSnapshot.color.a));
224 }
225
226 // Check if the parent has cropped the buffer
227 Rect bufferSize = snapshot.croppedBufferSize;
228 if (!bufferSize.isValid()) {
229 snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED;
230 return;
231 }
232
233 // Screenbounds are the layer bounds cropped by parents, transformed to screenspace.
234 // To check if the layer has been cropped, we take the buffer bounds, apply the local
235 // layer crop and apply the same set of transforms to move to screenspace. If the bounds
236 // match then the layer has not been cropped by its parents.
237 Rect bufferInScreenSpace(snapshot.geomLayerTransform.transform(bufferSize));
238 bool croppedByParent = bufferInScreenSpace != Rect{snapshot.transformedBounds};
239
240 if (croppedByParent) {
241 snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::DROP_INPUT;
242 ALOGV("Dropping input for %s as requested by policy because buffer is cropped by parent",
243 snapshot.name.c_str());
244 } else {
245 // If the layer is not obscured by its parents (by setting an alpha or crop), then only drop
246 // input if the window is obscured. This check should be done in surfaceflinger but the
247 // logic currently resides in inputflinger. So pass the if_obscured check to input to only
248 // drop input events if the window is obscured.
249 snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED;
250 }
251}
252
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000253auto getBlendMode(const LayerSnapshot& snapshot, const RequestedLayerState& requested) {
254 auto blendMode = Hwc2::IComposerClient::BlendMode::NONE;
255 if (snapshot.alpha != 1.0f || !snapshot.isContentOpaque()) {
256 blendMode = requested.premultipliedAlpha ? Hwc2::IComposerClient::BlendMode::PREMULTIPLIED
257 : Hwc2::IComposerClient::BlendMode::COVERAGE;
258 }
259 return blendMode;
260}
261
Vishnu Nair80a5a702023-02-11 01:21:51 +0000262void updateVisibility(LayerSnapshot& snapshot, bool visible) {
263 snapshot.isVisible = visible;
Vishnu Naircfb2d252023-01-19 04:44:02 +0000264
265 // TODO(b/238781169) we are ignoring this compat for now, since we will have
266 // to remove any optimization based on visibility.
267
268 // For compatibility reasons we let layers which can receive input
269 // receive input before they have actually submitted a buffer. Because
270 // of this we use canReceiveInput instead of isVisible to check the
271 // policy-visibility, ignoring the buffer state. However for layers with
272 // hasInputInfo()==false we can use the real visibility state.
273 // We are just using these layers for occlusion detection in
274 // InputDispatcher, and obviously if they aren't visible they can't occlude
275 // anything.
Vishnu Nair80a5a702023-02-11 01:21:51 +0000276 const bool visibleForInput =
Vishnu Nair40d02282023-02-28 21:11:40 +0000277 snapshot.hasInputInfo() ? snapshot.canReceiveInput() : snapshot.isVisible;
Vishnu Nair80a5a702023-02-11 01:21:51 +0000278 snapshot.inputInfo.setInputConfig(gui::WindowInfo::InputConfig::NOT_VISIBLE, !visibleForInput);
Vishnu Naira02943f2023-06-03 13:44:46 -0700279 LLOGV(snapshot.sequence, "updating visibility %s %s", visible ? "true" : "false",
280 snapshot.getDebugString().c_str());
Vishnu Naircfb2d252023-01-19 04:44:02 +0000281}
282
283bool needsInputInfo(const LayerSnapshot& snapshot, const RequestedLayerState& requested) {
284 if (requested.potentialCursor) {
285 return false;
286 }
287
288 if (snapshot.inputInfo.token != nullptr) {
289 return true;
290 }
291
292 if (snapshot.hasBufferOrSidebandStream()) {
293 return true;
294 }
295
296 return requested.windowInfoHandle &&
297 requested.windowInfoHandle->getInfo()->inputConfig.test(
298 gui::WindowInfo::InputConfig::NO_INPUT_CHANNEL);
299}
300
Vishnu Nairc765c6c2023-02-23 00:08:01 +0000301void updateMetadata(LayerSnapshot& snapshot, const RequestedLayerState& requested,
302 const LayerSnapshotBuilder::Args& args) {
303 snapshot.metadata.clear();
304 for (const auto& [key, mandatory] : args.supportedLayerGenericMetadata) {
305 auto compatIter = args.genericLayerMetadataKeyMap.find(key);
306 if (compatIter == std::end(args.genericLayerMetadataKeyMap)) {
307 continue;
308 }
309 const uint32_t id = compatIter->second;
310 auto it = requested.metadata.mMap.find(id);
311 if (it == std::end(requested.metadata.mMap)) {
312 continue;
313 }
314
315 snapshot.metadata.emplace(key,
316 compositionengine::GenericLayerMetadataEntry{mandatory,
317 it->second});
318 }
319}
320
Vishnu Naircfb2d252023-01-19 04:44:02 +0000321void clearChanges(LayerSnapshot& snapshot) {
322 snapshot.changes.clear();
Vishnu Naira02943f2023-06-03 13:44:46 -0700323 snapshot.clientChanges = 0;
Vishnu Naircfb2d252023-01-19 04:44:02 +0000324 snapshot.contentDirty = false;
325 snapshot.hasReadyFrame = false;
326 snapshot.sidebandStreamHasFrame = false;
327 snapshot.surfaceDamage.clear();
328}
329
Vishnu Naira02943f2023-06-03 13:44:46 -0700330// TODO (b/259407931): Remove.
331uint32_t getPrimaryDisplayRotationFlags(
332 const ui::DisplayMap<ui::LayerStack, frontend::DisplayInfo>& displays) {
333 for (auto& [_, display] : displays) {
334 if (display.isPrimary) {
335 return display.rotationFlags;
336 }
337 }
338 return 0;
339}
340
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000341} // namespace
342
343LayerSnapshot LayerSnapshotBuilder::getRootSnapshot() {
344 LayerSnapshot snapshot;
Vishnu Nair92990e22023-02-24 20:01:05 +0000345 snapshot.path = LayerHierarchy::TraversalPath::ROOT;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000346 snapshot.changes = ftl::Flags<RequestedLayerState::Changes>();
Vishnu Naira02943f2023-06-03 13:44:46 -0700347 snapshot.clientChanges = 0;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000348 snapshot.isHiddenByPolicyFromParent = false;
349 snapshot.isHiddenByPolicyFromRelativeParent = false;
350 snapshot.parentTransform.reset();
351 snapshot.geomLayerTransform.reset();
352 snapshot.geomInverseLayerTransform.reset();
353 snapshot.geomLayerBounds = getMaxDisplayBounds({});
354 snapshot.roundedCorner = RoundedCornerState();
355 snapshot.stretchEffect = {};
356 snapshot.outputFilter.layerStack = ui::DEFAULT_LAYER_STACK;
357 snapshot.outputFilter.toInternalDisplay = false;
358 snapshot.isSecure = false;
359 snapshot.color.a = 1.0_hf;
360 snapshot.colorTransformIsIdentity = true;
361 snapshot.shadowRadius = 0.f;
362 snapshot.layerMetadata.mMap.clear();
363 snapshot.relativeLayerMetadata.mMap.clear();
364 snapshot.inputInfo.touchOcclusionMode = gui::TouchOcclusionMode::BLOCK_UNTRUSTED;
365 snapshot.dropInputMode = gui::DropInputMode::NONE;
366 snapshot.isTrustedOverlay = false;
Vishnu Naircfb2d252023-01-19 04:44:02 +0000367 snapshot.gameMode = gui::GameMode::Unsupported;
368 snapshot.frameRate = {};
369 snapshot.fixedTransformHint = ui::Transform::ROT_INVALID;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000370 return snapshot;
371}
372
373LayerSnapshotBuilder::LayerSnapshotBuilder() : mRootSnapshot(getRootSnapshot()) {}
374
375LayerSnapshotBuilder::LayerSnapshotBuilder(Args args) : LayerSnapshotBuilder() {
Vishnu Naird47bcee2023-02-24 18:08:51 +0000376 args.forceUpdate = ForceUpdateFlags::ALL;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000377 updateSnapshots(args);
378}
379
380bool LayerSnapshotBuilder::tryFastUpdate(const Args& args) {
Vishnu Naira02943f2023-06-03 13:44:46 -0700381 const bool forceUpdate = args.forceUpdate != ForceUpdateFlags::NONE;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000382
Vishnu Naira02943f2023-06-03 13:44:46 -0700383 if (args.layerLifecycleManager.getGlobalChanges().get() == 0 && !forceUpdate &&
384 !args.displayChanges) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000385 return true;
386 }
387
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000388 // There are only content changes which do not require any child layer snapshots to be updated.
389 ALOGV("%s", __func__);
390 ATRACE_NAME("FastPath");
391
Vishnu Naira02943f2023-06-03 13:44:46 -0700392 uint32_t primaryDisplayRotationFlags = getPrimaryDisplayRotationFlags(args.displays);
393 if (forceUpdate || args.displayChanges) {
394 for (auto& snapshot : mSnapshots) {
395 const RequestedLayerState* requested =
396 args.layerLifecycleManager.getLayerFromId(snapshot->path.id);
397 if (!requested) continue;
398 snapshot->merge(*requested, forceUpdate, args.displayChanges, args.forceFullDamage,
399 primaryDisplayRotationFlags);
400 }
401 return false;
402 }
403
404 // Walk through all the updated requested layer states and update the corresponding snapshots.
405 for (const RequestedLayerState* requested : args.layerLifecycleManager.getChangedLayers()) {
406 auto range = mIdToSnapshots.equal_range(requested->id);
407 for (auto it = range.first; it != range.second; it++) {
408 it->second->merge(*requested, forceUpdate, args.displayChanges, args.forceFullDamage,
409 primaryDisplayRotationFlags);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000410 }
411 }
412
Vishnu Naira02943f2023-06-03 13:44:46 -0700413 if ((args.layerLifecycleManager.getGlobalChanges().get() &
414 ~(RequestedLayerState::Changes::Content | RequestedLayerState::Changes::Buffer).get()) !=
415 0) {
416 // We have changes that require us to walk the hierarchy and update child layers.
417 // No fast path for you.
418 return false;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000419 }
420 return true;
421}
422
423void LayerSnapshotBuilder::updateSnapshots(const Args& args) {
424 ATRACE_NAME("UpdateSnapshots");
Vishnu Nair3af0ec02023-02-10 04:13:48 +0000425 if (args.parentCrop) {
426 mRootSnapshot.geomLayerBounds = *args.parentCrop;
Vishnu Naird47bcee2023-02-24 18:08:51 +0000427 } else if (args.forceUpdate == ForceUpdateFlags::ALL || args.displayChanges) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000428 mRootSnapshot.geomLayerBounds = getMaxDisplayBounds(args.displays);
429 }
430 if (args.displayChanges) {
431 mRootSnapshot.changes = RequestedLayerState::Changes::AffectsChildren |
432 RequestedLayerState::Changes::Geometry;
433 }
Vishnu Naird47bcee2023-02-24 18:08:51 +0000434 if (args.forceUpdate == ForceUpdateFlags::HIERARCHY) {
435 mRootSnapshot.changes |=
436 RequestedLayerState::Changes::Hierarchy | RequestedLayerState::Changes::Visibility;
Vishnu Naira02943f2023-06-03 13:44:46 -0700437 mRootSnapshot.clientChanges |= layer_state_t::eReparent;
Vishnu Naird47bcee2023-02-24 18:08:51 +0000438 }
Vishnu Naira02943f2023-06-03 13:44:46 -0700439
440 for (auto& snapshot : mSnapshots) {
441 if (snapshot->reachablilty == LayerSnapshot::Reachablilty::Reachable) {
442 snapshot->reachablilty = LayerSnapshot::Reachablilty::Unreachable;
443 }
444 }
445
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000446 LayerHierarchy::TraversalPath root = LayerHierarchy::TraversalPath::ROOT;
Vishnu Naird47bcee2023-02-24 18:08:51 +0000447 if (args.root.getLayer()) {
448 // The hierarchy can have a root layer when used for screenshots otherwise, it will have
449 // multiple children.
450 LayerHierarchy::ScopedAddToTraversalPath addChildToPath(root, args.root.getLayer()->id,
451 LayerHierarchy::Variant::Attached);
Vishnu Naird1f74982023-06-15 20:16:51 -0700452 updateSnapshotsInHierarchy(args, args.root, root, mRootSnapshot, /*depth=*/0);
Vishnu Naird47bcee2023-02-24 18:08:51 +0000453 } else {
454 for (auto& [childHierarchy, variant] : args.root.mChildren) {
455 LayerHierarchy::ScopedAddToTraversalPath addChildToPath(root,
456 childHierarchy->getLayer()->id,
457 variant);
Vishnu Naird1f74982023-06-15 20:16:51 -0700458 updateSnapshotsInHierarchy(args, *childHierarchy, root, mRootSnapshot, /*depth=*/0);
Vishnu Naird47bcee2023-02-24 18:08:51 +0000459 }
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000460 }
461
Vishnu Nair29354ec2023-03-28 18:51:28 -0700462 // Update touchable region crops outside the main update pass. This is because a layer could be
463 // cropped by any other layer and it requires both snapshots to be updated.
464 updateTouchableRegionCrop(args);
465
Vishnu Nairfccd6362023-02-24 23:39:53 +0000466 const bool hasUnreachableSnapshots = sortSnapshotsByZ(args);
Vishnu Naircfb2d252023-01-19 04:44:02 +0000467 clearChanges(mRootSnapshot);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000468
Vishnu Nair29354ec2023-03-28 18:51:28 -0700469 // Destroy unreachable snapshots for clone layers. And destroy snapshots for non-clone
470 // layers if the layer have been destroyed.
471 // TODO(b/238781169) consider making clone layer ids stable as well
472 if (!hasUnreachableSnapshots && args.layerLifecycleManager.getDestroyedLayers().empty()) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000473 return;
474 }
475
Vishnu Nair29354ec2023-03-28 18:51:28 -0700476 std::unordered_set<uint32_t> destroyedLayerIds;
477 for (auto& destroyedLayer : args.layerLifecycleManager.getDestroyedLayers()) {
478 destroyedLayerIds.insert(destroyedLayer->id);
479 }
480
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000481 auto it = mSnapshots.begin();
482 while (it < mSnapshots.end()) {
483 auto& traversalPath = it->get()->path;
Vishnu Naira02943f2023-06-03 13:44:46 -0700484 const bool unreachable =
485 it->get()->reachablilty == LayerSnapshot::Reachablilty::Unreachable;
486 const bool isClone = traversalPath.isClone();
487 const bool layerIsDestroyed =
488 destroyedLayerIds.find(traversalPath.id) != destroyedLayerIds.end();
489 const bool destroySnapshot = (unreachable && isClone) || layerIsDestroyed;
490
491 if (!destroySnapshot) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000492 it++;
493 continue;
494 }
495
Vishnu Naira02943f2023-06-03 13:44:46 -0700496 mPathToSnapshot.erase(traversalPath);
497
498 auto range = mIdToSnapshots.equal_range(traversalPath.id);
499 auto matchingSnapshot =
500 std::find_if(range.first, range.second, [&traversalPath](auto& snapshotWithId) {
501 return snapshotWithId.second->path == traversalPath;
502 });
503 mIdToSnapshots.erase(matchingSnapshot);
Vishnu Nair29354ec2023-03-28 18:51:28 -0700504 mNeedsTouchableRegionCrop.erase(traversalPath);
Vishnu Naircfb2d252023-01-19 04:44:02 +0000505 mSnapshots.back()->globalZ = it->get()->globalZ;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000506 std::iter_swap(it, mSnapshots.end() - 1);
507 mSnapshots.erase(mSnapshots.end() - 1);
508 }
509}
510
511void LayerSnapshotBuilder::update(const Args& args) {
Vishnu Nair92990e22023-02-24 20:01:05 +0000512 for (auto& snapshot : mSnapshots) {
513 clearChanges(*snapshot);
514 }
515
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000516 if (tryFastUpdate(args)) {
517 return;
518 }
519 updateSnapshots(args);
520}
521
Vishnu Naircfb2d252023-01-19 04:44:02 +0000522const LayerSnapshot& LayerSnapshotBuilder::updateSnapshotsInHierarchy(
523 const Args& args, const LayerHierarchy& hierarchy,
Vishnu Naird1f74982023-06-15 20:16:51 -0700524 LayerHierarchy::TraversalPath& traversalPath, const LayerSnapshot& parentSnapshot,
525 int depth) {
526 if (depth > 50) {
527 TransactionTraceWriter::getInstance().invoke("layer_builder_stack_overflow_",
528 /*overwrite=*/false);
529 LOG_ALWAYS_FATAL("Cycle detected in LayerSnapshotBuilder. See "
530 "builder_stack_overflow_transactions.winscope");
531 }
532
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000533 const RequestedLayerState* layer = hierarchy.getLayer();
Vishnu Naircfb2d252023-01-19 04:44:02 +0000534 LayerSnapshot* snapshot = getSnapshot(traversalPath);
535 const bool newSnapshot = snapshot == nullptr;
Vishnu Naira02943f2023-06-03 13:44:46 -0700536 uint32_t primaryDisplayRotationFlags = getPrimaryDisplayRotationFlags(args.displays);
Vishnu Naircfb2d252023-01-19 04:44:02 +0000537 if (newSnapshot) {
Vishnu Nair92990e22023-02-24 20:01:05 +0000538 snapshot = createSnapshot(traversalPath, *layer, parentSnapshot);
Vishnu Naira02943f2023-06-03 13:44:46 -0700539 snapshot->merge(*layer, /*forceUpdate=*/true, /*displayChanges=*/true, args.forceFullDamage,
540 primaryDisplayRotationFlags);
541 snapshot->changes |= RequestedLayerState::Changes::Created;
Vishnu Naircfb2d252023-01-19 04:44:02 +0000542 }
Vishnu Naird47bcee2023-02-24 18:08:51 +0000543 scheduler::LayerInfo::FrameRate oldFrameRate = snapshot->frameRate;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000544 if (traversalPath.isRelative()) {
545 bool parentIsRelative = traversalPath.variant == LayerHierarchy::Variant::Relative;
546 updateRelativeState(*snapshot, parentSnapshot, parentIsRelative, args);
547 } else {
548 if (traversalPath.isAttached()) {
549 resetRelativeState(*snapshot);
550 }
Vishnu Nair92990e22023-02-24 20:01:05 +0000551 updateSnapshot(*snapshot, args, *layer, parentSnapshot, traversalPath);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000552 }
553
554 for (auto& [childHierarchy, variant] : hierarchy.mChildren) {
555 LayerHierarchy::ScopedAddToTraversalPath addChildToPath(traversalPath,
556 childHierarchy->getLayer()->id,
557 variant);
Vishnu Naircfb2d252023-01-19 04:44:02 +0000558 const LayerSnapshot& childSnapshot =
Vishnu Naird1f74982023-06-15 20:16:51 -0700559 updateSnapshotsInHierarchy(args, *childHierarchy, traversalPath, *snapshot,
560 depth + 1);
Vishnu Nair42b918e2023-07-18 20:05:29 +0000561 updateFrameRateFromChildSnapshot(*snapshot, childSnapshot, args);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000562 }
Vishnu Naird47bcee2023-02-24 18:08:51 +0000563
564 if (oldFrameRate == snapshot->frameRate) {
565 snapshot->changes.clear(RequestedLayerState::Changes::FrameRate);
566 }
Vishnu Naircfb2d252023-01-19 04:44:02 +0000567 return *snapshot;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000568}
569
570LayerSnapshot* LayerSnapshotBuilder::getSnapshot(uint32_t layerId) const {
571 if (layerId == UNASSIGNED_LAYER_ID) {
572 return nullptr;
573 }
574 LayerHierarchy::TraversalPath path{.id = layerId};
575 return getSnapshot(path);
576}
577
578LayerSnapshot* LayerSnapshotBuilder::getSnapshot(const LayerHierarchy::TraversalPath& id) const {
Vishnu Naira02943f2023-06-03 13:44:46 -0700579 auto it = mPathToSnapshot.find(id);
580 return it == mPathToSnapshot.end() ? nullptr : it->second;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000581}
582
Vishnu Nair92990e22023-02-24 20:01:05 +0000583LayerSnapshot* LayerSnapshotBuilder::createSnapshot(const LayerHierarchy::TraversalPath& path,
584 const RequestedLayerState& layer,
585 const LayerSnapshot& parentSnapshot) {
586 mSnapshots.emplace_back(std::make_unique<LayerSnapshot>(layer, path));
Vishnu Naircfb2d252023-01-19 04:44:02 +0000587 LayerSnapshot* snapshot = mSnapshots.back().get();
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000588 snapshot->globalZ = static_cast<size_t>(mSnapshots.size()) - 1;
Vishnu Nair92990e22023-02-24 20:01:05 +0000589 if (path.isClone() && path.variant != LayerHierarchy::Variant::Mirror) {
590 snapshot->mirrorRootPath = parentSnapshot.mirrorRootPath;
591 }
Vishnu Naira02943f2023-06-03 13:44:46 -0700592 mPathToSnapshot[path] = snapshot;
593
594 mIdToSnapshots.emplace(path.id, snapshot);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000595 return snapshot;
596}
597
Vishnu Nairfccd6362023-02-24 23:39:53 +0000598bool LayerSnapshotBuilder::sortSnapshotsByZ(const Args& args) {
Vishnu Naird47bcee2023-02-24 18:08:51 +0000599 if (!mResortSnapshots && args.forceUpdate == ForceUpdateFlags::NONE &&
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000600 !args.layerLifecycleManager.getGlobalChanges().any(
601 RequestedLayerState::Changes::Hierarchy |
602 RequestedLayerState::Changes::Visibility)) {
603 // We are not force updating and there are no hierarchy or visibility changes. Avoid sorting
604 // the snapshots.
Vishnu Nairfccd6362023-02-24 23:39:53 +0000605 return false;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000606 }
Vishnu Naircfb2d252023-01-19 04:44:02 +0000607 mResortSnapshots = false;
608
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000609 size_t globalZ = 0;
610 args.root.traverseInZOrder(
611 [this, &globalZ](const LayerHierarchy&,
612 const LayerHierarchy::TraversalPath& traversalPath) -> bool {
613 LayerSnapshot* snapshot = getSnapshot(traversalPath);
614 if (!snapshot) {
Vishnu Naira02943f2023-06-03 13:44:46 -0700615 return true;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000616 }
617
Vishnu Naircfb2d252023-01-19 04:44:02 +0000618 if (snapshot->getIsVisible() || snapshot->hasInputInfo()) {
Vishnu Nair80a5a702023-02-11 01:21:51 +0000619 updateVisibility(*snapshot, snapshot->getIsVisible());
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000620 size_t oldZ = snapshot->globalZ;
621 size_t newZ = globalZ++;
622 snapshot->globalZ = newZ;
623 if (oldZ == newZ) {
624 return true;
625 }
626 mSnapshots[newZ]->globalZ = oldZ;
Vishnu Naircfb2d252023-01-19 04:44:02 +0000627 LLOGV(snapshot->sequence, "Made visible z=%zu -> %zu %s", oldZ, newZ,
628 snapshot->getDebugString().c_str());
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000629 std::iter_swap(mSnapshots.begin() + static_cast<ssize_t>(oldZ),
630 mSnapshots.begin() + static_cast<ssize_t>(newZ));
631 }
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000632 return true;
633 });
Vishnu Naircfb2d252023-01-19 04:44:02 +0000634 mNumInterestingSnapshots = (int)globalZ;
Vishnu Nairfccd6362023-02-24 23:39:53 +0000635 bool hasUnreachableSnapshots = false;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000636 while (globalZ < mSnapshots.size()) {
637 mSnapshots[globalZ]->globalZ = globalZ;
Vishnu Nair80a5a702023-02-11 01:21:51 +0000638 /* mark unreachable snapshots as explicitly invisible */
639 updateVisibility(*mSnapshots[globalZ], false);
Vishnu Naira02943f2023-06-03 13:44:46 -0700640 if (mSnapshots[globalZ]->reachablilty == LayerSnapshot::Reachablilty::Unreachable) {
Vishnu Nairfccd6362023-02-24 23:39:53 +0000641 hasUnreachableSnapshots = true;
642 }
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000643 globalZ++;
644 }
Vishnu Nairfccd6362023-02-24 23:39:53 +0000645 return hasUnreachableSnapshots;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000646}
647
648void LayerSnapshotBuilder::updateRelativeState(LayerSnapshot& snapshot,
649 const LayerSnapshot& parentSnapshot,
650 bool parentIsRelative, const Args& args) {
651 if (parentIsRelative) {
Vishnu Naircfb2d252023-01-19 04:44:02 +0000652 snapshot.isHiddenByPolicyFromRelativeParent =
653 parentSnapshot.isHiddenByPolicyFromParent || parentSnapshot.invalidTransform;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000654 if (args.includeMetadata) {
655 snapshot.relativeLayerMetadata = parentSnapshot.layerMetadata;
656 }
657 } else {
658 snapshot.isHiddenByPolicyFromRelativeParent =
659 parentSnapshot.isHiddenByPolicyFromRelativeParent;
660 if (args.includeMetadata) {
661 snapshot.relativeLayerMetadata = parentSnapshot.relativeLayerMetadata;
662 }
663 }
Vishnu Naira02943f2023-06-03 13:44:46 -0700664 if (snapshot.reachablilty == LayerSnapshot::Reachablilty::Unreachable) {
665 snapshot.reachablilty = LayerSnapshot::Reachablilty::ReachableByRelativeParent;
666 }
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000667}
668
Vishnu Nair42b918e2023-07-18 20:05:29 +0000669void LayerSnapshotBuilder::updateFrameRateFromChildSnapshot(LayerSnapshot& snapshot,
670 const LayerSnapshot& childSnapshot,
671 const Args& args) {
672 if (args.forceUpdate == ForceUpdateFlags::NONE &&
673 !childSnapshot.changes.any(RequestedLayerState::Changes::FrameRate |
674 RequestedLayerState::Changes::Hierarchy)) {
Vishnu Naircfb2d252023-01-19 04:44:02 +0000675 return;
676 }
Vishnu Naircfb2d252023-01-19 04:44:02 +0000677
Vishnu Nair42b918e2023-07-18 20:05:29 +0000678 using FrameRateCompatibility = scheduler::LayerInfo::FrameRateCompatibility;
679 if (snapshot.frameRate.rate.isValid() ||
680 snapshot.frameRate.type == FrameRateCompatibility::NoVote) {
681 // we already have a valid framerate.
682 return;
683 }
Vishnu Naircfb2d252023-01-19 04:44:02 +0000684
Vishnu Nair42b918e2023-07-18 20:05:29 +0000685 // We return whether this layer or its children has a vote. We ignore ExactOrMultiple votes
686 // for the same reason we are allowing touch boost for those layers. See
687 // RefreshRateSelector::rankFrameRates for details.
688 const auto layerVotedWithDefaultCompatibility = childSnapshot.frameRate.rate.isValid() &&
689 childSnapshot.frameRate.type == FrameRateCompatibility::Default;
690 const auto layerVotedWithNoVote =
691 childSnapshot.frameRate.type == FrameRateCompatibility::NoVote;
692 const auto layerVotedWithExactCompatibility = childSnapshot.frameRate.rate.isValid() &&
693 childSnapshot.frameRate.type == FrameRateCompatibility::Exact;
694
695 bool childHasValidFrameRate = layerVotedWithDefaultCompatibility || layerVotedWithNoVote ||
696 layerVotedWithExactCompatibility;
697
698 // If we don't have a valid frame rate, but the children do, we set this
699 // layer as NoVote to allow the children to control the refresh rate
700 if (childHasValidFrameRate) {
701 snapshot.frameRate = scheduler::LayerInfo::FrameRate(Fps(), FrameRateCompatibility::NoVote);
702 snapshot.changes |= RequestedLayerState::Changes::FrameRate;
Vishnu Naircfb2d252023-01-19 04:44:02 +0000703 }
704}
705
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000706void LayerSnapshotBuilder::resetRelativeState(LayerSnapshot& snapshot) {
707 snapshot.isHiddenByPolicyFromRelativeParent = false;
708 snapshot.relativeLayerMetadata.mMap.clear();
709}
710
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000711void LayerSnapshotBuilder::updateSnapshot(LayerSnapshot& snapshot, const Args& args,
712 const RequestedLayerState& requested,
713 const LayerSnapshot& parentSnapshot,
Vishnu Nair92990e22023-02-24 20:01:05 +0000714 const LayerHierarchy::TraversalPath& path) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000715 // Always update flags and visibility
716 ftl::Flags<RequestedLayerState::Changes> parentChanges = parentSnapshot.changes &
717 (RequestedLayerState::Changes::Hierarchy | RequestedLayerState::Changes::Geometry |
718 RequestedLayerState::Changes::Visibility | RequestedLayerState::Changes::Metadata |
Vishnu Naird47bcee2023-02-24 18:08:51 +0000719 RequestedLayerState::Changes::AffectsChildren |
Vishnu Naira02943f2023-06-03 13:44:46 -0700720 RequestedLayerState::Changes::FrameRate | RequestedLayerState::Changes::GameMode);
721 snapshot.changes |= parentChanges;
722 if (args.displayChanges) snapshot.changes |= RequestedLayerState::Changes::Geometry;
723 snapshot.reachablilty = LayerSnapshot::Reachablilty::Reachable;
724 snapshot.clientChanges |= (parentSnapshot.clientChanges & layer_state_t::AFFECTS_CHILDREN);
Vishnu Naircfb2d252023-01-19 04:44:02 +0000725 snapshot.isHiddenByPolicyFromParent = parentSnapshot.isHiddenByPolicyFromParent ||
Vishnu Nair3af0ec02023-02-10 04:13:48 +0000726 parentSnapshot.invalidTransform || requested.isHiddenByPolicy() ||
727 (args.excludeLayerIds.find(path.id) != args.excludeLayerIds.end());
Vishnu Nair80a5a702023-02-11 01:21:51 +0000728
Vishnu Nair92990e22023-02-24 20:01:05 +0000729 const bool forceUpdate = args.forceUpdate == ForceUpdateFlags::ALL ||
Vishnu Naira02943f2023-06-03 13:44:46 -0700730 snapshot.clientChanges & layer_state_t::eReparent ||
Vishnu Nair92990e22023-02-24 20:01:05 +0000731 snapshot.changes.any(RequestedLayerState::Changes::Visibility |
732 RequestedLayerState::Changes::Created);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000733
Vishnu Naira02943f2023-06-03 13:44:46 -0700734 if (forceUpdate || snapshot.clientChanges & layer_state_t::eLayerStackChanged) {
735 // If root layer, use the layer stack otherwise get the parent's layer stack.
736 snapshot.outputFilter.layerStack =
737 parentSnapshot.path == LayerHierarchy::TraversalPath::ROOT
738 ? requested.layerStack
739 : parentSnapshot.outputFilter.layerStack;
Vishnu Naircfb2d252023-01-19 04:44:02 +0000740 }
741
Vishnu Nair92990e22023-02-24 20:01:05 +0000742 if (snapshot.isHiddenByPolicyFromParent &&
743 !snapshot.changes.test(RequestedLayerState::Changes::Created)) {
Vishnu Naircfb2d252023-01-19 04:44:02 +0000744 if (forceUpdate ||
Vishnu Naira02943f2023-06-03 13:44:46 -0700745 snapshot.changes.any(RequestedLayerState::Changes::Geometry |
Vishnu Naircfb2d252023-01-19 04:44:02 +0000746 RequestedLayerState::Changes::Input)) {
747 updateInput(snapshot, requested, parentSnapshot, path, args);
748 }
749 return;
750 }
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000751
Vishnu Naira02943f2023-06-03 13:44:46 -0700752 if (forceUpdate || snapshot.changes.any(RequestedLayerState::Changes::Mirror)) {
753 // Display mirrors are always placed in a VirtualDisplay so we never want to capture layers
754 // marked as skip capture
755 snapshot.handleSkipScreenshotFlag = parentSnapshot.handleSkipScreenshotFlag ||
756 (requested.layerStackToMirror != ui::INVALID_LAYER_STACK);
757 }
758
759 if (forceUpdate || snapshot.clientChanges & layer_state_t::eAlphaChanged) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000760 snapshot.color.a = parentSnapshot.color.a * requested.color.a;
761 snapshot.alpha = snapshot.color.a;
Vishnu Nair29354ec2023-03-28 18:51:28 -0700762 snapshot.inputInfo.alpha = snapshot.color.a;
Vishnu Naira02943f2023-06-03 13:44:46 -0700763 }
Vishnu Nair29354ec2023-03-28 18:51:28 -0700764
Vishnu Naira02943f2023-06-03 13:44:46 -0700765 if (forceUpdate || snapshot.clientChanges & layer_state_t::eFlagsChanged) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000766 snapshot.isSecure =
767 parentSnapshot.isSecure || (requested.flags & layer_state_t::eLayerSecure);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000768 snapshot.outputFilter.toInternalDisplay = parentSnapshot.outputFilter.toInternalDisplay ||
769 (requested.flags & layer_state_t::eLayerSkipScreenshot);
Vishnu Naira02943f2023-06-03 13:44:46 -0700770 }
771
772 if (forceUpdate || snapshot.clientChanges & layer_state_t::eTrustedOverlayChanged) {
773 snapshot.isTrustedOverlay = parentSnapshot.isTrustedOverlay || requested.isTrustedOverlay;
774 }
775
776 if (forceUpdate || snapshot.clientChanges & layer_state_t::eStretchChanged) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000777 snapshot.stretchEffect = (requested.stretchEffect.hasEffect())
778 ? requested.stretchEffect
779 : parentSnapshot.stretchEffect;
Vishnu Naira02943f2023-06-03 13:44:46 -0700780 }
781
782 if (forceUpdate || snapshot.clientChanges & layer_state_t::eColorTransformChanged) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000783 if (!parentSnapshot.colorTransformIsIdentity) {
784 snapshot.colorTransform = parentSnapshot.colorTransform * requested.colorTransform;
785 snapshot.colorTransformIsIdentity = false;
786 } else {
787 snapshot.colorTransform = requested.colorTransform;
788 snapshot.colorTransformIsIdentity = !requested.hasColorTransform;
789 }
Vishnu Naira02943f2023-06-03 13:44:46 -0700790 }
791
792 if (forceUpdate || snapshot.changes.test(RequestedLayerState::Changes::GameMode)) {
Vishnu Naircfb2d252023-01-19 04:44:02 +0000793 snapshot.gameMode = requested.metadata.has(gui::METADATA_GAME_MODE)
794 ? requested.gameMode
795 : parentSnapshot.gameMode;
Vishnu Naira02943f2023-06-03 13:44:46 -0700796 updateMetadata(snapshot, requested, args);
797 if (args.includeMetadata) {
798 snapshot.layerMetadata = parentSnapshot.layerMetadata;
799 snapshot.layerMetadata.merge(requested.metadata);
800 }
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000801 }
802
Vishnu Naira02943f2023-06-03 13:44:46 -0700803 if (forceUpdate || snapshot.clientChanges & layer_state_t::eFixedTransformHintChanged ||
Vishnu Nairb76d99a2023-03-19 18:22:31 -0700804 args.displayChanges) {
805 snapshot.fixedTransformHint = requested.fixedTransformHint != ui::Transform::ROT_INVALID
806 ? requested.fixedTransformHint
807 : parentSnapshot.fixedTransformHint;
808
809 if (snapshot.fixedTransformHint != ui::Transform::ROT_INVALID) {
810 snapshot.transformHint = snapshot.fixedTransformHint;
811 } else {
812 const auto display = args.displays.get(snapshot.outputFilter.layerStack);
813 snapshot.transformHint = display.has_value()
814 ? std::make_optional<>(display->get().transformHint)
815 : std::nullopt;
816 }
817 }
818
Vishnu Nair42b918e2023-07-18 20:05:29 +0000819 if (forceUpdate ||
820 snapshot.changes.any(RequestedLayerState::Changes::FrameRate |
821 RequestedLayerState::Changes::Hierarchy)) {
Vishnu Naird47bcee2023-02-24 18:08:51 +0000822 snapshot.frameRate = (requested.requestedFrameRate.rate.isValid() ||
823 (requested.requestedFrameRate.type ==
824 scheduler::LayerInfo::FrameRateCompatibility::NoVote))
825 ? requested.requestedFrameRate
826 : parentSnapshot.frameRate;
827 }
828
Vishnu Nair3d8565a2023-06-30 07:23:24 +0000829 if (forceUpdate || snapshot.clientChanges & layer_state_t::eFrameRateSelectionPriority) {
830 snapshot.frameRateSelectionPriority =
831 (requested.frameRateSelectionPriority == Layer::PRIORITY_UNSET)
832 ? parentSnapshot.frameRateSelectionPriority
833 : requested.frameRateSelectionPriority;
834 }
835
Vishnu Naira02943f2023-06-03 13:44:46 -0700836 if (forceUpdate ||
837 snapshot.clientChanges &
838 (layer_state_t::eBackgroundBlurRadiusChanged | layer_state_t::eBlurRegionsChanged |
839 layer_state_t::eAlphaChanged)) {
Vishnu Nair80a5a702023-02-11 01:21:51 +0000840 snapshot.backgroundBlurRadius = args.supportsBlur
841 ? static_cast<int>(parentSnapshot.color.a * (float)requested.backgroundBlurRadius)
842 : 0;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000843 snapshot.blurRegions = requested.blurRegions;
Vishnu Nair80a5a702023-02-11 01:21:51 +0000844 for (auto& region : snapshot.blurRegions) {
845 region.alpha = region.alpha * snapshot.color.a;
846 }
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000847 }
848
Vishnu Naira02943f2023-06-03 13:44:46 -0700849 if (forceUpdate || snapshot.changes.any(RequestedLayerState::Changes::Geometry)) {
850 uint32_t primaryDisplayRotationFlags = getPrimaryDisplayRotationFlags(args.displays);
Vishnu Nairb76d99a2023-03-19 18:22:31 -0700851 updateLayerBounds(snapshot, requested, parentSnapshot, primaryDisplayRotationFlags);
Vishnu Naira02943f2023-06-03 13:44:46 -0700852 }
853
854 if (forceUpdate || snapshot.clientChanges & layer_state_t::eCornerRadiusChanged ||
855 snapshot.changes.any(RequestedLayerState::Changes::Geometry)) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000856 updateRoundedCorner(snapshot, requested, parentSnapshot);
857 }
858
Vishnu Naira02943f2023-06-03 13:44:46 -0700859 if (forceUpdate || snapshot.clientChanges & layer_state_t::eShadowRadiusChanged ||
860 snapshot.changes.any(RequestedLayerState::Changes::Geometry)) {
861 updateShadows(snapshot, requested, args.globalShadowSettings);
862 }
863
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000864 if (forceUpdate ||
Vishnu Naira02943f2023-06-03 13:44:46 -0700865 snapshot.changes.any(RequestedLayerState::Changes::Geometry |
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000866 RequestedLayerState::Changes::Input)) {
Vishnu Naircfb2d252023-01-19 04:44:02 +0000867 updateInput(snapshot, requested, parentSnapshot, path, args);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000868 }
869
870 // computed snapshot properties
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000871 snapshot.forceClientComposition = snapshot.isHdrY410 || snapshot.shadowSettings.length > 0 ||
872 requested.blurRegions.size() > 0 || snapshot.stretchEffect.hasEffect();
Vishnu Nairc765c6c2023-02-23 00:08:01 +0000873 snapshot.contentOpaque = snapshot.isContentOpaque();
874 snapshot.isOpaque = snapshot.contentOpaque && !snapshot.roundedCorner.hasRoundedCorners() &&
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000875 snapshot.color.a == 1.f;
876 snapshot.blendMode = getBlendMode(snapshot, requested);
Vishnu Naircfb2d252023-01-19 04:44:02 +0000877 LLOGV(snapshot.sequence,
Vishnu Nair92990e22023-02-24 20:01:05 +0000878 "%supdated %s changes:%s parent:%s requested:%s requested:%s from parent %s",
879 args.forceUpdate == ForceUpdateFlags::ALL ? "Force " : "",
880 snapshot.getDebugString().c_str(), snapshot.changes.string().c_str(),
881 parentSnapshot.changes.string().c_str(), requested.changes.string().c_str(),
882 std::to_string(requested.what).c_str(), parentSnapshot.getDebugString().c_str());
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000883}
884
885void LayerSnapshotBuilder::updateRoundedCorner(LayerSnapshot& snapshot,
886 const RequestedLayerState& requested,
887 const LayerSnapshot& parentSnapshot) {
888 snapshot.roundedCorner = RoundedCornerState();
889 RoundedCornerState parentRoundedCorner;
890 if (parentSnapshot.roundedCorner.hasRoundedCorners()) {
891 parentRoundedCorner = parentSnapshot.roundedCorner;
892 ui::Transform t = snapshot.localTransform.inverse();
893 parentRoundedCorner.cropRect = t.transform(parentRoundedCorner.cropRect);
894 parentRoundedCorner.radius.x *= t.getScaleX();
895 parentRoundedCorner.radius.y *= t.getScaleY();
896 }
897
898 FloatRect layerCropRect = snapshot.croppedBufferSize.toFloatRect();
899 const vec2 radius(requested.cornerRadius, requested.cornerRadius);
900 RoundedCornerState layerSettings(layerCropRect, radius);
901 const bool layerSettingsValid = layerSettings.hasRoundedCorners() && !layerCropRect.isEmpty();
902 const bool parentRoundedCornerValid = parentRoundedCorner.hasRoundedCorners();
903 if (layerSettingsValid && parentRoundedCornerValid) {
904 // If the parent and the layer have rounded corner settings, use the parent settings if
905 // the parent crop is entirely inside the layer crop. This has limitations and cause
906 // rendering artifacts. See b/200300845 for correct fix.
907 if (parentRoundedCorner.cropRect.left > layerCropRect.left &&
908 parentRoundedCorner.cropRect.top > layerCropRect.top &&
909 parentRoundedCorner.cropRect.right < layerCropRect.right &&
910 parentRoundedCorner.cropRect.bottom < layerCropRect.bottom) {
911 snapshot.roundedCorner = parentRoundedCorner;
912 } else {
913 snapshot.roundedCorner = layerSettings;
914 }
915 } else if (layerSettingsValid) {
916 snapshot.roundedCorner = layerSettings;
917 } else if (parentRoundedCornerValid) {
918 snapshot.roundedCorner = parentRoundedCorner;
919 }
920}
921
922void LayerSnapshotBuilder::updateLayerBounds(LayerSnapshot& snapshot,
923 const RequestedLayerState& requested,
924 const LayerSnapshot& parentSnapshot,
Vishnu Nairb76d99a2023-03-19 18:22:31 -0700925 uint32_t primaryDisplayRotationFlags) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000926 snapshot.geomLayerTransform = parentSnapshot.geomLayerTransform * snapshot.localTransform;
Vishnu Naircfb2d252023-01-19 04:44:02 +0000927 const bool transformWasInvalid = snapshot.invalidTransform;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000928 snapshot.invalidTransform = !LayerSnapshot::isTransformValid(snapshot.geomLayerTransform);
929 if (snapshot.invalidTransform) {
Vishnu Naircfb2d252023-01-19 04:44:02 +0000930 auto& t = snapshot.geomLayerTransform;
931 auto& requestedT = requested.requestedTransform;
932 std::string transformDebug =
933 base::StringPrintf(" transform={%f,%f,%f,%f} requestedTransform={%f,%f,%f,%f}",
934 t.dsdx(), t.dsdy(), t.dtdx(), t.dtdy(), requestedT.dsdx(),
935 requestedT.dsdy(), requestedT.dtdx(), requestedT.dtdy());
936 std::string bufferDebug;
937 if (requested.externalTexture) {
Vishnu Nairb76d99a2023-03-19 18:22:31 -0700938 auto unRotBuffer = requested.getUnrotatedBufferSize(primaryDisplayRotationFlags);
Vishnu Naircfb2d252023-01-19 04:44:02 +0000939 auto& destFrame = requested.destinationFrame;
940 bufferDebug = base::StringPrintf(" buffer={%d,%d} displayRot=%d"
941 " destFrame={%d,%d,%d,%d} unRotBuffer={%d,%d}",
942 requested.externalTexture->getWidth(),
943 requested.externalTexture->getHeight(),
Vishnu Nairb76d99a2023-03-19 18:22:31 -0700944 primaryDisplayRotationFlags, destFrame.left,
945 destFrame.top, destFrame.right, destFrame.bottom,
Vishnu Naircfb2d252023-01-19 04:44:02 +0000946 unRotBuffer.getHeight(), unRotBuffer.getWidth());
947 }
948 ALOGW("Resetting transform for %s because it is invalid.%s%s",
949 snapshot.getDebugString().c_str(), transformDebug.c_str(), bufferDebug.c_str());
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000950 snapshot.geomLayerTransform.reset();
951 }
Vishnu Naircfb2d252023-01-19 04:44:02 +0000952 if (transformWasInvalid != snapshot.invalidTransform) {
953 // If transform is invalid, the layer will be hidden.
954 mResortSnapshots = true;
955 }
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000956 snapshot.geomInverseLayerTransform = snapshot.geomLayerTransform.inverse();
957
958 FloatRect parentBounds = parentSnapshot.geomLayerBounds;
959 parentBounds = snapshot.localTransform.inverse().transform(parentBounds);
960 snapshot.geomLayerBounds =
961 (requested.externalTexture) ? snapshot.bufferSize.toFloatRect() : parentBounds;
962 if (!requested.crop.isEmpty()) {
963 snapshot.geomLayerBounds = snapshot.geomLayerBounds.intersect(requested.crop.toFloatRect());
964 }
965 snapshot.geomLayerBounds = snapshot.geomLayerBounds.intersect(parentBounds);
966 snapshot.transformedBounds = snapshot.geomLayerTransform.transform(snapshot.geomLayerBounds);
Vishnu Naircfb2d252023-01-19 04:44:02 +0000967 const Rect geomLayerBoundsWithoutTransparentRegion =
968 RequestedLayerState::reduce(Rect(snapshot.geomLayerBounds),
969 requested.transparentRegion);
970 snapshot.transformedBoundsWithoutTransparentRegion =
971 snapshot.geomLayerTransform.transform(geomLayerBoundsWithoutTransparentRegion);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000972 snapshot.parentTransform = parentSnapshot.geomLayerTransform;
973
974 // Subtract the transparent region and snap to the bounds
Vishnu Naircfb2d252023-01-19 04:44:02 +0000975 const Rect bounds =
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000976 RequestedLayerState::reduce(snapshot.croppedBufferSize, requested.transparentRegion);
Vishnu Naircfb2d252023-01-19 04:44:02 +0000977 if (requested.potentialCursor) {
978 snapshot.cursorFrame = snapshot.geomLayerTransform.transform(bounds);
979 }
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000980}
981
Vishnu Naira02943f2023-06-03 13:44:46 -0700982void LayerSnapshotBuilder::updateShadows(LayerSnapshot& snapshot, const RequestedLayerState&,
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000983 const renderengine::ShadowSettings& globalShadowSettings) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000984 if (snapshot.shadowRadius > 0.f) {
985 snapshot.shadowSettings = globalShadowSettings;
986
987 // Note: this preserves existing behavior of shadowing the entire layer and not cropping
988 // it if transparent regions are present. This may not be necessary since shadows are
989 // typically cast by layers without transparent regions.
990 snapshot.shadowSettings.boundaries = snapshot.geomLayerBounds;
991
992 // If the casting layer is translucent, we need to fill in the shadow underneath the
993 // layer. Otherwise the generated shadow will only be shown around the casting layer.
994 snapshot.shadowSettings.casterIsTranslucent =
995 !snapshot.isContentOpaque() || (snapshot.alpha < 1.0f);
996 snapshot.shadowSettings.ambientColor *= snapshot.alpha;
997 snapshot.shadowSettings.spotColor *= snapshot.alpha;
998 }
999}
1000
1001void LayerSnapshotBuilder::updateInput(LayerSnapshot& snapshot,
1002 const RequestedLayerState& requested,
1003 const LayerSnapshot& parentSnapshot,
Vishnu Naircfb2d252023-01-19 04:44:02 +00001004 const LayerHierarchy::TraversalPath& path,
1005 const Args& args) {
1006 if (requested.windowInfoHandle) {
1007 snapshot.inputInfo = *requested.windowInfoHandle->getInfo();
1008 } else {
1009 snapshot.inputInfo = {};
Vishnu Nair40d02282023-02-28 21:11:40 +00001010 // b/271132344 revisit this and see if we can always use the layers uid/pid
1011 snapshot.inputInfo.name = requested.name;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001012 snapshot.inputInfo.ownerUid = gui::Uid{requested.ownerUid};
Prabir Pradhane59c6dc2023-06-13 19:53:03 +00001013 snapshot.inputInfo.ownerPid = gui::Pid{requested.ownerPid};
Vishnu Naircfb2d252023-01-19 04:44:02 +00001014 }
Vishnu Nair29354ec2023-03-28 18:51:28 -07001015 snapshot.touchCropId = requested.touchCropId;
Vishnu Naircfb2d252023-01-19 04:44:02 +00001016
Vishnu Nair93b8b792023-02-27 19:40:24 +00001017 snapshot.inputInfo.id = static_cast<int32_t>(snapshot.uniqueSequence);
Vishnu Naird47bcee2023-02-24 18:08:51 +00001018 snapshot.inputInfo.displayId = static_cast<int32_t>(snapshot.outputFilter.layerStack.id);
Vishnu Nair29354ec2023-03-28 18:51:28 -07001019 updateVisibility(snapshot, snapshot.isVisible);
Vishnu Naircfb2d252023-01-19 04:44:02 +00001020 if (!needsInputInfo(snapshot, requested)) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +00001021 return;
1022 }
1023
Vishnu Naircfb2d252023-01-19 04:44:02 +00001024 static frontend::DisplayInfo sDefaultInfo = {.isSecure = false};
1025 const std::optional<frontend::DisplayInfo> displayInfoOpt =
1026 args.displays.get(snapshot.outputFilter.layerStack);
1027 bool noValidDisplay = !displayInfoOpt.has_value();
1028 auto displayInfo = displayInfoOpt.value_or(sDefaultInfo);
1029
1030 if (!requested.windowInfoHandle) {
1031 snapshot.inputInfo.inputConfig = gui::WindowInfo::InputConfig::NO_INPUT_CHANNEL;
1032 }
Vishnu Nair8fc721b2022-12-22 20:06:32 +00001033 fillInputFrameInfo(snapshot.inputInfo, displayInfo.transform, snapshot);
1034
1035 if (noValidDisplay) {
1036 // Do not let the window receive touches if it is not associated with a valid display
1037 // transform. We still allow the window to receive keys and prevent ANRs.
1038 snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::NOT_TOUCHABLE;
1039 }
1040
Vishnu Nair8fc721b2022-12-22 20:06:32 +00001041 snapshot.inputInfo.alpha = snapshot.color.a;
Vishnu Nair40d02282023-02-28 21:11:40 +00001042 snapshot.inputInfo.touchOcclusionMode = requested.hasInputInfo()
1043 ? requested.windowInfoHandle->getInfo()->touchOcclusionMode
1044 : parentSnapshot.inputInfo.touchOcclusionMode;
Vishnu Nair8fc721b2022-12-22 20:06:32 +00001045 if (requested.dropInputMode == gui::DropInputMode::ALL ||
1046 parentSnapshot.dropInputMode == gui::DropInputMode::ALL) {
1047 snapshot.dropInputMode = gui::DropInputMode::ALL;
1048 } else if (requested.dropInputMode == gui::DropInputMode::OBSCURED ||
1049 parentSnapshot.dropInputMode == gui::DropInputMode::OBSCURED) {
1050 snapshot.dropInputMode = gui::DropInputMode::OBSCURED;
1051 } else {
1052 snapshot.dropInputMode = gui::DropInputMode::NONE;
1053 }
1054
1055 handleDropInputMode(snapshot, parentSnapshot);
1056
1057 // If the window will be blacked out on a display because the display does not have the secure
1058 // flag and the layer has the secure flag set, then drop input.
1059 if (!displayInfo.isSecure && snapshot.isSecure) {
1060 snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::DROP_INPUT;
1061 }
1062
Vishnu Naira02943f2023-06-03 13:44:46 -07001063 if (requested.touchCropId != UNASSIGNED_LAYER_ID || path.isClone()) {
Vishnu Nair29354ec2023-03-28 18:51:28 -07001064 mNeedsTouchableRegionCrop.insert(path);
Vishnu Naira02943f2023-06-03 13:44:46 -07001065 }
1066 auto cropLayerSnapshot = getSnapshot(requested.touchCropId);
1067 if (!cropLayerSnapshot && snapshot.inputInfo.replaceTouchableRegionWithCrop) {
Vishnu Nair29354ec2023-03-28 18:51:28 -07001068 FloatRect inputBounds = getInputBounds(snapshot, /*fillParentBounds=*/true).first;
Vishnu Nairfed7c122023-03-18 01:54:43 +00001069 Rect inputBoundsInDisplaySpace =
Vishnu Nair29354ec2023-03-28 18:51:28 -07001070 getInputBoundsInDisplaySpace(snapshot, inputBounds, displayInfo.transform);
1071 snapshot.inputInfo.touchableRegion = Region(inputBoundsInDisplaySpace);
Vishnu Nair8fc721b2022-12-22 20:06:32 +00001072 }
1073
1074 // Inherit the trusted state from the parent hierarchy, but don't clobber the trusted state
1075 // if it was set by WM for a known system overlay
1076 if (snapshot.isTrustedOverlay) {
1077 snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::TRUSTED_OVERLAY;
1078 }
1079
1080 // If the layer is a clone, we need to crop the input region to cloned root to prevent
1081 // touches from going outside the cloned area.
1082 if (path.isClone()) {
1083 snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::CLONE;
Vishnu Nair444f3952023-04-11 13:01:02 -07001084 // Cloned layers shouldn't handle watch outside since their z order is not determined by
1085 // WM or the client.
1086 snapshot.inputInfo.inputConfig.clear(gui::WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH);
Vishnu Nair8fc721b2022-12-22 20:06:32 +00001087 }
1088}
1089
1090std::vector<std::unique_ptr<LayerSnapshot>>& LayerSnapshotBuilder::getSnapshots() {
1091 return mSnapshots;
1092}
1093
Vishnu Naircfb2d252023-01-19 04:44:02 +00001094void LayerSnapshotBuilder::forEachVisibleSnapshot(const ConstVisitor& visitor) const {
1095 for (int i = 0; i < mNumInterestingSnapshots; i++) {
1096 LayerSnapshot& snapshot = *mSnapshots[(size_t)i];
1097 if (!snapshot.isVisible) continue;
1098 visitor(snapshot);
1099 }
1100}
1101
Vishnu Nair3af0ec02023-02-10 04:13:48 +00001102// Visit each visible snapshot in z-order
1103void LayerSnapshotBuilder::forEachVisibleSnapshot(const ConstVisitor& visitor,
1104 const LayerHierarchy& root) const {
1105 root.traverseInZOrder(
1106 [this, visitor](const LayerHierarchy&,
1107 const LayerHierarchy::TraversalPath& traversalPath) -> bool {
1108 LayerSnapshot* snapshot = getSnapshot(traversalPath);
1109 if (snapshot && snapshot->isVisible) {
1110 visitor(*snapshot);
1111 }
1112 return true;
1113 });
1114}
1115
Vishnu Naircfb2d252023-01-19 04:44:02 +00001116void LayerSnapshotBuilder::forEachVisibleSnapshot(const Visitor& visitor) {
1117 for (int i = 0; i < mNumInterestingSnapshots; i++) {
1118 std::unique_ptr<LayerSnapshot>& snapshot = mSnapshots.at((size_t)i);
1119 if (!snapshot->isVisible) continue;
1120 visitor(snapshot);
1121 }
1122}
1123
1124void LayerSnapshotBuilder::forEachInputSnapshot(const ConstVisitor& visitor) const {
1125 for (int i = mNumInterestingSnapshots - 1; i >= 0; i--) {
1126 LayerSnapshot& snapshot = *mSnapshots[(size_t)i];
1127 if (!snapshot.hasInputInfo()) continue;
1128 visitor(snapshot);
1129 }
1130}
1131
Vishnu Nair29354ec2023-03-28 18:51:28 -07001132void LayerSnapshotBuilder::updateTouchableRegionCrop(const Args& args) {
1133 if (mNeedsTouchableRegionCrop.empty()) {
1134 return;
1135 }
1136
1137 static constexpr ftl::Flags<RequestedLayerState::Changes> AFFECTS_INPUT =
1138 RequestedLayerState::Changes::Visibility | RequestedLayerState::Changes::Created |
1139 RequestedLayerState::Changes::Hierarchy | RequestedLayerState::Changes::Geometry |
1140 RequestedLayerState::Changes::Input;
1141
1142 if (args.forceUpdate != ForceUpdateFlags::ALL &&
Vishnu Naira02943f2023-06-03 13:44:46 -07001143 !args.layerLifecycleManager.getGlobalChanges().any(AFFECTS_INPUT) && !args.displayChanges) {
Vishnu Nair29354ec2023-03-28 18:51:28 -07001144 return;
1145 }
1146
1147 for (auto& path : mNeedsTouchableRegionCrop) {
1148 frontend::LayerSnapshot* snapshot = getSnapshot(path);
1149 if (!snapshot) {
1150 continue;
1151 }
Vishnu Naira02943f2023-06-03 13:44:46 -07001152 LLOGV(snapshot->sequence, "updateTouchableRegionCrop=%s",
1153 snapshot->getDebugString().c_str());
Vishnu Nair29354ec2023-03-28 18:51:28 -07001154 const std::optional<frontend::DisplayInfo> displayInfoOpt =
1155 args.displays.get(snapshot->outputFilter.layerStack);
1156 static frontend::DisplayInfo sDefaultInfo = {.isSecure = false};
1157 auto displayInfo = displayInfoOpt.value_or(sDefaultInfo);
1158
1159 bool needsUpdate =
1160 args.forceUpdate == ForceUpdateFlags::ALL || snapshot->changes.any(AFFECTS_INPUT);
1161 auto cropLayerSnapshot = getSnapshot(snapshot->touchCropId);
1162 needsUpdate =
1163 needsUpdate || (cropLayerSnapshot && cropLayerSnapshot->changes.any(AFFECTS_INPUT));
1164 auto clonedRootSnapshot = path.isClone() ? getSnapshot(snapshot->mirrorRootPath) : nullptr;
1165 needsUpdate = needsUpdate ||
1166 (clonedRootSnapshot && clonedRootSnapshot->changes.any(AFFECTS_INPUT));
1167
1168 if (!needsUpdate) {
1169 continue;
1170 }
1171
1172 if (snapshot->inputInfo.replaceTouchableRegionWithCrop) {
1173 Rect inputBoundsInDisplaySpace;
1174 if (!cropLayerSnapshot) {
1175 FloatRect inputBounds = getInputBounds(*snapshot, /*fillParentBounds=*/true).first;
1176 inputBoundsInDisplaySpace =
1177 getInputBoundsInDisplaySpace(*snapshot, inputBounds, displayInfo.transform);
1178 } else {
1179 FloatRect inputBounds =
1180 getInputBounds(*cropLayerSnapshot, /*fillParentBounds=*/true).first;
1181 inputBoundsInDisplaySpace =
1182 getInputBoundsInDisplaySpace(*cropLayerSnapshot, inputBounds,
1183 displayInfo.transform);
1184 }
1185 snapshot->inputInfo.touchableRegion = Region(inputBoundsInDisplaySpace);
1186 } else if (cropLayerSnapshot) {
1187 FloatRect inputBounds =
1188 getInputBounds(*cropLayerSnapshot, /*fillParentBounds=*/true).first;
1189 Rect inputBoundsInDisplaySpace =
1190 getInputBoundsInDisplaySpace(*cropLayerSnapshot, inputBounds,
1191 displayInfo.transform);
1192 snapshot->inputInfo.touchableRegion = snapshot->inputInfo.touchableRegion.intersect(
1193 displayInfo.transform.transform(inputBoundsInDisplaySpace));
1194 }
1195
1196 // If the layer is a clone, we need to crop the input region to cloned root to prevent
1197 // touches from going outside the cloned area.
1198 if (clonedRootSnapshot) {
1199 const Rect rect =
1200 displayInfo.transform.transform(Rect{clonedRootSnapshot->transformedBounds});
1201 snapshot->inputInfo.touchableRegion =
1202 snapshot->inputInfo.touchableRegion.intersect(rect);
1203 }
1204 }
1205}
1206
Vishnu Nair8fc721b2022-12-22 20:06:32 +00001207} // namespace android::surfaceflinger::frontend