Combine Buffer Properties when calling setBuffer

There are several properties, like releaseCallback, acquireFence,
frameNumber, that are tied to the buffer being set. If a new buffer is
set, all those properties should also be overwritten, rather than
through a separate call.

1. Remove Transaction.setAcquireFence and Transaction.setFrameNumber and
added them to the setBuffer as optional

2. Combine all the buffer info into a struct called BufferData that's
sent to SF as one. This will also help with merging or overwriting
buffer data since the callback, frameNumber, and acquireFence should
also be updated.

3. Combine the functions in SF so there's no longer a separate call to
BSL to set fence. Instead, send all buffer related data to BSL.setBuffer

Test: SurfaceFlinger_test
Fixes: 200065015
Change-Id: I53ad12dd105cd4cac6c3a7ecd48279d1b3cd2b8f
diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp
index 379b090..cc209f3 100644
--- a/libs/gui/BLASTBufferQueue.cpp
+++ b/libs/gui/BLASTBufferQueue.cpp
@@ -468,12 +468,12 @@
             std::bind(releaseBufferCallbackThunk, wp<BLASTBufferQueue>(this) /* callbackContext */,
                       std::placeholders::_1, std::placeholders::_2, std::placeholders::_3,
                       std::placeholders::_4);
-    t->setBuffer(mSurfaceControl, buffer, releaseCallbackId, releaseBufferCallback);
+    sp<Fence> fence = bufferItem.mFence ? new Fence(bufferItem.mFence->dup()) : Fence::NO_FENCE;
+    t->setBuffer(mSurfaceControl, buffer, fence, bufferItem.mFrameNumber, releaseCallbackId,
+                 releaseBufferCallback);
     t->setDataspace(mSurfaceControl, static_cast<ui::Dataspace>(bufferItem.mDataSpace));
     t->setHdrMetadata(mSurfaceControl, bufferItem.mHdrMetadata);
     t->setSurfaceDamageRegion(mSurfaceControl, bufferItem.mSurfaceDamage);
-    t->setAcquireFence(mSurfaceControl,
-                       bufferItem.mFence ? new Fence(bufferItem.mFence->dup()) : Fence::NO_FENCE);
     t->addTransactionCompletedCallback(transactionCallbackThunk, static_cast<void*>(this));
     mSurfaceControlsWithPendingCallback.push(mSurfaceControl);
 
@@ -486,7 +486,6 @@
     if (!bufferItem.mIsAutoTimestamp) {
         t->setDesiredPresentTime(bufferItem.mTimestamp);
     }
-    t->setFrameNumber(mSurfaceControl, bufferItem.mFrameNumber);
 
     if (!mNextFrameTimelineInfoQueue.empty()) {
         t->setFrameTimelineInfo(mNextFrameTimelineInfoQueue.front());
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index a419a63..cf61209 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -64,12 +64,10 @@
         frameRateCompatibility(ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT),
         changeFrameRateStrategy(ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS),
         fixedTransformHint(ui::Transform::ROT_INVALID),
-        frameNumber(0),
         autoRefresh(false),
         isTrustedOverlay(false),
         bufferCrop(Rect::INVALID_RECT),
         destinationFrame(Rect::INVALID_RECT),
-        releaseBufferListener(nullptr),
         dropInputMode(gui::DropInputMode::NONE) {
     matrix.dsdx = matrix.dtdy = 1.0f;
     matrix.dsdy = matrix.dtdx = 0.0f;
@@ -104,20 +102,6 @@
     SAFE_PARCEL(output.writeBool, transformToDisplayInverse);
     SAFE_PARCEL(output.write, orientedDisplaySpaceRect);
 
-    if (buffer) {
-        SAFE_PARCEL(output.writeBool, true);
-        SAFE_PARCEL(output.write, *buffer);
-    } else {
-        SAFE_PARCEL(output.writeBool, false);
-    }
-
-    if (acquireFence) {
-        SAFE_PARCEL(output.writeBool, true);
-        SAFE_PARCEL(output.write, *acquireFence);
-    } else {
-        SAFE_PARCEL(output.writeBool, false);
-    }
-
     SAFE_PARCEL(output.writeUint32, static_cast<uint32_t>(dataspace));
     SAFE_PARCEL(output.write, hdrMetadata);
     SAFE_PARCEL(output.write, surfaceDamageRegion);
@@ -133,8 +117,6 @@
     SAFE_PARCEL(output.write, colorTransform.asArray(), 16 * sizeof(float));
     SAFE_PARCEL(output.writeFloat, cornerRadius);
     SAFE_PARCEL(output.writeUint32, backgroundBlurRadius);
-    SAFE_PARCEL(output.writeStrongBinder, cachedBuffer.token.promote());
-    SAFE_PARCEL(output.writeUint64, cachedBuffer.id);
     SAFE_PARCEL(output.writeParcelable, metadata);
     SAFE_PARCEL(output.writeFloat, bgColorAlpha);
     SAFE_PARCEL(output.writeUint32, static_cast<uint32_t>(bgColorDataspace));
@@ -151,9 +133,7 @@
     SAFE_PARCEL(output.writeByte, frameRateCompatibility);
     SAFE_PARCEL(output.writeByte, changeFrameRateStrategy);
     SAFE_PARCEL(output.writeUint32, fixedTransformHint);
-    SAFE_PARCEL(output.writeUint64, frameNumber);
     SAFE_PARCEL(output.writeBool, autoRefresh);
-    SAFE_PARCEL(output.writeStrongBinder, IInterface::asBinder(releaseBufferListener));
 
     SAFE_PARCEL(output.writeUint32, blurRegions.size());
     for (auto region : blurRegions) {
@@ -174,8 +154,8 @@
     SAFE_PARCEL(output.write, destinationFrame);
     SAFE_PARCEL(output.writeBool, isTrustedOverlay);
 
-    SAFE_PARCEL(output.writeStrongBinder, releaseBufferEndpoint);
     SAFE_PARCEL(output.writeUint32, static_cast<uint32_t>(dropInputMode));
+    SAFE_PARCEL(bufferData.write, output);
     return NO_ERROR;
 }
 
@@ -217,19 +197,6 @@
     SAFE_PARCEL(input.readBool, &transformToDisplayInverse);
     SAFE_PARCEL(input.read, orientedDisplaySpaceRect);
 
-    bool tmpBool = false;
-    SAFE_PARCEL(input.readBool, &tmpBool);
-    if (tmpBool) {
-        buffer = new GraphicBuffer();
-        SAFE_PARCEL(input.read, *buffer);
-    }
-
-    SAFE_PARCEL(input.readBool, &tmpBool);
-    if (tmpBool) {
-        acquireFence = new Fence();
-        SAFE_PARCEL(input.read, *acquireFence);
-    }
-
     uint32_t tmpUint32 = 0;
     SAFE_PARCEL(input.readUint32, &tmpUint32);
     dataspace = static_cast<ui::Dataspace>(tmpUint32);
@@ -237,6 +204,8 @@
     SAFE_PARCEL(input.read, hdrMetadata);
     SAFE_PARCEL(input.read, surfaceDamageRegion);
     SAFE_PARCEL(input.readInt32, &api);
+
+    bool tmpBool = false;
     SAFE_PARCEL(input.readBool, &tmpBool);
     if (tmpBool) {
         sidebandStream = NativeHandle::create(input.readNativeHandle(), true);
@@ -245,10 +214,6 @@
     SAFE_PARCEL(input.read, &colorTransform, 16 * sizeof(float));
     SAFE_PARCEL(input.readFloat, &cornerRadius);
     SAFE_PARCEL(input.readUint32, &backgroundBlurRadius);
-    sp<IBinder> tmpBinder;
-    SAFE_PARCEL(input.readNullableStrongBinder, &tmpBinder);
-    cachedBuffer.token = tmpBinder;
-    SAFE_PARCEL(input.readUint64, &cachedBuffer.id);
     SAFE_PARCEL(input.readParcelable, &metadata);
 
     SAFE_PARCEL(input.readFloat, &bgColorAlpha);
@@ -273,15 +238,8 @@
     SAFE_PARCEL(input.readByte, &changeFrameRateStrategy);
     SAFE_PARCEL(input.readUint32, &tmpUint32);
     fixedTransformHint = static_cast<ui::Transform::RotationFlags>(tmpUint32);
-    SAFE_PARCEL(input.readUint64, &frameNumber);
     SAFE_PARCEL(input.readBool, &autoRefresh);
 
-    tmpBinder = nullptr;
-    SAFE_PARCEL(input.readNullableStrongBinder, &tmpBinder);
-    if (tmpBinder) {
-        releaseBufferListener = checked_interface_cast<ITransactionCompletedListener>(tmpBinder);
-    }
-
     uint32_t numRegions = 0;
     SAFE_PARCEL(input.readUint32, &numRegions);
     blurRegions.clear();
@@ -305,11 +263,10 @@
     SAFE_PARCEL(input.read, destinationFrame);
     SAFE_PARCEL(input.readBool, &isTrustedOverlay);
 
-    SAFE_PARCEL(input.readNullableStrongBinder, &releaseBufferEndpoint);
-
     uint32_t mode;
     SAFE_PARCEL(input.readUint32, &mode);
     dropInputMode = static_cast<gui::DropInputMode>(mode);
+    SAFE_PARCEL(bufferData.read, input);
     return NO_ERROR;
 }
 
@@ -460,12 +417,7 @@
     }
     if (other.what & eBufferChanged) {
         what |= eBufferChanged;
-        buffer = other.buffer;
-        releaseBufferEndpoint = other.releaseBufferEndpoint;
-    }
-    if (other.what & eAcquireFenceChanged) {
-        what |= eAcquireFenceChanged;
-        acquireFence = other.acquireFence;
+        bufferData = other.bufferData;
     }
     if (other.what & eDataspaceChanged) {
         what |= eDataspaceChanged;
@@ -498,10 +450,6 @@
         what |= eInputInfoChanged;
         windowInfoHandle = new WindowInfoHandle(*other.windowInfoHandle);
     }
-    if (other.what & eCachedBufferChanged) {
-        what |= eCachedBufferChanged;
-        cachedBuffer = other.cachedBuffer;
-    }
     if (other.what & eBackgroundColorChanged) {
         what |= eBackgroundColorChanged;
         color = other.color;
@@ -530,10 +478,6 @@
         what |= eFixedTransformHintChanged;
         fixedTransformHint = other.fixedTransformHint;
     }
-    if (other.what & eFrameNumberChanged) {
-        what |= eFrameNumberChanged;
-        frameNumber = other.frameNumber;
-    }
     if (other.what & eAutoRefreshChanged) {
         what |= eAutoRefreshChanged;
         autoRefresh = other.autoRefresh;
@@ -542,13 +486,6 @@
         what |= eTrustedOverlayChanged;
         isTrustedOverlay = other.isTrustedOverlay;
     }
-    if (other.what & eReleaseBufferListenerChanged) {
-        if (releaseBufferListener) {
-            ALOGW("Overriding releaseBufferListener");
-        }
-        what |= eReleaseBufferListenerChanged;
-        releaseBufferListener = other.releaseBufferListener;
-    }
     if (other.what & eStretchChanged) {
         what |= eStretchChanged;
         stretchEffect = other.stretchEffect;
@@ -576,11 +513,11 @@
 }
 
 bool layer_state_t::hasBufferChanges() const {
-    return (what & layer_state_t::eBufferChanged) || (what & layer_state_t::eCachedBufferChanged);
+    return what & layer_state_t::eBufferChanged;
 }
 
 bool layer_state_t::hasValidBuffer() const {
-    return buffer || cachedBuffer.isValid();
+    return bufferData.buffer || bufferData.cachedBuffer.isValid();
 }
 
 status_t layer_state_t::matrix22_t::write(Parcel& output) const {
@@ -741,4 +678,66 @@
     return NO_ERROR;
 }
 
+status_t BufferData::write(Parcel& output) const {
+    SAFE_PARCEL(output.writeInt32, flags.get());
+
+    if (buffer) {
+        SAFE_PARCEL(output.writeBool, true);
+        SAFE_PARCEL(output.write, *buffer);
+    } else {
+        SAFE_PARCEL(output.writeBool, false);
+    }
+
+    if (acquireFence) {
+        SAFE_PARCEL(output.writeBool, true);
+        SAFE_PARCEL(output.write, *acquireFence);
+    } else {
+        SAFE_PARCEL(output.writeBool, false);
+    }
+
+    SAFE_PARCEL(output.writeUint64, frameNumber);
+    SAFE_PARCEL(output.writeStrongBinder, IInterface::asBinder(releaseBufferListener));
+    SAFE_PARCEL(output.writeStrongBinder, releaseBufferEndpoint);
+
+    SAFE_PARCEL(output.writeStrongBinder, cachedBuffer.token.promote());
+    SAFE_PARCEL(output.writeUint64, cachedBuffer.id);
+
+    return NO_ERROR;
+}
+
+status_t BufferData::read(const Parcel& input) {
+    int32_t tmpInt32;
+    SAFE_PARCEL(input.readInt32, &tmpInt32);
+    flags = Flags<BufferDataChange>(tmpInt32);
+
+    bool tmpBool = false;
+    SAFE_PARCEL(input.readBool, &tmpBool);
+    if (tmpBool) {
+        buffer = new GraphicBuffer();
+        SAFE_PARCEL(input.read, *buffer);
+    }
+
+    SAFE_PARCEL(input.readBool, &tmpBool);
+    if (tmpBool) {
+        acquireFence = new Fence();
+        SAFE_PARCEL(input.read, *acquireFence);
+    }
+
+    SAFE_PARCEL(input.readUint64, &frameNumber);
+
+    sp<IBinder> tmpBinder = nullptr;
+    SAFE_PARCEL(input.readNullableStrongBinder, &tmpBinder);
+    if (tmpBinder) {
+        releaseBufferListener = checked_interface_cast<ITransactionCompletedListener>(tmpBinder);
+    }
+    SAFE_PARCEL(input.readNullableStrongBinder, &releaseBufferEndpoint);
+
+    tmpBinder = nullptr;
+    SAFE_PARCEL(input.readNullableStrongBinder, &tmpBinder);
+    cachedBuffer.token = tmpBinder;
+    SAFE_PARCEL(input.readUint64, &cachedBuffer.id);
+
+    return NO_ERROR;
+}
+
 }; // namespace android
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index bbd3cca..aca59b6 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -805,7 +805,7 @@
         layer_state_t* s = &(mComposerStates[handle].state);
         if (!(s->what & layer_state_t::eBufferChanged)) {
             continue;
-        } else if (s->what & layer_state_t::eCachedBufferChanged) {
+        } else if (s->bufferData.flags.test(BufferData::BufferDataChange::cachedBufferChanged)) {
             // If eBufferChanged and eCachedBufferChanged are both trued then that means
             // we already cached the buffer in a previous call to cacheBuffers, perhaps
             // from writeToParcel on a Transaction that was merged in to this one.
@@ -814,23 +814,22 @@
 
         // Don't try to cache a null buffer. Sending null buffers is cheap so we shouldn't waste
         // time trying to cache them.
-        if (!s->buffer) {
+        if (!s->bufferData.buffer) {
             continue;
         }
 
         uint64_t cacheId = 0;
-        status_t ret = BufferCache::getInstance().getCacheId(s->buffer, &cacheId);
+        status_t ret = BufferCache::getInstance().getCacheId(s->bufferData.buffer, &cacheId);
         if (ret == NO_ERROR) {
             // Cache-hit. Strip the buffer and send only the id.
-            s->what &= ~static_cast<uint64_t>(layer_state_t::eBufferChanged);
-            s->buffer = nullptr;
+            s->bufferData.buffer = nullptr;
         } else {
             // Cache-miss. Include the buffer and send the new cacheId.
-            cacheId = BufferCache::getInstance().cache(s->buffer);
+            cacheId = BufferCache::getInstance().cache(s->bufferData.buffer);
         }
-        s->what |= layer_state_t::eCachedBufferChanged;
-        s->cachedBuffer.token = BufferCache::getInstance().getToken();
-        s->cachedBuffer.id = cacheId;
+        s->bufferData.flags |= BufferData::BufferDataChange::cachedBufferChanged;
+        s->bufferData.cachedBuffer.token = BufferCache::getInstance().getToken();
+        s->bufferData.cachedBuffer.id = cacheId;
 
         // If we have more buffers than the size of the cache, we should stop caching so we don't
         // evict other buffers in this transaction
@@ -1289,22 +1288,33 @@
 }
 
 SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setBuffer(
-        const sp<SurfaceControl>& sc, const sp<GraphicBuffer>& buffer, const ReleaseCallbackId& id,
-        ReleaseBufferCallback callback) {
+        const sp<SurfaceControl>& sc, const sp<GraphicBuffer>& buffer,
+        const std::optional<sp<Fence>>& fence, const std::optional<uint64_t>& frameNumber,
+        const ReleaseCallbackId& id, ReleaseBufferCallback callback) {
     layer_state_t* s = getLayerState(sc);
     if (!s) {
         mStatus = BAD_INDEX;
         return *this;
     }
     removeReleaseBufferCallback(s);
-    s->what |= layer_state_t::eBufferChanged;
-    s->buffer = buffer;
-    s->releaseBufferEndpoint = IInterface::asBinder(TransactionCompletedListener::getIInstance());
+    BufferData bufferData;
+    bufferData.buffer = buffer;
+    if (frameNumber) {
+        bufferData.frameNumber = *frameNumber;
+        bufferData.flags |= BufferData::BufferDataChange::frameNumberChanged;
+    }
+    if (fence) {
+        bufferData.acquireFence = *fence;
+        bufferData.flags |= BufferData::BufferDataChange::fenceChanged;
+    }
+    bufferData.releaseBufferEndpoint =
+            IInterface::asBinder(TransactionCompletedListener::getIInstance());
     if (mIsAutoTimestamp) {
         mDesiredPresentTime = systemTime();
     }
-    setReleaseBufferCallback(s, id, callback);
-
+    setReleaseBufferCallback(&bufferData, id, callback);
+    s->what |= layer_state_t::eBufferChanged;
+    s->bufferData = bufferData;
     registerSurfaceControlForCallback(sc);
 
     mContainsBuffer = true;
@@ -1312,51 +1322,33 @@
 }
 
 void SurfaceComposerClient::Transaction::removeReleaseBufferCallback(layer_state_t* s) {
-    if (!s->releaseBufferListener) {
+    if (!(s->what & layer_state_t::eBufferChanged)) {
         return;
     }
 
-    s->what &= ~static_cast<uint64_t>(layer_state_t::eReleaseBufferListenerChanged);
-    s->releaseBufferListener = nullptr;
     auto listener = TransactionCompletedListener::getInstance();
-    listener->removeReleaseBufferCallback(s->releaseCallbackId);
-    s->releaseCallbackId = ReleaseCallbackId::INVALID_ID;
+    listener->removeReleaseBufferCallback(s->bufferData.releaseCallbackId);
 }
 
-void SurfaceComposerClient::Transaction::setReleaseBufferCallback(layer_state_t* s,
+void SurfaceComposerClient::Transaction::setReleaseBufferCallback(BufferData* bufferData,
                                                                   const ReleaseCallbackId& id,
                                                                   ReleaseBufferCallback callback) {
     if (!callback) {
         return;
     }
 
-    if (!s->buffer) {
+    if (!bufferData->buffer) {
         ALOGW("Transaction::setReleaseBufferCallback"
               "ignored trying to set a callback on a null buffer.");
         return;
     }
 
-    s->what |= layer_state_t::eReleaseBufferListenerChanged;
-    s->releaseBufferListener = TransactionCompletedListener::getIInstance();
-    s->releaseCallbackId = id;
+    bufferData->releaseBufferListener = TransactionCompletedListener::getIInstance();
+    bufferData->releaseCallbackId = id;
     auto listener = TransactionCompletedListener::getInstance();
     listener->setReleaseBufferCallback(id, callback);
 }
 
-SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setAcquireFence(
-        const sp<SurfaceControl>& sc, const sp<Fence>& fence) {
-    layer_state_t* s = getLayerState(sc);
-    if (!s) {
-        mStatus = BAD_INDEX;
-        return *this;
-    }
-    s->what |= layer_state_t::eAcquireFenceChanged;
-    s->acquireFence = fence;
-
-    registerSurfaceControlForCallback(sc);
-    return *this;
-}
-
 SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setDataspace(
         const sp<SurfaceControl>& sc, ui::Dataspace dataspace) {
     layer_state_t* s = getLayerState(sc);
@@ -1506,20 +1498,6 @@
     return *this;
 }
 
-SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFrameNumber(
-        const sp<SurfaceControl>& sc, uint64_t frameNumber) {
-    layer_state_t* s = getLayerState(sc);
-    if (!s) {
-        mStatus = BAD_INDEX;
-        return *this;
-    }
-
-    s->what |= layer_state_t::eFrameNumberChanged;
-    s->frameNumber = frameNumber;
-
-    return *this;
-}
-
 SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setInputWindowInfo(
         const sp<SurfaceControl>& sc, const WindowInfo& info) {
     layer_state_t* s = getLayerState(sc);
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index b27102b..1f5d289 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -58,6 +58,44 @@
     bool isValid() const { return token != nullptr; }
 };
 
+struct BufferData {
+    enum class BufferDataChange : uint32_t {
+        fenceChanged = 0x01,
+        frameNumberChanged = 0x02,
+        cachedBufferChanged = 0x04,
+    };
+
+    sp<GraphicBuffer> buffer;
+    sp<Fence> acquireFence;
+
+    // Used by BlastBufferQueue to forward the framenumber generated by the
+    // graphics producer.
+    uint64_t frameNumber = 0;
+
+    // Listens to when the buffer is safe to be released. This is used for blast
+    // layers only. The callback includes a release fence as well as the graphic
+    // buffer id to identify the buffer.
+    sp<ITransactionCompletedListener> releaseBufferListener = nullptr;
+
+    // Keeps track of the release callback id associated with the listener. This
+    // is not sent to the server since the id can be reconstructed there. This
+    // is used to remove the old callback from the client process map if it is
+    // overwritten by another setBuffer call.
+    ReleaseCallbackId releaseCallbackId = ReleaseCallbackId::INVALID_ID;
+
+    // Stores which endpoint the release information should be sent to. We don't want to send the
+    // releaseCallbackId and release fence to all listeners so we store which listener the setBuffer
+    // was called with.
+    sp<IBinder> releaseBufferEndpoint;
+
+    Flags<BufferDataChange> flags;
+
+    client_cache_t cachedBuffer;
+
+    status_t write(Parcel& output) const;
+    status_t read(const Parcel& input);
+};
+
 /*
  * Used to communicate layer information between SurfaceFlinger and its clients.
  */
@@ -82,7 +120,7 @@
         eTransparentRegionChanged = 0x00000020,
         eFlagsChanged = 0x00000040,
         eLayerStackChanged = 0x00000080,
-        eReleaseBufferListenerChanged = 0x00000400,
+        /* unused 0x00000400, */
         eShadowRadiusChanged = 0x00000800,
         eLayerCreated = 0x00001000,
         eBufferCropChanged = 0x00002000,
@@ -94,7 +132,7 @@
         eTransformToDisplayInverseChanged = 0x00080000,
         eCropChanged = 0x00100000,
         eBufferChanged = 0x00200000,
-        eAcquireFenceChanged = 0x00400000,
+        /* unused 0x00400000, */
         eDataspaceChanged = 0x00800000,
         eHdrMetadataChanged = 0x01000000,
         eSurfaceDamageRegionChanged = 0x02000000,
@@ -105,7 +143,7 @@
         eInputInfoChanged = 0x40000000,
         eCornerRadiusChanged = 0x80000000,
         eDestinationFrameChanged = 0x1'00000000,
-        eCachedBufferChanged = 0x2'00000000,
+        /* unused = 0x2'00000000, */
         eBackgroundColorChanged = 0x4'00000000,
         eMetadataChanged = 0x8'00000000,
         eColorSpaceAgnosticChanged = 0x10'00000000,
@@ -114,7 +152,7 @@
         eBackgroundBlurRadiusChanged = 0x80'00000000,
         eProducerDisconnect = 0x100'00000000,
         eFixedTransformHintChanged = 0x200'00000000,
-        eFrameNumberChanged = 0x400'00000000,
+        /* unused 0x400'00000000, */
         eBlurRegionsChanged = 0x800'00000000,
         eAutoRefreshChanged = 0x1000'00000000,
         eStretchChanged = 0x2000'00000000,
@@ -169,8 +207,7 @@
     bool transformToDisplayInverse;
     Rect crop;
     Rect orientedDisplaySpaceRect;
-    sp<GraphicBuffer> buffer;
-    sp<Fence> acquireFence;
+    BufferData bufferData;
     ui::Dataspace dataspace;
     HdrMetadata hdrMetadata;
     Region surfaceDamageRegion;
@@ -181,8 +218,6 @@
 
     sp<gui::WindowInfoHandle> windowInfoHandle = new gui::WindowInfoHandle();
 
-    client_cache_t cachedBuffer;
-
     LayerMetadata metadata;
 
     // The following refer to the alpha, and dataspace, respectively of
@@ -216,10 +251,6 @@
     // otherwise the value will be a valid ui::Rotation.
     ui::Transform::RotationFlags fixedTransformHint;
 
-    // Used by BlastBufferQueue to forward the framenumber generated by the
-    // graphics producer.
-    uint64_t frameNumber;
-
     // Indicates that the consumer should acquire the next frame as soon as it
     // can and not wait for a frame to become available. This is only relevant
     // in shared buffer mode.
@@ -235,22 +266,6 @@
     Rect bufferCrop;
     Rect destinationFrame;
 
-    // Listens to when the buffer is safe to be released. This is used for blast
-    // layers only. The callback includes a release fence as well as the graphic
-    // buffer id to identify the buffer.
-    sp<ITransactionCompletedListener> releaseBufferListener;
-
-    // Keeps track of the release callback id associated with the listener. This
-    // is not sent to the server since the id can be reconstructed there. This
-    // is used to remove the old callback from the client process map if it is
-    // overwritten by another setBuffer call.
-    ReleaseCallbackId releaseCallbackId;
-
-    // Stores which endpoint the release information should be sent to. We don't want to send the
-    // releaseCallbackId and release fence to all listeners so we store which listener the setBuffer
-    // was called with.
-    sp<IBinder> releaseBufferEndpoint;
-
     // Force inputflinger to drop all input events for the layer and its children.
     gui::DropInputMode dropInputMode;
 };
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 403ca0a..82249a3 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -399,8 +399,7 @@
 
         void cacheBuffers();
         void registerSurfaceControlForCallback(const sp<SurfaceControl>& sc);
-        void setReleaseBufferCallback(layer_state_t*, const ReleaseCallbackId&,
-                                      ReleaseBufferCallback);
+        void setReleaseBufferCallback(BufferData*, const ReleaseCallbackId&, ReleaseBufferCallback);
         void removeReleaseBufferCallback(layer_state_t*);
 
     public:
@@ -473,10 +472,10 @@
         Transaction& setTransformToDisplayInverse(const sp<SurfaceControl>& sc,
                                                   bool transformToDisplayInverse);
         Transaction& setBuffer(const sp<SurfaceControl>& sc, const sp<GraphicBuffer>& buffer,
+                               const std::optional<sp<Fence>>& fence = std::nullopt,
+                               const std::optional<uint64_t>& frameNumber = std::nullopt,
                                const ReleaseCallbackId& id = ReleaseCallbackId::INVALID_ID,
                                ReleaseBufferCallback callback = nullptr);
-        Transaction& setCachedBuffer(const sp<SurfaceControl>& sc, int32_t bufferId);
-        Transaction& setAcquireFence(const sp<SurfaceControl>& sc, const sp<Fence>& fence);
         Transaction& setDataspace(const sp<SurfaceControl>& sc, ui::Dataspace dataspace);
         Transaction& setHdrMetadata(const sp<SurfaceControl>& sc, const HdrMetadata& hdrMetadata);
         Transaction& setSurfaceDamageRegion(const sp<SurfaceControl>& sc,
@@ -501,8 +500,6 @@
 
         // ONLY FOR BLAST ADAPTER
         Transaction& notifyProducerDisconnect(const sp<SurfaceControl>& sc);
-        // Set the framenumber generated by the graphics producer to mimic BufferQueue behaviour.
-        Transaction& setFrameNumber(const sp<SurfaceControl>& sc, uint64_t frameNumber);
 
         Transaction& setInputWindowInfo(const sp<SurfaceControl>& sc, const gui::WindowInfo& info);
         Transaction& setFocusedWindow(const gui::FocusRequest& request);
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index d805294..ef05fe2 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -620,14 +620,6 @@
     return sourceCrop.getHeight() != frameHeight || sourceCrop.getWidth() != frameWidth;
 }
 
-uint64_t BufferLayer::getHeadFrameNumber(nsecs_t expectedPresentTime) const {
-    if (hasFrameUpdate()) {
-        return getFrameNumber(expectedPresentTime);
-    } else {
-        return mCurrentFrameNumber;
-    }
-}
-
 Rect BufferLayer::getBufferSize(const State& s) const {
     // If we have a sideband stream, or we are scaling the buffer then return the layer size since
     // we cannot determine the buffer size.
diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h
index 760c8b9..2da73f8 100644
--- a/services/surfaceflinger/BufferLayer.h
+++ b/services/surfaceflinger/BufferLayer.h
@@ -164,8 +164,6 @@
     void updateCloneBufferInfo() override;
     uint64_t mPreviousFrameNumber = 0;
 
-    uint64_t getHeadFrameNumber(nsecs_t expectedPresentTime) const override;
-
     void setTransformHint(ui::Transform::RotationFlags displayTransformHint) override;
 
     // Transform hint provided to the producer. This must be accessed holding
@@ -189,8 +187,6 @@
 private:
     virtual bool fenceHasSignaled() const = 0;
     virtual bool framePresentTimeIsCurrent(nsecs_t expectedPresentTime) const = 0;
-    virtual uint64_t getFrameNumber(nsecs_t expectedPresentTime) const = 0;
-
 
     // Latch sideband stream and returns true if the dirty region should be updated.
     virtual bool latchSidebandStream(bool& recomputeVisibleRegions) = 0;
diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp
index d51db88..8bbe438 100644
--- a/services/surfaceflinger/BufferQueueLayer.cpp
+++ b/services/surfaceflinger/BufferQueueLayer.cpp
@@ -161,39 +161,6 @@
     return mQueueItems[0].item.mTimestamp <= expectedPresentTime;
 }
 
-uint64_t BufferQueueLayer::getFrameNumber(nsecs_t expectedPresentTime) const {
-    Mutex::Autolock lock(mQueueItemLock);
-    uint64_t frameNumber = mQueueItems[0].item.mFrameNumber;
-
-    // The head of the queue will be dropped if there are signaled and timely frames behind it
-    if (isRemovedFromCurrentState()) {
-        expectedPresentTime = 0;
-    }
-
-    for (size_t i = 1; i < mQueueItems.size(); i++) {
-        const bool fenceSignaled =
-                mQueueItems[i].item.mFenceTime->getSignalTime() != Fence::SIGNAL_TIME_PENDING;
-        if (!fenceSignaled) {
-            break;
-        }
-
-        // We don't drop frames without explicit timestamps
-        if (mQueueItems[i].item.mIsAutoTimestamp) {
-            break;
-        }
-
-        const nsecs_t desiredPresent = mQueueItems[i].item.mTimestamp;
-        if (desiredPresent < expectedPresentTime - BufferQueueConsumer::MAX_REASONABLE_NSEC ||
-            desiredPresent > expectedPresentTime) {
-            break;
-        }
-
-        frameNumber = mQueueItems[i].item.mFrameNumber;
-    }
-
-    return frameNumber;
-}
-
 bool BufferQueueLayer::latchSidebandStream(bool& recomputeVisibleRegions) {
     // We need to update the sideband stream if the layer has both a buffer and a sideband stream.
     editCompositionState()->sidebandStreamHasFrame = hasFrameUpdate() && mSidebandStream.get();
diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h
index b3b7948..be2902b 100644
--- a/services/surfaceflinger/BufferQueueLayer.h
+++ b/services/surfaceflinger/BufferQueueLayer.h
@@ -89,7 +89,6 @@
     };
 
 private:
-    uint64_t getFrameNumber(nsecs_t expectedPresentTime) const override;
 
     bool latchSidebandStream(bool& recomputeVisibleRegions) override;
     void setTransformHint(ui::Transform::RotationFlags displayTransformHint) override;
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index 7466c06..82e5d46 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -406,15 +406,55 @@
     return true;
 }
 
-bool BufferStateLayer::setBuffer(const std::shared_ptr<renderengine::ExternalTexture>& buffer,
-                                 const sp<Fence>& acquireFence, nsecs_t postTime,
+std::shared_ptr<renderengine::ExternalTexture> BufferStateLayer::getBufferFromBufferData(
+        const BufferData& bufferData) {
+    bool cacheIdChanged = bufferData.flags.test(BufferData::BufferDataChange::cachedBufferChanged);
+    bool bufferSizeExceedsLimit = false;
+    std::shared_ptr<renderengine::ExternalTexture> buffer = nullptr;
+    if (cacheIdChanged && bufferData.buffer != nullptr) {
+        bufferSizeExceedsLimit =
+                mFlinger->exceedsMaxRenderTargetSize(bufferData.buffer->getWidth(),
+                                                     bufferData.buffer->getHeight());
+        if (!bufferSizeExceedsLimit) {
+            ClientCache::getInstance().add(bufferData.cachedBuffer, bufferData.buffer);
+            buffer = ClientCache::getInstance().get(bufferData.cachedBuffer);
+        }
+    } else if (cacheIdChanged) {
+        buffer = ClientCache::getInstance().get(bufferData.cachedBuffer);
+    } else if (bufferData.buffer != nullptr) {
+        bufferSizeExceedsLimit =
+                mFlinger->exceedsMaxRenderTargetSize(bufferData.buffer->getWidth(),
+                                                     bufferData.buffer->getHeight());
+        if (!bufferSizeExceedsLimit) {
+            buffer = std::make_shared<
+                    renderengine::ExternalTexture>(bufferData.buffer, mFlinger->getRenderEngine(),
+                                                   renderengine::ExternalTexture::Usage::READABLE);
+        }
+    }
+    ALOGE_IF(bufferSizeExceedsLimit,
+             "Attempted to create an ExternalTexture for layer %s that exceeds render target size "
+             "limit.",
+             getDebugName());
+    return buffer;
+}
+
+bool BufferStateLayer::setBuffer(const BufferData& bufferData, nsecs_t postTime,
                                  nsecs_t desiredPresentTime, bool isAutoTimestamp,
-                                 const client_cache_t& clientCacheId, uint64_t frameNumber,
-                                 std::optional<nsecs_t> dequeueTime, const FrameTimelineInfo& info,
-                                 const sp<ITransactionCompletedListener>& releaseBufferListener,
-                                 const sp<IBinder>& releaseBufferEndpoint) {
+                                 std::optional<nsecs_t> dequeueTime,
+                                 const FrameTimelineInfo& info) {
     ATRACE_CALL();
 
+    const std::shared_ptr<renderengine::ExternalTexture>& buffer =
+            getBufferFromBufferData(bufferData);
+    if (!buffer) {
+        return false;
+    }
+
+    const bool frameNumberChanged =
+            bufferData.flags.test(BufferData::BufferDataChange::frameNumberChanged);
+    const uint64_t frameNumber =
+            frameNumberChanged ? bufferData.frameNumber : mDrawingState.frameNumber + 1;
+
     if (mDrawingState.buffer) {
         mReleasePreviousBuffer = true;
         if (mDrawingState.buffer != mBufferInfo.mBuffer ||
@@ -438,9 +478,17 @@
     }
 
     mDrawingState.frameNumber = frameNumber;
-    mDrawingState.releaseBufferListener = releaseBufferListener;
+    mDrawingState.releaseBufferListener = bufferData.releaseBufferListener;
     mDrawingState.buffer = buffer;
-    mDrawingState.clientCacheId = clientCacheId;
+    mDrawingState.clientCacheId = bufferData.cachedBuffer;
+
+    mDrawingState.acquireFence = bufferData.flags.test(BufferData::BufferDataChange::fenceChanged)
+            ? bufferData.acquireFence
+            : Fence::NO_FENCE;
+    mDrawingState.acquireFenceTime = std::make_unique<FenceTime>(mDrawingState.acquireFence);
+    // The acquire fences of BufferStateLayers have already signaled before they are set
+    mCallbackHandleAcquireTime = mDrawingState.acquireFenceTime->getSignalTime();
+
     mDrawingState.modified = true;
     setTransactionFlags(eTransactionNeeded);
 
@@ -462,7 +510,7 @@
     mFlinger->mScheduler->recordLayerHistory(this, presentTime,
                                              LayerHistory::LayerUpdateType::Buffer);
 
-    addFrameEvent(acquireFence, postTime, isAutoTimestamp ? 0 : desiredPresentTime);
+    addFrameEvent(mDrawingState.acquireFence, postTime, isAutoTimestamp ? 0 : desiredPresentTime);
 
     setFrameTimelineVsyncForBufferTransaction(info, postTime);
 
@@ -477,20 +525,7 @@
 
     mDrawingState.width = mDrawingState.buffer->getBuffer()->getWidth();
     mDrawingState.height = mDrawingState.buffer->getBuffer()->getHeight();
-    mDrawingState.releaseBufferEndpoint = releaseBufferEndpoint;
-
-    return true;
-}
-
-bool BufferStateLayer::setAcquireFence(const sp<Fence>& fence) {
-    mDrawingState.acquireFence = fence;
-    mDrawingState.acquireFenceTime = std::make_unique<FenceTime>(fence);
-
-    // The acquire fences of BufferStateLayers have already signaled before they are set
-    mCallbackHandleAcquireTime = mDrawingState.acquireFenceTime->getSignalTime();
-
-    mDrawingState.modified = true;
-    setTransactionFlags(eTransactionNeeded);
+    mDrawingState.releaseBufferEndpoint = bufferData.releaseBufferEndpoint;
     return true;
 }
 
@@ -659,36 +694,6 @@
     return BufferLayer::onPreComposition(refreshStartTime);
 }
 
-uint64_t BufferStateLayer::getFrameNumber(nsecs_t /*expectedPresentTime*/) const {
-    return mDrawingState.frameNumber;
-}
-
-/**
- * This is the frameNumber used for deferred transaction signalling. We need to use this because
- * of cases where we defer a transaction for a surface to itself. In the BLAST world this
- * may not make a huge amount of sense (Why not just merge the Buffer transaction with the
- * deferred transaction?) but this is an important legacy use case, for example moving
- * a window at the same time it draws makes use of this kind of technique. So anyway
- * imagine we have something like this:
- *
- * Transaction { // containing
- *     Buffer -> frameNumber = 2
- *     DeferTransactionUntil -> frameNumber = 2
- *     Random other stuff
- *  }
- * Now imagine mFrameNumber returned mDrawingState.frameNumber (or mCurrentFrameNumber).
- * Prior to doTransaction SurfaceFlinger will call notifyAvailableFrames, but because we
- * haven't swapped mDrawingState to mDrawingState yet we will think the sync point
- * is not ready. So we will return false from applyPendingState and not swap
- * current state to drawing state. But because we don't swap current state
- * to drawing state the number will never update and we will be stuck. This way
- * we can see we need to return the frame number for the buffer we are about
- * to apply.
- */
-uint64_t BufferStateLayer::getHeadFrameNumber(nsecs_t /* expectedPresentTime */) const {
-    return mDrawingState.frameNumber;
-}
-
 void BufferStateLayer::setAutoRefresh(bool autoRefresh) {
     if (!mAutoRefresh.exchange(autoRefresh)) {
         mFlinger->signalLayerUpdate();
diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h
index 124e91a..87b68ea 100644
--- a/services/surfaceflinger/BufferStateLayer.h
+++ b/services/surfaceflinger/BufferStateLayer.h
@@ -55,13 +55,9 @@
     bool setTransform(uint32_t transform) override;
     bool setTransformToDisplayInverse(bool transformToDisplayInverse) override;
     bool setCrop(const Rect& crop) override;
-    bool setBuffer(const std::shared_ptr<renderengine::ExternalTexture>& buffer,
-                   const sp<Fence>& acquireFence, nsecs_t postTime, nsecs_t desiredPresentTime,
-                   bool isAutoTimestamp, const client_cache_t& clientCacheId, uint64_t frameNumber,
-                   std::optional<nsecs_t> dequeueTime, const FrameTimelineInfo& info,
-                   const sp<ITransactionCompletedListener>& transactionListener,
-                   const sp<IBinder>& releaseBufferEndpoint) override;
-    bool setAcquireFence(const sp<Fence>& fence) override;
+    bool setBuffer(const BufferData& bufferData, nsecs_t postTime, nsecs_t desiredPresentTime,
+                   bool isAutoTimestamp, std::optional<nsecs_t> dequeueTime,
+                   const FrameTimelineInfo& info) override;
     bool setDataspace(ui::Dataspace dataspace) override;
     bool setHdrMetadata(const HdrMetadata& hdrMetadata) override;
     bool setSurfaceDamageRegion(const Region& surfaceDamage) override;
@@ -105,7 +101,6 @@
 
 protected:
     void gatherBufferInfo() override;
-    uint64_t getHeadFrameNumber(nsecs_t expectedPresentTime) const;
     void onSurfaceFrameCreated(const std::shared_ptr<frametimeline::SurfaceFrame>& surfaceFrame);
     ui::Transform getInputTransform() const override;
     Rect getInputBounds() const override;
@@ -122,8 +117,6 @@
 
     status_t addReleaseFence(const sp<CallbackHandle>& ch, const sp<Fence>& releaseFence);
 
-    uint64_t getFrameNumber(nsecs_t expectedPresentTime) const override;
-
     bool latchSidebandStream(bool& recomputeVisibleRegions) override;
 
     bool hasFrameUpdate() const override;
@@ -143,6 +136,9 @@
 
     bool bufferNeedsFiltering() const override;
 
+    std::shared_ptr<renderengine::ExternalTexture> getBufferFromBufferData(
+            const BufferData& bufferData);
+
     sp<Fence> mPreviousReleaseFence;
     ReleaseCallbackId mPreviousReleaseCallbackId = ReleaseCallbackId::INVALID_ID;
     uint64_t mPreviousReleasedFrameNumber = 0;
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 8c281d5..f29ebde 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -416,17 +416,11 @@
     // Used only to set BufferStateLayer state
     virtual bool setTransform(uint32_t /*transform*/) { return false; };
     virtual bool setTransformToDisplayInverse(bool /*transformToDisplayInverse*/) { return false; };
-    virtual bool setBuffer(const std::shared_ptr<renderengine::ExternalTexture>& /*buffer*/,
-                           const sp<Fence>& /*acquireFence*/, nsecs_t /*postTime*/,
-                           nsecs_t /*desiredPresentTime*/, bool /*isAutoTimestamp*/,
-                           const client_cache_t& /*clientCacheId*/, uint64_t /* frameNumber */,
-                           std::optional<nsecs_t> /* dequeueTime */,
-                           const FrameTimelineInfo& /*info*/,
-                           const sp<ITransactionCompletedListener>& /* releaseBufferListener */,
-                           const sp<IBinder>& /* releaseBufferEndpoint */) {
+    virtual bool setBuffer(const BufferData&, nsecs_t /*postTime*/, nsecs_t /*desiredPresentTime*/,
+                           bool /*isAutoTimestamp*/, std::optional<nsecs_t> /* dequeueTime */,
+                           const FrameTimelineInfo& /*info*/) {
         return false;
     };
-    virtual bool setAcquireFence(const sp<Fence>& /*fence*/) { return false; };
     virtual bool setDataspace(ui::Dataspace /*dataspace*/) { return false; };
     virtual bool setHdrMetadata(const HdrMetadata& /*hdrMetadata*/) { return false; };
     virtual bool setSurfaceDamageRegion(const Region& /*surfaceDamage*/) { return false; };
@@ -527,8 +521,6 @@
 
     virtual bool shouldPresentNow(nsecs_t /*expectedPresentTime*/) const { return false; }
 
-    virtual uint64_t getHeadFrameNumber(nsecs_t /* expectedPresentTime */) const { return 0; }
-
     /*
      * called after composition.
      * returns true if the layer latched a new buffer this frame.
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 88715e3..da3d22e 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -3570,9 +3570,10 @@
 
     for (const ComposerState& state : states) {
         const layer_state_t& s = state.state;
-        const bool acquireFenceChanged = (s.what & layer_state_t::eAcquireFenceChanged);
-        if (acquireFenceChanged && s.acquireFence && !enableLatchUnsignaled &&
-            s.acquireFence->getStatus() == Fence::Status::Unsignaled) {
+        const bool acquireFenceChanged =
+                s.bufferData.flags.test(BufferData::BufferDataChange::fenceChanged);
+        if (acquireFenceChanged && s.bufferData.acquireFence && !enableLatchUnsignaled &&
+            s.bufferData.acquireFence->getStatus() == Fence::Status::Unsignaled) {
             ATRACE_NAME("fence unsignaled");
             return false;
         }
@@ -4069,9 +4070,6 @@
     if (what & layer_state_t::eCropChanged) {
         if (layer->setCrop(s.crop)) flags |= eTraversalNeeded;
     }
-    if (what & layer_state_t::eAcquireFenceChanged) {
-        if (layer->setAcquireFence(s.acquireFence)) flags |= eTraversalNeeded;
-    }
     if (what & layer_state_t::eDataspaceChanged) {
         if (layer->setDataspace(s.dataspace)) flags |= eTraversalNeeded;
     }
@@ -4198,43 +4196,11 @@
             callbackHandles.emplace_back(new CallbackHandle(listener, callbackIds, s.surface));
         }
     }
-    bool bufferChanged = what & layer_state_t::eBufferChanged;
-    bool cacheIdChanged = what & layer_state_t::eCachedBufferChanged;
-    bool bufferSizeExceedsLimit = false;
-    std::shared_ptr<renderengine::ExternalTexture> buffer;
-    if (bufferChanged && cacheIdChanged && s.buffer != nullptr) {
-        bufferSizeExceedsLimit =
-                exceedsMaxRenderTargetSize(s.buffer->getWidth(), s.buffer->getHeight());
-        if (!bufferSizeExceedsLimit) {
-            ClientCache::getInstance().add(s.cachedBuffer, s.buffer);
-            buffer = ClientCache::getInstance().get(s.cachedBuffer);
-        }
-    } else if (cacheIdChanged) {
-        buffer = ClientCache::getInstance().get(s.cachedBuffer);
-    } else if (bufferChanged && s.buffer != nullptr) {
-        bufferSizeExceedsLimit =
-                exceedsMaxRenderTargetSize(s.buffer->getWidth(), s.buffer->getHeight());
-        if (!bufferSizeExceedsLimit) {
-            buffer = std::make_shared<
-                    renderengine::ExternalTexture>(s.buffer, getRenderEngine(),
-                                                   renderengine::ExternalTexture::Usage::READABLE);
-        }
-    }
-    ALOGE_IF(bufferSizeExceedsLimit,
-             "Attempted to create an ExternalTexture for layer %s that exceeds render target size "
-             "limit.",
-             layer->getDebugName());
-    if (buffer) {
-        const bool frameNumberChanged = what & layer_state_t::eFrameNumberChanged;
-        const uint64_t frameNumber = frameNumberChanged
-                ? s.frameNumber
-                : layer->getHeadFrameNumber(-1 /* expectedPresentTime */) + 1;
 
-        if (layer->setBuffer(buffer, s.acquireFence, postTime, desiredPresentTime, isAutoTimestamp,
-                             s.cachedBuffer, frameNumber, dequeueBufferTimestamp, frameTimelineInfo,
-                             s.releaseBufferListener, s.releaseBufferEndpoint)) {
-            flags |= eTraversalNeeded;
-        }
+    if (what & layer_state_t::eBufferChanged &&
+        layer->setBuffer(s.bufferData, postTime, desiredPresentTime, isAutoTimestamp,
+                         dequeueBufferTimestamp, frameTimelineInfo)) {
+        flags |= eTraversalNeeded;
     } else if (frameTimelineInfo.vsyncId != FrameTimelineInfo::INVALID_VSYNC_ID) {
         layer->setFrameTimelineVsyncForBufferlessTransaction(frameTimelineInfo, postTime);
     }
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 141d7ac..5ef3fff 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -363,6 +363,10 @@
         return static_cast<bool>(findDisplay(p));
     }
 
+    bool exceedsMaxRenderTargetSize(uint32_t width, uint32_t height) const {
+        return width > mMaxRenderTargetSize || height > mMaxRenderTargetSize;
+    }
+
 private:
     friend class BufferLayer;
     friend class BufferQueueLayer;
@@ -939,10 +943,6 @@
 
     void readPersistentProperties();
 
-    bool exceedsMaxRenderTargetSize(uint32_t width, uint32_t height) const {
-        return width > mMaxRenderTargetSize || height > mMaxRenderTargetSize;
-    }
-
     uint32_t getMaxAcquiredBufferCountForCurrentRefreshRate(uid_t uid) const;
 
     /*
diff --git a/services/surfaceflinger/tests/IPC_test.cpp b/services/surfaceflinger/tests/IPC_test.cpp
index 8d7e175..94e1e0c 100644
--- a/services/surfaceflinger/tests/IPC_test.cpp
+++ b/services/surfaceflinger/tests/IPC_test.cpp
@@ -161,8 +161,7 @@
                                                  Color::RED);
         transaction->setLayerStack(mSurfaceControl, ui::DEFAULT_LAYER_STACK)
                 .setLayer(mSurfaceControl, std::numeric_limits<int32_t>::max())
-                .setBuffer(mSurfaceControl, gb)
-                .setAcquireFence(mSurfaceControl, fence)
+                .setBuffer(mSurfaceControl, gb, fence)
                 .show(mSurfaceControl)
                 .addTransactionCompletedCallback(mCallbackHelper.function,
                                                  mCallbackHelper.getContext());
@@ -312,8 +311,7 @@
     Transaction transaction;
     transaction.setLayerStack(sc, ui::DEFAULT_LAYER_STACK)
             .setLayer(sc, std::numeric_limits<int32_t>::max() - 1)
-            .setBuffer(sc, gb)
-            .setAcquireFence(sc, fence)
+            .setBuffer(sc, gb, fence)
             .show(sc)
             .addTransactionCompletedCallback(helper1.function, helper1.getContext());
 
diff --git a/services/surfaceflinger/tests/LayerCallback_test.cpp b/services/surfaceflinger/tests/LayerCallback_test.cpp
index 965aac3..e8759e5 100644
--- a/services/surfaceflinger/tests/LayerCallback_test.cpp
+++ b/services/surfaceflinger/tests/LayerCallback_test.cpp
@@ -66,8 +66,7 @@
                     return err;
                 }
 
-                transaction.setBuffer(layer, buffer);
-                transaction.setAcquireFence(layer, fence);
+                transaction.setBuffer(layer, buffer, fence);
             }
 
             if (setBackgroundColor) {
diff --git a/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp b/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp
index c8eeac6..0e2bc3d 100644
--- a/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp
+++ b/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp
@@ -1353,7 +1353,7 @@
         return;
     }
 
-    Transaction().setBuffer(layer, buffer).setAcquireFence(layer, fence).apply();
+    Transaction().setBuffer(layer, buffer, fence).apply();
 
     status_t status = fence->wait(1000);
     ASSERT_NE(static_cast<status_t>(Fence::Status::Unsignaled), status);
@@ -1375,7 +1375,7 @@
 
     sp<Fence> fence = Fence::NO_FENCE;
 
-    Transaction().setBuffer(layer, buffer).setAcquireFence(layer, fence).apply();
+    Transaction().setBuffer(layer, buffer, fence).apply();
 
     auto shot = getScreenCapture();
     shot->expectColor(Rect(0, 0, 32, 32), Color::RED);
diff --git a/services/surfaceflinger/tests/ReleaseBufferCallback_test.cpp b/services/surfaceflinger/tests/ReleaseBufferCallback_test.cpp
index c4d42fa..3847a51 100644
--- a/services/surfaceflinger/tests/ReleaseBufferCallback_test.cpp
+++ b/services/surfaceflinger/tests/ReleaseBufferCallback_test.cpp
@@ -85,9 +85,7 @@
                              sp<Fence> fence, CallbackHelper& callback, const ReleaseCallbackId& id,
                              ReleaseBufferCallbackHelper& releaseCallback) {
         Transaction t;
-        t.setFrameNumber(layer, id.framenumber);
-        t.setBuffer(layer, buffer, id, releaseCallback.getCallback());
-        t.setAcquireFence(layer, fence);
+        t.setBuffer(layer, buffer, fence, id.framenumber, id, releaseCallback.getCallback());
         t.addTransactionCompletedCallback(callback.function, callback.getContext());
         t.apply();
     }
@@ -302,8 +300,8 @@
     nsecs_t time = systemTime() + std::chrono::nanoseconds(100ms).count();
 
     Transaction t;
-    t.setBuffer(layer, firstBuffer, firstBufferCallbackId, releaseCallback->getCallback());
-    t.setAcquireFence(layer, Fence::NO_FENCE);
+    t.setBuffer(layer, firstBuffer, std::nullopt, std::nullopt, firstBufferCallbackId,
+                releaseCallback->getCallback());
     t.addTransactionCompletedCallback(transactionCallback.function,
                                       transactionCallback.getContext());
     t.setDesiredPresentTime(time);
@@ -318,8 +316,8 @@
     // Dropping frames in transaction queue emits a callback
     sp<GraphicBuffer> secondBuffer = getBuffer();
     ReleaseCallbackId secondBufferCallbackId(secondBuffer->getId(), generateFrameNumber());
-    t.setBuffer(layer, secondBuffer, secondBufferCallbackId, releaseCallback->getCallback());
-    t.setAcquireFence(layer, Fence::NO_FENCE);
+    t.setBuffer(layer, secondBuffer, std::nullopt, std::nullopt, secondBufferCallbackId,
+                releaseCallback->getCallback());
     t.addTransactionCompletedCallback(transactionCallback.function,
                                       transactionCallback.getContext());
     t.setDesiredPresentTime(time);
@@ -361,10 +359,8 @@
     ReleaseCallbackId secondBufferCallbackId(secondBuffer->getId(), generateFrameNumber());
 
     Transaction transaction1;
-    transaction1.setFrameNumber(layer, secondBufferCallbackId.framenumber);
-    transaction1.setBuffer(layer, secondBuffer, secondBufferCallbackId,
-                           releaseCallback->getCallback());
-    transaction1.setAcquireFence(layer, Fence::NO_FENCE);
+    transaction1.setBuffer(layer, secondBuffer, std::nullopt, secondBufferCallbackId.framenumber,
+                           secondBufferCallbackId, releaseCallback->getCallback());
     transaction1.addTransactionCompletedCallback(callback1.function, callback1.getContext());
 
     // Set a different TransactionCompletedListener to mimic a second process
diff --git a/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp b/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp
index a749ece..bd6a780 100644
--- a/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp
@@ -46,6 +46,7 @@
         ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name());
         setupScheduler();
         mFlinger.setupComposer(std::make_unique<Hwc2::mock::Composer>());
+        mFlinger.setupRenderEngine(std::unique_ptr<renderengine::RenderEngine>(mRenderEngine));
     }
 
     ~TransactionFrameTracerTest() {
@@ -92,21 +93,17 @@
     }
 
     TestableSurfaceFlinger mFlinger;
-    renderengine::mock::RenderEngine mRenderEngine;
+    renderengine::mock::RenderEngine* mRenderEngine = new renderengine::mock::RenderEngine();
 
     FenceToFenceTimeMap fenceFactory;
-    client_cache_t mClientCache;
 
     void BLASTTransactionSendsFrameTracerEvents() {
         sp<BufferStateLayer> layer = createBufferStateLayer();
 
         sp<Fence> fence(new Fence());
-        const auto buffer = std::make_shared<
-                renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888,
-                                                                 1, 0),
-                                               mRenderEngine, false);
+        const auto buffer = new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0);
         int32_t layerId = layer->getSequence();
-        uint64_t bufferId = buffer->getBuffer()->getId();
+        uint64_t bufferId = buffer->getId();
         uint64_t frameNumber = 5;
         nsecs_t dequeueTime = 10;
         nsecs_t postTime = 20;
@@ -117,9 +114,14 @@
         EXPECT_CALL(*mFlinger.getFrameTracer(),
                     traceTimestamp(layerId, bufferId, frameNumber, postTime,
                                    FrameTracer::FrameEvent::QUEUE, /*duration*/ 0));
-        layer->setBuffer(buffer, fence, postTime, /*desiredPresentTime*/ 30, false, mClientCache,
-                         frameNumber, dequeueTime, FrameTimelineInfo{},
-                         nullptr /* releaseBufferCallback */, nullptr /* releaseBufferEndpoint*/);
+        BufferData bufferData;
+        bufferData.buffer = buffer;
+        bufferData.acquireFence = fence;
+        bufferData.frameNumber = frameNumber;
+        bufferData.flags |= BufferData::BufferDataChange::fenceChanged;
+        bufferData.flags |= BufferData::BufferDataChange::frameNumberChanged;
+        layer->setBuffer(bufferData, postTime, /*desiredPresentTime*/ 30, false, dequeueTime,
+                         FrameTimelineInfo{});
 
         commitTransaction(layer.get());
         bool computeVisisbleRegions;
diff --git a/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp b/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp
index 2a7921f..2b5b7b5 100644
--- a/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp
@@ -46,6 +46,7 @@
         ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name());
         setupScheduler();
         mFlinger.setupComposer(std::make_unique<Hwc2::mock::Composer>());
+        mFlinger.setupRenderEngine(std::unique_ptr<renderengine::RenderEngine>(mRenderEngine));
     }
 
     ~TransactionSurfaceFrameTest() {
@@ -92,10 +93,9 @@
     }
 
     TestableSurfaceFlinger mFlinger;
-    renderengine::mock::RenderEngine mRenderEngine;
+    renderengine::mock::RenderEngine* mRenderEngine = new renderengine::mock::RenderEngine();
 
     FenceToFenceTimeMap fenceFactory;
-    client_cache_t mClientCache;
 
     void PresentedSurfaceFrameForBufferlessTransaction() {
         sp<BufferStateLayer> layer = createBufferStateLayer();
@@ -114,13 +114,15 @@
         sp<BufferStateLayer> layer = createBufferStateLayer();
         sp<Fence> fence(new Fence());
         auto acquireFence = fenceFactory.createFenceTimeForTest(fence);
-        const auto buffer = std::make_shared<
-                renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888,
-                                                                 1, 0),
-                                               mRenderEngine, false);
-        layer->setBuffer(buffer, fence, 10, 20, false, mClientCache, 1, std::nullopt,
-                         {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */,
-                         nullptr /* releaseBufferEndpoint */);
+        const auto buffer = new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0);
+        BufferData bufferData;
+        bufferData.buffer = buffer;
+        bufferData.acquireFence = fence;
+        bufferData.frameNumber = 1;
+        bufferData.flags |= BufferData::BufferDataChange::fenceChanged;
+        bufferData.flags |= BufferData::BufferDataChange::frameNumberChanged;
+        layer->setBuffer(bufferData, 10, 20, false, std::nullopt,
+                         {/*vsyncId*/ 1, /*inputEventId*/ 0});
         acquireFence->signalForTest(12);
 
         commitTransaction(layer.get());
@@ -143,27 +145,30 @@
 
         sp<Fence> fence1(new Fence());
         auto acquireFence1 = fenceFactory.createFenceTimeForTest(fence1);
-        const auto buffer1 = std::make_shared<
-                renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888,
-                                                                 1, 0),
-                                               mRenderEngine, false);
-        layer->setBuffer(buffer1, fence1, 10, 20, false, mClientCache, 1, std::nullopt,
-                         {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */,
-                         nullptr /* releaseBufferEndpoint */);
+        const auto buffer1 = new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0);
+        BufferData bufferData;
+        bufferData.buffer = buffer1;
+        bufferData.acquireFence = fence1;
+        bufferData.frameNumber = 1;
+        bufferData.flags |= BufferData::BufferDataChange::fenceChanged;
+        bufferData.flags |= BufferData::BufferDataChange::frameNumberChanged;
+        layer->setBuffer(bufferData, 10, 20, false, std::nullopt,
+                         {/*vsyncId*/ 1, /*inputEventId*/ 0});
         EXPECT_EQ(0u, layer->mDrawingState.bufferlessSurfaceFramesTX.size());
         ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX);
         const auto droppedSurfaceFrame = layer->mDrawingState.bufferSurfaceFrameTX;
 
         sp<Fence> fence2(new Fence());
         auto acquireFence2 = fenceFactory.createFenceTimeForTest(fence2);
-        const auto buffer2 = std::make_shared<
-                renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888,
-                                                                 1, 0),
-                                               mRenderEngine, false);
+        const auto buffer2 = new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0);
         nsecs_t start = systemTime();
-        layer->setBuffer(buffer2, fence2, 10, 20, false, mClientCache, 1, std::nullopt,
-                         {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */,
-                         nullptr /* releaseBufferEndpoint */);
+        bufferData.buffer = buffer2;
+        bufferData.acquireFence = fence2;
+        bufferData.frameNumber = 1;
+        bufferData.flags |= BufferData::BufferDataChange::fenceChanged;
+        bufferData.flags |= BufferData::BufferDataChange::frameNumberChanged;
+        layer->setBuffer(bufferData, 10, 20, false, std::nullopt,
+                         {/*vsyncId*/ 1, /*inputEventId*/ 0});
         nsecs_t end = systemTime();
         acquireFence2->signalForTest(12);
 
@@ -198,13 +203,15 @@
 
         sp<Fence> fence(new Fence());
         auto acquireFence = fenceFactory.createFenceTimeForTest(fence);
-        const auto buffer = std::make_shared<
-                renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888,
-                                                                 1, 0),
-                                               mRenderEngine, false);
-        layer->setBuffer(buffer, fence, 10, 20, false, mClientCache, 1, std::nullopt,
-                         {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */,
-                         nullptr /* releaseBufferEndpoint */);
+        const auto buffer = new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0);
+        BufferData bufferData;
+        bufferData.buffer = buffer;
+        bufferData.acquireFence = fence;
+        bufferData.frameNumber = 1;
+        bufferData.flags |= BufferData::BufferDataChange::fenceChanged;
+        bufferData.flags |= BufferData::BufferDataChange::frameNumberChanged;
+        layer->setBuffer(bufferData, 10, 20, false, std::nullopt,
+                         {/*vsyncId*/ 1, /*inputEventId*/ 0});
         acquireFence->signalForTest(12);
 
         EXPECT_EQ(0u, layer->mDrawingState.bufferlessSurfaceFramesTX.size());
@@ -227,13 +234,15 @@
         sp<BufferStateLayer> layer = createBufferStateLayer();
         sp<Fence> fence(new Fence());
         auto acquireFence = fenceFactory.createFenceTimeForTest(fence);
-        const auto buffer = std::make_shared<
-                renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888,
-                                                                 1, 0),
-                                               mRenderEngine, false);
-        layer->setBuffer(buffer, fence, 10, 20, false, mClientCache, 1, std::nullopt,
-                         {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */,
-                         nullptr /* releaseBufferEndpoint */);
+        const auto buffer = new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0);
+        BufferData bufferData;
+        bufferData.buffer = buffer;
+        bufferData.acquireFence = fence;
+        bufferData.frameNumber = 1;
+        bufferData.flags |= BufferData::BufferDataChange::fenceChanged;
+        bufferData.flags |= BufferData::BufferDataChange::frameNumberChanged;
+        layer->setBuffer(bufferData, 10, 20, false, std::nullopt,
+                         {/*vsyncId*/ 1, /*inputEventId*/ 0});
         EXPECT_EQ(0u, layer->mDrawingState.bufferlessSurfaceFramesTX.size());
         ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX);
 
@@ -260,13 +269,15 @@
 
         sp<Fence> fence(new Fence());
         auto acquireFence = fenceFactory.createFenceTimeForTest(fence);
-        const auto buffer = std::make_shared<
-                renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888,
-                                                                 1, 0),
-                                               mRenderEngine, false);
-        layer->setBuffer(buffer, fence, 10, 20, false, mClientCache, 1, std::nullopt,
-                         {/*vsyncId*/ 3, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */,
-                         nullptr /* releaseBufferEndpoint */);
+        const auto buffer = new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0);
+        BufferData bufferData;
+        bufferData.buffer = buffer;
+        bufferData.acquireFence = fence;
+        bufferData.frameNumber = 1;
+        bufferData.flags |= BufferData::BufferDataChange::fenceChanged;
+        bufferData.flags |= BufferData::BufferDataChange::frameNumberChanged;
+        layer->setBuffer(bufferData, 10, 20, false, std::nullopt,
+                         {/*vsyncId*/ 3, /*inputEventId*/ 0});
         EXPECT_EQ(2u, layer->mDrawingState.bufferlessSurfaceFramesTX.size());
         ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX);
         const auto bufferSurfaceFrameTX = layer->mDrawingState.bufferSurfaceFrameTX;
@@ -299,25 +310,28 @@
 
         sp<Fence> fence1(new Fence());
         auto acquireFence1 = fenceFactory.createFenceTimeForTest(fence1);
-        const auto buffer1 = std::make_shared<
-                renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888,
-                                                                 1, 0),
-                                               mRenderEngine, false);
-        layer->setBuffer(buffer1, fence1, 10, 20, false, mClientCache, 1, std::nullopt,
-                         {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */,
-                         nullptr /* releaseBufferEndpoint */);
+        const auto buffer1 = new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0);
+        BufferData bufferData;
+        bufferData.buffer = buffer1;
+        bufferData.acquireFence = fence1;
+        bufferData.frameNumber = 1;
+        bufferData.flags |= BufferData::BufferDataChange::fenceChanged;
+        bufferData.flags |= BufferData::BufferDataChange::frameNumberChanged;
+        layer->setBuffer(bufferData, 10, 20, false, std::nullopt,
+                         {/*vsyncId*/ 1, /*inputEventId*/ 0});
         ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX);
         const auto droppedSurfaceFrame = layer->mDrawingState.bufferSurfaceFrameTX;
 
         sp<Fence> fence2(new Fence());
         auto acquireFence2 = fenceFactory.createFenceTimeForTest(fence2);
-        const auto buffer2 = std::make_shared<
-                renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888,
-                                                                 1, 0),
-                                               mRenderEngine, false);
-        layer->setBuffer(buffer2, fence2, 10, 20, false, mClientCache, 1, std::nullopt,
-                         {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */,
-                         nullptr /* releaseBufferEndpoint */);
+        const auto buffer2 = new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0);
+        bufferData.buffer = buffer2;
+        bufferData.acquireFence = fence2;
+        bufferData.frameNumber = 1;
+        bufferData.flags |= BufferData::BufferDataChange::fenceChanged;
+        bufferData.flags |= BufferData::BufferDataChange::frameNumberChanged;
+        layer->setBuffer(bufferData, 10, 20, false, std::nullopt,
+                         {/*vsyncId*/ 1, /*inputEventId*/ 0});
         acquireFence2->signalForTest(12);
 
         ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX);
@@ -342,27 +356,30 @@
 
         sp<Fence> fence1(new Fence());
         auto acquireFence1 = fenceFactory.createFenceTimeForTest(fence1);
-        const auto buffer1 = std::make_shared<
-                renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888,
-                                                                 1, 0),
-                                               mRenderEngine, false);
-        layer->setBuffer(buffer1, fence1, 10, 20, false, mClientCache, 1, std::nullopt,
-                         {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */,
-                         nullptr /* releaseBufferEndpoint */);
+        const auto buffer1 = new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0);
+        BufferData bufferData;
+        bufferData.buffer = buffer1;
+        bufferData.acquireFence = fence1;
+        bufferData.frameNumber = 1;
+        bufferData.flags |= BufferData::BufferDataChange::fenceChanged;
+        bufferData.flags |= BufferData::BufferDataChange::frameNumberChanged;
+        layer->setBuffer(bufferData, 10, 20, false, std::nullopt,
+                         {/*vsyncId*/ 1, /*inputEventId*/ 0});
         EXPECT_EQ(0u, layer->mDrawingState.bufferlessSurfaceFramesTX.size());
         ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX);
         const auto droppedSurfaceFrame1 = layer->mDrawingState.bufferSurfaceFrameTX;
 
         sp<Fence> fence2(new Fence());
         auto acquireFence2 = fenceFactory.createFenceTimeForTest(fence2);
-        const auto buffer2 = std::make_shared<
-                renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888,
-                                                                 1, 0),
-                                               mRenderEngine, false);
+        const auto buffer2 = new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0);
         auto dropStartTime1 = systemTime();
-        layer->setBuffer(buffer2, fence2, 10, 20, false, mClientCache, 1, std::nullopt,
-                         {/*vsyncId*/ FrameTimelineInfo::INVALID_VSYNC_ID, /*inputEventId*/ 0},
-                         nullptr /* releaseBufferCallback */, nullptr /* releaseBufferEndpoint */);
+        bufferData.buffer = buffer2;
+        bufferData.acquireFence = fence2;
+        bufferData.frameNumber = 1;
+        bufferData.flags |= BufferData::BufferDataChange::fenceChanged;
+        bufferData.flags |= BufferData::BufferDataChange::frameNumberChanged;
+        layer->setBuffer(bufferData, 10, 20, false, std::nullopt,
+                         {/*vsyncId*/ FrameTimelineInfo::INVALID_VSYNC_ID, /*inputEventId*/ 0});
         auto dropEndTime1 = systemTime();
         EXPECT_EQ(0u, layer->mDrawingState.bufferlessSurfaceFramesTX.size());
         ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX);
@@ -370,14 +387,15 @@
 
         sp<Fence> fence3(new Fence());
         auto acquireFence3 = fenceFactory.createFenceTimeForTest(fence3);
-        const auto buffer3 = std::make_shared<
-                renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888,
-                                                                 1, 0),
-                                               mRenderEngine, false);
+        const auto buffer3 = new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0);
         auto dropStartTime2 = systemTime();
-        layer->setBuffer(buffer3, fence3, 10, 20, false, mClientCache, 1, std::nullopt,
-                         {/*vsyncId*/ 2, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */,
-                         nullptr /* releaseBufferEndpoint */);
+        bufferData.buffer = buffer3;
+        bufferData.acquireFence = fence3;
+        bufferData.frameNumber = 1;
+        bufferData.flags |= BufferData::BufferDataChange::fenceChanged;
+        bufferData.flags |= BufferData::BufferDataChange::frameNumberChanged;
+        layer->setBuffer(bufferData, 10, 20, false, std::nullopt,
+                         {/*vsyncId*/ 2, /*inputEventId*/ 0});
         auto dropEndTime2 = systemTime();
         acquireFence3->signalForTest(12);
 
@@ -413,16 +431,16 @@
         uint32_t surfaceFramesPendingClassification = 0;
         std::vector<std::shared_ptr<frametimeline::SurfaceFrame>> bufferlessSurfaceFrames;
         for (int i = 0; i < 10; i += 2) {
-            sp<Fence> fence1(new Fence());
-            const auto buffer1 = std::make_shared<
-                    renderengine::ExternalTexture>(new GraphicBuffer(1, 1,
-                                                                     HAL_PIXEL_FORMAT_RGBA_8888, 1,
-                                                                     0),
-                                                   mRenderEngine, false);
-            layer->setBuffer(buffer1, fence1, 10, 20, false, mClientCache, 1, std::nullopt,
-                             {/*vsyncId*/ 1, /*inputEventId*/ 0},
-                             nullptr /* releaseBufferCallback */,
-                             nullptr /* releaseBufferEndpoint */);
+            sp<Fence> fence(new Fence());
+            const auto buffer = new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0);
+            BufferData bufferData;
+            bufferData.buffer = buffer;
+            bufferData.acquireFence = fence;
+            bufferData.frameNumber = 1;
+            bufferData.flags |= BufferData::BufferDataChange::fenceChanged;
+            bufferData.flags |= BufferData::BufferDataChange::frameNumberChanged;
+            layer->setBuffer(bufferData, 10, 20, false, std::nullopt,
+                             {/*vsyncId*/ 1, /*inputEventId*/ 0});
             layer->setFrameTimelineVsyncForBufferlessTransaction({/*vsyncId*/ 2,
                                                                   /*inputEventId*/ 0},
                                                                  10);