Merge "swapchain: increase the minimal buffer count to 3" into sc-dev
diff --git a/cmds/installd/run_dex2oat.cpp b/cmds/installd/run_dex2oat.cpp
index a27fd10..e847626 100644
--- a/cmds/installd/run_dex2oat.cpp
+++ b/cmds/installd/run_dex2oat.cpp
@@ -324,6 +324,12 @@
 
     AddRuntimeArg(MapPropertyToArg("dalvik.vm.dex2oat-Xms", "-Xms%s"));
     AddRuntimeArg(MapPropertyToArg("dalvik.vm.dex2oat-Xmx", "-Xmx%s"));
+
+    // Enable compiling dex files in isolation on low ram devices.
+    // It takes longer but reduces the memory footprint.
+    if (GetBoolProperty("ro.config.low_ram", false)) {
+      AddArg("--compile-individually");
+    }
 }
 
 void RunDex2Oat::Exec(int exit_code) {
diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp
index 52d3fa3..364c939 100644
--- a/libs/gui/BLASTBufferQueue.cpp
+++ b/libs/gui/BLASTBufferQueue.cpp
@@ -151,6 +151,7 @@
                                                       1, false);
     static int32_t id = 0;
     auto consumerName = mName + "(BLAST Consumer)" + std::to_string(id);
+    mPendingBufferTrace = "PendingBuffer - " + mName + "BLAST#" + std::to_string(id);
     id++;
     mBufferItemConsumer->setName(String8(consumerName.c_str()));
     mBufferItemConsumer->setFrameAvailableListener(this);
@@ -168,7 +169,6 @@
           .setFlags(surface, layer_state_t::eEnableBackpressure,
                     layer_state_t::eEnableBackpressure)
           .apply();
-
     mNumAcquired = 0;
     mNumFrameAvailable = 0;
 }
@@ -205,6 +205,11 @@
         applyTransaction = true;
     }
 
+    if (mSurfaceControl != nullptr) {
+        mTransformHint = mSurfaceControl->getTransformHint();
+        mBufferItemConsumer->setTransformHint(mTransformHint);
+    }
+
     ui::Size newSize(width, height);
     if (mRequestedSize != newSize) {
         mRequestedSize.set(newSize);
@@ -259,15 +264,18 @@
 
                 mTransformHint = stat.transformHint;
                 mBufferItemConsumer->setTransformHint(mTransformHint);
-                mBufferItemConsumer
-                        ->updateFrameTimestamps(stat.frameEventStats.frameNumber,
-                                                stat.frameEventStats.refreshStartTime,
-                                                stat.frameEventStats.gpuCompositionDoneFence,
-                                                stat.presentFence, stat.previousReleaseFence,
-                                                stat.frameEventStats.compositorTiming,
-                                                stat.latchTime,
-                                                stat.frameEventStats.dequeueReadyTime);
-
+                // Update frametime stamps if the frame was latched and presented, indicated by a
+                // valid latch time.
+                if (stat.latchTime > 0) {
+                    mBufferItemConsumer
+                            ->updateFrameTimestamps(stat.frameEventStats.frameNumber,
+                                                    stat.frameEventStats.refreshStartTime,
+                                                    stat.frameEventStats.gpuCompositionDoneFence,
+                                                    stat.presentFence, stat.previousReleaseFence,
+                                                    stat.frameEventStats.compositorTiming,
+                                                    stat.latchTime,
+                                                    stat.frameEventStats.dequeueReadyTime);
+                }
                 currFrameNumber = stat.frameEventStats.frameNumber;
 
                 if (mTransactionCompleteCallback &&
@@ -361,6 +369,7 @@
     ATRACE_INT("PendingRelease", mPendingRelease.size());
 
     mNumAcquired--;
+    ATRACE_INT(mPendingBufferTrace.c_str(), mNumFrameAvailable + mNumAcquired);
     processNextBufferLocked(false /* useNextTransaction */);
     mCallbackCV.notify_all();
 }
@@ -529,6 +538,7 @@
     }
     // add to shadow queue
     mNumFrameAvailable++;
+    ATRACE_INT(mPendingBufferTrace.c_str(), mNumFrameAvailable + mNumAcquired);
 
     BQA_LOGV("onFrameAvailable framenumber=%" PRIu64 " nextTransactionSet=%s", item.mFrameNumber,
              toString(nextTransactionSet));
diff --git a/libs/gui/include/gui/BLASTBufferQueue.h b/libs/gui/include/gui/BLASTBufferQueue.h
index 0981e76..cb0e65e 100644
--- a/libs/gui/include/gui/BLASTBufferQueue.h
+++ b/libs/gui/include/gui/BLASTBufferQueue.h
@@ -125,6 +125,7 @@
     static PixelFormat convertBufferFormat(PixelFormat& format);
 
     std::string mName;
+    std::string mPendingBufferTrace;
     sp<SurfaceControl> mSurfaceControl;
 
     std::mutex mMutex;
diff --git a/libs/gui/include/gui/FrameTimestamps.h b/libs/gui/include/gui/FrameTimestamps.h
index 0750080..dd3de58 100644
--- a/libs/gui/include/gui/FrameTimestamps.h
+++ b/libs/gui/include/gui/FrameTimestamps.h
@@ -131,6 +131,7 @@
     // Public for testing.
     static nsecs_t snapToNextTick(
             nsecs_t timestamp, nsecs_t tickPhase, nsecs_t tickInterval);
+    nsecs_t getReportedCompositeDeadline() const { return mCompositorTiming.deadline; };
 
     nsecs_t getNextCompositeDeadline(const nsecs_t now) const;
     nsecs_t getCompositeInterval() const { return mCompositorTiming.interval; }
diff --git a/libs/gui/tests/BLASTBufferQueue_test.cpp b/libs/gui/tests/BLASTBufferQueue_test.cpp
index 06660b8..6ff67aa 100644
--- a/libs/gui/tests/BLASTBufferQueue_test.cpp
+++ b/libs/gui/tests/BLASTBufferQueue_test.cpp
@@ -948,21 +948,22 @@
 class BLASTFrameEventHistoryTest : public BLASTBufferQueueTest {
 public:
     void setUpAndQueueBuffer(const sp<IGraphicBufferProducer>& igbProducer,
-                             nsecs_t* requestedPresentTime, nsecs_t* postedTime,
+                             nsecs_t* outRequestedPresentTime, nsecs_t* postedTime,
                              IGraphicBufferProducer::QueueBufferOutput* qbOutput,
-                             bool getFrameTimestamps, nsecs_t requestedPresentTimeDelay = 0) {
+                             bool getFrameTimestamps, nsecs_t requestedPresentTime = systemTime()) {
         int slot;
         sp<Fence> fence;
         sp<GraphicBuffer> buf;
         auto ret = igbProducer->dequeueBuffer(&slot, &fence, mDisplayWidth, mDisplayHeight,
                                               PIXEL_FORMAT_RGBA_8888, GRALLOC_USAGE_SW_WRITE_OFTEN,
                                               nullptr, nullptr);
-        ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, ret);
-        ASSERT_EQ(OK, igbProducer->requestBuffer(slot, &buf));
+        if (IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION == ret) {
+            ASSERT_EQ(OK, igbProducer->requestBuffer(slot, &buf));
+        }
 
-        nsecs_t requestedTime = systemTime() + requestedPresentTimeDelay;
-        if (requestedPresentTime) *requestedPresentTime = requestedTime;
-        IGraphicBufferProducer::QueueBufferInput input(requestedTime, false, HAL_DATASPACE_UNKNOWN,
+        *outRequestedPresentTime = requestedPresentTime;
+        IGraphicBufferProducer::QueueBufferInput input(requestedPresentTime, false,
+                                                       HAL_DATASPACE_UNKNOWN,
                                                        Rect(mDisplayWidth, mDisplayHeight),
                                                        NATIVE_WINDOW_SCALING_MODE_FREEZE, 0,
                                                        Fence::NO_FENCE, /*sticky*/ 0,
@@ -1034,9 +1035,11 @@
     IGraphicBufferProducer::QueueBufferOutput qbOutput;
     nsecs_t requestedPresentTimeA = 0;
     nsecs_t postedTimeA = 0;
-    nsecs_t presentTimeDelay = std::chrono::nanoseconds(500ms).count();
+    // Present the frame sometime in the future so we can add two frames to the queue so the older
+    // one will be dropped.
+    nsecs_t presentTime = systemTime() + std::chrono::nanoseconds(500ms).count();
     setUpAndQueueBuffer(igbProducer, &requestedPresentTimeA, &postedTimeA, &qbOutput, true,
-                        presentTimeDelay);
+                        presentTime);
     history.applyDelta(qbOutput.frameTimestamps);
 
     FrameEvents* events = nullptr;
@@ -1049,7 +1052,10 @@
     // queue another buffer so the first can be dropped
     nsecs_t requestedPresentTimeB = 0;
     nsecs_t postedTimeB = 0;
-    setUpAndQueueBuffer(igbProducer, &requestedPresentTimeB, &postedTimeB, &qbOutput, true);
+    adapter.setTransactionCompleteCallback(2);
+    presentTime = systemTime() + std::chrono::nanoseconds(1ms).count();
+    setUpAndQueueBuffer(igbProducer, &requestedPresentTimeB, &postedTimeB, &qbOutput, true,
+                        presentTime);
     history.applyDelta(qbOutput.frameTimestamps);
     events = history.getFrame(1);
     ASSERT_NE(nullptr, events);
@@ -1059,20 +1065,75 @@
     ASSERT_EQ(requestedPresentTimeA, events->requestedPresentTime);
     ASSERT_GE(events->postedTime, postedTimeA);
 
-    // a valid latchtime should not be set
+    // a valid latchtime and pre and post composition info should not be set for the dropped frame
     ASSERT_FALSE(events->hasLatchInfo());
     ASSERT_FALSE(events->hasDequeueReadyInfo());
+    ASSERT_FALSE(events->hasGpuCompositionDoneInfo());
+    ASSERT_FALSE(events->hasDisplayPresentInfo());
+    ASSERT_FALSE(events->hasReleaseInfo());
 
-    ASSERT_NE(nullptr, events->gpuCompositionDoneFence);
-    ASSERT_NE(nullptr, events->displayPresentFence);
-    ASSERT_NE(nullptr, events->releaseFence);
+    // wait for the last transaction to be completed.
+    adapter.waitForCallback(2);
 
-    // we should also have gotten the initial values for the next frame
+    // queue another buffer so we query for frame event deltas
+    nsecs_t requestedPresentTimeC = 0;
+    nsecs_t postedTimeC = 0;
+    setUpAndQueueBuffer(igbProducer, &requestedPresentTimeC, &postedTimeC, &qbOutput, true);
+    history.applyDelta(qbOutput.frameTimestamps);
+
+    // frame number, requestedPresentTime, and postTime should not have changed
+    ASSERT_EQ(1, events->frameNumber);
+    ASSERT_EQ(requestedPresentTimeA, events->requestedPresentTime);
+    ASSERT_GE(events->postedTime, postedTimeA);
+
+    // a valid latchtime and pre and post composition info should not be set for the dropped frame
+    ASSERT_FALSE(events->hasLatchInfo());
+    ASSERT_FALSE(events->hasDequeueReadyInfo());
+    ASSERT_FALSE(events->hasGpuCompositionDoneInfo());
+    ASSERT_FALSE(events->hasDisplayPresentInfo());
+    ASSERT_FALSE(events->hasReleaseInfo());
+
+    // we should also have gotten values for the presented frame
     events = history.getFrame(2);
     ASSERT_NE(nullptr, events);
     ASSERT_EQ(2, events->frameNumber);
     ASSERT_EQ(requestedPresentTimeB, events->requestedPresentTime);
     ASSERT_GE(events->postedTime, postedTimeB);
+    ASSERT_GE(events->latchTime, postedTimeB);
+    ASSERT_GE(events->dequeueReadyTime, events->latchTime);
+    ASSERT_NE(nullptr, events->gpuCompositionDoneFence);
+    ASSERT_NE(nullptr, events->displayPresentFence);
+    ASSERT_NE(nullptr, events->releaseFence);
+
+    // wait for any callbacks that have not been received
+    adapter.waitForCallbacks();
+}
+
+TEST_F(BLASTFrameEventHistoryTest, FrameEventHistory_CompositorTimings) {
+    BLASTBufferQueueHelper adapter(mSurfaceControl, mDisplayWidth, mDisplayHeight);
+    sp<IGraphicBufferProducer> igbProducer;
+    ProducerFrameEventHistory history;
+    setUpProducer(adapter, igbProducer);
+
+    IGraphicBufferProducer::QueueBufferOutput qbOutput;
+    nsecs_t requestedPresentTimeA = 0;
+    nsecs_t postedTimeA = 0;
+    adapter.setTransactionCompleteCallback(1);
+    setUpAndQueueBuffer(igbProducer, &requestedPresentTimeA, &postedTimeA, &qbOutput, true);
+    history.applyDelta(qbOutput.frameTimestamps);
+    adapter.waitForCallback(1);
+
+    // queue another buffer so we query for frame event deltas
+    nsecs_t requestedPresentTimeB = 0;
+    nsecs_t postedTimeB = 0;
+    setUpAndQueueBuffer(igbProducer, &requestedPresentTimeB, &postedTimeB, &qbOutput, true);
+    history.applyDelta(qbOutput.frameTimestamps);
+
+    // check for a valid compositor deadline
+    ASSERT_NE(0, history.getReportedCompositeDeadline());
+
+    // wait for any callbacks that have not been received
+    adapter.waitForCallbacks();
 }
 
 } // namespace android
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/inputflinger/dispatcher/FocusResolver.cpp b/services/inputflinger/dispatcher/FocusResolver.cpp
index 2db8c13..fb19435 100644
--- a/services/inputflinger/dispatcher/FocusResolver.cpp
+++ b/services/inputflinger/dispatcher/FocusResolver.cpp
@@ -216,4 +216,9 @@
     return dump;
 }
 
+void FocusResolver::displayRemoved(int32_t displayId) {
+    mFocusRequestByDisplay.erase(displayId);
+    mLastFocusResultByDisplay.erase(displayId);
+}
+
 } // namespace android::inputdispatcher
diff --git a/services/inputflinger/dispatcher/FocusResolver.h b/services/inputflinger/dispatcher/FocusResolver.h
index dc5eeeb..afe16b3 100644
--- a/services/inputflinger/dispatcher/FocusResolver.h
+++ b/services/inputflinger/dispatcher/FocusResolver.h
@@ -62,6 +62,9 @@
     std::optional<FocusResolver::FocusChanges> setFocusedWindow(
             const FocusRequest& request, const std::vector<sp<InputWindowHandle>>& windows);
 
+    // Display has been removed from the system, clean up old references.
+    void displayRemoved(int32_t displayId);
+
     // exposed for debugging
     bool hasFocusedWindowTokens() const { return !mFocusedWindowTokenByDisplay.empty(); }
     std::string dumpFocusedWindows() const;
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index d2b8739..c0010ab 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -4613,30 +4613,34 @@
     }
     { // acquire lock
         std::scoped_lock _l(mLock);
-
-        std::shared_ptr<InputApplicationHandle> oldFocusedApplicationHandle =
-                getValueByKey(mFocusedApplicationHandlesByDisplay, displayId);
-
-        if (sharedPointersEqual(oldFocusedApplicationHandle, inputApplicationHandle)) {
-            return; // This application is already focused. No need to wake up or change anything.
-        }
-
-        // Set the new application handle.
-        if (inputApplicationHandle != nullptr) {
-            mFocusedApplicationHandlesByDisplay[displayId] = inputApplicationHandle;
-        } else {
-            mFocusedApplicationHandlesByDisplay.erase(displayId);
-        }
-
-        // No matter what the old focused application was, stop waiting on it because it is
-        // no longer focused.
-        resetNoFocusedWindowTimeoutLocked();
+        setFocusedApplicationLocked(displayId, inputApplicationHandle);
     } // release lock
 
     // Wake up poll loop since it may need to make new input dispatching choices.
     mLooper->wake();
 }
 
+void InputDispatcher::setFocusedApplicationLocked(
+        int32_t displayId, const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle) {
+    std::shared_ptr<InputApplicationHandle> oldFocusedApplicationHandle =
+            getValueByKey(mFocusedApplicationHandlesByDisplay, displayId);
+
+    if (sharedPointersEqual(oldFocusedApplicationHandle, inputApplicationHandle)) {
+        return; // This application is already focused. No need to wake up or change anything.
+    }
+
+    // Set the new application handle.
+    if (inputApplicationHandle != nullptr) {
+        mFocusedApplicationHandlesByDisplay[displayId] = inputApplicationHandle;
+    } else {
+        mFocusedApplicationHandlesByDisplay.erase(displayId);
+    }
+
+    // No matter what the old focused application was, stop waiting on it because it is
+    // no longer focused.
+    resetNoFocusedWindowTimeoutLocked();
+}
+
 /**
  * Sets the focused display, which is responsible for receiving focus-dispatched input events where
  * the display not specified.
@@ -6208,4 +6212,19 @@
     mLock.lock();
 }
 
+void InputDispatcher::displayRemoved(int32_t displayId) {
+    { // acquire lock
+        std::scoped_lock _l(mLock);
+        // Set an empty list to remove all handles from the specific display.
+        setInputWindowsLocked(/* window handles */ {}, displayId);
+        setFocusedApplicationLocked(displayId, nullptr);
+        // Call focus resolver to clean up stale requests. This must be called after input windows
+        // have been removed for the removed display.
+        mFocusResolver.displayRemoved(displayId);
+    } // release lock
+
+    // Wake up poll loop since it may need to make new input dispatching choices.
+    mLooper->wake();
+}
+
 } // namespace android::inputdispatcher
diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h
index bb3f3e6..9edf41c 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.h
+++ b/services/inputflinger/dispatcher/InputDispatcher.h
@@ -139,6 +139,8 @@
 
     std::array<uint8_t, 32> sign(const VerifiedInputEvent& event) const;
 
+    void displayRemoved(int32_t displayId) override;
+
 private:
     enum class DropReason {
         NOT_DROPPED,
@@ -343,6 +345,9 @@
     std::unordered_map<int32_t, TouchState> mTouchStatesByDisplay GUARDED_BY(mLock);
     std::unique_ptr<DragState> mDragState GUARDED_BY(mLock);
 
+    void setFocusedApplicationLocked(
+            int32_t displayId,
+            const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle) REQUIRES(mLock);
     // Focused applications.
     std::unordered_map<int32_t, std::shared_ptr<InputApplicationHandle>>
             mFocusedApplicationHandlesByDisplay GUARDED_BY(mLock);
diff --git a/services/inputflinger/dispatcher/include/InputDispatcherInterface.h b/services/inputflinger/dispatcher/include/InputDispatcherInterface.h
index 7f85e53..43428a0 100644
--- a/services/inputflinger/dispatcher/include/InputDispatcherInterface.h
+++ b/services/inputflinger/dispatcher/include/InputDispatcherInterface.h
@@ -209,6 +209,11 @@
      * Returns true on success.
      */
     virtual bool flushSensor(int deviceId, InputDeviceSensorType sensorType) = 0;
+
+    /**
+     * Called when a display has been removed from the system.
+     */
+    virtual void displayRemoved(int32_t displayId) = 0;
 };
 
 } // namespace android
diff --git a/services/inputflinger/tests/FocusResolver_test.cpp b/services/inputflinger/tests/FocusResolver_test.cpp
index 17efb5b..9051ff1 100644
--- a/services/inputflinger/tests/FocusResolver_test.cpp
+++ b/services/inputflinger/tests/FocusResolver_test.cpp
@@ -256,5 +256,37 @@
     // dropped.
     ASSERT_FALSE(changes);
 }
+TEST(FocusResolverTest, FocusRequestsAreClearedWhenWindowIsRemoved) {
+    sp<IBinder> windowToken = new BBinder();
+    std::vector<sp<InputWindowHandle>> windows;
+
+    sp<FakeWindowHandle> window = new FakeWindowHandle("Test Window", windowToken,
+                                                       true /* focusable */, true /* visible */);
+    windows.push_back(window);
+
+    FocusRequest request;
+    request.displayId = 42;
+    request.token = windowToken;
+    FocusResolver focusResolver;
+    std::optional<FocusResolver::FocusChanges> changes =
+            focusResolver.setFocusedWindow(request, windows);
+    ASSERT_FOCUS_CHANGE(changes, /*from*/ nullptr, /*to*/ windowToken);
+    ASSERT_EQ(request.displayId, changes->displayId);
+
+    // Start with a focused window
+    window->setFocusable(true);
+    changes = focusResolver.setInputWindows(request.displayId, windows);
+    ASSERT_FOCUS_CHANGE(changes, /*from*/ nullptr, /*to*/ windowToken);
+
+    // When a display is removed, all windows are removed from the display
+    // and our focused window loses focus
+    changes = focusResolver.setInputWindows(request.displayId, {});
+    ASSERT_FOCUS_CHANGE(changes, /*from*/ windowToken, /*to*/ nullptr);
+    focusResolver.displayRemoved(request.displayId);
+
+    // When a display is readded, the window does not get focus since the request was cleared.
+    changes = focusResolver.setInputWindows(request.displayId, windows);
+    ASSERT_FALSE(changes);
+}
 
 } // namespace android::inputdispatcher
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index d51acce..77ca12c 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -2688,6 +2688,23 @@
     window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
 }
 
+TEST_F(InputDispatcherTest, DisplayRemoved) {
+    std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
+    sp<FakeWindowHandle> window =
+            new FakeWindowHandle(application, mDispatcher, "window", ADISPLAY_ID_DEFAULT);
+    mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
+
+    // window is granted focus.
+    window->setFocusable(true);
+    mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
+    setFocusedWindow(window);
+    window->consumeFocusEvent(true);
+
+    // When a display is removed window loses focus.
+    mDispatcher->displayRemoved(ADISPLAY_ID_DEFAULT);
+    window->consumeFocusEvent(false);
+}
+
 /**
  * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
  * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
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 f8af908..6b5cf04 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -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() {
@@ -257,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 {
@@ -266,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) {
@@ -336,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);
         }
@@ -361,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,
@@ -383,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;
@@ -397,8 +402,8 @@
 
     mRequestedTransform.set(x, y);
 
-    mCurrentState.sequence++;
-    mCurrentState.modified = true;
+    mDrawingState.sequence++;
+    mDrawingState.modified = true;
     setTransactionFlags(eTransactionNeeded);
 
     return true;
@@ -410,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);
@@ -425,38 +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,
+            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;
@@ -483,61 +489,67 @@
                                                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;
-    setTransactionFlags(eTransactionNeeded);
+    if (mDrawingState.sidebandStream == sidebandStream) return false;
 
+    if (mDrawingState.sidebandStream != nullptr && sidebandStream == nullptr) {
+        mFlinger->mTunnelModeEnabledReporter->decrementTunnelModeCount();
+    } else if (sidebandStream != nullptr) {
+        mFlinger->mTunnelModeEnabledReporter->incrementTunnelModeCount();
+    }
+
+    mDrawingState.sidebandStream = sidebandStream;
+    mDrawingState.modified = true;
+    setTransactionFlags(eTransactionNeeded);
     if (!mSidebandStreamChanged.exchange(true)) {
         // mSidebandStreamChanged was false
         mFlinger->signalLayerUpdate();
@@ -563,14 +575,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
@@ -585,8 +597,8 @@
 }
 
 bool BufferStateLayer::setTransparentRegionHint(const Region& transparent) {
-    mCurrentState.transparentRegionHint = transparent;
-    mCurrentState.modified = true;
+    mDrawingState.transparentRegionHint = transparent;
+    mDrawingState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
@@ -645,7 +657,7 @@
         return true;
     }
 
-    return mCurrentState.isAutoTimestamp || mCurrentState.desiredPresentTime <= expectedPresentTime;
+    return mDrawingState.isAutoTimestamp || mDrawingState.desiredPresentTime <= expectedPresentTime;
 }
 
 bool BufferStateLayer::onPreComposition(nsecs_t refreshStartTime) {
@@ -674,7 +686,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
@@ -682,7 +694,7 @@
  * to apply.
  */
 uint64_t BufferStateLayer::getHeadFrameNumber(nsecs_t /* expectedPresentTime */) const {
-    return mCurrentState.frameNumber;
+    return mDrawingState.frameNumber;
 }
 
 void BufferStateLayer::setAutoRefresh(bool autoRefresh) {
@@ -712,8 +724,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,
@@ -756,6 +768,7 @@
         addSurfaceFramePresentedForBuffer(bufferSurfaceFrame,
                                           mDrawingState.acquireFenceTime->getSignalTime(),
                                           latchTime);
+        mDrawingState.bufferSurfaceFrameTX.reset();
     }
 
     std::deque<sp<CallbackHandle>> remainingHandles;
@@ -763,7 +776,7 @@
             .finalizeOnCommitCallbackHandles(mDrawingState.callbackHandles, remainingHandles);
     mDrawingState.callbackHandles = remainingHandles;
 
-    mCurrentStateModified = false;
+    mDrawingStateModified = false;
 
     return NO_ERROR;
 }
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..ad31b3f 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -70,6 +70,7 @@
 #include "MonitoredProducer.h"
 #include "SurfaceFlinger.h"
 #include "TimeStats/TimeStats.h"
+#include "TunnelModeEnabledReporter.h"
 #include "input/InputWindow.h"
 
 #define DEBUG_RESIZE 0
@@ -98,52 +99,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);
@@ -175,6 +173,10 @@
 
     mFrameTracker.logAndResetStats(mName);
     mFlinger->onLayerDestroyed(this);
+
+    if (mDrawingState.sidebandStream != nullptr) {
+        mFlinger->mTunnelModeEnabledReporter->decrementTunnelModeCount();
+    }
 }
 
 LayerCreationArgs::LayerCreationArgs(SurfaceFlinger* flinger, sp<Client> client, std::string name,
@@ -203,11 +205,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 +223,8 @@
 }
 
 void Layer::removeFromCurrentState() {
-    if (!mRemovedFromCurrentState) {
-        mRemovedFromCurrentState = true;
+    if (!mRemovedFromDrawingState) {
+        mRemovedFromDrawingState = true;
         mFlinger->mScheduler->deregisterLayer(this);
     }
 
@@ -249,8 +251,8 @@
 }
 
 void Layer::addToCurrentState() {
-    if (mRemovedFromCurrentState) {
-        mRemovedFromCurrentState = false;
+    if (mRemovedFromDrawingState) {
+        mRemovedFromDrawingState = false;
         mFlinger->mScheduler->registerLayer(this);
     }
 
@@ -679,158 +681,36 @@
 // 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();
 
-    if (mChildrenChanged) {
-        flags |= eVisibleRegion;
-        mChildrenChanged = false;
-    }
-
     // 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) {
-        flags |= eInputInfoChanged;
-        mCurrentState.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 +721,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 +735,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 +772,16 @@
 }
 
 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;
+
+    mFlinger->mSomeChildrenChanged = 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 +792,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 +824,18 @@
         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;
+    mFlinger->mSomeChildrenChanged = true;
 
-    auto oldZOrderRelativeOf = mCurrentState.zOrderRelativeOf.promote();
+    mDrawingState.sequence++;
+    mDrawingState.modified = true;
+    mDrawingState.z = relativeZ;
+
+    auto oldZOrderRelativeOf = mDrawingState.zOrderRelativeOf.promote();
     if (oldZOrderRelativeOf != nullptr) {
         oldZOrderRelativeOf->removeZOrderRelative(this);
     }
@@ -975,82 +848,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 +938,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 +1045,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 +1071,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 +1113,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 +1132,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 +1146,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 +1162,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 +1199,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 +1264,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 +1550,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);
     }
@@ -1681,7 +1561,7 @@
 }
 
 void Layer::addChild(const sp<Layer>& layer) {
-    mChildrenChanged = true;
+    mFlinger->mSomeChildrenChanged = true;
     setTransactionFlags(eTransactionNeeded);
 
     mCurrentChildren.add(layer);
@@ -1691,7 +1571,7 @@
 }
 
 ssize_t Layer::removeChild(const sp<Layer>& layer) {
-    mChildrenChanged = true;
+    mFlinger->mSomeChildrenChanged = true;
     setTransactionFlags(eTransactionNeeded);
 
     layer->setParent(nullptr);
@@ -1749,13 +1629,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 +1667,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 +1683,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 +1782,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 +1794,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 +1807,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 +1875,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 +1987,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;
+    mFlinger->mInputInfoChanged = true;
     setTransactionFlags(eTransactionNeeded);
 }
 
@@ -2190,7 +2068,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 +2156,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..ec9bb7c 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -1,3 +1,4 @@
+
 /*
  * Copyright (C) 2007 The Android Open Source Project
  *
@@ -185,7 +186,6 @@
         float cornerRadius;
         int backgroundBlurRadius;
 
-        bool inputInfoChanged;
         InputWindowInfo inputInfo;
         wp<Layer> touchableRegionCrop;
 
@@ -732,8 +732,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 +883,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 +901,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 +956,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 +983,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,17 +996,12 @@
     // 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 mDrawingChildren{LayerVector::StateSet::Drawing};
 
     wp<Layer> mCurrentParent;
     wp<Layer> mDrawingParent;
 
-    // Can only be accessed with the SF state lock held.
-    bool mChildrenChanged{false};
-
     // Window types from WindowManager.LayoutParams
     const InputWindowInfo::Type mWindowType;
 
@@ -1022,7 +1017,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/MonitoredProducer.cpp b/services/surfaceflinger/MonitoredProducer.cpp
index 18a2891..6b2d745 100644
--- a/services/surfaceflinger/MonitoredProducer.cpp
+++ b/services/surfaceflinger/MonitoredProducer.cpp
@@ -140,6 +140,11 @@
             outTransformMatrix);
 }
 
+status_t MonitoredProducer::getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer, sp<Fence>* outFence,
+                                                Rect* outRect, uint32_t* outTransform) {
+    return mProducer->getLastQueuedBuffer(outBuffer, outFence, outRect, outTransform);
+}
+
 void MonitoredProducer::getFrameTimestamps(FrameEventHistoryDelta* outDelta) {
     mProducer->getFrameTimestamps(outDelta);
 }
diff --git a/services/surfaceflinger/MonitoredProducer.h b/services/surfaceflinger/MonitoredProducer.h
index 788919b..3778277 100644
--- a/services/surfaceflinger/MonitoredProducer.h
+++ b/services/surfaceflinger/MonitoredProducer.h
@@ -64,6 +64,8 @@
     virtual status_t setLegacyBufferDrop(bool drop) override;
     virtual status_t getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer,
             sp<Fence>* outFence, float outTransformMatrix[16]) override;
+    virtual status_t getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer, sp<Fence>* outFence,
+                                         Rect* outRect, uint32_t* outTransform) override;
     virtual IBinder* onAsBinder();
     virtual status_t setSharedBufferMode(bool sharedBufferMode) override;
     virtual status_t setAutoRefresh(bool autoRefresh) override;
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 0234dbc..0eb16e2 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
@@ -867,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/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index e7187b1..a022a8e 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -342,6 +342,7 @@
         mEventQueue(mFactory.createMessageQueue()),
         mCompositionEngine(mFactory.createCompositionEngine()),
         mHwcServiceName(base::GetProperty("debug.sf.hwc_service_name"s, "default"s)),
+        mTunnelModeEnabledReporter(new TunnelModeEnabledReporter()),
         mInternalDisplayDensity(getDensityFromProperty("ro.sf.lcd_density", true)),
         mEmulatedDisplayDensity(getDensityFromProperty("qemu.sf.lcd_density", false)) {
     ALOGI("Using HWComposer service: %s", mHwcServiceName.c_str());
@@ -2231,18 +2232,15 @@
 
     getBE().mDisplayTimeline.push(mPreviousPresentFences[0].fenceTime);
 
+    nsecs_t now = systemTime();
+
     // Set presentation information before calling Layer::releasePendingBuffer, such that jank
     // information from previous' frame classification is already available when sending jank info
     // to clients, so they get jank classification as early as possible.
-    mFrameTimeline->setSfPresent(systemTime(), mPreviousPresentFences[0].fenceTime,
+    mFrameTimeline->setSfPresent(/* sfPresentTime */ now, mPreviousPresentFences[0].fenceTime,
                                  glCompositionDoneFenceTime);
 
-    nsecs_t dequeueReadyTime = systemTime();
-    for (const auto& layer : mLayersWithQueuedFrames) {
-        layer->releasePendingBuffer(dequeueReadyTime);
-    }
-
-    const DisplayStatInfo stats = mScheduler->getDisplayStatInfo(systemTime());
+    const DisplayStatInfo stats = mScheduler->getDisplayStatInfo(now);
 
     // We use the CompositionEngine::getLastFrameRefreshTimestamp() which might
     // be sampled a little later than when we started doing work for this frame,
@@ -2259,6 +2257,7 @@
         const bool frameLatched =
                 layer->onPostComposition(display, glCompositionDoneFenceTime,
                                          mPreviousPresentFences[0].fenceTime, compositorTiming);
+        layer->releasePendingBuffer(/*dequeueReadyTime*/ now);
         if (frameLatched) {
             recordBufferingStats(layer->getName(), layer->getOccupancyHistory(false));
         }
@@ -2859,7 +2858,9 @@
             (currentState.orientedDisplaySpaceRect != drawingState.orientedDisplaySpaceRect)) {
             display->setProjection(currentState.orientation, currentState.layerStackSpaceRect,
                                    currentState.orientedDisplaySpaceRect);
-            mDefaultDisplayTransformHint = display->getTransformHint();
+            if (display->isPrimary()) {
+                mDefaultDisplayTransformHint = display->getTransformHint();
+            }
         }
         if (currentState.width != drawingState.width ||
             currentState.height != drawingState.height) {
@@ -2923,23 +2924,12 @@
         processDisplayChangesLocked();
         processDisplayHotplugEventsLocked();
     }
+    mForceTraversal = false;
+    mForceTransactionDisplayChange = displayTransactionNeeded;
 
-    // Commit layer transactions. This needs to happen after display transactions are
-    // committed because some geometry logic relies on display orientation.
-    if ((transactionFlags & eTraversalNeeded) || mForceTraversal || displayTransactionNeeded) {
-        mForceTraversal = false;
-        mCurrentState.traverse([&](Layer* layer) {
-            uint32_t trFlags = layer->getTransactionFlags(eTransactionNeeded);
-            if (!trFlags && !displayTransactionNeeded) return;
-
-            const uint32_t flags = layer->doTransaction(0);
-            if (flags & Layer::eVisibleRegion)
-                mVisibleRegionsDirty = true;
-
-            if (flags & Layer::eInputInfoChanged) {
-                mInputInfoChanged = true;
-            }
-        });
+    if (mSomeChildrenChanged) {
+        mVisibleRegionsDirty = true;
+        mSomeChildrenChanged = false;
     }
 
     // Update transform hint
@@ -3164,7 +3154,6 @@
     mRegionSamplingThread =
             new RegionSamplingThread(*this, RegionSamplingThread::EnvironmentTimingTunables());
     mFpsReporter = new FpsReporter(*mFrameTimeline, *this);
-    mTunnelModeEnabledReporter = new TunnelModeEnabledReporter(*this);
     // Dispatch a mode change request for the primary display on scheduler
     // initialization, so that the EventThreads always contain a reference to a
     // prior configuration.
@@ -3200,6 +3189,7 @@
 }
 
 void SurfaceFlinger::commitTransaction() {
+    ATRACE_CALL();
     commitTransactionLocked();
     signalSynchronousTransactions(CountDownLatch::eSyncTransaction);
     mAnimTransactionPending = false;
@@ -3234,9 +3224,12 @@
     // clear the "changed" flags in current state
     mCurrentState.colorMatrixChanged = false;
 
-    for (const auto& rootLayer : mDrawingState.layersSortedByZ) {
-        rootLayer->commitChildList();
+    if (mVisibleRegionsDirty) {
+        for (const auto& rootLayer : mDrawingState.layersSortedByZ) {
+            rootLayer->commitChildList();
+        }
     }
+
     // TODO(b/163019109): See if this traversal is needed at all...
     if (!mOffscreenLayers.empty()) {
         mDrawingState.traverse([&](Layer* layer) {
@@ -3295,7 +3288,14 @@
     // Display is now waiting on Layer 1's frame, which is behind layer 0's
     // second frame. But layer 0's second frame could be waiting on display.
     mDrawingState.traverse([&](Layer* layer) {
-        if (layer->hasReadyFrame()) {
+         uint32_t trFlags = layer->getTransactionFlags(eTransactionNeeded);
+         if (trFlags || mForceTransactionDisplayChange) {
+             const uint32_t flags = layer->doTransaction(0);
+             if (flags & Layer::eVisibleRegion)
+                 mVisibleRegionsDirty = true;
+         }
+
+         if (layer->hasReadyFrame()) {
             frameQueued = true;
             if (layer->shouldPresentNow(expectedPresentTime)) {
                 mLayersWithQueuedFrames.emplace(layer);
@@ -3303,10 +3303,11 @@
                 ATRACE_NAME("!layer->shouldPresentNow()");
                 layer->useEmptyDamage();
             }
-        } else {
+         } else {
             layer->useEmptyDamage();
         }
     });
+    mForceTransactionDisplayChange = false;
 
     // The client can continue submitting buffers for offscreen layers, but they will not
     // be shown on screen. Therefore, we need to latch and release buffers of offscreen
@@ -4467,10 +4468,11 @@
     d.height = 0;
     displays.add(d);
 
+    nsecs_t now = systemTime();
     // It should be on the main thread, apply it directly.
     applyTransactionState(FrameTimelineInfo{}, state, displays, 0, mInputWindowCommands,
-                          systemTime(), true, {}, systemTime(), true, false, {}, getpid(), getuid(),
-                          0 /* Undefined transactionId */);
+                          /* desiredPresentTime */ now, true, {}, /* postTime */ now, true, false,
+                          {}, getpid(), getuid(), 0 /* Undefined transactionId */);
 
     setPowerModeInternal(display, hal::PowerMode::ON);
     const nsecs_t vsyncPeriod = mRefreshRateConfigs->getCurrentRefreshRate().getVsyncPeriod();
@@ -5810,8 +5812,6 @@
                 mKernelIdleTimerEnabled = true;
             }
             break;
-        case KernelIdleTimerAction::NoChange:
-            break;
     }
 }
 
@@ -6050,12 +6050,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();
@@ -6294,7 +6294,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{
@@ -6909,6 +6909,8 @@
         parent->addChild(layer);
     }
 
+    layer->updateTransformHint(mDefaultDisplayTransformHint);
+
     if (state->initialProducer != nullptr) {
         mGraphicBufferProducerList.insert(state->initialProducer);
         LOG_ALWAYS_FATAL_IF(mGraphicBufferProducerList.size() > mMaxGraphicBufferProducerListSize,
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 22d17eb..f33df86 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -364,6 +364,7 @@
     // For unit tests
     friend class TestableSurfaceFlinger;
     friend class TransactionApplicationTest;
+    friend class TunnelModeEnabledReporterTest;
 
     using RefreshRate = scheduler::RefreshRateConfigs::RefreshRate;
     using VsyncModulator = scheduler::VsyncModulator;
@@ -1228,8 +1229,14 @@
     // don't need synchronization
     State mDrawingState{LayerVector::StateSet::Drawing};
     bool mVisibleRegionsDirty = false;
-    // Set during transaction commit stage to track if the input info for a layer has changed.
+
+    // Set during transaction application stage to track if the input info or children
+    // for a layer has changed.
+    // TODO: Also move visibleRegions over to a boolean system.
     bool mInputInfoChanged = false;
+    bool mSomeChildrenChanged;
+    bool mForceTransactionDisplayChange = false;
+
     bool mGeometryInvalid = false;
     bool mAnimCompositionPending = false;
 
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/TunnelModeEnabledReporter.cpp b/services/surfaceflinger/TunnelModeEnabledReporter.cpp
index 1b3ddf7..4497caf 100644
--- a/services/surfaceflinger/TunnelModeEnabledReporter.cpp
+++ b/services/surfaceflinger/TunnelModeEnabledReporter.cpp
@@ -26,17 +26,10 @@
 
 namespace android {
 
-TunnelModeEnabledReporter::TunnelModeEnabledReporter(SurfaceFlinger& flinger) : mFlinger(flinger) {}
+TunnelModeEnabledReporter::TunnelModeEnabledReporter() {}
 
 void TunnelModeEnabledReporter::updateTunnelModeStatus() {
-    bool tunnelModeEnabled = false;
-    mFlinger.mCurrentState.traverse([&](Layer* layer) {
-        auto& currentState = layer->getCurrentState();
-        if (currentState.sidebandStream != nullptr) {
-            tunnelModeEnabled = true;
-            return;
-        }
-    });
+    bool tunnelModeEnabled = mTunnelModeCount > 0;
     dispatchTunnelModeEnabled(tunnelModeEnabled);
 }
 
diff --git a/services/surfaceflinger/TunnelModeEnabledReporter.h b/services/surfaceflinger/TunnelModeEnabledReporter.h
index d55507a..935502a 100644
--- a/services/surfaceflinger/TunnelModeEnabledReporter.h
+++ b/services/surfaceflinger/TunnelModeEnabledReporter.h
@@ -29,7 +29,7 @@
 
 class TunnelModeEnabledReporter : public IBinder::DeathRecipient {
 public:
-    TunnelModeEnabledReporter(SurfaceFlinger& flinger);
+    TunnelModeEnabledReporter();
 
     // Checks if there is a tunnel mode enabled state change and if so, dispatches the updated
     // tunnel mode enabled/disabled state to the registered listeners
@@ -49,6 +49,9 @@
     // Deregisters a TunnelModeEnabled listener
     void removeListener(const sp<gui::ITunnelModeEnabledListener>& listener);
 
+    inline void incrementTunnelModeCount() { mTunnelModeCount++; }
+    inline void decrementTunnelModeCount() { mTunnelModeCount--; }
+
 private:
     mutable std::mutex mMutex;
     struct WpHash {
@@ -57,10 +60,10 @@
         }
     };
 
-    SurfaceFlinger& mFlinger;
     std::unordered_map<wp<IBinder>, sp<gui::ITunnelModeEnabledListener>, WpHash> mListeners
             GUARDED_BY(mMutex);
     bool mTunnelModeEnabled GUARDED_BY(mMutex) = false;
+    uint32_t mTunnelModeCount = 0;
 };
 
 } // namespace android
diff --git a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
index 4e00e66..d4b229f 100644
--- a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
+++ b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
@@ -1897,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/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 b363146..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;
     }
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/TunnelModeEnabledReporterTest.cpp b/services/surfaceflinger/tests/unittests/TunnelModeEnabledReporterTest.cpp
index d7d7ea7..e4f7469 100644
--- a/services/surfaceflinger/tests/unittests/TunnelModeEnabledReporterTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TunnelModeEnabledReporterTest.cpp
@@ -27,6 +27,7 @@
 #include "TunnelModeEnabledReporter.h"
 #include "mock/DisplayHardware/MockComposer.h"
 #include "mock/MockEventThread.h"
+#include "mock/MockMessageQueue.h"
 
 namespace android {
 
@@ -71,15 +72,20 @@
     sp<TestableTunnelModeEnabledListener> mTunnelModeEnabledListener =
             new TestableTunnelModeEnabledListener();
     sp<TunnelModeEnabledReporter> mTunnelModeEnabledReporter =
-            new TunnelModeEnabledReporter(*(mFlinger.flinger()));
+            new TunnelModeEnabledReporter();
+
+    mock::MessageQueue* mMessageQueue = new mock::MessageQueue();
 };
 
 TunnelModeEnabledReporterTest::TunnelModeEnabledReporterTest() {
     const ::testing::TestInfo* const test_info =
             ::testing::UnitTest::GetInstance()->current_test_info();
     ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name());
+
+    mFlinger.mutableEventQueue().reset(mMessageQueue);
     setupScheduler();
     mFlinger.setupComposer(std::make_unique<Hwc2::mock::Composer>());
+    mFlinger.flinger()->mTunnelModeEnabledReporter = mTunnelModeEnabledReporter;
     mTunnelModeEnabledReporter->dispatchTunnelModeEnabled(false);
 }
 
@@ -156,16 +162,18 @@
     sp<NativeHandle> stream =
             NativeHandle::create(reinterpret_cast<native_handle_t*>(DEFAULT_SIDEBAND_STREAM),
                                  false);
-    mFlinger.setLayerSidebandStream(layer, stream);
+    layer->setSidebandStream(stream);
     mFlinger.mutableCurrentState().layersSortedByZ.add(layer);
     mTunnelModeEnabledReporter->updateTunnelModeStatus();
     mTunnelModeEnabledReporter->addListener(mTunnelModeEnabledListener);
     EXPECT_EQ(true, mTunnelModeEnabledListener->mTunnelModeEnabled);
     mTunnelModeEnabledReporter->removeListener(mTunnelModeEnabledListener);
-
     mFlinger.mutableCurrentState().layersSortedByZ.remove(layer);
+    layer = nullptr;
+
     mTunnelModeEnabledReporter->updateTunnelModeStatus();
     mTunnelModeEnabledReporter->addListener(mTunnelModeEnabledListener);
+
     EXPECT_EQ(false, mTunnelModeEnabledListener->mTunnelModeEnabled);
 }
 
@@ -178,7 +186,7 @@
     sp<NativeHandle> stream =
             NativeHandle::create(reinterpret_cast<native_handle_t*>(DEFAULT_SIDEBAND_STREAM),
                                  false);
-    mFlinger.setLayerSidebandStream(layerWithSidebandStream, stream);
+    layerWithSidebandStream->setSidebandStream(stream);
 
     mFlinger.mutableCurrentState().layersSortedByZ.add(simpleLayer);
     mFlinger.mutableCurrentState().layersSortedByZ.add(layerWithSidebandStream);
@@ -186,6 +194,7 @@
     EXPECT_EQ(true, mTunnelModeEnabledListener->mTunnelModeEnabled);
 
     mFlinger.mutableCurrentState().layersSortedByZ.remove(layerWithSidebandStream);
+    layerWithSidebandStream = nullptr;
     mTunnelModeEnabledReporter->updateTunnelModeStatus();
     EXPECT_EQ(false, mTunnelModeEnabledListener->mTunnelModeEnabled);
 }
diff --git a/services/vibratorservice/VibratorHalWrapper.cpp b/services/vibratorservice/VibratorHalWrapper.cpp
index f15a963..a375808 100644
--- a/services/vibratorservice/VibratorHalWrapper.cpp
+++ b/services/vibratorservice/VibratorHalWrapper.cpp
@@ -135,6 +135,18 @@
     if (mInfoCache.mSupportedBraking.isFailed()) {
         mInfoCache.mSupportedBraking = getSupportedBrakingInternal();
     }
+    if (mInfoCache.mPrimitiveDelayMax.isFailed()) {
+        mInfoCache.mPrimitiveDelayMax = getPrimitiveDelayMaxInternal();
+    }
+    if (mInfoCache.mPwlePrimitiveDurationMax.isFailed()) {
+        mInfoCache.mPwlePrimitiveDurationMax = getPrimitiveDurationMaxInternal();
+    }
+    if (mInfoCache.mCompositionSizeMax.isFailed()) {
+        mInfoCache.mCompositionSizeMax = getCompositionSizeMaxInternal();
+    }
+    if (mInfoCache.mPwleSizeMax.isFailed()) {
+        mInfoCache.mPwleSizeMax = getPwleSizeMaxInternal();
+    }
     if (mInfoCache.mMinFrequency.isFailed()) {
         mInfoCache.mMinFrequency = getMinFrequencyInternal();
     }
@@ -209,6 +221,26 @@
     return HalResult<std::vector<milliseconds>>::unsupported();
 }
 
+HalResult<milliseconds> HalWrapper::getPrimitiveDelayMaxInternal() {
+    ALOGV("Skipped getPrimitiveDelayMaxInternal because it's not available in Vibrator HAL");
+    return HalResult<milliseconds>::unsupported();
+}
+
+HalResult<milliseconds> HalWrapper::getPrimitiveDurationMaxInternal() {
+    ALOGV("Skipped getPrimitiveDurationMaxInternal because it's not available in Vibrator HAL");
+    return HalResult<milliseconds>::unsupported();
+}
+
+HalResult<int32_t> HalWrapper::getCompositionSizeMaxInternal() {
+    ALOGV("Skipped getCompositionSizeMaxInternal because it's not available in Vibrator HAL");
+    return HalResult<int32_t>::unsupported();
+}
+
+HalResult<int32_t> HalWrapper::getPwleSizeMaxInternal() {
+    ALOGV("Skipped getPwleSizeMaxInternal because it's not available in Vibrator HAL");
+    return HalResult<int32_t>::unsupported();
+}
+
 HalResult<float> HalWrapper::getMinFrequencyInternal() {
     ALOGV("Skipped getMinFrequency because it's not available in Vibrator HAL");
     return HalResult<float>::unsupported();
@@ -383,6 +415,30 @@
     return HalResult<std::vector<milliseconds>>::ok(durations);
 }
 
+HalResult<milliseconds> AidlHalWrapper::getPrimitiveDelayMaxInternal() {
+    int32_t delay = 0;
+    auto result = getHal()->getCompositionDelayMax(&delay);
+    return HalResult<milliseconds>::fromStatus(result, milliseconds(delay));
+}
+
+HalResult<milliseconds> AidlHalWrapper::getPrimitiveDurationMaxInternal() {
+    int32_t delay = 0;
+    auto result = getHal()->getPwlePrimitiveDurationMax(&delay);
+    return HalResult<milliseconds>::fromStatus(result, milliseconds(delay));
+}
+
+HalResult<int32_t> AidlHalWrapper::getCompositionSizeMaxInternal() {
+    int32_t size = 0;
+    auto result = getHal()->getCompositionSizeMax(&size);
+    return HalResult<int32_t>::fromStatus(result, size);
+}
+
+HalResult<int32_t> AidlHalWrapper::getPwleSizeMaxInternal() {
+    int32_t size = 0;
+    auto result = getHal()->getPwleCompositionSizeMax(&size);
+    return HalResult<int32_t>::fromStatus(result, size);
+}
+
 HalResult<float> AidlHalWrapper::getMinFrequencyInternal() {
     float minFrequency = 0;
     auto result = getHal()->getFrequencyMinimum(&minFrequency);
diff --git a/services/vibratorservice/include/vibratorservice/VibratorHalWrapper.h b/services/vibratorservice/include/vibratorservice/VibratorHalWrapper.h
index 87bc34e..68d6647 100644
--- a/services/vibratorservice/include/vibratorservice/VibratorHalWrapper.h
+++ b/services/vibratorservice/include/vibratorservice/VibratorHalWrapper.h
@@ -182,6 +182,10 @@
     const HalResult<std::vector<hardware::vibrator::Braking>> supportedBraking;
     const HalResult<std::vector<hardware::vibrator::CompositePrimitive>> supportedPrimitives;
     const HalResult<std::vector<std::chrono::milliseconds>> primitiveDurations;
+    const HalResult<std::chrono::milliseconds> primitiveDelayMax;
+    const HalResult<std::chrono::milliseconds> pwlePrimitiveDurationMax;
+    const HalResult<int32_t> compositionSizeMax;
+    const HalResult<int32_t> pwleSizeMax;
     const HalResult<float> minFrequency;
     const HalResult<float> resonantFrequency;
     const HalResult<float> frequencyResolution;
@@ -194,6 +198,10 @@
                 supportedBraking.checkAndLogFailure("getSupportedBraking") ||
                 supportedPrimitives.checkAndLogFailure("getSupportedPrimitives") ||
                 primitiveDurations.checkAndLogFailure("getPrimitiveDuration") ||
+                primitiveDelayMax.checkAndLogFailure("getPrimitiveDelayMax") ||
+                pwlePrimitiveDurationMax.checkAndLogFailure("getPwlePrimitiveDurationMax") ||
+                compositionSizeMax.checkAndLogFailure("getCompositionSizeMax") ||
+                pwleSizeMax.checkAndLogFailure("getPwleSizeMax") ||
                 minFrequency.checkAndLogFailure("getMinFrequency") ||
                 resonantFrequency.checkAndLogFailure("getResonantFrequency") ||
                 frequencyResolution.checkAndLogFailure("getFrequencyResolution") ||
@@ -205,9 +213,19 @@
 class InfoCache {
 public:
     Info get() {
-        return {mCapabilities,        mSupportedEffects,    mSupportedBraking,
-                mSupportedPrimitives, mPrimitiveDurations,  mMinFrequency,
-                mResonantFrequency,   mFrequencyResolution, mQFactor,
+        return {mCapabilities,
+                mSupportedEffects,
+                mSupportedBraking,
+                mSupportedPrimitives,
+                mPrimitiveDurations,
+                mPrimitiveDelayMax,
+                mPwlePrimitiveDurationMax,
+                mCompositionSizeMax,
+                mPwleSizeMax,
+                mMinFrequency,
+                mResonantFrequency,
+                mFrequencyResolution,
+                mQFactor,
                 mMaxAmplitudes};
     }
 
@@ -222,6 +240,12 @@
             HalResult<std::vector<hardware::vibrator::CompositePrimitive>>::failed(MSG);
     HalResult<std::vector<std::chrono::milliseconds>> mPrimitiveDurations =
             HalResult<std::vector<std::chrono::milliseconds>>::failed(MSG);
+    HalResult<std::chrono::milliseconds> mPrimitiveDelayMax =
+            HalResult<std::chrono::milliseconds>::failed(MSG);
+    HalResult<std::chrono::milliseconds> mPwlePrimitiveDurationMax =
+            HalResult<std::chrono::milliseconds>::failed(MSG);
+    HalResult<int32_t> mCompositionSizeMax = HalResult<int>::failed(MSG);
+    HalResult<int32_t> mPwleSizeMax = HalResult<int>::failed(MSG);
     HalResult<float> mMinFrequency = HalResult<float>::failed(MSG);
     HalResult<float> mResonantFrequency = HalResult<float>::failed(MSG);
     HalResult<float> mFrequencyResolution = HalResult<float>::failed(MSG);
@@ -285,6 +309,10 @@
     getSupportedPrimitivesInternal();
     virtual HalResult<std::vector<std::chrono::milliseconds>> getPrimitiveDurationsInternal(
             const std::vector<hardware::vibrator::CompositePrimitive>& supportedPrimitives);
+    virtual HalResult<std::chrono::milliseconds> getPrimitiveDelayMaxInternal();
+    virtual HalResult<std::chrono::milliseconds> getPrimitiveDurationMaxInternal();
+    virtual HalResult<int32_t> getCompositionSizeMaxInternal();
+    virtual HalResult<int32_t> getPwleSizeMaxInternal();
     virtual HalResult<float> getMinFrequencyInternal();
     virtual HalResult<float> getResonantFrequencyInternal();
     virtual HalResult<float> getFrequencyResolutionInternal();
@@ -347,6 +375,10 @@
     HalResult<std::vector<std::chrono::milliseconds>> getPrimitiveDurationsInternal(
             const std::vector<hardware::vibrator::CompositePrimitive>& supportedPrimitives)
             override final;
+    HalResult<std::chrono::milliseconds> getPrimitiveDelayMaxInternal() override final;
+    HalResult<std::chrono::milliseconds> getPrimitiveDurationMaxInternal() override final;
+    HalResult<int32_t> getCompositionSizeMaxInternal() override final;
+    HalResult<int32_t> getPwleSizeMaxInternal() override final;
     HalResult<float> getMinFrequencyInternal() override final;
     HalResult<float> getResonantFrequencyInternal() override final;
     HalResult<float> getFrequencyResolutionInternal() override final;
diff --git a/services/vibratorservice/test/VibratorHalWrapperAidlTest.cpp b/services/vibratorservice/test/VibratorHalWrapperAidlTest.cpp
index 7813303..03c9e77 100644
--- a/services/vibratorservice/test/VibratorHalWrapperAidlTest.cpp
+++ b/services/vibratorservice/test/VibratorHalWrapperAidlTest.cpp
@@ -301,6 +301,10 @@
     constexpr float F0 = 123.f;
     constexpr float F_RESOLUTION = 0.5f;
     constexpr float Q_FACTOR = 123.f;
+    constexpr int32_t COMPOSITION_SIZE_MAX = 10;
+    constexpr int32_t PWLE_SIZE_MAX = 20;
+    constexpr int32_t PRIMITIVE_DELAY_MAX = 100;
+    constexpr int32_t PWLE_DURATION_MAX = 200;
     std::vector<Effect> supportedEffects = {Effect::CLICK, Effect::TICK};
     std::vector<CompositePrimitive> supportedPrimitives = {CompositePrimitive::CLICK};
     std::vector<Braking> supportedBraking = {Braking::CLAB};
@@ -331,6 +335,22 @@
     EXPECT_CALL(*mMockHal.get(), getPrimitiveDuration(Eq(CompositePrimitive::CLICK), _))
             .Times(Exactly(1))
             .WillRepeatedly(DoAll(SetArgPointee<1>(10), Return(Status())));
+    EXPECT_CALL(*mMockHal.get(), getCompositionSizeMax(_))
+            .Times(Exactly(2))
+            .WillOnce(Return(Status::fromExceptionCode(Status::Exception::EX_SECURITY)))
+            .WillRepeatedly(DoAll(SetArgPointee<0>(COMPOSITION_SIZE_MAX), Return(Status())));
+    EXPECT_CALL(*mMockHal.get(), getCompositionDelayMax(_))
+            .Times(Exactly(2))
+            .WillOnce(Return(Status::fromExceptionCode(Status::Exception::EX_SECURITY)))
+            .WillRepeatedly(DoAll(SetArgPointee<0>(PRIMITIVE_DELAY_MAX), Return(Status())));
+    EXPECT_CALL(*mMockHal.get(), getPwlePrimitiveDurationMax(_))
+            .Times(Exactly(2))
+            .WillOnce(Return(Status::fromExceptionCode(Status::Exception::EX_SECURITY)))
+            .WillRepeatedly(DoAll(SetArgPointee<0>(PWLE_DURATION_MAX), Return(Status())));
+    EXPECT_CALL(*mMockHal.get(), getPwleCompositionSizeMax(_))
+            .Times(Exactly(2))
+            .WillOnce(Return(Status::fromExceptionCode(Status::Exception::EX_SECURITY)))
+            .WillRepeatedly(DoAll(SetArgPointee<0>(PWLE_SIZE_MAX), Return(Status())));
     EXPECT_CALL(*mMockHal.get(), getFrequencyMinimum(_))
             .Times(Exactly(2))
             .WillOnce(Return(Status::fromExceptionCode(Status::Exception::EX_SECURITY)))
@@ -358,6 +378,10 @@
     ASSERT_TRUE(failed.supportedBraking.isFailed());
     ASSERT_TRUE(failed.supportedPrimitives.isFailed());
     ASSERT_TRUE(failed.primitiveDurations.isFailed());
+    ASSERT_TRUE(failed.primitiveDelayMax.isFailed());
+    ASSERT_TRUE(failed.pwlePrimitiveDurationMax.isFailed());
+    ASSERT_TRUE(failed.compositionSizeMax.isFailed());
+    ASSERT_TRUE(failed.pwleSizeMax.isFailed());
     ASSERT_TRUE(failed.minFrequency.isFailed());
     ASSERT_TRUE(failed.resonantFrequency.isFailed());
     ASSERT_TRUE(failed.frequencyResolution.isFailed());
@@ -370,6 +394,11 @@
     ASSERT_EQ(supportedBraking, successful.supportedBraking.value());
     ASSERT_EQ(supportedPrimitives, successful.supportedPrimitives.value());
     ASSERT_EQ(primitiveDurations, successful.primitiveDurations.value());
+    ASSERT_EQ(std::chrono::milliseconds(PRIMITIVE_DELAY_MAX), successful.primitiveDelayMax.value());
+    ASSERT_EQ(std::chrono::milliseconds(PWLE_DURATION_MAX),
+              successful.pwlePrimitiveDurationMax.value());
+    ASSERT_EQ(COMPOSITION_SIZE_MAX, successful.compositionSizeMax.value());
+    ASSERT_EQ(PWLE_SIZE_MAX, successful.pwleSizeMax.value());
     ASSERT_EQ(F_MIN, successful.minFrequency.value());
     ASSERT_EQ(F0, successful.resonantFrequency.value());
     ASSERT_EQ(F_RESOLUTION, successful.frequencyResolution.value());
@@ -380,6 +409,10 @@
 TEST_F(VibratorHalWrapperAidlTest, TestGetInfoCachesResult) {
     constexpr float F_MIN = 100.f;
     constexpr float F0 = 123.f;
+    constexpr int32_t COMPOSITION_SIZE_MAX = 10;
+    constexpr int32_t PWLE_SIZE_MAX = 20;
+    constexpr int32_t PRIMITIVE_DELAY_MAX = 100;
+    constexpr int32_t PWLE_DURATION_MAX = 200;
     std::vector<Effect> supportedEffects = {Effect::CLICK, Effect::TICK};
 
     EXPECT_CALL(*mMockHal.get(), getCapabilities(_))
@@ -395,6 +428,18 @@
     EXPECT_CALL(*mMockHal.get(), getSupportedPrimitives(_))
             .Times(Exactly(1))
             .WillRepeatedly(Return(Status::fromStatusT(UNKNOWN_TRANSACTION)));
+    EXPECT_CALL(*mMockHal.get(), getCompositionSizeMax(_))
+            .Times(Exactly(1))
+            .WillRepeatedly(DoAll(SetArgPointee<0>(COMPOSITION_SIZE_MAX), Return(Status())));
+    EXPECT_CALL(*mMockHal.get(), getCompositionDelayMax(_))
+            .Times(Exactly(1))
+            .WillRepeatedly(DoAll(SetArgPointee<0>(PRIMITIVE_DELAY_MAX), Return(Status())));
+    EXPECT_CALL(*mMockHal.get(), getPwlePrimitiveDurationMax(_))
+            .Times(Exactly(1))
+            .WillRepeatedly(DoAll(SetArgPointee<0>(PWLE_DURATION_MAX), Return(Status())));
+    EXPECT_CALL(*mMockHal.get(), getPwleCompositionSizeMax(_))
+            .Times(Exactly(1))
+            .WillRepeatedly(DoAll(SetArgPointee<0>(PWLE_SIZE_MAX), Return(Status())));
     EXPECT_CALL(*mMockHal.get(), getFrequencyMinimum(_))
             .Times(Exactly(1))
             .WillRepeatedly(DoAll(SetArgPointee<0>(F_MIN), Return(Status())));
@@ -426,6 +471,10 @@
     ASSERT_TRUE(info.supportedBraking.isUnsupported());
     ASSERT_TRUE(info.supportedPrimitives.isUnsupported());
     ASSERT_TRUE(info.primitiveDurations.isUnsupported());
+    ASSERT_EQ(std::chrono::milliseconds(PRIMITIVE_DELAY_MAX), info.primitiveDelayMax.value());
+    ASSERT_EQ(std::chrono::milliseconds(PWLE_DURATION_MAX), info.pwlePrimitiveDurationMax.value());
+    ASSERT_EQ(COMPOSITION_SIZE_MAX, info.compositionSizeMax.value());
+    ASSERT_EQ(PWLE_SIZE_MAX, info.pwleSizeMax.value());
     ASSERT_EQ(F_MIN, info.minFrequency.value());
     ASSERT_EQ(F0, info.resonantFrequency.value());
     ASSERT_TRUE(info.frequencyResolution.isUnsupported());
diff --git a/services/vibratorservice/test/VibratorHalWrapperHidlV1_0Test.cpp b/services/vibratorservice/test/VibratorHalWrapperHidlV1_0Test.cpp
index 96b2582..0c27fc7 100644
--- a/services/vibratorservice/test/VibratorHalWrapperHidlV1_0Test.cpp
+++ b/services/vibratorservice/test/VibratorHalWrapperHidlV1_0Test.cpp
@@ -206,6 +206,10 @@
     ASSERT_TRUE(info.supportedBraking.isUnsupported());
     ASSERT_TRUE(info.supportedPrimitives.isUnsupported());
     ASSERT_TRUE(info.primitiveDurations.isUnsupported());
+    ASSERT_TRUE(info.primitiveDelayMax.isUnsupported());
+    ASSERT_TRUE(info.pwlePrimitiveDurationMax.isUnsupported());
+    ASSERT_TRUE(info.compositionSizeMax.isUnsupported());
+    ASSERT_TRUE(info.pwleSizeMax.isUnsupported());
     ASSERT_TRUE(info.minFrequency.isUnsupported());
     ASSERT_TRUE(info.resonantFrequency.isUnsupported());
     ASSERT_TRUE(info.frequencyResolution.isUnsupported());