Introduce eCanOccludePresentation layer flag
Sets a property on a layer hierarchy indicating that its visible region
should be considered when computing TrustedPresentation
Thresholds. This property is set on a layer and inherited by all its
children. The property is then passed via windowinfos so the
TrustedPresentation controller can determine which windows to
use when computing the thresholds.
Test: presubmit
Bug: b/275574214
Change-Id: Ide384c64cb7b5a9b2b3ce293b20e2be64da8ad69
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index 38fab9c..7564c26 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -199,7 +199,7 @@
SAFE_PARCEL(output.writeParcelable, trustedPresentationListener);
SAFE_PARCEL(output.writeFloat, currentHdrSdrRatio);
SAFE_PARCEL(output.writeFloat, desiredHdrSdrRatio);
- SAFE_PARCEL(output.writeInt32, static_cast<int32_t>(cachingHint))
+ SAFE_PARCEL(output.writeInt32, static_cast<int32_t>(cachingHint));
return NO_ERROR;
}
@@ -484,6 +484,12 @@
flags &= ~eLayerIsDisplayDecoration;
ALOGE("Stripped attempt to set LayerIsDisplayDecoration in sanitize");
}
+ if ((mask & eCanOccludePresentation) &&
+ !(permissions & Permission::ACCESS_SURFACE_FLINGER)) {
+ flags &= ~eCanOccludePresentation;
+ mask &= ~eCanOccludePresentation;
+ ALOGE("Stripped attempt to set eCanOccludePresentation in sanitize");
+ }
}
if (what & layer_state_t::eInputInfoChanged) {
diff --git a/libs/gui/WindowInfo.cpp b/libs/gui/WindowInfo.cpp
index 95b2641..9429d2c 100644
--- a/libs/gui/WindowInfo.cpp
+++ b/libs/gui/WindowInfo.cpp
@@ -109,7 +109,8 @@
info.inputConfig == inputConfig && info.displayId == displayId &&
info.replaceTouchableRegionWithCrop == replaceTouchableRegionWithCrop &&
info.applicationInfo == applicationInfo && info.layoutParamsType == layoutParamsType &&
- info.layoutParamsFlags == layoutParamsFlags;
+ info.layoutParamsFlags == layoutParamsFlags &&
+ info.canOccludePresentation == canOccludePresentation;
}
status_t WindowInfo::writeToParcel(android::Parcel* parcel) const {
@@ -158,8 +159,9 @@
parcel->write(touchableRegion) ?:
parcel->writeBool(replaceTouchableRegionWithCrop) ?:
parcel->writeStrongBinder(touchableRegionCropHandle.promote()) ?:
- parcel->writeStrongBinder(windowToken);
- parcel->writeStrongBinder(focusTransferTarget);
+ parcel->writeStrongBinder(windowToken) ?:
+ parcel->writeStrongBinder(focusTransferTarget) ?:
+ parcel->writeBool(canOccludePresentation);
// clang-format on
return status;
}
@@ -210,7 +212,8 @@
parcel->readBool(&replaceTouchableRegionWithCrop) ?:
parcel->readNullableStrongBinder(&touchableRegionCropHandleSp) ?:
parcel->readNullableStrongBinder(&windowToken) ?:
- parcel->readNullableStrongBinder(&focusTransferTarget);
+ parcel->readNullableStrongBinder(&focusTransferTarget) ?:
+ parcel->readBool(&canOccludePresentation);
// clang-format on
@@ -273,6 +276,7 @@
<< "ms, token=" << info.token.get()
<< ", touchOcclusionMode=" << ftl::enum_string(info.touchOcclusionMode) << "\n"
<< transform;
+ if (info.canOccludePresentation) out << " canOccludePresentation";
return out;
}
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index 6b8e824..920310e 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -161,6 +161,9 @@
// See SurfaceView scaling behavior for more details.
eIgnoreDestinationFrame = 0x400,
eLayerIsRefreshRateIndicator = 0x800, // REFRESH_RATE_INDICATOR
+ // Sets a property on this layer indicating that its visible region should be considered
+ // when computing TrustedPresentation Thresholds.
+ eCanOccludePresentation = 0x1000,
};
enum {
diff --git a/libs/gui/include/gui/WindowInfo.h b/libs/gui/include/gui/WindowInfo.h
index e72fd59..32d60be 100644
--- a/libs/gui/include/gui/WindowInfo.h
+++ b/libs/gui/include/gui/WindowInfo.h
@@ -246,6 +246,10 @@
// any other window.
sp<IBinder> focusTransferTarget;
+ // Sets a property on this window indicating that its visible region should be considered when
+ // computing TrustedPresentation Thresholds.
+ bool canOccludePresentation = false;
+
void setInputConfig(ftl::Flags<InputConfig> config, bool value);
void addTouchableRegion(const Rect& region);
diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp b/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp
index 38974a2..3ef9e69 100644
--- a/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp
+++ b/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp
@@ -315,6 +315,7 @@
if (obj.hasInputInfo()) {
out << "\n input{"
<< "(" << obj.inputInfo.inputConfig.string() << ")";
+ if (obj.inputInfo.canOccludePresentation) out << " canOccludePresentation";
if (obj.touchCropId != UNASSIGNED_LAYER_ID) out << " touchCropId=" << obj.touchCropId;
if (obj.inputInfo.replaceTouchableRegionWithCrop) out << " replaceTouchableRegionWithCrop";
auto touchableRegion = obj.inputInfo.touchableRegion.getBounds();
diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp
index 8df5d8c..0966fe0 100644
--- a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp
+++ b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp
@@ -1044,6 +1044,8 @@
snapshot.inputInfo.touchOcclusionMode = requested.hasInputInfo()
? requested.windowInfoHandle->getInfo()->touchOcclusionMode
: parentSnapshot.inputInfo.touchOcclusionMode;
+ snapshot.inputInfo.canOccludePresentation = parentSnapshot.inputInfo.canOccludePresentation ||
+ (requested.flags & layer_state_t::eCanOccludePresentation);
if (requested.dropInputMode == gui::DropInputMode::ALL ||
parentSnapshot.dropInputMode == gui::DropInputMode::ALL) {
snapshot.dropInputMode = gui::DropInputMode::ALL;
diff --git a/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp b/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp
index 209df79..2cf4c1b 100644
--- a/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp
+++ b/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp
@@ -170,6 +170,9 @@
if ((oldFlags ^ flags) & layer_state_t::eIgnoreDestinationFrame) {
changes |= RequestedLayerState::Changes::Geometry;
}
+ if ((oldFlags ^ flags) & layer_state_t::eCanOccludePresentation) {
+ changes |= RequestedLayerState::Changes::Input;
+ }
}
if (clientState.what & layer_state_t::eBufferChanged) {
diff --git a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp
index 13b47ff..3baa48d 100644
--- a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp
@@ -1237,4 +1237,25 @@
EXPECT_TRUE(foundInputLayer);
}
+TEST_F(LayerSnapshotTest, canOccludePresentation) {
+ setFlags(12, layer_state_t::eCanOccludePresentation, layer_state_t::eCanOccludePresentation);
+ LayerSnapshotBuilder::Args args{.root = mHierarchyBuilder.getHierarchy(),
+ .layerLifecycleManager = mLifecycleManager,
+ .includeMetadata = false,
+ .displays = mFrontEndDisplayInfos,
+ .displayChanges = false,
+ .globalShadowSettings = globalShadowSettings,
+ .supportsBlur = true,
+ .supportedLayerGenericMetadata = {},
+ .genericLayerMetadataKeyMap = {}};
+ UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);
+
+ EXPECT_EQ(getSnapshot(1)->inputInfo.canOccludePresentation, false);
+
+ // ensure we can set the property on the window info for layer and all its children
+ EXPECT_EQ(getSnapshot(12)->inputInfo.canOccludePresentation, true);
+ EXPECT_EQ(getSnapshot(121)->inputInfo.canOccludePresentation, true);
+ EXPECT_EQ(getSnapshot(1221)->inputInfo.canOccludePresentation, true);
+}
+
} // namespace android::surfaceflinger::frontend