blob: 4e093816dda58aea1f4869bd3fb58f1c5533749f [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
Vishnu Nair9e0017e2024-05-22 19:02:44 +000025#include <common/FlagManager.h>
Vishnu Nairbe0ad902024-06-27 23:38:43 +000026#include <common/trace.h>
Dominik Laskowski6b049ff2023-01-29 15:46:45 -050027#include <ftl/small_map.h>
Vishnu Naira02943f2023-06-03 13:44:46 -070028#include <ui/DisplayMap.h>
Dominik Laskowski6b049ff2023-01-29 15:46:45 -050029#include <ui/FloatRect.h>
30
Vishnu Nair8fc721b2022-12-22 20:06:32 +000031#include "DisplayHardware/HWC2.h"
32#include "DisplayHardware/Hal.h"
Vishnu Nair3d8565a2023-06-30 07:23:24 +000033#include "Layer.h" // eFrameRateSelectionPriority constants
Vishnu Naircfb2d252023-01-19 04:44:02 +000034#include "LayerLog.h"
Vishnu Nairb76d99a2023-03-19 18:22:31 -070035#include "LayerSnapshotBuilder.h"
Vishnu Naircfb2d252023-01-19 04:44:02 +000036#include "TimeStats/TimeStats.h"
Vishnu Naird1f74982023-06-15 20:16:51 -070037#include "Tracing/TransactionTracing.h"
Vishnu Nair8fc721b2022-12-22 20:06:32 +000038
39namespace android::surfaceflinger::frontend {
40
41using namespace ftl::flag_operators;
42
43namespace {
Dominik Laskowski6b049ff2023-01-29 15:46:45 -050044
45FloatRect getMaxDisplayBounds(const DisplayInfos& displays) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +000046 const ui::Size maxSize = [&displays] {
47 if (displays.empty()) return ui::Size{5000, 5000};
48
49 return std::accumulate(displays.begin(), displays.end(), ui::kEmptySize,
50 [](ui::Size size, const auto& pair) -> ui::Size {
51 const auto& display = pair.second;
52 return {std::max(size.getWidth(), display.info.logicalWidth),
53 std::max(size.getHeight(), display.info.logicalHeight)};
54 });
55 }();
56
57 // Ignore display bounds for now since they will be computed later. Use a large Rect bound
58 // to ensure it's bigger than an actual display will be.
59 const float xMax = static_cast<float>(maxSize.getWidth()) * 10.f;
60 const float yMax = static_cast<float>(maxSize.getHeight()) * 10.f;
61
62 return {-xMax, -yMax, xMax, yMax};
63}
64
65// Applies the given transform to the region, while protecting against overflows caused by any
66// offsets. If applying the offset in the transform to any of the Rects in the region would result
67// in an overflow, they are not added to the output Region.
68Region transformTouchableRegionSafely(const ui::Transform& t, const Region& r,
69 const std::string& debugWindowName) {
70 // Round the translation using the same rounding strategy used by ui::Transform.
71 const auto tx = static_cast<int32_t>(t.tx() + 0.5);
72 const auto ty = static_cast<int32_t>(t.ty() + 0.5);
73
74 ui::Transform transformWithoutOffset = t;
75 transformWithoutOffset.set(0.f, 0.f);
76
77 const Region transformed = transformWithoutOffset.transform(r);
78
79 // Apply the translation to each of the Rects in the region while discarding any that overflow.
80 Region ret;
81 for (const auto& rect : transformed) {
82 Rect newRect;
83 if (__builtin_add_overflow(rect.left, tx, &newRect.left) ||
84 __builtin_add_overflow(rect.top, ty, &newRect.top) ||
85 __builtin_add_overflow(rect.right, tx, &newRect.right) ||
86 __builtin_add_overflow(rect.bottom, ty, &newRect.bottom)) {
87 ALOGE("Applying transform to touchable region of window '%s' resulted in an overflow.",
88 debugWindowName.c_str());
89 continue;
90 }
91 ret.orSelf(newRect);
92 }
93 return ret;
94}
95
96/*
97 * We don't want to send the layer's transform to input, but rather the
98 * parent's transform. This is because Layer's transform is
99 * information about how the buffer is placed on screen. The parent's
100 * transform makes more sense to send since it's information about how the
101 * layer is placed on screen. This transform is used by input to determine
102 * how to go from screen space back to window space.
103 */
104ui::Transform getInputTransform(const LayerSnapshot& snapshot) {
105 if (!snapshot.hasBufferOrSidebandStream()) {
106 return snapshot.geomLayerTransform;
107 }
108 return snapshot.parentTransform;
109}
110
111/**
Vishnu Nairfed7c122023-03-18 01:54:43 +0000112 * Returns the bounds used to fill the input frame and the touchable region.
113 *
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000114 * Similar to getInputTransform, we need to update the bounds to include the transform.
115 * This is because bounds don't include the buffer transform, where the input assumes
116 * that's already included.
117 */
Vishnu Nairfed7c122023-03-18 01:54:43 +0000118std::pair<FloatRect, bool> getInputBounds(const LayerSnapshot& snapshot, bool fillParentBounds) {
119 FloatRect inputBounds = snapshot.croppedBufferSize.toFloatRect();
120 if (snapshot.hasBufferOrSidebandStream() && snapshot.croppedBufferSize.isValid() &&
121 snapshot.localTransform.getType() != ui::Transform::IDENTITY) {
122 inputBounds = snapshot.localTransform.transform(inputBounds);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000123 }
124
Vishnu Nairfed7c122023-03-18 01:54:43 +0000125 bool inputBoundsValid = snapshot.croppedBufferSize.isValid();
126 if (!inputBoundsValid) {
127 /**
128 * Input bounds are based on the layer crop or buffer size. But if we are using
129 * the layer bounds as the input bounds (replaceTouchableRegionWithCrop flag) then
130 * we can use the parent bounds as the input bounds if the layer does not have buffer
131 * or a crop. We want to unify this logic but because of compat reasons we cannot always
132 * use the parent bounds. A layer without a buffer can get input. So when a window is
133 * initially added, its touchable region can fill its parent layer bounds and that can
134 * have negative consequences.
135 */
136 inputBounds = fillParentBounds ? snapshot.geomLayerBounds : FloatRect{};
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000137 }
Vishnu Nairfed7c122023-03-18 01:54:43 +0000138
139 // Clamp surface inset to the input bounds.
140 const float inset = static_cast<float>(snapshot.inputInfo.surfaceInset);
141 const float xSurfaceInset = std::clamp(inset, 0.f, inputBounds.getWidth() / 2.f);
142 const float ySurfaceInset = std::clamp(inset, 0.f, inputBounds.getHeight() / 2.f);
143
144 // Apply the insets to the input bounds.
145 inputBounds.left += xSurfaceInset;
146 inputBounds.top += ySurfaceInset;
147 inputBounds.right -= xSurfaceInset;
148 inputBounds.bottom -= ySurfaceInset;
149 return {inputBounds, inputBoundsValid};
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000150}
151
Vishnu Nairfed7c122023-03-18 01:54:43 +0000152Rect getInputBoundsInDisplaySpace(const LayerSnapshot& snapshot, const FloatRect& insetBounds,
153 const ui::Transform& screenToDisplay) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000154 // InputDispatcher works in the display device's coordinate space. Here, we calculate the
155 // frame and transform used for the layer, which determines the bounds and the coordinate space
156 // within which the layer will receive input.
Vishnu Nairfed7c122023-03-18 01:54:43 +0000157
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000158 // Coordinate space definitions:
159 // - display: The display device's coordinate space. Correlates to pixels on the display.
160 // - screen: The post-rotation coordinate space for the display, a.k.a. logical display space.
161 // - layer: The coordinate space of this layer.
162 // - input: The coordinate space in which this layer will receive input events. This could be
163 // different than layer space if a surfaceInset is used, which changes the origin
164 // of the input space.
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000165
166 // Crop the input bounds to ensure it is within the parent's bounds.
Vishnu Nairfed7c122023-03-18 01:54:43 +0000167 const FloatRect croppedInsetBoundsInLayer = snapshot.geomLayerBounds.intersect(insetBounds);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000168
169 const ui::Transform layerToScreen = getInputTransform(snapshot);
170 const ui::Transform layerToDisplay = screenToDisplay * layerToScreen;
171
Vishnu Nairfed7c122023-03-18 01:54:43 +0000172 return Rect{layerToDisplay.transform(croppedInsetBoundsInLayer)};
173}
174
175void fillInputFrameInfo(gui::WindowInfo& info, const ui::Transform& screenToDisplay,
176 const LayerSnapshot& snapshot) {
177 auto [inputBounds, inputBoundsValid] = getInputBounds(snapshot, /*fillParentBounds=*/false);
178 if (!inputBoundsValid) {
179 info.touchableRegion.clear();
180 }
181
Chavi Weingarten7f019192023-08-08 20:39:01 +0000182 info.frame = getInputBoundsInDisplaySpace(snapshot, inputBounds, screenToDisplay);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000183
184 ui::Transform inputToLayer;
Vishnu Nairfed7c122023-03-18 01:54:43 +0000185 inputToLayer.set(inputBounds.left, inputBounds.top);
186 const ui::Transform layerToScreen = getInputTransform(snapshot);
187 const ui::Transform inputToDisplay = screenToDisplay * layerToScreen * inputToLayer;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000188
189 // InputDispatcher expects a display-to-input transform.
190 info.transform = inputToDisplay.inverse();
191
192 // The touchable region is specified in the input coordinate space. Change it to display space.
193 info.touchableRegion =
194 transformTouchableRegionSafely(inputToDisplay, info.touchableRegion, snapshot.name);
195}
196
197void handleDropInputMode(LayerSnapshot& snapshot, const LayerSnapshot& parentSnapshot) {
198 if (snapshot.inputInfo.inputConfig.test(gui::WindowInfo::InputConfig::NO_INPUT_CHANNEL)) {
199 return;
200 }
201
202 // Check if we need to drop input unconditionally
203 const gui::DropInputMode dropInputMode = snapshot.dropInputMode;
204 if (dropInputMode == gui::DropInputMode::ALL) {
205 snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::DROP_INPUT;
206 ALOGV("Dropping input for %s as requested by policy.", snapshot.name.c_str());
207 return;
208 }
209
210 // Check if we need to check if the window is obscured by parent
211 if (dropInputMode != gui::DropInputMode::OBSCURED) {
212 return;
213 }
214
215 // Check if the parent has set an alpha on the layer
216 if (parentSnapshot.color.a != 1.0_hf) {
217 snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::DROP_INPUT;
218 ALOGV("Dropping input for %s as requested by policy because alpha=%f",
219 snapshot.name.c_str(), static_cast<float>(parentSnapshot.color.a));
220 }
221
222 // Check if the parent has cropped the buffer
223 Rect bufferSize = snapshot.croppedBufferSize;
224 if (!bufferSize.isValid()) {
225 snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED;
226 return;
227 }
228
229 // Screenbounds are the layer bounds cropped by parents, transformed to screenspace.
230 // To check if the layer has been cropped, we take the buffer bounds, apply the local
231 // layer crop and apply the same set of transforms to move to screenspace. If the bounds
232 // match then the layer has not been cropped by its parents.
233 Rect bufferInScreenSpace(snapshot.geomLayerTransform.transform(bufferSize));
234 bool croppedByParent = bufferInScreenSpace != Rect{snapshot.transformedBounds};
235
236 if (croppedByParent) {
237 snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::DROP_INPUT;
238 ALOGV("Dropping input for %s as requested by policy because buffer is cropped by parent",
239 snapshot.name.c_str());
240 } else {
241 // If the layer is not obscured by its parents (by setting an alpha or crop), then only drop
242 // input if the window is obscured. This check should be done in surfaceflinger but the
243 // logic currently resides in inputflinger. So pass the if_obscured check to input to only
244 // drop input events if the window is obscured.
245 snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED;
246 }
247}
248
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000249auto getBlendMode(const LayerSnapshot& snapshot, const RequestedLayerState& requested) {
250 auto blendMode = Hwc2::IComposerClient::BlendMode::NONE;
251 if (snapshot.alpha != 1.0f || !snapshot.isContentOpaque()) {
252 blendMode = requested.premultipliedAlpha ? Hwc2::IComposerClient::BlendMode::PREMULTIPLIED
253 : Hwc2::IComposerClient::BlendMode::COVERAGE;
254 }
255 return blendMode;
256}
257
Vishnu Nair80a5a702023-02-11 01:21:51 +0000258void updateVisibility(LayerSnapshot& snapshot, bool visible) {
Vishnu Nairb4a6a772024-06-12 14:41:08 -0700259 if (snapshot.isVisible != visible) {
260 snapshot.changes |= RequestedLayerState::Changes::Visibility;
261 }
Vishnu Nair80a5a702023-02-11 01:21:51 +0000262 snapshot.isVisible = visible;
Vishnu Naircfb2d252023-01-19 04:44:02 +0000263
264 // TODO(b/238781169) we are ignoring this compat for now, since we will have
265 // to remove any optimization based on visibility.
266
267 // For compatibility reasons we let layers which can receive input
268 // receive input before they have actually submitted a buffer. Because
269 // of this we use canReceiveInput instead of isVisible to check the
270 // policy-visibility, ignoring the buffer state. However for layers with
271 // hasInputInfo()==false we can use the real visibility state.
272 // We are just using these layers for occlusion detection in
273 // InputDispatcher, and obviously if they aren't visible they can't occlude
274 // anything.
Vishnu Nair80a5a702023-02-11 01:21:51 +0000275 const bool visibleForInput =
Vishnu Nair40d02282023-02-28 21:11:40 +0000276 snapshot.hasInputInfo() ? snapshot.canReceiveInput() : snapshot.isVisible;
Vishnu Nair80a5a702023-02-11 01:21:51 +0000277 snapshot.inputInfo.setInputConfig(gui::WindowInfo::InputConfig::NOT_VISIBLE, !visibleForInput);
Vishnu Naira02943f2023-06-03 13:44:46 -0700278 LLOGV(snapshot.sequence, "updating visibility %s %s", visible ? "true" : "false",
279 snapshot.getDebugString().c_str());
Vishnu Naircfb2d252023-01-19 04:44:02 +0000280}
281
282bool needsInputInfo(const LayerSnapshot& snapshot, const RequestedLayerState& requested) {
283 if (requested.potentialCursor) {
284 return false;
285 }
286
287 if (snapshot.inputInfo.token != nullptr) {
288 return true;
289 }
290
291 if (snapshot.hasBufferOrSidebandStream()) {
292 return true;
293 }
294
295 return requested.windowInfoHandle &&
296 requested.windowInfoHandle->getInfo()->inputConfig.test(
297 gui::WindowInfo::InputConfig::NO_INPUT_CHANNEL);
298}
299
Vishnu Nairc765c6c2023-02-23 00:08:01 +0000300void updateMetadata(LayerSnapshot& snapshot, const RequestedLayerState& requested,
301 const LayerSnapshotBuilder::Args& args) {
302 snapshot.metadata.clear();
303 for (const auto& [key, mandatory] : args.supportedLayerGenericMetadata) {
304 auto compatIter = args.genericLayerMetadataKeyMap.find(key);
305 if (compatIter == std::end(args.genericLayerMetadataKeyMap)) {
306 continue;
307 }
308 const uint32_t id = compatIter->second;
309 auto it = requested.metadata.mMap.find(id);
310 if (it == std::end(requested.metadata.mMap)) {
311 continue;
312 }
313
314 snapshot.metadata.emplace(key,
315 compositionengine::GenericLayerMetadataEntry{mandatory,
316 it->second});
317 }
318}
319
Nergi Rahardi0dfc0962024-05-23 06:57:36 +0000320void updateMetadataAndGameMode(LayerSnapshot& snapshot, const RequestedLayerState& requested,
321 const LayerSnapshotBuilder::Args& args,
322 const LayerSnapshot& parentSnapshot) {
323 if (snapshot.changes.test(RequestedLayerState::Changes::GameMode)) {
324 snapshot.gameMode = requested.metadata.has(gui::METADATA_GAME_MODE)
325 ? requested.gameMode
326 : parentSnapshot.gameMode;
327 }
328 updateMetadata(snapshot, requested, args);
329 if (args.includeMetadata) {
330 snapshot.layerMetadata = parentSnapshot.layerMetadata;
331 snapshot.layerMetadata.merge(requested.metadata);
332 }
333}
334
Vishnu Naircfb2d252023-01-19 04:44:02 +0000335void clearChanges(LayerSnapshot& snapshot) {
336 snapshot.changes.clear();
Vishnu Naira02943f2023-06-03 13:44:46 -0700337 snapshot.clientChanges = 0;
Vishnu Naircfb2d252023-01-19 04:44:02 +0000338 snapshot.contentDirty = false;
339 snapshot.hasReadyFrame = false;
340 snapshot.sidebandStreamHasFrame = false;
341 snapshot.surfaceDamage.clear();
342}
343
Vishnu Naira02943f2023-06-03 13:44:46 -0700344// TODO (b/259407931): Remove.
345uint32_t getPrimaryDisplayRotationFlags(
346 const ui::DisplayMap<ui::LayerStack, frontend::DisplayInfo>& displays) {
347 for (auto& [_, display] : displays) {
348 if (display.isPrimary) {
349 return display.rotationFlags;
350 }
351 }
352 return 0;
353}
354
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000355} // namespace
356
357LayerSnapshot LayerSnapshotBuilder::getRootSnapshot() {
358 LayerSnapshot snapshot;
Vishnu Nair92990e22023-02-24 20:01:05 +0000359 snapshot.path = LayerHierarchy::TraversalPath::ROOT;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000360 snapshot.changes = ftl::Flags<RequestedLayerState::Changes>();
Vishnu Naira02943f2023-06-03 13:44:46 -0700361 snapshot.clientChanges = 0;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000362 snapshot.isHiddenByPolicyFromParent = false;
363 snapshot.isHiddenByPolicyFromRelativeParent = false;
364 snapshot.parentTransform.reset();
365 snapshot.geomLayerTransform.reset();
366 snapshot.geomInverseLayerTransform.reset();
367 snapshot.geomLayerBounds = getMaxDisplayBounds({});
368 snapshot.roundedCorner = RoundedCornerState();
369 snapshot.stretchEffect = {};
Marzia Favarodcc9d9b2024-01-10 10:17:00 +0000370 snapshot.edgeExtensionEffect = {};
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000371 snapshot.outputFilter.layerStack = ui::DEFAULT_LAYER_STACK;
372 snapshot.outputFilter.toInternalDisplay = false;
373 snapshot.isSecure = false;
374 snapshot.color.a = 1.0_hf;
375 snapshot.colorTransformIsIdentity = true;
Vishnu Naird9e4f462023-10-06 04:05:45 +0000376 snapshot.shadowSettings.length = 0.f;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000377 snapshot.layerMetadata.mMap.clear();
378 snapshot.relativeLayerMetadata.mMap.clear();
379 snapshot.inputInfo.touchOcclusionMode = gui::TouchOcclusionMode::BLOCK_UNTRUSTED;
380 snapshot.dropInputMode = gui::DropInputMode::NONE;
Vishnu Nair9e0017e2024-05-22 19:02:44 +0000381 snapshot.trustedOverlay = gui::TrustedOverlay::UNSET;
Vishnu Naircfb2d252023-01-19 04:44:02 +0000382 snapshot.gameMode = gui::GameMode::Unsupported;
383 snapshot.frameRate = {};
384 snapshot.fixedTransformHint = ui::Transform::ROT_INVALID;
Vishnu Nair422b81c2024-05-16 05:44:28 +0000385 snapshot.ignoreLocalTransform = false;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000386 return snapshot;
387}
388
Chavi Weingarten4aa22af2023-11-17 19:37:07 +0000389LayerSnapshotBuilder::LayerSnapshotBuilder() {}
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000390
391LayerSnapshotBuilder::LayerSnapshotBuilder(Args args) : LayerSnapshotBuilder() {
Vishnu Naird47bcee2023-02-24 18:08:51 +0000392 args.forceUpdate = ForceUpdateFlags::ALL;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000393 updateSnapshots(args);
394}
395
396bool LayerSnapshotBuilder::tryFastUpdate(const Args& args) {
Vishnu Naira02943f2023-06-03 13:44:46 -0700397 const bool forceUpdate = args.forceUpdate != ForceUpdateFlags::NONE;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000398
Vishnu Naira02943f2023-06-03 13:44:46 -0700399 if (args.layerLifecycleManager.getGlobalChanges().get() == 0 && !forceUpdate &&
400 !args.displayChanges) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000401 return true;
402 }
403
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000404 // There are only content changes which do not require any child layer snapshots to be updated.
405 ALOGV("%s", __func__);
Vishnu Nairbe0ad902024-06-27 23:38:43 +0000406 SFTRACE_NAME("FastPath");
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000407
Vishnu Naira02943f2023-06-03 13:44:46 -0700408 uint32_t primaryDisplayRotationFlags = getPrimaryDisplayRotationFlags(args.displays);
409 if (forceUpdate || args.displayChanges) {
410 for (auto& snapshot : mSnapshots) {
411 const RequestedLayerState* requested =
412 args.layerLifecycleManager.getLayerFromId(snapshot->path.id);
413 if (!requested) continue;
414 snapshot->merge(*requested, forceUpdate, args.displayChanges, args.forceFullDamage,
415 primaryDisplayRotationFlags);
416 }
417 return false;
418 }
419
420 // Walk through all the updated requested layer states and update the corresponding snapshots.
421 for (const RequestedLayerState* requested : args.layerLifecycleManager.getChangedLayers()) {
422 auto range = mIdToSnapshots.equal_range(requested->id);
423 for (auto it = range.first; it != range.second; it++) {
424 it->second->merge(*requested, forceUpdate, args.displayChanges, args.forceFullDamage,
425 primaryDisplayRotationFlags);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000426 }
427 }
428
Vishnu Naira02943f2023-06-03 13:44:46 -0700429 if ((args.layerLifecycleManager.getGlobalChanges().get() &
430 ~(RequestedLayerState::Changes::Content | RequestedLayerState::Changes::Buffer).get()) !=
431 0) {
432 // We have changes that require us to walk the hierarchy and update child layers.
433 // No fast path for you.
434 return false;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000435 }
436 return true;
437}
438
439void LayerSnapshotBuilder::updateSnapshots(const Args& args) {
Vishnu Nairbe0ad902024-06-27 23:38:43 +0000440 SFTRACE_NAME("UpdateSnapshots");
Chavi Weingarten4aa22af2023-11-17 19:37:07 +0000441 LayerSnapshot rootSnapshot = args.rootSnapshot;
Vishnu Nair3af0ec02023-02-10 04:13:48 +0000442 if (args.parentCrop) {
Chavi Weingarten4aa22af2023-11-17 19:37:07 +0000443 rootSnapshot.geomLayerBounds = *args.parentCrop;
Vishnu Naird47bcee2023-02-24 18:08:51 +0000444 } else if (args.forceUpdate == ForceUpdateFlags::ALL || args.displayChanges) {
Chavi Weingarten4aa22af2023-11-17 19:37:07 +0000445 rootSnapshot.geomLayerBounds = getMaxDisplayBounds(args.displays);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000446 }
447 if (args.displayChanges) {
Chavi Weingarten4aa22af2023-11-17 19:37:07 +0000448 rootSnapshot.changes = RequestedLayerState::Changes::AffectsChildren |
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000449 RequestedLayerState::Changes::Geometry;
450 }
Vishnu Naird47bcee2023-02-24 18:08:51 +0000451 if (args.forceUpdate == ForceUpdateFlags::HIERARCHY) {
Chavi Weingarten4aa22af2023-11-17 19:37:07 +0000452 rootSnapshot.changes |=
Vishnu Naird47bcee2023-02-24 18:08:51 +0000453 RequestedLayerState::Changes::Hierarchy | RequestedLayerState::Changes::Visibility;
Chavi Weingarten4aa22af2023-11-17 19:37:07 +0000454 rootSnapshot.clientChanges |= layer_state_t::eReparent;
Vishnu Naird47bcee2023-02-24 18:08:51 +0000455 }
Vishnu Naira02943f2023-06-03 13:44:46 -0700456
457 for (auto& snapshot : mSnapshots) {
458 if (snapshot->reachablilty == LayerSnapshot::Reachablilty::Reachable) {
459 snapshot->reachablilty = LayerSnapshot::Reachablilty::Unreachable;
460 }
461 }
462
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000463 LayerHierarchy::TraversalPath root = LayerHierarchy::TraversalPath::ROOT;
Vishnu Naird47bcee2023-02-24 18:08:51 +0000464 if (args.root.getLayer()) {
465 // The hierarchy can have a root layer when used for screenshots otherwise, it will have
466 // multiple children.
467 LayerHierarchy::ScopedAddToTraversalPath addChildToPath(root, args.root.getLayer()->id,
468 LayerHierarchy::Variant::Attached);
Chavi Weingarten4aa22af2023-11-17 19:37:07 +0000469 updateSnapshotsInHierarchy(args, args.root, root, rootSnapshot, /*depth=*/0);
Vishnu Naird47bcee2023-02-24 18:08:51 +0000470 } else {
471 for (auto& [childHierarchy, variant] : args.root.mChildren) {
472 LayerHierarchy::ScopedAddToTraversalPath addChildToPath(root,
473 childHierarchy->getLayer()->id,
474 variant);
Chavi Weingarten4aa22af2023-11-17 19:37:07 +0000475 updateSnapshotsInHierarchy(args, *childHierarchy, root, rootSnapshot, /*depth=*/0);
Vishnu Naird47bcee2023-02-24 18:08:51 +0000476 }
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000477 }
478
Vishnu Nair29354ec2023-03-28 18:51:28 -0700479 // Update touchable region crops outside the main update pass. This is because a layer could be
480 // cropped by any other layer and it requires both snapshots to be updated.
481 updateTouchableRegionCrop(args);
482
Vishnu Nairfccd6362023-02-24 23:39:53 +0000483 const bool hasUnreachableSnapshots = sortSnapshotsByZ(args);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000484
Vishnu Nair29354ec2023-03-28 18:51:28 -0700485 // Destroy unreachable snapshots for clone layers. And destroy snapshots for non-clone
486 // layers if the layer have been destroyed.
487 // TODO(b/238781169) consider making clone layer ids stable as well
488 if (!hasUnreachableSnapshots && args.layerLifecycleManager.getDestroyedLayers().empty()) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000489 return;
490 }
491
Vishnu Nair29354ec2023-03-28 18:51:28 -0700492 std::unordered_set<uint32_t> destroyedLayerIds;
493 for (auto& destroyedLayer : args.layerLifecycleManager.getDestroyedLayers()) {
494 destroyedLayerIds.insert(destroyedLayer->id);
495 }
496
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000497 auto it = mSnapshots.begin();
498 while (it < mSnapshots.end()) {
499 auto& traversalPath = it->get()->path;
Vishnu Naira02943f2023-06-03 13:44:46 -0700500 const bool unreachable =
501 it->get()->reachablilty == LayerSnapshot::Reachablilty::Unreachable;
502 const bool isClone = traversalPath.isClone();
503 const bool layerIsDestroyed =
504 destroyedLayerIds.find(traversalPath.id) != destroyedLayerIds.end();
505 const bool destroySnapshot = (unreachable && isClone) || layerIsDestroyed;
506
507 if (!destroySnapshot) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000508 it++;
509 continue;
510 }
511
Vishnu Naira02943f2023-06-03 13:44:46 -0700512 mPathToSnapshot.erase(traversalPath);
513
514 auto range = mIdToSnapshots.equal_range(traversalPath.id);
515 auto matchingSnapshot =
516 std::find_if(range.first, range.second, [&traversalPath](auto& snapshotWithId) {
517 return snapshotWithId.second->path == traversalPath;
518 });
519 mIdToSnapshots.erase(matchingSnapshot);
Vishnu Nair29354ec2023-03-28 18:51:28 -0700520 mNeedsTouchableRegionCrop.erase(traversalPath);
Vishnu Naircfb2d252023-01-19 04:44:02 +0000521 mSnapshots.back()->globalZ = it->get()->globalZ;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000522 std::iter_swap(it, mSnapshots.end() - 1);
523 mSnapshots.erase(mSnapshots.end() - 1);
524 }
525}
526
527void LayerSnapshotBuilder::update(const Args& args) {
Vishnu Nair92990e22023-02-24 20:01:05 +0000528 for (auto& snapshot : mSnapshots) {
529 clearChanges(*snapshot);
530 }
531
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000532 if (tryFastUpdate(args)) {
533 return;
534 }
535 updateSnapshots(args);
536}
537
Vishnu Naircfb2d252023-01-19 04:44:02 +0000538const LayerSnapshot& LayerSnapshotBuilder::updateSnapshotsInHierarchy(
539 const Args& args, const LayerHierarchy& hierarchy,
Vishnu Naird1f74982023-06-15 20:16:51 -0700540 LayerHierarchy::TraversalPath& traversalPath, const LayerSnapshot& parentSnapshot,
541 int depth) {
Vishnu Nair606d9d02023-08-19 14:20:18 -0700542 LLOG_ALWAYS_FATAL_WITH_TRACE_IF(depth > 50,
543 "Cycle detected in LayerSnapshotBuilder. See "
544 "builder_stack_overflow_transactions.winscope");
Vishnu Naird1f74982023-06-15 20:16:51 -0700545
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000546 const RequestedLayerState* layer = hierarchy.getLayer();
Vishnu Naircfb2d252023-01-19 04:44:02 +0000547 LayerSnapshot* snapshot = getSnapshot(traversalPath);
548 const bool newSnapshot = snapshot == nullptr;
Vishnu Naira02943f2023-06-03 13:44:46 -0700549 uint32_t primaryDisplayRotationFlags = getPrimaryDisplayRotationFlags(args.displays);
Vishnu Naircfb2d252023-01-19 04:44:02 +0000550 if (newSnapshot) {
Vishnu Nair92990e22023-02-24 20:01:05 +0000551 snapshot = createSnapshot(traversalPath, *layer, parentSnapshot);
Vishnu Naira02943f2023-06-03 13:44:46 -0700552 snapshot->merge(*layer, /*forceUpdate=*/true, /*displayChanges=*/true, args.forceFullDamage,
553 primaryDisplayRotationFlags);
554 snapshot->changes |= RequestedLayerState::Changes::Created;
Vishnu Naircfb2d252023-01-19 04:44:02 +0000555 }
Vishnu Nair52d56fd2023-07-20 17:02:43 +0000556
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000557 if (traversalPath.isRelative()) {
558 bool parentIsRelative = traversalPath.variant == LayerHierarchy::Variant::Relative;
559 updateRelativeState(*snapshot, parentSnapshot, parentIsRelative, args);
560 } else {
561 if (traversalPath.isAttached()) {
562 resetRelativeState(*snapshot);
563 }
Vishnu Nair92990e22023-02-24 20:01:05 +0000564 updateSnapshot(*snapshot, args, *layer, parentSnapshot, traversalPath);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000565 }
566
567 for (auto& [childHierarchy, variant] : hierarchy.mChildren) {
568 LayerHierarchy::ScopedAddToTraversalPath addChildToPath(traversalPath,
569 childHierarchy->getLayer()->id,
570 variant);
Vishnu Naircfb2d252023-01-19 04:44:02 +0000571 const LayerSnapshot& childSnapshot =
Vishnu Naird1f74982023-06-15 20:16:51 -0700572 updateSnapshotsInHierarchy(args, *childHierarchy, traversalPath, *snapshot,
573 depth + 1);
Vishnu Nair42b918e2023-07-18 20:05:29 +0000574 updateFrameRateFromChildSnapshot(*snapshot, childSnapshot, args);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000575 }
Vishnu Naird47bcee2023-02-24 18:08:51 +0000576
Vishnu Naircfb2d252023-01-19 04:44:02 +0000577 return *snapshot;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000578}
579
580LayerSnapshot* LayerSnapshotBuilder::getSnapshot(uint32_t layerId) const {
581 if (layerId == UNASSIGNED_LAYER_ID) {
582 return nullptr;
583 }
584 LayerHierarchy::TraversalPath path{.id = layerId};
585 return getSnapshot(path);
586}
587
588LayerSnapshot* LayerSnapshotBuilder::getSnapshot(const LayerHierarchy::TraversalPath& id) const {
Vishnu Naira02943f2023-06-03 13:44:46 -0700589 auto it = mPathToSnapshot.find(id);
590 return it == mPathToSnapshot.end() ? nullptr : it->second;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000591}
592
Vishnu Nair92990e22023-02-24 20:01:05 +0000593LayerSnapshot* LayerSnapshotBuilder::createSnapshot(const LayerHierarchy::TraversalPath& path,
594 const RequestedLayerState& layer,
595 const LayerSnapshot& parentSnapshot) {
596 mSnapshots.emplace_back(std::make_unique<LayerSnapshot>(layer, path));
Vishnu Naircfb2d252023-01-19 04:44:02 +0000597 LayerSnapshot* snapshot = mSnapshots.back().get();
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000598 snapshot->globalZ = static_cast<size_t>(mSnapshots.size()) - 1;
Vishnu Nair491827d2024-04-29 23:43:26 +0000599 if (path.isClone() && !LayerHierarchy::isMirror(path.variant)) {
Vishnu Nair92990e22023-02-24 20:01:05 +0000600 snapshot->mirrorRootPath = parentSnapshot.mirrorRootPath;
601 }
Vishnu Nair491827d2024-04-29 23:43:26 +0000602 snapshot->ignoreLocalTransform =
603 path.isClone() && path.variant == LayerHierarchy::Variant::Detached_Mirror;
Vishnu Naira02943f2023-06-03 13:44:46 -0700604 mPathToSnapshot[path] = snapshot;
605
606 mIdToSnapshots.emplace(path.id, snapshot);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000607 return snapshot;
608}
609
Vishnu Nairfccd6362023-02-24 23:39:53 +0000610bool LayerSnapshotBuilder::sortSnapshotsByZ(const Args& args) {
Vishnu Naird47bcee2023-02-24 18:08:51 +0000611 if (!mResortSnapshots && args.forceUpdate == ForceUpdateFlags::NONE &&
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000612 !args.layerLifecycleManager.getGlobalChanges().any(
Chavi Weingarten92c7d8c2024-01-19 23:25:45 +0000613 RequestedLayerState::Changes::Hierarchy | RequestedLayerState::Changes::Visibility |
614 RequestedLayerState::Changes::Input)) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000615 // We are not force updating and there are no hierarchy or visibility changes. Avoid sorting
616 // the snapshots.
Vishnu Nairfccd6362023-02-24 23:39:53 +0000617 return false;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000618 }
Vishnu Naircfb2d252023-01-19 04:44:02 +0000619 mResortSnapshots = false;
620
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000621 size_t globalZ = 0;
622 args.root.traverseInZOrder(
623 [this, &globalZ](const LayerHierarchy&,
624 const LayerHierarchy::TraversalPath& traversalPath) -> bool {
625 LayerSnapshot* snapshot = getSnapshot(traversalPath);
626 if (!snapshot) {
Vishnu Naira02943f2023-06-03 13:44:46 -0700627 return true;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000628 }
629
Vishnu Naircfb2d252023-01-19 04:44:02 +0000630 if (snapshot->getIsVisible() || snapshot->hasInputInfo()) {
Vishnu Nair80a5a702023-02-11 01:21:51 +0000631 updateVisibility(*snapshot, snapshot->getIsVisible());
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000632 size_t oldZ = snapshot->globalZ;
633 size_t newZ = globalZ++;
634 snapshot->globalZ = newZ;
635 if (oldZ == newZ) {
636 return true;
637 }
638 mSnapshots[newZ]->globalZ = oldZ;
Vishnu Naircfb2d252023-01-19 04:44:02 +0000639 LLOGV(snapshot->sequence, "Made visible z=%zu -> %zu %s", oldZ, newZ,
640 snapshot->getDebugString().c_str());
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000641 std::iter_swap(mSnapshots.begin() + static_cast<ssize_t>(oldZ),
642 mSnapshots.begin() + static_cast<ssize_t>(newZ));
643 }
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000644 return true;
645 });
Vishnu Naircfb2d252023-01-19 04:44:02 +0000646 mNumInterestingSnapshots = (int)globalZ;
Vishnu Nairfccd6362023-02-24 23:39:53 +0000647 bool hasUnreachableSnapshots = false;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000648 while (globalZ < mSnapshots.size()) {
649 mSnapshots[globalZ]->globalZ = globalZ;
Vishnu Nair80a5a702023-02-11 01:21:51 +0000650 /* mark unreachable snapshots as explicitly invisible */
651 updateVisibility(*mSnapshots[globalZ], false);
Vishnu Naira02943f2023-06-03 13:44:46 -0700652 if (mSnapshots[globalZ]->reachablilty == LayerSnapshot::Reachablilty::Unreachable) {
Vishnu Nairfccd6362023-02-24 23:39:53 +0000653 hasUnreachableSnapshots = true;
654 }
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000655 globalZ++;
656 }
Vishnu Nairfccd6362023-02-24 23:39:53 +0000657 return hasUnreachableSnapshots;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000658}
659
660void LayerSnapshotBuilder::updateRelativeState(LayerSnapshot& snapshot,
661 const LayerSnapshot& parentSnapshot,
662 bool parentIsRelative, const Args& args) {
663 if (parentIsRelative) {
Vishnu Naircfb2d252023-01-19 04:44:02 +0000664 snapshot.isHiddenByPolicyFromRelativeParent =
665 parentSnapshot.isHiddenByPolicyFromParent || parentSnapshot.invalidTransform;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000666 if (args.includeMetadata) {
667 snapshot.relativeLayerMetadata = parentSnapshot.layerMetadata;
668 }
669 } else {
670 snapshot.isHiddenByPolicyFromRelativeParent =
671 parentSnapshot.isHiddenByPolicyFromRelativeParent;
672 if (args.includeMetadata) {
673 snapshot.relativeLayerMetadata = parentSnapshot.relativeLayerMetadata;
674 }
675 }
Vishnu Naira02943f2023-06-03 13:44:46 -0700676 if (snapshot.reachablilty == LayerSnapshot::Reachablilty::Unreachable) {
677 snapshot.reachablilty = LayerSnapshot::Reachablilty::ReachableByRelativeParent;
678 }
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000679}
680
Vishnu Nair42b918e2023-07-18 20:05:29 +0000681void LayerSnapshotBuilder::updateFrameRateFromChildSnapshot(LayerSnapshot& snapshot,
682 const LayerSnapshot& childSnapshot,
683 const Args& args) {
684 if (args.forceUpdate == ForceUpdateFlags::NONE &&
Vishnu Nair52d56fd2023-07-20 17:02:43 +0000685 !args.layerLifecycleManager.getGlobalChanges().any(
686 RequestedLayerState::Changes::Hierarchy) &&
687 !childSnapshot.changes.any(RequestedLayerState::Changes::FrameRate) &&
688 !snapshot.changes.any(RequestedLayerState::Changes::FrameRate)) {
Vishnu Naircfb2d252023-01-19 04:44:02 +0000689 return;
690 }
Vishnu Naircfb2d252023-01-19 04:44:02 +0000691
Vishnu Nair3fbe3262023-09-29 17:07:00 -0700692 using FrameRateCompatibility = scheduler::FrameRateCompatibility;
Rachel Leece6e0042023-06-27 11:22:54 -0700693 if (snapshot.frameRate.isValid()) {
Vishnu Nair42b918e2023-07-18 20:05:29 +0000694 // we already have a valid framerate.
695 return;
696 }
Vishnu Naircfb2d252023-01-19 04:44:02 +0000697
Vishnu Nair42b918e2023-07-18 20:05:29 +0000698 // We return whether this layer or its children has a vote. We ignore ExactOrMultiple votes
699 // for the same reason we are allowing touch boost for those layers. See
700 // RefreshRateSelector::rankFrameRates for details.
Rachel Leece6e0042023-06-27 11:22:54 -0700701 const auto layerVotedWithDefaultCompatibility = childSnapshot.frameRate.vote.rate.isValid() &&
702 childSnapshot.frameRate.vote.type == FrameRateCompatibility::Default;
Vishnu Nair42b918e2023-07-18 20:05:29 +0000703 const auto layerVotedWithNoVote =
Rachel Leece6e0042023-06-27 11:22:54 -0700704 childSnapshot.frameRate.vote.type == FrameRateCompatibility::NoVote;
705 const auto layerVotedWithCategory =
706 childSnapshot.frameRate.category != FrameRateCategory::Default;
707 const auto layerVotedWithExactCompatibility = childSnapshot.frameRate.vote.rate.isValid() &&
708 childSnapshot.frameRate.vote.type == FrameRateCompatibility::Exact;
Vishnu Nair42b918e2023-07-18 20:05:29 +0000709
710 bool childHasValidFrameRate = layerVotedWithDefaultCompatibility || layerVotedWithNoVote ||
Rachel Leece6e0042023-06-27 11:22:54 -0700711 layerVotedWithCategory || layerVotedWithExactCompatibility;
Vishnu Nair42b918e2023-07-18 20:05:29 +0000712
713 // If we don't have a valid frame rate, but the children do, we set this
714 // layer as NoVote to allow the children to control the refresh rate
715 if (childHasValidFrameRate) {
716 snapshot.frameRate = scheduler::LayerInfo::FrameRate(Fps(), FrameRateCompatibility::NoVote);
717 snapshot.changes |= RequestedLayerState::Changes::FrameRate;
Vishnu Naircfb2d252023-01-19 04:44:02 +0000718 }
719}
720
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000721void LayerSnapshotBuilder::resetRelativeState(LayerSnapshot& snapshot) {
722 snapshot.isHiddenByPolicyFromRelativeParent = false;
723 snapshot.relativeLayerMetadata.mMap.clear();
724}
725
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000726void LayerSnapshotBuilder::updateSnapshot(LayerSnapshot& snapshot, const Args& args,
727 const RequestedLayerState& requested,
728 const LayerSnapshot& parentSnapshot,
Vishnu Nair92990e22023-02-24 20:01:05 +0000729 const LayerHierarchy::TraversalPath& path) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000730 // Always update flags and visibility
731 ftl::Flags<RequestedLayerState::Changes> parentChanges = parentSnapshot.changes &
732 (RequestedLayerState::Changes::Hierarchy | RequestedLayerState::Changes::Geometry |
733 RequestedLayerState::Changes::Visibility | RequestedLayerState::Changes::Metadata |
Vishnu Nairf13c8982023-12-02 11:26:09 -0800734 RequestedLayerState::Changes::AffectsChildren | RequestedLayerState::Changes::Input |
Vishnu Naira02943f2023-06-03 13:44:46 -0700735 RequestedLayerState::Changes::FrameRate | RequestedLayerState::Changes::GameMode);
736 snapshot.changes |= parentChanges;
737 if (args.displayChanges) snapshot.changes |= RequestedLayerState::Changes::Geometry;
738 snapshot.reachablilty = LayerSnapshot::Reachablilty::Reachable;
739 snapshot.clientChanges |= (parentSnapshot.clientChanges & layer_state_t::AFFECTS_CHILDREN);
Vishnu Naircfb2d252023-01-19 04:44:02 +0000740 snapshot.isHiddenByPolicyFromParent = parentSnapshot.isHiddenByPolicyFromParent ||
Vishnu Nair3af0ec02023-02-10 04:13:48 +0000741 parentSnapshot.invalidTransform || requested.isHiddenByPolicy() ||
742 (args.excludeLayerIds.find(path.id) != args.excludeLayerIds.end());
Vishnu Nair80a5a702023-02-11 01:21:51 +0000743
Vishnu Nair92990e22023-02-24 20:01:05 +0000744 const bool forceUpdate = args.forceUpdate == ForceUpdateFlags::ALL ||
Vishnu Naira02943f2023-06-03 13:44:46 -0700745 snapshot.clientChanges & layer_state_t::eReparent ||
Vishnu Nair92990e22023-02-24 20:01:05 +0000746 snapshot.changes.any(RequestedLayerState::Changes::Visibility |
747 RequestedLayerState::Changes::Created);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000748
Vishnu Naira02943f2023-06-03 13:44:46 -0700749 if (forceUpdate || snapshot.clientChanges & layer_state_t::eLayerStackChanged) {
750 // If root layer, use the layer stack otherwise get the parent's layer stack.
751 snapshot.outputFilter.layerStack =
752 parentSnapshot.path == LayerHierarchy::TraversalPath::ROOT
753 ? requested.layerStack
754 : parentSnapshot.outputFilter.layerStack;
Vishnu Naircfb2d252023-01-19 04:44:02 +0000755 }
756
Chavi Weingartenb74093a2023-10-11 20:29:59 +0000757 if (forceUpdate || snapshot.clientChanges & layer_state_t::eTrustedOverlayChanged) {
Vishnu Nair9e0017e2024-05-22 19:02:44 +0000758 switch (requested.trustedOverlay) {
759 case gui::TrustedOverlay::UNSET:
760 snapshot.trustedOverlay = parentSnapshot.trustedOverlay;
761 break;
762 case gui::TrustedOverlay::DISABLED:
763 snapshot.trustedOverlay = FlagManager::getInstance().override_trusted_overlay()
764 ? requested.trustedOverlay
765 : parentSnapshot.trustedOverlay;
766 break;
767 case gui::TrustedOverlay::ENABLED:
768 snapshot.trustedOverlay = requested.trustedOverlay;
769 break;
770 }
Chavi Weingartenb74093a2023-10-11 20:29:59 +0000771 }
772
Vishnu Nair92990e22023-02-24 20:01:05 +0000773 if (snapshot.isHiddenByPolicyFromParent &&
774 !snapshot.changes.test(RequestedLayerState::Changes::Created)) {
Vishnu Naircfb2d252023-01-19 04:44:02 +0000775 if (forceUpdate ||
Vishnu Naira02943f2023-06-03 13:44:46 -0700776 snapshot.changes.any(RequestedLayerState::Changes::Geometry |
Vishnu Nair494a2e42023-11-10 17:21:19 -0800777 RequestedLayerState::Changes::BufferSize |
Vishnu Naircfb2d252023-01-19 04:44:02 +0000778 RequestedLayerState::Changes::Input)) {
779 updateInput(snapshot, requested, parentSnapshot, path, args);
780 }
Nergi Rahardi0dfc0962024-05-23 06:57:36 +0000781 if (forceUpdate ||
782 (args.includeMetadata &&
783 snapshot.changes.test(RequestedLayerState::Changes::Metadata))) {
784 updateMetadataAndGameMode(snapshot, requested, args, parentSnapshot);
785 }
Vishnu Naircfb2d252023-01-19 04:44:02 +0000786 return;
787 }
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000788
Vishnu Naira02943f2023-06-03 13:44:46 -0700789 if (forceUpdate || snapshot.changes.any(RequestedLayerState::Changes::Mirror)) {
790 // Display mirrors are always placed in a VirtualDisplay so we never want to capture layers
791 // marked as skip capture
792 snapshot.handleSkipScreenshotFlag = parentSnapshot.handleSkipScreenshotFlag ||
793 (requested.layerStackToMirror != ui::INVALID_LAYER_STACK);
794 }
795
796 if (forceUpdate || snapshot.clientChanges & layer_state_t::eAlphaChanged) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000797 snapshot.color.a = parentSnapshot.color.a * requested.color.a;
798 snapshot.alpha = snapshot.color.a;
Vishnu Nair29354ec2023-03-28 18:51:28 -0700799 snapshot.inputInfo.alpha = snapshot.color.a;
Vishnu Naira02943f2023-06-03 13:44:46 -0700800 }
Vishnu Nair29354ec2023-03-28 18:51:28 -0700801
Vishnu Naira02943f2023-06-03 13:44:46 -0700802 if (forceUpdate || snapshot.clientChanges & layer_state_t::eFlagsChanged) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000803 snapshot.isSecure =
804 parentSnapshot.isSecure || (requested.flags & layer_state_t::eLayerSecure);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000805 snapshot.outputFilter.toInternalDisplay = parentSnapshot.outputFilter.toInternalDisplay ||
806 (requested.flags & layer_state_t::eLayerSkipScreenshot);
Vishnu Naira02943f2023-06-03 13:44:46 -0700807 }
808
Vishnu Naira02943f2023-06-03 13:44:46 -0700809 if (forceUpdate || snapshot.clientChanges & layer_state_t::eStretchChanged) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000810 snapshot.stretchEffect = (requested.stretchEffect.hasEffect())
811 ? requested.stretchEffect
812 : parentSnapshot.stretchEffect;
Vishnu Naira02943f2023-06-03 13:44:46 -0700813 }
814
Marzia Favarodcc9d9b2024-01-10 10:17:00 +0000815 if (forceUpdate ||
816 (snapshot.clientChanges | parentSnapshot.clientChanges) &
817 layer_state_t::eEdgeExtensionChanged) {
818 if (requested.edgeExtensionParameters.extendLeft ||
819 requested.edgeExtensionParameters.extendRight ||
820 requested.edgeExtensionParameters.extendTop ||
821 requested.edgeExtensionParameters.extendBottom) {
822 // This is the root layer to which the extension is applied
823 snapshot.edgeExtensionEffect =
824 EdgeExtensionEffect(requested.edgeExtensionParameters.extendLeft,
825 requested.edgeExtensionParameters.extendRight,
826 requested.edgeExtensionParameters.extendTop,
827 requested.edgeExtensionParameters.extendBottom);
828 } else if (parentSnapshot.clientChanges & layer_state_t::eEdgeExtensionChanged) {
829 // Extension is inherited
830 snapshot.edgeExtensionEffect = parentSnapshot.edgeExtensionEffect;
831 } else {
832 // There is no edge extension
833 snapshot.edgeExtensionEffect.reset();
834 }
835 if (snapshot.edgeExtensionEffect.hasEffect()) {
836 snapshot.clientChanges |= layer_state_t::eEdgeExtensionChanged;
837 snapshot.changes |= RequestedLayerState::Changes::Geometry;
838 }
839 }
840
Vishnu Naira02943f2023-06-03 13:44:46 -0700841 if (forceUpdate || snapshot.clientChanges & layer_state_t::eColorTransformChanged) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000842 if (!parentSnapshot.colorTransformIsIdentity) {
843 snapshot.colorTransform = parentSnapshot.colorTransform * requested.colorTransform;
844 snapshot.colorTransformIsIdentity = false;
845 } else {
846 snapshot.colorTransform = requested.colorTransform;
847 snapshot.colorTransformIsIdentity = !requested.hasColorTransform;
848 }
Vishnu Naira02943f2023-06-03 13:44:46 -0700849 }
850
Nergi Rahardi27613c32024-05-23 06:57:02 +0000851 if (forceUpdate || snapshot.changes.test(RequestedLayerState::Changes::Metadata)) {
Nergi Rahardi0dfc0962024-05-23 06:57:36 +0000852 updateMetadataAndGameMode(snapshot, requested, args, parentSnapshot);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000853 }
854
Vishnu Naira02943f2023-06-03 13:44:46 -0700855 if (forceUpdate || snapshot.clientChanges & layer_state_t::eFixedTransformHintChanged ||
Vishnu Nairb76d99a2023-03-19 18:22:31 -0700856 args.displayChanges) {
857 snapshot.fixedTransformHint = requested.fixedTransformHint != ui::Transform::ROT_INVALID
858 ? requested.fixedTransformHint
859 : parentSnapshot.fixedTransformHint;
860
861 if (snapshot.fixedTransformHint != ui::Transform::ROT_INVALID) {
862 snapshot.transformHint = snapshot.fixedTransformHint;
863 } else {
864 const auto display = args.displays.get(snapshot.outputFilter.layerStack);
865 snapshot.transformHint = display.has_value()
866 ? std::make_optional<>(display->get().transformHint)
867 : std::nullopt;
868 }
869 }
870
Vishnu Nair42b918e2023-07-18 20:05:29 +0000871 if (forceUpdate ||
Vishnu Nair52d56fd2023-07-20 17:02:43 +0000872 args.layerLifecycleManager.getGlobalChanges().any(
873 RequestedLayerState::Changes::Hierarchy) ||
Vishnu Nair42b918e2023-07-18 20:05:29 +0000874 snapshot.changes.any(RequestedLayerState::Changes::FrameRate |
875 RequestedLayerState::Changes::Hierarchy)) {
Rachel Leea021bb02023-11-20 21:51:09 -0800876 const bool shouldOverrideChildren = parentSnapshot.frameRateSelectionStrategy ==
Rachel Lee58cc90d2023-09-05 18:50:20 -0700877 scheduler::LayerInfo::FrameRateSelectionStrategy::OverrideChildren;
Rachel Leea021bb02023-11-20 21:51:09 -0800878 const bool propagationAllowed = parentSnapshot.frameRateSelectionStrategy !=
Rachel Lee70f7b692023-11-22 11:24:02 -0800879 scheduler::LayerInfo::FrameRateSelectionStrategy::Self;
Rachel Leea021bb02023-11-20 21:51:09 -0800880 if ((!requested.requestedFrameRate.isValid() && propagationAllowed) ||
881 shouldOverrideChildren) {
Vishnu Nair30515cb2023-10-19 21:54:08 -0700882 snapshot.inheritedFrameRate = parentSnapshot.inheritedFrameRate;
883 } else {
884 snapshot.inheritedFrameRate = requested.requestedFrameRate;
885 }
886 // Set the framerate as the inherited frame rate and allow children to override it if
887 // needed.
888 snapshot.frameRate = snapshot.inheritedFrameRate;
Vishnu Nair52d56fd2023-07-20 17:02:43 +0000889 snapshot.changes |= RequestedLayerState::Changes::FrameRate;
Vishnu Naird47bcee2023-02-24 18:08:51 +0000890 }
891
Rachel Lee58cc90d2023-09-05 18:50:20 -0700892 if (forceUpdate || snapshot.clientChanges & layer_state_t::eFrameRateSelectionStrategyChanged) {
Rachel Leea021bb02023-11-20 21:51:09 -0800893 if (parentSnapshot.frameRateSelectionStrategy ==
894 scheduler::LayerInfo::FrameRateSelectionStrategy::OverrideChildren) {
895 snapshot.frameRateSelectionStrategy =
896 scheduler::LayerInfo::FrameRateSelectionStrategy::OverrideChildren;
897 } else {
898 const auto strategy = scheduler::LayerInfo::convertFrameRateSelectionStrategy(
899 requested.frameRateSelectionStrategy);
900 snapshot.frameRateSelectionStrategy = strategy;
901 }
Rachel Lee58cc90d2023-09-05 18:50:20 -0700902 }
903
Vishnu Nair3d8565a2023-06-30 07:23:24 +0000904 if (forceUpdate || snapshot.clientChanges & layer_state_t::eFrameRateSelectionPriority) {
905 snapshot.frameRateSelectionPriority =
906 (requested.frameRateSelectionPriority == Layer::PRIORITY_UNSET)
907 ? parentSnapshot.frameRateSelectionPriority
908 : requested.frameRateSelectionPriority;
909 }
910
Vishnu Naira02943f2023-06-03 13:44:46 -0700911 if (forceUpdate ||
912 snapshot.clientChanges &
913 (layer_state_t::eBackgroundBlurRadiusChanged | layer_state_t::eBlurRegionsChanged |
914 layer_state_t::eAlphaChanged)) {
Vishnu Nair80a5a702023-02-11 01:21:51 +0000915 snapshot.backgroundBlurRadius = args.supportsBlur
916 ? static_cast<int>(parentSnapshot.color.a * (float)requested.backgroundBlurRadius)
917 : 0;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000918 snapshot.blurRegions = requested.blurRegions;
Vishnu Nair80a5a702023-02-11 01:21:51 +0000919 for (auto& region : snapshot.blurRegions) {
920 region.alpha = region.alpha * snapshot.color.a;
921 }
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000922 }
923
Vishnu Naira02943f2023-06-03 13:44:46 -0700924 if (forceUpdate || snapshot.changes.any(RequestedLayerState::Changes::Geometry)) {
925 uint32_t primaryDisplayRotationFlags = getPrimaryDisplayRotationFlags(args.displays);
Vishnu Nairb76d99a2023-03-19 18:22:31 -0700926 updateLayerBounds(snapshot, requested, parentSnapshot, primaryDisplayRotationFlags);
Vishnu Naira02943f2023-06-03 13:44:46 -0700927 }
928
Marzia Favarodcc9d9b2024-01-10 10:17:00 +0000929 if (snapshot.edgeExtensionEffect.hasEffect()) {
930 updateBoundsForEdgeExtension(snapshot);
931 }
932
Vishnu Naira02943f2023-06-03 13:44:46 -0700933 if (forceUpdate || snapshot.clientChanges & layer_state_t::eCornerRadiusChanged ||
Vishnu Nair0808ae62023-08-07 21:42:42 -0700934 snapshot.changes.any(RequestedLayerState::Changes::Geometry |
935 RequestedLayerState::Changes::BufferUsageFlags)) {
936 updateRoundedCorner(snapshot, requested, parentSnapshot, args);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000937 }
938
Vishnu Naira02943f2023-06-03 13:44:46 -0700939 if (forceUpdate || snapshot.clientChanges & layer_state_t::eShadowRadiusChanged ||
940 snapshot.changes.any(RequestedLayerState::Changes::Geometry)) {
941 updateShadows(snapshot, requested, args.globalShadowSettings);
942 }
943
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000944 if (forceUpdate ||
Vishnu Naira02943f2023-06-03 13:44:46 -0700945 snapshot.changes.any(RequestedLayerState::Changes::Geometry |
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000946 RequestedLayerState::Changes::Input)) {
Vishnu Naircfb2d252023-01-19 04:44:02 +0000947 updateInput(snapshot, requested, parentSnapshot, path, args);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000948 }
949
950 // computed snapshot properties
Marzia Favarodcc9d9b2024-01-10 10:17:00 +0000951 snapshot.forceClientComposition = snapshot.shadowSettings.length > 0 ||
952 snapshot.stretchEffect.hasEffect() || snapshot.edgeExtensionEffect.hasEffect();
Vishnu Nairc765c6c2023-02-23 00:08:01 +0000953 snapshot.contentOpaque = snapshot.isContentOpaque();
954 snapshot.isOpaque = snapshot.contentOpaque && !snapshot.roundedCorner.hasRoundedCorners() &&
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000955 snapshot.color.a == 1.f;
956 snapshot.blendMode = getBlendMode(snapshot, requested);
Vishnu Naircfb2d252023-01-19 04:44:02 +0000957 LLOGV(snapshot.sequence,
Vishnu Nair92990e22023-02-24 20:01:05 +0000958 "%supdated %s changes:%s parent:%s requested:%s requested:%s from parent %s",
959 args.forceUpdate == ForceUpdateFlags::ALL ? "Force " : "",
960 snapshot.getDebugString().c_str(), snapshot.changes.string().c_str(),
961 parentSnapshot.changes.string().c_str(), requested.changes.string().c_str(),
962 std::to_string(requested.what).c_str(), parentSnapshot.getDebugString().c_str());
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000963}
964
965void LayerSnapshotBuilder::updateRoundedCorner(LayerSnapshot& snapshot,
966 const RequestedLayerState& requested,
Vishnu Nair0808ae62023-08-07 21:42:42 -0700967 const LayerSnapshot& parentSnapshot,
968 const Args& args) {
969 if (args.skipRoundCornersWhenProtected && requested.isProtected()) {
970 snapshot.roundedCorner = RoundedCornerState();
971 return;
972 }
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000973 snapshot.roundedCorner = RoundedCornerState();
974 RoundedCornerState parentRoundedCorner;
975 if (parentSnapshot.roundedCorner.hasRoundedCorners()) {
976 parentRoundedCorner = parentSnapshot.roundedCorner;
977 ui::Transform t = snapshot.localTransform.inverse();
978 parentRoundedCorner.cropRect = t.transform(parentRoundedCorner.cropRect);
979 parentRoundedCorner.radius.x *= t.getScaleX();
980 parentRoundedCorner.radius.y *= t.getScaleY();
981 }
982
983 FloatRect layerCropRect = snapshot.croppedBufferSize.toFloatRect();
984 const vec2 radius(requested.cornerRadius, requested.cornerRadius);
985 RoundedCornerState layerSettings(layerCropRect, radius);
986 const bool layerSettingsValid = layerSettings.hasRoundedCorners() && !layerCropRect.isEmpty();
987 const bool parentRoundedCornerValid = parentRoundedCorner.hasRoundedCorners();
988 if (layerSettingsValid && parentRoundedCornerValid) {
989 // If the parent and the layer have rounded corner settings, use the parent settings if
990 // the parent crop is entirely inside the layer crop. This has limitations and cause
991 // rendering artifacts. See b/200300845 for correct fix.
992 if (parentRoundedCorner.cropRect.left > layerCropRect.left &&
993 parentRoundedCorner.cropRect.top > layerCropRect.top &&
994 parentRoundedCorner.cropRect.right < layerCropRect.right &&
995 parentRoundedCorner.cropRect.bottom < layerCropRect.bottom) {
996 snapshot.roundedCorner = parentRoundedCorner;
997 } else {
998 snapshot.roundedCorner = layerSettings;
999 }
1000 } else if (layerSettingsValid) {
1001 snapshot.roundedCorner = layerSettings;
1002 } else if (parentRoundedCornerValid) {
1003 snapshot.roundedCorner = parentRoundedCorner;
1004 }
1005}
1006
Marzia Favarodcc9d9b2024-01-10 10:17:00 +00001007/**
1008 * According to the edges that we are requested to extend, we increase the bounds to the maximum
1009 * extension allowed by the crop (parent crop + requested crop). The animation that called
1010 * Transition#setEdgeExtensionEffect is in charge of setting the requested crop.
1011 * @param snapshot
1012 */
1013void LayerSnapshotBuilder::updateBoundsForEdgeExtension(LayerSnapshot& snapshot) {
1014 EdgeExtensionEffect& effect = snapshot.edgeExtensionEffect;
1015
1016 if (effect.extendsEdge(LEFT)) {
1017 snapshot.geomLayerBounds.left = snapshot.geomLayerCrop.left;
1018 }
1019 if (effect.extendsEdge(RIGHT)) {
1020 snapshot.geomLayerBounds.right = snapshot.geomLayerCrop.right;
1021 }
1022 if (effect.extendsEdge(TOP)) {
1023 snapshot.geomLayerBounds.top = snapshot.geomLayerCrop.top;
1024 }
1025 if (effect.extendsEdge(BOTTOM)) {
1026 snapshot.geomLayerBounds.bottom = snapshot.geomLayerCrop.bottom;
1027 }
1028
1029 snapshot.transformedBounds = snapshot.geomLayerTransform.transform(snapshot.geomLayerBounds);
1030}
1031
Vishnu Nair8fc721b2022-12-22 20:06:32 +00001032void LayerSnapshotBuilder::updateLayerBounds(LayerSnapshot& snapshot,
1033 const RequestedLayerState& requested,
1034 const LayerSnapshot& parentSnapshot,
Vishnu Nairb76d99a2023-03-19 18:22:31 -07001035 uint32_t primaryDisplayRotationFlags) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +00001036 snapshot.geomLayerTransform = parentSnapshot.geomLayerTransform * snapshot.localTransform;
Vishnu Naircfb2d252023-01-19 04:44:02 +00001037 const bool transformWasInvalid = snapshot.invalidTransform;
Vishnu Nair8fc721b2022-12-22 20:06:32 +00001038 snapshot.invalidTransform = !LayerSnapshot::isTransformValid(snapshot.geomLayerTransform);
1039 if (snapshot.invalidTransform) {
Vishnu Naircfb2d252023-01-19 04:44:02 +00001040 auto& t = snapshot.geomLayerTransform;
1041 auto& requestedT = requested.requestedTransform;
1042 std::string transformDebug =
1043 base::StringPrintf(" transform={%f,%f,%f,%f} requestedTransform={%f,%f,%f,%f}",
1044 t.dsdx(), t.dsdy(), t.dtdx(), t.dtdy(), requestedT.dsdx(),
1045 requestedT.dsdy(), requestedT.dtdx(), requestedT.dtdy());
1046 std::string bufferDebug;
1047 if (requested.externalTexture) {
Vishnu Nairb76d99a2023-03-19 18:22:31 -07001048 auto unRotBuffer = requested.getUnrotatedBufferSize(primaryDisplayRotationFlags);
Vishnu Naircfb2d252023-01-19 04:44:02 +00001049 auto& destFrame = requested.destinationFrame;
1050 bufferDebug = base::StringPrintf(" buffer={%d,%d} displayRot=%d"
1051 " destFrame={%d,%d,%d,%d} unRotBuffer={%d,%d}",
1052 requested.externalTexture->getWidth(),
1053 requested.externalTexture->getHeight(),
Vishnu Nairb76d99a2023-03-19 18:22:31 -07001054 primaryDisplayRotationFlags, destFrame.left,
1055 destFrame.top, destFrame.right, destFrame.bottom,
Vishnu Naircfb2d252023-01-19 04:44:02 +00001056 unRotBuffer.getHeight(), unRotBuffer.getWidth());
1057 }
1058 ALOGW("Resetting transform for %s because it is invalid.%s%s",
1059 snapshot.getDebugString().c_str(), transformDebug.c_str(), bufferDebug.c_str());
Vishnu Nair8fc721b2022-12-22 20:06:32 +00001060 snapshot.geomLayerTransform.reset();
1061 }
Vishnu Naircfb2d252023-01-19 04:44:02 +00001062 if (transformWasInvalid != snapshot.invalidTransform) {
1063 // If transform is invalid, the layer will be hidden.
1064 mResortSnapshots = true;
1065 }
Vishnu Nair8fc721b2022-12-22 20:06:32 +00001066 snapshot.geomInverseLayerTransform = snapshot.geomLayerTransform.inverse();
1067
1068 FloatRect parentBounds = parentSnapshot.geomLayerBounds;
1069 parentBounds = snapshot.localTransform.inverse().transform(parentBounds);
1070 snapshot.geomLayerBounds =
Marzia Favarodcc9d9b2024-01-10 10:17:00 +00001071 requested.externalTexture ? snapshot.bufferSize.toFloatRect() : parentBounds;
1072 snapshot.geomLayerCrop = parentBounds;
Vishnu Nair8fc721b2022-12-22 20:06:32 +00001073 if (!requested.crop.isEmpty()) {
Marzia Favarodcc9d9b2024-01-10 10:17:00 +00001074 snapshot.geomLayerCrop = snapshot.geomLayerCrop.intersect(requested.crop.toFloatRect());
Vishnu Nair8fc721b2022-12-22 20:06:32 +00001075 }
Marzia Favarodcc9d9b2024-01-10 10:17:00 +00001076 snapshot.geomLayerBounds = snapshot.geomLayerBounds.intersect(snapshot.geomLayerCrop);
Vishnu Nair8fc721b2022-12-22 20:06:32 +00001077 snapshot.transformedBounds = snapshot.geomLayerTransform.transform(snapshot.geomLayerBounds);
Vishnu Naircfb2d252023-01-19 04:44:02 +00001078 const Rect geomLayerBoundsWithoutTransparentRegion =
1079 RequestedLayerState::reduce(Rect(snapshot.geomLayerBounds),
1080 requested.transparentRegion);
1081 snapshot.transformedBoundsWithoutTransparentRegion =
1082 snapshot.geomLayerTransform.transform(geomLayerBoundsWithoutTransparentRegion);
Vishnu Nair8fc721b2022-12-22 20:06:32 +00001083 snapshot.parentTransform = parentSnapshot.geomLayerTransform;
1084
1085 // Subtract the transparent region and snap to the bounds
Vishnu Naircfb2d252023-01-19 04:44:02 +00001086 const Rect bounds =
Vishnu Nair8fc721b2022-12-22 20:06:32 +00001087 RequestedLayerState::reduce(snapshot.croppedBufferSize, requested.transparentRegion);
Vishnu Naircfb2d252023-01-19 04:44:02 +00001088 if (requested.potentialCursor) {
1089 snapshot.cursorFrame = snapshot.geomLayerTransform.transform(bounds);
1090 }
Vishnu Nair8fc721b2022-12-22 20:06:32 +00001091}
1092
Vishnu Naira02943f2023-06-03 13:44:46 -07001093void LayerSnapshotBuilder::updateShadows(LayerSnapshot& snapshot, const RequestedLayerState&,
Vishnu Naird9e4f462023-10-06 04:05:45 +00001094 const ShadowSettings& globalShadowSettings) {
1095 if (snapshot.shadowSettings.length > 0.f) {
1096 snapshot.shadowSettings.ambientColor = globalShadowSettings.ambientColor;
1097 snapshot.shadowSettings.spotColor = globalShadowSettings.spotColor;
1098 snapshot.shadowSettings.lightPos = globalShadowSettings.lightPos;
1099 snapshot.shadowSettings.lightRadius = globalShadowSettings.lightRadius;
Vishnu Nair8fc721b2022-12-22 20:06:32 +00001100
1101 // Note: this preserves existing behavior of shadowing the entire layer and not cropping
1102 // it if transparent regions are present. This may not be necessary since shadows are
1103 // typically cast by layers without transparent regions.
1104 snapshot.shadowSettings.boundaries = snapshot.geomLayerBounds;
1105
1106 // If the casting layer is translucent, we need to fill in the shadow underneath the
1107 // layer. Otherwise the generated shadow will only be shown around the casting layer.
1108 snapshot.shadowSettings.casterIsTranslucent =
1109 !snapshot.isContentOpaque() || (snapshot.alpha < 1.0f);
1110 snapshot.shadowSettings.ambientColor *= snapshot.alpha;
1111 snapshot.shadowSettings.spotColor *= snapshot.alpha;
1112 }
1113}
1114
1115void LayerSnapshotBuilder::updateInput(LayerSnapshot& snapshot,
1116 const RequestedLayerState& requested,
1117 const LayerSnapshot& parentSnapshot,
Vishnu Naircfb2d252023-01-19 04:44:02 +00001118 const LayerHierarchy::TraversalPath& path,
1119 const Args& args) {
Prabir Pradhancf359192024-03-20 00:42:57 +00001120 using InputConfig = gui::WindowInfo::InputConfig;
1121
Vishnu Naircfb2d252023-01-19 04:44:02 +00001122 if (requested.windowInfoHandle) {
1123 snapshot.inputInfo = *requested.windowInfoHandle->getInfo();
1124 } else {
1125 snapshot.inputInfo = {};
Vishnu Nair40d02282023-02-28 21:11:40 +00001126 // b/271132344 revisit this and see if we can always use the layers uid/pid
1127 snapshot.inputInfo.name = requested.name;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001128 snapshot.inputInfo.ownerUid = gui::Uid{requested.ownerUid};
Prabir Pradhane59c6dc2023-06-13 19:53:03 +00001129 snapshot.inputInfo.ownerPid = gui::Pid{requested.ownerPid};
Vishnu Naircfb2d252023-01-19 04:44:02 +00001130 }
Vishnu Nair29354ec2023-03-28 18:51:28 -07001131 snapshot.touchCropId = requested.touchCropId;
Vishnu Naircfb2d252023-01-19 04:44:02 +00001132
Vishnu Nair93b8b792023-02-27 19:40:24 +00001133 snapshot.inputInfo.id = static_cast<int32_t>(snapshot.uniqueSequence);
Linnan Li13bf76a2024-05-05 19:18:02 +08001134 snapshot.inputInfo.displayId =
1135 ui::LogicalDisplayId{static_cast<int32_t>(snapshot.outputFilter.layerStack.id)};
Vishnu Nairf13c8982023-12-02 11:26:09 -08001136 snapshot.inputInfo.touchOcclusionMode = requested.hasInputInfo()
1137 ? requested.windowInfoHandle->getInfo()->touchOcclusionMode
1138 : parentSnapshot.inputInfo.touchOcclusionMode;
Vishnu Nair59a6be32024-01-29 10:26:21 -08001139 snapshot.inputInfo.canOccludePresentation = parentSnapshot.inputInfo.canOccludePresentation ||
1140 (requested.flags & layer_state_t::eCanOccludePresentation);
Vishnu Nairf13c8982023-12-02 11:26:09 -08001141 if (requested.dropInputMode == gui::DropInputMode::ALL ||
1142 parentSnapshot.dropInputMode == gui::DropInputMode::ALL) {
1143 snapshot.dropInputMode = gui::DropInputMode::ALL;
1144 } else if (requested.dropInputMode == gui::DropInputMode::OBSCURED ||
1145 parentSnapshot.dropInputMode == gui::DropInputMode::OBSCURED) {
1146 snapshot.dropInputMode = gui::DropInputMode::OBSCURED;
1147 } else {
1148 snapshot.dropInputMode = gui::DropInputMode::NONE;
1149 }
1150
Prabir Pradhancf359192024-03-20 00:42:57 +00001151 if (snapshot.isSecure ||
Arpit Singh490ccc92024-04-30 14:26:21 +00001152 parentSnapshot.inputInfo.inputConfig.test(InputConfig::SENSITIVE_FOR_PRIVACY)) {
1153 snapshot.inputInfo.inputConfig |= InputConfig::SENSITIVE_FOR_PRIVACY;
Prabir Pradhancf359192024-03-20 00:42:57 +00001154 }
1155
Vishnu Nair29354ec2023-03-28 18:51:28 -07001156 updateVisibility(snapshot, snapshot.isVisible);
Vishnu Naircfb2d252023-01-19 04:44:02 +00001157 if (!needsInputInfo(snapshot, requested)) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +00001158 return;
1159 }
1160
Vishnu Naircfb2d252023-01-19 04:44:02 +00001161 static frontend::DisplayInfo sDefaultInfo = {.isSecure = false};
1162 const std::optional<frontend::DisplayInfo> displayInfoOpt =
1163 args.displays.get(snapshot.outputFilter.layerStack);
1164 bool noValidDisplay = !displayInfoOpt.has_value();
1165 auto displayInfo = displayInfoOpt.value_or(sDefaultInfo);
1166
1167 if (!requested.windowInfoHandle) {
Prabir Pradhancf359192024-03-20 00:42:57 +00001168 snapshot.inputInfo.inputConfig = InputConfig::NO_INPUT_CHANNEL;
Vishnu Naircfb2d252023-01-19 04:44:02 +00001169 }
Vishnu Nair8fc721b2022-12-22 20:06:32 +00001170 fillInputFrameInfo(snapshot.inputInfo, displayInfo.transform, snapshot);
1171
1172 if (noValidDisplay) {
1173 // Do not let the window receive touches if it is not associated with a valid display
1174 // transform. We still allow the window to receive keys and prevent ANRs.
Prabir Pradhancf359192024-03-20 00:42:57 +00001175 snapshot.inputInfo.inputConfig |= InputConfig::NOT_TOUCHABLE;
Vishnu Nair8fc721b2022-12-22 20:06:32 +00001176 }
1177
Vishnu Nair8fc721b2022-12-22 20:06:32 +00001178 snapshot.inputInfo.alpha = snapshot.color.a;
Vishnu Nair8fc721b2022-12-22 20:06:32 +00001179
1180 handleDropInputMode(snapshot, parentSnapshot);
1181
1182 // If the window will be blacked out on a display because the display does not have the secure
1183 // flag and the layer has the secure flag set, then drop input.
1184 if (!displayInfo.isSecure && snapshot.isSecure) {
Prabir Pradhancf359192024-03-20 00:42:57 +00001185 snapshot.inputInfo.inputConfig |= InputConfig::DROP_INPUT;
Vishnu Nair8fc721b2022-12-22 20:06:32 +00001186 }
1187
Vishnu Naira02943f2023-06-03 13:44:46 -07001188 if (requested.touchCropId != UNASSIGNED_LAYER_ID || path.isClone()) {
Vishnu Nair29354ec2023-03-28 18:51:28 -07001189 mNeedsTouchableRegionCrop.insert(path);
Vishnu Naira02943f2023-06-03 13:44:46 -07001190 }
1191 auto cropLayerSnapshot = getSnapshot(requested.touchCropId);
1192 if (!cropLayerSnapshot && snapshot.inputInfo.replaceTouchableRegionWithCrop) {
Vishnu Nair29354ec2023-03-28 18:51:28 -07001193 FloatRect inputBounds = getInputBounds(snapshot, /*fillParentBounds=*/true).first;
Vishnu Nairfed7c122023-03-18 01:54:43 +00001194 Rect inputBoundsInDisplaySpace =
Vishnu Nair29354ec2023-03-28 18:51:28 -07001195 getInputBoundsInDisplaySpace(snapshot, inputBounds, displayInfo.transform);
1196 snapshot.inputInfo.touchableRegion = Region(inputBoundsInDisplaySpace);
Vishnu Nair8fc721b2022-12-22 20:06:32 +00001197 }
1198
1199 // Inherit the trusted state from the parent hierarchy, but don't clobber the trusted state
1200 // if it was set by WM for a known system overlay
Vishnu Nair9e0017e2024-05-22 19:02:44 +00001201 if (snapshot.trustedOverlay == gui::TrustedOverlay::ENABLED) {
Prabir Pradhancf359192024-03-20 00:42:57 +00001202 snapshot.inputInfo.inputConfig |= InputConfig::TRUSTED_OVERLAY;
Vishnu Nair8fc721b2022-12-22 20:06:32 +00001203 }
1204
Vishnu Nair494a2e42023-11-10 17:21:19 -08001205 snapshot.inputInfo.contentSize = snapshot.croppedBufferSize.getSize();
1206
Vishnu Nair8fc721b2022-12-22 20:06:32 +00001207 // If the layer is a clone, we need to crop the input region to cloned root to prevent
1208 // touches from going outside the cloned area.
1209 if (path.isClone()) {
Prabir Pradhancf359192024-03-20 00:42:57 +00001210 snapshot.inputInfo.inputConfig |= InputConfig::CLONE;
Vishnu Nair444f3952023-04-11 13:01:02 -07001211 // Cloned layers shouldn't handle watch outside since their z order is not determined by
1212 // WM or the client.
Prabir Pradhancf359192024-03-20 00:42:57 +00001213 snapshot.inputInfo.inputConfig.clear(InputConfig::WATCH_OUTSIDE_TOUCH);
Vishnu Nair8fc721b2022-12-22 20:06:32 +00001214 }
1215}
1216
1217std::vector<std::unique_ptr<LayerSnapshot>>& LayerSnapshotBuilder::getSnapshots() {
1218 return mSnapshots;
1219}
1220
Vishnu Naircfb2d252023-01-19 04:44:02 +00001221void LayerSnapshotBuilder::forEachVisibleSnapshot(const ConstVisitor& visitor) const {
1222 for (int i = 0; i < mNumInterestingSnapshots; i++) {
1223 LayerSnapshot& snapshot = *mSnapshots[(size_t)i];
1224 if (!snapshot.isVisible) continue;
1225 visitor(snapshot);
1226 }
1227}
1228
Vishnu Nair3af0ec02023-02-10 04:13:48 +00001229// Visit each visible snapshot in z-order
1230void LayerSnapshotBuilder::forEachVisibleSnapshot(const ConstVisitor& visitor,
1231 const LayerHierarchy& root) const {
1232 root.traverseInZOrder(
1233 [this, visitor](const LayerHierarchy&,
1234 const LayerHierarchy::TraversalPath& traversalPath) -> bool {
1235 LayerSnapshot* snapshot = getSnapshot(traversalPath);
1236 if (snapshot && snapshot->isVisible) {
1237 visitor(*snapshot);
1238 }
1239 return true;
1240 });
1241}
1242
Vishnu Naircfb2d252023-01-19 04:44:02 +00001243void LayerSnapshotBuilder::forEachVisibleSnapshot(const Visitor& visitor) {
1244 for (int i = 0; i < mNumInterestingSnapshots; i++) {
1245 std::unique_ptr<LayerSnapshot>& snapshot = mSnapshots.at((size_t)i);
1246 if (!snapshot->isVisible) continue;
1247 visitor(snapshot);
1248 }
1249}
1250
Nergi Rahardi0dfc0962024-05-23 06:57:36 +00001251void LayerSnapshotBuilder::forEachSnapshot(const Visitor& visitor,
1252 const ConstPredicate& predicate) {
1253 for (int i = 0; i < mNumInterestingSnapshots; i++) {
1254 std::unique_ptr<LayerSnapshot>& snapshot = mSnapshots.at((size_t)i);
1255 if (!predicate(*snapshot)) continue;
1256 visitor(snapshot);
1257 }
1258}
1259
Vishnu Naircfb2d252023-01-19 04:44:02 +00001260void LayerSnapshotBuilder::forEachInputSnapshot(const ConstVisitor& visitor) const {
1261 for (int i = mNumInterestingSnapshots - 1; i >= 0; i--) {
1262 LayerSnapshot& snapshot = *mSnapshots[(size_t)i];
1263 if (!snapshot.hasInputInfo()) continue;
1264 visitor(snapshot);
1265 }
1266}
1267
Vishnu Nair29354ec2023-03-28 18:51:28 -07001268void LayerSnapshotBuilder::updateTouchableRegionCrop(const Args& args) {
1269 if (mNeedsTouchableRegionCrop.empty()) {
1270 return;
1271 }
1272
1273 static constexpr ftl::Flags<RequestedLayerState::Changes> AFFECTS_INPUT =
1274 RequestedLayerState::Changes::Visibility | RequestedLayerState::Changes::Created |
1275 RequestedLayerState::Changes::Hierarchy | RequestedLayerState::Changes::Geometry |
1276 RequestedLayerState::Changes::Input;
1277
1278 if (args.forceUpdate != ForceUpdateFlags::ALL &&
Vishnu Naira02943f2023-06-03 13:44:46 -07001279 !args.layerLifecycleManager.getGlobalChanges().any(AFFECTS_INPUT) && !args.displayChanges) {
Vishnu Nair29354ec2023-03-28 18:51:28 -07001280 return;
1281 }
1282
1283 for (auto& path : mNeedsTouchableRegionCrop) {
1284 frontend::LayerSnapshot* snapshot = getSnapshot(path);
1285 if (!snapshot) {
1286 continue;
1287 }
Vishnu Naira02943f2023-06-03 13:44:46 -07001288 LLOGV(snapshot->sequence, "updateTouchableRegionCrop=%s",
1289 snapshot->getDebugString().c_str());
Vishnu Nair29354ec2023-03-28 18:51:28 -07001290 const std::optional<frontend::DisplayInfo> displayInfoOpt =
1291 args.displays.get(snapshot->outputFilter.layerStack);
1292 static frontend::DisplayInfo sDefaultInfo = {.isSecure = false};
1293 auto displayInfo = displayInfoOpt.value_or(sDefaultInfo);
1294
1295 bool needsUpdate =
1296 args.forceUpdate == ForceUpdateFlags::ALL || snapshot->changes.any(AFFECTS_INPUT);
1297 auto cropLayerSnapshot = getSnapshot(snapshot->touchCropId);
1298 needsUpdate =
1299 needsUpdate || (cropLayerSnapshot && cropLayerSnapshot->changes.any(AFFECTS_INPUT));
1300 auto clonedRootSnapshot = path.isClone() ? getSnapshot(snapshot->mirrorRootPath) : nullptr;
1301 needsUpdate = needsUpdate ||
1302 (clonedRootSnapshot && clonedRootSnapshot->changes.any(AFFECTS_INPUT));
1303
1304 if (!needsUpdate) {
1305 continue;
1306 }
1307
1308 if (snapshot->inputInfo.replaceTouchableRegionWithCrop) {
1309 Rect inputBoundsInDisplaySpace;
1310 if (!cropLayerSnapshot) {
1311 FloatRect inputBounds = getInputBounds(*snapshot, /*fillParentBounds=*/true).first;
1312 inputBoundsInDisplaySpace =
1313 getInputBoundsInDisplaySpace(*snapshot, inputBounds, displayInfo.transform);
1314 } else {
1315 FloatRect inputBounds =
1316 getInputBounds(*cropLayerSnapshot, /*fillParentBounds=*/true).first;
1317 inputBoundsInDisplaySpace =
1318 getInputBoundsInDisplaySpace(*cropLayerSnapshot, inputBounds,
1319 displayInfo.transform);
1320 }
1321 snapshot->inputInfo.touchableRegion = Region(inputBoundsInDisplaySpace);
1322 } else if (cropLayerSnapshot) {
1323 FloatRect inputBounds =
1324 getInputBounds(*cropLayerSnapshot, /*fillParentBounds=*/true).first;
1325 Rect inputBoundsInDisplaySpace =
1326 getInputBoundsInDisplaySpace(*cropLayerSnapshot, inputBounds,
1327 displayInfo.transform);
Chavi Weingarten1ba381e2024-01-09 21:54:11 +00001328 snapshot->inputInfo.touchableRegion =
1329 snapshot->inputInfo.touchableRegion.intersect(inputBoundsInDisplaySpace);
Vishnu Nair29354ec2023-03-28 18:51:28 -07001330 }
1331
1332 // If the layer is a clone, we need to crop the input region to cloned root to prevent
1333 // touches from going outside the cloned area.
1334 if (clonedRootSnapshot) {
1335 const Rect rect =
1336 displayInfo.transform.transform(Rect{clonedRootSnapshot->transformedBounds});
1337 snapshot->inputInfo.touchableRegion =
1338 snapshot->inputInfo.touchableRegion.intersect(rect);
1339 }
1340 }
1341}
1342
Vishnu Nair8fc721b2022-12-22 20:06:32 +00001343} // namespace android::surfaceflinger::frontend