Merge "[sf] protect against out of order transactions" into udc-dev
diff --git a/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp b/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp
index 1f670c8..4dcdd96 100644
--- a/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp
+++ b/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp
@@ -158,12 +158,15 @@
RequestedLayerState::Changes::VisibleRegion |
RequestedLayerState::Changes::Visibility | RequestedLayerState::Changes::Input;
}
- if (clientState.what & layer_state_t::eBufferChanged) {
- changes |= RequestedLayerState::Changes::Buffer;
- }
- if (clientState.what & layer_state_t::eSidebandStreamChanged) {
- changes |= RequestedLayerState::Changes::SidebandStream;
- }
+ }
+ if (clientState.what & layer_state_t::eBufferChanged) {
+ barrierProducerId = std::max(bufferData->producerId, barrierProducerId);
+ barrierFrameNumber = std::max(bufferData->frameNumber, barrierFrameNumber);
+ // TODO(b/277265947) log and flush transaction trace when we detect out of order updates
+ changes |= RequestedLayerState::Changes::Buffer;
+ }
+ if (clientState.what & layer_state_t::eSidebandStreamChanged) {
+ changes |= RequestedLayerState::Changes::SidebandStream;
}
if (what & (layer_state_t::eAlphaChanged)) {
if (oldAlpha == 0 || color.a == 0) {
diff --git a/services/surfaceflinger/FrontEnd/RequestedLayerState.h b/services/surfaceflinger/FrontEnd/RequestedLayerState.h
index 216e95f..f15f023 100644
--- a/services/surfaceflinger/FrontEnd/RequestedLayerState.h
+++ b/services/surfaceflinger/FrontEnd/RequestedLayerState.h
@@ -111,6 +111,8 @@
ui::LayerStack layerStackToMirror = ui::INVALID_LAYER_STACK;
uint32_t touchCropId = UNASSIGNED_LAYER_ID;
uint32_t bgColorLayerId = UNASSIGNED_LAYER_ID;
+ uint64_t barrierFrameNumber = 0;
+ uint32_t barrierProducerId = 0;
// book keeping states
bool handleAlive = true;
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 3406e92..a538c6d 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -167,6 +167,9 @@
mDrawingState.sequence = 0;
mDrawingState.transform.set(0, 0);
mDrawingState.frameNumber = 0;
+ mDrawingState.barrierFrameNumber = 0;
+ mDrawingState.producerId = 0;
+ mDrawingState.barrierProducerId = 0;
mDrawingState.bufferTransform = 0;
mDrawingState.transformToDisplayInverse = false;
mDrawingState.crop.makeInvalid();
@@ -3070,7 +3073,13 @@
}
mDrawingState.producerId = bufferData.producerId;
+ mDrawingState.barrierProducerId =
+ std::max(mDrawingState.producerId, mDrawingState.barrierProducerId);
mDrawingState.frameNumber = frameNumber;
+ mDrawingState.barrierFrameNumber =
+ std::max(mDrawingState.frameNumber, mDrawingState.barrierFrameNumber);
+
+ // TODO(b/277265947) log and flush transaction trace when we detect out of order updates
mDrawingState.releaseBufferListener = bufferData.releaseBufferListener;
mDrawingState.buffer = std::move(buffer);
mDrawingState.clientCacheId = bufferData.cachedBuffer;
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 70b4e9b..acdd01d 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -139,9 +139,16 @@
ui::Dataspace dataspace;
uint64_t frameNumber;
+ // high watermark framenumber to use to check for barriers to protect ourselves
+ // from out of order transactions
+ uint64_t barrierFrameNumber;
ui::Transform transform;
uint32_t producerId = 0;
+ // high watermark producerId to use to check for barriers to protect ourselves
+ // from out of order transactions
+ uint32_t barrierProducerId = 0;
+
uint32_t bufferTransform;
bool transformToDisplayInverse;
Region transparentRegionHint;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 2f024ce..c4b8382 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -4228,7 +4228,7 @@
// The current producerId is already a newer producer than the buffer that has a
// barrier. This means the incoming buffer is older and we can release it here. We
// don't wait on the barrier since we know that's stale information.
- if (layer->getDrawingState().producerId > s.bufferData->producerId) {
+ if (layer->getDrawingState().barrierProducerId > s.bufferData->producerId) {
layer->callReleaseBufferCallback(s.bufferData->releaseBufferListener,
externalTexture->getBuffer(),
s.bufferData->frameNumber,
@@ -4239,7 +4239,7 @@
return TraverseBuffersReturnValues::DELETE_AND_CONTINUE_TRAVERSAL;
}
- if (layer->getDrawingState().frameNumber < s.bufferData->barrierFrameNumber) {
+ if (layer->getDrawingState().barrierFrameNumber < s.bufferData->barrierFrameNumber) {
const bool willApplyBarrierFrame =
flushState.bufferLayersReadyToPresent.contains(s.surface.get()) &&
((flushState.bufferLayersReadyToPresent.get(s.surface.get()) >=