blob: f10bb33a2f9ee34034a1a232eb6aecdee4260e72 [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
Chavi Weingarten7f019192023-08-08 20:39:01 +0000181 info.frame = getInputBoundsInDisplaySpace(snapshot, inputBounds, screenToDisplay);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000182
183 ui::Transform inputToLayer;
Vishnu Nairfed7c122023-03-18 01:54:43 +0000184 inputToLayer.set(inputBounds.left, inputBounds.top);
185 const ui::Transform layerToScreen = getInputTransform(snapshot);
186 const ui::Transform inputToDisplay = screenToDisplay * layerToScreen * inputToLayer;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000187
188 // InputDispatcher expects a display-to-input transform.
189 info.transform = inputToDisplay.inverse();
190
191 // The touchable region is specified in the input coordinate space. Change it to display space.
192 info.touchableRegion =
193 transformTouchableRegionSafely(inputToDisplay, info.touchableRegion, snapshot.name);
194}
195
196void handleDropInputMode(LayerSnapshot& snapshot, const LayerSnapshot& parentSnapshot) {
197 if (snapshot.inputInfo.inputConfig.test(gui::WindowInfo::InputConfig::NO_INPUT_CHANNEL)) {
198 return;
199 }
200
201 // Check if we need to drop input unconditionally
202 const gui::DropInputMode dropInputMode = snapshot.dropInputMode;
203 if (dropInputMode == gui::DropInputMode::ALL) {
204 snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::DROP_INPUT;
205 ALOGV("Dropping input for %s as requested by policy.", snapshot.name.c_str());
206 return;
207 }
208
209 // Check if we need to check if the window is obscured by parent
210 if (dropInputMode != gui::DropInputMode::OBSCURED) {
211 return;
212 }
213
214 // Check if the parent has set an alpha on the layer
215 if (parentSnapshot.color.a != 1.0_hf) {
216 snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::DROP_INPUT;
217 ALOGV("Dropping input for %s as requested by policy because alpha=%f",
218 snapshot.name.c_str(), static_cast<float>(parentSnapshot.color.a));
219 }
220
221 // Check if the parent has cropped the buffer
222 Rect bufferSize = snapshot.croppedBufferSize;
223 if (!bufferSize.isValid()) {
224 snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED;
225 return;
226 }
227
228 // Screenbounds are the layer bounds cropped by parents, transformed to screenspace.
229 // To check if the layer has been cropped, we take the buffer bounds, apply the local
230 // layer crop and apply the same set of transforms to move to screenspace. If the bounds
231 // match then the layer has not been cropped by its parents.
232 Rect bufferInScreenSpace(snapshot.geomLayerTransform.transform(bufferSize));
233 bool croppedByParent = bufferInScreenSpace != Rect{snapshot.transformedBounds};
234
235 if (croppedByParent) {
236 snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::DROP_INPUT;
237 ALOGV("Dropping input for %s as requested by policy because buffer is cropped by parent",
238 snapshot.name.c_str());
239 } else {
240 // If the layer is not obscured by its parents (by setting an alpha or crop), then only drop
241 // input if the window is obscured. This check should be done in surfaceflinger but the
242 // logic currently resides in inputflinger. So pass the if_obscured check to input to only
243 // drop input events if the window is obscured.
244 snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED;
245 }
246}
247
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000248auto getBlendMode(const LayerSnapshot& snapshot, const RequestedLayerState& requested) {
249 auto blendMode = Hwc2::IComposerClient::BlendMode::NONE;
250 if (snapshot.alpha != 1.0f || !snapshot.isContentOpaque()) {
251 blendMode = requested.premultipliedAlpha ? Hwc2::IComposerClient::BlendMode::PREMULTIPLIED
252 : Hwc2::IComposerClient::BlendMode::COVERAGE;
253 }
254 return blendMode;
255}
256
Vishnu Nair80a5a702023-02-11 01:21:51 +0000257void updateVisibility(LayerSnapshot& snapshot, bool visible) {
258 snapshot.isVisible = visible;
Vishnu Naircfb2d252023-01-19 04:44:02 +0000259
260 // TODO(b/238781169) we are ignoring this compat for now, since we will have
261 // to remove any optimization based on visibility.
262
263 // For compatibility reasons we let layers which can receive input
264 // receive input before they have actually submitted a buffer. Because
265 // of this we use canReceiveInput instead of isVisible to check the
266 // policy-visibility, ignoring the buffer state. However for layers with
267 // hasInputInfo()==false we can use the real visibility state.
268 // We are just using these layers for occlusion detection in
269 // InputDispatcher, and obviously if they aren't visible they can't occlude
270 // anything.
Vishnu Nair80a5a702023-02-11 01:21:51 +0000271 const bool visibleForInput =
Vishnu Nair40d02282023-02-28 21:11:40 +0000272 snapshot.hasInputInfo() ? snapshot.canReceiveInput() : snapshot.isVisible;
Vishnu Nair80a5a702023-02-11 01:21:51 +0000273 snapshot.inputInfo.setInputConfig(gui::WindowInfo::InputConfig::NOT_VISIBLE, !visibleForInput);
Vishnu Naira02943f2023-06-03 13:44:46 -0700274 LLOGV(snapshot.sequence, "updating visibility %s %s", visible ? "true" : "false",
275 snapshot.getDebugString().c_str());
Vishnu Naircfb2d252023-01-19 04:44:02 +0000276}
277
278bool needsInputInfo(const LayerSnapshot& snapshot, const RequestedLayerState& requested) {
279 if (requested.potentialCursor) {
280 return false;
281 }
282
283 if (snapshot.inputInfo.token != nullptr) {
284 return true;
285 }
286
287 if (snapshot.hasBufferOrSidebandStream()) {
288 return true;
289 }
290
291 return requested.windowInfoHandle &&
292 requested.windowInfoHandle->getInfo()->inputConfig.test(
293 gui::WindowInfo::InputConfig::NO_INPUT_CHANNEL);
294}
295
Vishnu Nairc765c6c2023-02-23 00:08:01 +0000296void updateMetadata(LayerSnapshot& snapshot, const RequestedLayerState& requested,
297 const LayerSnapshotBuilder::Args& args) {
298 snapshot.metadata.clear();
299 for (const auto& [key, mandatory] : args.supportedLayerGenericMetadata) {
300 auto compatIter = args.genericLayerMetadataKeyMap.find(key);
301 if (compatIter == std::end(args.genericLayerMetadataKeyMap)) {
302 continue;
303 }
304 const uint32_t id = compatIter->second;
305 auto it = requested.metadata.mMap.find(id);
306 if (it == std::end(requested.metadata.mMap)) {
307 continue;
308 }
309
310 snapshot.metadata.emplace(key,
311 compositionengine::GenericLayerMetadataEntry{mandatory,
312 it->second});
313 }
314}
315
Garfield Tan8eb8f352024-05-17 09:12:01 -0700316void updateMetadataAndGameMode(LayerSnapshot& snapshot, const RequestedLayerState& requested,
317 const LayerSnapshotBuilder::Args& args,
318 const LayerSnapshot& parentSnapshot) {
319 if (snapshot.changes.test(RequestedLayerState::Changes::GameMode)) {
320 snapshot.gameMode = requested.metadata.has(gui::METADATA_GAME_MODE)
321 ? requested.gameMode
322 : parentSnapshot.gameMode;
323 }
324 updateMetadata(snapshot, requested, args);
325 if (args.includeMetadata) {
326 snapshot.layerMetadata = parentSnapshot.layerMetadata;
327 snapshot.layerMetadata.merge(requested.metadata);
328 }
329}
330
Vishnu Naircfb2d252023-01-19 04:44:02 +0000331void clearChanges(LayerSnapshot& snapshot) {
332 snapshot.changes.clear();
Vishnu Naira02943f2023-06-03 13:44:46 -0700333 snapshot.clientChanges = 0;
Vishnu Naircfb2d252023-01-19 04:44:02 +0000334 snapshot.contentDirty = false;
335 snapshot.hasReadyFrame = false;
336 snapshot.sidebandStreamHasFrame = false;
337 snapshot.surfaceDamage.clear();
338}
339
Vishnu Naira02943f2023-06-03 13:44:46 -0700340// TODO (b/259407931): Remove.
341uint32_t getPrimaryDisplayRotationFlags(
342 const ui::DisplayMap<ui::LayerStack, frontend::DisplayInfo>& displays) {
343 for (auto& [_, display] : displays) {
344 if (display.isPrimary) {
345 return display.rotationFlags;
346 }
347 }
348 return 0;
349}
350
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000351} // namespace
352
353LayerSnapshot LayerSnapshotBuilder::getRootSnapshot() {
354 LayerSnapshot snapshot;
Vishnu Nair92990e22023-02-24 20:01:05 +0000355 snapshot.path = LayerHierarchy::TraversalPath::ROOT;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000356 snapshot.changes = ftl::Flags<RequestedLayerState::Changes>();
Vishnu Naira02943f2023-06-03 13:44:46 -0700357 snapshot.clientChanges = 0;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000358 snapshot.isHiddenByPolicyFromParent = false;
359 snapshot.isHiddenByPolicyFromRelativeParent = false;
360 snapshot.parentTransform.reset();
361 snapshot.geomLayerTransform.reset();
362 snapshot.geomInverseLayerTransform.reset();
363 snapshot.geomLayerBounds = getMaxDisplayBounds({});
364 snapshot.roundedCorner = RoundedCornerState();
365 snapshot.stretchEffect = {};
366 snapshot.outputFilter.layerStack = ui::DEFAULT_LAYER_STACK;
367 snapshot.outputFilter.toInternalDisplay = false;
368 snapshot.isSecure = false;
369 snapshot.color.a = 1.0_hf;
370 snapshot.colorTransformIsIdentity = true;
Vishnu Naird9e4f462023-10-06 04:05:45 +0000371 snapshot.shadowSettings.length = 0.f;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000372 snapshot.layerMetadata.mMap.clear();
373 snapshot.relativeLayerMetadata.mMap.clear();
374 snapshot.inputInfo.touchOcclusionMode = gui::TouchOcclusionMode::BLOCK_UNTRUSTED;
375 snapshot.dropInputMode = gui::DropInputMode::NONE;
376 snapshot.isTrustedOverlay = false;
Vishnu Naircfb2d252023-01-19 04:44:02 +0000377 snapshot.gameMode = gui::GameMode::Unsupported;
378 snapshot.frameRate = {};
379 snapshot.fixedTransformHint = ui::Transform::ROT_INVALID;
Vishnu Nair422b81c2024-05-16 05:44:28 +0000380 snapshot.ignoreLocalTransform = false;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000381 return snapshot;
382}
383
Chavi Weingarten4aa22af2023-11-17 19:37:07 +0000384LayerSnapshotBuilder::LayerSnapshotBuilder() {}
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000385
386LayerSnapshotBuilder::LayerSnapshotBuilder(Args args) : LayerSnapshotBuilder() {
Vishnu Naird47bcee2023-02-24 18:08:51 +0000387 args.forceUpdate = ForceUpdateFlags::ALL;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000388 updateSnapshots(args);
389}
390
391bool LayerSnapshotBuilder::tryFastUpdate(const Args& args) {
Vishnu Naira02943f2023-06-03 13:44:46 -0700392 const bool forceUpdate = args.forceUpdate != ForceUpdateFlags::NONE;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000393
Vishnu Naira02943f2023-06-03 13:44:46 -0700394 if (args.layerLifecycleManager.getGlobalChanges().get() == 0 && !forceUpdate &&
395 !args.displayChanges) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000396 return true;
397 }
398
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000399 // There are only content changes which do not require any child layer snapshots to be updated.
400 ALOGV("%s", __func__);
401 ATRACE_NAME("FastPath");
402
Vishnu Naira02943f2023-06-03 13:44:46 -0700403 uint32_t primaryDisplayRotationFlags = getPrimaryDisplayRotationFlags(args.displays);
404 if (forceUpdate || args.displayChanges) {
405 for (auto& snapshot : mSnapshots) {
406 const RequestedLayerState* requested =
407 args.layerLifecycleManager.getLayerFromId(snapshot->path.id);
408 if (!requested) continue;
409 snapshot->merge(*requested, forceUpdate, args.displayChanges, args.forceFullDamage,
410 primaryDisplayRotationFlags);
411 }
412 return false;
413 }
414
415 // Walk through all the updated requested layer states and update the corresponding snapshots.
416 for (const RequestedLayerState* requested : args.layerLifecycleManager.getChangedLayers()) {
417 auto range = mIdToSnapshots.equal_range(requested->id);
418 for (auto it = range.first; it != range.second; it++) {
419 it->second->merge(*requested, forceUpdate, args.displayChanges, args.forceFullDamage,
420 primaryDisplayRotationFlags);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000421 }
422 }
423
Vishnu Naira02943f2023-06-03 13:44:46 -0700424 if ((args.layerLifecycleManager.getGlobalChanges().get() &
425 ~(RequestedLayerState::Changes::Content | RequestedLayerState::Changes::Buffer).get()) !=
426 0) {
427 // We have changes that require us to walk the hierarchy and update child layers.
428 // No fast path for you.
429 return false;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000430 }
431 return true;
432}
433
434void LayerSnapshotBuilder::updateSnapshots(const Args& args) {
435 ATRACE_NAME("UpdateSnapshots");
Chavi Weingarten4aa22af2023-11-17 19:37:07 +0000436 LayerSnapshot rootSnapshot = args.rootSnapshot;
Vishnu Nair3af0ec02023-02-10 04:13:48 +0000437 if (args.parentCrop) {
Chavi Weingarten4aa22af2023-11-17 19:37:07 +0000438 rootSnapshot.geomLayerBounds = *args.parentCrop;
Vishnu Naird47bcee2023-02-24 18:08:51 +0000439 } else if (args.forceUpdate == ForceUpdateFlags::ALL || args.displayChanges) {
Chavi Weingarten4aa22af2023-11-17 19:37:07 +0000440 rootSnapshot.geomLayerBounds = getMaxDisplayBounds(args.displays);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000441 }
442 if (args.displayChanges) {
Chavi Weingarten4aa22af2023-11-17 19:37:07 +0000443 rootSnapshot.changes = RequestedLayerState::Changes::AffectsChildren |
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000444 RequestedLayerState::Changes::Geometry;
445 }
Vishnu Naird47bcee2023-02-24 18:08:51 +0000446 if (args.forceUpdate == ForceUpdateFlags::HIERARCHY) {
Chavi Weingarten4aa22af2023-11-17 19:37:07 +0000447 rootSnapshot.changes |=
Vishnu Naird47bcee2023-02-24 18:08:51 +0000448 RequestedLayerState::Changes::Hierarchy | RequestedLayerState::Changes::Visibility;
Chavi Weingarten4aa22af2023-11-17 19:37:07 +0000449 rootSnapshot.clientChanges |= layer_state_t::eReparent;
Vishnu Naird47bcee2023-02-24 18:08:51 +0000450 }
Vishnu Naira02943f2023-06-03 13:44:46 -0700451
452 for (auto& snapshot : mSnapshots) {
453 if (snapshot->reachablilty == LayerSnapshot::Reachablilty::Reachable) {
454 snapshot->reachablilty = LayerSnapshot::Reachablilty::Unreachable;
455 }
456 }
457
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000458 LayerHierarchy::TraversalPath root = LayerHierarchy::TraversalPath::ROOT;
Vishnu Naird47bcee2023-02-24 18:08:51 +0000459 if (args.root.getLayer()) {
460 // The hierarchy can have a root layer when used for screenshots otherwise, it will have
461 // multiple children.
462 LayerHierarchy::ScopedAddToTraversalPath addChildToPath(root, args.root.getLayer()->id,
463 LayerHierarchy::Variant::Attached);
Chavi Weingarten4aa22af2023-11-17 19:37:07 +0000464 updateSnapshotsInHierarchy(args, args.root, root, rootSnapshot, /*depth=*/0);
Vishnu Naird47bcee2023-02-24 18:08:51 +0000465 } else {
466 for (auto& [childHierarchy, variant] : args.root.mChildren) {
467 LayerHierarchy::ScopedAddToTraversalPath addChildToPath(root,
468 childHierarchy->getLayer()->id,
469 variant);
Chavi Weingarten4aa22af2023-11-17 19:37:07 +0000470 updateSnapshotsInHierarchy(args, *childHierarchy, root, rootSnapshot, /*depth=*/0);
Vishnu Naird47bcee2023-02-24 18:08:51 +0000471 }
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000472 }
473
Vishnu Nair29354ec2023-03-28 18:51:28 -0700474 // Update touchable region crops outside the main update pass. This is because a layer could be
475 // cropped by any other layer and it requires both snapshots to be updated.
476 updateTouchableRegionCrop(args);
477
Vishnu Nairfccd6362023-02-24 23:39:53 +0000478 const bool hasUnreachableSnapshots = sortSnapshotsByZ(args);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000479
Vishnu Nair29354ec2023-03-28 18:51:28 -0700480 // Destroy unreachable snapshots for clone layers. And destroy snapshots for non-clone
481 // layers if the layer have been destroyed.
482 // TODO(b/238781169) consider making clone layer ids stable as well
483 if (!hasUnreachableSnapshots && args.layerLifecycleManager.getDestroyedLayers().empty()) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000484 return;
485 }
486
Vishnu Nair29354ec2023-03-28 18:51:28 -0700487 std::unordered_set<uint32_t> destroyedLayerIds;
488 for (auto& destroyedLayer : args.layerLifecycleManager.getDestroyedLayers()) {
489 destroyedLayerIds.insert(destroyedLayer->id);
490 }
491
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000492 auto it = mSnapshots.begin();
493 while (it < mSnapshots.end()) {
494 auto& traversalPath = it->get()->path;
Vishnu Naira02943f2023-06-03 13:44:46 -0700495 const bool unreachable =
496 it->get()->reachablilty == LayerSnapshot::Reachablilty::Unreachable;
497 const bool isClone = traversalPath.isClone();
498 const bool layerIsDestroyed =
499 destroyedLayerIds.find(traversalPath.id) != destroyedLayerIds.end();
500 const bool destroySnapshot = (unreachable && isClone) || layerIsDestroyed;
501
502 if (!destroySnapshot) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000503 it++;
504 continue;
505 }
506
Vishnu Naira02943f2023-06-03 13:44:46 -0700507 mPathToSnapshot.erase(traversalPath);
508
509 auto range = mIdToSnapshots.equal_range(traversalPath.id);
510 auto matchingSnapshot =
511 std::find_if(range.first, range.second, [&traversalPath](auto& snapshotWithId) {
512 return snapshotWithId.second->path == traversalPath;
513 });
514 mIdToSnapshots.erase(matchingSnapshot);
Vishnu Nair29354ec2023-03-28 18:51:28 -0700515 mNeedsTouchableRegionCrop.erase(traversalPath);
Vishnu Naircfb2d252023-01-19 04:44:02 +0000516 mSnapshots.back()->globalZ = it->get()->globalZ;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000517 std::iter_swap(it, mSnapshots.end() - 1);
518 mSnapshots.erase(mSnapshots.end() - 1);
519 }
520}
521
522void LayerSnapshotBuilder::update(const Args& args) {
Vishnu Nair92990e22023-02-24 20:01:05 +0000523 for (auto& snapshot : mSnapshots) {
524 clearChanges(*snapshot);
525 }
526
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000527 if (tryFastUpdate(args)) {
528 return;
529 }
530 updateSnapshots(args);
531}
532
Vishnu Naircfb2d252023-01-19 04:44:02 +0000533const LayerSnapshot& LayerSnapshotBuilder::updateSnapshotsInHierarchy(
534 const Args& args, const LayerHierarchy& hierarchy,
Vishnu Naird1f74982023-06-15 20:16:51 -0700535 LayerHierarchy::TraversalPath& traversalPath, const LayerSnapshot& parentSnapshot,
536 int depth) {
Vishnu Nair606d9d02023-08-19 14:20:18 -0700537 LLOG_ALWAYS_FATAL_WITH_TRACE_IF(depth > 50,
538 "Cycle detected in LayerSnapshotBuilder. See "
539 "builder_stack_overflow_transactions.winscope");
Vishnu Naird1f74982023-06-15 20:16:51 -0700540
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000541 const RequestedLayerState* layer = hierarchy.getLayer();
Vishnu Naircfb2d252023-01-19 04:44:02 +0000542 LayerSnapshot* snapshot = getSnapshot(traversalPath);
543 const bool newSnapshot = snapshot == nullptr;
Vishnu Naira02943f2023-06-03 13:44:46 -0700544 uint32_t primaryDisplayRotationFlags = getPrimaryDisplayRotationFlags(args.displays);
Vishnu Naircfb2d252023-01-19 04:44:02 +0000545 if (newSnapshot) {
Vishnu Nair92990e22023-02-24 20:01:05 +0000546 snapshot = createSnapshot(traversalPath, *layer, parentSnapshot);
Vishnu Naira02943f2023-06-03 13:44:46 -0700547 snapshot->merge(*layer, /*forceUpdate=*/true, /*displayChanges=*/true, args.forceFullDamage,
548 primaryDisplayRotationFlags);
549 snapshot->changes |= RequestedLayerState::Changes::Created;
Vishnu Naircfb2d252023-01-19 04:44:02 +0000550 }
Vishnu Nair52d56fd2023-07-20 17:02:43 +0000551
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000552 if (traversalPath.isRelative()) {
553 bool parentIsRelative = traversalPath.variant == LayerHierarchy::Variant::Relative;
554 updateRelativeState(*snapshot, parentSnapshot, parentIsRelative, args);
555 } else {
556 if (traversalPath.isAttached()) {
557 resetRelativeState(*snapshot);
558 }
Vishnu Nair92990e22023-02-24 20:01:05 +0000559 updateSnapshot(*snapshot, args, *layer, parentSnapshot, traversalPath);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000560 }
561
562 for (auto& [childHierarchy, variant] : hierarchy.mChildren) {
563 LayerHierarchy::ScopedAddToTraversalPath addChildToPath(traversalPath,
564 childHierarchy->getLayer()->id,
565 variant);
Vishnu Naircfb2d252023-01-19 04:44:02 +0000566 const LayerSnapshot& childSnapshot =
Vishnu Naird1f74982023-06-15 20:16:51 -0700567 updateSnapshotsInHierarchy(args, *childHierarchy, traversalPath, *snapshot,
568 depth + 1);
Vishnu Nair42b918e2023-07-18 20:05:29 +0000569 updateFrameRateFromChildSnapshot(*snapshot, childSnapshot, args);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000570 }
Vishnu Naird47bcee2023-02-24 18:08:51 +0000571
Vishnu Naircfb2d252023-01-19 04:44:02 +0000572 return *snapshot;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000573}
574
575LayerSnapshot* LayerSnapshotBuilder::getSnapshot(uint32_t layerId) const {
576 if (layerId == UNASSIGNED_LAYER_ID) {
577 return nullptr;
578 }
579 LayerHierarchy::TraversalPath path{.id = layerId};
580 return getSnapshot(path);
581}
582
583LayerSnapshot* LayerSnapshotBuilder::getSnapshot(const LayerHierarchy::TraversalPath& id) const {
Vishnu Naira02943f2023-06-03 13:44:46 -0700584 auto it = mPathToSnapshot.find(id);
585 return it == mPathToSnapshot.end() ? nullptr : it->second;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000586}
587
Vishnu Nair92990e22023-02-24 20:01:05 +0000588LayerSnapshot* LayerSnapshotBuilder::createSnapshot(const LayerHierarchy::TraversalPath& path,
589 const RequestedLayerState& layer,
590 const LayerSnapshot& parentSnapshot) {
591 mSnapshots.emplace_back(std::make_unique<LayerSnapshot>(layer, path));
Vishnu Naircfb2d252023-01-19 04:44:02 +0000592 LayerSnapshot* snapshot = mSnapshots.back().get();
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000593 snapshot->globalZ = static_cast<size_t>(mSnapshots.size()) - 1;
Vishnu Nair491827d2024-04-29 23:43:26 +0000594 if (path.isClone() && !LayerHierarchy::isMirror(path.variant)) {
Vishnu Nair92990e22023-02-24 20:01:05 +0000595 snapshot->mirrorRootPath = parentSnapshot.mirrorRootPath;
596 }
Vishnu Nair491827d2024-04-29 23:43:26 +0000597 snapshot->ignoreLocalTransform =
598 path.isClone() && path.variant == LayerHierarchy::Variant::Detached_Mirror;
Vishnu Naira02943f2023-06-03 13:44:46 -0700599 mPathToSnapshot[path] = snapshot;
600
601 mIdToSnapshots.emplace(path.id, snapshot);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000602 return snapshot;
603}
604
Vishnu Nairfccd6362023-02-24 23:39:53 +0000605bool LayerSnapshotBuilder::sortSnapshotsByZ(const Args& args) {
Vishnu Naird47bcee2023-02-24 18:08:51 +0000606 if (!mResortSnapshots && args.forceUpdate == ForceUpdateFlags::NONE &&
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000607 !args.layerLifecycleManager.getGlobalChanges().any(
Chavi Weingarten92c7d8c2024-01-19 23:25:45 +0000608 RequestedLayerState::Changes::Hierarchy | RequestedLayerState::Changes::Visibility |
609 RequestedLayerState::Changes::Input)) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000610 // We are not force updating and there are no hierarchy or visibility changes. Avoid sorting
611 // the snapshots.
Vishnu Nairfccd6362023-02-24 23:39:53 +0000612 return false;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000613 }
Vishnu Naircfb2d252023-01-19 04:44:02 +0000614 mResortSnapshots = false;
615
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000616 size_t globalZ = 0;
617 args.root.traverseInZOrder(
618 [this, &globalZ](const LayerHierarchy&,
619 const LayerHierarchy::TraversalPath& traversalPath) -> bool {
620 LayerSnapshot* snapshot = getSnapshot(traversalPath);
621 if (!snapshot) {
Vishnu Naira02943f2023-06-03 13:44:46 -0700622 return true;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000623 }
624
Vishnu Naircfb2d252023-01-19 04:44:02 +0000625 if (snapshot->getIsVisible() || snapshot->hasInputInfo()) {
Vishnu Nair80a5a702023-02-11 01:21:51 +0000626 updateVisibility(*snapshot, snapshot->getIsVisible());
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000627 size_t oldZ = snapshot->globalZ;
628 size_t newZ = globalZ++;
629 snapshot->globalZ = newZ;
630 if (oldZ == newZ) {
631 return true;
632 }
633 mSnapshots[newZ]->globalZ = oldZ;
Vishnu Naircfb2d252023-01-19 04:44:02 +0000634 LLOGV(snapshot->sequence, "Made visible z=%zu -> %zu %s", oldZ, newZ,
635 snapshot->getDebugString().c_str());
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000636 std::iter_swap(mSnapshots.begin() + static_cast<ssize_t>(oldZ),
637 mSnapshots.begin() + static_cast<ssize_t>(newZ));
638 }
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000639 return true;
640 });
Vishnu Naircfb2d252023-01-19 04:44:02 +0000641 mNumInterestingSnapshots = (int)globalZ;
Vishnu Nairfccd6362023-02-24 23:39:53 +0000642 bool hasUnreachableSnapshots = false;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000643 while (globalZ < mSnapshots.size()) {
644 mSnapshots[globalZ]->globalZ = globalZ;
Vishnu Nair80a5a702023-02-11 01:21:51 +0000645 /* mark unreachable snapshots as explicitly invisible */
646 updateVisibility(*mSnapshots[globalZ], false);
Vishnu Naira02943f2023-06-03 13:44:46 -0700647 if (mSnapshots[globalZ]->reachablilty == LayerSnapshot::Reachablilty::Unreachable) {
Vishnu Nairfccd6362023-02-24 23:39:53 +0000648 hasUnreachableSnapshots = true;
649 }
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000650 globalZ++;
651 }
Vishnu Nairfccd6362023-02-24 23:39:53 +0000652 return hasUnreachableSnapshots;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000653}
654
655void LayerSnapshotBuilder::updateRelativeState(LayerSnapshot& snapshot,
656 const LayerSnapshot& parentSnapshot,
657 bool parentIsRelative, const Args& args) {
658 if (parentIsRelative) {
Vishnu Naircfb2d252023-01-19 04:44:02 +0000659 snapshot.isHiddenByPolicyFromRelativeParent =
660 parentSnapshot.isHiddenByPolicyFromParent || parentSnapshot.invalidTransform;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000661 if (args.includeMetadata) {
662 snapshot.relativeLayerMetadata = parentSnapshot.layerMetadata;
663 }
664 } else {
665 snapshot.isHiddenByPolicyFromRelativeParent =
666 parentSnapshot.isHiddenByPolicyFromRelativeParent;
667 if (args.includeMetadata) {
668 snapshot.relativeLayerMetadata = parentSnapshot.relativeLayerMetadata;
669 }
670 }
Vishnu Naira02943f2023-06-03 13:44:46 -0700671 if (snapshot.reachablilty == LayerSnapshot::Reachablilty::Unreachable) {
672 snapshot.reachablilty = LayerSnapshot::Reachablilty::ReachableByRelativeParent;
673 }
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000674}
675
Vishnu Nair42b918e2023-07-18 20:05:29 +0000676void LayerSnapshotBuilder::updateFrameRateFromChildSnapshot(LayerSnapshot& snapshot,
677 const LayerSnapshot& childSnapshot,
678 const Args& args) {
679 if (args.forceUpdate == ForceUpdateFlags::NONE &&
Vishnu Nair52d56fd2023-07-20 17:02:43 +0000680 !args.layerLifecycleManager.getGlobalChanges().any(
681 RequestedLayerState::Changes::Hierarchy) &&
682 !childSnapshot.changes.any(RequestedLayerState::Changes::FrameRate) &&
683 !snapshot.changes.any(RequestedLayerState::Changes::FrameRate)) {
Vishnu Naircfb2d252023-01-19 04:44:02 +0000684 return;
685 }
Vishnu Naircfb2d252023-01-19 04:44:02 +0000686
Vishnu Nair3fbe3262023-09-29 17:07:00 -0700687 using FrameRateCompatibility = scheduler::FrameRateCompatibility;
Rachel Leece6e0042023-06-27 11:22:54 -0700688 if (snapshot.frameRate.isValid()) {
Vishnu Nair42b918e2023-07-18 20:05:29 +0000689 // we already have a valid framerate.
690 return;
691 }
Vishnu Naircfb2d252023-01-19 04:44:02 +0000692
Vishnu Nair42b918e2023-07-18 20:05:29 +0000693 // We return whether this layer or its children has a vote. We ignore ExactOrMultiple votes
694 // for the same reason we are allowing touch boost for those layers. See
695 // RefreshRateSelector::rankFrameRates for details.
Rachel Leece6e0042023-06-27 11:22:54 -0700696 const auto layerVotedWithDefaultCompatibility = childSnapshot.frameRate.vote.rate.isValid() &&
697 childSnapshot.frameRate.vote.type == FrameRateCompatibility::Default;
Vishnu Nair42b918e2023-07-18 20:05:29 +0000698 const auto layerVotedWithNoVote =
Rachel Leece6e0042023-06-27 11:22:54 -0700699 childSnapshot.frameRate.vote.type == FrameRateCompatibility::NoVote;
700 const auto layerVotedWithCategory =
701 childSnapshot.frameRate.category != FrameRateCategory::Default;
702 const auto layerVotedWithExactCompatibility = childSnapshot.frameRate.vote.rate.isValid() &&
703 childSnapshot.frameRate.vote.type == FrameRateCompatibility::Exact;
Vishnu Nair42b918e2023-07-18 20:05:29 +0000704
705 bool childHasValidFrameRate = layerVotedWithDefaultCompatibility || layerVotedWithNoVote ||
Rachel Leece6e0042023-06-27 11:22:54 -0700706 layerVotedWithCategory || layerVotedWithExactCompatibility;
Vishnu Nair42b918e2023-07-18 20:05:29 +0000707
708 // If we don't have a valid frame rate, but the children do, we set this
709 // layer as NoVote to allow the children to control the refresh rate
710 if (childHasValidFrameRate) {
711 snapshot.frameRate = scheduler::LayerInfo::FrameRate(Fps(), FrameRateCompatibility::NoVote);
712 snapshot.changes |= RequestedLayerState::Changes::FrameRate;
Vishnu Naircfb2d252023-01-19 04:44:02 +0000713 }
714}
715
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000716void LayerSnapshotBuilder::resetRelativeState(LayerSnapshot& snapshot) {
717 snapshot.isHiddenByPolicyFromRelativeParent = false;
718 snapshot.relativeLayerMetadata.mMap.clear();
719}
720
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000721void LayerSnapshotBuilder::updateSnapshot(LayerSnapshot& snapshot, const Args& args,
722 const RequestedLayerState& requested,
723 const LayerSnapshot& parentSnapshot,
Vishnu Nair92990e22023-02-24 20:01:05 +0000724 const LayerHierarchy::TraversalPath& path) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000725 // Always update flags and visibility
726 ftl::Flags<RequestedLayerState::Changes> parentChanges = parentSnapshot.changes &
727 (RequestedLayerState::Changes::Hierarchy | RequestedLayerState::Changes::Geometry |
728 RequestedLayerState::Changes::Visibility | RequestedLayerState::Changes::Metadata |
Vishnu Nairf13c8982023-12-02 11:26:09 -0800729 RequestedLayerState::Changes::AffectsChildren | RequestedLayerState::Changes::Input |
Vishnu Naira02943f2023-06-03 13:44:46 -0700730 RequestedLayerState::Changes::FrameRate | RequestedLayerState::Changes::GameMode);
731 snapshot.changes |= parentChanges;
732 if (args.displayChanges) snapshot.changes |= RequestedLayerState::Changes::Geometry;
733 snapshot.reachablilty = LayerSnapshot::Reachablilty::Reachable;
734 snapshot.clientChanges |= (parentSnapshot.clientChanges & layer_state_t::AFFECTS_CHILDREN);
Vishnu Naircfb2d252023-01-19 04:44:02 +0000735 snapshot.isHiddenByPolicyFromParent = parentSnapshot.isHiddenByPolicyFromParent ||
Vishnu Nair3af0ec02023-02-10 04:13:48 +0000736 parentSnapshot.invalidTransform || requested.isHiddenByPolicy() ||
737 (args.excludeLayerIds.find(path.id) != args.excludeLayerIds.end());
Vishnu Nair80a5a702023-02-11 01:21:51 +0000738
Vishnu Nair92990e22023-02-24 20:01:05 +0000739 const bool forceUpdate = args.forceUpdate == ForceUpdateFlags::ALL ||
Vishnu Naira02943f2023-06-03 13:44:46 -0700740 snapshot.clientChanges & layer_state_t::eReparent ||
Vishnu Nair92990e22023-02-24 20:01:05 +0000741 snapshot.changes.any(RequestedLayerState::Changes::Visibility |
742 RequestedLayerState::Changes::Created);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000743
Vishnu Naira02943f2023-06-03 13:44:46 -0700744 if (forceUpdate || snapshot.clientChanges & layer_state_t::eLayerStackChanged) {
745 // If root layer, use the layer stack otherwise get the parent's layer stack.
746 snapshot.outputFilter.layerStack =
747 parentSnapshot.path == LayerHierarchy::TraversalPath::ROOT
748 ? requested.layerStack
749 : parentSnapshot.outputFilter.layerStack;
Vishnu Naircfb2d252023-01-19 04:44:02 +0000750 }
751
Chavi Weingartenb74093a2023-10-11 20:29:59 +0000752 if (forceUpdate || snapshot.clientChanges & layer_state_t::eTrustedOverlayChanged) {
753 snapshot.isTrustedOverlay = parentSnapshot.isTrustedOverlay || requested.isTrustedOverlay;
754 }
755
Vishnu Nair92990e22023-02-24 20:01:05 +0000756 if (snapshot.isHiddenByPolicyFromParent &&
757 !snapshot.changes.test(RequestedLayerState::Changes::Created)) {
Vishnu Naircfb2d252023-01-19 04:44:02 +0000758 if (forceUpdate ||
Vishnu Naira02943f2023-06-03 13:44:46 -0700759 snapshot.changes.any(RequestedLayerState::Changes::Geometry |
Vishnu Nair494a2e42023-11-10 17:21:19 -0800760 RequestedLayerState::Changes::BufferSize |
Vishnu Naircfb2d252023-01-19 04:44:02 +0000761 RequestedLayerState::Changes::Input)) {
762 updateInput(snapshot, requested, parentSnapshot, path, args);
763 }
Garfield Tan8eb8f352024-05-17 09:12:01 -0700764 if (forceUpdate ||
765 (args.includeMetadata &&
766 snapshot.changes.test(RequestedLayerState::Changes::Metadata))) {
767 updateMetadataAndGameMode(snapshot, requested, args, parentSnapshot);
768 }
Vishnu Naircfb2d252023-01-19 04:44:02 +0000769 return;
770 }
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000771
Vishnu Naira02943f2023-06-03 13:44:46 -0700772 if (forceUpdate || snapshot.changes.any(RequestedLayerState::Changes::Mirror)) {
773 // Display mirrors are always placed in a VirtualDisplay so we never want to capture layers
774 // marked as skip capture
775 snapshot.handleSkipScreenshotFlag = parentSnapshot.handleSkipScreenshotFlag ||
776 (requested.layerStackToMirror != ui::INVALID_LAYER_STACK);
777 }
778
779 if (forceUpdate || snapshot.clientChanges & layer_state_t::eAlphaChanged) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000780 snapshot.color.a = parentSnapshot.color.a * requested.color.a;
781 snapshot.alpha = snapshot.color.a;
Vishnu Nair29354ec2023-03-28 18:51:28 -0700782 snapshot.inputInfo.alpha = snapshot.color.a;
Vishnu Naira02943f2023-06-03 13:44:46 -0700783 }
Vishnu Nair29354ec2023-03-28 18:51:28 -0700784
Vishnu Naira02943f2023-06-03 13:44:46 -0700785 if (forceUpdate || snapshot.clientChanges & layer_state_t::eFlagsChanged) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000786 snapshot.isSecure =
787 parentSnapshot.isSecure || (requested.flags & layer_state_t::eLayerSecure);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000788 snapshot.outputFilter.toInternalDisplay = parentSnapshot.outputFilter.toInternalDisplay ||
789 (requested.flags & layer_state_t::eLayerSkipScreenshot);
Vishnu Naira02943f2023-06-03 13:44:46 -0700790 }
791
Vishnu Naira02943f2023-06-03 13:44:46 -0700792 if (forceUpdate || snapshot.clientChanges & layer_state_t::eStretchChanged) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000793 snapshot.stretchEffect = (requested.stretchEffect.hasEffect())
794 ? requested.stretchEffect
795 : parentSnapshot.stretchEffect;
Vishnu Naira02943f2023-06-03 13:44:46 -0700796 }
797
798 if (forceUpdate || snapshot.clientChanges & layer_state_t::eColorTransformChanged) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000799 if (!parentSnapshot.colorTransformIsIdentity) {
800 snapshot.colorTransform = parentSnapshot.colorTransform * requested.colorTransform;
801 snapshot.colorTransformIsIdentity = false;
802 } else {
803 snapshot.colorTransform = requested.colorTransform;
804 snapshot.colorTransformIsIdentity = !requested.hasColorTransform;
805 }
Vishnu Naira02943f2023-06-03 13:44:46 -0700806 }
807
Nergi Rahardi6431d4a2024-05-15 18:42:48 +0900808 if (forceUpdate || snapshot.changes.test(RequestedLayerState::Changes::Metadata)) {
Garfield Tan8eb8f352024-05-17 09:12:01 -0700809 updateMetadataAndGameMode(snapshot, requested, args, parentSnapshot);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000810 }
811
Vishnu Naira02943f2023-06-03 13:44:46 -0700812 if (forceUpdate || snapshot.clientChanges & layer_state_t::eFixedTransformHintChanged ||
Vishnu Nairb76d99a2023-03-19 18:22:31 -0700813 args.displayChanges) {
814 snapshot.fixedTransformHint = requested.fixedTransformHint != ui::Transform::ROT_INVALID
815 ? requested.fixedTransformHint
816 : parentSnapshot.fixedTransformHint;
817
818 if (snapshot.fixedTransformHint != ui::Transform::ROT_INVALID) {
819 snapshot.transformHint = snapshot.fixedTransformHint;
820 } else {
821 const auto display = args.displays.get(snapshot.outputFilter.layerStack);
822 snapshot.transformHint = display.has_value()
823 ? std::make_optional<>(display->get().transformHint)
824 : std::nullopt;
825 }
826 }
827
Vishnu Nair42b918e2023-07-18 20:05:29 +0000828 if (forceUpdate ||
Vishnu Nair52d56fd2023-07-20 17:02:43 +0000829 args.layerLifecycleManager.getGlobalChanges().any(
830 RequestedLayerState::Changes::Hierarchy) ||
Vishnu Nair42b918e2023-07-18 20:05:29 +0000831 snapshot.changes.any(RequestedLayerState::Changes::FrameRate |
832 RequestedLayerState::Changes::Hierarchy)) {
Rachel Leea021bb02023-11-20 21:51:09 -0800833 const bool shouldOverrideChildren = parentSnapshot.frameRateSelectionStrategy ==
Rachel Lee58cc90d2023-09-05 18:50:20 -0700834 scheduler::LayerInfo::FrameRateSelectionStrategy::OverrideChildren;
Rachel Leea021bb02023-11-20 21:51:09 -0800835 const bool propagationAllowed = parentSnapshot.frameRateSelectionStrategy !=
Rachel Lee70f7b692023-11-22 11:24:02 -0800836 scheduler::LayerInfo::FrameRateSelectionStrategy::Self;
Rachel Leea021bb02023-11-20 21:51:09 -0800837 if ((!requested.requestedFrameRate.isValid() && propagationAllowed) ||
838 shouldOverrideChildren) {
Vishnu Nair30515cb2023-10-19 21:54:08 -0700839 snapshot.inheritedFrameRate = parentSnapshot.inheritedFrameRate;
840 } else {
841 snapshot.inheritedFrameRate = requested.requestedFrameRate;
842 }
843 // Set the framerate as the inherited frame rate and allow children to override it if
844 // needed.
845 snapshot.frameRate = snapshot.inheritedFrameRate;
Vishnu Nair52d56fd2023-07-20 17:02:43 +0000846 snapshot.changes |= RequestedLayerState::Changes::FrameRate;
Vishnu Naird47bcee2023-02-24 18:08:51 +0000847 }
848
Rachel Lee58cc90d2023-09-05 18:50:20 -0700849 if (forceUpdate || snapshot.clientChanges & layer_state_t::eFrameRateSelectionStrategyChanged) {
Rachel Leea021bb02023-11-20 21:51:09 -0800850 if (parentSnapshot.frameRateSelectionStrategy ==
851 scheduler::LayerInfo::FrameRateSelectionStrategy::OverrideChildren) {
852 snapshot.frameRateSelectionStrategy =
853 scheduler::LayerInfo::FrameRateSelectionStrategy::OverrideChildren;
854 } else {
855 const auto strategy = scheduler::LayerInfo::convertFrameRateSelectionStrategy(
856 requested.frameRateSelectionStrategy);
857 snapshot.frameRateSelectionStrategy = strategy;
858 }
Rachel Lee58cc90d2023-09-05 18:50:20 -0700859 }
860
Vishnu Nair3d8565a2023-06-30 07:23:24 +0000861 if (forceUpdate || snapshot.clientChanges & layer_state_t::eFrameRateSelectionPriority) {
862 snapshot.frameRateSelectionPriority =
863 (requested.frameRateSelectionPriority == Layer::PRIORITY_UNSET)
864 ? parentSnapshot.frameRateSelectionPriority
865 : requested.frameRateSelectionPriority;
866 }
867
Vishnu Naira02943f2023-06-03 13:44:46 -0700868 if (forceUpdate ||
869 snapshot.clientChanges &
870 (layer_state_t::eBackgroundBlurRadiusChanged | layer_state_t::eBlurRegionsChanged |
871 layer_state_t::eAlphaChanged)) {
Vishnu Nair80a5a702023-02-11 01:21:51 +0000872 snapshot.backgroundBlurRadius = args.supportsBlur
873 ? static_cast<int>(parentSnapshot.color.a * (float)requested.backgroundBlurRadius)
874 : 0;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000875 snapshot.blurRegions = requested.blurRegions;
Vishnu Nair80a5a702023-02-11 01:21:51 +0000876 for (auto& region : snapshot.blurRegions) {
877 region.alpha = region.alpha * snapshot.color.a;
878 }
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000879 }
880
Vishnu Naira02943f2023-06-03 13:44:46 -0700881 if (forceUpdate || snapshot.changes.any(RequestedLayerState::Changes::Geometry)) {
882 uint32_t primaryDisplayRotationFlags = getPrimaryDisplayRotationFlags(args.displays);
Vishnu Nairb76d99a2023-03-19 18:22:31 -0700883 updateLayerBounds(snapshot, requested, parentSnapshot, primaryDisplayRotationFlags);
Vishnu Naira02943f2023-06-03 13:44:46 -0700884 }
885
886 if (forceUpdate || snapshot.clientChanges & layer_state_t::eCornerRadiusChanged ||
Vishnu Nair0808ae62023-08-07 21:42:42 -0700887 snapshot.changes.any(RequestedLayerState::Changes::Geometry |
888 RequestedLayerState::Changes::BufferUsageFlags)) {
889 updateRoundedCorner(snapshot, requested, parentSnapshot, args);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000890 }
891
Vishnu Naira02943f2023-06-03 13:44:46 -0700892 if (forceUpdate || snapshot.clientChanges & layer_state_t::eShadowRadiusChanged ||
893 snapshot.changes.any(RequestedLayerState::Changes::Geometry)) {
894 updateShadows(snapshot, requested, args.globalShadowSettings);
895 }
896
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000897 if (forceUpdate ||
Vishnu Naira02943f2023-06-03 13:44:46 -0700898 snapshot.changes.any(RequestedLayerState::Changes::Geometry |
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000899 RequestedLayerState::Changes::Input)) {
Vishnu Naircfb2d252023-01-19 04:44:02 +0000900 updateInput(snapshot, requested, parentSnapshot, path, args);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000901 }
902
903 // computed snapshot properties
Alec Mouri994761f2023-08-04 21:50:55 +0000904 snapshot.forceClientComposition =
905 snapshot.shadowSettings.length > 0 || snapshot.stretchEffect.hasEffect();
Vishnu Nairc765c6c2023-02-23 00:08:01 +0000906 snapshot.contentOpaque = snapshot.isContentOpaque();
907 snapshot.isOpaque = snapshot.contentOpaque && !snapshot.roundedCorner.hasRoundedCorners() &&
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000908 snapshot.color.a == 1.f;
909 snapshot.blendMode = getBlendMode(snapshot, requested);
Vishnu Naircfb2d252023-01-19 04:44:02 +0000910 LLOGV(snapshot.sequence,
Vishnu Nair92990e22023-02-24 20:01:05 +0000911 "%supdated %s changes:%s parent:%s requested:%s requested:%s from parent %s",
912 args.forceUpdate == ForceUpdateFlags::ALL ? "Force " : "",
913 snapshot.getDebugString().c_str(), snapshot.changes.string().c_str(),
914 parentSnapshot.changes.string().c_str(), requested.changes.string().c_str(),
915 std::to_string(requested.what).c_str(), parentSnapshot.getDebugString().c_str());
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000916}
917
918void LayerSnapshotBuilder::updateRoundedCorner(LayerSnapshot& snapshot,
919 const RequestedLayerState& requested,
Vishnu Nair0808ae62023-08-07 21:42:42 -0700920 const LayerSnapshot& parentSnapshot,
921 const Args& args) {
922 if (args.skipRoundCornersWhenProtected && requested.isProtected()) {
923 snapshot.roundedCorner = RoundedCornerState();
924 return;
925 }
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000926 snapshot.roundedCorner = RoundedCornerState();
927 RoundedCornerState parentRoundedCorner;
928 if (parentSnapshot.roundedCorner.hasRoundedCorners()) {
929 parentRoundedCorner = parentSnapshot.roundedCorner;
930 ui::Transform t = snapshot.localTransform.inverse();
931 parentRoundedCorner.cropRect = t.transform(parentRoundedCorner.cropRect);
932 parentRoundedCorner.radius.x *= t.getScaleX();
933 parentRoundedCorner.radius.y *= t.getScaleY();
934 }
935
936 FloatRect layerCropRect = snapshot.croppedBufferSize.toFloatRect();
937 const vec2 radius(requested.cornerRadius, requested.cornerRadius);
938 RoundedCornerState layerSettings(layerCropRect, radius);
939 const bool layerSettingsValid = layerSettings.hasRoundedCorners() && !layerCropRect.isEmpty();
940 const bool parentRoundedCornerValid = parentRoundedCorner.hasRoundedCorners();
941 if (layerSettingsValid && parentRoundedCornerValid) {
942 // If the parent and the layer have rounded corner settings, use the parent settings if
943 // the parent crop is entirely inside the layer crop. This has limitations and cause
944 // rendering artifacts. See b/200300845 for correct fix.
945 if (parentRoundedCorner.cropRect.left > layerCropRect.left &&
946 parentRoundedCorner.cropRect.top > layerCropRect.top &&
947 parentRoundedCorner.cropRect.right < layerCropRect.right &&
948 parentRoundedCorner.cropRect.bottom < layerCropRect.bottom) {
949 snapshot.roundedCorner = parentRoundedCorner;
950 } else {
951 snapshot.roundedCorner = layerSettings;
952 }
953 } else if (layerSettingsValid) {
954 snapshot.roundedCorner = layerSettings;
955 } else if (parentRoundedCornerValid) {
956 snapshot.roundedCorner = parentRoundedCorner;
957 }
958}
959
960void LayerSnapshotBuilder::updateLayerBounds(LayerSnapshot& snapshot,
961 const RequestedLayerState& requested,
962 const LayerSnapshot& parentSnapshot,
Vishnu Nairb76d99a2023-03-19 18:22:31 -0700963 uint32_t primaryDisplayRotationFlags) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000964 snapshot.geomLayerTransform = parentSnapshot.geomLayerTransform * snapshot.localTransform;
Vishnu Naircfb2d252023-01-19 04:44:02 +0000965 const bool transformWasInvalid = snapshot.invalidTransform;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000966 snapshot.invalidTransform = !LayerSnapshot::isTransformValid(snapshot.geomLayerTransform);
967 if (snapshot.invalidTransform) {
Vishnu Naircfb2d252023-01-19 04:44:02 +0000968 auto& t = snapshot.geomLayerTransform;
969 auto& requestedT = requested.requestedTransform;
970 std::string transformDebug =
971 base::StringPrintf(" transform={%f,%f,%f,%f} requestedTransform={%f,%f,%f,%f}",
972 t.dsdx(), t.dsdy(), t.dtdx(), t.dtdy(), requestedT.dsdx(),
973 requestedT.dsdy(), requestedT.dtdx(), requestedT.dtdy());
974 std::string bufferDebug;
975 if (requested.externalTexture) {
Vishnu Nairb76d99a2023-03-19 18:22:31 -0700976 auto unRotBuffer = requested.getUnrotatedBufferSize(primaryDisplayRotationFlags);
Vishnu Naircfb2d252023-01-19 04:44:02 +0000977 auto& destFrame = requested.destinationFrame;
978 bufferDebug = base::StringPrintf(" buffer={%d,%d} displayRot=%d"
979 " destFrame={%d,%d,%d,%d} unRotBuffer={%d,%d}",
980 requested.externalTexture->getWidth(),
981 requested.externalTexture->getHeight(),
Vishnu Nairb76d99a2023-03-19 18:22:31 -0700982 primaryDisplayRotationFlags, destFrame.left,
983 destFrame.top, destFrame.right, destFrame.bottom,
Vishnu Naircfb2d252023-01-19 04:44:02 +0000984 unRotBuffer.getHeight(), unRotBuffer.getWidth());
985 }
986 ALOGW("Resetting transform for %s because it is invalid.%s%s",
987 snapshot.getDebugString().c_str(), transformDebug.c_str(), bufferDebug.c_str());
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000988 snapshot.geomLayerTransform.reset();
989 }
Vishnu Naircfb2d252023-01-19 04:44:02 +0000990 if (transformWasInvalid != snapshot.invalidTransform) {
991 // If transform is invalid, the layer will be hidden.
992 mResortSnapshots = true;
993 }
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000994 snapshot.geomInverseLayerTransform = snapshot.geomLayerTransform.inverse();
995
996 FloatRect parentBounds = parentSnapshot.geomLayerBounds;
997 parentBounds = snapshot.localTransform.inverse().transform(parentBounds);
998 snapshot.geomLayerBounds =
999 (requested.externalTexture) ? snapshot.bufferSize.toFloatRect() : parentBounds;
1000 if (!requested.crop.isEmpty()) {
1001 snapshot.geomLayerBounds = snapshot.geomLayerBounds.intersect(requested.crop.toFloatRect());
1002 }
1003 snapshot.geomLayerBounds = snapshot.geomLayerBounds.intersect(parentBounds);
1004 snapshot.transformedBounds = snapshot.geomLayerTransform.transform(snapshot.geomLayerBounds);
Vishnu Naircfb2d252023-01-19 04:44:02 +00001005 const Rect geomLayerBoundsWithoutTransparentRegion =
1006 RequestedLayerState::reduce(Rect(snapshot.geomLayerBounds),
1007 requested.transparentRegion);
1008 snapshot.transformedBoundsWithoutTransparentRegion =
1009 snapshot.geomLayerTransform.transform(geomLayerBoundsWithoutTransparentRegion);
Vishnu Nair8fc721b2022-12-22 20:06:32 +00001010 snapshot.parentTransform = parentSnapshot.geomLayerTransform;
1011
1012 // Subtract the transparent region and snap to the bounds
Vishnu Naircfb2d252023-01-19 04:44:02 +00001013 const Rect bounds =
Vishnu Nair8fc721b2022-12-22 20:06:32 +00001014 RequestedLayerState::reduce(snapshot.croppedBufferSize, requested.transparentRegion);
Vishnu Naircfb2d252023-01-19 04:44:02 +00001015 if (requested.potentialCursor) {
1016 snapshot.cursorFrame = snapshot.geomLayerTransform.transform(bounds);
1017 }
Vishnu Nair8fc721b2022-12-22 20:06:32 +00001018}
1019
Vishnu Naira02943f2023-06-03 13:44:46 -07001020void LayerSnapshotBuilder::updateShadows(LayerSnapshot& snapshot, const RequestedLayerState&,
Vishnu Naird9e4f462023-10-06 04:05:45 +00001021 const ShadowSettings& globalShadowSettings) {
1022 if (snapshot.shadowSettings.length > 0.f) {
1023 snapshot.shadowSettings.ambientColor = globalShadowSettings.ambientColor;
1024 snapshot.shadowSettings.spotColor = globalShadowSettings.spotColor;
1025 snapshot.shadowSettings.lightPos = globalShadowSettings.lightPos;
1026 snapshot.shadowSettings.lightRadius = globalShadowSettings.lightRadius;
Vishnu Nair8fc721b2022-12-22 20:06:32 +00001027
1028 // Note: this preserves existing behavior of shadowing the entire layer and not cropping
1029 // it if transparent regions are present. This may not be necessary since shadows are
1030 // typically cast by layers without transparent regions.
1031 snapshot.shadowSettings.boundaries = snapshot.geomLayerBounds;
1032
1033 // If the casting layer is translucent, we need to fill in the shadow underneath the
1034 // layer. Otherwise the generated shadow will only be shown around the casting layer.
1035 snapshot.shadowSettings.casterIsTranslucent =
1036 !snapshot.isContentOpaque() || (snapshot.alpha < 1.0f);
1037 snapshot.shadowSettings.ambientColor *= snapshot.alpha;
1038 snapshot.shadowSettings.spotColor *= snapshot.alpha;
1039 }
1040}
1041
1042void LayerSnapshotBuilder::updateInput(LayerSnapshot& snapshot,
1043 const RequestedLayerState& requested,
1044 const LayerSnapshot& parentSnapshot,
Vishnu Naircfb2d252023-01-19 04:44:02 +00001045 const LayerHierarchy::TraversalPath& path,
1046 const Args& args) {
Prabir Pradhancf359192024-03-20 00:42:57 +00001047 using InputConfig = gui::WindowInfo::InputConfig;
1048
Vishnu Naircfb2d252023-01-19 04:44:02 +00001049 if (requested.windowInfoHandle) {
1050 snapshot.inputInfo = *requested.windowInfoHandle->getInfo();
1051 } else {
1052 snapshot.inputInfo = {};
Vishnu Nair40d02282023-02-28 21:11:40 +00001053 // b/271132344 revisit this and see if we can always use the layers uid/pid
1054 snapshot.inputInfo.name = requested.name;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001055 snapshot.inputInfo.ownerUid = gui::Uid{requested.ownerUid};
Prabir Pradhane59c6dc2023-06-13 19:53:03 +00001056 snapshot.inputInfo.ownerPid = gui::Pid{requested.ownerPid};
Vishnu Naircfb2d252023-01-19 04:44:02 +00001057 }
Vishnu Nair29354ec2023-03-28 18:51:28 -07001058 snapshot.touchCropId = requested.touchCropId;
Vishnu Naircfb2d252023-01-19 04:44:02 +00001059
Vishnu Nair93b8b792023-02-27 19:40:24 +00001060 snapshot.inputInfo.id = static_cast<int32_t>(snapshot.uniqueSequence);
Linnan Li13bf76a2024-05-05 19:18:02 +08001061 snapshot.inputInfo.displayId =
1062 ui::LogicalDisplayId{static_cast<int32_t>(snapshot.outputFilter.layerStack.id)};
Vishnu Nairf13c8982023-12-02 11:26:09 -08001063 snapshot.inputInfo.touchOcclusionMode = requested.hasInputInfo()
1064 ? requested.windowInfoHandle->getInfo()->touchOcclusionMode
1065 : parentSnapshot.inputInfo.touchOcclusionMode;
Vishnu Nair59a6be32024-01-29 10:26:21 -08001066 snapshot.inputInfo.canOccludePresentation = parentSnapshot.inputInfo.canOccludePresentation ||
1067 (requested.flags & layer_state_t::eCanOccludePresentation);
Vishnu Nairf13c8982023-12-02 11:26:09 -08001068 if (requested.dropInputMode == gui::DropInputMode::ALL ||
1069 parentSnapshot.dropInputMode == gui::DropInputMode::ALL) {
1070 snapshot.dropInputMode = gui::DropInputMode::ALL;
1071 } else if (requested.dropInputMode == gui::DropInputMode::OBSCURED ||
1072 parentSnapshot.dropInputMode == gui::DropInputMode::OBSCURED) {
1073 snapshot.dropInputMode = gui::DropInputMode::OBSCURED;
1074 } else {
1075 snapshot.dropInputMode = gui::DropInputMode::NONE;
1076 }
1077
Prabir Pradhancf359192024-03-20 00:42:57 +00001078 if (snapshot.isSecure ||
Arpit Singh490ccc92024-04-30 14:26:21 +00001079 parentSnapshot.inputInfo.inputConfig.test(InputConfig::SENSITIVE_FOR_PRIVACY)) {
1080 snapshot.inputInfo.inputConfig |= InputConfig::SENSITIVE_FOR_PRIVACY;
Prabir Pradhancf359192024-03-20 00:42:57 +00001081 }
1082
Vishnu Nair29354ec2023-03-28 18:51:28 -07001083 updateVisibility(snapshot, snapshot.isVisible);
Vishnu Naircfb2d252023-01-19 04:44:02 +00001084 if (!needsInputInfo(snapshot, requested)) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +00001085 return;
1086 }
1087
Vishnu Naircfb2d252023-01-19 04:44:02 +00001088 static frontend::DisplayInfo sDefaultInfo = {.isSecure = false};
1089 const std::optional<frontend::DisplayInfo> displayInfoOpt =
1090 args.displays.get(snapshot.outputFilter.layerStack);
1091 bool noValidDisplay = !displayInfoOpt.has_value();
1092 auto displayInfo = displayInfoOpt.value_or(sDefaultInfo);
1093
1094 if (!requested.windowInfoHandle) {
Prabir Pradhancf359192024-03-20 00:42:57 +00001095 snapshot.inputInfo.inputConfig = InputConfig::NO_INPUT_CHANNEL;
Vishnu Naircfb2d252023-01-19 04:44:02 +00001096 }
Vishnu Nair8fc721b2022-12-22 20:06:32 +00001097 fillInputFrameInfo(snapshot.inputInfo, displayInfo.transform, snapshot);
1098
1099 if (noValidDisplay) {
1100 // Do not let the window receive touches if it is not associated with a valid display
1101 // transform. We still allow the window to receive keys and prevent ANRs.
Prabir Pradhancf359192024-03-20 00:42:57 +00001102 snapshot.inputInfo.inputConfig |= InputConfig::NOT_TOUCHABLE;
Vishnu Nair8fc721b2022-12-22 20:06:32 +00001103 }
1104
Vishnu Nair8fc721b2022-12-22 20:06:32 +00001105 snapshot.inputInfo.alpha = snapshot.color.a;
Vishnu Nair8fc721b2022-12-22 20:06:32 +00001106
1107 handleDropInputMode(snapshot, parentSnapshot);
1108
1109 // If the window will be blacked out on a display because the display does not have the secure
1110 // flag and the layer has the secure flag set, then drop input.
1111 if (!displayInfo.isSecure && snapshot.isSecure) {
Prabir Pradhancf359192024-03-20 00:42:57 +00001112 snapshot.inputInfo.inputConfig |= InputConfig::DROP_INPUT;
Vishnu Nair8fc721b2022-12-22 20:06:32 +00001113 }
1114
Vishnu Naira02943f2023-06-03 13:44:46 -07001115 if (requested.touchCropId != UNASSIGNED_LAYER_ID || path.isClone()) {
Vishnu Nair29354ec2023-03-28 18:51:28 -07001116 mNeedsTouchableRegionCrop.insert(path);
Vishnu Naira02943f2023-06-03 13:44:46 -07001117 }
1118 auto cropLayerSnapshot = getSnapshot(requested.touchCropId);
1119 if (!cropLayerSnapshot && snapshot.inputInfo.replaceTouchableRegionWithCrop) {
Vishnu Nair29354ec2023-03-28 18:51:28 -07001120 FloatRect inputBounds = getInputBounds(snapshot, /*fillParentBounds=*/true).first;
Vishnu Nairfed7c122023-03-18 01:54:43 +00001121 Rect inputBoundsInDisplaySpace =
Vishnu Nair29354ec2023-03-28 18:51:28 -07001122 getInputBoundsInDisplaySpace(snapshot, inputBounds, displayInfo.transform);
1123 snapshot.inputInfo.touchableRegion = Region(inputBoundsInDisplaySpace);
Vishnu Nair8fc721b2022-12-22 20:06:32 +00001124 }
1125
1126 // Inherit the trusted state from the parent hierarchy, but don't clobber the trusted state
1127 // if it was set by WM for a known system overlay
1128 if (snapshot.isTrustedOverlay) {
Prabir Pradhancf359192024-03-20 00:42:57 +00001129 snapshot.inputInfo.inputConfig |= InputConfig::TRUSTED_OVERLAY;
Vishnu Nair8fc721b2022-12-22 20:06:32 +00001130 }
1131
Vishnu Nair494a2e42023-11-10 17:21:19 -08001132 snapshot.inputInfo.contentSize = snapshot.croppedBufferSize.getSize();
1133
Vishnu Nair8fc721b2022-12-22 20:06:32 +00001134 // If the layer is a clone, we need to crop the input region to cloned root to prevent
1135 // touches from going outside the cloned area.
1136 if (path.isClone()) {
Prabir Pradhancf359192024-03-20 00:42:57 +00001137 snapshot.inputInfo.inputConfig |= InputConfig::CLONE;
Vishnu Nair444f3952023-04-11 13:01:02 -07001138 // Cloned layers shouldn't handle watch outside since their z order is not determined by
1139 // WM or the client.
Prabir Pradhancf359192024-03-20 00:42:57 +00001140 snapshot.inputInfo.inputConfig.clear(InputConfig::WATCH_OUTSIDE_TOUCH);
Vishnu Nair8fc721b2022-12-22 20:06:32 +00001141 }
1142}
1143
1144std::vector<std::unique_ptr<LayerSnapshot>>& LayerSnapshotBuilder::getSnapshots() {
1145 return mSnapshots;
1146}
1147
Vishnu Naircfb2d252023-01-19 04:44:02 +00001148void LayerSnapshotBuilder::forEachVisibleSnapshot(const ConstVisitor& visitor) const {
1149 for (int i = 0; i < mNumInterestingSnapshots; i++) {
1150 LayerSnapshot& snapshot = *mSnapshots[(size_t)i];
1151 if (!snapshot.isVisible) continue;
1152 visitor(snapshot);
1153 }
1154}
1155
Vishnu Nair3af0ec02023-02-10 04:13:48 +00001156// Visit each visible snapshot in z-order
1157void LayerSnapshotBuilder::forEachVisibleSnapshot(const ConstVisitor& visitor,
1158 const LayerHierarchy& root) const {
1159 root.traverseInZOrder(
1160 [this, visitor](const LayerHierarchy&,
1161 const LayerHierarchy::TraversalPath& traversalPath) -> bool {
1162 LayerSnapshot* snapshot = getSnapshot(traversalPath);
1163 if (snapshot && snapshot->isVisible) {
1164 visitor(*snapshot);
1165 }
1166 return true;
1167 });
1168}
1169
Vishnu Naircfb2d252023-01-19 04:44:02 +00001170void LayerSnapshotBuilder::forEachVisibleSnapshot(const Visitor& visitor) {
1171 for (int i = 0; i < mNumInterestingSnapshots; i++) {
1172 std::unique_ptr<LayerSnapshot>& snapshot = mSnapshots.at((size_t)i);
1173 if (!snapshot->isVisible) continue;
1174 visitor(snapshot);
1175 }
1176}
1177
Garfield Tan8eb8f352024-05-17 09:12:01 -07001178void LayerSnapshotBuilder::forEachSnapshot(const Visitor& visitor,
1179 const ConstPredicate& predicate) {
1180 for (int i = 0; i < mNumInterestingSnapshots; i++) {
1181 std::unique_ptr<LayerSnapshot>& snapshot = mSnapshots.at((size_t)i);
1182 if (!predicate(*snapshot)) continue;
1183 visitor(snapshot);
1184 }
1185}
1186
Vishnu Naircfb2d252023-01-19 04:44:02 +00001187void LayerSnapshotBuilder::forEachInputSnapshot(const ConstVisitor& visitor) const {
1188 for (int i = mNumInterestingSnapshots - 1; i >= 0; i--) {
1189 LayerSnapshot& snapshot = *mSnapshots[(size_t)i];
1190 if (!snapshot.hasInputInfo()) continue;
1191 visitor(snapshot);
1192 }
1193}
1194
Vishnu Nair29354ec2023-03-28 18:51:28 -07001195void LayerSnapshotBuilder::updateTouchableRegionCrop(const Args& args) {
1196 if (mNeedsTouchableRegionCrop.empty()) {
1197 return;
1198 }
1199
1200 static constexpr ftl::Flags<RequestedLayerState::Changes> AFFECTS_INPUT =
1201 RequestedLayerState::Changes::Visibility | RequestedLayerState::Changes::Created |
1202 RequestedLayerState::Changes::Hierarchy | RequestedLayerState::Changes::Geometry |
1203 RequestedLayerState::Changes::Input;
1204
1205 if (args.forceUpdate != ForceUpdateFlags::ALL &&
Vishnu Naira02943f2023-06-03 13:44:46 -07001206 !args.layerLifecycleManager.getGlobalChanges().any(AFFECTS_INPUT) && !args.displayChanges) {
Vishnu Nair29354ec2023-03-28 18:51:28 -07001207 return;
1208 }
1209
1210 for (auto& path : mNeedsTouchableRegionCrop) {
1211 frontend::LayerSnapshot* snapshot = getSnapshot(path);
1212 if (!snapshot) {
1213 continue;
1214 }
Vishnu Naira02943f2023-06-03 13:44:46 -07001215 LLOGV(snapshot->sequence, "updateTouchableRegionCrop=%s",
1216 snapshot->getDebugString().c_str());
Vishnu Nair29354ec2023-03-28 18:51:28 -07001217 const std::optional<frontend::DisplayInfo> displayInfoOpt =
1218 args.displays.get(snapshot->outputFilter.layerStack);
1219 static frontend::DisplayInfo sDefaultInfo = {.isSecure = false};
1220 auto displayInfo = displayInfoOpt.value_or(sDefaultInfo);
1221
1222 bool needsUpdate =
1223 args.forceUpdate == ForceUpdateFlags::ALL || snapshot->changes.any(AFFECTS_INPUT);
1224 auto cropLayerSnapshot = getSnapshot(snapshot->touchCropId);
1225 needsUpdate =
1226 needsUpdate || (cropLayerSnapshot && cropLayerSnapshot->changes.any(AFFECTS_INPUT));
1227 auto clonedRootSnapshot = path.isClone() ? getSnapshot(snapshot->mirrorRootPath) : nullptr;
1228 needsUpdate = needsUpdate ||
1229 (clonedRootSnapshot && clonedRootSnapshot->changes.any(AFFECTS_INPUT));
1230
1231 if (!needsUpdate) {
1232 continue;
1233 }
1234
1235 if (snapshot->inputInfo.replaceTouchableRegionWithCrop) {
1236 Rect inputBoundsInDisplaySpace;
1237 if (!cropLayerSnapshot) {
1238 FloatRect inputBounds = getInputBounds(*snapshot, /*fillParentBounds=*/true).first;
1239 inputBoundsInDisplaySpace =
1240 getInputBoundsInDisplaySpace(*snapshot, inputBounds, displayInfo.transform);
1241 } else {
1242 FloatRect inputBounds =
1243 getInputBounds(*cropLayerSnapshot, /*fillParentBounds=*/true).first;
1244 inputBoundsInDisplaySpace =
1245 getInputBoundsInDisplaySpace(*cropLayerSnapshot, inputBounds,
1246 displayInfo.transform);
1247 }
1248 snapshot->inputInfo.touchableRegion = Region(inputBoundsInDisplaySpace);
1249 } else if (cropLayerSnapshot) {
1250 FloatRect inputBounds =
1251 getInputBounds(*cropLayerSnapshot, /*fillParentBounds=*/true).first;
1252 Rect inputBoundsInDisplaySpace =
1253 getInputBoundsInDisplaySpace(*cropLayerSnapshot, inputBounds,
1254 displayInfo.transform);
Chavi Weingarten1ba381e2024-01-09 21:54:11 +00001255 snapshot->inputInfo.touchableRegion =
1256 snapshot->inputInfo.touchableRegion.intersect(inputBoundsInDisplaySpace);
Vishnu Nair29354ec2023-03-28 18:51:28 -07001257 }
1258
1259 // If the layer is a clone, we need to crop the input region to cloned root to prevent
1260 // touches from going outside the cloned area.
1261 if (clonedRootSnapshot) {
1262 const Rect rect =
1263 displayInfo.transform.transform(Rect{clonedRootSnapshot->transformedBounds});
1264 snapshot->inputInfo.touchableRegion =
1265 snapshot->inputInfo.touchableRegion.intersect(rect);
1266 }
1267 }
1268}
1269
Vishnu Nair8fc721b2022-12-22 20:06:32 +00001270} // namespace android::surfaceflinger::frontend