Merge "Enable compiling dex files in isolation on low ram devices." into sc-dev
diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp
index b9a293f..52d3fa3 100644
--- a/libs/gui/BLASTBufferQueue.cpp
+++ b/libs/gui/BLASTBufferQueue.cpp
@@ -29,9 +29,10 @@
 #include <gui/IProducerListener.h>
 #include <gui/Surface.h>
 #include <utils/Singleton.h>
-
 #include <utils/Trace.h>
 
+#include <private/gui/ComposerService.h>
+
 #include <chrono>
 
 using namespace std::chrono_literals;
@@ -158,6 +159,9 @@
     mBufferItemConsumer->setDefaultBufferFormat(convertBufferFormat(format));
     mBufferItemConsumer->setBlastBufferQueue(this);
 
+    ComposerService::getComposerService()->getMaxAcquiredBufferCount(&mMaxAcquiredBuffers);
+    mBufferItemConsumer->setMaxAcquiredBufferCount(mMaxAcquiredBuffers);
+
     mTransformHint = mSurfaceControl->getTransformHint();
     mBufferItemConsumer->setTransformHint(mTransformHint);
     SurfaceComposerClient::Transaction()
@@ -302,18 +306,20 @@
 // So we pass in a weak pointer to the BBQ and if it still alive, then we release the buffer.
 // Otherwise, this is a no-op.
 static void releaseBufferCallbackThunk(wp<BLASTBufferQueue> context, uint64_t graphicBufferId,
-                                       const sp<Fence>& releaseFence, uint32_t transformHint) {
+                                       const sp<Fence>& releaseFence, uint32_t transformHint,
+                                       uint32_t currentMaxAcquiredBufferCount) {
     sp<BLASTBufferQueue> blastBufferQueue = context.promote();
     ALOGV("releaseBufferCallbackThunk graphicBufferId=%" PRIu64 " blastBufferQueue=%s",
           graphicBufferId, blastBufferQueue ? "alive" : "dead");
     if (blastBufferQueue) {
-        blastBufferQueue->releaseBufferCallback(graphicBufferId, releaseFence, transformHint);
+        blastBufferQueue->releaseBufferCallback(graphicBufferId, releaseFence, transformHint,
+                                                currentMaxAcquiredBufferCount);
     }
 }
 
 void BLASTBufferQueue::releaseBufferCallback(uint64_t graphicBufferId,
-                                             const sp<Fence>& releaseFence,
-                                             uint32_t transformHint) {
+                                             const sp<Fence>& releaseFence, uint32_t transformHint,
+                                             uint32_t currentMaxAcquiredBufferCount) {
     ATRACE_CALL();
     std::unique_lock _lock{mMutex};
     BQA_LOGV("releaseBufferCallback graphicBufferId=%" PRIu64, graphicBufferId);
@@ -324,15 +330,36 @@
         mBufferItemConsumer->setTransformHint(mTransformHint);
     }
 
-    auto it = mSubmitted.find(graphicBufferId);
-    if (it == mSubmitted.end()) {
-        BQA_LOGE("ERROR: releaseBufferCallback without corresponding submitted buffer %" PRIu64,
-                 graphicBufferId);
-        return;
+    // Calculate how many buffers we need to hold before we release them back
+    // to the buffer queue. This will prevent higher latency when we are running
+    // on a lower refresh rate than the max supported. We only do that for EGL
+    // clients as others don't care about latency
+    const bool isEGL = [&] {
+        const auto it = mSubmitted.find(graphicBufferId);
+        return it != mSubmitted.end() && it->second.mApi == NATIVE_WINDOW_API_EGL;
+    }();
+
+    const auto numPendingBuffersToHold =
+            isEGL ? std::max(0u, mMaxAcquiredBuffers - currentMaxAcquiredBufferCount) : 0;
+    mPendingRelease.emplace_back(ReleasedBuffer{graphicBufferId, releaseFence});
+
+    // Release all buffers that are beyond the ones that we need to hold
+    while (mPendingRelease.size() > numPendingBuffersToHold) {
+        const auto releaseBuffer = mPendingRelease.front();
+        mPendingRelease.pop_front();
+        auto it = mSubmitted.find(releaseBuffer.bufferId);
+        if (it == mSubmitted.end()) {
+            BQA_LOGE("ERROR: releaseBufferCallback without corresponding submitted buffer %" PRIu64,
+                     graphicBufferId);
+            return;
+        }
+
+        mBufferItemConsumer->releaseBuffer(it->second, releaseBuffer.releaseFence);
+        mSubmitted.erase(it);
     }
 
-    mBufferItemConsumer->releaseBuffer(it->second, releaseFence);
-    mSubmitted.erase(it);
+    ATRACE_INT("PendingRelease", mPendingRelease.size());
+
     mNumAcquired--;
     processNextBufferLocked(false /* useNextTransaction */);
     mCallbackCV.notify_all();
@@ -414,7 +441,8 @@
 
     auto releaseBufferCallback =
             std::bind(releaseBufferCallbackThunk, wp<BLASTBufferQueue>(this) /* callbackContext */,
-                      std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
+                      std::placeholders::_1, std::placeholders::_2, std::placeholders::_3,
+                      std::placeholders::_4);
     t->setBuffer(mSurfaceControl, buffer, releaseBufferCallback);
     t->setDataspace(mSurfaceControl, static_cast<ui::Dataspace>(bufferItem.mDataSpace));
     t->setHdrMetadata(mSurfaceControl, bufferItem.mHdrMetadata);
@@ -567,7 +595,7 @@
 // includeExtraAcquire is true to include this buffer to the count. Since this depends on the state
 // of the buffer, the next acquire may return with NO_BUFFER_AVAILABLE.
 bool BLASTBufferQueue::maxBuffersAcquired(bool includeExtraAcquire) const {
-    int maxAcquiredBuffers = MAX_ACQUIRED_BUFFERS + (includeExtraAcquire ? 2 : 1);
+    int maxAcquiredBuffers = mMaxAcquiredBuffers + (includeExtraAcquire ? 2 : 1);
     return mNumAcquired == maxAcquiredBuffers;
 }
 
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index 71e18a9..0d7795e 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -1215,16 +1215,17 @@
         return reply.readInt32();
     }
 
-    status_t getExtraBufferCount(int* extraBuffers) const override {
+    status_t getMaxAcquiredBufferCount(int* buffers) const override {
         Parcel data, reply;
         data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
-        status_t err = remote()->transact(BnSurfaceComposer::GET_EXTRA_BUFFER_COUNT, data, &reply);
+        status_t err =
+                remote()->transact(BnSurfaceComposer::GET_MAX_ACQUIRED_BUFFER_COUNT, data, &reply);
         if (err != NO_ERROR) {
-            ALOGE("getExtraBufferCount failed to read data:  %s (%d)", strerror(-err), err);
+            ALOGE("getMaxAcquiredBufferCount failed to read data:  %s (%d)", strerror(-err), err);
             return err;
         }
 
-        return reply.readInt32(extraBuffers);
+        return reply.readInt32(buffers);
     }
 };
 
@@ -2069,14 +2070,14 @@
             SAFE_PARCEL(reply->writeInt32, priority);
             return NO_ERROR;
         }
-        case GET_EXTRA_BUFFER_COUNT: {
+        case GET_MAX_ACQUIRED_BUFFER_COUNT: {
             CHECK_INTERFACE(ISurfaceComposer, data, reply);
-            int extraBuffers = 0;
-            int err = getExtraBufferCount(&extraBuffers);
+            int buffers = 0;
+            int err = getMaxAcquiredBufferCount(&buffers);
             if (err != NO_ERROR) {
                 return err;
             }
-            SAFE_PARCEL(reply->writeInt32, extraBuffers);
+            SAFE_PARCEL(reply->writeInt32, buffers);
             return NO_ERROR;
         }
         case OVERRIDE_HDR_TYPES: {
diff --git a/libs/gui/ITransactionCompletedListener.cpp b/libs/gui/ITransactionCompletedListener.cpp
index 63d07ba..17499ec 100644
--- a/libs/gui/ITransactionCompletedListener.cpp
+++ b/libs/gui/ITransactionCompletedListener.cpp
@@ -119,6 +119,7 @@
         SAFE_PARCEL(output->writeBool, false);
     }
     SAFE_PARCEL(output->writeUint32, transformHint);
+    SAFE_PARCEL(output->writeUint32, currentMaxAcquiredBufferCount);
     SAFE_PARCEL(output->writeParcelable, eventStats);
     SAFE_PARCEL(output->writeInt32, static_cast<int32_t>(jankData.size()));
     for (const auto& data : jankData) {
@@ -138,6 +139,7 @@
         SAFE_PARCEL(input->read, *previousReleaseFence);
     }
     SAFE_PARCEL(input->readUint32, &transformHint);
+    SAFE_PARCEL(input->readUint32, &currentMaxAcquiredBufferCount);
     SAFE_PARCEL(input->readParcelable, &eventStats);
 
     int32_t jankData_size = 0;
@@ -251,11 +253,13 @@
                                                                   stats);
     }
 
-    void onReleaseBuffer(uint64_t graphicBufferId, sp<Fence> releaseFence,
-                         uint32_t transformHint) override {
+    void onReleaseBuffer(uint64_t graphicBufferId, sp<Fence> releaseFence, uint32_t transformHint,
+                         uint32_t currentMaxAcquiredBufferCount) override {
         callRemoteAsync<decltype(
                 &ITransactionCompletedListener::onReleaseBuffer)>(Tag::ON_RELEASE_BUFFER,
-                graphicBufferId, releaseFence, transformHint);
+                                                                  graphicBufferId, releaseFence,
+                                                                  transformHint,
+                                                                  currentMaxAcquiredBufferCount);
     }
 };
 
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index e117d11..821ec16 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -1501,9 +1501,6 @@
     case NATIVE_WINDOW_SET_FRAME_TIMELINE_INFO:
         res = dispatchSetFrameTimelineInfo(args);
         break;
-    case NATIVE_WINDOW_GET_EXTRA_BUFFER_COUNT:
-        res = dispatchGetExtraBufferCount(args);
-        break;
     default:
         res = NAME_NOT_FOUND;
         break;
@@ -1853,14 +1850,6 @@
     return setFrameTimelineInfo({frameTimelineVsyncId, inputEventId});
 }
 
-int Surface::dispatchGetExtraBufferCount(va_list args) {
-    ATRACE_CALL();
-    auto extraBuffers = static_cast<int*>(va_arg(args, int*));
-
-    ALOGV("Surface::dispatchGetExtraBufferCount");
-    return getExtraBufferCount(extraBuffers);
-}
-
 bool Surface::transformToDisplayInverse() const {
     return (mTransform & NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY) ==
             NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY;
@@ -2632,8 +2621,4 @@
     return composerService()->setFrameTimelineInfo(mGraphicBufferProducer, frameTimelineInfo);
 }
 
-status_t Surface::getExtraBufferCount(int* extraBuffers) const {
-    return composerService()->getExtraBufferCount(extraBuffers);
-}
-
 }; // namespace android
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 660c5bd..c69435d 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -328,7 +328,8 @@
                                  surfaceStats.previousReleaseFence
                                          ? surfaceStats.previousReleaseFence
                                          : Fence::NO_FENCE,
-                                 surfaceStats.transformHint);
+                                 surfaceStats.transformHint,
+                                 surfaceStats.currentMaxAcquiredBufferCount);
                     }
                 }
             }
@@ -364,9 +365,9 @@
     }
 }
 
-void TransactionCompletedListener::onReleaseBuffer(uint64_t graphicBufferId,
-                                                   sp<Fence> releaseFence,
-                                                   uint32_t transformHint) {
+void TransactionCompletedListener::onReleaseBuffer(uint64_t graphicBufferId, sp<Fence> releaseFence,
+                                                   uint32_t transformHint,
+                                                   uint32_t currentMaxAcquiredBufferCount) {
     ReleaseBufferCallback callback;
     {
         std::scoped_lock<std::mutex> lock(mMutex);
@@ -376,7 +377,7 @@
         ALOGE("Could not call release buffer callback, buffer not found %" PRIu64, graphicBufferId);
         return;
     }
-    callback(graphicBufferId, releaseFence, transformHint);
+    callback(graphicBufferId, releaseFence, transformHint, currentMaxAcquiredBufferCount);
 }
 
 ReleaseBufferCallback TransactionCompletedListener::popReleaseBufferCallbackLocked(
diff --git a/libs/gui/SurfaceControl.cpp b/libs/gui/SurfaceControl.cpp
index d7c07b9..6529a4e 100644
--- a/libs/gui/SurfaceControl.cpp
+++ b/libs/gui/SurfaceControl.cpp
@@ -139,7 +139,7 @@
                                  ISurfaceComposerClient::eOpaque);
     mBbqChild = mClient->createSurface(String8("bbq-wrapper"), 0, 0, mFormat,
                                        flags, mHandle, {}, &ignore);
-    mBbq = new BLASTBufferQueue("bbq-adapter", mBbqChild, mWidth, mHeight, mFormat);
+    mBbq = sp<BLASTBufferQueue>::make("bbq-adapter", mBbqChild, mWidth, mHeight, mFormat);
 
     // This surface is always consumed by SurfaceFlinger, so the
     // producerControlledByApp value doesn't matter; using false.
diff --git a/libs/gui/include/gui/BLASTBufferQueue.h b/libs/gui/include/gui/BLASTBufferQueue.h
index 3ab1ee1..0981e76 100644
--- a/libs/gui/include/gui/BLASTBufferQueue.h
+++ b/libs/gui/include/gui/BLASTBufferQueue.h
@@ -90,7 +90,7 @@
     void transactionCallback(nsecs_t latchTime, const sp<Fence>& presentFence,
             const std::vector<SurfaceControlStats>& stats);
     void releaseBufferCallback(uint64_t graphicBufferId, const sp<Fence>& releaseFence,
-                               uint32_t transformHint);
+                               uint32_t transformHint, uint32_t currentMaxAcquiredBufferCount);
     void setNextTransaction(SurfaceComposerClient::Transaction *t);
     void mergeWithNextTransaction(SurfaceComposerClient::Transaction* t, uint64_t frameNumber);
     void setTransactionCompleteCallback(uint64_t frameNumber,
@@ -132,7 +132,7 @@
 
     // BufferQueue internally allows 1 more than
     // the max to be acquired
-    static const int MAX_ACQUIRED_BUFFERS = 1;
+    int32_t mMaxAcquiredBuffers = 1;
 
     int32_t mNumFrameAvailable GUARDED_BY(mMutex);
     int32_t mNumAcquired GUARDED_BY(mMutex);
@@ -141,6 +141,15 @@
     // buffer or the buffer has been presented and a new buffer is ready to be presented.
     std::unordered_map<uint64_t /* bufferId */, BufferItem> mSubmitted GUARDED_BY(mMutex);
 
+    // Keep a queue of the released buffers instead of immediately releasing
+    // the buffers back to the buffer queue. This would be controlled by SF
+    // setting the max acquired buffer count.
+    struct ReleasedBuffer {
+        uint64_t bufferId;
+        sp<Fence> releaseFence;
+    };
+    std::deque<ReleasedBuffer> mPendingRelease GUARDED_BY(mMutex);
+
     ui::Size mSize GUARDED_BY(mMutex);
     ui::Size mRequestedSize GUARDED_BY(mMutex);
     int32_t mFormat GUARDED_BY(mMutex);
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index 439d90a..2a3f6a4 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -537,22 +537,21 @@
     virtual int getGPUContextPriority() = 0;
 
     /**
-     * Gets the extra buffers a client would need to allocate if it passes
-     * the Choreographer#getVsyncId with its buffers.
-     *
-     * When Choreographer#getVsyncId is passed to SurfaceFlinger, it is used
-     * as an indication of when to latch the buffer. SurfaceFlinger will make
-     * sure that it will give the app at least the time configured as the
-     * 'appDuration' before trying to latch the buffer.
+     * Gets the number of buffers SurfaceFlinger would need acquire. This number
+     * would be propagated to the client via MIN_UNDEQUEUED_BUFFERS so that the
+     * client could allocate enough buffers to match SF expectations of the
+     * pipeline depth. SurfaceFlinger will make sure that it will give the app at
+     * least the time configured as the 'appDuration' before trying to latch
+     * the buffer.
      *
      * The total buffers needed for a given configuration is basically the
      * numbers of vsyncs a single buffer is used across the stack. For the default
      * configuration a buffer is held ~1 vsync by the app, ~1 vsync by SurfaceFlinger
      * and 1 vsync by the display. The extra buffers are calculated as the
-     * number of additional buffers on top of the 3 buffers already allocated
-     * by the app.
+     * number of additional buffers on top of the 2 buffers already present
+     * in MIN_UNDEQUEUED_BUFFERS.
      */
-    virtual status_t getExtraBufferCount(int* extraBuffers) const = 0;
+    virtual status_t getMaxAcquiredBufferCount(int* buffers) const = 0;
 };
 
 // ----------------------------------------------------------------------------
@@ -615,7 +614,7 @@
         SET_FRAME_TIMELINE_INFO,
         ADD_TRANSACTION_TRACE_LISTENER,
         GET_GPU_CONTEXT_PRIORITY,
-        GET_EXTRA_BUFFER_COUNT,
+        GET_MAX_ACQUIRED_BUFFER_COUNT,
         GET_DYNAMIC_DISPLAY_INFO,
         ADD_FPS_LISTENER,
         REMOVE_FPS_LISTENER,
diff --git a/libs/gui/include/gui/ITransactionCompletedListener.h b/libs/gui/include/gui/ITransactionCompletedListener.h
index 3bfeef1..d286c34 100644
--- a/libs/gui/include/gui/ITransactionCompletedListener.h
+++ b/libs/gui/include/gui/ITransactionCompletedListener.h
@@ -101,12 +101,14 @@
 
     SurfaceStats() = default;
     SurfaceStats(const sp<IBinder>& sc, nsecs_t time, const sp<Fence>& prevReleaseFence,
-                 uint32_t hint, FrameEventHistoryStats frameEventStats,
-                 std::vector<JankData> jankData, uint64_t previousBufferId)
+                 uint32_t hint, uint32_t currentMaxAcquiredBuffersCount,
+                 FrameEventHistoryStats frameEventStats, std::vector<JankData> jankData,
+                 uint64_t previousBufferId)
           : surfaceControl(sc),
             acquireTime(time),
             previousReleaseFence(prevReleaseFence),
             transformHint(hint),
+            currentMaxAcquiredBufferCount(currentMaxAcquiredBuffersCount),
             eventStats(frameEventStats),
             jankData(std::move(jankData)),
             previousBufferId(previousBufferId) {}
@@ -115,6 +117,7 @@
     nsecs_t acquireTime = -1;
     sp<Fence> previousReleaseFence;
     uint32_t transformHint = 0;
+    uint32_t currentMaxAcquiredBufferCount = 0;
     FrameEventHistoryStats eventStats;
     std::vector<JankData> jankData;
     uint64_t previousBufferId;
@@ -159,7 +162,8 @@
     virtual void onTransactionCompleted(ListenerStats stats) = 0;
 
     virtual void onReleaseBuffer(uint64_t graphicBufferId, sp<Fence> releaseFence,
-                                 uint32_t transformHint) = 0;
+                                 uint32_t transformHint,
+                                 uint32_t currentMaxAcquiredBufferCount) = 0;
 };
 
 class BnTransactionCompletedListener : public SafeBnInterface<ITransactionCompletedListener> {
diff --git a/libs/gui/include/gui/Surface.h b/libs/gui/include/gui/Surface.h
index 48885eb..7e4143b 100644
--- a/libs/gui/include/gui/Surface.h
+++ b/libs/gui/include/gui/Surface.h
@@ -190,7 +190,6 @@
     virtual status_t setFrameRate(float frameRate, int8_t compatibility,
                                   int8_t changeFrameRateStrategy);
     virtual status_t setFrameTimelineInfo(const FrameTimelineInfo& info);
-    virtual status_t getExtraBufferCount(int* extraBuffers) const;
 
 protected:
     virtual ~Surface();
@@ -278,7 +277,6 @@
     int dispatchGetLastQueuedBuffer(va_list args);
     int dispatchGetLastQueuedBuffer2(va_list args);
     int dispatchSetFrameTimelineInfo(va_list args);
-    int dispatchGetExtraBufferCount(va_list args);
 
 protected:
     virtual int dequeueBuffer(ANativeWindowBuffer** buffer, int* fenceFd);
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 5aa132c..fa91bfa 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -83,7 +83,7 @@
                            const std::vector<SurfaceControlStats>& /*stats*/)>;
 using ReleaseBufferCallback =
         std::function<void(uint64_t /* graphicsBufferId */, const sp<Fence>& /*releaseFence*/,
-                           uint32_t transformHint)>;
+                           uint32_t transformHint, uint32_t currentMaxAcquiredBufferCount)>;
 
 using SurfaceStatsCallback =
         std::function<void(void* /*context*/, nsecs_t /*latchTime*/,
@@ -729,7 +729,7 @@
     // BnTransactionCompletedListener overrides
     void onTransactionCompleted(ListenerStats stats) override;
     void onReleaseBuffer(uint64_t /* graphicsBufferId */, sp<Fence> releaseFence,
-                         uint32_t transformHint) override;
+                         uint32_t transformHint, uint32_t currentMaxAcquiredBufferCount) override;
 
 private:
     ReleaseBufferCallback popReleaseBufferCallbackLocked(uint64_t /* graphicsBufferId */);
diff --git a/libs/gui/tests/BLASTBufferQueue_test.cpp b/libs/gui/tests/BLASTBufferQueue_test.cpp
index 5a5da97..06660b8 100644
--- a/libs/gui/tests/BLASTBufferQueue_test.cpp
+++ b/libs/gui/tests/BLASTBufferQueue_test.cpp
@@ -394,7 +394,11 @@
     setUpProducer(adapter, igbProducer);
 
     std::vector<std::pair<int, sp<Fence>>> allocated;
-    for (int i = 0; i < 3; i++) {
+    int minUndequeuedBuffers = 0;
+    ASSERT_EQ(OK, igbProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minUndequeuedBuffers));
+    const auto bufferCount = minUndequeuedBuffers + 2;
+
+    for (int i = 0; i < bufferCount; i++) {
         int slot;
         sp<Fence> fence;
         sp<GraphicBuffer> buf;
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index b8d34c3..59b0c04 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -902,7 +902,7 @@
 
     int getGPUContextPriority() override { return 0; };
 
-    status_t getExtraBufferCount(int* /*extraBuffers*/) const override { return NO_ERROR; }
+    status_t getMaxAcquiredBufferCount(int* /*buffers*/) const override { return NO_ERROR; }
 
 protected:
     IBinder* onAsBinder() override { return nullptr; }
diff --git a/libs/nativewindow/include/system/window.h b/libs/nativewindow/include/system/window.h
index 935eded..7f01135 100644
--- a/libs/nativewindow/include/system/window.h
+++ b/libs/nativewindow/include/system/window.h
@@ -256,8 +256,7 @@
     NATIVE_WINDOW_GET_LAST_QUEUED_BUFFER          = 46,    /* private */
     NATIVE_WINDOW_SET_QUERY_INTERCEPTOR           = 47,    /* private */
     NATIVE_WINDOW_SET_FRAME_TIMELINE_INFO         = 48,    /* private */
-    NATIVE_WINDOW_GET_EXTRA_BUFFER_COUNT          = 49,    /* private */
-    NATIVE_WINDOW_GET_LAST_QUEUED_BUFFER2         = 50,    /* private */
+    NATIVE_WINDOW_GET_LAST_QUEUED_BUFFER2         = 49,    /* private */
     // clang-format on
 };
 
@@ -1032,11 +1031,6 @@
                            frameTimelineVsyncId, inputEventId);
 }
 
-static inline int native_window_get_extra_buffer_count(
-    struct ANativeWindow* window, int* extraBuffers) {
-    return window->perform(window, NATIVE_WINDOW_GET_EXTRA_BUFFER_COUNT, extraBuffers);
-}
-
 // ------------------------------------------------------------------------------------------------
 // Candidates for APEX visibility
 // These functions are planned to be made stable for APEX modules, but have not
diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.cpp b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
index d28d623..cb80ef4 100644
--- a/libs/renderengine/skia/SkiaGLRenderEngine.cpp
+++ b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
@@ -552,10 +552,25 @@
 
         iter->second--;
 
+        // Swap contexts if needed prior to deleting this buffer
+        // See Issue 1 of
+        // https://www.khronos.org/registry/EGL/extensions/EXT/EGL_EXT_protected_content.txt: even
+        // when a protected context and an unprotected context are part of the same share group,
+        // protected surfaces may not be accessed by an unprotected context, implying that protected
+        // surfaces may only be freed when a protected context is active.
+        const bool inProtected = mInProtectedContext;
+        useProtectedContext(buffer->getUsage() & GRALLOC_USAGE_PROTECTED);
+
         if (iter->second == 0) {
             mTextureCache.erase(buffer->getId());
             mGraphicBufferExternalRefs.erase(buffer->getId());
         }
+
+        // Swap back to the previous context so that cached values of isProtected in SurfaceFlinger
+        // are up-to-date.
+        if (inProtected != mInProtectedContext) {
+            useProtectedContext(inProtected);
+        }
     }
 }
 
diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp
index e7f373f..c64371b 100644
--- a/services/surfaceflinger/BufferQueueLayer.cpp
+++ b/services/surfaceflinger/BufferQueueLayer.cpp
@@ -223,7 +223,7 @@
     // buffer mode.
     bool queuedBuffer = false;
     const int32_t layerId = getSequence();
-    LayerRejecter r(mDrawingState, getCurrentState(), recomputeVisibleRegions,
+    LayerRejecter r(mDrawingState, getDrawingState(), recomputeVisibleRegions,
                     getProducerStickyTransform() != 0, mName,
                     getTransformToDisplayInverse());
 
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index 6213a8a..a3b7b13 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -45,12 +45,12 @@
 namespace {
 void callReleaseBufferCallback(const sp<ITransactionCompletedListener>& listener,
                                const sp<GraphicBuffer>& buffer, const sp<Fence>& releaseFence,
-                               uint32_t transformHint) {
+                               uint32_t transformHint, uint32_t currentMaxAcquiredBufferCount) {
     if (!listener) {
         return;
     }
     listener->onReleaseBuffer(buffer->getId(), releaseFence ? releaseFence : Fence::NO_FENCE,
-                              transformHint);
+                              transformHint, currentMaxAcquiredBufferCount);
 }
 } // namespace
 
@@ -65,7 +65,7 @@
 
 BufferStateLayer::BufferStateLayer(const LayerCreationArgs& args)
       : BufferLayer(args), mHwcSlotGenerator(new HwcSlotGenerator()) {
-    mCurrentState.dataspace = ui::Dataspace::V0_SRGB;
+    mDrawingState.dataspace = ui::Dataspace::V0_SRGB;
 }
 
 BufferStateLayer::~BufferStateLayer() {
@@ -76,7 +76,9 @@
     if (mBufferInfo.mBuffer != nullptr && !isClone()) {
         callReleaseBufferCallback(mDrawingState.releaseBufferListener,
                                   mBufferInfo.mBuffer->getBuffer(), mBufferInfo.mFence,
-                                  mTransformHint);
+                                  mTransformHint,
+                                  mFlinger->getMaxAcquiredBufferCountForCurrentRefreshRate(
+                                          mOwnerUid));
     }
 }
 
@@ -200,6 +202,8 @@
     for (const auto& handle : mDrawingState.callbackHandles) {
         handle->transformHint = mTransformHint;
         handle->dequeueReadyTime = dequeueReadyTime;
+        handle->currentMaxAcquiredBufferCount =
+                mFlinger->getMaxAcquiredBufferCountForCurrentRefreshRate(mOwnerUid);
     }
 
     // If there are multiple transactions in this frame, set the previous id on the earliest
@@ -253,8 +257,8 @@
 bool BufferStateLayer::willPresentCurrentTransaction() const {
     // Returns true if the most recent Transaction applied to CurrentState will be presented.
     return (getSidebandStreamChanged() || getAutoRefresh() ||
-            (mCurrentState.modified &&
-             (mCurrentState.buffer != nullptr || mCurrentState.bgColorLayer != nullptr)));
+            (mDrawingState.modified &&
+             (mDrawingState.buffer != nullptr || mDrawingState.bgColorLayer != nullptr)));
 }
 
 Rect BufferStateLayer::getCrop(const Layer::State& s) const {
@@ -262,65 +266,72 @@
 }
 
 bool BufferStateLayer::setTransform(uint32_t transform) {
-    if (mCurrentState.bufferTransform == transform) return false;
-    mCurrentState.bufferTransform = transform;
-    mCurrentState.modified = true;
+    if (mDrawingState.bufferTransform == transform) return false;
+    mDrawingState.bufferTransform = transform;
+    mDrawingState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
 
 bool BufferStateLayer::setTransformToDisplayInverse(bool transformToDisplayInverse) {
-    if (mCurrentState.transformToDisplayInverse == transformToDisplayInverse) return false;
-    mCurrentState.sequence++;
-    mCurrentState.transformToDisplayInverse = transformToDisplayInverse;
-    mCurrentState.modified = true;
+    if (mDrawingState.transformToDisplayInverse == transformToDisplayInverse) return false;
+    mDrawingState.sequence++;
+    mDrawingState.transformToDisplayInverse = transformToDisplayInverse;
+    mDrawingState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
 
 bool BufferStateLayer::setCrop(const Rect& crop) {
-    if (mCurrentState.crop == crop) return false;
-    mCurrentState.sequence++;
-    mCurrentState.crop = crop;
+    if (mDrawingState.crop == crop) return false;
+    mDrawingState.sequence++;
+    mDrawingState.crop = crop;
 
-    mCurrentState.modified = true;
+    mDrawingState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
 
 bool BufferStateLayer::setBufferCrop(const Rect& bufferCrop) {
-    if (mCurrentState.bufferCrop == bufferCrop) return false;
+    if (mDrawingState.bufferCrop == bufferCrop) return false;
 
-    mCurrentState.sequence++;
-    mCurrentState.bufferCrop = bufferCrop;
+    mDrawingState.sequence++;
+    mDrawingState.bufferCrop = bufferCrop;
 
-    mCurrentState.modified = true;
+    mDrawingState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
 
 bool BufferStateLayer::setDestinationFrame(const Rect& destinationFrame) {
-    if (mCurrentState.destinationFrame == destinationFrame) return false;
+    if (mDrawingState.destinationFrame == destinationFrame) return false;
 
-    mCurrentState.sequence++;
-    mCurrentState.destinationFrame = destinationFrame;
+    mDrawingState.sequence++;
+    mDrawingState.destinationFrame = destinationFrame;
 
-    mCurrentState.modified = true;
+    mDrawingState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
 
+static bool assignTransform(ui::Transform* dst, ui::Transform& from) {
+    if (*dst == from) {
+        return false;
+    }
+    *dst = from;
+    return true;
+}
+
 // Translate destination frame into scale and position. If a destination frame is not set, use the
 // provided scale and position
-void BufferStateLayer::updateGeometry() {
-    if (mCurrentState.destinationFrame.isEmpty()) {
+bool BufferStateLayer::updateGeometry() {
+    if (mDrawingState.destinationFrame.isEmpty()) {
         // If destination frame is not set, use the requested transform set via
         // BufferStateLayer::setPosition and BufferStateLayer::setMatrix.
-        mCurrentState.transform = mRequestedTransform;
-        return;
+        return assignTransform(&mDrawingState.transform, mRequestedTransform);
     }
 
-    Rect destRect = mCurrentState.destinationFrame;
+    Rect destRect = mDrawingState.destinationFrame;
     int32_t destW = destRect.width();
     int32_t destH = destRect.height();
     if (destRect.left < 0) {
@@ -332,21 +343,20 @@
         destRect.bottom = destH;
     }
 
-    if (!mCurrentState.buffer) {
+    if (!mDrawingState.buffer) {
         ui::Transform t;
         t.set(destRect.left, destRect.top);
-        mCurrentState.transform = t;
-        return;
+        return assignTransform(&mDrawingState.transform, t);
     }
 
-    uint32_t bufferWidth = mCurrentState.buffer->getBuffer()->getWidth();
-    uint32_t bufferHeight = mCurrentState.buffer->getBuffer()->getHeight();
+    uint32_t bufferWidth = mDrawingState.buffer->getBuffer()->getWidth();
+    uint32_t bufferHeight = mDrawingState.buffer->getBuffer()->getHeight();
     // Undo any transformations on the buffer.
-    if (mCurrentState.bufferTransform & ui::Transform::ROT_90) {
+    if (mDrawingState.bufferTransform & ui::Transform::ROT_90) {
         std::swap(bufferWidth, bufferHeight);
     }
     uint32_t invTransform = DisplayDevice::getPrimaryDisplayRotationFlags();
-    if (mCurrentState.transformToDisplayInverse) {
+    if (mDrawingState.transformToDisplayInverse) {
         if (invTransform & ui::Transform::ROT_90) {
             std::swap(bufferWidth, bufferHeight);
         }
@@ -357,8 +367,7 @@
     ui::Transform t;
     t.set(sx, 0, 0, sy);
     t.set(destRect.left, destRect.top);
-    mCurrentState.transform = t;
-    return;
+    return assignTransform(&mDrawingState.transform, t);
 }
 
 bool BufferStateLayer::setMatrix(const layer_state_t::matrix22_t& matrix,
@@ -379,8 +388,8 @@
 
     mRequestedTransform.set(matrix.dsdx, matrix.dtdy, matrix.dtdx, matrix.dsdy);
 
-    mCurrentState.sequence++;
-    mCurrentState.modified = true;
+    mDrawingState.sequence++;
+    mDrawingState.modified = true;
     setTransactionFlags(eTransactionNeeded);
 
     return true;
@@ -393,8 +402,8 @@
 
     mRequestedTransform.set(x, y);
 
-    mCurrentState.sequence++;
-    mCurrentState.modified = true;
+    mDrawingState.sequence++;
+    mDrawingState.modified = true;
     setTransactionFlags(eTransactionNeeded);
 
     return true;
@@ -406,7 +415,7 @@
     mAcquireTimeline.updateSignalTimes();
     std::shared_ptr<FenceTime> acquireFenceTime =
             std::make_shared<FenceTime>((acquireFence ? acquireFence : Fence::NO_FENCE));
-    NewFrameEventsEntry newTimestamps = {mCurrentState.frameNumber, postedTime, desiredPresentTime,
+    NewFrameEventsEntry newTimestamps = {mDrawingState.frameNumber, postedTime, desiredPresentTime,
                                          acquireFenceTime};
     mFrameEventHistory.setProducerWantsEvents();
     mFrameEventHistory.addQueue(newTimestamps);
@@ -421,37 +430,39 @@
                                  const sp<ITransactionCompletedListener>& releaseBufferListener) {
     ATRACE_CALL();
 
-    if (mCurrentState.buffer) {
+    if (mDrawingState.buffer) {
         mReleasePreviousBuffer = true;
-        if (!mDrawingState.buffer ||
-            mCurrentState.buffer->getBuffer() != mDrawingState.buffer->getBuffer()) {
-            // If mCurrentState has a buffer, and we are about to update again
+        if (mDrawingState.buffer != mBufferInfo.mBuffer) {
+            // If mDrawingState has a buffer, and we are about to update again
             // before swapping to drawing state, then the first buffer will be
             // dropped and we should decrement the pending buffer count and
             // call any release buffer callbacks if set.
-            callReleaseBufferCallback(mCurrentState.releaseBufferListener,
-                                      mCurrentState.buffer->getBuffer(),
-                                      mCurrentState.acquireFence,
-                                      mTransformHint);
+            callReleaseBufferCallback(mDrawingState.releaseBufferListener,
+                                      mDrawingState.buffer->getBuffer(), mDrawingState.acquireFence,
+                                      mTransformHint,
+                                      mFlinger->getMaxAcquiredBufferCountForCurrentRefreshRate(
+                                              mOwnerUid));
             decrementPendingBufferCount();
-            if (mCurrentState.bufferSurfaceFrameTX != nullptr) {
-                addSurfaceFrameDroppedForBuffer(mCurrentState.bufferSurfaceFrameTX);
-                mCurrentState.bufferSurfaceFrameTX.reset();
+            if (mDrawingState.bufferSurfaceFrameTX != nullptr &&
+                mDrawingState.bufferSurfaceFrameTX->getPresentState() != PresentState::Presented) {
+              addSurfaceFrameDroppedForBuffer(mDrawingState.bufferSurfaceFrameTX);
+              mDrawingState.bufferSurfaceFrameTX.reset();
             }
         }
     }
-    mCurrentState.frameNumber = frameNumber;
-    mCurrentState.releaseBufferListener = releaseBufferListener;
-    mCurrentState.buffer = buffer;
-    mCurrentState.clientCacheId = clientCacheId;
-    mCurrentState.modified = true;
+
+    mDrawingState.frameNumber = frameNumber;
+    mDrawingState.releaseBufferListener = releaseBufferListener;
+    mDrawingState.buffer = buffer;
+    mDrawingState.clientCacheId = clientCacheId;
+    mDrawingState.modified = true;
     setTransactionFlags(eTransactionNeeded);
 
     const int32_t layerId = getSequence();
-    mFlinger->mTimeStats->setPostTime(layerId, mCurrentState.frameNumber, getName().c_str(),
+    mFlinger->mTimeStats->setPostTime(layerId, mDrawingState.frameNumber, getName().c_str(),
                                       mOwnerUid, postTime, getGameMode());
-    mCurrentState.desiredPresentTime = desiredPresentTime;
-    mCurrentState.isAutoTimestamp = isAutoTimestamp;
+    mDrawingState.desiredPresentTime = desiredPresentTime;
+    mDrawingState.isAutoTimestamp = isAutoTimestamp;
 
     const nsecs_t presentTime = [&] {
         if (!isAutoTimestamp) return desiredPresentTime;
@@ -478,59 +489,59 @@
                                                FrameTracer::FrameEvent::QUEUE);
     }
 
-    mCurrentState.width = mCurrentState.buffer->getBuffer()->getWidth();
-    mCurrentState.height = mCurrentState.buffer->getBuffer()->getHeight();
+    mDrawingState.width = mDrawingState.buffer->getBuffer()->getWidth();
+    mDrawingState.height = mDrawingState.buffer->getBuffer()->getHeight();
 
     return true;
 }
 
 bool BufferStateLayer::setAcquireFence(const sp<Fence>& fence) {
-    mCurrentState.acquireFence = fence;
-    mCurrentState.acquireFenceTime = std::make_unique<FenceTime>(fence);
+    mDrawingState.acquireFence = fence;
+    mDrawingState.acquireFenceTime = std::make_unique<FenceTime>(fence);
 
     // The acquire fences of BufferStateLayers have already signaled before they are set
-    mCallbackHandleAcquireTime = mCurrentState.acquireFenceTime->getSignalTime();
+    mCallbackHandleAcquireTime = mDrawingState.acquireFenceTime->getSignalTime();
 
-    mCurrentState.modified = true;
+    mDrawingState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
 
 bool BufferStateLayer::setDataspace(ui::Dataspace dataspace) {
-    if (mCurrentState.dataspace == dataspace) return false;
-    mCurrentState.dataspace = dataspace;
-    mCurrentState.modified = true;
+    if (mDrawingState.dataspace == dataspace) return false;
+    mDrawingState.dataspace = dataspace;
+    mDrawingState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
 
 bool BufferStateLayer::setHdrMetadata(const HdrMetadata& hdrMetadata) {
-    if (mCurrentState.hdrMetadata == hdrMetadata) return false;
-    mCurrentState.hdrMetadata = hdrMetadata;
-    mCurrentState.modified = true;
+    if (mDrawingState.hdrMetadata == hdrMetadata) return false;
+    mDrawingState.hdrMetadata = hdrMetadata;
+    mDrawingState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
 
 bool BufferStateLayer::setSurfaceDamageRegion(const Region& surfaceDamage) {
-    mCurrentState.surfaceDamageRegion = surfaceDamage;
-    mCurrentState.modified = true;
+    mDrawingState.surfaceDamageRegion = surfaceDamage;
+    mDrawingState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
 
 bool BufferStateLayer::setApi(int32_t api) {
-    if (mCurrentState.api == api) return false;
-    mCurrentState.api = api;
-    mCurrentState.modified = true;
+    if (mDrawingState.api == api) return false;
+    mDrawingState.api = api;
+    mDrawingState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
 
 bool BufferStateLayer::setSidebandStream(const sp<NativeHandle>& sidebandStream) {
-    if (mCurrentState.sidebandStream == sidebandStream) return false;
-    mCurrentState.sidebandStream = sidebandStream;
-    mCurrentState.modified = true;
+    if (mDrawingState.sidebandStream == sidebandStream) return false;
+    mDrawingState.sidebandStream = sidebandStream;
+    mDrawingState.modified = true;
     setTransactionFlags(eTransactionNeeded);
 
     if (!mSidebandStreamChanged.exchange(true)) {
@@ -558,14 +569,14 @@
         if (willPresent) {
             // If this transaction set an acquire fence on this layer, set its acquire time
             handle->acquireTime = mCallbackHandleAcquireTime;
-            handle->frameNumber = mCurrentState.frameNumber;
+            handle->frameNumber = mDrawingState.frameNumber;
 
             // Notify the transaction completed thread that there is a pending latched callback
             // handle
             mFlinger->getTransactionCallbackInvoker().registerPendingCallbackHandle(handle);
 
             // Store so latched time and release fence can be set
-            mCurrentState.callbackHandles.push_back(handle);
+            mDrawingState.callbackHandles.push_back(handle);
 
         } else { // If this layer will NOT need to be relatched and presented this frame
             // Notify the transaction completed thread this handle is done
@@ -580,8 +591,8 @@
 }
 
 bool BufferStateLayer::setTransparentRegionHint(const Region& transparent) {
-    mCurrentState.transparentRegionHint = transparent;
-    mCurrentState.modified = true;
+    mDrawingState.transparentRegionHint = transparent;
+    mDrawingState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
@@ -640,7 +651,7 @@
         return true;
     }
 
-    return mCurrentState.isAutoTimestamp || mCurrentState.desiredPresentTime <= expectedPresentTime;
+    return mDrawingState.isAutoTimestamp || mDrawingState.desiredPresentTime <= expectedPresentTime;
 }
 
 bool BufferStateLayer::onPreComposition(nsecs_t refreshStartTime) {
@@ -669,7 +680,7 @@
  *  }
  * Now imagine getHeadFrameNumber returned mDrawingState.mFrameNumber (or mCurrentFrameNumber).
  * Prior to doTransaction SurfaceFlinger will call notifyAvailableFrames, but because we
- * haven't swapped mCurrentState to mDrawingState yet we will think the sync point
+ * 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
@@ -677,7 +688,7 @@
  * to apply.
  */
 uint64_t BufferStateLayer::getHeadFrameNumber(nsecs_t /* expectedPresentTime */) const {
-    return mCurrentState.frameNumber;
+    return mDrawingState.frameNumber;
 }
 
 void BufferStateLayer::setAutoRefresh(bool autoRefresh) {
@@ -707,8 +718,8 @@
 }
 
 bool BufferStateLayer::hasFrameUpdate() const {
-    const State& c(getCurrentState());
-    return mCurrentStateModified && (c.buffer != nullptr || c.bgColorLayer != nullptr);
+    const State& c(getDrawingState());
+    return mDrawingStateModified && (c.buffer != nullptr || c.bgColorLayer != nullptr);
 }
 
 status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nsecs_t latchTime,
@@ -751,6 +762,7 @@
         addSurfaceFramePresentedForBuffer(bufferSurfaceFrame,
                                           mDrawingState.acquireFenceTime->getSignalTime(),
                                           latchTime);
+        mDrawingState.bufferSurfaceFrameTX.reset();
     }
 
     std::deque<sp<CallbackHandle>> remainingHandles;
@@ -758,7 +770,7 @@
             .finalizeOnCommitCallbackHandles(mDrawingState.callbackHandles, remainingHandles);
     mDrawingState.callbackHandles = remainingHandles;
 
-    mCurrentStateModified = false;
+    mDrawingStateModified = false;
 
     return NO_ERROR;
 }
@@ -952,7 +964,9 @@
         // call any release buffer callbacks if set.
         callReleaseBufferCallback(mDrawingState.releaseBufferListener,
                                   mDrawingState.buffer->getBuffer(), mDrawingState.acquireFence,
-                                  mTransformHint);
+                                  mTransformHint,
+                                  mFlinger->getMaxAcquiredBufferCountForCurrentRefreshRate(
+                                          mOwnerUid));
         decrementPendingBufferCount();
     }
 }
diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h
index 2e48452..2747018 100644
--- a/services/surfaceflinger/BufferStateLayer.h
+++ b/services/surfaceflinger/BufferStateLayer.h
@@ -47,10 +47,6 @@
 
     bool isBufferDue(nsecs_t /*expectedPresentTime*/) const override { return true; }
 
-    uint32_t doTransactionResize(uint32_t flags, Layer::State* /*stateToCommit*/) override {
-        return flags;
-    }
-
     Region getActiveTransparentRegion(const Layer::State& s) const override {
         return s.transparentRegionHint;
     }
@@ -87,7 +83,7 @@
 
     bool setBufferCrop(const Rect& bufferCrop) override;
     bool setDestinationFrame(const Rect& destinationFrame) override;
-    void updateGeometry() override;
+    bool updateGeometry() override;
 
     // -----------------------------------------------------------------------
 
diff --git a/services/surfaceflinger/EffectLayer.cpp b/services/surfaceflinger/EffectLayer.cpp
index 0cc5f33..86c6b21 100644
--- a/services/surfaceflinger/EffectLayer.cpp
+++ b/services/surfaceflinger/EffectLayer.cpp
@@ -78,28 +78,28 @@
 }
 
 bool EffectLayer::setColor(const half3& color) {
-    if (mCurrentState.color.r == color.r && mCurrentState.color.g == color.g &&
-        mCurrentState.color.b == color.b) {
+    if (mDrawingState.color.r == color.r && mDrawingState.color.g == color.g &&
+        mDrawingState.color.b == color.b) {
         return false;
     }
 
-    mCurrentState.sequence++;
-    mCurrentState.color.r = color.r;
-    mCurrentState.color.g = color.g;
-    mCurrentState.color.b = color.b;
-    mCurrentState.modified = true;
+    mDrawingState.sequence++;
+    mDrawingState.color.r = color.r;
+    mDrawingState.color.g = color.g;
+    mDrawingState.color.b = color.b;
+    mDrawingState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
 
 bool EffectLayer::setDataspace(ui::Dataspace dataspace) {
-    if (mCurrentState.dataspace == dataspace) {
+    if (mDrawingState.dataspace == dataspace) {
         return false;
     }
 
-    mCurrentState.sequence++;
-    mCurrentState.dataspace = dataspace;
-    mCurrentState.modified = true;
+    mDrawingState.sequence++;
+    mDrawingState.dataspace = dataspace;
+    mDrawingState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
diff --git a/services/surfaceflinger/FpsReporter.cpp b/services/surfaceflinger/FpsReporter.cpp
index 23db805..e12835f 100644
--- a/services/surfaceflinger/FpsReporter.cpp
+++ b/services/surfaceflinger/FpsReporter.cpp
@@ -55,7 +55,7 @@
     std::vector<std::pair<TrackedListener, sp<Layer>>> listenersAndLayersToReport;
 
     mFlinger.mCurrentState.traverse([&](Layer* layer) {
-        auto& currentState = layer->getCurrentState();
+        auto& currentState = layer->getDrawingState();
         if (currentState.metadata.has(METADATA_TASK_ID)) {
             int32_t taskId = currentState.metadata.getInt32(METADATA_TASK_ID, 0);
             if (seenTasks.count(taskId) == 0) {
@@ -100,4 +100,4 @@
     mListeners.erase(wp<IBinder>(IInterface::asBinder(listener)));
 }
 
-} // namespace android
\ No newline at end of file
+} // namespace android
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 4beb526..b819dbe 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -98,52 +98,49 @@
     if (args.flags & ISurfaceComposerClient::eSkipScreenshot)
         layerFlags |= layer_state_t::eLayerSkipScreenshot;
 
-    mCurrentState.active_legacy.w = args.w;
-    mCurrentState.active_legacy.h = args.h;
-    mCurrentState.flags = layerFlags;
-    mCurrentState.active_legacy.transform.set(0, 0);
-    mCurrentState.crop.makeInvalid();
-    mCurrentState.requestedCrop = mCurrentState.crop;
-    mCurrentState.z = 0;
-    mCurrentState.color.a = 1.0f;
-    mCurrentState.layerStack = 0;
-    mCurrentState.sequence = 0;
-    mCurrentState.requested_legacy = mCurrentState.active_legacy;
-    mCurrentState.width = UINT32_MAX;
-    mCurrentState.height = UINT32_MAX;
-    mCurrentState.transform.set(0, 0);
-    mCurrentState.frameNumber = 0;
-    mCurrentState.bufferTransform = 0;
-    mCurrentState.transformToDisplayInverse = false;
-    mCurrentState.crop.makeInvalid();
-    mCurrentState.acquireFence = sp<Fence>::make(-1);
-    mCurrentState.acquireFenceTime = std::make_shared<FenceTime>(mCurrentState.acquireFence);
-    mCurrentState.dataspace = ui::Dataspace::UNKNOWN;
-    mCurrentState.hdrMetadata.validTypes = 0;
-    mCurrentState.surfaceDamageRegion = Region::INVALID_REGION;
-    mCurrentState.cornerRadius = 0.0f;
-    mCurrentState.backgroundBlurRadius = 0;
-    mCurrentState.api = -1;
-    mCurrentState.hasColorTransform = false;
-    mCurrentState.colorSpaceAgnostic = false;
-    mCurrentState.frameRateSelectionPriority = PRIORITY_UNSET;
-    mCurrentState.metadata = args.metadata;
-    mCurrentState.shadowRadius = 0.f;
-    mCurrentState.fixedTransformHint = ui::Transform::ROT_INVALID;
-    mCurrentState.frameTimelineInfo = {};
-    mCurrentState.postTime = -1;
-    mCurrentState.destinationFrame.makeInvalid();
+    mDrawingState.active_legacy.w = args.w;
+    mDrawingState.active_legacy.h = args.h;
+    mDrawingState.flags = layerFlags;
+    mDrawingState.active_legacy.transform.set(0, 0);
+    mDrawingState.crop.makeInvalid();
+    mDrawingState.requestedCrop = mDrawingState.crop;
+    mDrawingState.z = 0;
+    mDrawingState.color.a = 1.0f;
+    mDrawingState.layerStack = 0;
+    mDrawingState.sequence = 0;
+    mDrawingState.requested_legacy = mDrawingState.active_legacy;
+    mDrawingState.width = UINT32_MAX;
+    mDrawingState.height = UINT32_MAX;
+    mDrawingState.transform.set(0, 0);
+    mDrawingState.frameNumber = 0;
+    mDrawingState.bufferTransform = 0;
+    mDrawingState.transformToDisplayInverse = false;
+    mDrawingState.crop.makeInvalid();
+    mDrawingState.acquireFence = sp<Fence>::make(-1);
+    mDrawingState.acquireFenceTime = std::make_shared<FenceTime>(mDrawingState.acquireFence);
+    mDrawingState.dataspace = ui::Dataspace::UNKNOWN;
+    mDrawingState.hdrMetadata.validTypes = 0;
+    mDrawingState.surfaceDamageRegion = Region::INVALID_REGION;
+    mDrawingState.cornerRadius = 0.0f;
+    mDrawingState.backgroundBlurRadius = 0;
+    mDrawingState.api = -1;
+    mDrawingState.hasColorTransform = false;
+    mDrawingState.colorSpaceAgnostic = false;
+    mDrawingState.frameRateSelectionPriority = PRIORITY_UNSET;
+    mDrawingState.metadata = args.metadata;
+    mDrawingState.shadowRadius = 0.f;
+    mDrawingState.fixedTransformHint = ui::Transform::ROT_INVALID;
+    mDrawingState.frameTimelineInfo = {};
+    mDrawingState.postTime = -1;
+    mDrawingState.destinationFrame.makeInvalid();
 
     if (args.flags & ISurfaceComposerClient::eNoColorFill) {
         // Set an invalid color so there is no color fill.
-        mCurrentState.color.r = -1.0_hf;
-        mCurrentState.color.g = -1.0_hf;
-        mCurrentState.color.b = -1.0_hf;
+        mDrawingState.color.r = -1.0_hf;
+        mDrawingState.color.g = -1.0_hf;
+        mDrawingState.color.b = -1.0_hf;
     }
 
-    // drawing state & current state are identical
-    mDrawingState = mCurrentState;
-
     CompositorTiming compositorTiming;
     args.flinger->getCompositorTiming(&compositorTiming);
     mFrameEventHistory.initializeCompositorTiming(compositorTiming);
@@ -203,11 +200,11 @@
 void Layer::onLayerDisplayed(const sp<Fence>& /*releaseFence*/) {}
 
 void Layer::removeRelativeZ(const std::vector<Layer*>& layersInTree) {
-    if (mCurrentState.zOrderRelativeOf == nullptr) {
+    if (mDrawingState.zOrderRelativeOf == nullptr) {
         return;
     }
 
-    sp<Layer> strongRelative = mCurrentState.zOrderRelativeOf.promote();
+    sp<Layer> strongRelative = mDrawingState.zOrderRelativeOf.promote();
     if (strongRelative == nullptr) {
         setZOrderRelativeOf(nullptr);
         return;
@@ -221,8 +218,8 @@
 }
 
 void Layer::removeFromCurrentState() {
-    if (!mRemovedFromCurrentState) {
-        mRemovedFromCurrentState = true;
+    if (!mRemovedFromDrawingState) {
+        mRemovedFromDrawingState = true;
         mFlinger->mScheduler->deregisterLayer(this);
     }
 
@@ -249,8 +246,8 @@
 }
 
 void Layer::addToCurrentState() {
-    if (mRemovedFromCurrentState) {
-        mRemovedFromCurrentState = false;
+    if (mRemovedFromDrawingState) {
+        mRemovedFromDrawingState = false;
         mFlinger->mScheduler->registerLayer(this);
     }
 
@@ -679,78 +676,6 @@
 // transaction
 // ----------------------------------------------------------------------------
 
-uint32_t Layer::doTransactionResize(uint32_t flags, State* stateToCommit) {
-    const State& s(getDrawingState());
-
-    const bool sizeChanged = (stateToCommit->requested_legacy.w != s.requested_legacy.w) ||
-            (stateToCommit->requested_legacy.h != s.requested_legacy.h);
-
-    if (sizeChanged) {
-        // the size changed, we need to ask our client to request a new buffer
-        ALOGD_IF(DEBUG_RESIZE,
-                 "doTransaction: geometry (layer=%p '%s'), tr=%02x, scalingMode=%d\n"
-                 "  current={ active   ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
-                 "            requested={ wh={%4u,%4u} }}\n"
-                 "  drawing={ active   ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
-                 "            requested={ wh={%4u,%4u} }}\n",
-                 this, getName().c_str(), getBufferTransform(), getEffectiveScalingMode(),
-                 stateToCommit->active_legacy.w, stateToCommit->active_legacy.h,
-                 stateToCommit->crop.left, stateToCommit->crop.top, stateToCommit->crop.right,
-                 stateToCommit->crop.bottom, stateToCommit->crop.getWidth(),
-                 stateToCommit->crop.getHeight(), stateToCommit->requested_legacy.w,
-                 stateToCommit->requested_legacy.h, s.active_legacy.w, s.active_legacy.h,
-                 s.crop.left, s.crop.top, s.crop.right, s.crop.bottom, s.crop.getWidth(),
-                 s.crop.getHeight(), s.requested_legacy.w, s.requested_legacy.h);
-    }
-
-    // Don't let Layer::doTransaction update the drawing state
-    // if we have a pending resize, unless we are in fixed-size mode.
-    // the drawing state will be updated only once we receive a buffer
-    // with the correct size.
-    //
-    // In particular, we want to make sure the clip (which is part
-    // of the geometry state) is latched together with the size but is
-    // latched immediately when no resizing is involved.
-    //
-    // If a sideband stream is attached, however, we want to skip this
-    // optimization so that transactions aren't missed when a buffer
-    // never arrives
-    //
-    // In the case that we don't have a buffer we ignore other factors
-    // and avoid entering the resizePending state. At a high level the
-    // resizePending state is to avoid applying the state of the new buffer
-    // to the old buffer. However in the state where we don't have an old buffer
-    // there is no such concern but we may still be being used as a parent layer.
-    const bool resizePending =
-            ((stateToCommit->requested_legacy.w != stateToCommit->active_legacy.w) ||
-             (stateToCommit->requested_legacy.h != stateToCommit->active_legacy.h)) &&
-            (getBuffer() != nullptr);
-    if (!isFixedSize()) {
-        if (resizePending && mSidebandStream == nullptr) {
-            flags |= eDontUpdateGeometryState;
-        }
-    }
-
-    // Here we apply various requested geometry states, depending on our
-    // latching configuration. See Layer.h for a detailed discussion of
-    // how geometry latching is controlled.
-    if (!(flags & eDontUpdateGeometryState)) {
-        State& editCurrentState(getCurrentState());
-
-        // There is an awkward asymmetry in the handling of the crop states in the position
-        // states, as can be seen below. Largely this arises from position and transform
-        // being stored in the same data structure while having different latching rules.
-        // b/38182305
-        //
-        // Careful that "stateToCommit" and editCurrentState may not begin as equivalent due to
-        // applyPendingStates in the presence of deferred transactions.
-        editCurrentState.active_legacy = editCurrentState.requested_legacy;
-        stateToCommit->active_legacy = stateToCommit->requested_legacy;
-    }
-
-    return flags;
-}
-
 uint32_t Layer::doTransaction(uint32_t flags) {
     ATRACE_CALL();
 
@@ -760,77 +685,37 @@
     }
 
     // TODO: This is unfortunate.
-    mCurrentStateModified = mCurrentState.modified;
-    mCurrentState.modified = false;
-
-    flags = doTransactionResize(flags, &mCurrentState);
+    mDrawingStateModified = mDrawingState.modified;
+    mDrawingState.modified = false;
 
     const State& s(getDrawingState());
-    State& c(getCurrentState());
 
-    // Translates dest frame into scale and position updates. This helps align geometry calculations
-    // for BufferStateLayer with other layers. This should ideally happen in the client once client
-    // has the display orientation details from WM.
-    updateGeometry();
-
-    if (c.width != s.width || c.height != s.height || !(c.transform == s.transform)) {
+    if (updateGeometry()) {
         // invalidate and recompute the visible regions if needed
         flags |= Layer::eVisibleRegion;
     }
 
-    if (c.sequence != s.sequence) {
+    if (s.sequence != mLastCommittedTxSequence) {
         // invalidate and recompute the visible regions if needed
+         mLastCommittedTxSequence = s.sequence;
         flags |= eVisibleRegion;
         this->contentDirty = true;
 
         // we may use linear filtering, if the matrix scales us
-        mNeedsFiltering = getActiveTransform(c).needsBilinearFiltering();
+        mNeedsFiltering = getActiveTransform(s).needsBilinearFiltering();
     }
 
-    if (mCurrentState.inputInfoChanged) {
+    if (mDrawingState.inputInfoChanged) {
         flags |= eInputInfoChanged;
-        mCurrentState.inputInfoChanged = false;
+        mDrawingState.inputInfoChanged = false;
     }
 
-    // Add the callbacks from the drawing state into the current state. This is so when the current
-    // state gets copied to drawing, we don't lose the callback handles that are still in drawing.
-    for (auto& handle : s.callbackHandles) {
-        c.callbackHandles.push_back(handle);
-    }
-
-    // Allow BufferStateLayer to release any unlatched buffers in drawing state.
-    bufferMayChange(c.buffer->getBuffer());
-
-    // Commit the transaction
-    commitTransaction(c);
-    mCurrentState.callbackHandles = {};
+    commitTransaction(mDrawingState);
 
     return flags;
 }
 
-void Layer::commitTransaction(State& stateToCommit) {
-    if (auto& bufferSurfaceFrame = mDrawingState.bufferSurfaceFrameTX;
-        ((mDrawingState.buffer && stateToCommit.buffer &&
-          mDrawingState.buffer->getBuffer() != stateToCommit.buffer->getBuffer()) ||
-         (mDrawingState.buffer && !stateToCommit.buffer) ||
-         (!mDrawingState.buffer && stateToCommit.buffer)) &&
-        bufferSurfaceFrame != nullptr &&
-        bufferSurfaceFrame->getPresentState() != PresentState::Presented) {
-        // If the previous buffer was committed but not latched (refreshPending - happens during
-        // back to back invalidates), it gets silently dropped here. Mark the corresponding
-        // SurfaceFrame as dropped to prevent it from getting stuck in the pending classification
-        // list.
-        addSurfaceFrameDroppedForBuffer(bufferSurfaceFrame);
-    }
-    const bool frameRateVoteChanged =
-            mDrawingState.frameRateForLayerTree != stateToCommit.frameRateForLayerTree;
-    mDrawingState = stateToCommit;
-
-    if (frameRateVoteChanged) {
-        mFlinger->mScheduler->recordLayerHistory(this, systemTime(),
-                                                 LayerHistory::LayerUpdateType::SetFrameRate);
-    }
-
+void Layer::commitTransaction(State&) {
     // Set the present state for all bufferlessSurfaceFramesTX to Presented. The
     // bufferSurfaceFrameTX will be presented in latchBuffer.
     for (auto& [token, surfaceFrame] : mDrawingState.bufferlessSurfaceFramesTX) {
@@ -841,9 +726,7 @@
             mFlinger->mFrameTimeline->addSurfaceFrame(surfaceFrame);
         }
     }
-    // Clear the surfaceFrames from the old state now that it has been copied into DrawingState.
-    stateToCommit.bufferSurfaceFrameTX.reset();
-    stateToCommit.bufferlessSurfaceFramesTX.clear();
+    mDrawingState.bufferlessSurfaceFramesTX.clear();
 }
 
 uint32_t Layer::getTransactionFlags(uint32_t flags) {
@@ -857,20 +740,11 @@
 }
 
 bool Layer::setPosition(float x, float y) {
-    if (mCurrentState.transform.tx() == x && mCurrentState.transform.ty() == y) return false;
-    mCurrentState.sequence++;
+    if (mDrawingState.transform.tx() == x && mDrawingState.transform.ty() == y) return false;
+    mDrawingState.sequence++;
+    mDrawingState.transform.set(x, y);
 
-    // We update the requested and active position simultaneously because
-    // we want to apply the position portion of the transform matrix immediately,
-    // but still delay scaling when resizing a SCALING_MODE_FREEZE layer.
-    mCurrentState.transform.set(x, y);
-    // Here we directly update the active state
-    // unlike other setters, because we store it within
-    // the transform, but use different latching rules.
-    // b/38182305
-    mCurrentState.transform.set(x, y);
-
-    mCurrentState.modified = true;
+    mDrawingState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
@@ -903,14 +777,14 @@
 }
 
 bool Layer::setLayer(int32_t z) {
-    if (mCurrentState.z == z && !usingRelativeZ(LayerVector::StateSet::Current)) return false;
-    mCurrentState.sequence++;
-    mCurrentState.z = z;
-    mCurrentState.modified = true;
+    if (mDrawingState.z == z && !usingRelativeZ(LayerVector::StateSet::Current)) return false;
+    mDrawingState.sequence++;
+    mDrawingState.z = z;
+    mDrawingState.modified = true;
 
     // Discard all relative layering.
-    if (mCurrentState.zOrderRelativeOf != nullptr) {
-        sp<Layer> strongRelative = mCurrentState.zOrderRelativeOf.promote();
+    if (mDrawingState.zOrderRelativeOf != nullptr) {
+        sp<Layer> strongRelative = mDrawingState.zOrderRelativeOf.promote();
         if (strongRelative != nullptr) {
             strongRelative->removeZOrderRelative(this);
         }
@@ -921,24 +795,24 @@
 }
 
 void Layer::removeZOrderRelative(const wp<Layer>& relative) {
-    mCurrentState.zOrderRelatives.remove(relative);
-    mCurrentState.sequence++;
-    mCurrentState.modified = true;
+    mDrawingState.zOrderRelatives.remove(relative);
+    mDrawingState.sequence++;
+    mDrawingState.modified = true;
     setTransactionFlags(eTransactionNeeded);
 }
 
 void Layer::addZOrderRelative(const wp<Layer>& relative) {
-    mCurrentState.zOrderRelatives.add(relative);
-    mCurrentState.modified = true;
-    mCurrentState.sequence++;
+    mDrawingState.zOrderRelatives.add(relative);
+    mDrawingState.modified = true;
+    mDrawingState.sequence++;
     setTransactionFlags(eTransactionNeeded);
 }
 
 void Layer::setZOrderRelativeOf(const wp<Layer>& relativeOf) {
-    mCurrentState.zOrderRelativeOf = relativeOf;
-    mCurrentState.sequence++;
-    mCurrentState.modified = true;
-    mCurrentState.isRelativeOf = relativeOf != nullptr;
+    mDrawingState.zOrderRelativeOf = relativeOf;
+    mDrawingState.sequence++;
+    mDrawingState.modified = true;
+    mDrawingState.isRelativeOf = relativeOf != nullptr;
 
     setTransactionFlags(eTransactionNeeded);
 }
@@ -953,16 +827,16 @@
         return false;
     }
 
-    if (mCurrentState.z == relativeZ && usingRelativeZ(LayerVector::StateSet::Current) &&
-        mCurrentState.zOrderRelativeOf == relative) {
+    if (mDrawingState.z == relativeZ && usingRelativeZ(LayerVector::StateSet::Current) &&
+        mDrawingState.zOrderRelativeOf == relative) {
         return false;
     }
 
-    mCurrentState.sequence++;
-    mCurrentState.modified = true;
-    mCurrentState.z = relativeZ;
+    mDrawingState.sequence++;
+    mDrawingState.modified = true;
+    mDrawingState.z = relativeZ;
 
-    auto oldZOrderRelativeOf = mCurrentState.zOrderRelativeOf.promote();
+    auto oldZOrderRelativeOf = mDrawingState.zOrderRelativeOf.promote();
     if (oldZOrderRelativeOf != nullptr) {
         oldZOrderRelativeOf->removeZOrderRelative(this);
     }
@@ -975,82 +849,82 @@
 }
 
 bool Layer::setSize(uint32_t w, uint32_t h) {
-    if (mCurrentState.requested_legacy.w == w && mCurrentState.requested_legacy.h == h)
+    if (mDrawingState.requested_legacy.w == w && mDrawingState.requested_legacy.h == h)
         return false;
-    mCurrentState.requested_legacy.w = w;
-    mCurrentState.requested_legacy.h = h;
-    mCurrentState.modified = true;
+    mDrawingState.requested_legacy.w = w;
+    mDrawingState.requested_legacy.h = h;
+    mDrawingState.modified = true;
     setTransactionFlags(eTransactionNeeded);
 
     // record the new size, from this point on, when the client request
     // a buffer, it'll get the new size.
-    setDefaultBufferSize(mCurrentState.requested_legacy.w, mCurrentState.requested_legacy.h);
+    setDefaultBufferSize(mDrawingState.requested_legacy.w, mDrawingState.requested_legacy.h);
     return true;
 }
 
 bool Layer::setAlpha(float alpha) {
-    if (mCurrentState.color.a == alpha) return false;
-    mCurrentState.sequence++;
-    mCurrentState.color.a = alpha;
-    mCurrentState.modified = true;
+    if (mDrawingState.color.a == alpha) return false;
+    mDrawingState.sequence++;
+    mDrawingState.color.a = alpha;
+    mDrawingState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
 
 bool Layer::setBackgroundColor(const half3& color, float alpha, ui::Dataspace dataspace) {
-    if (!mCurrentState.bgColorLayer && alpha == 0) {
+    if (!mDrawingState.bgColorLayer && alpha == 0) {
         return false;
     }
-    mCurrentState.sequence++;
-    mCurrentState.modified = true;
+    mDrawingState.sequence++;
+    mDrawingState.modified = true;
     setTransactionFlags(eTransactionNeeded);
 
-    if (!mCurrentState.bgColorLayer && alpha != 0) {
+    if (!mDrawingState.bgColorLayer && alpha != 0) {
         // create background color layer if one does not yet exist
         uint32_t flags = ISurfaceComposerClient::eFXSurfaceEffect;
         std::string name = mName + "BackgroundColorLayer";
-        mCurrentState.bgColorLayer = mFlinger->getFactory().createEffectLayer(
+        mDrawingState.bgColorLayer = mFlinger->getFactory().createEffectLayer(
                 LayerCreationArgs(mFlinger.get(), nullptr, std::move(name), 0, 0, flags,
                                   LayerMetadata()));
 
         // add to child list
-        addChild(mCurrentState.bgColorLayer);
+        addChild(mDrawingState.bgColorLayer);
         mFlinger->mLayersAdded = true;
         // set up SF to handle added color layer
         if (isRemovedFromCurrentState()) {
-            mCurrentState.bgColorLayer->onRemovedFromCurrentState();
+            mDrawingState.bgColorLayer->onRemovedFromCurrentState();
         }
         mFlinger->setTransactionFlags(eTransactionNeeded);
-    } else if (mCurrentState.bgColorLayer && alpha == 0) {
-        mCurrentState.bgColorLayer->reparent(nullptr);
-        mCurrentState.bgColorLayer = nullptr;
+    } else if (mDrawingState.bgColorLayer && alpha == 0) {
+        mDrawingState.bgColorLayer->reparent(nullptr);
+        mDrawingState.bgColorLayer = nullptr;
         return true;
     }
 
-    mCurrentState.bgColorLayer->setColor(color);
-    mCurrentState.bgColorLayer->setLayer(std::numeric_limits<int32_t>::min());
-    mCurrentState.bgColorLayer->setAlpha(alpha);
-    mCurrentState.bgColorLayer->setDataspace(dataspace);
+    mDrawingState.bgColorLayer->setColor(color);
+    mDrawingState.bgColorLayer->setLayer(std::numeric_limits<int32_t>::min());
+    mDrawingState.bgColorLayer->setAlpha(alpha);
+    mDrawingState.bgColorLayer->setDataspace(dataspace);
 
     return true;
 }
 
 bool Layer::setCornerRadius(float cornerRadius) {
-    if (mCurrentState.cornerRadius == cornerRadius) return false;
+    if (mDrawingState.cornerRadius == cornerRadius) return false;
 
-    mCurrentState.sequence++;
-    mCurrentState.cornerRadius = cornerRadius;
-    mCurrentState.modified = true;
+    mDrawingState.sequence++;
+    mDrawingState.cornerRadius = cornerRadius;
+    mDrawingState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
 
 bool Layer::setBackgroundBlurRadius(int backgroundBlurRadius) {
-    if (mCurrentState.backgroundBlurRadius == backgroundBlurRadius) return false;
+    if (mDrawingState.backgroundBlurRadius == backgroundBlurRadius) return false;
 
-    mCurrentState.sequence++;
-    mCurrentState.backgroundBlurRadius = backgroundBlurRadius;
-    mCurrentState.modified = true;
+    mDrawingState.sequence++;
+    mDrawingState.backgroundBlurRadius = backgroundBlurRadius;
+    mDrawingState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
@@ -1065,81 +939,82 @@
               "ROTATE_SURFACE_FLINGER ignored");
         return false;
     }
-    mCurrentState.sequence++;
-    mCurrentState.transform.set(matrix.dsdx, matrix.dtdy, matrix.dtdx, matrix.dsdy);
-    mCurrentState.modified = true;
+    mDrawingState.sequence++;
+    mDrawingState.transform.set(matrix.dsdx, matrix.dtdy, matrix.dtdx, matrix.dsdy);
+    mDrawingState.modified = true;
+
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
 
 bool Layer::setTransparentRegionHint(const Region& transparent) {
-    mCurrentState.requestedTransparentRegion_legacy = transparent;
-    mCurrentState.modified = true;
+    mDrawingState.requestedTransparentRegion_legacy = transparent;
+    mDrawingState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
 
 bool Layer::setBlurRegions(const std::vector<BlurRegion>& blurRegions) {
-    mCurrentState.sequence++;
-    mCurrentState.blurRegions = blurRegions;
-    mCurrentState.modified = true;
+    mDrawingState.sequence++;
+    mDrawingState.blurRegions = blurRegions;
+    mDrawingState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
 
 bool Layer::setFlags(uint32_t flags, uint32_t mask) {
-    const uint32_t newFlags = (mCurrentState.flags & ~mask) | (flags & mask);
-    if (mCurrentState.flags == newFlags) return false;
-    mCurrentState.sequence++;
-    mCurrentState.flags = newFlags;
-    mCurrentState.modified = true;
+    const uint32_t newFlags = (mDrawingState.flags & ~mask) | (flags & mask);
+    if (mDrawingState.flags == newFlags) return false;
+    mDrawingState.sequence++;
+    mDrawingState.flags = newFlags;
+    mDrawingState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
 
 bool Layer::setCrop(const Rect& crop) {
-    if (mCurrentState.requestedCrop == crop) return false;
-    mCurrentState.sequence++;
-    mCurrentState.requestedCrop = crop;
-    mCurrentState.crop = crop;
+    if (mDrawingState.requestedCrop == crop) return false;
+    mDrawingState.sequence++;
+    mDrawingState.requestedCrop = crop;
+    mDrawingState.crop = crop;
 
-    mCurrentState.modified = true;
+    mDrawingState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
 
 bool Layer::setMetadata(const LayerMetadata& data) {
-    if (!mCurrentState.metadata.merge(data, true /* eraseEmpty */)) return false;
-    mCurrentState.modified = true;
+    if (!mDrawingState.metadata.merge(data, true /* eraseEmpty */)) return false;
+    mDrawingState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
 
 bool Layer::setLayerStack(uint32_t layerStack) {
-    if (mCurrentState.layerStack == layerStack) return false;
-    mCurrentState.sequence++;
-    mCurrentState.layerStack = layerStack;
-    mCurrentState.modified = true;
+    if (mDrawingState.layerStack == layerStack) return false;
+    mDrawingState.sequence++;
+    mDrawingState.layerStack = layerStack;
+    mDrawingState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
 
 bool Layer::setColorSpaceAgnostic(const bool agnostic) {
-    if (mCurrentState.colorSpaceAgnostic == agnostic) {
+    if (mDrawingState.colorSpaceAgnostic == agnostic) {
         return false;
     }
-    mCurrentState.sequence++;
-    mCurrentState.colorSpaceAgnostic = agnostic;
-    mCurrentState.modified = true;
+    mDrawingState.sequence++;
+    mDrawingState.colorSpaceAgnostic = agnostic;
+    mDrawingState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
 
 bool Layer::setFrameRateSelectionPriority(int32_t priority) {
-    if (mCurrentState.frameRateSelectionPriority == priority) return false;
-    mCurrentState.frameRateSelectionPriority = priority;
-    mCurrentState.sequence++;
-    mCurrentState.modified = true;
+    if (mDrawingState.frameRateSelectionPriority == priority) return false;
+    mDrawingState.frameRateSelectionPriority = priority;
+    mDrawingState.sequence++;
+    mDrawingState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
@@ -1171,25 +1046,25 @@
 }
 
 bool Layer::setShadowRadius(float shadowRadius) {
-    if (mCurrentState.shadowRadius == shadowRadius) {
+    if (mDrawingState.shadowRadius == shadowRadius) {
         return false;
     }
 
-    mCurrentState.sequence++;
-    mCurrentState.shadowRadius = shadowRadius;
-    mCurrentState.modified = true;
+    mDrawingState.sequence++;
+    mDrawingState.shadowRadius = shadowRadius;
+    mDrawingState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
 
 bool Layer::setFixedTransformHint(ui::Transform::RotationFlags fixedTransformHint) {
-    if (mCurrentState.fixedTransformHint == fixedTransformHint) {
+    if (mDrawingState.fixedTransformHint == fixedTransformHint) {
         return false;
     }
 
-    mCurrentState.sequence++;
-    mCurrentState.fixedTransformHint = fixedTransformHint;
-    mCurrentState.modified = true;
+    mDrawingState.sequence++;
+    mDrawingState.fixedTransformHint = fixedTransformHint;
+    mDrawingState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
@@ -1197,12 +1072,12 @@
 bool Layer::setStretchEffect(const StretchEffect& effect) {
     StretchEffect temp = effect;
     temp.sanitize();
-    if (mCurrentState.stretchEffect == temp) {
+    if (mDrawingState.stretchEffect == temp) {
         return false;
     }
-    mCurrentState.sequence++;
-    mCurrentState.stretchEffect = temp;
-    mCurrentState.modified = true;
+    mDrawingState.sequence++;
+    mDrawingState.stretchEffect = temp;
+    mDrawingState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
@@ -1239,12 +1114,12 @@
     int layersWithVote = 0;
     traverseTree([&layersWithVote](Layer* layer) {
         const auto layerVotedWithDefaultCompatibility =
-                layer->mCurrentState.frameRate.rate.isValid() &&
-                layer->mCurrentState.frameRate.type == FrameRateCompatibility::Default;
+                layer->mDrawingState.frameRate.rate.isValid() &&
+                layer->mDrawingState.frameRate.type == FrameRateCompatibility::Default;
         const auto layerVotedWithNoVote =
-                layer->mCurrentState.frameRate.type == FrameRateCompatibility::NoVote;
+                layer->mDrawingState.frameRate.type == FrameRateCompatibility::NoVote;
         const auto layerVotedWithExactCompatibility =
-                layer->mCurrentState.frameRate.type == FrameRateCompatibility::Exact;
+                layer->mDrawingState.frameRate.type == FrameRateCompatibility::Exact;
 
         // We do not count layers that are ExactOrMultiple for the same reason
         // we are allowing touch boost for those layers. See
@@ -1258,6 +1133,7 @@
     // Now we can update the tree frame rate vote for each layer in the tree
     const bool treeHasFrameRateVote = layersWithVote > 0;
     bool transactionNeeded = false;
+
     traverseTree([treeHasFrameRateVote, &transactionNeeded](Layer* layer) {
         transactionNeeded = layer->updateFrameRateForLayerTree(treeHasFrameRateVote);
     });
@@ -1271,13 +1147,13 @@
     if (!mFlinger->useFrameRateApi) {
         return false;
     }
-    if (mCurrentState.frameRate == frameRate) {
+    if (mDrawingState.frameRate == frameRate) {
         return false;
     }
 
-    mCurrentState.sequence++;
-    mCurrentState.frameRate = frameRate;
-    mCurrentState.modified = true;
+    mDrawingState.sequence++;
+    mDrawingState.frameRate = frameRate;
+    mDrawingState.modified = true;
 
     updateTreeHasFrameRateVote();
 
@@ -1287,33 +1163,33 @@
 
 void Layer::setFrameTimelineVsyncForBufferTransaction(const FrameTimelineInfo& info,
                                                       nsecs_t postTime) {
-    mCurrentState.postTime = postTime;
+    mDrawingState.postTime = postTime;
 
     // Check if one of the bufferlessSurfaceFramesTX contains the same vsyncId. This can happen if
     // there are two transactions with the same token, the first one without a buffer and the
     // second one with a buffer. We promote the bufferlessSurfaceFrame to a bufferSurfaceFrameTX
     // in that case.
-    auto it = mCurrentState.bufferlessSurfaceFramesTX.find(info.vsyncId);
-    if (it != mCurrentState.bufferlessSurfaceFramesTX.end()) {
+    auto it = mDrawingState.bufferlessSurfaceFramesTX.find(info.vsyncId);
+    if (it != mDrawingState.bufferlessSurfaceFramesTX.end()) {
         // Promote the bufferlessSurfaceFrame to a bufferSurfaceFrameTX
-        mCurrentState.bufferSurfaceFrameTX = it->second;
-        mCurrentState.bufferlessSurfaceFramesTX.erase(it);
-        mCurrentState.bufferSurfaceFrameTX->promoteToBuffer();
-        mCurrentState.bufferSurfaceFrameTX->setActualQueueTime(postTime);
+        mDrawingState.bufferSurfaceFrameTX = it->second;
+        mDrawingState.bufferlessSurfaceFramesTX.erase(it);
+        mDrawingState.bufferSurfaceFrameTX->promoteToBuffer();
+        mDrawingState.bufferSurfaceFrameTX->setActualQueueTime(postTime);
     } else {
-        mCurrentState.bufferSurfaceFrameTX =
+        mDrawingState.bufferSurfaceFrameTX =
                 createSurfaceFrameForBuffer(info, postTime, mTransactionName);
     }
 }
 
 void Layer::setFrameTimelineVsyncForBufferlessTransaction(const FrameTimelineInfo& info,
                                                           nsecs_t postTime) {
-    mCurrentState.frameTimelineInfo = info;
-    mCurrentState.postTime = postTime;
-    mCurrentState.modified = true;
+    mDrawingState.frameTimelineInfo = info;
+    mDrawingState.postTime = postTime;
+    mDrawingState.modified = true;
     setTransactionFlags(eTransactionNeeded);
 
-    if (const auto& bufferSurfaceFrameTX = mCurrentState.bufferSurfaceFrameTX;
+    if (const auto& bufferSurfaceFrameTX = mDrawingState.bufferSurfaceFrameTX;
         bufferSurfaceFrameTX != nullptr) {
         if (bufferSurfaceFrameTX->getToken() == info.vsyncId) {
             // BufferSurfaceFrame takes precedence over BufferlessSurfaceFrame. If the same token is
@@ -1324,10 +1200,10 @@
     // For Transactions without a buffer, we create only one SurfaceFrame per vsyncId. If multiple
     // transactions use the same vsyncId, we just treat them as one SurfaceFrame (unless they are
     // targeting different vsyncs).
-    auto it = mCurrentState.bufferlessSurfaceFramesTX.find(info.vsyncId);
-    if (it == mCurrentState.bufferlessSurfaceFramesTX.end()) {
+    auto it = mDrawingState.bufferlessSurfaceFramesTX.find(info.vsyncId);
+    if (it == mDrawingState.bufferlessSurfaceFramesTX.end()) {
         auto surfaceFrame = createSurfaceFrameForTransaction(info, postTime);
-        mCurrentState.bufferlessSurfaceFramesTX[info.vsyncId] = surfaceFrame;
+        mDrawingState.bufferlessSurfaceFramesTX[info.vsyncId] = surfaceFrame;
     } else {
         if (it->second->getPresentState() == PresentState::Presented) {
             // If the SurfaceFrame was already presented, its safe to overwrite it since it must
@@ -1389,36 +1265,41 @@
 }
 
 bool Layer::updateFrameRateForLayerTree(bool treeHasFrameRateVote) {
-    const auto updateCurrentState = [&](FrameRate frameRate) {
-        if (mCurrentState.frameRateForLayerTree == frameRate) {
+    const auto updateDrawingState = [&](FrameRate frameRate) {
+        if (mDrawingState.frameRateForLayerTree == frameRate) {
             return false;
         }
-        mCurrentState.frameRateForLayerTree = frameRate;
-        mCurrentState.sequence++;
-        mCurrentState.modified = true;
+
+        mDrawingState.frameRateForLayerTree = frameRate;
+        mDrawingState.sequence++;
+        mDrawingState.modified = true;
         setTransactionFlags(eTransactionNeeded);
+
+        mFlinger->mScheduler->recordLayerHistory(this, systemTime(),
+                                                 LayerHistory::LayerUpdateType::SetFrameRate);
+
         return true;
     };
 
-    const auto frameRate = mCurrentState.frameRate;
+    const auto frameRate = mDrawingState.frameRate;
     if (frameRate.rate.isValid() || frameRate.type == FrameRateCompatibility::NoVote) {
-        return updateCurrentState(frameRate);
+        return updateDrawingState(frameRate);
     }
 
     // This layer doesn't have a frame rate. Check if its ancestors have a vote
     for (sp<Layer> parent = getParent(); parent; parent = parent->getParent()) {
-        if (parent->mCurrentState.frameRate.rate.isValid()) {
-            return updateCurrentState(parent->mCurrentState.frameRate);
+        if (parent->mDrawingState.frameRate.rate.isValid()) {
+            return updateDrawingState(parent->mDrawingState.frameRate);
         }
     }
 
     // This layer and its ancestors don't have a frame rate. If one of successors
     // has a vote, return a NoVote for successors to set the vote
     if (treeHasFrameRateVote) {
-        return updateCurrentState(FrameRate(Fps(0.0f), FrameRateCompatibility::NoVote));
+        return updateDrawingState(FrameRate(Fps(0.0f), FrameRateCompatibility::NoVote));
     }
 
-    return updateCurrentState(frameRate);
+    return updateDrawingState(frameRate);
 }
 
 Layer::FrameRate Layer::getFrameRateForLayerTree() const {
@@ -1670,7 +1551,7 @@
 
 void Layer::setGameModeForTree(int parentGameMode) {
     int gameMode = parentGameMode;
-    auto& currentState = getCurrentState();
+    auto& currentState = getDrawingState();
     if (currentState.metadata.has(METADATA_GAME_MODE)) {
         gameMode = currentState.metadata.getInt32(METADATA_GAME_MODE, 0);
     }
@@ -1749,13 +1630,13 @@
 bool Layer::setColorTransform(const mat4& matrix) {
     static const mat4 identityMatrix = mat4();
 
-    if (mCurrentState.colorTransform == matrix) {
+    if (mDrawingState.colorTransform == matrix) {
         return false;
     }
-    ++mCurrentState.sequence;
-    mCurrentState.colorTransform = matrix;
-    mCurrentState.hasColorTransform = matrix != identityMatrix;
-    mCurrentState.modified = true;
+    ++mDrawingState.sequence;
+    mDrawingState.colorTransform = matrix;
+    mDrawingState.hasColorTransform = matrix != identityMatrix;
+    mDrawingState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
@@ -1787,15 +1668,13 @@
     mCurrentParent = layer;
 }
 
-int32_t Layer::getZ(LayerVector::StateSet stateSet) const {
-    const bool useDrawing = stateSet == LayerVector::StateSet::Drawing;
-    const State& state = useDrawing ? mDrawingState : mCurrentState;
-    return state.z;
+int32_t Layer::getZ(LayerVector::StateSet) const {
+    return mDrawingState.z;
 }
 
 bool Layer::usingRelativeZ(LayerVector::StateSet stateSet) const {
     const bool useDrawing = stateSet == LayerVector::StateSet::Drawing;
-    const State& state = useDrawing ? mDrawingState : mCurrentState;
+    const State& state = useDrawing ? mDrawingState : mDrawingState;
     return state.isRelativeOf;
 }
 
@@ -1805,7 +1684,7 @@
                         "makeTraversalList received invalid stateSet");
     const bool useDrawing = stateSet == LayerVector::StateSet::Drawing;
     const LayerVector& children = useDrawing ? mDrawingChildren : mCurrentChildren;
-    const State& state = useDrawing ? mDrawingState : mCurrentState;
+    const State& state = useDrawing ? mDrawingState : mDrawingState;
 
     if (state.zOrderRelatives.size() == 0) {
         *outSkipRelativeZUsers = true;
@@ -1904,7 +1783,7 @@
 void Layer::traverse(LayerVector::StateSet state, const LayerVector::Visitor& visitor) {
     visitor(this);
     const LayerVector& children =
-            state == LayerVector::StateSet::Drawing ? mDrawingChildren : mCurrentChildren;
+          state == LayerVector::StateSet::Drawing ? mDrawingChildren : mCurrentChildren;
     for (const sp<Layer>& child : children) {
         child->traverse(state, visitor);
     }
@@ -1916,7 +1795,7 @@
                         "makeTraversalList received invalid stateSet");
     const bool useDrawing = stateSet == LayerVector::StateSet::Drawing;
     const LayerVector& children = useDrawing ? mDrawingChildren : mCurrentChildren;
-    const State& state = useDrawing ? mDrawingState : mCurrentState;
+    const State& state = useDrawing ? mDrawingState : mDrawingState;
 
     LayerVector traverse(stateSet);
     for (const wp<Layer>& weakRelative : state.zOrderRelatives) {
@@ -1929,7 +1808,7 @@
     }
 
     for (const sp<Layer>& child : children) {
-        const State& childState = useDrawing ? child->mDrawingState : child->mCurrentState;
+        const State& childState = useDrawing ? child->mDrawingState : child->mDrawingState;
         // If a layer has a relativeOf layer, only ignore if the layer it's relative to is a
         // descendent of the top most parent of the tree. If it's not a descendent, then just add
         // the child here since it won't be added later as a relative.
@@ -1997,7 +1876,7 @@
 }
 
 ui::Transform::RotationFlags Layer::getFixedTransformHint() const {
-    ui::Transform::RotationFlags fixedTransformHint = mCurrentState.fixedTransformHint;
+    ui::Transform::RotationFlags fixedTransformHint = mDrawingState.fixedTransformHint;
     if (fixedTransformHint != ui::Transform::ROT_INVALID) {
         return fixedTransformHint;
     }
@@ -2109,10 +1988,10 @@
 }
 
 void Layer::setInputInfo(const InputWindowInfo& info) {
-    mCurrentState.inputInfo = info;
-    mCurrentState.touchableRegionCrop = extractLayerFromBinder(info.touchableRegionCropHandle);
-    mCurrentState.modified = true;
-    mCurrentState.inputInfoChanged = true;
+    mDrawingState.inputInfo = info;
+    mDrawingState.touchableRegionCrop = extractLayerFromBinder(info.touchableRegionCropHandle);
+    mDrawingState.modified = true;
+    mDrawingState.inputInfoChanged = true;
     setTransactionFlags(eTransactionNeeded);
 }
 
@@ -2190,7 +2069,7 @@
                                     uint32_t traceFlags) {
     const bool useDrawing = stateSet == LayerVector::StateSet::Drawing;
     const LayerVector& children = useDrawing ? mDrawingChildren : mCurrentChildren;
-    const State& state = useDrawing ? mDrawingState : mCurrentState;
+    const State& state = useDrawing ? mDrawingState : mDrawingState;
 
     ui::Transform requestedTransform = state.transform;
 
@@ -2278,7 +2157,7 @@
 }
 
 bool Layer::isRemovedFromCurrentState() const  {
-    return mRemovedFromCurrentState;
+    return mRemovedFromDrawingState;
 }
 
 ui::Transform Layer::getInputTransform() const {
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 5669049..9b30fcb 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -1,3 +1,4 @@
+
 /*
  * Copyright (C) 2007 The Android Open Source Project
  *
@@ -732,8 +733,7 @@
     void updateTransformHint(ui::Transform::RotationFlags);
 
     inline const State& getDrawingState() const { return mDrawingState; }
-    inline const State& getCurrentState() const { return mCurrentState; }
-    inline State& getCurrentState() { return mCurrentState; }
+    inline State& getDrawingState() { return mDrawingState; }
 
     LayerDebugInfo getLayerDebugInfo(const DisplayDevice*) const;
 
@@ -884,7 +884,7 @@
     virtual bool setDestinationFrame(const Rect& /* destinationFrame */) { return false; }
     virtual std::atomic<int32_t>* getPendingBufferCounter() { return nullptr; }
     virtual std::string getPendingBufferCounterName() { return ""; }
-    virtual void updateGeometry() {}
+    virtual bool updateGeometry() { return false; }
 
 protected:
     friend class impl::SurfaceInterceptor;
@@ -902,7 +902,6 @@
             compositionengine::LayerFE::ClientCompositionTargetSettings&);
     virtual void preparePerFrameCompositionState();
     virtual void commitTransaction(State& stateToCommit);
-    virtual uint32_t doTransactionResize(uint32_t flags, Layer::State* stateToCommit);
     virtual void onSurfaceFrameCreated(const std::shared_ptr<frametimeline::SurfaceFrame>&) {}
 
     // Returns mCurrentScaling mode (originating from the
@@ -958,9 +957,11 @@
     // These are only accessed by the main thread or the tracing thread.
     State mDrawingState;
 
-    // these are protected by an external lock (mStateLock)
-    State mCurrentState;
     uint32_t mTransactionFlags{0};
+    // Updated in doTransaction, used to track the last sequence number we
+    // committed. Currently this is really only used for updating visible
+    // regions.
+    int32_t mLastCommittedTxSequence = -1;
 
     // Timestamp history for UIAutomation. Thread safe.
     FrameTracker mFrameTracker;
@@ -983,7 +984,7 @@
     // Whether filtering is needed b/c of the drawingstate
     bool mNeedsFiltering{false};
 
-    std::atomic<bool> mRemovedFromCurrentState{false};
+    std::atomic<bool> mRemovedFromDrawingState{false};
 
     // page-flip thread (currently main thread)
     bool mProtectedByApp{false}; // application requires protected path to external sink
@@ -996,9 +997,7 @@
     // This layer can be a cursor on some displays.
     bool mPotentialCursor{false};
 
-    // Child list about to be committed/used for editing.
-    LayerVector mCurrentChildren{LayerVector::StateSet::Current};
-    // Child list used for rendering.
+    LayerVector mCurrentChildren{LayerVector::StateSet::Drawing};
     LayerVector mDrawingChildren{LayerVector::StateSet::Drawing};
 
     wp<Layer> mCurrentParent;
@@ -1022,7 +1021,7 @@
     // Used in buffer stuffing analysis in FrameTimeline.
     nsecs_t mLastLatchTime = 0;
 
-    mutable bool mCurrentStateModified = false;
+    mutable bool mDrawingStateModified = false;
 
 private:
     virtual void setTransformHint(ui::Transform::RotationFlags) {}
diff --git a/services/surfaceflinger/LayerVector.cpp b/services/surfaceflinger/LayerVector.cpp
index 9b94920..aee820a 100644
--- a/services/surfaceflinger/LayerVector.cpp
+++ b/services/surfaceflinger/LayerVector.cpp
@@ -42,10 +42,8 @@
     const auto& l = *reinterpret_cast<const sp<Layer>*>(lhs);
     const auto& r = *reinterpret_cast<const sp<Layer>*>(rhs);
 
-    const auto& lState =
-            (mStateSet == StateSet::Current) ? l->getCurrentState() : l->getDrawingState();
-    const auto& rState =
-            (mStateSet == StateSet::Current) ? r->getCurrentState() : r->getDrawingState();
+    const auto& lState = l->getDrawingState();
+    const auto& rState = r->getDrawingState();
 
     uint32_t ls = lState.layerStack;
     uint32_t rs = rState.layerStack;
@@ -66,8 +64,7 @@
 void LayerVector::traverseInZOrder(StateSet stateSet, const Visitor& visitor) const {
     for (size_t i = 0; i < size(); i++) {
         const auto& layer = (*this)[i];
-        auto& state = (stateSet == StateSet::Current) ? layer->getCurrentState()
-                                                      : layer->getDrawingState();
+        auto& state = layer->getDrawingState();
         if (state.isRelativeOf) {
             continue;
         }
@@ -78,8 +75,7 @@
 void LayerVector::traverseInReverseZOrder(StateSet stateSet, const Visitor& visitor) const {
     for (auto i = static_cast<int64_t>(size()) - 1; i >= 0; i--) {
         const auto& layer = (*this)[i];
-        auto& state = (stateSet == StateSet::Current) ? layer->getCurrentState()
-                                                      : layer->getDrawingState();
+        auto& state = layer->getDrawingState();
         if (state.isRelativeOf) {
             continue;
         }
diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp
index a9fd16c..663e62a 100644
--- a/services/surfaceflinger/RefreshRateOverlay.cpp
+++ b/services/surfaceflinger/RefreshRateOverlay.cpp
@@ -199,10 +199,10 @@
     mLayer->setFrameRate(Layer::FrameRate(Fps(0.0f), Layer::FrameRateCompatibility::NoVote));
 
     // setting Layer's Z requires resorting layersSortedByZ
-    ssize_t idx = mFlinger.mCurrentState.layersSortedByZ.indexOf(mLayer);
+    ssize_t idx = mFlinger.mDrawingState.layersSortedByZ.indexOf(mLayer);
     if (mLayer->setLayer(INT32_MAX - 2) && idx >= 0) {
-        mFlinger.mCurrentState.layersSortedByZ.removeAt(idx);
-        mFlinger.mCurrentState.layersSortedByZ.add(mLayer);
+        mFlinger.mDrawingState.layersSortedByZ.removeAt(idx);
+        mFlinger.mDrawingState.layersSortedByZ.add(mLayer);
     }
 
     return true;
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
index 9746076..0eb16e2 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
@@ -422,7 +422,15 @@
     // actually increase the refresh rate over the normal selection.
     const RefreshRate& touchRefreshRate = getMaxRefreshRateByPolicyLocked();
 
-    bool touchBoostForExplicitExact = explicitExact == 0 || mSupportsFrameRateOverride;
+    const bool touchBoostForExplicitExact = [&] {
+        if (mSupportsFrameRateOverride) {
+            // Enable touch boost if there are other layers besides exact
+            return explicitExact + noVoteLayers != layers.size();
+        } else {
+            // Enable touch boost if there are no exact layers
+            return explicitExact == 0;
+        }
+    }();
     if (globalSignals.touch && explicitDefaultVoteLayers == 0 && touchBoostForExplicitExact &&
         bestRefreshRate->fps.lessThanWithMargin(touchRefreshRate.fps)) {
         setTouchConsidered();
@@ -859,11 +867,6 @@
         return RefreshRateConfigs::KernelIdleTimerAction::TurnOff;
     }
     if (minByPolicy == maxByPolicy) {
-        // Do not sent the call to toggle off kernel idle timer if the device min and policy min and
-        // max are all the same. This saves us extra unnecessary calls to sysprop.
-        if (deviceMin == minByPolicy) {
-            return RefreshRateConfigs::KernelIdleTimerAction::NoChange;
-        }
         return RefreshRateConfigs::KernelIdleTimerAction::TurnOff;
     }
     // Turn on the timer in all other cases.
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
index 342fde0..6cd0f42 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
@@ -318,7 +318,6 @@
     // Class to enumerate options around toggling the kernel timer on and off. We have an option
     // for no change to avoid extra calls to kernel.
     enum class KernelIdleTimerAction {
-        NoChange, // Do not change the idle timer.
         TurnOff,  // Turn off the idle timer.
         TurnOn    // Turn on the idle timer.
     };
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index 4b8cbfb..e0b3640 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -205,6 +205,10 @@
 }
 
 std::optional<Fps> Scheduler::getFrameRateOverride(uid_t uid) const {
+    if (!mRefreshRateConfigs.supportsFrameRateOverride()) {
+        return std::nullopt;
+    }
+
     std::lock_guard lock(mFrameRateOverridesMutex);
     {
         const auto iter = mFrameRateOverridesFromBackdoor.find(uid);
@@ -224,10 +228,6 @@
 }
 
 bool Scheduler::isVsyncValid(nsecs_t expectedVsyncTimestamp, uid_t uid) const {
-    if (!mRefreshRateConfigs.supportsFrameRateOverride()) {
-        return true;
-    }
-
     const auto frameRate = getFrameRateOverride(uid);
     if (!frameRate.has_value()) {
         return true;
diff --git a/services/surfaceflinger/Scheduler/VsyncConfiguration.cpp b/services/surfaceflinger/Scheduler/VsyncConfiguration.cpp
index cb57aea..43e0297 100644
--- a/services/surfaceflinger/Scheduler/VsyncConfiguration.cpp
+++ b/services/surfaceflinger/Scheduler/VsyncConfiguration.cpp
@@ -59,7 +59,7 @@
 }
 
 void VsyncConfiguration::dump(std::string& result) const {
-    const auto [early, earlyGpu, late] = getCurrentConfigs();
+    const auto [early, earlyGpu, late, hwcMinWorkDuration] = getCurrentConfigs();
     using base::StringAppendF;
     StringAppendF(&result,
                   "           app phase:    %9" PRId64 " ns\t         SF phase:    %9" PRId64
@@ -70,7 +70,8 @@
                   "     early app duration: %9lld ns\t   early SF duration: %9lld ns\n"
                   "  GL early app phase:    %9" PRId64 " ns\tGL early SF phase:    %9" PRId64
                   " ns\n"
-                  "  GL early app duration: %9lld ns\tGL early SF duration: %9lld ns\n",
+                  "  GL early app duration: %9lld ns\tGL early SF duration: %9lld ns\n"
+                  "       HWC min duration: %9lld ns\n",
                   late.appOffset, late.sfOffset,
 
                   late.appWorkDuration.count(), late.sfWorkDuration.count(),
@@ -81,7 +82,9 @@
 
                   earlyGpu.appOffset, earlyGpu.sfOffset,
 
-                  earlyGpu.appWorkDuration.count(), earlyGpu.sfWorkDuration.count());
+                  earlyGpu.appWorkDuration.count(), earlyGpu.sfWorkDuration.count(),
+
+                  hwcMinWorkDuration.count());
 }
 
 PhaseOffsets::PhaseOffsets(Fps currentRefreshRate)
@@ -103,7 +106,8 @@
                      // offset >= threshold, SF wake up (2 * vsync_duration - offset) before HW
                      // vsync.
                      getProperty("debug.sf.phase_offset_threshold_for_next_vsync_ns")
-                             .value_or(std::numeric_limits<nsecs_t>::max())) {}
+                             .value_or(std::numeric_limits<nsecs_t>::max()),
+                     getProperty("debug.sf.hwc.min.duration").value_or(0)) {}
 
 PhaseOffsets::PhaseOffsets(Fps currentFps, nsecs_t vsyncPhaseOffsetNs, nsecs_t sfVSyncPhaseOffsetNs,
                            std::optional<nsecs_t> earlySfOffsetNs,
@@ -115,7 +119,7 @@
                            std::optional<nsecs_t> highFpsEarlyGpuSfOffsetNs,
                            std::optional<nsecs_t> highFpsEarlyAppOffsetNs,
                            std::optional<nsecs_t> highFpsEarlyGpuAppOffsetNs,
-                           nsecs_t thresholdForNextVsync)
+                           nsecs_t thresholdForNextVsync, nsecs_t hwcMinWorkDuration)
       : VsyncConfiguration(currentFps),
         mVSyncPhaseOffsetNs(vsyncPhaseOffsetNs),
         mSfVSyncPhaseOffsetNs(sfVSyncPhaseOffsetNs),
@@ -129,7 +133,8 @@
         mHighFpsEarlyGpuSfOffsetNs(highFpsEarlyGpuSfOffsetNs),
         mHighFpsEarlyAppOffsetNs(highFpsEarlyAppOffsetNs),
         mHighFpsEarlyGpuAppOffsetNs(highFpsEarlyGpuAppOffsetNs),
-        mThresholdForNextVsync(thresholdForNextVsync) {}
+        mThresholdForNextVsync(thresholdForNextVsync),
+        mHwcMinWorkDuration(hwcMinWorkDuration) {}
 
 PhaseOffsets::VsyncConfigSet PhaseOffsets::constructOffsets(nsecs_t vsyncDuration) const {
     if (vsyncDuration < std::chrono::nanoseconds(15ms).count()) {
@@ -189,6 +194,7 @@
                      .sfWorkDuration = sfOffsetToDuration(lateSfOffset, vsyncDuration),
                      .appWorkDuration =
                              appOffsetToDuration(lateAppOffset, lateSfOffset, vsyncDuration)},
+            .hwcMinWorkDuration = std::chrono::nanoseconds(mHwcMinWorkDuration),
     };
 }
 
@@ -234,6 +240,7 @@
                             .appWorkDuration =
                                     appOffsetToDuration(lateAppOffset, lateSfOffset, vsyncDuration),
                     },
+            .hwcMinWorkDuration = std::chrono::nanoseconds(mHwcMinWorkDuration),
     };
 }
 
@@ -342,6 +349,7 @@
                             .sfWorkDuration = sfDuration,
                             .appWorkDuration = appDuration,
                     },
+            .hwcMinWorkDuration = std::chrono::nanoseconds(mHwcMinWorkDuration),
     };
 }
 
@@ -351,19 +359,22 @@
                      getProperty("debug.sf.early.sf.duration").value_or(mSfDuration),
                      getProperty("debug.sf.early.app.duration").value_or(mAppDuration),
                      getProperty("debug.sf.earlyGl.sf.duration").value_or(mSfDuration),
-                     getProperty("debug.sf.earlyGl.app.duration").value_or(mAppDuration)) {
+                     getProperty("debug.sf.earlyGl.app.duration").value_or(mAppDuration),
+                     getProperty("debug.sf.hwc.min.duration").value_or(0)) {
     validateSysprops();
 }
 
 WorkDuration::WorkDuration(Fps currentRefreshRate, nsecs_t sfDuration, nsecs_t appDuration,
                            nsecs_t sfEarlyDuration, nsecs_t appEarlyDuration,
-                           nsecs_t sfEarlyGpuDuration, nsecs_t appEarlyGpuDuration)
+                           nsecs_t sfEarlyGpuDuration, nsecs_t appEarlyGpuDuration,
+                           nsecs_t hwcMinWorkDuration)
       : VsyncConfiguration(currentRefreshRate),
         mSfDuration(sfDuration),
         mAppDuration(appDuration),
         mSfEarlyDuration(sfEarlyDuration),
         mAppEarlyDuration(appEarlyDuration),
         mSfEarlyGpuDuration(sfEarlyGpuDuration),
-        mAppEarlyGpuDuration(appEarlyGpuDuration) {}
+        mAppEarlyGpuDuration(appEarlyGpuDuration),
+        mHwcMinWorkDuration(hwcMinWorkDuration) {}
 
 } // namespace android::scheduler::impl
diff --git a/services/surfaceflinger/Scheduler/VsyncConfiguration.h b/services/surfaceflinger/Scheduler/VsyncConfiguration.h
index d9d206d..3e53b3f 100644
--- a/services/surfaceflinger/Scheduler/VsyncConfiguration.h
+++ b/services/surfaceflinger/Scheduler/VsyncConfiguration.h
@@ -111,7 +111,8 @@
                  nsecs_t highFpsSfVSyncPhaseOffsetNs, std::optional<nsecs_t> highFpsEarlySfOffsetNs,
                  std::optional<nsecs_t> highFpsEarlyGpuSfOffsetNs,
                  std::optional<nsecs_t> highFpsEarlyAppOffsetNs,
-                 std::optional<nsecs_t> highFpsEarlyGpuAppOffsetNs, nsecs_t thresholdForNextVsync);
+                 std::optional<nsecs_t> highFpsEarlyGpuAppOffsetNs, nsecs_t thresholdForNextVsync,
+                 nsecs_t hwcMinWorkDuration);
 
 private:
     VsyncConfiguration::VsyncConfigSet constructOffsets(nsecs_t vsyncDuration) const override;
@@ -134,6 +135,7 @@
     const std::optional<nsecs_t> mHighFpsEarlyGpuAppOffsetNs;
 
     const nsecs_t mThresholdForNextVsync;
+    const nsecs_t mHwcMinWorkDuration;
 };
 
 /*
@@ -148,7 +150,8 @@
 protected:
     // Used for unit tests
     WorkDuration(Fps currentFps, nsecs_t sfDuration, nsecs_t appDuration, nsecs_t sfEarlyDuration,
-                 nsecs_t appEarlyDuration, nsecs_t sfEarlyGpuDuration, nsecs_t appEarlyGpuDuration);
+                 nsecs_t appEarlyDuration, nsecs_t sfEarlyGpuDuration, nsecs_t appEarlyGpuDuration,
+                 nsecs_t hwcMinWorkDuration);
 
 private:
     VsyncConfiguration::VsyncConfigSet constructOffsets(nsecs_t vsyncDuration) const override;
@@ -161,6 +164,8 @@
 
     const nsecs_t mSfEarlyGpuDuration;
     const nsecs_t mAppEarlyGpuDuration;
+
+    const nsecs_t mHwcMinWorkDuration;
 };
 
 } // namespace impl
diff --git a/services/surfaceflinger/Scheduler/VsyncModulator.h b/services/surfaceflinger/Scheduler/VsyncModulator.h
index fcde279..9410768 100644
--- a/services/surfaceflinger/Scheduler/VsyncModulator.h
+++ b/services/surfaceflinger/Scheduler/VsyncModulator.h
@@ -69,9 +69,12 @@
         VsyncConfig early;    // Used for early transactions, and during refresh rate change.
         VsyncConfig earlyGpu; // Used during GPU composition.
         VsyncConfig late;     // Default.
+        std::chrono::nanoseconds hwcMinWorkDuration; // Used for calculating the
+                                                     // earliest present time
 
         bool operator==(const VsyncConfigSet& other) const {
-            return early == other.early && earlyGpu == other.earlyGpu && late == other.late;
+            return early == other.early && earlyGpu == other.earlyGpu && late == other.late &&
+                    hwcMinWorkDuration == other.hwcMinWorkDuration;
         }
 
         bool operator!=(const VsyncConfigSet& other) const { return !(*this == other); }
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 4fcec16..c6841ed 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -2066,7 +2066,9 @@
                 std::chrono::milliseconds(mDebugRegion > 1 ? mDebugRegion : 0);
     }
 
-    refreshArgs.earliestPresentTime = mScheduler->getPreviousVsyncFrom(mExpectedPresentTime);
+    const auto prevVsyncTime = mScheduler->getPreviousVsyncFrom(mExpectedPresentTime);
+    const auto hwcMinWorkDuration = mVsyncConfiguration->getCurrentConfigs().hwcMinWorkDuration;
+    refreshArgs.earliestPresentTime = prevVsyncTime - hwcMinWorkDuration;
     refreshArgs.nextInvalidateTime = mEventQueue->nextExpectedInvalidate();
 
     mGeometryInvalid = false;
@@ -3198,6 +3200,7 @@
 }
 
 void SurfaceFlinger::commitTransaction() {
+    ATRACE_CALL();
     commitTransactionLocked();
     signalSynchronousTransactions(CountDownLatch::eSyncTransaction);
     mAnimTransactionPending = false;
@@ -5247,7 +5250,7 @@
         case CAPTURE_DISPLAY:
         case SET_FRAME_TIMELINE_INFO:
         case GET_GPU_CONTEXT_PRIORITY:
-        case GET_EXTRA_BUFFER_COUNT: {
+        case GET_MAX_ACQUIRED_BUFFER_COUNT: {
             // This is not sensitive information, so should not require permission control.
             return OK;
         }
@@ -5808,8 +5811,6 @@
                 mKernelIdleTimerEnabled = true;
             }
             break;
-        case KernelIdleTimerAction::NoChange:
-            break;
     }
 }
 
@@ -6048,12 +6049,12 @@
         }
 
         if (!canCaptureBlackoutContent &&
-            parent->getCurrentState().flags & layer_state_t::eLayerSecure) {
+            parent->getDrawingState().flags & layer_state_t::eLayerSecure) {
             ALOGW("Attempting to capture secure layer: PERMISSION_DENIED");
             return PERMISSION_DENIED;
         }
 
-        Rect parentSourceBounds = parent->getCroppedBufferSize(parent->getCurrentState());
+        Rect parentSourceBounds = parent->getCroppedBufferSize(parent->getDrawingState());
         if (args.sourceCrop.width() <= 0) {
             crop.left = 0;
             crop.right = parentSourceBounds.getWidth();
@@ -6292,7 +6293,7 @@
     Region clearRegion = Region::INVALID_REGION;
     bool disableBlurs = false;
     traverseLayers([&](Layer* layer) {
-        disableBlurs |= layer->getCurrentState().sidebandStream != nullptr;
+        disableBlurs |= layer->getDrawingState().sidebandStream != nullptr;
 
         Region clip(renderArea.getBounds());
         compositionengine::LayerFE::ClientCompositionTargetSettings targetSettings{
@@ -6800,25 +6801,38 @@
     return getRenderEngine().getContextPriority();
 }
 
-int SurfaceFlinger::calculateExtraBufferCount(Fps maxSupportedRefreshRate,
-                                              std::chrono::nanoseconds presentLatency) {
-    auto pipelineDepth = presentLatency.count() / maxSupportedRefreshRate.getPeriodNsecs();
-    if (presentLatency.count() % maxSupportedRefreshRate.getPeriodNsecs()) {
+int SurfaceFlinger::calculateMaxAcquiredBufferCount(Fps refreshRate,
+                                                    std::chrono::nanoseconds presentLatency) {
+    auto pipelineDepth = presentLatency.count() / refreshRate.getPeriodNsecs();
+    if (presentLatency.count() % refreshRate.getPeriodNsecs()) {
         pipelineDepth++;
     }
-    return std::max(0ll, pipelineDepth - 2);
+    return std::max(1ll, pipelineDepth - 1);
 }
 
-status_t SurfaceFlinger::getExtraBufferCount(int* extraBuffers) const {
+status_t SurfaceFlinger::getMaxAcquiredBufferCount(int* buffers) const {
     const auto maxSupportedRefreshRate = mRefreshRateConfigs->getSupportedRefreshRateRange().max;
-    const auto vsyncConfig =
-            mVsyncConfiguration->getConfigsForRefreshRate(maxSupportedRefreshRate).late;
-    const auto presentLatency = vsyncConfig.appWorkDuration + vsyncConfig.sfWorkDuration;
-
-    *extraBuffers = calculateExtraBufferCount(maxSupportedRefreshRate, presentLatency);
+    *buffers = getMaxAcquiredBufferCountForRefreshRate(maxSupportedRefreshRate);
     return NO_ERROR;
 }
 
+int SurfaceFlinger::getMaxAcquiredBufferCountForCurrentRefreshRate(uid_t uid) const {
+    const auto refreshRate = [&] {
+        const auto frameRateOverride = mScheduler->getFrameRateOverride(uid);
+        if (frameRateOverride.has_value()) {
+            return frameRateOverride.value();
+        }
+        return mRefreshRateConfigs->getCurrentRefreshRate().getFps();
+    }();
+    return getMaxAcquiredBufferCountForRefreshRate(refreshRate);
+}
+
+int SurfaceFlinger::getMaxAcquiredBufferCountForRefreshRate(Fps refreshRate) const {
+    const auto vsyncConfig = mVsyncConfiguration->getConfigsForRefreshRate(refreshRate).late;
+    const auto presentLatency = vsyncConfig.appWorkDuration + vsyncConfig.sfWorkDuration;
+    return calculateMaxAcquiredBufferCount(refreshRate, presentLatency);
+}
+
 void SurfaceFlinger::TransactionState::traverseStatesWithBuffers(
         std::function<void(const layer_state_t&)> visitor) {
     for (const auto& state : states) {
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index a3fa8d6..22d17eb 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -708,7 +708,7 @@
 
     int getGPUContextPriority() override;
 
-    status_t getExtraBufferCount(int* extraBuffers) const override;
+    status_t getMaxAcquiredBufferCount(int* buffers) const override;
 
     // Implements IBinder::DeathRecipient.
     void binderDied(const wp<IBinder>& who) override;
@@ -923,6 +923,8 @@
     size_t getMaxTextureSize() const;
     size_t getMaxViewportDims() const;
 
+    int getMaxAcquiredBufferCountForCurrentRefreshRate(uid_t uid) const;
+
     /*
      * Display and layer stack management
      */
@@ -1062,6 +1064,7 @@
 
     // Calculates the expected present time for this frame. For negative offsets, performs a
     // correction using the predicted vsync for the next frame instead.
+
     nsecs_t calculateExpectedPresentTime(DisplayStatInfo) const;
 
     /*
@@ -1177,8 +1180,9 @@
     std::vector<ui::ColorMode> getDisplayColorModes(PhysicalDisplayId displayId)
             REQUIRES(mStateLock);
 
-    static int calculateExtraBufferCount(Fps maxSupportedRefreshRate,
-                                         std::chrono::nanoseconds presentLatency);
+    static int calculateMaxAcquiredBufferCount(Fps refreshRate,
+                                               std::chrono::nanoseconds presentLatency);
+    int getMaxAcquiredBufferCountForRefreshRate(Fps refreshRate) const;
 
     sp<StartPropertySetThread> mStartPropertySetThread;
     surfaceflinger::Factory& mFactory;
diff --git a/services/surfaceflinger/SurfaceInterceptor.cpp b/services/surfaceflinger/SurfaceInterceptor.cpp
index c5f1598..8ca241e 100644
--- a/services/surfaceflinger/SurfaceInterceptor.cpp
+++ b/services/surfaceflinger/SurfaceInterceptor.cpp
@@ -130,25 +130,25 @@
     transaction->set_animation(layerFlags & BnSurfaceComposer::eAnimation);
 
     const int32_t layerId(getLayerId(layer));
-    addPositionLocked(transaction, layerId, layer->mCurrentState.transform.tx(),
-                      layer->mCurrentState.transform.ty());
-    addDepthLocked(transaction, layerId, layer->mCurrentState.z);
-    addAlphaLocked(transaction, layerId, layer->mCurrentState.color.a);
+    addPositionLocked(transaction, layerId, layer->mDrawingState.transform.tx(),
+                      layer->mDrawingState.transform.ty());
+    addDepthLocked(transaction, layerId, layer->mDrawingState.z);
+    addAlphaLocked(transaction, layerId, layer->mDrawingState.color.a);
     addTransparentRegionLocked(transaction, layerId,
-                               layer->mCurrentState.activeTransparentRegion_legacy);
-    addLayerStackLocked(transaction, layerId, layer->mCurrentState.layerStack);
-    addCropLocked(transaction, layerId, layer->mCurrentState.crop);
-    addCornerRadiusLocked(transaction, layerId, layer->mCurrentState.cornerRadius);
-    addBackgroundBlurRadiusLocked(transaction, layerId, layer->mCurrentState.backgroundBlurRadius);
-    addBlurRegionsLocked(transaction, layerId, layer->mCurrentState.blurRegions);
-    addFlagsLocked(transaction, layerId, layer->mCurrentState.flags,
+                               layer->mDrawingState.activeTransparentRegion_legacy);
+    addLayerStackLocked(transaction, layerId, layer->mDrawingState.layerStack);
+    addCropLocked(transaction, layerId, layer->mDrawingState.crop);
+    addCornerRadiusLocked(transaction, layerId, layer->mDrawingState.cornerRadius);
+    addBackgroundBlurRadiusLocked(transaction, layerId, layer->mDrawingState.backgroundBlurRadius);
+    addBlurRegionsLocked(transaction, layerId, layer->mDrawingState.blurRegions);
+    addFlagsLocked(transaction, layerId, layer->mDrawingState.flags,
                    layer_state_t::eLayerHidden | layer_state_t::eLayerOpaque |
                            layer_state_t::eLayerSecure);
-    addReparentLocked(transaction, layerId, getLayerIdFromWeakRef(layer->mCurrentParent));
+    addReparentLocked(transaction, layerId, getLayerIdFromWeakRef(layer->mDrawingParent));
     addRelativeParentLocked(transaction, layerId,
-                            getLayerIdFromWeakRef(layer->mCurrentState.zOrderRelativeOf),
-                            layer->mCurrentState.z);
-    addShadowRadiusLocked(transaction, layerId, layer->mCurrentState.shadowRadius);
+                            getLayerIdFromWeakRef(layer->mDrawingState.zOrderRelativeOf),
+                            layer->mDrawingState.z);
+    addShadowRadiusLocked(transaction, layerId, layer->mDrawingState.shadowRadius);
 }
 
 void SurfaceInterceptor::addInitialDisplayStateLocked(Increment* increment,
@@ -511,8 +511,8 @@
     SurfaceCreation* creation(increment->mutable_surface_creation());
     creation->set_id(getLayerId(layer));
     creation->set_name(layer->getName());
-    creation->set_w(layer->mCurrentState.active_legacy.w);
-    creation->set_h(layer->mCurrentState.active_legacy.h);
+    creation->set_w(layer->mDrawingState.active_legacy.w);
+    creation->set_h(layer->mDrawingState.active_legacy.h);
 }
 
 void SurfaceInterceptor::addSurfaceDeletionLocked(Increment* increment,
diff --git a/services/surfaceflinger/TransactionCallbackInvoker.cpp b/services/surfaceflinger/TransactionCallbackInvoker.cpp
index 4f4c02b..fdf16a7 100644
--- a/services/surfaceflinger/TransactionCallbackInvoker.cpp
+++ b/services/surfaceflinger/TransactionCallbackInvoker.cpp
@@ -235,8 +235,9 @@
                                           handle->dequeueReadyTime);
         transactionStats->surfaceStats.emplace_back(surfaceControl, handle->acquireTime,
                                                     handle->previousReleaseFence,
-                                                    handle->transformHint, eventStats, jankData,
-                                                    handle->previousBufferId);
+                                                    handle->transformHint,
+                                                    handle->currentMaxAcquiredBufferCount,
+                                                    eventStats, jankData, handle->previousBufferId);
     }
     return NO_ERROR;
 }
diff --git a/services/surfaceflinger/TransactionCallbackInvoker.h b/services/surfaceflinger/TransactionCallbackInvoker.h
index 184b151..444bec6 100644
--- a/services/surfaceflinger/TransactionCallbackInvoker.h
+++ b/services/surfaceflinger/TransactionCallbackInvoker.h
@@ -45,6 +45,7 @@
     nsecs_t acquireTime = -1;
     nsecs_t latchTime = -1;
     uint32_t transformHint = 0;
+    uint32_t currentMaxAcquiredBufferCount = 0;
     std::shared_ptr<FenceTime> gpuCompositionDoneFence{FenceTime::NO_FENCE};
     CompositorTiming compositorTiming;
     nsecs_t refreshStartTime = 0;
diff --git a/services/surfaceflinger/TunnelModeEnabledReporter.cpp b/services/surfaceflinger/TunnelModeEnabledReporter.cpp
index 1b3ddf7..48e3216 100644
--- a/services/surfaceflinger/TunnelModeEnabledReporter.cpp
+++ b/services/surfaceflinger/TunnelModeEnabledReporter.cpp
@@ -31,8 +31,8 @@
 void TunnelModeEnabledReporter::updateTunnelModeStatus() {
     bool tunnelModeEnabled = false;
     mFlinger.mCurrentState.traverse([&](Layer* layer) {
-        auto& currentState = layer->getCurrentState();
-        if (currentState.sidebandStream != nullptr) {
+        auto& state = layer->getDrawingState();
+        if (state.sidebandStream != nullptr) {
             tunnelModeEnabled = true;
             return;
         }
diff --git a/services/surfaceflinger/tests/ReleaseBufferCallback_test.cpp b/services/surfaceflinger/tests/ReleaseBufferCallback_test.cpp
index fb7d41c..5aa809d 100644
--- a/services/surfaceflinger/tests/ReleaseBufferCallback_test.cpp
+++ b/services/surfaceflinger/tests/ReleaseBufferCallback_test.cpp
@@ -30,7 +30,8 @@
 class ReleaseBufferCallbackHelper {
 public:
     static void function(void* callbackContext, uint64_t graphicsBufferId,
-                         const sp<Fence>& releaseFence) {
+                         const sp<Fence>& releaseFence,
+                         uint32_t /*currentMaxAcquiredBufferCount*/) {
         if (!callbackContext) {
             FAIL() << "failed to get callback context";
         }
@@ -66,7 +67,7 @@
 
     android::ReleaseBufferCallback getCallback() {
         return std::bind(function, static_cast<void*>(this) /* callbackContext */,
-                         std::placeholders::_1, std::placeholders::_2);
+                         std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
     }
 
     std::mutex mMutex;
diff --git a/services/surfaceflinger/tests/unittests/FakeVsyncConfiguration.h b/services/surfaceflinger/tests/unittests/FakeVsyncConfiguration.h
index e890a62..f6f3c07 100644
--- a/services/surfaceflinger/tests/unittests/FakeVsyncConfiguration.h
+++ b/services/surfaceflinger/tests/unittests/FakeVsyncConfiguration.h
@@ -34,7 +34,8 @@
                 {FAKE_PHASE_OFFSET_NS, FAKE_PHASE_OFFSET_NS, FAKE_DURATION_OFFSET_NS,
                  FAKE_DURATION_OFFSET_NS},
                 {FAKE_PHASE_OFFSET_NS, FAKE_PHASE_OFFSET_NS, FAKE_DURATION_OFFSET_NS,
-                 FAKE_DURATION_OFFSET_NS}};
+                 FAKE_DURATION_OFFSET_NS},
+                FAKE_DURATION_OFFSET_NS};
     }
 
     void reset() override {}
diff --git a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
index d04a7d7..d4b229f 100644
--- a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
+++ b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
@@ -144,6 +144,7 @@
                                        mConfig30DifferentGroup,
                                        mConfig25DifferentGroup,
                                        mConfig50};
+    DisplayModes m60_120Device = {mConfig60, mConfig120};
 
     // Expected RefreshRate objects
     RefreshRate mExpected60Config = {HWC_CONFIG_ID_60, mConfig60, Fps(60),
@@ -1844,6 +1845,38 @@
     ASSERT_FALSE(detaultSignals == lastInvocation->outSignalsConsidered);
 }
 
+TEST_F(RefreshRateConfigsTest, getBestRefreshRate_ExplicitExactTouchBoost) {
+    auto refreshRateConfigs =
+            std::make_unique<RefreshRateConfigs>(m60_120Device,
+                                                 /*currentConfigId=*/HWC_CONFIG_ID_60,
+                                                 /*enableFrameRateOverride=*/true);
+
+    auto layers = std::vector<LayerRequirement>{LayerRequirement{.weight = 1.0f},
+                                                LayerRequirement{.weight = 0.5f}};
+    auto& explicitExactLayer = layers[0];
+    auto& explicitExactOrMultipleLayer = layers[1];
+
+    explicitExactOrMultipleLayer.vote = LayerVoteType::ExplicitExactOrMultiple;
+    explicitExactOrMultipleLayer.name = "ExplicitExactOrMultiple";
+    explicitExactOrMultipleLayer.desiredRefreshRate = Fps(60);
+
+    explicitExactLayer.vote = LayerVoteType::ExplicitExact;
+    explicitExactLayer.name = "ExplicitExact";
+    explicitExactLayer.desiredRefreshRate = Fps(30);
+
+    EXPECT_EQ(mExpected60Config,
+              refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
+    EXPECT_EQ(mExpected120Config,
+              refreshRateConfigs->getBestRefreshRate(layers, {.touch = true, .idle = false}));
+
+    explicitExactOrMultipleLayer.vote = LayerVoteType::NoVote;
+
+    EXPECT_EQ(mExpected60Config,
+              refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
+    EXPECT_EQ(mExpected60Config,
+              refreshRateConfigs->getBestRefreshRate(layers, {.touch = true, .idle = false}));
+}
+
 TEST_F(RefreshRateConfigsTest, testComparisonOperator) {
     EXPECT_TRUE(mExpected60Config < mExpected90Config);
     EXPECT_FALSE(mExpected60Config < mExpected60Config);
@@ -1864,10 +1897,10 @@
               0);
     EXPECT_EQ(KernelIdleTimerAction::TurnOn, refreshRateConfigs->getIdleTimerAction());
 
-    // SetPolicy(60, 60), current 60Hz => NoChange, avoid extra calls.
+    // SetPolicy(60, 60), current 60Hz => TurnOff
     ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_60, {Fps(60), Fps(60)}}),
               0);
-    EXPECT_EQ(KernelIdleTimerAction::NoChange, refreshRateConfigs->getIdleTimerAction());
+    EXPECT_EQ(KernelIdleTimerAction::TurnOff, refreshRateConfigs->getIdleTimerAction());
 
     // SetPolicy(90, 90), current 90Hz => TurnOff.
     ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_90, {Fps(90), Fps(90)}}),
diff --git a/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp
index fd3e564..35033ea 100644
--- a/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp
@@ -116,7 +116,7 @@
 }
 
 void RefreshRateSelectionTest::commitTransaction(Layer* layer) {
-    auto c = layer->getCurrentState();
+    auto c = layer->getDrawingState();
     layer->commitTransaction(c);
 }
 
diff --git a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
index 423d0cc..f680d80 100644
--- a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
@@ -210,14 +210,14 @@
     EXPECT_CALL(*mEventThread, onModeChanged(_, _, _)).Times(0);
 }
 
-TEST_F(SchedulerTest, calculateExtraBufferCount) {
-    EXPECT_EQ(0, mFlinger.calculateExtraBufferCount(Fps(60), 30ms));
-    EXPECT_EQ(1, mFlinger.calculateExtraBufferCount(Fps(90), 30ms));
-    EXPECT_EQ(2, mFlinger.calculateExtraBufferCount(Fps(120), 30ms));
+TEST_F(SchedulerTest, calculateMaxAcquiredBufferCount) {
+    EXPECT_EQ(1, mFlinger.calculateMaxAcquiredBufferCount(Fps(60), 30ms));
+    EXPECT_EQ(2, mFlinger.calculateMaxAcquiredBufferCount(Fps(90), 30ms));
+    EXPECT_EQ(3, mFlinger.calculateMaxAcquiredBufferCount(Fps(120), 30ms));
 
-    EXPECT_EQ(1, mFlinger.calculateExtraBufferCount(Fps(60), 40ms));
+    EXPECT_EQ(2, mFlinger.calculateMaxAcquiredBufferCount(Fps(60), 40ms));
 
-    EXPECT_EQ(0, mFlinger.calculateExtraBufferCount(Fps(60), 10ms));
+    EXPECT_EQ(1, mFlinger.calculateMaxAcquiredBufferCount(Fps(60), 10ms));
 }
 
 MATCHER(Is120Hz, "") {
diff --git a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp
index 46ef750..1ed52ea 100644
--- a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp
@@ -152,7 +152,7 @@
 
 void SetFrameRateTest::commitTransaction() {
     for (auto layer : mLayers) {
-        auto c = layer->getCurrentState();
+        auto c = layer->getDrawingState();
         layer->commitTransaction(c);
     }
 }
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_DestroyDisplayTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_DestroyDisplayTest.cpp
index 0614434..e2be074 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_DestroyDisplayTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_DestroyDisplayTest.cpp
@@ -74,4 +74,4 @@
 }
 
 } // namespace
-} // namespace android
\ No newline at end of file
+} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index d78f36c..7f6e05e 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -259,7 +259,6 @@
         memcpy(&mFlinger->mInternalDisplayPrimaries, &primaries, sizeof(ui::DisplayPrimaries));
     }
 
-    static auto& mutableLayerCurrentState(const sp<Layer>& layer) { return layer->mCurrentState; }
     static auto& mutableLayerDrawingState(const sp<Layer>& layer) { return layer->mDrawingState; }
 
     auto& mutableStateLock() { return mFlinger->mStateLock; }
@@ -272,7 +271,6 @@
     static void setLayerSidebandStream(const sp<Layer>& layer,
                                        const sp<NativeHandle>& sidebandStream) {
         layer->mDrawingState.sidebandStream = sidebandStream;
-        layer->mCurrentState.sidebandStream = sidebandStream;
         layer->mSidebandStream = sidebandStream;
         layer->editCompositionState()->sidebandStream = sidebandStream;
     }
@@ -391,9 +389,9 @@
 
     auto getGPUContextPriority() { return mFlinger->getGPUContextPriority(); }
 
-    auto calculateExtraBufferCount(Fps maxSupportedRefreshRate,
-                                   std::chrono::nanoseconds presentLatency) const {
-        return SurfaceFlinger::calculateExtraBufferCount(maxSupportedRefreshRate, presentLatency);
+    auto calculateMaxAcquiredBufferCount(Fps refreshRate,
+                                         std::chrono::nanoseconds presentLatency) const {
+        return SurfaceFlinger::calculateMaxAcquiredBufferCount(refreshRate, presentLatency);
     }
 
     /* ------------------------------------------------------------------------
diff --git a/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp b/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp
index 546bc4a..2845d0a 100644
--- a/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp
@@ -62,7 +62,7 @@
     }
 
     void commitTransaction(Layer* layer) {
-        auto c = layer->getCurrentState();
+        auto c = layer->getDrawingState();
         layer->commitTransaction(c);
     }
 
diff --git a/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp b/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp
index c1123cd..7bf224d 100644
--- a/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp
@@ -62,7 +62,7 @@
     }
 
     void commitTransaction(Layer* layer) {
-        auto c = layer->getCurrentState();
+        auto c = layer->getDrawingState();
         layer->commitTransaction(c);
     }
 
@@ -101,9 +101,9 @@
         sp<BufferStateLayer> layer = createBufferStateLayer();
         layer->setFrameTimelineVsyncForBufferlessTransaction({/*vsyncId*/ 1, /*inputEventId*/ 0},
                                                              10);
-        EXPECT_EQ(1u, layer->mCurrentState.bufferlessSurfaceFramesTX.size());
-        ASSERT_TRUE(layer->mCurrentState.bufferSurfaceFrameTX == nullptr);
-        const auto surfaceFrame = layer->mCurrentState.bufferlessSurfaceFramesTX.at(/*token*/ 1);
+        EXPECT_EQ(1u, layer->mDrawingState.bufferlessSurfaceFramesTX.size());
+        ASSERT_TRUE(layer->mDrawingState.bufferSurfaceFrameTX == nullptr);
+        const auto surfaceFrame = layer->mDrawingState.bufferlessSurfaceFramesTX.at(/*token*/ 1);
         commitTransaction(layer.get());
         EXPECT_EQ(1, surfaceFrame->getToken());
         EXPECT_EQ(false, surfaceFrame->getIsBuffer());
@@ -123,9 +123,9 @@
         acquireFence->signalForTest(12);
 
         commitTransaction(layer.get());
-        EXPECT_EQ(0u, layer->mCurrentState.bufferlessSurfaceFramesTX.size());
-        ASSERT_NE(nullptr, layer->mCurrentState.bufferSurfaceFrameTX);
-        const auto& surfaceFrame = layer->mCurrentState.bufferSurfaceFrameTX;
+        EXPECT_EQ(0u, layer->mDrawingState.bufferlessSurfaceFramesTX.size());
+        ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX);
+        const auto surfaceFrame = layer->mDrawingState.bufferSurfaceFrameTX;
         // Buffers are presented only at latch time.
         EXPECT_EQ(PresentState::Unknown, surfaceFrame->getPresentState());
 
@@ -148,9 +148,9 @@
                                                mRenderEngine, false);
         layer->setBuffer(buffer1, fence1, 10, 20, false, mClientCache, 1, std::nullopt,
                          {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */);
-        EXPECT_EQ(0u, layer->mCurrentState.bufferlessSurfaceFramesTX.size());
-        ASSERT_NE(nullptr, layer->mCurrentState.bufferSurfaceFrameTX);
-        const auto droppedSurfaceFrame = layer->mCurrentState.bufferSurfaceFrameTX;
+        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);
@@ -164,9 +164,9 @@
         nsecs_t end = systemTime();
         acquireFence2->signalForTest(12);
 
-        EXPECT_EQ(0u, layer->mCurrentState.bufferlessSurfaceFramesTX.size());
-        ASSERT_NE(nullptr, layer->mCurrentState.bufferSurfaceFrameTX);
-        const auto& presentedSurfaceFrame = layer->mCurrentState.bufferSurfaceFrameTX;
+        EXPECT_EQ(0u, layer->mDrawingState.bufferlessSurfaceFramesTX.size());
+        ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX);
+        const auto presentedSurfaceFrame = layer->mDrawingState.bufferSurfaceFrameTX;
 
         commitTransaction(layer.get());
         bool computeVisisbleRegions;
@@ -190,8 +190,8 @@
         layer->setFrameTimelineVsyncForBufferlessTransaction({/*vsyncId*/ 1, /*inputEventId*/ 0},
                                                              10);
 
-        EXPECT_EQ(1u, layer->mCurrentState.bufferlessSurfaceFramesTX.size());
-        ASSERT_EQ(nullptr, layer->mCurrentState.bufferSurfaceFrameTX);
+        EXPECT_EQ(1u, layer->mDrawingState.bufferlessSurfaceFramesTX.size());
+        ASSERT_EQ(nullptr, layer->mDrawingState.bufferSurfaceFrameTX);
 
         sp<Fence> fence(new Fence());
         auto acquireFence = fenceFactory.createFenceTimeForTest(fence);
@@ -203,9 +203,9 @@
                          {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */);
         acquireFence->signalForTest(12);
 
-        EXPECT_EQ(0u, layer->mCurrentState.bufferlessSurfaceFramesTX.size());
-        ASSERT_NE(nullptr, layer->mCurrentState.bufferSurfaceFrameTX);
-        const auto& surfaceFrame = layer->mCurrentState.bufferSurfaceFrameTX;
+        EXPECT_EQ(0u, layer->mDrawingState.bufferlessSurfaceFramesTX.size());
+        ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX);
+        const auto surfaceFrame = layer->mDrawingState.bufferSurfaceFrameTX;
 
         commitTransaction(layer.get());
         EXPECT_EQ(1, surfaceFrame->getToken());
@@ -229,29 +229,29 @@
                                                mRenderEngine, false);
         layer->setBuffer(buffer, fence, 10, 20, false, mClientCache, 1, std::nullopt,
                          {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */);
-        EXPECT_EQ(0u, layer->mCurrentState.bufferlessSurfaceFramesTX.size());
-        ASSERT_NE(nullptr, layer->mCurrentState.bufferSurfaceFrameTX);
+        EXPECT_EQ(0u, layer->mDrawingState.bufferlessSurfaceFramesTX.size());
+        ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX);
 
         layer->setFrameTimelineVsyncForBufferlessTransaction({/*vsyncId*/ 1, /*inputEventId*/ 0},
                                                              10);
-        EXPECT_EQ(0u, layer->mCurrentState.bufferlessSurfaceFramesTX.size());
-        ASSERT_NE(nullptr, layer->mCurrentState.bufferSurfaceFrameTX);
+        EXPECT_EQ(0u, layer->mDrawingState.bufferlessSurfaceFramesTX.size());
+        ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX);
     }
 
     void MultipleSurfaceFramesPresentedTogether() {
         sp<BufferStateLayer> layer = createBufferStateLayer();
         layer->setFrameTimelineVsyncForBufferlessTransaction({/*vsyncId*/ 1, /*inputEventId*/ 0},
                                                              10);
-        EXPECT_EQ(1u, layer->mCurrentState.bufferlessSurfaceFramesTX.size());
-        ASSERT_EQ(nullptr, layer->mCurrentState.bufferSurfaceFrameTX);
+        EXPECT_EQ(1u, layer->mDrawingState.bufferlessSurfaceFramesTX.size());
+        ASSERT_EQ(nullptr, layer->mDrawingState.bufferSurfaceFrameTX);
         const auto bufferlessSurfaceFrame1 =
-                layer->mCurrentState.bufferlessSurfaceFramesTX.at(/*token*/ 1);
+                layer->mDrawingState.bufferlessSurfaceFramesTX.at(/*token*/ 1);
 
         layer->setFrameTimelineVsyncForBufferlessTransaction({/*vsyncId*/ 4, /*inputEventId*/ 0},
                                                              10);
-        EXPECT_EQ(2u, layer->mCurrentState.bufferlessSurfaceFramesTX.size());
-        ASSERT_EQ(nullptr, layer->mCurrentState.bufferSurfaceFrameTX);
-        const auto bufferlessSurfaceFrame2 = layer->mCurrentState.bufferlessSurfaceFramesTX[4];
+        EXPECT_EQ(2u, layer->mDrawingState.bufferlessSurfaceFramesTX.size());
+        ASSERT_EQ(nullptr, layer->mDrawingState.bufferSurfaceFrameTX);
+        const auto bufferlessSurfaceFrame2 = layer->mDrawingState.bufferlessSurfaceFramesTX[4];
 
         sp<Fence> fence(new Fence());
         auto acquireFence = fenceFactory.createFenceTimeForTest(fence);
@@ -261,9 +261,9 @@
                                                mRenderEngine, false);
         layer->setBuffer(buffer, fence, 10, 20, false, mClientCache, 1, std::nullopt,
                          {/*vsyncId*/ 3, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */);
-        EXPECT_EQ(2u, layer->mCurrentState.bufferlessSurfaceFramesTX.size());
-        ASSERT_NE(nullptr, layer->mCurrentState.bufferSurfaceFrameTX);
-        const auto& bufferSurfaceFrameTX = layer->mCurrentState.bufferSurfaceFrameTX;
+        EXPECT_EQ(2u, layer->mDrawingState.bufferlessSurfaceFramesTX.size());
+        ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX);
+        const auto bufferSurfaceFrameTX = layer->mDrawingState.bufferSurfaceFrameTX;
 
         acquireFence->signalForTest(12);
 
@@ -299,8 +299,8 @@
                                                mRenderEngine, false);
         layer->setBuffer(buffer1, fence1, 10, 20, false, mClientCache, 1, std::nullopt,
                          {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */);
-        ASSERT_NE(nullptr, layer->mCurrentState.bufferSurfaceFrameTX);
-        const auto droppedSurfaceFrame = layer->mCurrentState.bufferSurfaceFrameTX;
+        ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX);
+        const auto droppedSurfaceFrame = layer->mDrawingState.bufferSurfaceFrameTX;
 
         sp<Fence> fence2(new Fence());
         auto acquireFence2 = fenceFactory.createFenceTimeForTest(fence2);
@@ -312,8 +312,8 @@
                          {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */);
         acquireFence2->signalForTest(12);
 
-        ASSERT_NE(nullptr, layer->mCurrentState.bufferSurfaceFrameTX);
-        auto& presentedSurfaceFrame = layer->mCurrentState.bufferSurfaceFrameTX;
+        ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX);
+        auto presentedSurfaceFrame = layer->mDrawingState.bufferSurfaceFrameTX;
 
         commitTransaction(layer.get());
         bool computeVisisbleRegions;
@@ -340,9 +340,9 @@
                                                mRenderEngine, false);
         layer->setBuffer(buffer1, fence1, 10, 20, false, mClientCache, 1, std::nullopt,
                          {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */);
-        EXPECT_EQ(0u, layer->mCurrentState.bufferlessSurfaceFramesTX.size());
-        ASSERT_NE(nullptr, layer->mCurrentState.bufferSurfaceFrameTX);
-        const auto droppedSurfaceFrame1 = layer->mCurrentState.bufferSurfaceFrameTX;
+        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);
@@ -355,9 +355,9 @@
                          {/*vsyncId*/ FrameTimelineInfo::INVALID_VSYNC_ID, /*inputEventId*/ 0},
                          nullptr /* releaseBufferCallback */);
         auto dropEndTime1 = systemTime();
-        EXPECT_EQ(0u, layer->mCurrentState.bufferlessSurfaceFramesTX.size());
-        ASSERT_NE(nullptr, layer->mCurrentState.bufferSurfaceFrameTX);
-        const auto droppedSurfaceFrame2 = layer->mCurrentState.bufferSurfaceFrameTX;
+        EXPECT_EQ(0u, layer->mDrawingState.bufferlessSurfaceFramesTX.size());
+        ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX);
+        const auto droppedSurfaceFrame2 = layer->mDrawingState.bufferSurfaceFrameTX;
 
         sp<Fence> fence3(new Fence());
         auto acquireFence3 = fenceFactory.createFenceTimeForTest(fence3);
@@ -371,9 +371,9 @@
         auto dropEndTime2 = systemTime();
         acquireFence3->signalForTest(12);
 
-        EXPECT_EQ(0u, layer->mCurrentState.bufferlessSurfaceFramesTX.size());
-        ASSERT_NE(nullptr, layer->mCurrentState.bufferSurfaceFrameTX);
-        const auto& presentedSurfaceFrame = layer->mCurrentState.bufferSurfaceFrameTX;
+        EXPECT_EQ(0u, layer->mDrawingState.bufferlessSurfaceFramesTX.size());
+        ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX);
+        const auto presentedSurfaceFrame = layer->mDrawingState.bufferSurfaceFrameTX;
 
         commitTransaction(layer.get());
         bool computeVisisbleRegions;
@@ -415,10 +415,10 @@
             layer->setFrameTimelineVsyncForBufferlessTransaction({/*vsyncId*/ 2,
                                                                   /*inputEventId*/ 0},
                                                                  10);
-            ASSERT_NE(nullptr, layer->mCurrentState.bufferSurfaceFrameTX);
-            EXPECT_EQ(1u, layer->mCurrentState.bufferlessSurfaceFramesTX.size());
+            ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX);
+            EXPECT_EQ(1u, layer->mDrawingState.bufferlessSurfaceFramesTX.size());
             auto& bufferlessSurfaceFrame =
-                    layer->mCurrentState.bufferlessSurfaceFramesTX.at(/*vsyncId*/ 2);
+                    layer->mDrawingState.bufferlessSurfaceFramesTX.at(/*vsyncId*/ 2);
             bufferlessSurfaceFrames.push_back(bufferlessSurfaceFrame);
 
             commitTransaction(layer.get());
diff --git a/services/surfaceflinger/tests/unittests/VsyncConfigurationTest.cpp b/services/surfaceflinger/tests/unittests/VsyncConfigurationTest.cpp
index bb7578d..41a4d30 100644
--- a/services/surfaceflinger/tests/unittests/VsyncConfigurationTest.cpp
+++ b/services/surfaceflinger/tests/unittests/VsyncConfigurationTest.cpp
@@ -34,16 +34,18 @@
 public:
     TestableWorkDuration(Fps currentFps, nsecs_t sfDuration, nsecs_t appDuration,
                          nsecs_t sfEarlyDuration, nsecs_t appEarlyDuration,
-                         nsecs_t sfEarlyGlDuration, nsecs_t appEarlyGlDuration)
+                         nsecs_t sfEarlyGlDuration, nsecs_t appEarlyGlDuration,
+                         nsecs_t hwcMinWorkDuration)
           : impl::WorkDuration(currentFps, sfDuration, appDuration, sfEarlyDuration,
-                               appEarlyDuration, sfEarlyGlDuration, appEarlyGlDuration) {}
+                               appEarlyDuration, sfEarlyGlDuration, appEarlyGlDuration,
+                               hwcMinWorkDuration) {}
 };
 
 class WorkDurationTest : public testing::Test {
 protected:
     WorkDurationTest()
           : mWorkDuration(Fps(60.0f), 10'500'000, 20'500'000, 16'000'000, 16'500'000, 13'500'000,
-                          21'000'000) {}
+                          21'000'000, 1234) {}
 
     ~WorkDurationTest() = default;
 
@@ -104,7 +106,7 @@
 }
 
 TEST_F(WorkDurationTest, getConfigsForRefreshRate_DefaultOffsets) {
-    TestableWorkDuration phaseOffsetsWithDefaultValues(Fps(60.0f), -1, -1, -1, -1, -1, -1);
+    TestableWorkDuration phaseOffsetsWithDefaultValues(Fps(60.0f), -1, -1, -1, -1, -1, -1, 0);
 
     auto validateOffsets = [](const auto& offsets, std::chrono::nanoseconds vsyncPeriod) {
         EXPECT_EQ(offsets.late.sfOffset, 1'000'000);
@@ -124,6 +126,8 @@
 
         EXPECT_EQ(offsets.earlyGpu.sfWorkDuration, vsyncPeriod - 1'000'000ns);
         EXPECT_EQ(offsets.earlyGpu.appWorkDuration, vsyncPeriod);
+
+        EXPECT_EQ(offsets.hwcMinWorkDuration, 0ns);
     };
 
     const auto testForRefreshRate = [&](Fps refreshRate) {
@@ -160,6 +164,10 @@
     EXPECT_EQ(offsets.earlyGpu.appWorkDuration, 21'000'000ns);
 }
 
+TEST_F(WorkDurationTest, minHwcWorkDuration) {
+    EXPECT_EQ(mWorkDuration.getCurrentConfigs().hwcMinWorkDuration, 1234ns);
+}
+
 class TestablePhaseOffsets : public impl::PhaseOffsets {
 public:
     TestablePhaseOffsets(nsecs_t vsyncPhaseOffsetNs, nsecs_t sfVSyncPhaseOffsetNs,
@@ -172,13 +180,14 @@
                          std::optional<nsecs_t> highFpsEarlyGpuSfOffsetNs,
                          std::optional<nsecs_t> highFpsEarlyAppOffsetNs,
                          std::optional<nsecs_t> highFpsEarlyGpuAppOffsetNs,
-                         nsecs_t thresholdForNextVsync)
+                         nsecs_t thresholdForNextVsync, nsecs_t hwcMinWorkDuration)
           : impl::PhaseOffsets(Fps(60.0f), vsyncPhaseOffsetNs, sfVSyncPhaseOffsetNs,
                                earlySfOffsetNs, earlyGpuSfOffsetNs, earlyAppOffsetNs,
                                earlyGpuAppOffsetNs, highFpsVsyncPhaseOffsetNs,
                                highFpsSfVSyncPhaseOffsetNs, highFpsEarlySfOffsetNs,
                                highFpsEarlyGpuSfOffsetNs, highFpsEarlyAppOffsetNs,
-                               highFpsEarlyGpuAppOffsetNs, thresholdForNextVsync) {}
+                               highFpsEarlyGpuAppOffsetNs, thresholdForNextVsync,
+                               hwcMinWorkDuration) {}
 };
 
 class PhaseOffsetsTest : public testing::Test {
@@ -186,9 +195,9 @@
     PhaseOffsetsTest() = default;
     ~PhaseOffsetsTest() = default;
 
-    TestablePhaseOffsets mPhaseOffsets{2'000'000, 6'000'000, 7'000'000, 8'000'000, 3'000'000,
-                                       4'000'000, 2'000'000, 1'000'000, 2'000'000, 3'000'000,
-                                       3'000'000, 4'000'000, 10'000'000};
+    TestablePhaseOffsets mPhaseOffsets{2'000'000, 6'000'000, 7'000'000,  8'000'000, 3'000'000,
+                                       4'000'000, 2'000'000, 1'000'000,  2'000'000, 3'000'000,
+                                       3'000'000, 4'000'000, 10'000'000, 1234};
 };
 
 TEST_F(PhaseOffsetsTest, getConfigsForRefreshRate_unknownRefreshRate) {
@@ -258,8 +267,8 @@
 }
 
 TEST_F(PhaseOffsetsTest, getConfigsForRefreshRate_DefaultValues_60Hz) {
-    TestablePhaseOffsets phaseOffsets{1'000'000, 1'000'000, {}, {}, {}, {},        2'000'000,
-                                      1'000'000, {},        {}, {}, {}, 10'000'000};
+    TestablePhaseOffsets phaseOffsets{1'000'000, 1'000'000, {}, {}, {}, {},         2'000'000,
+                                      1'000'000, {},        {}, {}, {}, 10'000'000, 1234};
     auto offsets = phaseOffsets.getConfigsForRefreshRate(Fps(60.0f));
 
     EXPECT_EQ(offsets.late.sfOffset, 1'000'000);
@@ -282,8 +291,8 @@
 }
 
 TEST_F(PhaseOffsetsTest, getConfigsForRefreshRate_DefaultValues_90Hz) {
-    TestablePhaseOffsets phaseOffsets{1'000'000, 1'000'000, {}, {}, {}, {},        2'000'000,
-                                      1'000'000, {},        {}, {}, {}, 10'000'000};
+    TestablePhaseOffsets phaseOffsets{1'000'000, 1'000'000, {}, {}, {}, {},         2'000'000,
+                                      1'000'000, {},        {}, {}, {}, 10'000'000, 1234};
     auto offsets = phaseOffsets.getConfigsForRefreshRate(Fps(90.0f));
 
     EXPECT_EQ(offsets.late.sfOffset, 1'000'000);
@@ -305,4 +314,10 @@
     EXPECT_EQ(offsets.earlyGpu.appWorkDuration, 21'222'222ns);
 }
 
+TEST_F(PhaseOffsetsTest, minHwcWorkDuration) {
+    TestablePhaseOffsets phaseOffsets{1'000'000, 1'000'000, {}, {}, {}, {},         2'000'000,
+                                      1'000'000, {},        {}, {}, {}, 10'000'000, 1234};
+    EXPECT_EQ(phaseOffsets.getCurrentConfigs().hwcMinWorkDuration, 1234ns);
+}
+
 } // namespace android::scheduler
diff --git a/services/surfaceflinger/tests/unittests/VsyncModulatorTest.cpp b/services/surfaceflinger/tests/unittests/VsyncModulatorTest.cpp
index 17648d5..60952bf 100644
--- a/services/surfaceflinger/tests/unittests/VsyncModulatorTest.cpp
+++ b/services/surfaceflinger/tests/unittests/VsyncModulatorTest.cpp
@@ -35,6 +35,7 @@
         APP_OFFSET_EARLY_GPU,
         SF_DURATION_EARLY_GPU,
         APP_DURATION_EARLY_GPU,
+        HWC_MIN_WORK_DURATION,
     };
 
     static VsyncModulator::TimePoint Now() {
@@ -57,7 +58,8 @@
                                             nanos(SF_DURATION_EARLY_GPU),
                                             nanos(APP_DURATION_EARLY_GPU)};
 
-    const VsyncModulator::VsyncConfigSet mOffsets = {kEarly, kEarlyGpu, kLate};
+    const VsyncModulator::VsyncConfigSet mOffsets = {kEarly, kEarlyGpu, kLate,
+                                                     nanos(HWC_MIN_WORK_DURATION)};
     VsyncModulator mVsyncModulator{mOffsets, Now};
 
     void SetUp() override { EXPECT_EQ(kLate, mVsyncModulator.setVsyncConfigSet(mOffsets)); }