1 /*
2 * Copyright 2022 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 // #define LOG_NDEBUG 0
18 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
19 #undef LOG_TAG
20 #define LOG_TAG "SurfaceFlinger"
21
22 #include <numeric>
23 #include <optional>
24
25 #include <common/FlagManager.h>
26 #include <common/trace.h>
27 #include <ftl/small_map.h>
28 #include <ui/DisplayMap.h>
29 #include <ui/FloatRect.h>
30
31 #include "DisplayHardware/HWC2.h"
32 #include "DisplayHardware/Hal.h"
33 #include "Layer.h" // eFrameRateSelectionPriority constants
34 #include "LayerLog.h"
35 #include "LayerSnapshotBuilder.h"
36 #include "TimeStats/TimeStats.h"
37 #include "Tracing/TransactionTracing.h"
38
39 namespace android::surfaceflinger::frontend {
40
41 using namespace ftl::flag_operators;
42
43 namespace {
44
getMaxDisplayBounds(const DisplayInfos & displays)45 FloatRect getMaxDisplayBounds(const DisplayInfos& displays) {
46 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.
transformTouchableRegionSafely(const ui::Transform & t,const Region & r,const std::string & debugWindowName)68 Region 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 */
getInputTransform(const LayerSnapshot & snapshot)104 ui::Transform getInputTransform(const LayerSnapshot& snapshot) {
105 if (!snapshot.hasBufferOrSidebandStream()) {
106 return snapshot.geomLayerTransform;
107 }
108 return snapshot.parentTransform;
109 }
110
111 /**
112 * Returns the bounds used to fill the input frame and the touchable region.
113 *
114 * 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 */
getInputBounds(const LayerSnapshot & snapshot,bool fillParentBounds)118 std::pair<FloatRect, bool> getInputBounds(const LayerSnapshot& snapshot, bool fillParentBounds) {
119 FloatRect inputBounds = snapshot.croppedBufferSize;
120 if (snapshot.hasBufferOrSidebandStream() && snapshot.croppedBufferSize.isValid() &&
121 snapshot.localTransform.getType() != ui::Transform::IDENTITY) {
122 inputBounds = snapshot.localTransform.transform(inputBounds);
123 }
124
125 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{};
137 }
138
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};
150 }
151
getInputBoundsInDisplaySpace(const LayerSnapshot & snapshot,const FloatRect & insetBounds,const ui::Transform & screenToDisplay)152 Rect getInputBoundsInDisplaySpace(const LayerSnapshot& snapshot, const FloatRect& insetBounds,
153 const ui::Transform& screenToDisplay) {
154 // 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.
157
158 // 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.
165
166 // Crop the input bounds to ensure it is within the parent's bounds.
167 const FloatRect croppedInsetBoundsInLayer = snapshot.geomLayerBounds.intersect(insetBounds);
168
169 const ui::Transform layerToScreen = getInputTransform(snapshot);
170 const ui::Transform layerToDisplay = screenToDisplay * layerToScreen;
171
172 return Rect{layerToDisplay.transform(croppedInsetBoundsInLayer)};
173 }
174
fillInputFrameInfo(gui::WindowInfo & info,const ui::Transform & screenToDisplay,const LayerSnapshot & snapshot)175 void 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
182 info.frame = getInputBoundsInDisplaySpace(snapshot, inputBounds, screenToDisplay);
183
184 ui::Transform inputToLayer;
185 inputToLayer.set(inputBounds.left, inputBounds.top);
186 const ui::Transform layerToScreen = getInputTransform(snapshot);
187 const ui::Transform inputToDisplay = screenToDisplay * layerToScreen * inputToLayer;
188
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
handleDropInputMode(LayerSnapshot & snapshot,const LayerSnapshot & parentSnapshot)197 void 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 FloatRect 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
getBlendMode(const LayerSnapshot & snapshot,const RequestedLayerState & requested)249 auto 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
updateVisibility(LayerSnapshot & snapshot,bool visible)258 void updateVisibility(LayerSnapshot& snapshot, bool visible) {
259 if (snapshot.isVisible != visible) {
260 snapshot.changes |= RequestedLayerState::Changes::Visibility;
261 }
262 snapshot.isVisible = visible;
263
264 if (FlagManager::getInstance().skip_invisible_windows_in_input()) {
265 snapshot.inputInfo.setInputConfig(gui::WindowInfo::InputConfig::NOT_VISIBLE, !visible);
266 } else {
267 // TODO(b/238781169) we are ignoring this compat for now, since we will have
268 // to remove any optimization based on visibility.
269
270 // For compatibility reasons we let layers which can receive input
271 // receive input before they have actually submitted a buffer. Because
272 // of this we use canReceiveInput instead of isVisible to check the
273 // policy-visibility, ignoring the buffer state. However for layers with
274 // hasInputInfo()==false we can use the real visibility state.
275 // We are just using these layers for occlusion detection in
276 // InputDispatcher, and obviously if they aren't visible they can't occlude
277 // anything.
278 const bool visibleForInput =
279 snapshot.hasInputInfo() ? snapshot.canReceiveInput() : snapshot.isVisible;
280 snapshot.inputInfo.setInputConfig(gui::WindowInfo::InputConfig::NOT_VISIBLE,
281 !visibleForInput);
282 }
283 LLOGV(snapshot.sequence, "updating visibility %s %s", visible ? "true" : "false",
284 snapshot.getDebugString().c_str());
285 }
286
updateMetadata(LayerSnapshot & snapshot,const RequestedLayerState & requested,const LayerSnapshotBuilder::Args & args)287 void updateMetadata(LayerSnapshot& snapshot, const RequestedLayerState& requested,
288 const LayerSnapshotBuilder::Args& args) {
289 snapshot.metadata.clear();
290 for (const auto& [key, mandatory] : args.supportedLayerGenericMetadata) {
291 auto compatIter = args.genericLayerMetadataKeyMap.find(key);
292 if (compatIter == std::end(args.genericLayerMetadataKeyMap)) {
293 continue;
294 }
295 const uint32_t id = compatIter->second;
296 auto it = requested.metadata.mMap.find(id);
297 if (it == std::end(requested.metadata.mMap)) {
298 continue;
299 }
300
301 snapshot.metadata.emplace(key,
302 compositionengine::GenericLayerMetadataEntry{mandatory,
303 it->second});
304 }
305 }
306
updateMetadataAndGameMode(LayerSnapshot & snapshot,const RequestedLayerState & requested,const LayerSnapshotBuilder::Args & args,const LayerSnapshot & parentSnapshot)307 void updateMetadataAndGameMode(LayerSnapshot& snapshot, const RequestedLayerState& requested,
308 const LayerSnapshotBuilder::Args& args,
309 const LayerSnapshot& parentSnapshot) {
310 snapshot.gameMode = requested.metadata.has(gui::METADATA_GAME_MODE) ? requested.gameMode
311 : parentSnapshot.gameMode;
312 updateMetadata(snapshot, requested, args);
313 if (args.includeMetadata) {
314 snapshot.layerMetadata = parentSnapshot.layerMetadata;
315 snapshot.layerMetadata.merge(requested.metadata);
316 }
317 }
318
clearChanges(LayerSnapshot & snapshot)319 void clearChanges(LayerSnapshot& snapshot) {
320 snapshot.changes.clear();
321 snapshot.clientChanges = 0;
322 snapshot.contentDirty = snapshot.autoRefresh;
323 snapshot.hasReadyFrame = snapshot.autoRefresh;
324 snapshot.sidebandStreamHasFrame = false;
325 snapshot.surfaceDamage.clear();
326 }
327
328 // TODO (b/259407931): Remove.
getPrimaryDisplayRotationFlags(const ui::DisplayMap<ui::LayerStack,frontend::DisplayInfo> & displays)329 uint32_t getPrimaryDisplayRotationFlags(
330 const ui::DisplayMap<ui::LayerStack, frontend::DisplayInfo>& displays) {
331 for (auto& [_, display] : displays) {
332 if (display.isPrimary) {
333 return display.rotationFlags;
334 }
335 }
336 return 0;
337 }
338
339 } // namespace
340
getRootSnapshot()341 LayerSnapshot LayerSnapshotBuilder::getRootSnapshot() {
342 LayerSnapshot snapshot;
343 snapshot.path = LayerHierarchy::TraversalPath::ROOT;
344 snapshot.changes = ftl::Flags<RequestedLayerState::Changes>();
345 snapshot.clientChanges = 0;
346 snapshot.isHiddenByPolicyFromParent = false;
347 snapshot.isHiddenByPolicyFromRelativeParent = false;
348 snapshot.parentTransform.reset();
349 snapshot.geomLayerTransform.reset();
350 snapshot.geomInverseLayerTransform.reset();
351 snapshot.geomLayerBounds = getMaxDisplayBounds({});
352 snapshot.roundedCorner = RoundedCornerState();
353 snapshot.stretchEffect = {};
354 snapshot.edgeExtensionEffect = {};
355 snapshot.outputFilter.layerStack = ui::DEFAULT_LAYER_STACK;
356 snapshot.outputFilter.toInternalDisplay = false;
357 snapshot.isSecure = false;
358 snapshot.color.a = 1.0_hf;
359 snapshot.colorTransformIsIdentity = true;
360 snapshot.shadowSettings.length = 0.f;
361 snapshot.layerMetadata.mMap.clear();
362 snapshot.relativeLayerMetadata.mMap.clear();
363 snapshot.inputInfo.touchOcclusionMode = gui::TouchOcclusionMode::BLOCK_UNTRUSTED;
364 snapshot.dropInputMode = gui::DropInputMode::NONE;
365 snapshot.trustedOverlay = gui::TrustedOverlay::UNSET;
366 snapshot.gameMode = gui::GameMode::Unsupported;
367 snapshot.frameRate = {};
368 snapshot.fixedTransformHint = ui::Transform::ROT_INVALID;
369 snapshot.ignoreLocalTransform = false;
370 return snapshot;
371 }
372
LayerSnapshotBuilder()373 LayerSnapshotBuilder::LayerSnapshotBuilder() {}
374
LayerSnapshotBuilder(Args args)375 LayerSnapshotBuilder::LayerSnapshotBuilder(Args args) : LayerSnapshotBuilder() {
376 args.forceUpdate = ForceUpdateFlags::ALL;
377 updateSnapshots(args);
378 }
379
tryFastUpdate(const Args & args)380 bool LayerSnapshotBuilder::tryFastUpdate(const Args& args) {
381 const bool forceUpdate = args.forceUpdate != ForceUpdateFlags::NONE;
382
383 if (args.layerLifecycleManager.getGlobalChanges().get() == 0 && !forceUpdate &&
384 !args.displayChanges) {
385 return true;
386 }
387
388 // There are only content changes which do not require any child layer snapshots to be updated.
389 ALOGV("%s", __func__);
390 SFTRACE_NAME("FastPath");
391
392 uint32_t primaryDisplayRotationFlags = getPrimaryDisplayRotationFlags(args.displays);
393 if (forceUpdate || args.displayChanges) {
394 for (auto& snapshot : mSnapshots) {
395 const RequestedLayerState* requested =
396 args.layerLifecycleManager.getLayerFromId(snapshot->path.id);
397 if (!requested) continue;
398 snapshot->merge(*requested, forceUpdate, args.displayChanges, args.forceFullDamage,
399 primaryDisplayRotationFlags);
400 }
401 return false;
402 }
403
404 // Walk through all the updated requested layer states and update the corresponding snapshots.
405 for (const RequestedLayerState* requested : args.layerLifecycleManager.getChangedLayers()) {
406 auto range = mIdToSnapshots.equal_range(requested->id);
407 for (auto it = range.first; it != range.second; it++) {
408 it->second->merge(*requested, forceUpdate, args.displayChanges, args.forceFullDamage,
409 primaryDisplayRotationFlags);
410 }
411 }
412
413 if ((args.layerLifecycleManager.getGlobalChanges().get() &
414 ~(RequestedLayerState::Changes::Content | RequestedLayerState::Changes::Buffer).get()) !=
415 0) {
416 // We have changes that require us to walk the hierarchy and update child layers.
417 // No fast path for you.
418 return false;
419 }
420 return true;
421 }
422
updateSnapshots(const Args & args)423 void LayerSnapshotBuilder::updateSnapshots(const Args& args) {
424 SFTRACE_NAME("UpdateSnapshots");
425 LayerSnapshot rootSnapshot = args.rootSnapshot;
426 if (args.parentCrop) {
427 rootSnapshot.geomLayerBounds = *args.parentCrop;
428 } else if (args.forceUpdate == ForceUpdateFlags::ALL || args.displayChanges) {
429 rootSnapshot.geomLayerBounds = getMaxDisplayBounds(args.displays);
430 }
431 if (args.displayChanges) {
432 rootSnapshot.changes = RequestedLayerState::Changes::AffectsChildren |
433 RequestedLayerState::Changes::Geometry;
434 }
435 if (args.forceUpdate == ForceUpdateFlags::HIERARCHY) {
436 rootSnapshot.changes |=
437 RequestedLayerState::Changes::Hierarchy | RequestedLayerState::Changes::Visibility;
438 rootSnapshot.clientChanges |= layer_state_t::eReparent;
439 }
440
441 for (auto& snapshot : mSnapshots) {
442 if (snapshot->reachablilty == LayerSnapshot::Reachablilty::Reachable) {
443 snapshot->reachablilty = LayerSnapshot::Reachablilty::Unreachable;
444 }
445 }
446
447 LayerHierarchy::TraversalPath root = LayerHierarchy::TraversalPath::ROOT;
448 if (args.root.getLayer()) {
449 // The hierarchy can have a root layer when used for screenshots otherwise, it will have
450 // multiple children.
451 LayerHierarchy::ScopedAddToTraversalPath addChildToPath(root, args.root.getLayer()->id,
452 LayerHierarchy::Variant::Attached);
453 updateSnapshotsInHierarchy(args, args.root, root, rootSnapshot, /*depth=*/0);
454 } else {
455 for (auto& [childHierarchy, variant] : args.root.mChildren) {
456 LayerHierarchy::ScopedAddToTraversalPath addChildToPath(root,
457 childHierarchy->getLayer()->id,
458 variant);
459 updateSnapshotsInHierarchy(args, *childHierarchy, root, rootSnapshot, /*depth=*/0);
460 }
461 }
462
463 // Update touchable region crops outside the main update pass. This is because a layer could be
464 // cropped by any other layer and it requires both snapshots to be updated.
465 updateTouchableRegionCrop(args);
466
467 const bool hasUnreachableSnapshots = sortSnapshotsByZ(args);
468
469 // Destroy unreachable snapshots for clone layers. And destroy snapshots for non-clone
470 // layers if the layer have been destroyed.
471 // TODO(b/238781169) consider making clone layer ids stable as well
472 if (!hasUnreachableSnapshots && args.layerLifecycleManager.getDestroyedLayers().empty()) {
473 return;
474 }
475
476 std::unordered_set<uint32_t> destroyedLayerIds;
477 for (auto& destroyedLayer : args.layerLifecycleManager.getDestroyedLayers()) {
478 destroyedLayerIds.insert(destroyedLayer->id);
479 }
480
481 auto it = mSnapshots.begin();
482 while (it < mSnapshots.end()) {
483 auto& traversalPath = it->get()->path;
484 const bool unreachable =
485 it->get()->reachablilty == LayerSnapshot::Reachablilty::Unreachable;
486 const bool isClone = traversalPath.isClone();
487 const bool layerIsDestroyed =
488 destroyedLayerIds.find(traversalPath.id) != destroyedLayerIds.end();
489 const bool destroySnapshot = (unreachable && isClone) || layerIsDestroyed;
490
491 if (!destroySnapshot) {
492 it++;
493 continue;
494 }
495
496 mPathToSnapshot.erase(traversalPath);
497
498 auto range = mIdToSnapshots.equal_range(traversalPath.id);
499 auto matchingSnapshot =
500 std::find_if(range.first, range.second, [&traversalPath](auto& snapshotWithId) {
501 return snapshotWithId.second->path == traversalPath;
502 });
503 mIdToSnapshots.erase(matchingSnapshot);
504 mNeedsTouchableRegionCrop.erase(traversalPath);
505 mSnapshots.back()->globalZ = it->get()->globalZ;
506 std::iter_swap(it, mSnapshots.end() - 1);
507 mSnapshots.erase(mSnapshots.end() - 1);
508 }
509 }
510
update(const Args & args)511 void LayerSnapshotBuilder::update(const Args& args) {
512 for (auto& snapshot : mSnapshots) {
513 clearChanges(*snapshot);
514 }
515
516 if (tryFastUpdate(args)) {
517 return;
518 }
519 updateSnapshots(args);
520 }
521
updateSnapshotsInHierarchy(const Args & args,const LayerHierarchy & hierarchy,LayerHierarchy::TraversalPath & traversalPath,const LayerSnapshot & parentSnapshot,int depth)522 const LayerSnapshot& LayerSnapshotBuilder::updateSnapshotsInHierarchy(
523 const Args& args, const LayerHierarchy& hierarchy,
524 LayerHierarchy::TraversalPath& traversalPath, const LayerSnapshot& parentSnapshot,
525 int depth) {
526 LLOG_ALWAYS_FATAL_WITH_TRACE_IF(depth > 50,
527 "Cycle detected in LayerSnapshotBuilder. See "
528 "builder_stack_overflow_transactions.winscope");
529
530 const RequestedLayerState* layer = hierarchy.getLayer();
531 LayerSnapshot* snapshot = getSnapshot(traversalPath);
532 const bool newSnapshot = snapshot == nullptr;
533 uint32_t primaryDisplayRotationFlags = getPrimaryDisplayRotationFlags(args.displays);
534 if (newSnapshot) {
535 snapshot = createSnapshot(traversalPath, *layer, parentSnapshot);
536 snapshot->merge(*layer, /*forceUpdate=*/true, /*displayChanges=*/true, args.forceFullDamage,
537 primaryDisplayRotationFlags);
538 snapshot->changes |= RequestedLayerState::Changes::Created;
539 }
540
541 if (traversalPath.isRelative()) {
542 bool parentIsRelative = traversalPath.variant == LayerHierarchy::Variant::Relative;
543 updateRelativeState(*snapshot, parentSnapshot, parentIsRelative, args);
544 } else {
545 if (traversalPath.isAttached()) {
546 resetRelativeState(*snapshot);
547 }
548 updateSnapshot(*snapshot, args, *layer, parentSnapshot, traversalPath);
549 }
550
551 bool childHasValidFrameRate = false;
552 for (auto& [childHierarchy, variant] : hierarchy.mChildren) {
553 LayerHierarchy::ScopedAddToTraversalPath addChildToPath(traversalPath,
554 childHierarchy->getLayer()->id,
555 variant);
556 const LayerSnapshot& childSnapshot =
557 updateSnapshotsInHierarchy(args, *childHierarchy, traversalPath, *snapshot,
558 depth + 1);
559 updateFrameRateFromChildSnapshot(*snapshot, childSnapshot, *childHierarchy->getLayer(),
560 args, &childHasValidFrameRate);
561 }
562
563 return *snapshot;
564 }
565
getSnapshot(uint32_t layerId) const566 LayerSnapshot* LayerSnapshotBuilder::getSnapshot(uint32_t layerId) const {
567 if (layerId == UNASSIGNED_LAYER_ID) {
568 return nullptr;
569 }
570 LayerHierarchy::TraversalPath path{.id = layerId};
571 return getSnapshot(path);
572 }
573
getSnapshot(const LayerHierarchy::TraversalPath & id) const574 LayerSnapshot* LayerSnapshotBuilder::getSnapshot(const LayerHierarchy::TraversalPath& id) const {
575 auto it = mPathToSnapshot.find(id);
576 return it == mPathToSnapshot.end() ? nullptr : it->second;
577 }
578
createSnapshot(const LayerHierarchy::TraversalPath & path,const RequestedLayerState & layer,const LayerSnapshot & parentSnapshot)579 LayerSnapshot* LayerSnapshotBuilder::createSnapshot(const LayerHierarchy::TraversalPath& path,
580 const RequestedLayerState& layer,
581 const LayerSnapshot& parentSnapshot) {
582 mSnapshots.emplace_back(std::make_unique<LayerSnapshot>(layer, path));
583 LayerSnapshot* snapshot = mSnapshots.back().get();
584 snapshot->globalZ = static_cast<size_t>(mSnapshots.size()) - 1;
585 if (path.isClone() && !LayerHierarchy::isMirror(path.variant)) {
586 snapshot->mirrorRootPath = parentSnapshot.mirrorRootPath;
587 }
588 snapshot->ignoreLocalTransform =
589 path.isClone() && path.variant == LayerHierarchy::Variant::Detached_Mirror;
590 mPathToSnapshot[path] = snapshot;
591
592 mIdToSnapshots.emplace(path.id, snapshot);
593 return snapshot;
594 }
595
sortSnapshotsByZ(const Args & args)596 bool LayerSnapshotBuilder::sortSnapshotsByZ(const Args& args) {
597 if (!mResortSnapshots && args.forceUpdate == ForceUpdateFlags::NONE &&
598 !args.layerLifecycleManager.getGlobalChanges().any(
599 RequestedLayerState::Changes::Hierarchy | RequestedLayerState::Changes::Visibility |
600 RequestedLayerState::Changes::Input)) {
601 // We are not force updating and there are no hierarchy or visibility changes. Avoid sorting
602 // the snapshots.
603 return false;
604 }
605 mResortSnapshots = false;
606
607 size_t globalZ = 0;
608 args.root.traverseInZOrder(
609 [this, &globalZ](const LayerHierarchy&,
610 const LayerHierarchy::TraversalPath& traversalPath) -> bool {
611 LayerSnapshot* snapshot = getSnapshot(traversalPath);
612 if (!snapshot) {
613 return true;
614 }
615
616 if (snapshot->getIsVisible() || snapshot->hasInputInfo()) {
617 updateVisibility(*snapshot, snapshot->getIsVisible());
618 size_t oldZ = snapshot->globalZ;
619 size_t newZ = globalZ++;
620 snapshot->globalZ = newZ;
621 if (oldZ == newZ) {
622 return true;
623 }
624 mSnapshots[newZ]->globalZ = oldZ;
625 LLOGV(snapshot->sequence, "Made visible z=%zu -> %zu %s", oldZ, newZ,
626 snapshot->getDebugString().c_str());
627 std::iter_swap(mSnapshots.begin() + static_cast<ssize_t>(oldZ),
628 mSnapshots.begin() + static_cast<ssize_t>(newZ));
629 }
630 return true;
631 });
632 mNumInterestingSnapshots = (int)globalZ;
633 bool hasUnreachableSnapshots = false;
634 while (globalZ < mSnapshots.size()) {
635 mSnapshots[globalZ]->globalZ = globalZ;
636 /* mark unreachable snapshots as explicitly invisible */
637 updateVisibility(*mSnapshots[globalZ], false);
638 if (mSnapshots[globalZ]->reachablilty == LayerSnapshot::Reachablilty::Unreachable) {
639 hasUnreachableSnapshots = true;
640 }
641 globalZ++;
642 }
643 return hasUnreachableSnapshots;
644 }
645
updateRelativeState(LayerSnapshot & snapshot,const LayerSnapshot & parentSnapshot,bool parentIsRelative,const Args & args)646 void LayerSnapshotBuilder::updateRelativeState(LayerSnapshot& snapshot,
647 const LayerSnapshot& parentSnapshot,
648 bool parentIsRelative, const Args& args) {
649 if (parentIsRelative) {
650 snapshot.isHiddenByPolicyFromRelativeParent =
651 parentSnapshot.isHiddenByPolicyFromParent || parentSnapshot.invalidTransform;
652 if (args.includeMetadata) {
653 snapshot.relativeLayerMetadata = parentSnapshot.layerMetadata;
654 }
655 } else {
656 snapshot.isHiddenByPolicyFromRelativeParent =
657 parentSnapshot.isHiddenByPolicyFromRelativeParent;
658 if (args.includeMetadata) {
659 snapshot.relativeLayerMetadata = parentSnapshot.relativeLayerMetadata;
660 }
661 }
662 if (snapshot.reachablilty == LayerSnapshot::Reachablilty::Unreachable) {
663 snapshot.reachablilty = LayerSnapshot::Reachablilty::ReachableByRelativeParent;
664 }
665 }
666
updateFrameRateFromChildSnapshot(LayerSnapshot & snapshot,const LayerSnapshot & childSnapshot,const RequestedLayerState &,const Args & args,bool * outChildHasValidFrameRate)667 void LayerSnapshotBuilder::updateFrameRateFromChildSnapshot(
668 LayerSnapshot& snapshot, const LayerSnapshot& childSnapshot,
669 const RequestedLayerState& /* requestedChildState */, const Args& args,
670 bool* outChildHasValidFrameRate) {
671 if (args.forceUpdate == ForceUpdateFlags::NONE &&
672 !args.layerLifecycleManager.getGlobalChanges().any(
673 RequestedLayerState::Changes::Hierarchy) &&
674 !childSnapshot.changes.any(RequestedLayerState::Changes::FrameRate) &&
675 !snapshot.changes.any(RequestedLayerState::Changes::FrameRate)) {
676 return;
677 }
678
679 using FrameRateCompatibility = scheduler::FrameRateCompatibility;
680 if (snapshot.inheritedFrameRate.isValid() || *outChildHasValidFrameRate) {
681 // we already have a valid framerate.
682 return;
683 }
684
685 // We return whether this layer or its children has a vote. We ignore ExactOrMultiple votes
686 // for the same reason we are allowing touch boost for those layers. See
687 // RefreshRateSelector::rankFrameRates for details.
688 const auto layerVotedWithDefaultCompatibility = childSnapshot.frameRate.vote.rate.isValid() &&
689 childSnapshot.frameRate.vote.type == FrameRateCompatibility::Default;
690 const auto layerVotedWithNoVote =
691 childSnapshot.frameRate.vote.type == FrameRateCompatibility::NoVote;
692 const auto layerVotedWithCategory =
693 childSnapshot.frameRate.category != FrameRateCategory::Default;
694 const auto layerVotedWithExactCompatibility = childSnapshot.frameRate.vote.rate.isValid() &&
695 childSnapshot.frameRate.vote.type == FrameRateCompatibility::Exact;
696
697 *outChildHasValidFrameRate |= layerVotedWithDefaultCompatibility || layerVotedWithNoVote ||
698 layerVotedWithCategory || layerVotedWithExactCompatibility;
699
700 // If we don't have a valid frame rate, but the children do, we set this
701 // layer as NoVote to allow the children to control the refresh rate
702 static const auto noVote =
703 scheduler::LayerInfo::FrameRate(Fps(), FrameRateCompatibility::NoVote);
704 if (*outChildHasValidFrameRate) {
705 snapshot.frameRate = noVote;
706 snapshot.changes |= RequestedLayerState::Changes::FrameRate;
707 } else if (snapshot.frameRate != snapshot.inheritedFrameRate) {
708 snapshot.frameRate = snapshot.inheritedFrameRate;
709 snapshot.changes |= RequestedLayerState::Changes::FrameRate;
710 }
711 }
712
resetRelativeState(LayerSnapshot & snapshot)713 void LayerSnapshotBuilder::resetRelativeState(LayerSnapshot& snapshot) {
714 snapshot.isHiddenByPolicyFromRelativeParent = false;
715 snapshot.relativeLayerMetadata.mMap.clear();
716 }
717
updateSnapshot(LayerSnapshot & snapshot,const Args & args,const RequestedLayerState & requested,const LayerSnapshot & parentSnapshot,const LayerHierarchy::TraversalPath & path)718 void LayerSnapshotBuilder::updateSnapshot(LayerSnapshot& snapshot, const Args& args,
719 const RequestedLayerState& requested,
720 const LayerSnapshot& parentSnapshot,
721 const LayerHierarchy::TraversalPath& path) {
722 // Always update flags and visibility
723 ftl::Flags<RequestedLayerState::Changes> parentChanges = parentSnapshot.changes &
724 (RequestedLayerState::Changes::Hierarchy | RequestedLayerState::Changes::Geometry |
725 RequestedLayerState::Changes::Visibility | RequestedLayerState::Changes::Metadata |
726 RequestedLayerState::Changes::AffectsChildren | RequestedLayerState::Changes::Input |
727 RequestedLayerState::Changes::FrameRate | RequestedLayerState::Changes::GameMode);
728 snapshot.changes |= parentChanges;
729 if (args.displayChanges) snapshot.changes |= RequestedLayerState::Changes::Geometry;
730 snapshot.reachablilty = LayerSnapshot::Reachablilty::Reachable;
731 snapshot.clientChanges |= (parentSnapshot.clientChanges & layer_state_t::AFFECTS_CHILDREN);
732 // mark the content as dirty if the parent state changes can dirty the child's content (for
733 // example alpha)
734 snapshot.contentDirty |= (snapshot.clientChanges & layer_state_t::CONTENT_DIRTY) != 0;
735 snapshot.isHiddenByPolicyFromParent = parentSnapshot.isHiddenByPolicyFromParent ||
736 parentSnapshot.invalidTransform || requested.isHiddenByPolicy() ||
737 (args.excludeLayerIds.find(path.id) != args.excludeLayerIds.end());
738 const bool forceUpdate = args.forceUpdate == ForceUpdateFlags::ALL ||
739 snapshot.clientChanges & layer_state_t::eReparent ||
740 snapshot.changes.any(RequestedLayerState::Changes::Visibility |
741 RequestedLayerState::Changes::Created);
742
743 if (forceUpdate || snapshot.clientChanges & layer_state_t::eLayerStackChanged) {
744 // If root layer, use the layer stack otherwise get the parent's layer stack.
745 snapshot.outputFilter.layerStack =
746 parentSnapshot.path == LayerHierarchy::TraversalPath::ROOT
747 ? requested.layerStack
748 : parentSnapshot.outputFilter.layerStack;
749 }
750
751 if (forceUpdate || snapshot.clientChanges & layer_state_t::eTrustedOverlayChanged) {
752 switch (requested.trustedOverlay) {
753 case gui::TrustedOverlay::UNSET:
754 snapshot.trustedOverlay = parentSnapshot.trustedOverlay;
755 break;
756 case gui::TrustedOverlay::DISABLED:
757 snapshot.trustedOverlay = FlagManager::getInstance().override_trusted_overlay()
758 ? requested.trustedOverlay
759 : parentSnapshot.trustedOverlay;
760 break;
761 case gui::TrustedOverlay::ENABLED:
762 snapshot.trustedOverlay = requested.trustedOverlay;
763 break;
764 }
765 }
766
767 if (snapshot.isHiddenByPolicyFromParent &&
768 !snapshot.changes.test(RequestedLayerState::Changes::Created)) {
769 if (forceUpdate ||
770 snapshot.changes.any(RequestedLayerState::Changes::Geometry |
771 RequestedLayerState::Changes::BufferSize |
772 RequestedLayerState::Changes::Input)) {
773 updateInput(snapshot, requested, parentSnapshot, path, args);
774 }
775 if (forceUpdate ||
776 (args.includeMetadata &&
777 snapshot.changes.any(RequestedLayerState::Changes::Metadata |
778 RequestedLayerState::Changes::Geometry))) {
779 updateMetadataAndGameMode(snapshot, requested, args, parentSnapshot);
780 }
781 return;
782 }
783
784 if (forceUpdate || snapshot.changes.any(RequestedLayerState::Changes::Mirror)) {
785 // Display mirrors are always placed in a VirtualDisplay so we never want to capture layers
786 // marked as skip capture
787 snapshot.handleSkipScreenshotFlag = parentSnapshot.handleSkipScreenshotFlag ||
788 (requested.layerStackToMirror != ui::INVALID_LAYER_STACK);
789 }
790
791 if (forceUpdate || snapshot.clientChanges & layer_state_t::eAlphaChanged) {
792 snapshot.color.a = parentSnapshot.color.a * requested.color.a;
793 snapshot.alpha = snapshot.color.a;
794 snapshot.inputInfo.alpha = snapshot.color.a;
795 }
796
797 if (forceUpdate || snapshot.clientChanges & layer_state_t::eFlagsChanged) {
798 snapshot.isSecure =
799 parentSnapshot.isSecure || (requested.flags & layer_state_t::eLayerSecure);
800 snapshot.outputFilter.toInternalDisplay = parentSnapshot.outputFilter.toInternalDisplay ||
801 (requested.flags & layer_state_t::eLayerSkipScreenshot);
802 }
803
804 if (forceUpdate || snapshot.clientChanges & layer_state_t::eStretchChanged) {
805 snapshot.stretchEffect = (requested.stretchEffect.hasEffect())
806 ? requested.stretchEffect
807 : parentSnapshot.stretchEffect;
808 }
809
810 if (forceUpdate ||
811 (snapshot.clientChanges | parentSnapshot.clientChanges) &
812 layer_state_t::eEdgeExtensionChanged) {
813 if (requested.edgeExtensionParameters.extendLeft ||
814 requested.edgeExtensionParameters.extendRight ||
815 requested.edgeExtensionParameters.extendTop ||
816 requested.edgeExtensionParameters.extendBottom) {
817 // This is the root layer to which the extension is applied
818 snapshot.edgeExtensionEffect =
819 EdgeExtensionEffect(requested.edgeExtensionParameters.extendLeft,
820 requested.edgeExtensionParameters.extendRight,
821 requested.edgeExtensionParameters.extendTop,
822 requested.edgeExtensionParameters.extendBottom);
823 } else if (parentSnapshot.clientChanges & layer_state_t::eEdgeExtensionChanged) {
824 // Extension is inherited
825 snapshot.edgeExtensionEffect = parentSnapshot.edgeExtensionEffect;
826 } else {
827 // There is no edge extension
828 snapshot.edgeExtensionEffect.reset();
829 }
830 if (snapshot.edgeExtensionEffect.hasEffect()) {
831 snapshot.clientChanges |= layer_state_t::eEdgeExtensionChanged;
832 snapshot.changes |= RequestedLayerState::Changes::Geometry;
833 }
834 }
835
836 if (forceUpdate || snapshot.clientChanges & layer_state_t::eColorTransformChanged) {
837 if (!parentSnapshot.colorTransformIsIdentity) {
838 snapshot.colorTransform = parentSnapshot.colorTransform * requested.colorTransform;
839 snapshot.colorTransformIsIdentity = false;
840 } else {
841 snapshot.colorTransform = requested.colorTransform;
842 snapshot.colorTransformIsIdentity = !requested.hasColorTransform;
843 }
844 }
845
846 if (forceUpdate ||
847 snapshot.changes.any(RequestedLayerState::Changes::Metadata |
848 RequestedLayerState::Changes::Hierarchy)) {
849 updateMetadataAndGameMode(snapshot, requested, args, parentSnapshot);
850 }
851
852 if (forceUpdate || snapshot.clientChanges & layer_state_t::eFixedTransformHintChanged ||
853 args.displayChanges) {
854 snapshot.fixedTransformHint = requested.fixedTransformHint != ui::Transform::ROT_INVALID
855 ? requested.fixedTransformHint
856 : parentSnapshot.fixedTransformHint;
857
858 if (snapshot.fixedTransformHint != ui::Transform::ROT_INVALID) {
859 snapshot.transformHint = snapshot.fixedTransformHint;
860 } else {
861 const auto display = args.displays.get(snapshot.outputFilter.layerStack);
862 snapshot.transformHint = display.has_value()
863 ? std::make_optional<>(display->get().transformHint)
864 : std::nullopt;
865 }
866 }
867
868 if (forceUpdate ||
869 args.layerLifecycleManager.getGlobalChanges().any(
870 RequestedLayerState::Changes::Hierarchy) ||
871 snapshot.changes.any(RequestedLayerState::Changes::FrameRate |
872 RequestedLayerState::Changes::Hierarchy)) {
873 const bool shouldOverrideChildren = parentSnapshot.frameRateSelectionStrategy ==
874 scheduler::LayerInfo::FrameRateSelectionStrategy::OverrideChildren;
875 const bool propagationAllowed = parentSnapshot.frameRateSelectionStrategy !=
876 scheduler::LayerInfo::FrameRateSelectionStrategy::Self;
877 if ((!requested.requestedFrameRate.isValid() && propagationAllowed) ||
878 shouldOverrideChildren) {
879 snapshot.inheritedFrameRate = parentSnapshot.inheritedFrameRate;
880 } else {
881 snapshot.inheritedFrameRate = requested.requestedFrameRate;
882 }
883 // Set the framerate as the inherited frame rate and allow children to override it if
884 // needed.
885 snapshot.frameRate = snapshot.inheritedFrameRate;
886 snapshot.changes |= RequestedLayerState::Changes::FrameRate;
887 }
888
889 if (forceUpdate || snapshot.clientChanges & layer_state_t::eFrameRateSelectionStrategyChanged) {
890 if (parentSnapshot.frameRateSelectionStrategy ==
891 scheduler::LayerInfo::FrameRateSelectionStrategy::OverrideChildren) {
892 snapshot.frameRateSelectionStrategy =
893 scheduler::LayerInfo::FrameRateSelectionStrategy::OverrideChildren;
894 } else {
895 const auto strategy = scheduler::LayerInfo::convertFrameRateSelectionStrategy(
896 requested.frameRateSelectionStrategy);
897 snapshot.frameRateSelectionStrategy = strategy;
898 }
899 }
900
901 if (forceUpdate || snapshot.clientChanges & layer_state_t::eFrameRateSelectionPriority) {
902 snapshot.frameRateSelectionPriority =
903 (requested.frameRateSelectionPriority == Layer::PRIORITY_UNSET)
904 ? parentSnapshot.frameRateSelectionPriority
905 : requested.frameRateSelectionPriority;
906 }
907
908 if (forceUpdate ||
909 snapshot.clientChanges &
910 (layer_state_t::eBackgroundBlurRadiusChanged | layer_state_t::eBlurRegionsChanged |
911 layer_state_t::eAlphaChanged)) {
912 snapshot.backgroundBlurRadius = args.supportsBlur
913 ? static_cast<int>(parentSnapshot.color.a * (float)requested.backgroundBlurRadius)
914 : 0;
915 snapshot.blurRegions = requested.blurRegions;
916 for (auto& region : snapshot.blurRegions) {
917 region.alpha = region.alpha * snapshot.color.a;
918 }
919 }
920
921 if (forceUpdate || snapshot.changes.any(RequestedLayerState::Changes::Geometry)) {
922 uint32_t primaryDisplayRotationFlags = getPrimaryDisplayRotationFlags(args.displays);
923 updateLayerBounds(snapshot, requested, parentSnapshot, primaryDisplayRotationFlags);
924 }
925
926 if (snapshot.edgeExtensionEffect.hasEffect()) {
927 updateBoundsForEdgeExtension(snapshot);
928 }
929
930 if (forceUpdate || snapshot.clientChanges & layer_state_t::eCornerRadiusChanged ||
931 snapshot.changes.any(RequestedLayerState::Changes::Geometry |
932 RequestedLayerState::Changes::BufferUsageFlags)) {
933 updateRoundedCorner(snapshot, requested, parentSnapshot, args);
934 }
935
936 if (forceUpdate || snapshot.clientChanges & layer_state_t::eShadowRadiusChanged ||
937 snapshot.changes.any(RequestedLayerState::Changes::Geometry)) {
938 updateShadows(snapshot, requested, args.globalShadowSettings);
939 }
940
941 if (forceUpdate ||
942 snapshot.changes.any(RequestedLayerState::Changes::Geometry |
943 RequestedLayerState::Changes::Input)) {
944 updateInput(snapshot, requested, parentSnapshot, path, args);
945 }
946
947 // computed snapshot properties
948 snapshot.forceClientComposition = snapshot.shadowSettings.length > 0 ||
949 snapshot.stretchEffect.hasEffect() || snapshot.edgeExtensionEffect.hasEffect();
950 snapshot.contentOpaque = snapshot.isContentOpaque();
951 snapshot.isOpaque = snapshot.contentOpaque && !snapshot.roundedCorner.hasRoundedCorners() &&
952 snapshot.color.a == 1.f;
953 snapshot.blendMode = getBlendMode(snapshot, requested);
954 LLOGV(snapshot.sequence,
955 "%supdated %s changes:%s parent:%s requested:%s requested:%s from parent %s",
956 args.forceUpdate == ForceUpdateFlags::ALL ? "Force " : "",
957 snapshot.getDebugString().c_str(), snapshot.changes.string().c_str(),
958 parentSnapshot.changes.string().c_str(), requested.changes.string().c_str(),
959 std::to_string(requested.what).c_str(), parentSnapshot.getDebugString().c_str());
960 }
961
updateRoundedCorner(LayerSnapshot & snapshot,const RequestedLayerState & requested,const LayerSnapshot & parentSnapshot,const Args & args)962 void LayerSnapshotBuilder::updateRoundedCorner(LayerSnapshot& snapshot,
963 const RequestedLayerState& requested,
964 const LayerSnapshot& parentSnapshot,
965 const Args& args) {
966 if (args.skipRoundCornersWhenProtected && requested.isProtected()) {
967 snapshot.roundedCorner = RoundedCornerState();
968 return;
969 }
970 snapshot.roundedCorner = RoundedCornerState();
971 RoundedCornerState parentRoundedCorner;
972 if (parentSnapshot.roundedCorner.hasRoundedCorners()) {
973 parentRoundedCorner = parentSnapshot.roundedCorner;
974 ui::Transform t = snapshot.localTransform.inverse();
975 parentRoundedCorner.cropRect = t.transform(parentRoundedCorner.cropRect);
976 parentRoundedCorner.radius.x *= t.getScaleX();
977 parentRoundedCorner.radius.y *= t.getScaleY();
978 }
979
980 FloatRect layerCropRect = snapshot.croppedBufferSize;
981 const vec2 radius(requested.cornerRadius, requested.cornerRadius);
982 RoundedCornerState layerSettings(layerCropRect, radius);
983 const bool layerSettingsValid = layerSettings.hasRoundedCorners() && !layerCropRect.isEmpty();
984 const bool parentRoundedCornerValid = parentRoundedCorner.hasRoundedCorners();
985 if (layerSettingsValid && parentRoundedCornerValid) {
986 // If the parent and the layer have rounded corner settings, use the parent settings if
987 // the parent crop is entirely inside the layer crop. This has limitations and cause
988 // rendering artifacts. See b/200300845 for correct fix.
989 if (parentRoundedCorner.cropRect.left > layerCropRect.left &&
990 parentRoundedCorner.cropRect.top > layerCropRect.top &&
991 parentRoundedCorner.cropRect.right < layerCropRect.right &&
992 parentRoundedCorner.cropRect.bottom < layerCropRect.bottom) {
993 snapshot.roundedCorner = parentRoundedCorner;
994 } else {
995 snapshot.roundedCorner = layerSettings;
996 }
997 } else if (layerSettingsValid) {
998 snapshot.roundedCorner = layerSettings;
999 } else if (parentRoundedCornerValid) {
1000 snapshot.roundedCorner = parentRoundedCorner;
1001 }
1002 }
1003
1004 /**
1005 * According to the edges that we are requested to extend, we increase the bounds to the maximum
1006 * extension allowed by the crop (parent crop + requested crop). The animation that called
1007 * Transition#setEdgeExtensionEffect is in charge of setting the requested crop.
1008 * @param snapshot
1009 */
updateBoundsForEdgeExtension(LayerSnapshot & snapshot)1010 void LayerSnapshotBuilder::updateBoundsForEdgeExtension(LayerSnapshot& snapshot) {
1011 EdgeExtensionEffect& effect = snapshot.edgeExtensionEffect;
1012
1013 if (effect.extendsEdge(LEFT)) {
1014 snapshot.geomLayerBounds.left = snapshot.geomLayerCrop.left;
1015 }
1016 if (effect.extendsEdge(RIGHT)) {
1017 snapshot.geomLayerBounds.right = snapshot.geomLayerCrop.right;
1018 }
1019 if (effect.extendsEdge(TOP)) {
1020 snapshot.geomLayerBounds.top = snapshot.geomLayerCrop.top;
1021 }
1022 if (effect.extendsEdge(BOTTOM)) {
1023 snapshot.geomLayerBounds.bottom = snapshot.geomLayerCrop.bottom;
1024 }
1025
1026 snapshot.transformedBounds = snapshot.geomLayerTransform.transform(snapshot.geomLayerBounds);
1027 }
1028
updateLayerBounds(LayerSnapshot & snapshot,const RequestedLayerState & requested,const LayerSnapshot & parentSnapshot,uint32_t primaryDisplayRotationFlags)1029 void LayerSnapshotBuilder::updateLayerBounds(LayerSnapshot& snapshot,
1030 const RequestedLayerState& requested,
1031 const LayerSnapshot& parentSnapshot,
1032 uint32_t primaryDisplayRotationFlags) {
1033 snapshot.geomLayerTransform = parentSnapshot.geomLayerTransform * snapshot.localTransform;
1034 const bool transformWasInvalid = snapshot.invalidTransform;
1035 snapshot.invalidTransform = !LayerSnapshot::isTransformValid(snapshot.geomLayerTransform);
1036 if (snapshot.invalidTransform) {
1037 auto& t = snapshot.geomLayerTransform;
1038 auto& requestedT = requested.requestedTransform;
1039 std::string transformDebug =
1040 base::StringPrintf(" transform={%f,%f,%f,%f} requestedTransform={%f,%f,%f,%f}",
1041 t.dsdx(), t.dsdy(), t.dtdx(), t.dtdy(), requestedT.dsdx(),
1042 requestedT.dsdy(), requestedT.dtdx(), requestedT.dtdy());
1043 std::string bufferDebug;
1044 if (requested.externalTexture) {
1045 auto unRotBuffer = requested.getUnrotatedBufferSize(primaryDisplayRotationFlags);
1046 auto& destFrame = requested.destinationFrame;
1047 bufferDebug = base::StringPrintf(" buffer={%d,%d} displayRot=%d"
1048 " destFrame={%d,%d,%d,%d} unRotBuffer={%d,%d}",
1049 requested.externalTexture->getWidth(),
1050 requested.externalTexture->getHeight(),
1051 primaryDisplayRotationFlags, destFrame.left,
1052 destFrame.top, destFrame.right, destFrame.bottom,
1053 unRotBuffer.getHeight(), unRotBuffer.getWidth());
1054 }
1055 ALOGW("Resetting transform for %s because it is invalid.%s%s",
1056 snapshot.getDebugString().c_str(), transformDebug.c_str(), bufferDebug.c_str());
1057 snapshot.geomLayerTransform.reset();
1058 }
1059 if (transformWasInvalid != snapshot.invalidTransform) {
1060 // If transform is invalid, the layer will be hidden.
1061 mResortSnapshots = true;
1062 }
1063 snapshot.geomInverseLayerTransform = snapshot.geomLayerTransform.inverse();
1064
1065 FloatRect parentBounds = parentSnapshot.geomLayerBounds;
1066 parentBounds = snapshot.localTransform.inverse().transform(parentBounds);
1067 snapshot.geomLayerBounds =
1068 requested.externalTexture ? snapshot.bufferSize.toFloatRect() : parentBounds;
1069 snapshot.geomLayerCrop = parentBounds;
1070 if (!requested.crop.isEmpty()) {
1071 snapshot.geomLayerCrop = snapshot.geomLayerCrop.intersect(requested.crop);
1072 }
1073 snapshot.geomLayerBounds = snapshot.geomLayerBounds.intersect(snapshot.geomLayerCrop);
1074 snapshot.transformedBounds = snapshot.geomLayerTransform.transform(snapshot.geomLayerBounds);
1075 const Rect geomLayerBoundsWithoutTransparentRegion =
1076 RequestedLayerState::reduce(Rect(snapshot.geomLayerBounds),
1077 requested.transparentRegion);
1078 snapshot.transformedBoundsWithoutTransparentRegion =
1079 snapshot.geomLayerTransform.transform(geomLayerBoundsWithoutTransparentRegion);
1080 snapshot.parentTransform = parentSnapshot.geomLayerTransform;
1081
1082 if (requested.potentialCursor) {
1083 // Subtract the transparent region and snap to the bounds
1084 const Rect bounds = RequestedLayerState::reduce(Rect(snapshot.croppedBufferSize),
1085 requested.transparentRegion);
1086 snapshot.cursorFrame = snapshot.geomLayerTransform.transform(bounds);
1087 }
1088 }
1089
updateShadows(LayerSnapshot & snapshot,const RequestedLayerState &,const ShadowSettings & globalShadowSettings)1090 void LayerSnapshotBuilder::updateShadows(LayerSnapshot& snapshot, const RequestedLayerState&,
1091 const ShadowSettings& globalShadowSettings) {
1092 if (snapshot.shadowSettings.length > 0.f) {
1093 snapshot.shadowSettings.ambientColor = globalShadowSettings.ambientColor;
1094 snapshot.shadowSettings.spotColor = globalShadowSettings.spotColor;
1095 snapshot.shadowSettings.lightPos = globalShadowSettings.lightPos;
1096 snapshot.shadowSettings.lightRadius = globalShadowSettings.lightRadius;
1097
1098 // Note: this preserves existing behavior of shadowing the entire layer and not cropping
1099 // it if transparent regions are present. This may not be necessary since shadows are
1100 // typically cast by layers without transparent regions.
1101 snapshot.shadowSettings.boundaries = snapshot.geomLayerBounds;
1102
1103 // If the casting layer is translucent, we need to fill in the shadow underneath the
1104 // layer. Otherwise the generated shadow will only be shown around the casting layer.
1105 snapshot.shadowSettings.casterIsTranslucent =
1106 !snapshot.isContentOpaque() || (snapshot.alpha < 1.0f);
1107 snapshot.shadowSettings.ambientColor *= snapshot.alpha;
1108 snapshot.shadowSettings.spotColor *= snapshot.alpha;
1109 }
1110 }
1111
updateInput(LayerSnapshot & snapshot,const RequestedLayerState & requested,const LayerSnapshot & parentSnapshot,const LayerHierarchy::TraversalPath & path,const Args & args)1112 void LayerSnapshotBuilder::updateInput(LayerSnapshot& snapshot,
1113 const RequestedLayerState& requested,
1114 const LayerSnapshot& parentSnapshot,
1115 const LayerHierarchy::TraversalPath& path,
1116 const Args& args) {
1117 using InputConfig = gui::WindowInfo::InputConfig;
1118
1119 if (requested.windowInfoHandle) {
1120 snapshot.inputInfo = *requested.windowInfoHandle->getInfo();
1121 } else {
1122 snapshot.inputInfo = {};
1123 // b/271132344 revisit this and see if we can always use the layers uid/pid
1124 snapshot.inputInfo.name = requested.name;
1125 snapshot.inputInfo.ownerUid = gui::Uid{requested.ownerUid};
1126 snapshot.inputInfo.ownerPid = gui::Pid{requested.ownerPid};
1127 }
1128 snapshot.touchCropId = requested.touchCropId;
1129
1130 snapshot.inputInfo.id = static_cast<int32_t>(snapshot.uniqueSequence);
1131 snapshot.inputInfo.displayId =
1132 ui::LogicalDisplayId{static_cast<int32_t>(snapshot.outputFilter.layerStack.id)};
1133 snapshot.inputInfo.touchOcclusionMode = requested.hasInputInfo()
1134 ? requested.windowInfoHandle->getInfo()->touchOcclusionMode
1135 : parentSnapshot.inputInfo.touchOcclusionMode;
1136 snapshot.inputInfo.canOccludePresentation = parentSnapshot.inputInfo.canOccludePresentation ||
1137 (requested.flags & layer_state_t::eCanOccludePresentation);
1138 if (requested.dropInputMode == gui::DropInputMode::ALL ||
1139 parentSnapshot.dropInputMode == gui::DropInputMode::ALL) {
1140 snapshot.dropInputMode = gui::DropInputMode::ALL;
1141 } else if (requested.dropInputMode == gui::DropInputMode::OBSCURED ||
1142 parentSnapshot.dropInputMode == gui::DropInputMode::OBSCURED) {
1143 snapshot.dropInputMode = gui::DropInputMode::OBSCURED;
1144 } else {
1145 snapshot.dropInputMode = gui::DropInputMode::NONE;
1146 }
1147
1148 if (snapshot.isSecure ||
1149 parentSnapshot.inputInfo.inputConfig.test(InputConfig::SENSITIVE_FOR_PRIVACY)) {
1150 snapshot.inputInfo.inputConfig |= InputConfig::SENSITIVE_FOR_PRIVACY;
1151 }
1152
1153 updateVisibility(snapshot, snapshot.isVisible);
1154 if (!requested.needsInputInfo()) {
1155 return;
1156 }
1157
1158 static frontend::DisplayInfo sDefaultInfo = {.isSecure = false};
1159 const std::optional<frontend::DisplayInfo> displayInfoOpt =
1160 args.displays.get(snapshot.outputFilter.layerStack);
1161 bool noValidDisplay = !displayInfoOpt.has_value();
1162 auto displayInfo = displayInfoOpt.value_or(sDefaultInfo);
1163
1164 if (!requested.hasInputInfo()) {
1165 snapshot.inputInfo.inputConfig = InputConfig::NO_INPUT_CHANNEL;
1166 }
1167 fillInputFrameInfo(snapshot.inputInfo, displayInfo.transform, snapshot);
1168
1169 if (noValidDisplay) {
1170 // Do not let the window receive touches if it is not associated with a valid display
1171 // transform. We still allow the window to receive keys and prevent ANRs.
1172 snapshot.inputInfo.inputConfig |= InputConfig::NOT_TOUCHABLE;
1173 }
1174
1175 snapshot.inputInfo.alpha = snapshot.color.a;
1176
1177 handleDropInputMode(snapshot, parentSnapshot);
1178
1179 // If the window will be blacked out on a display because the display does not have the secure
1180 // flag and the layer has the secure flag set, then drop input.
1181 if (!displayInfo.isSecure && snapshot.isSecure) {
1182 snapshot.inputInfo.inputConfig |= InputConfig::DROP_INPUT;
1183 }
1184
1185 if (requested.touchCropId != UNASSIGNED_LAYER_ID || path.isClone()) {
1186 mNeedsTouchableRegionCrop.insert(path);
1187 }
1188 auto cropLayerSnapshot = getSnapshot(requested.touchCropId);
1189 if (!cropLayerSnapshot && snapshot.inputInfo.replaceTouchableRegionWithCrop) {
1190 FloatRect inputBounds = getInputBounds(snapshot, /*fillParentBounds=*/true).first;
1191 Rect inputBoundsInDisplaySpace =
1192 getInputBoundsInDisplaySpace(snapshot, inputBounds, displayInfo.transform);
1193 snapshot.inputInfo.touchableRegion = Region(inputBoundsInDisplaySpace);
1194 }
1195
1196 // Inherit the trusted state from the parent hierarchy, but don't clobber the trusted state
1197 // if it was set by WM for a known system overlay
1198 if (snapshot.trustedOverlay == gui::TrustedOverlay::ENABLED) {
1199 snapshot.inputInfo.inputConfig |= InputConfig::TRUSTED_OVERLAY;
1200 }
1201
1202 snapshot.inputInfo.contentSize = {snapshot.croppedBufferSize.getHeight(),
1203 snapshot.croppedBufferSize.getWidth()};
1204
1205 // If the layer is a clone, we need to crop the input region to cloned root to prevent
1206 // touches from going outside the cloned area.
1207 if (path.isClone()) {
1208 snapshot.inputInfo.inputConfig |= InputConfig::CLONE;
1209 // Cloned layers shouldn't handle watch outside since their z order is not determined by
1210 // WM or the client.
1211 snapshot.inputInfo.inputConfig.clear(InputConfig::WATCH_OUTSIDE_TOUCH);
1212 }
1213 }
1214
getSnapshots()1215 std::vector<std::unique_ptr<LayerSnapshot>>& LayerSnapshotBuilder::getSnapshots() {
1216 return mSnapshots;
1217 }
1218
forEachVisibleSnapshot(const ConstVisitor & visitor) const1219 void LayerSnapshotBuilder::forEachVisibleSnapshot(const ConstVisitor& visitor) const {
1220 for (int i = 0; i < mNumInterestingSnapshots; i++) {
1221 LayerSnapshot& snapshot = *mSnapshots[(size_t)i];
1222 if (!snapshot.isVisible) continue;
1223 visitor(snapshot);
1224 }
1225 }
1226
1227 // Visit each visible snapshot in z-order
forEachVisibleSnapshot(const ConstVisitor & visitor,const LayerHierarchy & root) const1228 void LayerSnapshotBuilder::forEachVisibleSnapshot(const ConstVisitor& visitor,
1229 const LayerHierarchy& root) const {
1230 root.traverseInZOrder(
1231 [this, visitor](const LayerHierarchy&,
1232 const LayerHierarchy::TraversalPath& traversalPath) -> bool {
1233 LayerSnapshot* snapshot = getSnapshot(traversalPath);
1234 if (snapshot && snapshot->isVisible) {
1235 visitor(*snapshot);
1236 }
1237 return true;
1238 });
1239 }
1240
forEachVisibleSnapshot(const Visitor & visitor)1241 void LayerSnapshotBuilder::forEachVisibleSnapshot(const Visitor& visitor) {
1242 for (int i = 0; i < mNumInterestingSnapshots; i++) {
1243 std::unique_ptr<LayerSnapshot>& snapshot = mSnapshots.at((size_t)i);
1244 if (!snapshot->isVisible) continue;
1245 visitor(snapshot);
1246 }
1247 }
1248
forEachSnapshot(const Visitor & visitor,const ConstPredicate & predicate)1249 void LayerSnapshotBuilder::forEachSnapshot(const Visitor& visitor,
1250 const ConstPredicate& predicate) {
1251 for (int i = 0; i < mNumInterestingSnapshots; i++) {
1252 std::unique_ptr<LayerSnapshot>& snapshot = mSnapshots.at((size_t)i);
1253 if (!predicate(*snapshot)) continue;
1254 visitor(snapshot);
1255 }
1256 }
1257
forEachSnapshot(const ConstVisitor & visitor) const1258 void LayerSnapshotBuilder::forEachSnapshot(const ConstVisitor& visitor) const {
1259 for (auto& snapshot : mSnapshots) {
1260 visitor(*snapshot);
1261 }
1262 }
1263
forEachInputSnapshot(const ConstVisitor & visitor) const1264 void LayerSnapshotBuilder::forEachInputSnapshot(const ConstVisitor& visitor) const {
1265 for (int i = mNumInterestingSnapshots - 1; i >= 0; i--) {
1266 LayerSnapshot& snapshot = *mSnapshots[(size_t)i];
1267 if (!snapshot.hasInputInfo()) continue;
1268 if (FlagManager::getInstance().skip_invisible_windows_in_input() &&
1269 snapshot.inputInfo.inputConfig.test(gui::WindowInfo::InputConfig::NOT_VISIBLE)) {
1270 continue;
1271 }
1272 visitor(snapshot);
1273 }
1274 }
1275
updateTouchableRegionCrop(const Args & args)1276 void LayerSnapshotBuilder::updateTouchableRegionCrop(const Args& args) {
1277 if (mNeedsTouchableRegionCrop.empty()) {
1278 return;
1279 }
1280
1281 static constexpr ftl::Flags<RequestedLayerState::Changes> AFFECTS_INPUT =
1282 RequestedLayerState::Changes::Visibility | RequestedLayerState::Changes::Created |
1283 RequestedLayerState::Changes::Hierarchy | RequestedLayerState::Changes::Geometry |
1284 RequestedLayerState::Changes::Input;
1285
1286 if (args.forceUpdate != ForceUpdateFlags::ALL &&
1287 !args.layerLifecycleManager.getGlobalChanges().any(AFFECTS_INPUT) && !args.displayChanges) {
1288 return;
1289 }
1290
1291 for (auto& path : mNeedsTouchableRegionCrop) {
1292 frontend::LayerSnapshot* snapshot = getSnapshot(path);
1293 if (!snapshot) {
1294 continue;
1295 }
1296 LLOGV(snapshot->sequence, "updateTouchableRegionCrop=%s",
1297 snapshot->getDebugString().c_str());
1298 const std::optional<frontend::DisplayInfo> displayInfoOpt =
1299 args.displays.get(snapshot->outputFilter.layerStack);
1300 static frontend::DisplayInfo sDefaultInfo = {.isSecure = false};
1301 auto displayInfo = displayInfoOpt.value_or(sDefaultInfo);
1302
1303 bool needsUpdate =
1304 args.forceUpdate == ForceUpdateFlags::ALL || snapshot->changes.any(AFFECTS_INPUT);
1305 auto cropLayerSnapshot = getSnapshot(snapshot->touchCropId);
1306 needsUpdate =
1307 needsUpdate || (cropLayerSnapshot && cropLayerSnapshot->changes.any(AFFECTS_INPUT));
1308 auto clonedRootSnapshot = path.isClone() ? getSnapshot(snapshot->mirrorRootPath) : nullptr;
1309 needsUpdate = needsUpdate ||
1310 (clonedRootSnapshot && clonedRootSnapshot->changes.any(AFFECTS_INPUT));
1311
1312 if (!needsUpdate) {
1313 continue;
1314 }
1315
1316 if (snapshot->inputInfo.replaceTouchableRegionWithCrop) {
1317 Rect inputBoundsInDisplaySpace;
1318 if (!cropLayerSnapshot) {
1319 FloatRect inputBounds = getInputBounds(*snapshot, /*fillParentBounds=*/true).first;
1320 inputBoundsInDisplaySpace =
1321 getInputBoundsInDisplaySpace(*snapshot, inputBounds, displayInfo.transform);
1322 } else {
1323 FloatRect inputBounds =
1324 getInputBounds(*cropLayerSnapshot, /*fillParentBounds=*/true).first;
1325 inputBoundsInDisplaySpace =
1326 getInputBoundsInDisplaySpace(*cropLayerSnapshot, inputBounds,
1327 displayInfo.transform);
1328 }
1329 snapshot->inputInfo.touchableRegion = Region(inputBoundsInDisplaySpace);
1330 } else if (cropLayerSnapshot) {
1331 FloatRect inputBounds =
1332 getInputBounds(*cropLayerSnapshot, /*fillParentBounds=*/true).first;
1333 Rect inputBoundsInDisplaySpace =
1334 getInputBoundsInDisplaySpace(*cropLayerSnapshot, inputBounds,
1335 displayInfo.transform);
1336 snapshot->inputInfo.touchableRegion =
1337 snapshot->inputInfo.touchableRegion.intersect(inputBoundsInDisplaySpace);
1338 }
1339
1340 // If the layer is a clone, we need to crop the input region to cloned root to prevent
1341 // touches from going outside the cloned area.
1342 if (clonedRootSnapshot) {
1343 const Rect rect =
1344 displayInfo.transform.transform(Rect{clonedRootSnapshot->transformedBounds});
1345 snapshot->inputInfo.touchableRegion =
1346 snapshot->inputInfo.touchableRegion.intersect(rect);
1347 }
1348 }
1349 }
1350
1351 } // namespace android::surfaceflinger::frontend
1352