Merge "Some fixes to TrustedPresentationListener"
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionRefreshArgs.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionRefreshArgs.h
index 4777f13..a8322d8 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionRefreshArgs.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionRefreshArgs.h
@@ -97,6 +97,8 @@
std::optional<std::chrono::steady_clock::time_point> scheduledFrameTime;
std::vector<BorderRenderInfo> borderInfoList;
+
+ bool hasTrustedPresentationListener = false;
};
} // namespace android::compositionengine
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h
index 5bb2497..32684fc 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h
@@ -212,6 +212,8 @@
float currentSdrHdrRatio = 1.f;
float desiredSdrHdrRatio = 1.f;
+ bool isInternalDisplayOverlay = false;
+
virtual ~LayerFECompositionState();
// Debugging
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
index 52ebd9e..a3d8639 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
@@ -153,6 +153,10 @@
Region aboveOpaqueLayers;
// The region of the output which should be considered dirty
Region dirtyRegion;
+ // The region of the output which is covered by layers, excluding display overlays. This
+ // only has a value if there's something needing it, like when a TrustedPresentationListener
+ // is set
+ std::optional<Region> aboveCoveredLayersExcludingOverlays;
};
virtual ~Output();
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h
index b86782f..7b0af3a 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h
@@ -63,9 +63,15 @@
// The portion of the layer that is not obscured and is also opaque
Region visibleNonTransparentRegion;
- // The portion of the layer that is obscured by opaque layers on top
+ // The portion of the layer that is obscured by all layers on top. This includes transparent and
+ // opaque.
Region coveredRegion;
+ // The portion of the layer that is obscured by all layers on top excluding display overlays.
+ // This only has a value if there's something needing it, like when a
+ // TrustedPresentationListener is set.
+ std::optional<Region> coveredRegionExcludingDisplayOverlays;
+
// The visibleRegion transformed to output space
Region outputSpaceVisibleRegion;
diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp
index 403385e..7d94316 100644
--- a/services/surfaceflinger/CompositionEngine/src/Output.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp
@@ -31,6 +31,7 @@
#include <ftl/future.h>
#include <gui/TraceUtils.h>
+#include <optional>
#include <thread>
#include "renderengine/ExternalTexture.h"
@@ -480,6 +481,9 @@
// Process the layers to determine visibility and coverage
compositionengine::Output::CoverageState coverage{layerFESet};
+ coverage.aboveCoveredLayersExcludingOverlays = refreshArgs.hasTrustedPresentationListener
+ ? std::make_optional<Region>()
+ : std::nullopt;
collectVisibleLayers(refreshArgs, coverage);
// Compute the resulting coverage for this output, and store it for later
@@ -534,6 +538,9 @@
return;
}
+ bool computeAboveCoveredExcludingOverlays =
+ coverage.aboveCoveredLayersExcludingOverlays && !layerFEState->isInternalDisplayOverlay;
+
/*
* opaqueRegion: area of a surface that is fully opaque.
*/
@@ -575,6 +582,11 @@
*/
Region shadowRegion;
+ /**
+ * covered region above excluding internal display overlay layers
+ */
+ std::optional<Region> coveredRegionExcludingDisplayOverlays = std::nullopt;
+
const ui::Transform& tr = layerFEState->geomLayerTransform;
// Get the visible region
@@ -647,6 +659,12 @@
// Update accumAboveCoveredLayers for next (lower) layer
coverage.aboveCoveredLayers.orSelf(visibleRegion);
+ if (CC_UNLIKELY(computeAboveCoveredExcludingOverlays)) {
+ coveredRegionExcludingDisplayOverlays =
+ coverage.aboveCoveredLayersExcludingOverlays->intersect(visibleRegion);
+ coverage.aboveCoveredLayersExcludingOverlays->orSelf(visibleRegion);
+ }
+
// subtract the opaque region covered by the layers above us
visibleRegion.subtractSelf(coverage.aboveOpaqueLayers);
@@ -733,6 +751,10 @@
? outputState.transform.transform(
transparentRegion.intersect(outputState.layerStackSpace.getContent()))
: Region();
+ if (CC_UNLIKELY(computeAboveCoveredExcludingOverlays)) {
+ outputLayerState.coveredRegionExcludingDisplayOverlays =
+ std::move(coveredRegionExcludingDisplayOverlays);
+ }
}
void Output::setReleasedLayers(const compositionengine::CompositionRefreshArgs&) {
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 704f336..084d9b9 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -393,14 +393,22 @@
if (!leaveState) {
const auto outputLayer = findOutputLayerForDisplay(display);
- if (outputLayer != nullptr && snapshot != nullptr) {
- mLastComputedTrustedPresentationState =
- computeTrustedPresentationState(snapshot->geomLayerBounds,
- snapshot->sourceBounds(),
- outputLayer->getState().coveredRegion,
- snapshot->transformedBounds, snapshot->alpha,
- snapshot->geomLayerTransform,
- mTrustedPresentationThresholds);
+ if (outputLayer != nullptr) {
+ if (outputLayer->getState().coveredRegionExcludingDisplayOverlays) {
+ Region coveredRegion =
+ *outputLayer->getState().coveredRegionExcludingDisplayOverlays;
+ mLastComputedTrustedPresentationState =
+ computeTrustedPresentationState(snapshot->geomLayerBounds,
+ snapshot->sourceBounds(), coveredRegion,
+ snapshot->transformedBounds,
+ snapshot->alpha,
+ snapshot->geomLayerTransform,
+ mTrustedPresentationThresholds);
+ } else {
+ ALOGE("CoveredRegionExcludingDisplayOverlays was not set for %s. Don't compute "
+ "TrustedPresentationState",
+ getDebugName());
+ }
}
}
const bool newState = mLastComputedTrustedPresentationState;
@@ -457,10 +465,15 @@
float boundsOverSourceH = bounds.getHeight() / (float)sourceBounds.getHeight();
fractionRendered *= boundsOverSourceW * boundsOverSourceH;
- Rect coveredBounds = coveredRegion.bounds();
- fractionRendered *= (1 -
- ((coveredBounds.width() / (float)screenBounds.getWidth()) *
- coveredBounds.height() / (float)screenBounds.getHeight()));
+ Region tJunctionFreeRegion = Region::createTJunctionFreeRegion(coveredRegion);
+ // Compute the size of all the rects since they may be disconnected.
+ float coveredSize = 0;
+ for (auto rect = tJunctionFreeRegion.begin(); rect < tJunctionFreeRegion.end(); rect++) {
+ float size = rect->width() * rect->height();
+ coveredSize += size;
+ }
+
+ fractionRendered *= (1 - (coveredSize / (screenBounds.getWidth() * screenBounds.getHeight())));
if (fractionRendered < thresholds.minFractionRendered) {
return false;
@@ -3993,6 +4006,7 @@
snapshot->bufferSize = getBufferSize(mDrawingState);
snapshot->externalTexture = mBufferInfo.mBuffer;
snapshot->hasReadyFrame = hasReadyFrame();
+ snapshot->isInternalDisplayOverlay = isInternalDisplayOverlay();
preparePerFrameCompositionState();
}
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index b42576f..732390e 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -2517,6 +2517,7 @@
refreshArgs.previousPresentFence = mPreviousPresentFences[0].fenceTime;
refreshArgs.scheduledFrameTime = mScheduler->getScheduledFrameTime();
refreshArgs.expectedPresentTime = mExpectedPresentTime.ns();
+ refreshArgs.hasTrustedPresentationListener = mNumTrustedPresentationListeners > 0;
// Store the present time just before calling to the composition engine so we could notify
// the scheduler.
diff --git a/services/surfaceflinger/tests/LayerTrustedPresentationListener_test.cpp b/services/surfaceflinger/tests/LayerTrustedPresentationListener_test.cpp
index a843fd1..2be8d3b 100644
--- a/services/surfaceflinger/tests/LayerTrustedPresentationListener_test.cpp
+++ b/services/surfaceflinger/tests/LayerTrustedPresentationListener_test.cpp
@@ -238,4 +238,50 @@
EXPECT_TRUE(pch.awaitCallback());
}
+TEST_F(LayerTrustedPresentationListenerTest, obscuring_with_display_overlay) {
+ auto otherLayer = makeLayer();
+ t.show(otherLayer)
+ .setPosition(otherLayer, 100, 100)
+ .setLayer(otherLayer, INT32_MAX)
+ .setFlags(otherLayer, layer_state_t::eLayerSkipScreenshot,
+ layer_state_t::eLayerSkipScreenshot)
+ .setLayer(mainLayer, INT32_MAX - 1)
+ .show(mainLayer)
+ .setPosition(mainLayer, 100, 100)
+ .setTrustedPresentationCallback(
+ mainLayer,
+ [&](void* context, bool state) {
+ PresentationCallbackHelper* helper = (PresentationCallbackHelper*)context;
+ helper->callbackArrived(state);
+ },
+ thresholds, &pch, mCallback)
+ .apply();
+ EXPECT_TRUE(pch.awaitCallback());
+}
+
+TEST_F(LayerTrustedPresentationListenerTest, obscuring_with_non_overlapping_bounds) {
+ thresholds.minFractionRendered = 0.5;
+ auto otherLayer1 = makeLayer();
+ auto otherLayer2 = makeLayer();
+ t.show(otherLayer1)
+ .show(otherLayer2)
+ .setPosition(otherLayer1, 100, 25)
+ .setLayer(otherLayer1, INT32_MAX)
+ .setPosition(otherLayer2, 100, 175)
+ .setLayer(otherLayer2, INT32_MAX)
+ .setLayer(mainLayer, INT32_MAX - 1)
+ .show(mainLayer)
+ .setPosition(mainLayer, 100, 100)
+ .setTrustedPresentationCallback(
+ mainLayer,
+ [&](void* context, bool state) {
+ PresentationCallbackHelper* helper = (PresentationCallbackHelper*)context;
+ helper->callbackArrived(state);
+ },
+ thresholds, &pch, mCallback)
+ .apply();
+
+ EXPECT_TRUE(pch.awaitCallback());
+}
+
} // namespace android