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