Merge "libgui: add aidl header lib" into sc-dev
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 7ab2a8d..e2ffd02 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -2175,14 +2175,13 @@
     }
 
     /*
-     * mount debugfs for non-user builds which launch with S and unmount it
-     * after invoking dumpstateBoard_* methods. This is to enable debug builds
-     * to not have debugfs mounted during runtime. It will also ensure that
-     * debugfs is only accessed by the dumpstate HAL.
+     * mount debugfs for non-user builds with ro.product.enforce_debugfs_restrictions
+     * set to true and unmount it after invoking dumpstateBoard_* methods.
+     * This is to enable debug builds to not have debugfs mounted during runtime.
+     * It will also ensure that debugfs is only accessed by the dumpstate HAL.
      */
-    auto api_level = android::base::GetIntProperty("ro.product.first_api_level", 0);
-    bool mount_debugfs = !PropertiesHelper::IsUserBuild() && api_level >= 31;
-
+    auto mount_debugfs =
+        android::base::GetBoolProperty("ro.product.enforce_debugfs_restrictions", false);
     if (mount_debugfs) {
         RunCommand("mount debugfs", {"mount", "-t", "debugfs", "debugfs", "/sys/kernel/debug"},
                    AS_ROOT_20);
@@ -2290,7 +2289,10 @@
     }
 
     if (mount_debugfs) {
-        RunCommand("unmount debugfs", {"umount", "/sys/kernel/debug"}, AS_ROOT_20);
+        auto keep_debugfs_mounted =
+            android::base::GetProperty("persist.dbg.keep_debugfs_mounted", "");
+        if (keep_debugfs_mounted.empty())
+            RunCommand("unmount debugfs", {"umount", "/sys/kernel/debug"}, AS_ROOT_20);
     }
 
     auto file_sizes = std::make_unique<ssize_t[]>(paths.size());
diff --git a/data/etc/android.software.translation.xml b/data/etc/android.software.translation.xml
deleted file mode 100644
index 3b361e5..0000000
--- a/data/etc/android.software.translation.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2020 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<permissions>
-    <feature name="android.software.translation" />
-</permissions>
diff --git a/data/etc/handheld_core_hardware.xml b/data/etc/handheld_core_hardware.xml
index c3c3a7f..41f1514 100644
--- a/data/etc/handheld_core_hardware.xml
+++ b/data/etc/handheld_core_hardware.xml
@@ -54,7 +54,6 @@
     <feature name="android.software.autofill" />
     <feature name="android.software.cant_save_state" />
     <feature name="android.software.secure_lock_screen" />
-    <feature name="android.software.translation" />
 
     <!-- Feature to specify if the device supports adding device admins. -->
     <feature name="android.software.device_admin" />
diff --git a/data/etc/tablet_core_hardware.xml b/data/etc/tablet_core_hardware.xml
index 4b565fd..8c369de 100644
--- a/data/etc/tablet_core_hardware.xml
+++ b/data/etc/tablet_core_hardware.xml
@@ -54,7 +54,6 @@
     <feature name="android.software.autofill" />
     <feature name="android.software.cant_save_state" />
     <feature name="android.software.secure_lock_screen" />
-    <feature name="android.software.translation" />
 
     <!-- Feature to specify if the device supports adding device admins. -->
     <feature name="android.software.device_admin" />
diff --git a/include/powermanager/PowerHalController.h b/include/powermanager/PowerHalController.h
index dd34c0a..71a36d0 100644
--- a/include/powermanager/PowerHalController.h
+++ b/include/powermanager/PowerHalController.h
@@ -20,6 +20,7 @@
 #include <android-base/thread_annotations.h>
 #include <android/hardware/power/Boost.h>
 #include <android/hardware/power/IPower.h>
+#include <android/hardware/power/IPowerHintSession.h>
 #include <android/hardware/power/Mode.h>
 #include <powermanager/PowerHalWrapper.h>
 
@@ -54,8 +55,12 @@
 
     void init();
 
-    virtual HalResult setBoost(hardware::power::Boost boost, int32_t durationMs) override;
-    virtual HalResult setMode(hardware::power::Mode mode, bool enabled) override;
+    virtual HalResult<void> setBoost(hardware::power::Boost boost, int32_t durationMs) override;
+    virtual HalResult<void> setMode(hardware::power::Mode mode, bool enabled) override;
+    virtual HalResult<sp<hardware::power::IPowerHintSession>> createHintSession(
+            int32_t tgid, int32_t uid, const std::vector<int32_t>& threadIds,
+            int64_t durationNanos) override;
+    virtual HalResult<int64_t> getHintSessionPreferredRate() override;
 
 private:
     std::mutex mConnectedHalMutex;
@@ -67,7 +72,8 @@
     const std::shared_ptr<HalWrapper> mDefaultHal = std::make_shared<EmptyHalWrapper>();
 
     std::shared_ptr<HalWrapper> initHal();
-    HalResult processHalResult(HalResult result, const char* functionName);
+    template <typename T>
+    HalResult<T> processHalResult(HalResult<T> result, const char* functionName);
 };
 
 // -------------------------------------------------------------------------------------------------
diff --git a/include/powermanager/PowerHalWrapper.h b/include/powermanager/PowerHalWrapper.h
index c3e7601..2c6eacb 100644
--- a/include/powermanager/PowerHalWrapper.h
+++ b/include/powermanager/PowerHalWrapper.h
@@ -21,6 +21,7 @@
 #include <android/hardware/power/1.1/IPower.h>
 #include <android/hardware/power/Boost.h>
 #include <android/hardware/power/IPower.h>
+#include <android/hardware/power/IPowerHintSession.h>
 #include <android/hardware/power/Mode.h>
 
 namespace android {
@@ -34,11 +35,81 @@
     OFF = 2,
 };
 
-// State of the Power HAL api call result.
-enum class HalResult {
-    SUCCESSFUL = 0,
-    FAILED = 1,
-    UNSUPPORTED = 2,
+// Result of a call to the Power HAL wrapper, holding data if successful.
+template <typename T>
+class HalResult {
+public:
+    static HalResult<T> ok(T value) { return HalResult(value); }
+    static HalResult<T> failed(std::string msg) {
+        return HalResult(std::move(msg), /* unsupported= */ false);
+    }
+    static HalResult<T> unsupported() { return HalResult("", /* unsupported= */ true); }
+
+    static HalResult<T> fromStatus(binder::Status status, T data) {
+        if (status.exceptionCode() == binder::Status::EX_UNSUPPORTED_OPERATION) {
+            return HalResult<T>::unsupported();
+        }
+        if (status.isOk()) {
+            return HalResult<T>::ok(data);
+        }
+        return HalResult<T>::failed(std::string(status.toString8().c_str()));
+    }
+    static HalResult<T> fromStatus(hardware::power::V1_0::Status status, T data);
+
+    template <typename R>
+    static HalResult<T> fromReturn(hardware::Return<R>& ret, T data);
+
+    template <typename R>
+    static HalResult<T> fromReturn(hardware::Return<R>& ret, hardware::power::V1_0::Status status,
+                                   T data);
+
+    // This will throw std::bad_optional_access if this result is not ok.
+    const T& value() const { return mValue.value(); }
+    bool isOk() const { return !mUnsupported && mValue.has_value(); }
+    bool isFailed() const { return !mUnsupported && !mValue.has_value(); }
+    bool isUnsupported() const { return mUnsupported; }
+    const char* errorMessage() const { return mErrorMessage.c_str(); }
+
+private:
+    std::optional<T> mValue;
+    std::string mErrorMessage;
+    bool mUnsupported;
+
+    explicit HalResult(T value)
+          : mValue(std::make_optional(value)), mErrorMessage(), mUnsupported(false) {}
+    explicit HalResult(std::string errorMessage, bool unsupported)
+          : mValue(), mErrorMessage(std::move(errorMessage)), mUnsupported(unsupported) {}
+};
+
+// Empty result of a call to the Power HAL wrapper.
+template <>
+class HalResult<void> {
+public:
+    static HalResult<void> ok() { return HalResult(); }
+    static HalResult<void> failed(std::string msg) { return HalResult(std::move(msg)); }
+    static HalResult<void> unsupported() { return HalResult(/* unsupported= */ true); }
+
+    static HalResult<void> fromStatus(status_t status);
+    static HalResult<void> fromStatus(binder::Status status);
+    static HalResult<void> fromStatus(hardware::power::V1_0::Status status);
+
+    template <typename R>
+    static HalResult<void> fromReturn(hardware::Return<R>& ret);
+
+    bool isOk() const { return !mUnsupported && !mFailed; }
+    bool isFailed() const { return !mUnsupported && mFailed; }
+    bool isUnsupported() const { return mUnsupported; }
+    const char* errorMessage() const { return mErrorMessage.c_str(); }
+
+private:
+    std::string mErrorMessage;
+    bool mFailed;
+    bool mUnsupported;
+
+    explicit HalResult(bool unsupported = false)
+          : mErrorMessage(), mFailed(false), mUnsupported(unsupported) {}
+    explicit HalResult(std::string errorMessage)
+          : mErrorMessage(std::move(errorMessage)), mFailed(true), mUnsupported(false) {}
 };
 
 // Wrapper for Power HAL handlers.
@@ -46,8 +117,12 @@
 public:
     virtual ~HalWrapper() = default;
 
-    virtual HalResult setBoost(hardware::power::Boost boost, int32_t durationMs) = 0;
-    virtual HalResult setMode(hardware::power::Mode mode, bool enabled) = 0;
+    virtual HalResult<void> setBoost(hardware::power::Boost boost, int32_t durationMs) = 0;
+    virtual HalResult<void> setMode(hardware::power::Mode mode, bool enabled) = 0;
+    virtual HalResult<sp<hardware::power::IPowerHintSession>> createHintSession(
+            int32_t tgid, int32_t uid, const std::vector<int32_t>& threadIds,
+            int64_t durationNanos) = 0;
+    virtual HalResult<int64_t> getHintSessionPreferredRate() = 0;
 };
 
 // Empty Power HAL wrapper that ignores all api calls.
@@ -56,8 +131,12 @@
     EmptyHalWrapper() = default;
     ~EmptyHalWrapper() = default;
 
-    virtual HalResult setBoost(hardware::power::Boost boost, int32_t durationMs) override;
-    virtual HalResult setMode(hardware::power::Mode mode, bool enabled) override;
+    virtual HalResult<void> setBoost(hardware::power::Boost boost, int32_t durationMs) override;
+    virtual HalResult<void> setMode(hardware::power::Mode mode, bool enabled) override;
+    virtual HalResult<sp<hardware::power::IPowerHintSession>> createHintSession(
+            int32_t tgid, int32_t uid, const std::vector<int32_t>& threadIds,
+            int64_t durationNanos) override;
+    virtual HalResult<int64_t> getHintSessionPreferredRate() override;
 };
 
 // Wrapper for the HIDL Power HAL v1.0.
@@ -67,16 +146,20 @@
           : mHandleV1_0(std::move(Hal)) {}
     virtual ~HidlHalWrapperV1_0() = default;
 
-    virtual HalResult setBoost(hardware::power::Boost boost, int32_t durationMs) override;
-    virtual HalResult setMode(hardware::power::Mode mode, bool enabled) override;
+    virtual HalResult<void> setBoost(hardware::power::Boost boost, int32_t durationMs) override;
+    virtual HalResult<void> setMode(hardware::power::Mode mode, bool enabled) override;
+    virtual HalResult<sp<hardware::power::IPowerHintSession>> createHintSession(
+            int32_t tgid, int32_t uid, const std::vector<int32_t>& threadIds,
+            int64_t durationNanos) override;
+    virtual HalResult<int64_t> getHintSessionPreferredRate() override;
 
 protected:
-    virtual HalResult sendPowerHint(hardware::power::V1_0::PowerHint hintId, uint32_t data);
+    virtual HalResult<void> sendPowerHint(hardware::power::V1_0::PowerHint hintId, uint32_t data);
 
 private:
     sp<hardware::power::V1_0::IPower> mHandleV1_0;
-    HalResult setInteractive(bool enabled);
-    HalResult setFeature(hardware::power::V1_0::Feature feature, bool enabled);
+    HalResult<void> setInteractive(bool enabled);
+    HalResult<void> setFeature(hardware::power::V1_0::Feature feature, bool enabled);
 };
 
 // Wrapper for the HIDL Power HAL v1.1.
@@ -88,8 +171,8 @@
     virtual ~HidlHalWrapperV1_1() = default;
 
 protected:
-    virtual HalResult sendPowerHint(hardware::power::V1_0::PowerHint hintId,
-                                    uint32_t data) override;
+    virtual HalResult<void> sendPowerHint(hardware::power::V1_0::PowerHint hintId,
+                                          uint32_t data) override;
 
 private:
     sp<hardware::power::V1_1::IPower> mHandleV1_1;
@@ -101,8 +184,12 @@
     explicit AidlHalWrapper(sp<hardware::power::IPower> handle) : mHandle(std::move(handle)) {}
     virtual ~AidlHalWrapper() = default;
 
-    virtual HalResult setBoost(hardware::power::Boost boost, int32_t durationMs) override;
-    virtual HalResult setMode(hardware::power::Mode mode, bool enabled) override;
+    virtual HalResult<void> setBoost(hardware::power::Boost boost, int32_t durationMs) override;
+    virtual HalResult<void> setMode(hardware::power::Mode mode, bool enabled) override;
+    virtual HalResult<sp<hardware::power::IPowerHintSession>> createHintSession(
+            int32_t tgid, int32_t uid, const std::vector<int32_t>& threadIds,
+            int64_t durationNanos) override;
+    virtual HalResult<int64_t> getHintSessionPreferredRate() override;
 
 private:
     // Control access to the boost and mode supported arrays.
diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp
index bcdd06b..e5afd40 100644
--- a/libs/gui/BLASTBufferQueue.cpp
+++ b/libs/gui/BLASTBufferQueue.cpp
@@ -204,13 +204,16 @@
     if (mRequestedSize != newSize) {
         mRequestedSize.set(newSize);
         mBufferItemConsumer->setDefaultBufferSize(mRequestedSize.width, mRequestedSize.height);
-        if (mLastBufferScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE) {
+        if (mLastBufferInfo.scalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE) {
             // If the buffer supports scaling, update the frame immediately since the client may
             // want to scale the existing buffer to the new size.
             mSize = mRequestedSize;
-            t.setFrame(mSurfaceControl,
-                       {0, 0, static_cast<int32_t>(mSize.width),
-                        static_cast<int32_t>(mSize.height)});
+            // We only need to update the scale if we've received at least one buffer. The reason
+            // for this is the scale is calculated based on the requested size and buffer size.
+            // If there's no buffer, the scale will always be 1.
+            if (mLastBufferInfo.hasBuffer) {
+                setMatrix(&t, mLastBufferInfo);
+            }
             applyTransaction = true;
         }
     }
@@ -374,8 +377,10 @@
     // Ensure BLASTBufferQueue stays alive until we receive the transaction complete callback.
     incStrong((void*)transactionCallbackThunk);
 
-    mLastBufferScalingMode = bufferItem.mScalingMode;
     mLastAcquiredFrameNumber = bufferItem.mFrameNumber;
+    mLastBufferInfo.update(true /* hasBuffer */, bufferItem.mGraphicBuffer->getWidth(),
+                           bufferItem.mGraphicBuffer->getHeight(), bufferItem.mTransform,
+                           bufferItem.mScalingMode);
 
     auto releaseBufferCallback =
             std::bind(releaseBufferCallbackThunk, wp<BLASTBufferQueue>(this) /* callbackContext */,
@@ -388,8 +393,7 @@
                        bufferItem.mFence ? new Fence(bufferItem.mFence->dup()) : Fence::NO_FENCE);
     t->addTransactionCompletedCallback(transactionCallbackThunk, static_cast<void*>(this));
 
-    t->setFrame(mSurfaceControl,
-                {0, 0, static_cast<int32_t>(mSize.width), static_cast<int32_t>(mSize.height)});
+    setMatrix(t, mLastBufferInfo);
     t->setCrop(mSurfaceControl, computeCrop(bufferItem));
     t->setTransform(mSurfaceControl, bufferItem.mTransform);
     t->setTransformToDisplayInverse(mSurfaceControl, bufferItem.mTransformToDisplayInverse);
@@ -515,6 +519,17 @@
     return mSize != bufferSize;
 }
 
+void BLASTBufferQueue::setMatrix(SurfaceComposerClient::Transaction* t,
+                                 const BufferInfo& bufferInfo) {
+    uint32_t bufWidth = bufferInfo.width;
+    uint32_t bufHeight = bufferInfo.height;
+
+    float dsdx = mSize.width / static_cast<float>(bufWidth);
+    float dsdy = mSize.height / static_cast<float>(bufHeight);
+
+    t->setMatrix(mSurfaceControl, dsdx, 0, 0, dsdy);
+}
+
 void BLASTBufferQueue::setTransactionCompleteCallback(
         uint64_t frameNumber, std::function<void(int64_t)>&& transactionCompleteCallback) {
     std::lock_guard _lock{mMutex};
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index 5b213ad..8094385 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -455,10 +455,6 @@
         what |= eCropChanged;
         crop = other.crop;
     }
-    if (other.what & eFrameChanged) {
-        what |= eFrameChanged;
-        orientedDisplaySpaceRect = other.orientedDisplaySpaceRect;
-    }
     if (other.what & eBufferChanged) {
         what |= eBufferChanged;
         buffer = other.buffer;
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index e01a5ae..9ce094a 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -1232,20 +1232,6 @@
     return *this;
 }
 
-SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFrame(
-        const sp<SurfaceControl>& sc, const Rect& frame) {
-    layer_state_t* s = getLayerState(sc);
-    if (!s) {
-        mStatus = BAD_INDEX;
-        return *this;
-    }
-    s->what |= layer_state_t::eFrameChanged;
-    s->orientedDisplaySpaceRect = frame;
-
-    registerSurfaceControlForCallback(sc);
-    return *this;
-}
-
 SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setBuffer(
         const sp<SurfaceControl>& sc, const sp<GraphicBuffer>& buffer,
         ReleaseBufferCallback callback) {
diff --git a/libs/gui/include/gui/BLASTBufferQueue.h b/libs/gui/include/gui/BLASTBufferQueue.h
index fbd16f4..a48f95a 100644
--- a/libs/gui/include/gui/BLASTBufferQueue.h
+++ b/libs/gui/include/gui/BLASTBufferQueue.h
@@ -142,6 +142,33 @@
     ui::Size mRequestedSize GUARDED_BY(mMutex);
     int32_t mFormat GUARDED_BY(mMutex);
 
+    struct BufferInfo {
+        bool hasBuffer = false;
+        uint32_t width;
+        uint32_t height;
+        uint32_t transform;
+        // This is used to check if we should update the blast layer size immediately or wait until
+        // we get the next buffer. This will support scenarios where the layer can change sizes
+        // and the buffer will scale to fit the new size.
+        uint32_t scalingMode = NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW;
+
+        void update(bool hasBuffer, uint32_t width, uint32_t height, uint32_t transform,
+                    uint32_t scalingMode) {
+            this->hasBuffer = hasBuffer;
+            this->width = width;
+            this->height = height;
+            this->transform = transform;
+            this->scalingMode = scalingMode;
+        }
+    };
+
+    // Last acquired buffer's info. This is used to calculate the correct scale when size change is
+    // requested. We need to use the old buffer's info to determine what scale we need to apply to
+    // ensure the correct size.
+    BufferInfo mLastBufferInfo GUARDED_BY(mMutex);
+    void setMatrix(SurfaceComposerClient::Transaction* t, const BufferInfo& bufferInfo)
+            REQUIRES(mMutex);
+
     uint32_t mTransformHint GUARDED_BY(mMutex);
 
     sp<IGraphicBufferConsumer> mConsumer;
@@ -159,11 +186,6 @@
 
     std::queue<FrameTimelineInfo> mNextFrameTimelineInfoQueue GUARDED_BY(mMutex);
 
-    // Last acquired buffer's scaling mode. This is used to check if we should update the blast
-    // layer size immediately or wait until we get the next buffer. This will support scenarios
-    // where the layer can change sizes and the buffer will scale to fit the new size.
-    uint32_t mLastBufferScalingMode = NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW;
-
     // Tracks the last acquired frame number
     uint64_t mLastAcquiredFrameNumber GUARDED_BY(mMutex) = 0;
 
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index 65d7710..41a022f 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -105,7 +105,7 @@
         eHasListenerCallbacksChanged = 0x20000000,
         eInputInfoChanged = 0x40000000,
         eCornerRadiusChanged = 0x80000000,
-        eFrameChanged = 0x1'00000000,
+        /* was eFrameChanged, now available 0x1'00000000, */
         eCachedBufferChanged = 0x2'00000000,
         eBackgroundColorChanged = 0x4'00000000,
         eMetadataChanged = 0x8'00000000,
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 2487961..1590b10 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -473,7 +473,6 @@
         Transaction& setTransform(const sp<SurfaceControl>& sc, uint32_t transform);
         Transaction& setTransformToDisplayInverse(const sp<SurfaceControl>& sc,
                                                   bool transformToDisplayInverse);
-        Transaction& setFrame(const sp<SurfaceControl>& sc, const Rect& frame);
         Transaction& setBuffer(const sp<SurfaceControl>& sc, const sp<GraphicBuffer>& buffer,
                                ReleaseBufferCallback callback = nullptr);
         Transaction& setCachedBuffer(const sp<SurfaceControl>& sc, int32_t bufferId);
diff --git a/libs/gui/tests/BLASTBufferQueue_test.cpp b/libs/gui/tests/BLASTBufferQueue_test.cpp
index fe48d88..9b1f0db 100644
--- a/libs/gui/tests/BLASTBufferQueue_test.cpp
+++ b/libs/gui/tests/BLASTBufferQueue_test.cpp
@@ -140,7 +140,6 @@
                                                  /*parent*/ nullptr);
         t.setLayerStack(mSurfaceControl, 0)
                 .setLayer(mSurfaceControl, std::numeric_limits<int32_t>::max())
-                .setFrame(mSurfaceControl, Rect(resolution))
                 .show(mSurfaceControl)
                 .setDataspace(mSurfaceControl, ui::Dataspace::V0_SRGB)
                 .apply();
@@ -218,13 +217,13 @@
                             col >= region.left - border && col < region.right + border;
                 }
                 if (!outsideRegion && inRegion) {
-                    EXPECT_GE(epsilon, abs(r - *(pixel)));
-                    EXPECT_GE(epsilon, abs(g - *(pixel + 1)));
-                    EXPECT_GE(epsilon, abs(b - *(pixel + 2)));
+                    ASSERT_GE(epsilon, abs(r - *(pixel)));
+                    ASSERT_GE(epsilon, abs(g - *(pixel + 1)));
+                    ASSERT_GE(epsilon, abs(b - *(pixel + 2)));
                 } else if (outsideRegion && !inRegion) {
-                    EXPECT_GE(epsilon, abs(r - *(pixel)));
-                    EXPECT_GE(epsilon, abs(g - *(pixel + 1)));
-                    EXPECT_GE(epsilon, abs(b - *(pixel + 2)));
+                    ASSERT_GE(epsilon, abs(r - *(pixel)));
+                    ASSERT_GE(epsilon, abs(g - *(pixel + 1)));
+                    ASSERT_GE(epsilon, abs(b - *(pixel + 2)));
                 }
                 ASSERT_EQ(false, ::testing::Test::HasFailure());
             }
@@ -466,7 +465,8 @@
     ASSERT_EQ(NO_ERROR, captureDisplay(mCaptureArgs, mCaptureResults));
 
     ASSERT_NO_FATAL_FAILURE(
-            checkScreenCapture(r, g, b, {0, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight}));
+            checkScreenCapture(r, g, b,
+                               {0, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight / 2}));
 }
 
 TEST_F(BLASTBufferQueueTest, SetCrop_ScalingModeScaleCrop) {
@@ -523,13 +523,15 @@
     // capture screen and verify that it is red
     ASSERT_EQ(NO_ERROR, captureDisplay(mCaptureArgs, mCaptureResults));
 
+    Rect bounds;
+    bounds.left = finalCropSideLength / 2;
+    bounds.top = 0;
+    bounds.right = bounds.left + finalCropSideLength;
+    bounds.bottom = finalCropSideLength;
+
+    ASSERT_NO_FATAL_FAILURE(checkScreenCapture(r, g, b, bounds));
     ASSERT_NO_FATAL_FAILURE(
-            checkScreenCapture(r, g, b,
-                               {0, 0, (int32_t)bufferSideLength, (int32_t)bufferSideLength}));
-    ASSERT_NO_FATAL_FAILURE(
-            checkScreenCapture(0, 0, 0,
-                               {0, 0, (int32_t)bufferSideLength, (int32_t)bufferSideLength},
-                               /*border*/ 0, /*outsideRegion*/ true));
+            checkScreenCapture(0, 0, 0, bounds, /*border*/ 0, /*outsideRegion*/ true));
 }
 
 class TestProducerListener : public BnProducerListener {
@@ -596,7 +598,6 @@
     t.setLayerStack(bgSurface, 0)
             .show(bgSurface)
             .setDataspace(bgSurface, ui::Dataspace::V0_SRGB)
-            .setFrame(bgSurface, Rect(0, 0, mDisplayWidth, mDisplayHeight))
             .setLayer(bgSurface, std::numeric_limits<int32_t>::max() - 1)
             .apply();
 
@@ -619,7 +620,8 @@
     ASSERT_EQ(NO_ERROR, captureDisplay(mCaptureArgs, mCaptureResults));
 
     ASSERT_NO_FATAL_FAILURE(
-            checkScreenCapture(r, g, b, {0, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight}));
+            checkScreenCapture(r, g, b,
+                               {0, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight / 2}));
 }
 
 class BLASTBufferQueueTransformTest : public BLASTBufferQueueTest {
diff --git a/libs/renderengine/skia/Cache.cpp b/libs/renderengine/skia/Cache.cpp
index 0cd3b62..1db20c0 100644
--- a/libs/renderengine/skia/Cache.cpp
+++ b/libs/renderengine/skia/Cache.cpp
@@ -25,8 +25,6 @@
 #include "ui/Rect.h"
 #include "utils/Timers.h"
 
-#include <android/hardware_buffer.h>
-
 namespace android::renderengine::skia {
 
 namespace {
@@ -183,41 +181,6 @@
     }
 }
 
-namespace {
-
-struct AHardwareBuffer_deleter {
-    void operator()(AHardwareBuffer* ahb) const { AHardwareBuffer_release(ahb); }
-};
-
-std::unique_ptr<AHardwareBuffer, AHardwareBuffer_deleter> makeAHardwareBuffer() {
-    AHardwareBuffer* buffer = nullptr;
-
-    int w = 32;
-    int h = 32;
-
-    AHardwareBuffer_Desc hwbDesc;
-    hwbDesc.width = w;
-    hwbDesc.height = h;
-    hwbDesc.layers = 1;
-    hwbDesc.usage = AHARDWAREBUFFER_USAGE_CPU_READ_NEVER | AHARDWAREBUFFER_USAGE_CPU_WRITE_NEVER |
-            AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
-    hwbDesc.format = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
-    // The following three are not used in the allocate
-    hwbDesc.stride = 0;
-    hwbDesc.rfu0 = 0;
-    hwbDesc.rfu1 = 0;
-
-    if (int error = AHardwareBuffer_allocate(&hwbDesc, &buffer)) {
-        ALOGE("Failed to allocated hardware buffer, error: %d", error);
-        if (buffer) {
-            AHardwareBuffer_release(buffer);
-        }
-        return nullptr;
-    }
-    return std::unique_ptr<AHardwareBuffer, AHardwareBuffer_deleter>(buffer);
-}
-} // namespace
-
 //
 // The collection of shaders cached here were found by using perfetto to record shader compiles
 // during actions that involve RenderEngine, logging the layer settings, and the shader code
@@ -265,14 +228,16 @@
     // The majority of shaders are related to sampling images.
     drawImageLayers(renderengine, display, dstBuffer, srcBuffer);
 
-    // Draw image layers again sampling from an AHardwareBuffer if it is possible to create one.
-    if (auto ahb = makeAHardwareBuffer()) {
-        sp<GraphicBuffer> externalBuffer = GraphicBuffer::fromAHardwareBuffer(ahb.get());
-        // TODO(b/184665179) doubles number of image shader compilations, but only somewhere
-        // between 6 and 8 will occur in real uses.
-        drawImageLayers(renderengine, display, dstBuffer, externalBuffer);
-        renderengine->unbindExternalTextureBuffer(externalBuffer->getId());
-    }
+    // should be the same as AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
+    const int64_t usageExternal = GRALLOC_USAGE_HW_TEXTURE;
+
+    sp<GraphicBuffer> externalBuffer =
+            new GraphicBuffer(displayRect.width(), displayRect.height(), PIXEL_FORMAT_RGBA_8888, 1,
+                              usageExternal, "primeShaderCache_external");
+    // TODO(b/184665179) doubles number of image shader compilations, but only somewhere
+    // between 6 and 8 will occur in real uses.
+    drawImageLayers(renderengine, display, dstBuffer, externalBuffer);
+    renderengine->unbindExternalTextureBuffer(externalBuffer->getId());
 
     renderengine->unbindExternalTextureBuffer(srcBuffer->getId());
 
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index 073455a..4e05847 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -2326,6 +2326,8 @@
     if (dropWindow) {
         vec2 local = dropWindow->getInfo()->transform.transform(x, y);
         notifyDropWindowLocked(dropWindow->getToken(), local.x, local.y);
+    } else {
+        notifyDropWindowLocked(nullptr, 0, 0);
     }
     mDragState.reset();
 }
@@ -2372,6 +2374,7 @@
     } else if (maskedAction == AMOTION_EVENT_ACTION_UP) {
         finishDragAndDrop(entry.displayId, x, y);
     } else if (maskedAction == AMOTION_EVENT_ACTION_CANCEL) {
+        notifyDropWindowLocked(nullptr, 0, 0);
         mDragState.reset();
     }
 }
diff --git a/services/inputflinger/reader/Android.bp b/services/inputflinger/reader/Android.bp
index 7468894..7db32e3 100644
--- a/services/inputflinger/reader/Android.bp
+++ b/services/inputflinger/reader/Android.bp
@@ -36,7 +36,7 @@
     srcs: [
         "EventHub.cpp",
         "InputDevice.cpp",
-        "controller/InputController.cpp",
+        "controller/PeripheralController.cpp",
         "mapper/accumulator/CursorButtonAccumulator.cpp",
         "mapper/accumulator/CursorScrollAccumulator.cpp",
         "mapper/accumulator/SingleTouchMotionAccumulator.cpp",
diff --git a/services/inputflinger/reader/EventHub.cpp b/services/inputflinger/reader/EventHub.cpp
index 045d24c..e3e6c12 100644
--- a/services/inputflinger/reader/EventHub.cpp
+++ b/services/inputflinger/reader/EventHub.cpp
@@ -363,7 +363,7 @@
         virtualKeyMap(nullptr),
         ffEffectPlaying(false),
         ffEffectId(-1),
-        miscDevice(nullptr),
+        associatedDevice(nullptr),
         controllerNumber(0),
         enabled(true),
         isVirtual(fd < 0) {}
@@ -554,7 +554,7 @@
 }
 
 // Check the sysfs path for any input device batteries, returns true if battery found.
-bool EventHub::MiscDevice::configureBatteryLocked() {
+bool EventHub::AssociatedDevice::configureBatteryLocked() {
     nextBatteryId = 0;
     // Check if device has any battery.
     const auto& paths = findSysfsNodes(sysfsRootPath, SysfsClass::POWER_SUPPLY);
@@ -580,7 +580,7 @@
 }
 
 // Check the sysfs path for any input device lights, returns true if lights found.
-bool EventHub::MiscDevice::configureLightsLocked() {
+bool EventHub::AssociatedDevice::configureLightsLocked() {
     nextLightId = 0;
     // Check if device has any lights.
     const auto& paths = findSysfsNodes(sysfsRootPath, SysfsClass::LEDS);
@@ -988,14 +988,10 @@
         int32_t deviceId) const {
     static const std::unordered_map<int32_t, RawBatteryInfo> EMPTY_BATTERY_INFO = {};
     Device* device = getDeviceLocked(deviceId);
-    if (device == nullptr) {
+    if (device == nullptr || !device->associatedDevice) {
         return EMPTY_BATTERY_INFO;
     }
-    auto it = mMiscDevices.find(device->identifier.descriptor);
-    if (it == mMiscDevices.end()) {
-        return EMPTY_BATTERY_INFO;
-    }
-    return it->second->batteryInfos;
+    return device->associatedDevice->batteryInfos;
 }
 
 const std::vector<int32_t> EventHub::getRawBatteryIds(int32_t deviceId) {
@@ -1028,14 +1024,10 @@
         int32_t deviceId) const {
     static const std::unordered_map<int32_t, RawLightInfo> EMPTY_LIGHT_INFO = {};
     Device* device = getDeviceLocked(deviceId);
-    if (device == nullptr) {
+    if (device == nullptr || !device->associatedDevice) {
         return EMPTY_LIGHT_INFO;
     }
-    auto it = mMiscDevices.find(device->identifier.descriptor);
-    if (it == mMiscDevices.end()) {
-        return EMPTY_LIGHT_INFO;
-    }
-    return it->second->lightInfos;
+    return device->associatedDevice->lightInfos;
 }
 
 const std::vector<int32_t> EventHub::getRawLightIds(int32_t deviceId) {
@@ -1946,18 +1938,20 @@
     // Check the sysfs root path
     std::optional<std::filesystem::path> sysfsRootPath = getSysfsRootPath(devicePath.c_str());
     if (sysfsRootPath.has_value()) {
-        std::shared_ptr<MiscDevice> miscDevice;
-        auto it = mMiscDevices.find(device->identifier.descriptor);
-        if (it == mMiscDevices.end()) {
-            miscDevice = std::make_shared<MiscDevice>(sysfsRootPath.value());
-        } else {
-            miscDevice = it->second;
+        std::shared_ptr<AssociatedDevice> associatedDevice;
+        for (const auto& [id, dev] : mDevices) {
+            if (device->identifier.descriptor == dev->identifier.descriptor &&
+                !dev->associatedDevice) {
+                associatedDevice = dev->associatedDevice;
+            }
         }
-        hasBattery = miscDevice->configureBatteryLocked();
-        hasLights = miscDevice->configureLightsLocked();
+        if (!associatedDevice) {
+            associatedDevice = std::make_shared<AssociatedDevice>(sysfsRootPath.value());
+        }
+        hasBattery = associatedDevice->configureBatteryLocked();
+        hasLights = associatedDevice->configureLightsLocked();
 
-        device->miscDevice = miscDevice;
-        mMiscDevices.insert_or_assign(device->identifier.descriptor, std::move(miscDevice));
+        device->associatedDevice = associatedDevice;
     }
 
     // Figure out the kinds of events the device reports.
@@ -2329,12 +2323,6 @@
     mClosingDevices.push_back(std::move(mDevices[device.id]));
 
     mDevices.erase(device.id);
-    // If all devices with the descriptor have been removed then the miscellaneous device should
-    // be removed too.
-    std::string descriptor = device.identifier.descriptor;
-    if (getDeviceByDescriptorLocked(descriptor) == nullptr) {
-        mMiscDevices.erase(descriptor);
-    }
 }
 
 status_t EventHub::readNotifyLocked() {
diff --git a/services/inputflinger/reader/InputDevice.cpp b/services/inputflinger/reader/InputDevice.cpp
index f935c36..8f75d22 100644
--- a/services/inputflinger/reader/InputDevice.cpp
+++ b/services/inputflinger/reader/InputDevice.cpp
@@ -23,11 +23,11 @@
 
 #include "CursorInputMapper.h"
 #include "ExternalStylusInputMapper.h"
-#include "InputController.h"
 #include "InputReaderContext.h"
 #include "JoystickInputMapper.h"
 #include "KeyboardInputMapper.h"
 #include "MultiTouchInputMapper.h"
+#include "PeripheralController.h"
 #include "RotaryEncoderInputMapper.h"
 #include "SensorInputMapper.h"
 #include "SingleTouchInputMapper.h"
@@ -165,9 +165,9 @@
     }
 
     // Battery-like devices or light-containing devices.
-    // InputController will be created with associated EventHub device.
+    // PeripheralController will be created with associated EventHub device.
     if (classes.test(InputDeviceClass::BATTERY) || classes.test(InputDeviceClass::LIGHT)) {
-        mController = std::make_unique<InputController>(*contextPtr);
+        mController = std::make_unique<PeripheralController>(*contextPtr);
     }
 
     // Keyboard-like devices.
@@ -504,8 +504,6 @@
     for_each_mapper([when, readTime](InputMapper& mapper) { mapper.cancelTouch(when, readTime); });
 }
 
-// TODO b/180733860 support multiple battery in API and remove this.
-constexpr int32_t DEFAULT_BATTERY_ID = 1;
 std::optional<int32_t> InputDevice::getBatteryCapacity() {
     return mController ? mController->getBatteryCapacity(DEFAULT_BATTERY_ID) : std::nullopt;
 }
diff --git a/services/inputflinger/reader/controller/InputController.cpp b/services/inputflinger/reader/controller/PeripheralController.cpp
similarity index 90%
rename from services/inputflinger/reader/controller/InputController.cpp
rename to services/inputflinger/reader/controller/PeripheralController.cpp
index 45266fb..1a40d06 100644
--- a/services/inputflinger/reader/controller/InputController.cpp
+++ b/services/inputflinger/reader/controller/PeripheralController.cpp
@@ -19,7 +19,7 @@
 
 #include "../Macros.h"
 
-#include "InputController.h"
+#include "PeripheralController.h"
 #include "input/NamedEnum.h"
 
 // Log detailed debug messages about input device lights.
@@ -52,15 +52,15 @@
  * lights, getting and setting the lights brightness and color, by interacting with EventHub
  * devices.
  */
-InputController::InputController(InputDeviceContext& deviceContext)
+PeripheralController::PeripheralController(InputDeviceContext& deviceContext)
       : mDeviceContext(deviceContext) {
     configureBattries();
     configureLights();
 }
 
-InputController::~InputController() {}
+PeripheralController::~PeripheralController() {}
 
-std::optional<std::int32_t> InputController::Light::getRawLightBrightness(int32_t rawLightId) {
+std::optional<std::int32_t> PeripheralController::Light::getRawLightBrightness(int32_t rawLightId) {
     std::optional<RawLightInfo> rawInfoOpt = context.getRawLightInfo(rawLightId);
     if (!rawInfoOpt.has_value()) {
         return std::nullopt;
@@ -85,7 +85,7 @@
     return brightness;
 }
 
-void InputController::Light::setRawLightBrightness(int32_t rawLightId, int32_t brightness) {
+void PeripheralController::Light::setRawLightBrightness(int32_t rawLightId, int32_t brightness) {
     std::optional<RawLightInfo> rawInfo = context.getRawLightInfo(rawLightId);
     if (!rawInfo.has_value()) {
         return;
@@ -104,14 +104,14 @@
     context.setLightBrightness(rawLightId, brightness);
 }
 
-bool InputController::SingleLight::setLightColor(int32_t color) {
+bool PeripheralController::SingleLight::setLightColor(int32_t color) {
     int32_t brightness = getAlpha(color);
     setRawLightBrightness(rawId, brightness);
 
     return true;
 }
 
-bool InputController::RgbLight::setLightColor(int32_t color) {
+bool PeripheralController::RgbLight::setLightColor(int32_t color) {
     // Compose color value as per:
     // https://developer.android.com/reference/android/graphics/Color?hl=en
     // int color = (A & 0xff) << 24 | (R & 0xff) << 16 | (G & 0xff) << 8 | (B & 0xff);
@@ -137,7 +137,7 @@
     return true;
 }
 
-bool InputController::MultiColorLight::setLightColor(int32_t color) {
+bool PeripheralController::MultiColorLight::setLightColor(int32_t color) {
     std::unordered_map<LightColor, int32_t> intensities;
     intensities.emplace(LightColor::RED, getRed(color));
     intensities.emplace(LightColor::GREEN, getGreen(color));
@@ -148,7 +148,7 @@
     return true;
 }
 
-std::optional<int32_t> InputController::SingleLight::getLightColor() {
+std::optional<int32_t> PeripheralController::SingleLight::getLightColor() {
     std::optional<int32_t> brightness = getRawLightBrightness(rawId);
     if (!brightness.has_value()) {
         return std::nullopt;
@@ -157,7 +157,7 @@
     return toArgb(brightness.value(), 0 /* red */, 0 /* green */, 0 /* blue */);
 }
 
-std::optional<int32_t> InputController::RgbLight::getLightColor() {
+std::optional<int32_t> PeripheralController::RgbLight::getLightColor() {
     // If the Alpha component is zero, then return color 0.
     if (brightness == 0) {
         return 0;
@@ -192,7 +192,7 @@
     return toArgb(brightness, red, green, blue);
 }
 
-std::optional<int32_t> InputController::MultiColorLight::getLightColor() {
+std::optional<int32_t> PeripheralController::MultiColorLight::getLightColor() {
     auto ret = context.getLightIntensities(rawId);
     if (!ret.has_value()) {
         return std::nullopt;
@@ -210,7 +210,7 @@
     return std::nullopt;
 }
 
-bool InputController::PlayerIdLight::setLightPlayerId(int32_t playerId) {
+bool PeripheralController::PlayerIdLight::setLightPlayerId(int32_t playerId) {
     if (rawLightIds.find(playerId) == rawLightIds.end()) {
         return false;
     }
@@ -224,7 +224,7 @@
     return true;
 }
 
-std::optional<int32_t> InputController::PlayerIdLight::getLightPlayerId() {
+std::optional<int32_t> PeripheralController::PlayerIdLight::getLightPlayerId() {
     for (const auto& [id, rawId] : rawLightIds) {
         std::optional<int32_t> brightness = getRawLightBrightness(rawId);
         if (brightness.has_value() && brightness.value() > 0) {
@@ -234,11 +234,11 @@
     return std::nullopt;
 }
 
-void InputController::SingleLight::dump(std::string& dump) {
+void PeripheralController::SingleLight::dump(std::string& dump) {
     dump += StringPrintf(INDENT4 "Color: 0x%x\n", getLightColor().value_or(0));
 }
 
-void InputController::PlayerIdLight::dump(std::string& dump) {
+void PeripheralController::PlayerIdLight::dump(std::string& dump) {
     dump += StringPrintf(INDENT4 "PlayerId: %d\n", getLightPlayerId().value_or(-1));
     dump += StringPrintf(INDENT4 "Raw Player ID LEDs:");
     for (const auto& [id, rawId] : rawLightIds) {
@@ -247,7 +247,7 @@
     dump += "\n";
 }
 
-void InputController::RgbLight::dump(std::string& dump) {
+void PeripheralController::RgbLight::dump(std::string& dump) {
     dump += StringPrintf(INDENT4 "Color: 0x%x\n", getLightColor().value_or(0));
     dump += StringPrintf(INDENT4 "Raw RGB LEDs: [%d, %d, %d] ", rawRgbIds.at(LightColor::RED),
                          rawRgbIds.at(LightColor::GREEN), rawRgbIds.at(LightColor::BLUE));
@@ -257,11 +257,11 @@
     dump += "\n";
 }
 
-void InputController::MultiColorLight::dump(std::string& dump) {
+void PeripheralController::MultiColorLight::dump(std::string& dump) {
     dump += StringPrintf(INDENT4 "Color: 0x%x\n", getLightColor().value_or(0));
 }
 
-void InputController::populateDeviceInfo(InputDeviceInfo* deviceInfo) {
+void PeripheralController::populateDeviceInfo(InputDeviceInfo* deviceInfo) {
     // TODO: b/180733860 Remove this after enabling multi-battery
     if (!mBatteries.empty()) {
         deviceInfo->setHasBattery(true);
@@ -279,7 +279,7 @@
     }
 }
 
-void InputController::dump(std::string& dump) {
+void PeripheralController::dump(std::string& dump) {
     dump += INDENT2 "Input Controller:\n";
     if (!mLights.empty()) {
         dump += INDENT3 "Lights:\n";
@@ -340,7 +340,7 @@
     }
 }
 
-void InputController::configureBattries() {
+void PeripheralController::configureBattries() {
     // Check raw batteries
     const std::vector<int32_t> rawBatteryIds = getDeviceContext().getRawBatteryIds();
 
@@ -355,7 +355,7 @@
     }
 }
 
-void InputController::configureLights() {
+void PeripheralController::configureLights() {
     bool hasRedLed = false;
     bool hasGreenLed = false;
     bool hasBlueLed = false;
@@ -472,15 +472,15 @@
     }
 }
 
-std::optional<int32_t> InputController::getBatteryCapacity(int batteryId) {
+std::optional<int32_t> PeripheralController::getBatteryCapacity(int batteryId) {
     return getDeviceContext().getBatteryCapacity(batteryId);
 }
 
-std::optional<int32_t> InputController::getBatteryStatus(int batteryId) {
+std::optional<int32_t> PeripheralController::getBatteryStatus(int batteryId) {
     return getDeviceContext().getBatteryStatus(batteryId);
 }
 
-bool InputController::setLightColor(int32_t lightId, int32_t color) {
+bool PeripheralController::setLightColor(int32_t lightId, int32_t color) {
     auto it = mLights.find(lightId);
     if (it == mLights.end()) {
         return false;
@@ -493,7 +493,7 @@
     return light->setLightColor(color);
 }
 
-std::optional<int32_t> InputController::getLightColor(int32_t lightId) {
+std::optional<int32_t> PeripheralController::getLightColor(int32_t lightId) {
     auto it = mLights.find(lightId);
     if (it == mLights.end()) {
         return std::nullopt;
@@ -507,7 +507,7 @@
     return color;
 }
 
-bool InputController::setLightPlayerId(int32_t lightId, int32_t playerId) {
+bool PeripheralController::setLightPlayerId(int32_t lightId, int32_t playerId) {
     auto it = mLights.find(lightId);
     if (it == mLights.end()) {
         return false;
@@ -516,7 +516,7 @@
     return light->setLightPlayerId(playerId);
 }
 
-std::optional<int32_t> InputController::getLightPlayerId(int32_t lightId) {
+std::optional<int32_t> PeripheralController::getLightPlayerId(int32_t lightId) {
     auto it = mLights.find(lightId);
     if (it == mLights.end()) {
         return std::nullopt;
diff --git a/services/inputflinger/reader/controller/InputController.h b/services/inputflinger/reader/controller/PeripheralController.h
similarity index 96%
rename from services/inputflinger/reader/controller/InputController.h
rename to services/inputflinger/reader/controller/PeripheralController.h
index d4222e2..ff3607f 100644
--- a/services/inputflinger/reader/controller/InputController.h
+++ b/services/inputflinger/reader/controller/PeripheralController.h
@@ -17,19 +17,19 @@
 #ifndef _UI_INPUTREADER_LIGHT_CONTROLLER_H
 #define _UI_INPUTREADER_LIGHT_CONTROLLER_H
 
-#include "InputControllerInterface.h"
+#include "PeripheralControllerInterface.h"
 
 namespace android {
 
-class InputController : public InputControllerInterface {
+class PeripheralController : public PeripheralControllerInterface {
     // Refer to https://developer.android.com/reference/kotlin/android/graphics/Color
     /* Number of colors : {red, green, blue} */
     static constexpr size_t COLOR_NUM = 3;
     static constexpr int32_t MAX_BRIGHTNESS = 0xff;
 
 public:
-    explicit InputController(InputDeviceContext& deviceContext);
-    ~InputController() override;
+    explicit PeripheralController(InputDeviceContext& deviceContext);
+    ~PeripheralController() override;
 
     void populateDeviceInfo(InputDeviceInfo* deviceInfo) override;
     void dump(std::string& dump) override;
diff --git a/services/inputflinger/reader/controller/InputControllerInterface.h b/services/inputflinger/reader/controller/PeripheralControllerInterface.h
similarity index 87%
rename from services/inputflinger/reader/controller/InputControllerInterface.h
rename to services/inputflinger/reader/controller/PeripheralControllerInterface.h
index 504eded..7688a43 100644
--- a/services/inputflinger/reader/controller/InputControllerInterface.h
+++ b/services/inputflinger/reader/controller/PeripheralControllerInterface.h
@@ -24,14 +24,14 @@
 
 namespace android {
 
-/* An input controller manages the miscellaneous devices associated with the input device,
+/* A peripheral controller manages the input device peripherals associated with the input device,
  * like the sysfs based battery and light class devices.
  *
  */
-class InputControllerInterface {
+class PeripheralControllerInterface {
 public:
-    InputControllerInterface() {}
-    virtual ~InputControllerInterface() {}
+    PeripheralControllerInterface() {}
+    virtual ~PeripheralControllerInterface() {}
 
     // Interface methods for Battery
     virtual std::optional<int32_t> getBatteryCapacity(int32_t batteryId) = 0;
diff --git a/services/inputflinger/reader/include/EventHub.h b/services/inputflinger/reader/include/EventHub.h
index c970c8b..410a706 100644
--- a/services/inputflinger/reader/include/EventHub.h
+++ b/services/inputflinger/reader/include/EventHub.h
@@ -528,7 +528,7 @@
     ~EventHub() override;
 
 private:
-    struct MiscDevice {
+    struct AssociatedDevice {
         // The device descriptor from evdev device the misc device associated with.
         std::string descriptor;
         // The sysfs root path of the misc device.
@@ -538,7 +538,7 @@
         int32_t nextLightId;
         std::unordered_map<int32_t, RawBatteryInfo> batteryInfos;
         std::unordered_map<int32_t, RawLightInfo> lightInfos;
-        explicit MiscDevice(std::filesystem::path sysfsRootPath)
+        explicit AssociatedDevice(std::filesystem::path sysfsRootPath)
               : sysfsRootPath(sysfsRootPath), nextBatteryId(0), nextLightId(0) {}
         bool configureBatteryLocked();
         bool configureLightsLocked();
@@ -573,7 +573,9 @@
         bool ffEffectPlaying;
         int16_t ffEffectId; // initially -1
 
-        std::shared_ptr<MiscDevice> miscDevice;
+        // A shared_ptr of a device associated with the input device.
+        // The input devices with same descriptor has the same associated device.
+        std::shared_ptr<AssociatedDevice> associatedDevice;
 
         int32_t controllerNumber;
 
@@ -690,11 +692,6 @@
     std::vector<std::unique_ptr<Device>> mOpeningDevices;
     std::vector<std::unique_ptr<Device>> mClosingDevices;
 
-    // Map from std::string descriptor, to a shared_ptr of a miscellaneous device associated with
-    // the input device. The descriptor is the same from the EventHub device which it associates
-    // with.
-    std::unordered_map<std::string, std::shared_ptr<MiscDevice>> mMiscDevices;
-
     bool mNeedToSendFinishedDeviceScan;
     bool mNeedToReopenDevices;
     bool mNeedToScanDevices;
diff --git a/services/inputflinger/reader/include/InputDevice.h b/services/inputflinger/reader/include/InputDevice.h
index 5d56f5a..b2b23e5 100644
--- a/services/inputflinger/reader/include/InputDevice.h
+++ b/services/inputflinger/reader/include/InputDevice.h
@@ -32,9 +32,11 @@
 #include "InputReaderContext.h"
 
 namespace android {
+// TODO b/180733860 support multiple battery in API and remove this.
+constexpr int32_t DEFAULT_BATTERY_ID = 1;
 
-class InputController;
-class InputControllerInterface;
+class PeripheralController;
+class PeripheralControllerInterface;
 class InputDeviceContext;
 class InputMapper;
 
@@ -162,7 +164,7 @@
     // Map from EventHub ID to pair of device context and vector of mapper.
     std::unordered_map<int32_t, DevicePair> mDevices;
     // Misc devices controller for lights, battery, etc.
-    std::unique_ptr<InputControllerInterface> mController;
+    std::unique_ptr<PeripheralControllerInterface> mController;
 
     uint32_t mSources;
     bool mIsExternal;
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index b62fce4..31d6900 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -268,7 +268,9 @@
 
     void assertDropTargetEquals(const sp<IBinder>& targetToken) {
         std::scoped_lock lock(mLock);
+        ASSERT_TRUE(mNotifyDropWindowWasCalled);
         ASSERT_EQ(targetToken, mDropTargetWindowToken);
+        mNotifyDropWindowWasCalled = false;
     }
 
 private:
@@ -290,6 +292,7 @@
     std::condition_variable mNotifyAnr;
 
     sp<IBinder> mDropTargetWindowToken GUARDED_BY(mLock);
+    bool mNotifyDropWindowWasCalled GUARDED_BY(mLock) = false;
 
     void notifyConfigurationChanged(nsecs_t when) override {
         std::scoped_lock lock(mLock);
@@ -403,6 +406,7 @@
 
     void notifyDropWindow(const sp<IBinder>& token, float x, float y) override {
         std::scoped_lock lock(mLock);
+        mNotifyDropWindowWasCalled = true;
         mDropTargetWindowToken = token;
     }
 
@@ -4951,4 +4955,40 @@
     mSecondWindow->assertNoEvents();
 }
 
+TEST_F(InputDispatcherDragTests, DragAndDrop_InvalidWindow) {
+    performDrag();
+
+    // Set second window invisible.
+    mSecondWindow->setVisible(false);
+    mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mDragWindow, mWindow, mSecondWindow}}});
+
+    // Move on window.
+    ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
+              injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
+                                ADISPLAY_ID_DEFAULT, {50, 50}))
+            << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
+    mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
+    mWindow->consumeDragEvent(false, 50, 50);
+    mSecondWindow->assertNoEvents();
+
+    // Move to another window.
+    ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
+              injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
+                                ADISPLAY_ID_DEFAULT, {150, 50}))
+            << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
+    mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
+    mWindow->consumeDragEvent(true, 150, 50);
+    mSecondWindow->assertNoEvents();
+
+    // drop to another window.
+    ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
+              injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
+                             {150, 50}))
+            << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
+    mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
+    mFakePolicy->assertDropTargetEquals(nullptr);
+    mWindow->assertNoEvents();
+    mSecondWindow->assertNoEvents();
+}
+
 } // namespace android::inputdispatcher
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index 3d99a6b..0e721e9 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -15,7 +15,6 @@
  */
 
 #include <CursorInputMapper.h>
-#include <InputController.h>
 #include <InputDevice.h>
 #include <InputMapper.h>
 #include <InputReader.h>
@@ -23,6 +22,7 @@
 #include <InputReaderFactory.h>
 #include <KeyboardInputMapper.h>
 #include <MultiTouchInputMapper.h>
+#include <PeripheralController.h>
 #include <SensorInputMapper.h>
 #include <SingleTouchInputMapper.h>
 #include <SwitchInputMapper.h>
@@ -2015,13 +2015,13 @@
     ASSERT_EQ(mReader->getVibratorIds(deviceId).size(), 2U);
 }
 
-// --- FakeInputController ---
+// --- FakePeripheralController ---
 
-class FakeInputController : public InputControllerInterface {
+class FakePeripheralController : public PeripheralControllerInterface {
 public:
-    FakeInputController(InputDeviceContext& deviceContext) : mDeviceContext(deviceContext) {}
+    FakePeripheralController(InputDeviceContext& deviceContext) : mDeviceContext(deviceContext) {}
 
-    ~FakeInputController() override {}
+    ~FakePeripheralController() override {}
 
     void populateDeviceInfo(InputDeviceInfo* deviceInfo) override {}
 
@@ -2064,7 +2064,8 @@
     constexpr int32_t eventHubId = 1;
     const char* DEVICE_LOCATION = "BLUETOOTH";
     std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake", DEVICE_LOCATION);
-    FakeInputController& controller = device->addController<FakeInputController>(eventHubId);
+    FakePeripheralController& controller =
+            device->addController<FakePeripheralController>(eventHubId);
     mReader->pushNextDevice(device);
 
     ASSERT_NO_FATAL_FAILURE(addDevice(eventHubId, "fake", deviceClass, nullptr));
@@ -2079,7 +2080,8 @@
     constexpr int32_t eventHubId = 1;
     const char* DEVICE_LOCATION = "BLUETOOTH";
     std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake", DEVICE_LOCATION);
-    FakeInputController& controller = device->addController<FakeInputController>(eventHubId);
+    FakePeripheralController& controller =
+            device->addController<FakePeripheralController>(eventHubId);
     mReader->pushNextDevice(device);
 
     ASSERT_NO_FATAL_FAILURE(addDevice(eventHubId, "fake", deviceClass, nullptr));
@@ -2094,7 +2096,8 @@
     constexpr int32_t eventHubId = 1;
     const char* DEVICE_LOCATION = "BLUETOOTH";
     std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake", DEVICE_LOCATION);
-    FakeInputController& controller = device->addController<FakeInputController>(eventHubId);
+    FakePeripheralController& controller =
+            device->addController<FakePeripheralController>(eventHubId);
     mReader->pushNextDevice(device);
     RawLightInfo info = {.id = 1,
                          .name = "Mono",
@@ -8598,9 +8601,9 @@
     ASSERT_EQ(AINPUT_SOURCE_TOUCHPAD, mapper.getSources());
 }
 
-// --- InputControllerTest ---
+// --- PeripheralControllerTest ---
 
-class InputControllerTest : public testing::Test {
+class PeripheralControllerTest : public testing::Test {
 protected:
     static const char* DEVICE_NAME;
     static const char* DEVICE_LOCATION;
@@ -8663,41 +8666,43 @@
     }
 };
 
-const char* InputControllerTest::DEVICE_NAME = "device";
-const char* InputControllerTest::DEVICE_LOCATION = "BLUETOOTH";
-const int32_t InputControllerTest::DEVICE_ID = END_RESERVED_ID + 1000;
-const int32_t InputControllerTest::DEVICE_GENERATION = 2;
-const int32_t InputControllerTest::DEVICE_CONTROLLER_NUMBER = 0;
-const Flags<InputDeviceClass> InputControllerTest::DEVICE_CLASSES =
+const char* PeripheralControllerTest::DEVICE_NAME = "device";
+const char* PeripheralControllerTest::DEVICE_LOCATION = "BLUETOOTH";
+const int32_t PeripheralControllerTest::DEVICE_ID = END_RESERVED_ID + 1000;
+const int32_t PeripheralControllerTest::DEVICE_GENERATION = 2;
+const int32_t PeripheralControllerTest::DEVICE_CONTROLLER_NUMBER = 0;
+const Flags<InputDeviceClass> PeripheralControllerTest::DEVICE_CLASSES =
         Flags<InputDeviceClass>(0); // not needed for current tests
-const int32_t InputControllerTest::EVENTHUB_ID = 1;
+const int32_t PeripheralControllerTest::EVENTHUB_ID = 1;
 
 // --- BatteryControllerTest ---
-class BatteryControllerTest : public InputControllerTest {
+class BatteryControllerTest : public PeripheralControllerTest {
 protected:
     void SetUp() override {
-        InputControllerTest::SetUp(DEVICE_CLASSES | InputDeviceClass::BATTERY);
+        PeripheralControllerTest::SetUp(DEVICE_CLASSES | InputDeviceClass::BATTERY);
     }
 };
 
 TEST_F(BatteryControllerTest, GetBatteryCapacity) {
-    InputController& controller = addControllerAndConfigure<InputController>();
+    PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
 
     ASSERT_TRUE(controller.getBatteryCapacity(DEFAULT_BATTERY));
     ASSERT_EQ(controller.getBatteryCapacity(DEFAULT_BATTERY).value_or(-1), BATTERY_CAPACITY);
 }
 
 TEST_F(BatteryControllerTest, GetBatteryStatus) {
-    InputController& controller = addControllerAndConfigure<InputController>();
+    PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
 
     ASSERT_TRUE(controller.getBatteryStatus(DEFAULT_BATTERY));
     ASSERT_EQ(controller.getBatteryStatus(DEFAULT_BATTERY).value_or(-1), BATTERY_STATUS);
 }
 
 // --- LightControllerTest ---
-class LightControllerTest : public InputControllerTest {
+class LightControllerTest : public PeripheralControllerTest {
 protected:
-    void SetUp() override { InputControllerTest::SetUp(DEVICE_CLASSES | InputDeviceClass::LIGHT); }
+    void SetUp() override {
+        PeripheralControllerTest::SetUp(DEVICE_CLASSES | InputDeviceClass::LIGHT);
+    }
 };
 
 TEST_F(LightControllerTest, SingleLight) {
@@ -8708,7 +8713,7 @@
                                .path = ""};
     mFakeEventHub->addRawLightInfo(infoSingle.id, std::move(infoSingle));
 
-    InputController& controller = addControllerAndConfigure<InputController>();
+    PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
     InputDeviceInfo info;
     controller.populateDeviceInfo(&info);
     const auto& ids = info.getLightIds();
@@ -8739,7 +8744,7 @@
     mFakeEventHub->addRawLightInfo(infoGreen.id, std::move(infoGreen));
     mFakeEventHub->addRawLightInfo(infoBlue.id, std::move(infoBlue));
 
-    InputController& controller = addControllerAndConfigure<InputController>();
+    PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
     InputDeviceInfo info;
     controller.populateDeviceInfo(&info);
     const auto& ids = info.getLightIds();
@@ -8761,7 +8766,7 @@
 
     mFakeEventHub->addRawLightInfo(infoColor.id, std::move(infoColor));
 
-    InputController& controller = addControllerAndConfigure<InputController>();
+    PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
     InputDeviceInfo info;
     controller.populateDeviceInfo(&info);
     const auto& ids = info.getLightIds();
@@ -8798,7 +8803,7 @@
     mFakeEventHub->addRawLightInfo(info3.id, std::move(info3));
     mFakeEventHub->addRawLightInfo(info4.id, std::move(info4));
 
-    InputController& controller = addControllerAndConfigure<InputController>();
+    PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
     InputDeviceInfo info;
     controller.populateDeviceInfo(&info);
     const auto& ids = info.getLightIds();
diff --git a/services/powermanager/Android.bp b/services/powermanager/Android.bp
index 1d3e5b5..d828aa9 100644
--- a/services/powermanager/Android.bp
+++ b/services/powermanager/Android.bp
@@ -38,7 +38,7 @@
         "libutils",
         "android.hardware.power@1.0",
         "android.hardware.power@1.1",
-        "android.hardware.power-V1-cpp",
+        "android.hardware.power-V2-cpp",
     ],
 
     cflags: [
diff --git a/services/powermanager/PowerHalController.cpp b/services/powermanager/PowerHalController.cpp
index 178f545..8c225d5 100644
--- a/services/powermanager/PowerHalController.cpp
+++ b/services/powermanager/PowerHalController.cpp
@@ -18,6 +18,7 @@
 #include <android/hardware/power/1.1/IPower.h>
 #include <android/hardware/power/Boost.h>
 #include <android/hardware/power/IPower.h>
+#include <android/hardware/power/IPowerHintSession.h>
 #include <android/hardware/power/Mode.h>
 #include <powermanager/PowerHalController.h>
 #include <powermanager/PowerHalLoader.h>
@@ -73,9 +74,10 @@
 
 // Check if a call to Power HAL function failed; if so, log the failure and
 // invalidate the current Power HAL handle.
-HalResult PowerHalController::processHalResult(HalResult result, const char* fnName) {
-    if (result == HalResult::FAILED) {
-        ALOGE("%s() failed: power HAL service not available.", fnName);
+template <typename T>
+HalResult<T> PowerHalController::processHalResult(HalResult<T> result, const char* fnName) {
+    if (result.isFailed()) {
+        ALOGE("%s failed: %s", fnName, result.errorMessage());
         std::lock_guard<std::mutex> lock(mConnectedHalMutex);
         // Drop Power HAL handle. This will force future api calls to reconnect.
         mConnectedHal = nullptr;
@@ -84,18 +86,31 @@
     return result;
 }
 
-HalResult PowerHalController::setBoost(Boost boost, int32_t durationMs) {
+HalResult<void> PowerHalController::setBoost(Boost boost, int32_t durationMs) {
     std::shared_ptr<HalWrapper> handle = initHal();
     auto result = handle->setBoost(boost, durationMs);
     return processHalResult(result, "setBoost");
 }
 
-HalResult PowerHalController::setMode(Mode mode, bool enabled) {
+HalResult<void> PowerHalController::setMode(Mode mode, bool enabled) {
     std::shared_ptr<HalWrapper> handle = initHal();
     auto result = handle->setMode(mode, enabled);
     return processHalResult(result, "setMode");
 }
 
+HalResult<sp<IPowerHintSession>> PowerHalController::createHintSession(
+        int32_t tgid, int32_t uid, const std::vector<int32_t>& threadIds, int64_t durationNanos) {
+    std::shared_ptr<HalWrapper> handle = initHal();
+    auto result = handle->createHintSession(tgid, uid, threadIds, durationNanos);
+    return processHalResult(result, "createHintSession");
+}
+
+HalResult<int64_t> PowerHalController::getHintSessionPreferredRate() {
+    std::shared_ptr<HalWrapper> handle = initHal();
+    auto result = handle->getHintSessionPreferredRate();
+    return processHalResult(result, "getHintSessionPreferredRate");
+}
+
 } // namespace power
 
 } // namespace android
diff --git a/services/powermanager/PowerHalWrapper.cpp b/services/powermanager/PowerHalWrapper.cpp
index 2f32827..d74bd23 100644
--- a/services/powermanager/PowerHalWrapper.cpp
+++ b/services/powermanager/PowerHalWrapper.cpp
@@ -16,11 +16,17 @@
 
 #define LOG_TAG "HalWrapper"
 #include <android/hardware/power/Boost.h>
+#include <android/hardware/power/IPowerHintSession.h>
 #include <android/hardware/power/Mode.h>
 #include <powermanager/PowerHalWrapper.h>
 #include <utils/Log.h>
 
+#include <cinttypes>
+
 using namespace android::hardware::power;
+namespace V1_0 = android::hardware::power::V1_0;
+namespace V1_1 = android::hardware::power::V1_1;
+namespace Aidl = android::hardware::power;
 
 namespace android {
 
@@ -28,49 +34,88 @@
 
 // -------------------------------------------------------------------------------------------------
 
-inline HalResult toHalResult(const binder::Status& result) {
+inline HalResult<void> toHalResult(const binder::Status& result) {
     if (result.isOk()) {
-        return HalResult::SUCCESSFUL;
+        return HalResult<void>::ok();
     }
     ALOGE("Power HAL request failed: %s", result.toString8().c_str());
-    return HalResult::FAILED;
+    return HalResult<void>::fromStatus(result);
 }
 
 template <typename T>
-inline HalResult toHalResult(const hardware::Return<T>& result) {
-    if (result.isOk()) {
-        return HalResult::SUCCESSFUL;
-    }
-    ALOGE("Power HAL request failed: %s", result.description().c_str());
-    return HalResult::FAILED;
+template <typename R>
+HalResult<T> HalResult<T>::fromReturn(hardware::Return<R>& ret, T data) {
+    return ret.isOk() ? HalResult<T>::ok(data) : HalResult<T>::failed(ret.description());
+}
+
+template <typename T>
+template <typename R>
+HalResult<T> HalResult<T>::fromReturn(hardware::Return<R>& ret, V1_0::Status status, T data) {
+    return ret.isOk() ? HalResult<T>::fromStatus(status, data)
+                      : HalResult<T>::failed(ret.description());
 }
 
 // -------------------------------------------------------------------------------------------------
 
-HalResult EmptyHalWrapper::setBoost(Boost boost, int32_t durationMs) {
+HalResult<void> HalResult<void>::fromStatus(status_t status) {
+    if (status == android::OK) {
+        return HalResult<void>::ok();
+    }
+    return HalResult<void>::failed(statusToString(status));
+}
+
+HalResult<void> HalResult<void>::fromStatus(binder::Status status) {
+    if (status.exceptionCode() == binder::Status::EX_UNSUPPORTED_OPERATION) {
+        return HalResult<void>::unsupported();
+    }
+    if (status.isOk()) {
+        return HalResult<void>::ok();
+    }
+    return HalResult<void>::failed(std::string(status.toString8().c_str()));
+}
+
+template <typename R>
+HalResult<void> HalResult<void>::fromReturn(hardware::Return<R>& ret) {
+    return ret.isOk() ? HalResult<void>::ok() : HalResult<void>::failed(ret.description());
+}
+// -------------------------------------------------------------------------------------------------
+
+HalResult<void> EmptyHalWrapper::setBoost(Boost boost, int32_t durationMs) {
     ALOGV("Skipped setBoost %s with duration %dms because Power HAL not available",
           toString(boost).c_str(), durationMs);
-    return HalResult::UNSUPPORTED;
+    return HalResult<void>::unsupported();
 }
 
-HalResult EmptyHalWrapper::setMode(Mode mode, bool enabled) {
+HalResult<void> EmptyHalWrapper::setMode(Mode mode, bool enabled) {
     ALOGV("Skipped setMode %s to %s because Power HAL not available", toString(mode).c_str(),
           enabled ? "true" : "false");
-    return HalResult::UNSUPPORTED;
+    return HalResult<void>::unsupported();
+}
+
+HalResult<sp<Aidl::IPowerHintSession>> EmptyHalWrapper::createHintSession(
+        int32_t, int32_t, const std::vector<int32_t>& threadIds, int64_t) {
+    ALOGV("Skipped createHintSession(task num=%zu) because Power HAL not available",
+          threadIds.size());
+    return HalResult<sp<Aidl::IPowerHintSession>>::unsupported();
+}
+
+HalResult<int64_t> EmptyHalWrapper::getHintSessionPreferredRate() {
+    ALOGV("Skipped getHintSessionPreferredRate because Power HAL not available");
+    return HalResult<int64_t>::unsupported();
 }
 
 // -------------------------------------------------------------------------------------------------
 
-HalResult HidlHalWrapperV1_0::setBoost(Boost boost, int32_t durationMs) {
+HalResult<void> HidlHalWrapperV1_0::setBoost(Boost boost, int32_t durationMs) {
     if (boost == Boost::INTERACTION) {
         return sendPowerHint(V1_0::PowerHint::INTERACTION, durationMs);
     } else {
         ALOGV("Skipped setBoost %s because Power HAL AIDL not available", toString(boost).c_str());
-        return HalResult::UNSUPPORTED;
+        return HalResult<void>::unsupported();
     }
 }
 
-HalResult HidlHalWrapperV1_0::setMode(Mode mode, bool enabled) {
+HalResult<void> HidlHalWrapperV1_0::setMode(Mode mode, bool enabled) {
     uint32_t data = enabled ? 1 : 0;
     switch (mode) {
         case Mode::LAUNCH:
@@ -88,38 +133,54 @@
         default:
             ALOGV("Skipped setMode %s because Power HAL AIDL not available",
                   toString(mode).c_str());
-            return HalResult::UNSUPPORTED;
+            return HalResult<void>::unsupported();
     }
 }
 
-HalResult HidlHalWrapperV1_0::sendPowerHint(V1_0::PowerHint hintId, uint32_t data) {
-    return toHalResult(mHandleV1_0->powerHint(hintId, data));
+HalResult<void> HidlHalWrapperV1_0::sendPowerHint(V1_0::PowerHint hintId, uint32_t data) {
+    auto ret = mHandleV1_0->powerHint(hintId, data);
+    return HalResult<void>::fromReturn(ret);
 }
 
-HalResult HidlHalWrapperV1_0::setInteractive(bool enabled) {
-    return toHalResult(mHandleV1_0->setInteractive(enabled));
+HalResult<void> HidlHalWrapperV1_0::setInteractive(bool enabled) {
+    auto ret = mHandleV1_0->setInteractive(enabled);
+    return HalResult<void>::fromReturn(ret);
 }
 
-HalResult HidlHalWrapperV1_0::setFeature(V1_0::Feature feature, bool enabled) {
-    return toHalResult(mHandleV1_0->setFeature(feature, enabled));
+HalResult<void> HidlHalWrapperV1_0::setFeature(V1_0::Feature feature, bool enabled) {
+    auto ret = mHandleV1_0->setFeature(feature, enabled);
+    return HalResult<void>::fromReturn(ret);
+}
+
+HalResult<sp<Aidl::IPowerHintSession>> HidlHalWrapperV1_0::createHintSession(
+        int32_t, int32_t, const std::vector<int32_t>& threadIds, int64_t) {
+    ALOGV("Skipped createHintSession(task num=%zu) because Power HAL not available",
+          threadIds.size());
+    return HalResult<sp<Aidl::IPowerHintSession>>::unsupported();
+}
+
+HalResult<int64_t> HidlHalWrapperV1_0::getHintSessionPreferredRate() {
+    ALOGV("Skipped getHintSessionPreferredRate because Power HAL not available");
+    return HalResult<int64_t>::unsupported();
 }
 
 // -------------------------------------------------------------------------------------------------
 
-HalResult HidlHalWrapperV1_1::sendPowerHint(V1_0::PowerHint hintId, uint32_t data) {
-    return toHalResult(mHandleV1_1->powerHintAsync(hintId, data));
+HalResult<void> HidlHalWrapperV1_1::sendPowerHint(V1_0::PowerHint hintId, uint32_t data) {
+    auto ret = mHandleV1_1->powerHintAsync(hintId, data);
+    return HalResult<void>::fromReturn(ret);
 }
 
 // -------------------------------------------------------------------------------------------------
 
-HalResult AidlHalWrapper::setBoost(Boost boost, int32_t durationMs) {
+HalResult<void> AidlHalWrapper::setBoost(Boost boost, int32_t durationMs) {
     std::unique_lock<std::mutex> lock(mBoostMutex);
     size_t idx = static_cast<size_t>(boost);
 
     // Quick return if boost is not supported by HAL
     if (idx >= mBoostSupportedArray.size() || mBoostSupportedArray[idx] == HalSupport::OFF) {
         ALOGV("Skipped setBoost %s because Power HAL doesn't support it", toString(boost).c_str());
-        return HalResult::UNSUPPORTED;
+        return HalResult<void>::unsupported();
     }
 
     if (mBoostSupportedArray[idx] == HalSupport::UNKNOWN) {
@@ -128,14 +189,15 @@
         if (!isSupportedRet.isOk()) {
             ALOGE("Skipped setBoost %s because check support failed with: %s",
                   toString(boost).c_str(), isSupportedRet.toString8().c_str());
-            return HalResult::FAILED;
+            // return HalResult::FAILED;
+            return HalResult<void>::fromStatus(isSupportedRet);
         }
 
         mBoostSupportedArray[idx] = isSupported ? HalSupport::ON : HalSupport::OFF;
         if (!isSupported) {
             ALOGV("Skipped setBoost %s because Power HAL doesn't support it",
                   toString(boost).c_str());
-            return HalResult::UNSUPPORTED;
+            return HalResult<void>::unsupported();
         }
     }
     lock.unlock();
@@ -143,30 +205,28 @@
     return toHalResult(mHandle->setBoost(boost, durationMs));
 }
 
-HalResult AidlHalWrapper::setMode(Mode mode, bool enabled) {
+HalResult<void> AidlHalWrapper::setMode(Mode mode, bool enabled) {
     std::unique_lock<std::mutex> lock(mModeMutex);
     size_t idx = static_cast<size_t>(mode);
 
     // Quick return if mode is not supported by HAL
     if (idx >= mModeSupportedArray.size() || mModeSupportedArray[idx] == HalSupport::OFF) {
         ALOGV("Skipped setMode %s because Power HAL doesn't support it", toString(mode).c_str());
-        return HalResult::UNSUPPORTED;
+        return HalResult<void>::unsupported();
     }
 
     if (mModeSupportedArray[idx] == HalSupport::UNKNOWN) {
         bool isSupported = false;
         auto isSupportedRet = mHandle->isModeSupported(mode, &isSupported);
         if (!isSupportedRet.isOk()) {
-            ALOGE("Skipped setMode %s because check support failed with: %s",
-                  toString(mode).c_str(), isSupportedRet.toString8().c_str());
-            return HalResult::FAILED;
+            return HalResult<void>::failed(isSupportedRet.toString8().c_str());
         }
 
         mModeSupportedArray[idx] = isSupported ? HalSupport::ON : HalSupport::OFF;
         if (!isSupported) {
             ALOGV("Skipped setMode %s because Power HAL doesn't support it",
                   toString(mode).c_str());
-            return HalResult::UNSUPPORTED;
+            return HalResult<void>::unsupported();
         }
     }
     lock.unlock();
@@ -174,6 +234,20 @@
     return toHalResult(mHandle->setMode(mode, enabled));
 }
 
+HalResult<sp<Aidl::IPowerHintSession>> AidlHalWrapper::createHintSession(
+        int32_t tgid, int32_t uid, const std::vector<int32_t>& threadIds, int64_t durationNanos) {
+    sp<IPowerHintSession> appSession;
+    return HalResult<sp<Aidl::IPowerHintSession>>::
+            fromStatus(mHandle->createHintSession(tgid, uid, threadIds, durationNanos, &appSession),
+                       appSession);
+}
+
+HalResult<int64_t> AidlHalWrapper::getHintSessionPreferredRate() {
+    int64_t rate = -1;
+    auto result = mHandle->getHintSessionPreferredRate(&rate);
+    return HalResult<int64_t>::fromStatus(result, rate);
+}
+
 // -------------------------------------------------------------------------------------------------
 
 } // namespace power
diff --git a/services/powermanager/benchmarks/Android.bp b/services/powermanager/benchmarks/Android.bp
index a489253..3997929 100644
--- a/services/powermanager/benchmarks/Android.bp
+++ b/services/powermanager/benchmarks/Android.bp
@@ -38,7 +38,7 @@
         "libutils",
         "android.hardware.power@1.0",
         "android.hardware.power@1.1",
-        "android.hardware.power-V1-cpp",
+        "android.hardware.power-V2-cpp",
     ],
     static_libs: [
         "libtestUtil",
diff --git a/services/powermanager/benchmarks/PowerHalAidlBenchmarks.cpp b/services/powermanager/benchmarks/PowerHalAidlBenchmarks.cpp
index 1004828..1100cad 100644
--- a/services/powermanager/benchmarks/PowerHalAidlBenchmarks.cpp
+++ b/services/powermanager/benchmarks/PowerHalAidlBenchmarks.cpp
@@ -18,7 +18,9 @@
 
 #include <android/hardware/power/Boost.h>
 #include <android/hardware/power/IPower.h>
+#include <android/hardware/power/IPowerHintSession.h>
 #include <android/hardware/power/Mode.h>
+#include <android/hardware/power/WorkDuration.h>
 #include <benchmark/benchmark.h>
 #include <binder/IServiceManager.h>
 #include <testUtil.h>
@@ -26,7 +28,9 @@
 
 using android::hardware::power::Boost;
 using android::hardware::power::IPower;
+using android::hardware::power::IPowerHintSession;
 using android::hardware::power::Mode;
+using android::hardware::power::WorkDuration;
 using std::chrono::microseconds;
 
 using namespace android;
@@ -38,6 +42,21 @@
 static constexpr int64_t FIRST_MODE = static_cast<int64_t>(Mode::DOUBLE_TAP_TO_WAKE);
 static constexpr int64_t LAST_MODE = static_cast<int64_t>(Mode::CAMERA_STREAMING_HIGH);
 
+class DurationWrapper : public WorkDuration {
+public:
+    DurationWrapper(int64_t dur, int64_t time) {
+        durationNanos = dur;
+        timeStampNanos = time;
+    }
+};
+
+static const std::vector<WorkDuration> DURATIONS = {
+        DurationWrapper(1L, 1L),
+        DurationWrapper(1000L, 2L),
+        DurationWrapper(1000000L, 3L),
+        DurationWrapper(1000000000L, 4L),
+};
+
 // Delay between oneway method calls to avoid overflowing the binder buffers.
 static constexpr microseconds ONEWAY_API_DELAY = 100us;
 
@@ -68,6 +87,47 @@
     }
 }
 
+template <class R, class... Args0, class... Args1>
+static void runSessionBenchmark(benchmark::State& state, R (IPowerHintSession::*fn)(Args0...),
+                                Args1&&... args1) {
+    sp<IPower> pwHal = waitForVintfService<IPower>();
+
+    if (pwHal == nullptr) {
+        ALOGI("Power HAL not available, skipping test...");
+        return;
+    }
+
+    // do not use tid from the benchmark process, use 1 for init
+    std::vector<int32_t> threadIds{1};
+    int64_t durationNanos = 16666666L;
+    sp<IPowerHintSession> hal;
+
+    auto status = pwHal->createHintSession(1, 0, threadIds, durationNanos, &hal);
+
+    if (hal == nullptr) {
+        ALOGI("Power HAL doesn't support session, skipping test...");
+        return;
+    }
+
+    binder::Status ret = (*hal.*fn)(std::forward<Args1>(args1)...);
+    if (ret.exceptionCode() == binder::Status::Exception::EX_UNSUPPORTED_OPERATION) {
+        ALOGI("Power HAL does not support this operation, skipping test...");
+        return;
+    }
+
+    while (state.KeepRunning()) {
+        ret = (*hal.*fn)(std::forward<Args1>(args1)...);
+        state.PauseTiming();
+        if (!ret.isOk()) state.SkipWithError(ret.toString8().c_str());
+        if (ONEWAY_API_DELAY > 0us) {
+            testDelaySpin(std::chrono::duration_cast<std::chrono::duration<float>>(ONEWAY_API_DELAY)
+                                  .count());
+        }
+        state.ResumeTiming();
+    }
+    hal->close();
+}
+
 static void BM_PowerHalAidlBenchmarks_isBoostSupported(benchmark::State& state) {
     bool isSupported;
     Boost boost = static_cast<Boost>(state.range(0));
@@ -90,7 +150,53 @@
     runBenchmark(state, ONEWAY_API_DELAY, &IPower::setMode, mode, false);
 }
 
+static void BM_PowerHalAidlBenchmarks_createHintSession(benchmark::State& state) {
+    std::vector<int32_t> threadIds{static_cast<int32_t>(state.range(0))};
+    int64_t durationNanos = 16666666L;
+    int32_t tgid = 999;
+    int32_t uid = 1001;
+    sp<IPowerHintSession> appSession;
+    sp<IPower> hal = waitForVintfService<IPower>();
+
+    if (hal == nullptr) {
+        ALOGI("Power HAL not available, skipping test...");
+        return;
+    }
+
+    binder::Status ret = hal->createHintSession(tgid, uid, threadIds, durationNanos, &appSession);
+    if (ret.exceptionCode() == binder::Status::Exception::EX_UNSUPPORTED_OPERATION) {
+        ALOGI("Power HAL does not support this operation, skipping test...");
+        return;
+    }
+
+    while (state.KeepRunning()) {
+        ret = hal->createHintSession(tgid, uid, threadIds, durationNanos, &appSession);
+        state.PauseTiming();
+        if (!ret.isOk()) state.SkipWithError(ret.toString8().c_str());
+        appSession->close();
+        state.ResumeTiming();
+    }
+}
+
+static void BM_PowerHalAidlBenchmarks_getHintSessionPreferredRate(benchmark::State& state) {
+    int64_t rate;
+    runBenchmark(state, 0us, &IPower::getHintSessionPreferredRate, &rate);
+}
+
+static void BM_PowerHalAidlBenchmarks_updateTargetWorkDuration(benchmark::State& state) {
+    int64_t duration = 1000;
+    runSessionBenchmark(state, &IPowerHintSession::updateTargetWorkDuration, duration);
+}
+
+static void BM_PowerHalAidlBenchmarks_reportActualWorkDuration(benchmark::State& state) {
+    runSessionBenchmark(state, &IPowerHintSession::reportActualWorkDuration, DURATIONS);
+}
+
 BENCHMARK(BM_PowerHalAidlBenchmarks_isBoostSupported)->DenseRange(FIRST_BOOST, LAST_BOOST, 1);
 BENCHMARK(BM_PowerHalAidlBenchmarks_isModeSupported)->DenseRange(FIRST_MODE, LAST_MODE, 1);
 BENCHMARK(BM_PowerHalAidlBenchmarks_setBoost)->DenseRange(FIRST_BOOST, LAST_BOOST, 1);
 BENCHMARK(BM_PowerHalAidlBenchmarks_setMode)->DenseRange(FIRST_MODE, LAST_MODE, 1);
+BENCHMARK(BM_PowerHalAidlBenchmarks_createHintSession)->Arg(1);
+BENCHMARK(BM_PowerHalAidlBenchmarks_getHintSessionPreferredRate);
+BENCHMARK(BM_PowerHalAidlBenchmarks_updateTargetWorkDuration);
+BENCHMARK(BM_PowerHalAidlBenchmarks_reportActualWorkDuration);
diff --git a/services/powermanager/benchmarks/PowerHalControllerBenchmarks.cpp b/services/powermanager/benchmarks/PowerHalControllerBenchmarks.cpp
index 598080b..f8abc7a 100644
--- a/services/powermanager/benchmarks/PowerHalControllerBenchmarks.cpp
+++ b/services/powermanager/benchmarks/PowerHalControllerBenchmarks.cpp
@@ -40,29 +40,29 @@
 // Delay between oneway method calls to avoid overflowing the binder buffers.
 static constexpr std::chrono::microseconds ONEWAY_API_DELAY = 100us;
 
-template <class... Args0, class... Args1>
-static void runBenchmark(benchmark::State& state, HalResult (PowerHalController::*fn)(Args0...),
+template <typename T, class... Args0, class... Args1>
+static void runBenchmark(benchmark::State& state, HalResult<T> (PowerHalController::*fn)(Args0...),
                          Args1&&... args1) {
     while (state.KeepRunning()) {
         PowerHalController controller;
-        HalResult ret = (controller.*fn)(std::forward<Args1>(args1)...);
+        HalResult<T> ret = (controller.*fn)(std::forward<Args1>(args1)...);
         state.PauseTiming();
-        if (ret == HalResult::FAILED) state.SkipWithError("Power HAL request failed");
+        if (ret.isFailed()) state.SkipWithError("Power HAL request failed");
         state.ResumeTiming();
     }
 }
 
-template <class... Args0, class... Args1>
+template <typename T, class... Args0, class... Args1>
 static void runCachedBenchmark(benchmark::State& state,
-                               HalResult (PowerHalController::*fn)(Args0...), Args1&&... args1) {
+                               HalResult<T> (PowerHalController::*fn)(Args0...), Args1&&... args1) {
     PowerHalController controller;
     // First call out of test, to cache HAL service and isSupported result.
     (controller.*fn)(std::forward<Args1>(args1)...);
 
     while (state.KeepRunning()) {
-        HalResult ret = (controller.*fn)(std::forward<Args1>(args1)...);
+        HalResult<T> ret = (controller.*fn)(std::forward<Args1>(args1)...);
         state.PauseTiming();
-        if (ret == HalResult::FAILED) {
+        if (ret.isFailed()) {
             state.SkipWithError("Power HAL request failed");
         }
         testDelaySpin(
diff --git a/services/powermanager/tests/Android.bp b/services/powermanager/tests/Android.bp
index 69e4041..659b2d2 100644
--- a/services/powermanager/tests/Android.bp
+++ b/services/powermanager/tests/Android.bp
@@ -46,7 +46,7 @@
         "libutils",
         "android.hardware.power@1.0",
         "android.hardware.power@1.1",
-        "android.hardware.power-V1-cpp",
+        "android.hardware.power-V2-cpp",
     ],
     static_libs: [
         "libgmock",
diff --git a/services/powermanager/tests/PowerHalControllerTest.cpp b/services/powermanager/tests/PowerHalControllerTest.cpp
index 141b244..6cc7a6f 100644
--- a/services/powermanager/tests/PowerHalControllerTest.cpp
+++ b/services/powermanager/tests/PowerHalControllerTest.cpp
@@ -134,9 +134,9 @@
     // Still works with EmptyPowerHalWrapper as fallback ignoring every api call
     // and logging.
     auto result = halController.setBoost(Boost::INTERACTION, 1000);
-    ASSERT_EQ(HalResult::UNSUPPORTED, result);
+    ASSERT_TRUE(result.isUnsupported());
     result = halController.setMode(Mode::LAUNCH, true);
-    ASSERT_EQ(HalResult::UNSUPPORTED, result);
+    ASSERT_TRUE(result.isUnsupported());
 
     // PowerHalConnector was called every time to attempt to reconnect with
     // underlying service.
@@ -159,9 +159,9 @@
     }
 
     auto result = mHalController->setBoost(Boost::INTERACTION, 100);
-    ASSERT_EQ(HalResult::SUCCESSFUL, result);
+    ASSERT_TRUE(result.isOk());
     result = mHalController->setMode(Mode::LAUNCH, true);
-    ASSERT_EQ(HalResult::SUCCESSFUL, result);
+    ASSERT_TRUE(result.isOk());
 
     // PowerHalConnector was called only once and never reset.
     powerHalConnectCount = mHalConnector->getConnectCount();
@@ -182,13 +182,13 @@
     EXPECT_CALL(*mMockHal.get(), powerHint(_, _)).Times(Exactly(4));
 
     auto result = mHalController->setBoost(Boost::INTERACTION, 1000);
-    ASSERT_EQ(HalResult::SUCCESSFUL, result);
+    ASSERT_TRUE(result.isOk());
     result = mHalController->setMode(Mode::LAUNCH, true);
-    ASSERT_EQ(HalResult::FAILED, result);
+    ASSERT_TRUE(result.isFailed());
     result = mHalController->setMode(Mode::VR, false);
-    ASSERT_EQ(HalResult::SUCCESSFUL, result);
+    ASSERT_TRUE(result.isOk());
     result = mHalController->setMode(Mode::LOW_POWER, true);
-    ASSERT_EQ(HalResult::SUCCESSFUL, result);
+    ASSERT_TRUE(result.isOk());
 
     // PowerHalConnector was called only twice: on first api call and after failed
     // call.
@@ -204,9 +204,9 @@
     EXPECT_EQ(powerHalConnectCount, 0);
 
     auto result = mHalController->setBoost(Boost::CAMERA_LAUNCH, 1000);
-    ASSERT_EQ(HalResult::UNSUPPORTED, result);
+    ASSERT_TRUE(result.isUnsupported());
     result = mHalController->setMode(Mode::CAMERA_STREAMING_HIGH, true);
-    ASSERT_EQ(HalResult::UNSUPPORTED, result);
+    ASSERT_TRUE(result.isUnsupported());
 
     // PowerHalConnector was called only once and never reset.
     powerHalConnectCount = mHalConnector->getConnectCount();
@@ -225,7 +225,7 @@
     for (int i = 0; i < 10; i++) {
         threads.push_back(std::thread([&]() {
             auto result = mHalController->setBoost(Boost::INTERACTION, 1000);
-            ASSERT_EQ(HalResult::SUCCESSFUL, result);
+            ASSERT_TRUE(result.isOk());
         }));
     }
     std::for_each(threads.begin(), threads.end(), [](std::thread& t) { t.join(); });
@@ -253,19 +253,19 @@
     for (int i = 0; i < 10; i++) {
         threads.push_back(std::thread([&]() {
             auto result = mHalController->setBoost(Boost::INTERACTION, 1000);
-            ASSERT_EQ(HalResult::SUCCESSFUL, result);
+            ASSERT_TRUE(result.isOk());
         }));
         threads.push_back(std::thread([&]() {
             auto result = mHalController->setMode(Mode::LAUNCH, true);
-            ASSERT_EQ(HalResult::FAILED, result);
+            ASSERT_TRUE(result.isFailed());
         }));
         threads.push_back(std::thread([&]() {
             auto result = mHalController->setMode(Mode::LOW_POWER, false);
-            ASSERT_EQ(HalResult::SUCCESSFUL, result);
+            ASSERT_TRUE(result.isOk());
         }));
         threads.push_back(std::thread([&]() {
             auto result = mHalController->setMode(Mode::VR, true);
-            ASSERT_EQ(HalResult::SUCCESSFUL, result);
+            ASSERT_TRUE(result.isOk());
         }));
     }
     std::for_each(threads.begin(), threads.end(), [](std::thread& t) { t.join(); });
diff --git a/services/powermanager/tests/PowerHalWrapperAidlTest.cpp b/services/powermanager/tests/PowerHalWrapperAidlTest.cpp
index a765659..d890f5c 100644
--- a/services/powermanager/tests/PowerHalWrapperAidlTest.cpp
+++ b/services/powermanager/tests/PowerHalWrapperAidlTest.cpp
@@ -17,6 +17,7 @@
 #define LOG_TAG "PowerHalWrapperAidlTest"
 
 #include <android/hardware/power/Boost.h>
+#include <android/hardware/power/IPowerHintSession.h>
 #include <android/hardware/power/Mode.h>
 #include <binder/IServiceManager.h>
 #include <gmock/gmock.h>
@@ -24,11 +25,13 @@
 #include <powermanager/PowerHalWrapper.h>
 #include <utils/Log.h>
 
+#include <unistd.h>
 #include <thread>
 
 using android::binder::Status;
 using android::hardware::power::Boost;
 using android::hardware::power::IPower;
+using android::hardware::power::IPowerHintSession;
 using android::hardware::power::Mode;
 
 using namespace android;
@@ -44,6 +47,11 @@
     MOCK_METHOD(Status, setBoost, (Boost boost, int32_t durationMs), (override));
     MOCK_METHOD(Status, isModeSupported, (Mode mode, bool* ret), (override));
     MOCK_METHOD(Status, setMode, (Mode mode, bool enabled), (override));
+    MOCK_METHOD(Status, createHintSession,
+                (int32_t tgid, int32_t uid, const std::vector<int32_t>& threadIds,
+                 int64_t durationNanos, sp<IPowerHintSession>* session),
+                (override));
+    MOCK_METHOD(Status, getHintSessionPreferredRate, (int64_t * rate), (override));
     MOCK_METHOD(int32_t, getInterfaceVersion, (), (override));
     MOCK_METHOD(std::string, getInterfaceHash, (), (override));
     MOCK_METHOD(IBinder*, onAsBinder, (), (override));
@@ -65,7 +73,7 @@
 void PowerHalWrapperAidlTest::SetUp() {
     mMockHal = new StrictMock<MockIPower>();
     mWrapper = std::make_unique<AidlHalWrapper>(mMockHal);
-    ASSERT_NE(mWrapper, nullptr);
+    ASSERT_NE(nullptr, mWrapper);
 }
 
 // -------------------------------------------------------------------------------------------------
@@ -81,7 +89,7 @@
     }
 
     auto result = mWrapper->setBoost(Boost::DISPLAY_UPDATE_IMMINENT, 100);
-    ASSERT_EQ(HalResult::SUCCESSFUL, result);
+    ASSERT_TRUE(result.isOk());
 }
 
 TEST_F(PowerHalWrapperAidlTest, TestSetBoostFailed) {
@@ -99,9 +107,9 @@
     }
 
     auto result = mWrapper->setBoost(Boost::INTERACTION, 100);
-    ASSERT_EQ(HalResult::FAILED, result);
+    ASSERT_TRUE(result.isFailed());
     result = mWrapper->setBoost(Boost::DISPLAY_UPDATE_IMMINENT, 1000);
-    ASSERT_EQ(HalResult::FAILED, result);
+    ASSERT_TRUE(result.isFailed());
 }
 
 TEST_F(PowerHalWrapperAidlTest, TestSetBoostUnsupported) {
@@ -110,9 +118,9 @@
             .WillRepeatedly(DoAll(SetArgPointee<1>(false), Return(Status())));
 
     auto result = mWrapper->setBoost(Boost::INTERACTION, 1000);
-    ASSERT_EQ(HalResult::UNSUPPORTED, result);
+    ASSERT_TRUE(result.isUnsupported());
     result = mWrapper->setBoost(Boost::CAMERA_SHOT, 10);
-    ASSERT_EQ(HalResult::UNSUPPORTED, result);
+    ASSERT_TRUE(result.isUnsupported());
 }
 
 TEST_F(PowerHalWrapperAidlTest, TestSetBoostMultiThreadCheckSupportedOnlyOnce) {
@@ -128,7 +136,7 @@
     for (int i = 0; i < 10; i++) {
         threads.push_back(std::thread([&]() {
             auto result = mWrapper->setBoost(Boost::INTERACTION, 100);
-            ASSERT_EQ(HalResult::SUCCESSFUL, result);
+            ASSERT_TRUE(result.isOk());
         }));
     }
     std::for_each(threads.begin(), threads.end(), [](std::thread& t) { t.join(); });
@@ -145,7 +153,7 @@
     }
 
     auto result = mWrapper->setMode(Mode::DISPLAY_INACTIVE, false);
-    ASSERT_EQ(HalResult::SUCCESSFUL, result);
+    ASSERT_TRUE(result.isOk());
 }
 
 TEST_F(PowerHalWrapperAidlTest, TestSetModeFailed) {
@@ -163,9 +171,9 @@
     }
 
     auto result = mWrapper->setMode(Mode::LAUNCH, true);
-    ASSERT_EQ(HalResult::FAILED, result);
+    ASSERT_TRUE(result.isFailed());
     result = mWrapper->setMode(Mode::DISPLAY_INACTIVE, false);
-    ASSERT_EQ(HalResult::FAILED, result);
+    ASSERT_TRUE(result.isFailed());
 }
 
 TEST_F(PowerHalWrapperAidlTest, TestSetModeUnsupported) {
@@ -174,9 +182,9 @@
             .WillRepeatedly(DoAll(SetArgPointee<1>(false), Return(Status())));
 
     auto result = mWrapper->setMode(Mode::LAUNCH, true);
-    ASSERT_EQ(HalResult::UNSUPPORTED, result);
+    ASSERT_TRUE(result.isUnsupported());
     result = mWrapper->setMode(Mode::CAMERA_STREAMING_HIGH, true);
-    ASSERT_EQ(HalResult::UNSUPPORTED, result);
+    ASSERT_TRUE(result.isUnsupported());
 }
 
 TEST_F(PowerHalWrapperAidlTest, TestSetModeMultiThreadCheckSupportedOnlyOnce) {
@@ -192,8 +200,41 @@
     for (int i = 0; i < 10; i++) {
         threads.push_back(std::thread([&]() {
             auto result = mWrapper->setMode(Mode::LAUNCH, false);
-            ASSERT_EQ(HalResult::SUCCESSFUL, result);
+            ASSERT_TRUE(result.isOk());
         }));
     }
     std::for_each(threads.begin(), threads.end(), [](std::thread& t) { t.join(); });
 }
+
+TEST_F(PowerHalWrapperAidlTest, TestCreateHintSessionSuccessful) {
+    std::vector<int> threadIds{gettid()};
+    int32_t tgid = 999;
+    int32_t uid = 1001;
+    int64_t durationNanos = 16666666L;
+    EXPECT_CALL(*mMockHal.get(),
+                createHintSession(Eq(tgid), Eq(uid), Eq(threadIds), Eq(durationNanos), _))
+            .Times(Exactly(1));
+    auto result = mWrapper->createHintSession(tgid, uid, threadIds, durationNanos);
+    ASSERT_TRUE(result.isOk());
+}
+
+TEST_F(PowerHalWrapperAidlTest, TestCreateHintSessionFailed) {
+    int32_t tgid = 999;
+    int32_t uid = 1001;
+    std::vector<int> threadIds{};
+    int64_t durationNanos = 16666666L;
+    EXPECT_CALL(*mMockHal.get(),
+                createHintSession(Eq(tgid), Eq(uid), Eq(threadIds), Eq(durationNanos), _))
+            .Times(Exactly(1))
+            .WillRepeatedly(Return(Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT)));
+    auto result = mWrapper->createHintSession(tgid, uid, threadIds, durationNanos);
+    ASSERT_TRUE(result.isFailed());
+}
+
+TEST_F(PowerHalWrapperAidlTest, TestGetHintSessionPreferredRate) {
+    EXPECT_CALL(*mMockHal.get(), getHintSessionPreferredRate(_)).Times(Exactly(1));
+    auto result = mWrapper->getHintSessionPreferredRate();
+    ASSERT_TRUE(result.isOk());
+    int64_t rate = result.value();
+    ASSERT_GE(0, rate);
+}
diff --git a/services/powermanager/tests/PowerHalWrapperHidlV1_0Test.cpp b/services/powermanager/tests/PowerHalWrapperHidlV1_0Test.cpp
index 6693d0b..b54762c 100644
--- a/services/powermanager/tests/PowerHalWrapperHidlV1_0Test.cpp
+++ b/services/powermanager/tests/PowerHalWrapperHidlV1_0Test.cpp
@@ -72,7 +72,7 @@
     EXPECT_CALL(*mMockHal.get(), powerHint(Eq(PowerHint::INTERACTION), Eq(1000))).Times(Exactly(1));
 
     auto result = mWrapper->setBoost(Boost::INTERACTION, 1000);
-    ASSERT_EQ(HalResult::SUCCESSFUL, result);
+    ASSERT_TRUE(result.isOk());
 }
 
 TEST_F(PowerHalWrapperHidlV1_0Test, TestSetBoostFailed) {
@@ -83,12 +83,12 @@
             });
 
     auto result = mWrapper->setBoost(Boost::INTERACTION, 1000);
-    ASSERT_EQ(HalResult::FAILED, result);
+    ASSERT_TRUE(result.isFailed());
 }
 
 TEST_F(PowerHalWrapperHidlV1_0Test, TestSetBoostUnsupported) {
     auto result = mWrapper->setBoost(Boost::CAMERA_LAUNCH, 10);
-    ASSERT_EQ(HalResult::UNSUPPORTED, result);
+    ASSERT_TRUE(result.isUnsupported());
 }
 
 TEST_F(PowerHalWrapperHidlV1_0Test, TestSetModeSuccessful) {
@@ -106,17 +106,17 @@
     }
 
     auto result = mWrapper->setMode(Mode::LAUNCH, true);
-    ASSERT_EQ(HalResult::SUCCESSFUL, result);
+    ASSERT_TRUE(result.isOk());
     result = mWrapper->setMode(Mode::LOW_POWER, false);
-    ASSERT_EQ(HalResult::SUCCESSFUL, result);
+    ASSERT_TRUE(result.isOk());
     result = mWrapper->setMode(Mode::SUSTAINED_PERFORMANCE, true);
-    ASSERT_EQ(HalResult::SUCCESSFUL, result);
+    ASSERT_TRUE(result.isOk());
     result = mWrapper->setMode(Mode::VR, false);
-    ASSERT_EQ(HalResult::SUCCESSFUL, result);
+    ASSERT_TRUE(result.isOk());
     result = mWrapper->setMode(Mode::INTERACTIVE, true);
-    ASSERT_EQ(HalResult::SUCCESSFUL, result);
+    ASSERT_TRUE(result.isOk());
     result = mWrapper->setMode(Mode::DOUBLE_TAP_TO_WAKE, false);
-    ASSERT_EQ(HalResult::SUCCESSFUL, result);
+    ASSERT_TRUE(result.isOk());
 }
 
 TEST_F(PowerHalWrapperHidlV1_0Test, TestSetModeFailed) {
@@ -127,10 +127,10 @@
             });
 
     auto result = mWrapper->setMode(Mode::LAUNCH, 1);
-    ASSERT_EQ(HalResult::FAILED, result);
+    ASSERT_TRUE(result.isFailed());
 }
 
 TEST_F(PowerHalWrapperHidlV1_0Test, TestSetModeIgnored) {
     auto result = mWrapper->setMode(Mode::CAMERA_STREAMING_HIGH, true);
-    ASSERT_EQ(HalResult::UNSUPPORTED, result);
+    ASSERT_TRUE(result.isUnsupported());
 }
diff --git a/services/powermanager/tests/PowerHalWrapperHidlV1_1Test.cpp b/services/powermanager/tests/PowerHalWrapperHidlV1_1Test.cpp
index 55bbd6d..d30e8d2 100644
--- a/services/powermanager/tests/PowerHalWrapperHidlV1_1Test.cpp
+++ b/services/powermanager/tests/PowerHalWrapperHidlV1_1Test.cpp
@@ -89,7 +89,7 @@
             .Times(Exactly(1));
 
     auto result = mWrapper->setBoost(Boost::INTERACTION, 1000);
-    ASSERT_EQ(HalResult::SUCCESSFUL, result);
+    ASSERT_TRUE(result.isOk());
 }
 
 TEST_F(PowerHalWrapperHidlV1_1Test, TestSetBoostFailed) {
@@ -100,12 +100,12 @@
             });
 
     auto result = mWrapper->setBoost(Boost::INTERACTION, 1000);
-    ASSERT_EQ(HalResult::FAILED, result);
+    ASSERT_TRUE(result.isFailed());
 }
 
 TEST_F(PowerHalWrapperHidlV1_1Test, TestSetBoostUnsupported) {
     auto result = mWrapper->setBoost(Boost::CAMERA_LAUNCH, 10);
-    ASSERT_EQ(HalResult::UNSUPPORTED, result);
+    ASSERT_TRUE(result.isUnsupported());
 }
 
 TEST_F(PowerHalWrapperHidlV1_1Test, TestSetMode) {
@@ -127,17 +127,17 @@
     }
 
     auto result = mWrapper->setMode(Mode::LAUNCH, true);
-    ASSERT_EQ(HalResult::SUCCESSFUL, result);
+    ASSERT_TRUE(result.isOk());
     result = mWrapper->setMode(Mode::LOW_POWER, false);
-    ASSERT_EQ(HalResult::SUCCESSFUL, result);
+    ASSERT_TRUE(result.isOk());
     result = mWrapper->setMode(Mode::SUSTAINED_PERFORMANCE, true);
-    ASSERT_EQ(HalResult::SUCCESSFUL, result);
+    ASSERT_TRUE(result.isOk());
     result = mWrapper->setMode(Mode::VR, false);
-    ASSERT_EQ(HalResult::SUCCESSFUL, result);
+    ASSERT_TRUE(result.isOk());
     result = mWrapper->setMode(Mode::INTERACTIVE, true);
-    ASSERT_EQ(HalResult::SUCCESSFUL, result);
+    ASSERT_TRUE(result.isOk());
     result = mWrapper->setMode(Mode::DOUBLE_TAP_TO_WAKE, false);
-    ASSERT_EQ(HalResult::SUCCESSFUL, result);
+    ASSERT_TRUE(result.isOk());
 }
 
 TEST_F(PowerHalWrapperHidlV1_1Test, TestSetModeFailed) {
@@ -148,10 +148,10 @@
             });
 
     auto result = mWrapper->setMode(Mode::LAUNCH, 1);
-    ASSERT_EQ(HalResult::FAILED, result);
+    ASSERT_TRUE(result.isFailed());
 }
 
 TEST_F(PowerHalWrapperHidlV1_1Test, TestSetModeIgnored) {
     auto result = mWrapper->setMode(Mode::CAMERA_STREAMING_HIGH, true);
-    ASSERT_EQ(HalResult::UNSUPPORTED, result);
+    ASSERT_TRUE(result.isUnsupported());
 }
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index b976eb5..9885352 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -60,7 +60,6 @@
         "libnativewindow",
         "libprocessgroup",
         "libprotobuf-cpp-lite",
-        "libstatslog",
         "libsync",
         "libtimestats",
         "libui",
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index 48a0be2..ed826a0 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -278,9 +278,8 @@
     return stateUpdateAvailable;
 }
 
-// Crop that applies to the window
-Rect BufferStateLayer::getCrop(const Layer::State& /*s*/) const {
-    return Rect::INVALID_RECT;
+Rect BufferStateLayer::getCrop(const Layer::State& s) const {
+    return s.crop;
 }
 
 bool BufferStateLayer::setTransform(uint32_t transform) {
@@ -301,57 +300,53 @@
 }
 
 bool BufferStateLayer::setCrop(const Rect& crop) {
-    Rect c = crop;
-    if (c.left < 0) {
-        c.left = 0;
-    }
-    if (c.top < 0) {
-        c.top = 0;
-    }
-    // If the width and/or height are < 0, make it [0, 0, -1, -1] so the equality comparision below
-    // treats all invalid rectangles the same.
-    if (!c.isValid()) {
-        c.makeInvalid();
-    }
+    if (mCurrentState.crop == crop) return false;
+    mCurrentState.sequence++;
+    mCurrentState.crop = crop;
 
-    if (mCurrentState.crop == c) return false;
-    mCurrentState.crop = c;
     mCurrentState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
 
-bool BufferStateLayer::setFrame(const Rect& frame) {
-    int x = frame.left;
-    int y = frame.top;
-    int w = frame.getWidth();
-    int h = frame.getHeight();
-
-    if (x < 0) {
-        x = 0;
-        w = frame.right;
-    }
-
-    if (y < 0) {
-        y = 0;
-        h = frame.bottom;
-    }
-
-    if (mCurrentState.transform.tx() == x && mCurrentState.transform.ty() == y &&
-        mCurrentState.width == w && mCurrentState.height == h) {
+bool BufferStateLayer::setMatrix(const layer_state_t::matrix22_t& matrix,
+                                 bool allowNonRectPreservingTransforms) {
+    if (mCurrentState.transform.dsdx() == matrix.dsdx &&
+        mCurrentState.transform.dtdy() == matrix.dtdy &&
+        mCurrentState.transform.dtdx() == matrix.dtdx &&
+        mCurrentState.transform.dsdy() == matrix.dsdy) {
         return false;
     }
 
-    if (!frame.isValid()) {
-        x = y = w = h = 0;
+    ui::Transform t;
+    t.set(matrix.dsdx, matrix.dtdy, matrix.dtdx, matrix.dsdy);
+
+    if (!allowNonRectPreservingTransforms && !t.preserveRects()) {
+        ALOGW("Attempt to set rotation matrix without permission ACCESS_SURFACE_FLINGER nor "
+              "ROTATE_SURFACE_FLINGER ignored");
+        return false;
     }
-    mCurrentState.transform.set(x, y);
-    mCurrentState.width = w;
-    mCurrentState.height = h;
+
+    mCurrentState.transform.set(matrix.dsdx, matrix.dtdy, matrix.dtdx, matrix.dsdy);
 
     mCurrentState.sequence++;
     mCurrentState.modified = true;
     setTransactionFlags(eTransactionNeeded);
+
+    return true;
+}
+
+bool BufferStateLayer::setPosition(float x, float y) {
+    if (mCurrentState.transform.tx() == x && mCurrentState.transform.ty() == y) {
+        return false;
+    }
+
+    mCurrentState.transform.set(x, y);
+
+    mCurrentState.sequence++;
+    mCurrentState.modified = true;
+    setTransactionFlags(eTransactionNeeded);
+
     return true;
 }
 
@@ -428,6 +423,10 @@
         mFlinger->mFrameTracer->traceTimestamp(layerId, bufferId, frameNumber, postTime,
                                                FrameTracer::FrameEvent::QUEUE);
     }
+
+    mCurrentState.width = mCurrentState.buffer->width;
+    mCurrentState.height = mCurrentState.buffer->height;
+
     return true;
 }
 
@@ -858,33 +857,6 @@
     return layer;
 }
 
-Layer::RoundedCornerState BufferStateLayer::getRoundedCornerState() const {
-    const auto& p = mDrawingParent.promote();
-    if (p != nullptr) {
-        RoundedCornerState parentState = p->getRoundedCornerState();
-        if (parentState.radius > 0) {
-            ui::Transform t = getActiveTransform(getDrawingState());
-            t = t.inverse();
-            parentState.cropRect = t.transform(parentState.cropRect);
-            // The rounded corners shader only accepts 1 corner radius for performance reasons,
-            // but a transform matrix can define horizontal and vertical scales.
-            // Let's take the average between both of them and pass into the shader, practically we
-            // never do this type of transformation on windows anyway.
-            parentState.radius *= (t[0][0] + t[1][1]) / 2.0f;
-            return parentState;
-        }
-    }
-    const float radius = getDrawingState().cornerRadius;
-    const State& s(getDrawingState());
-    if (radius <= 0 || (getActiveWidth(s) == UINT32_MAX && getActiveHeight(s) == UINT32_MAX))
-        return RoundedCornerState();
-    return RoundedCornerState(FloatRect(static_cast<float>(s.transform.tx()),
-                                        static_cast<float>(s.transform.ty()),
-                                        static_cast<float>(s.transform.tx() + s.width),
-                                        static_cast<float>(s.transform.ty() + s.height)),
-                              radius);
-}
-
 bool BufferStateLayer::bufferNeedsFiltering() const {
     const State& s(getDrawingState());
     if (!s.buffer) {
diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h
index 3878f50..8ce3e1f 100644
--- a/services/surfaceflinger/BufferStateLayer.h
+++ b/services/surfaceflinger/BufferStateLayer.h
@@ -66,7 +66,6 @@
     bool setTransform(uint32_t transform) override;
     bool setTransformToDisplayInverse(bool transformToDisplayInverse) override;
     bool setCrop(const Rect& crop) override;
-    bool setFrame(const Rect& frame) override;
     bool setBuffer(const sp<GraphicBuffer>& buffer, const sp<Fence>& acquireFence, nsecs_t postTime,
                    nsecs_t desiredPresentTime, bool isAutoTimestamp,
                    const client_cache_t& clientCacheId, uint64_t frameNumber,
@@ -81,15 +80,13 @@
     bool setTransactionCompletedListeners(const std::vector<sp<CallbackHandle>>& handles) override;
     bool addFrameEvent(const sp<Fence>& acquireFence, nsecs_t postedTime,
                        nsecs_t requestedPresentTime) override;
+    bool setPosition(float /*x*/, float /*y*/) override;
+    bool setMatrix(const layer_state_t::matrix22_t& /*matrix*/,
+                   bool /*allowNonRectPreservingTransforms*/);
 
     // Override to ignore legacy layer state properties that are not used by BufferStateLayer
     bool setSize(uint32_t /*w*/, uint32_t /*h*/) override { return false; }
-    bool setPosition(float /*x*/, float /*y*/) override { return false; }
     bool setTransparentRegionHint(const Region& transparent) override;
-    bool setMatrix(const layer_state_t::matrix22_t& /*matrix*/,
-                   bool /*allowNonRectPreservingTransforms*/) override {
-        return false;
-    }
     void deferTransactionUntil_legacy(const sp<IBinder>& /*barrierHandle*/,
                                       uint64_t /*frameNumber*/) override {}
     void deferTransactionUntil_legacy(const sp<Layer>& /*barrierLayer*/,
@@ -97,7 +94,6 @@
 
     Rect getBufferSize(const State& s) const override;
     FloatRect computeSourceBounds(const FloatRect& parentBounds) const override;
-    Layer::RoundedCornerState getRoundedCornerState() const override;
     void setAutoRefresh(bool autoRefresh) override;
 
     // -----------------------------------------------------------------------
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h
index 4c065ec..48a54d6 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h
@@ -115,6 +115,9 @@
         // The buffer cache for this layer. This is used to lower the
         // cost of sending reused buffers to the HWC.
         HwcBufferCache hwcBufferCache;
+
+        // Set to true when overridden info has been sent to HW composer
+        bool stateOverridden = false;
     };
 
     // The HWC state is optional, and is only set up if there is any potential
diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp
index aed3be9..3ac5433 100644
--- a/services/surfaceflinger/CompositionEngine/src/Output.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp
@@ -722,10 +722,7 @@
             previousOverride = layer->getState().overrideInfo.buffer;
         }
 
-        // TODO(b/181172795): We now update geometry for all flattened layers. We should update it
-        // only when the geometry actually changes
-        const bool includeGeometry = refreshArgs.updatingGeometryThisFrame ||
-                layer->getState().overrideInfo.buffer != nullptr || skipLayer;
+        const bool includeGeometry = refreshArgs.updatingGeometryThisFrame;
         layer->writeStateToHWC(includeGeometry, skipLayer);
     }
 }
@@ -1104,6 +1101,7 @@
     Region stubRegion;
 
     bool disableBlurs = false;
+    sp<GraphicBuffer> previousOverrideBuffer = nullptr;
 
     for (auto* layer : getOutputLayersOrderedByZ()) {
         const auto& layerState = layer->getState();
@@ -1153,8 +1151,14 @@
 
             std::vector<LayerFE::LayerSettings> results;
             if (layer->getState().overrideInfo.buffer != nullptr) {
-                results = layer->getOverrideCompositionList();
-                ALOGV("Replacing [%s] with override in RE", layer->getLayerFE().getDebugName());
+                if (layer->getState().overrideInfo.buffer != previousOverrideBuffer) {
+                    results = layer->getOverrideCompositionList();
+                    previousOverrideBuffer = layer->getState().overrideInfo.buffer;
+                    ALOGV("Replacing [%s] with override in RE", layer->getLayerFE().getDebugName());
+                } else {
+                    ALOGV("Skipping redundant override buffer for [%s] in RE",
+                          layer->getLayerFE().getDebugName());
+                }
             } else {
                 results = layerFE.prepareClientCompositionList(targetSettings);
                 if (realContentIsVisible && !results.empty()) {
diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
index 3f36a8f..f640f85 100644
--- a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
@@ -333,7 +333,11 @@
 
     auto requestedCompositionType = outputIndependentState->compositionType;
 
-    if (includeGeometry) {
+    // TODO(b/181172795): We now update geometry for all flattened layers. We should update it
+    // only when the geometry actually changes
+    const bool isOverridden = state.overrideInfo.buffer != nullptr;
+    const bool prevOverridden = state.hwc->stateOverridden;
+    if (isOverridden || prevOverridden || skipLayer || includeGeometry) {
         writeOutputDependentGeometryStateToHWC(hwcLayer.get(), requestedCompositionType);
         writeOutputIndependentGeometryStateToHWC(hwcLayer.get(), *outputIndependentState,
                                                  skipLayer);
@@ -346,6 +350,8 @@
 
     // Always set the layer color after setting the composition type.
     writeSolidColorStateToHWC(hwcLayer.get(), *outputIndependentState);
+
+    editState().hwc->stateOverridden = isOverridden;
 }
 
 void OutputLayer::writeOutputDependentGeometryStateToHWC(
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
index 1bf43da..fd70988 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
@@ -20,11 +20,7 @@
 
 #undef LOG_TAG
 #define LOG_TAG "HwcComposer"
-
-#include <log/log.h>
-
-#include <algorithm>
-#include <cinttypes>
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
 
 #include "ComposerHal.h"
 
@@ -32,6 +28,11 @@
 #include <gui/BufferQueue.h>
 #include <hidl/HidlTransportSupport.h>
 #include <hidl/HidlTransportUtils.h>
+#include <log/log.h>
+#include <utils/Trace.h>
+
+#include <algorithm>
+#include <cinttypes>
 
 namespace android {
 
@@ -492,6 +493,7 @@
 
 Error Composer::presentDisplay(Display display, int* outPresentFence)
 {
+    ATRACE_NAME("HwcPresentDisplay");
     mWriter.selectDisplay(display);
     mWriter.presentDisplay();
 
@@ -586,6 +588,7 @@
 Error Composer::validateDisplay(Display display, uint32_t* outNumTypes,
         uint32_t* outNumRequests)
 {
+    ATRACE_NAME("HwcValidateDisplay");
     mWriter.selectDisplay(display);
     mWriter.validateDisplay();
 
@@ -601,13 +604,14 @@
 
 Error Composer::presentOrValidateDisplay(Display display, uint32_t* outNumTypes,
                                uint32_t* outNumRequests, int* outPresentFence, uint32_t* state) {
-   mWriter.selectDisplay(display);
-   mWriter.presentOrvalidateDisplay();
+    ATRACE_NAME("HwcPresentOrValidateDisplay");
+    mWriter.selectDisplay(display);
+    mWriter.presentOrvalidateDisplay();
 
-   Error error = execute();
-   if (error != Error::NONE) {
-       return error;
-   }
+    Error error = execute();
+    if (error != Error::NONE) {
+        return error;
+    }
 
    mReader.takePresentOrValidateStage(display, state);
 
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 94fd62f..6038658 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -2287,8 +2287,8 @@
         }
     }
     const float radius = getDrawingState().cornerRadius;
-    return radius > 0 && getCrop(getDrawingState()).isValid()
-            ? RoundedCornerState(getCrop(getDrawingState()).toFloatRect(), radius)
+    return radius > 0 && getCroppedBufferSize(getDrawingState()).isValid()
+            ? RoundedCornerState(getCroppedBufferSize(getDrawingState()).toFloatRect(), radius)
             : RoundedCornerState();
 }
 
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 3a45c94..5528a81 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -412,7 +412,6 @@
     // Used only to set BufferStateLayer state
     virtual bool setTransform(uint32_t /*transform*/) { return false; };
     virtual bool setTransformToDisplayInverse(bool /*transformToDisplayInverse*/) { return false; };
-    virtual bool setFrame(const Rect& /*frame*/) { return false; };
     virtual bool setBuffer(const sp<GraphicBuffer>& /*buffer*/, const sp<Fence>& /*acquireFence*/,
                            nsecs_t /*postTime*/, nsecs_t /*desiredPresentTime*/,
                            bool /*isAutoTimestamp*/, const client_cache_t& /*clientCacheId*/,
diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp
index 1d00cc3..7a3e433 100644
--- a/services/surfaceflinger/RefreshRateOverlay.cpp
+++ b/services/surfaceflinger/RefreshRateOverlay.cpp
@@ -231,8 +231,14 @@
 void RefreshRateOverlay::setViewport(ui::Size viewport) {
     Rect frame((3 * viewport.width) >> 4, viewport.height >> 5);
     frame.offsetBy(viewport.width >> 5, viewport.height >> 4);
-    mLayer->setFrame(frame);
 
+    layer_state_t::matrix22_t matrix;
+    matrix.dsdx = frame.getWidth() / static_cast<float>(SevenSegmentDrawer::getWidth());
+    matrix.dtdx = 0;
+    matrix.dtdy = 0;
+    matrix.dsdy = frame.getHeight() / static_cast<float>(SevenSegmentDrawer::getHeight());
+    mLayer->setMatrix(matrix, true);
+    mLayer->setPosition(frame.left, frame.top);
     mFlinger.mTransactionFlags.fetch_or(eTransactionMask);
 }
 
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 825834b..02579c6 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1814,10 +1814,6 @@
     if (frameMissed) {
         mFrameMissedCount++;
         mTimeStats->incrementMissedFrames();
-        if (mMissedFrameJankCount == 0) {
-            mMissedFrameJankStart = systemTime();
-        }
-        mMissedFrameJankCount++;
     }
 
     if (hwcFrameMissed) {
@@ -1849,37 +1845,6 @@
         }
     }
 
-    // Our jank window is always at least 100ms since we missed a
-    // frame...
-    static constexpr nsecs_t kMinJankyDuration =
-            std::chrono::duration_cast<std::chrono::nanoseconds>(100ms).count();
-    // ...but if it's larger than 1s then we missed the trace cutoff.
-    static constexpr nsecs_t kMaxJankyDuration =
-            std::chrono::duration_cast<std::chrono::nanoseconds>(1s).count();
-    nsecs_t jankDurationToUpload = -1;
-    // If we're in a user build then don't push any atoms
-    if (!mIsUserBuild && mMissedFrameJankCount > 0) {
-        const auto display = ON_MAIN_THREAD(getDefaultDisplayDeviceLocked());
-        // Only report jank when the display is on, as displays in DOZE
-        // power mode may operate at a different frame rate than is
-        // reported in their config, which causes noticeable (but less
-        // severe) jank.
-        if (display && display->getPowerMode() == hal::PowerMode::ON) {
-            const nsecs_t currentTime = systemTime();
-            const nsecs_t jankDuration = currentTime - mMissedFrameJankStart;
-            if (jankDuration > kMinJankyDuration && jankDuration < kMaxJankyDuration) {
-                jankDurationToUpload = jankDuration;
-            }
-
-            // We either reported a jank event or we missed the trace
-            // window, so clear counters here.
-            if (jankDuration > kMinJankyDuration) {
-                mMissedFrameJankCount = 0;
-                mMissedFrameJankStart = 0;
-            }
-        }
-    }
-
     if (mTracingEnabledChanged) {
         mTracingEnabled = mTracing.isEnabled();
         mTracingEnabledChanged = false;
@@ -1926,7 +1891,6 @@
 
     refreshNeeded |= mRepaintEverything;
     if (refreshNeeded && CC_LIKELY(mBootStage != BootStage::BOOTLOADER)) {
-        mLastJankDuration = jankDurationToUpload;
         // Signal a refresh if a transaction modified the window state,
         // a new buffer was latched, or if HWC has requested a full
         // repaint
@@ -2302,14 +2266,6 @@
     const size_t appConnections = mScheduler->getEventThreadConnectionCount(mAppConnectionHandle);
     mTimeStats->recordDisplayEventConnectionCount(sfConnections + appConnections);
 
-    if (mLastJankDuration > 0) {
-        ATRACE_NAME("Jank detected");
-        const int32_t jankyDurationMillis = mLastJankDuration / (1000 * 1000);
-        android::util::stats_write(android::util::DISPLAY_JANK_REPORTED, jankyDurationMillis,
-                                   mMissedFrameJankCount);
-        mLastJankDuration = -1;
-    }
-
     if (isDisplayConnected && !display->isPoweredOn()) {
         return;
     }
@@ -4033,9 +3989,6 @@
     if (what & layer_state_t::eCropChanged) {
         if (layer->setCrop(s.crop)) flags |= eTraversalNeeded;
     }
-    if (what & layer_state_t::eFrameChanged) {
-        if (layer->setFrame(s.orientedDisplaySpaceRect)) flags |= eTraversalNeeded;
-    }
     if (what & layer_state_t::eAcquireFenceChanged) {
         if (layer->setAcquireFence(s.acquireFence)) flags |= eTraversalNeeded;
     }
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index c7601fa..b3da61e 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -1387,13 +1387,6 @@
     // be any issues with a raw pointer referencing an invalid object.
     std::unordered_set<Layer*> mOffscreenLayers;
 
-    // Fields tracking the current jank event: when it started and how many
-    // janky frames there are.
-    nsecs_t mMissedFrameJankStart = 0;
-    int32_t mMissedFrameJankCount = 0;
-    // Positive if jank should be uploaded in postComposition
-    nsecs_t mLastJankDuration = -1;
-
     int mFrameRateFlexibilityTokenCount = 0;
 
     sp<IBinder> mDebugFrameRateFlexibilityToken;
diff --git a/services/surfaceflinger/tests/BufferGenerator.cpp b/services/surfaceflinger/tests/BufferGenerator.cpp
index 03f8e1a..47a150d 100644
--- a/services/surfaceflinger/tests/BufferGenerator.cpp
+++ b/services/surfaceflinger/tests/BufferGenerator.cpp
@@ -296,12 +296,12 @@
 
 BufferGenerator::BufferGenerator()
       : mSurfaceManager(new SurfaceManager), mEglManager(new EglManager), mProgram(new Program) {
-    const float width = 1000.0;
-    const float height = 1000.0;
+    mBufferSize.set(1000.0, 1000.0);
 
     auto setBufferWithContext =
             std::bind(setBuffer, std::placeholders::_1, std::placeholders::_2, this);
-    mSurfaceManager->initialize(width, height, HAL_PIXEL_FORMAT_RGBA_8888, setBufferWithContext);
+    mSurfaceManager->initialize(mBufferSize.width, mBufferSize.height, HAL_PIXEL_FORMAT_RGBA_8888,
+                                setBufferWithContext);
 
     if (!mEglManager->initialize(mSurfaceManager->getSurface())) return;
 
@@ -309,7 +309,9 @@
 
     if (!mProgram->initialize(VERTEX_SHADER, FRAGMENT_SHADER)) return;
     mProgram->use();
-    mProgram->bindVec4(0, vec4{width, height, 1.0f / width, 1.0f / height});
+    mProgram->bindVec4(0,
+                       vec4{mBufferSize.width, mBufferSize.height, 1.0f / mBufferSize.width,
+                            1.0f / mBufferSize.height});
     mProgram->bindVec3(2, &SPHERICAL_HARMONICS[0], 4);
 
     glEnableVertexAttribArray(0);
@@ -372,6 +374,10 @@
     return NO_ERROR;
 }
 
+ui::Size BufferGenerator::getSize() {
+    return mBufferSize;
+}
+
 // static
 void BufferGenerator::setBuffer(const sp<GraphicBuffer>& buffer, int32_t fence,
                                 void* bufferGenerator) {
diff --git a/services/surfaceflinger/tests/BufferGenerator.h b/services/surfaceflinger/tests/BufferGenerator.h
index a3ffe86..f7d548b 100644
--- a/services/surfaceflinger/tests/BufferGenerator.h
+++ b/services/surfaceflinger/tests/BufferGenerator.h
@@ -37,6 +37,7 @@
 
     /* Static callback that sets the fence on a particular instance */
     static void setBuffer(const sp<GraphicBuffer>& buffer, int32_t fence, void* fenceGenerator);
+    ui::Size getSize();
 
 private:
     bool mInitialized = false;
@@ -53,6 +54,7 @@
 
     using Epoch = std::chrono::time_point<std::chrono::steady_clock>;
     Epoch mEpoch = std::chrono::steady_clock::now();
+    ui::Size mBufferSize;
 };
 
 } // namespace android
diff --git a/services/surfaceflinger/tests/EffectLayer_test.cpp b/services/surfaceflinger/tests/EffectLayer_test.cpp
index f470eda..af00ec7 100644
--- a/services/surfaceflinger/tests/EffectLayer_test.cpp
+++ b/services/surfaceflinger/tests/EffectLayer_test.cpp
@@ -149,7 +149,6 @@
         t.reparent(blurLayer, mParentLayer);
         t.setBackgroundBlurRadius(blurLayer, blurRadius);
         t.setCrop(blurLayer, blurRect);
-        t.setFrame(blurLayer, blurRect);
         t.setAlpha(blurLayer, 0.0f);
         t.show(blurLayer);
     });
diff --git a/services/surfaceflinger/tests/IPC_test.cpp b/services/surfaceflinger/tests/IPC_test.cpp
index a8647c3..9fa3d4c 100644
--- a/services/surfaceflinger/tests/IPC_test.cpp
+++ b/services/surfaceflinger/tests/IPC_test.cpp
@@ -161,7 +161,6 @@
                                                  Color::RED);
         transaction->setLayerStack(mSurfaceControl, 0)
                 .setLayer(mSurfaceControl, std::numeric_limits<int32_t>::max())
-                .setFrame(mSurfaceControl, Rect(0, 0, width, height))
                 .setBuffer(mSurfaceControl, gb)
                 .setAcquireFence(mSurfaceControl, fence)
                 .show(mSurfaceControl)
diff --git a/services/surfaceflinger/tests/LayerCallback_test.cpp b/services/surfaceflinger/tests/LayerCallback_test.cpp
index 158801a..011ff70 100644
--- a/services/surfaceflinger/tests/LayerCallback_test.cpp
+++ b/services/surfaceflinger/tests/LayerCallback_test.cpp
@@ -164,7 +164,10 @@
         return;
     }
 
-    transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply();
+    ui::Size bufferSize = getBufferSize();
+    TransactionUtils::setFrame(transaction, layer, Rect(0, 0, bufferSize.width, bufferSize.height),
+                               Rect(0, 0, 32, 32));
+    transaction.apply();
 
     ExpectedResult expected;
     expected.addSurface(ExpectedResult::Transaction::NOT_PRESENTED, layer,
@@ -184,7 +187,10 @@
         return;
     }
 
-    transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply();
+    ui::Size bufferSize = getBufferSize();
+    TransactionUtils::setFrame(transaction, layer, Rect(0, 0, bufferSize.width, bufferSize.height),
+                               Rect(0, 0, 32, 32));
+    transaction.apply();
 
     ExpectedResult expected;
     expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer);
@@ -203,7 +209,10 @@
         return;
     }
 
-    transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply();
+    ui::Size bufferSize = getBufferSize();
+    TransactionUtils::setFrame(transaction, layer, Rect(0, 0, bufferSize.width, bufferSize.height),
+                               Rect(0, 0, 32, 32));
+    transaction.apply();
 
     ExpectedResult expected;
     expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer,
@@ -238,7 +247,10 @@
         return;
     }
 
-    transaction.setFrame(layer, Rect(-100, -100, 100, 100)).apply();
+    ui::Size bufferSize = getBufferSize();
+    TransactionUtils::setFrame(transaction, layer, Rect(0, 0, bufferSize.width, bufferSize.height),
+                               Rect(-100, -100, 100, 100));
+    transaction.apply();
 
     ExpectedResult expected;
     expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer);
@@ -263,8 +275,15 @@
         return;
     }
 
-    transaction1.setFrame(layer1, Rect(0, 0, 32, 32));
-    transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply();
+    ui::Size bufferSize = getBufferSize();
+
+    TransactionUtils::setFrame(transaction1, layer1,
+                               Rect(0, 0, bufferSize.width, bufferSize.height), Rect(0, 0, 32, 32));
+    TransactionUtils::setFrame(transaction2, layer2,
+                               Rect(0, 0, bufferSize.width, bufferSize.height),
+                               Rect(32, 32, 64, 64));
+
+    transaction2.merge(std::move(transaction1)).apply();
 
     ExpectedResult expected;
     expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2});
@@ -290,8 +309,15 @@
         return;
     }
 
-    transaction1.setFrame(layer1, Rect(0, 0, 32, 32));
-    transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply();
+    ui::Size bufferSize = getBufferSize();
+
+    TransactionUtils::setFrame(transaction1, layer1,
+                               Rect(0, 0, bufferSize.width, bufferSize.height), Rect(0, 0, 32, 32));
+    TransactionUtils::setFrame(transaction2, layer2,
+                               Rect(0, 0, bufferSize.width, bufferSize.height),
+                               Rect(32, 32, 64, 64));
+
+    transaction2.merge(std::move(transaction1)).apply();
 
     ExpectedResult expected;
     expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2},
@@ -318,8 +344,15 @@
         return;
     }
 
-    transaction1.setFrame(layer1, Rect(0, 0, 32, 32));
-    transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply();
+    ui::Size bufferSize = getBufferSize();
+
+    TransactionUtils::setFrame(transaction1, layer1,
+                               Rect(0, 0, bufferSize.width, bufferSize.height), Rect(0, 0, 32, 32));
+    TransactionUtils::setFrame(transaction2, layer2,
+                               Rect(0, 0, bufferSize.width, bufferSize.height),
+                               Rect(32, 32, 64, 64));
+
+    transaction2.merge(std::move(transaction1)).apply();
 
     ExpectedResult expected;
     expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer1);
@@ -405,8 +438,15 @@
         return;
     }
 
-    transaction1.setFrame(layer1, Rect(0, 0, 32, 32));
-    transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply();
+    ui::Size bufferSize = getBufferSize();
+
+    TransactionUtils::setFrame(transaction1, layer1,
+                               Rect(0, 0, bufferSize.width, bufferSize.height), Rect(0, 0, 32, 32));
+    TransactionUtils::setFrame(transaction2, layer2,
+                               Rect(0, 0, bufferSize.width, bufferSize.height),
+                               Rect(32, 32, 64, 64));
+
+    transaction2.merge(std::move(transaction1)).apply();
 
     ExpectedResult expected;
     expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2});
@@ -491,7 +531,11 @@
             }
         }
 
-        transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply();
+        ui::Size bufferSize = getBufferSize();
+        TransactionUtils::setFrame(transaction, layer,
+                                   Rect(0, 0, bufferSize.width, bufferSize.height),
+                                   Rect(0, 0, 32, 32));
+        transaction.apply();
 
         ExpectedResult expected;
         expected.addSurface((i == 0) ? ExpectedResult::Transaction::PRESENTED
@@ -523,8 +567,16 @@
             return;
         }
 
-        transaction1.setFrame(layer1, Rect(0, 0, 32, 32));
-        transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply();
+        ui::Size bufferSize = getBufferSize();
+
+        TransactionUtils::setFrame(transaction1, layer1,
+                                   Rect(0, 0, bufferSize.width, bufferSize.height),
+                                   Rect(0, 0, 32, 32));
+        TransactionUtils::setFrame(transaction2, layer2,
+                                   Rect(0, 0, bufferSize.width, bufferSize.height),
+                                   Rect(32, 32, 64, 64));
+
+        transaction2.merge(std::move(transaction1)).apply();
 
         ExpectedResult expected;
         expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2},
@@ -564,8 +616,16 @@
             return;
         }
 
-        transaction1.setFrame(layer1, Rect(0, 0, 32, 32));
-        transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply();
+        ui::Size bufferSize = getBufferSize();
+
+        TransactionUtils::setFrame(transaction1, layer1,
+                                   Rect(0, 0, bufferSize.width, bufferSize.height),
+                                   Rect(0, 0, 32, 32));
+        TransactionUtils::setFrame(transaction2, layer2,
+                                   Rect(0, 0, bufferSize.width, bufferSize.height),
+                                   Rect(32, 32, 64, 64));
+
+        transaction2.merge(std::move(transaction1)).apply();
 
         ExpectedResult expected;
         expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2},
@@ -606,8 +666,15 @@
         return;
     }
 
-    transaction1.setFrame(layer1, Rect(0, 0, 32, 32));
-    transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply();
+    ui::Size bufferSize = getBufferSize();
+
+    TransactionUtils::setFrame(transaction1, layer1,
+                               Rect(0, 0, bufferSize.width, bufferSize.height), Rect(0, 0, 32, 32));
+    TransactionUtils::setFrame(transaction2, layer2,
+                               Rect(0, 0, bufferSize.width, bufferSize.height),
+                               Rect(32, 32, 64, 64));
+
+    transaction2.merge(std::move(transaction1)).apply();
 
     ExpectedResult expected;
     expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2});
@@ -661,8 +728,15 @@
         return;
     }
 
-    transaction1.setFrame(layer1, Rect(0, 0, 32, 32));
-    transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply();
+    ui::Size bufferSize = getBufferSize();
+
+    TransactionUtils::setFrame(transaction1, layer1,
+                               Rect(0, 0, bufferSize.width, bufferSize.height), Rect(0, 0, 32, 32));
+    TransactionUtils::setFrame(transaction2, layer2,
+                               Rect(0, 0, bufferSize.width, bufferSize.height),
+                               Rect(32, 32, 64, 64));
+
+    transaction2.merge(std::move(transaction1)).apply();
 
     ExpectedResult expected;
     expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2});
@@ -682,7 +756,10 @@
         return;
     }
 
-    transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply();
+    TransactionUtils::setFrame(transaction2, layer2,
+                               Rect(0, 0, bufferSize.width, bufferSize.height),
+                               Rect(32, 32, 64, 64));
+    transaction2.merge(std::move(transaction1)).apply();
 
     expected.addSurface(ExpectedResult::Transaction::NOT_PRESENTED, layer2,
                         ExpectedResult::Buffer::NOT_ACQUIRED);
@@ -762,7 +839,10 @@
         return;
     }
 
-    transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply();
+    ui::Size bufferSize = getBufferSize();
+    TransactionUtils::setFrame(transaction, layer, Rect(0, 0, bufferSize.width, bufferSize.height),
+                               Rect(0, 0, 32, 32));
+    transaction.apply();
 
     ExpectedResult expectedResult;
     expectedResult.addSurface(ExpectedResult::Transaction::PRESENTED, layer);
@@ -781,7 +861,10 @@
             return;
         }
 
-        transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply();
+        TransactionUtils::setFrame(transaction, layer,
+                                   Rect(0, 0, bufferSize.width, bufferSize.height),
+                                   Rect(0, 0, 32, 32));
+        transaction.apply();
     }
     EXPECT_NO_FATAL_FAILURE(waitForCallbacks(callback, expectedResults, true));
 }
diff --git a/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp b/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp
index 7505e6e..53d230a 100644
--- a/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp
+++ b/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp
@@ -204,11 +204,7 @@
             Transaction().setPosition(layerG, 16, 16).setRelativeLayer(layerG, layerR, 1).apply();
             break;
         case ISurfaceComposerClient::eFXSurfaceBufferState:
-            Transaction()
-                    .setFrame(layerR, Rect(0, 0, 32, 32))
-                    .setFrame(layerG, Rect(16, 16, 48, 48))
-                    .setRelativeLayer(layerG, layerR, 1)
-                    .apply();
+            Transaction().setPosition(layerG, 16, 16).setRelativeLayer(layerG, layerR, 1).apply();
             break;
         default:
             ASSERT_FALSE(true) << "Unsupported layer type";
@@ -260,10 +256,9 @@
             break;
         case ISurfaceComposerClient::eFXSurfaceBufferState:
             Transaction()
-                    .setFrame(layerR, Rect(0, 0, 32, 32))
-                    .setFrame(layerG, Rect(8, 8, 40, 40))
+                    .setPosition(layerG, 8, 8)
                     .setRelativeLayer(layerG, layerR, 3)
-                    .setFrame(layerB, Rect(16, 16, 48, 48))
+                    .setPosition(layerB, 16, 16)
                     .setLayer(layerB, mLayerZBase + 2)
                     .apply();
             break;
@@ -388,7 +383,6 @@
     Transaction()
             .setTransparentRegionHint(layer, Region(top))
             .setBuffer(layer, buffer)
-            .setFrame(layer, Rect(0, 0, 32, 32))
             .apply();
     {
         SCOPED_TRACE("top transparent");
@@ -447,7 +441,7 @@
     // check that transparent region hint is bound by the layer size
     Transaction()
             .setTransparentRegionHint(layerTransparent, Region(mDisplayRect))
-            .setFrame(layerR, Rect(16, 16, 48, 48))
+            .setPosition(layerR, 16, 16)
             .setLayer(layerR, mLayerZBase + 1)
             .apply();
     ASSERT_NO_FATAL_FAILURE(
@@ -477,8 +471,7 @@
             Transaction()
                     .setAlpha(layer1, 0.25f)
                     .setAlpha(layer2, 0.75f)
-                    .setFrame(layer1, Rect(0, 0, 32, 32))
-                    .setFrame(layer2, Rect(16, 0, 48, 32))
+                    .setPosition(layer2, 16, 0)
                     .setLayer(layer2, mLayerZBase + 1)
                     .apply();
             break;
@@ -573,7 +566,7 @@
                 ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, fillColor, width, height));
                 expectedColor = fillColor;
             }
-            Transaction().setFrame(layer, Rect(0, 0, width, height)).apply();
+            Transaction().setCrop(layer, Rect(0, 0, width, height)).apply();
             break;
         default:
             GTEST_FAIL() << "Unknown layer type in setBackgroundColorHelper";
@@ -849,42 +842,39 @@
     ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN,
                                                          Color::BLUE, Color::WHITE));
 
-    Transaction()
-            .setMatrix(layer, 1.0f, 0.0f, 0.0f, 1.0f)
-            .setFrame(layer, Rect(0, 0, 32, 32))
-            .apply();
+    Transaction().setPosition(layer, 32, 32).setMatrix(layer, 1.0f, 0.0f, 0.0f, 1.0f).apply();
     {
         SCOPED_TRACE("IDENTITY");
-        getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::RED, Color::GREEN,
+        getScreenCapture()->expectQuadrant(Rect(32, 32, 64, 64), Color::RED, Color::GREEN,
                                            Color::BLUE, Color::WHITE);
     }
 
     Transaction().setMatrix(layer, -1.0f, 0.0f, 0.0f, 1.0f).apply();
     {
         SCOPED_TRACE("FLIP_H");
-        getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::RED, Color::GREEN,
-                                           Color::BLUE, Color::WHITE);
+        getScreenCapture()->expectQuadrant(Rect(0, 32, 32, 64), Color::GREEN, Color::RED,
+                                           Color::WHITE, Color::BLUE);
     }
 
     Transaction().setMatrix(layer, 1.0f, 0.0f, 0.0f, -1.0f).apply();
     {
         SCOPED_TRACE("FLIP_V");
-        getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::RED, Color::GREEN,
-                                           Color::BLUE, Color::WHITE);
+        getScreenCapture()->expectQuadrant(Rect(32, 0, 64, 32), Color::BLUE, Color::WHITE,
+                                           Color::RED, Color::GREEN);
     }
 
     Transaction().setMatrix(layer, 0.0f, 1.0f, -1.0f, 0.0f).apply();
     {
         SCOPED_TRACE("ROT_90");
-        getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::RED, Color::GREEN,
-                                           Color::BLUE, Color::WHITE);
+        getScreenCapture()->expectQuadrant(Rect(0, 32, 32, 64), Color::BLUE, Color::RED,
+                                           Color::WHITE, Color::GREEN);
     }
 
     Transaction().setMatrix(layer, 2.0f, 0.0f, 0.0f, 2.0f).apply();
     {
         SCOPED_TRACE("SCALE");
-        getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::RED, Color::GREEN,
-                                           Color::BLUE, Color::WHITE);
+        getScreenCapture()->expectQuadrant(Rect(32, 32, 96, 96), Color::RED, Color::GREEN,
+                                           Color::BLUE, Color::WHITE, 1 /* tolerance */);
     }
 }
 
@@ -955,8 +945,8 @@
 
     Transaction().setCrop(layer, crop).apply();
     auto shot = getScreenCapture();
-    shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED);
-    shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK);
+    shot->expectColor(crop, Color::RED);
+    shot->expectBorder(crop, Color::BLACK);
 }
 
 TEST_P(LayerRenderTypeTransactionTest, SetCropEmpty_BufferQueue) {
@@ -986,13 +976,13 @@
     {
         SCOPED_TRACE("empty rect");
         Transaction().setCrop(layer, Rect(8, 8, 8, 8)).apply();
-        getScreenCapture()->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED);
+        getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::RED);
     }
 
     {
         SCOPED_TRACE("negative rect");
         Transaction().setCrop(layer, Rect(8, 8, 0, 0)).apply();
-        getScreenCapture()->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED);
+        getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::RED);
     }
 }
 
@@ -1016,8 +1006,6 @@
     TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, 32, 16), Color::BLUE);
     TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 16, 32, 64), Color::RED);
 
-    Transaction().setFrame(layer, Rect(0, 0, 64, 64)).apply();
-
     Transaction().setBuffer(layer, buffer).apply();
 
     // Partially out of bounds in the negative (upper left) direction
@@ -1025,8 +1013,8 @@
     {
         SCOPED_TRACE("out of bounds, negative (upper left) direction");
         auto shot = getScreenCapture();
-        shot->expectColor(Rect(0, 0, 64, 64), Color::BLUE);
-        shot->expectBorder(Rect(0, 0, 64, 64), Color::BLACK);
+        shot->expectColor(Rect(0, 0, 32, 16), Color::BLUE);
+        shot->expectBorder(Rect(0, 0, 32, 16), Color::BLACK);
     }
 
     // Partially out of bounds in the positive (lower right) direction
@@ -1034,8 +1022,8 @@
     {
         SCOPED_TRACE("out of bounds, positive (lower right) direction");
         auto shot = getScreenCapture();
-        shot->expectColor(Rect(0, 0, 64, 64), Color::RED);
-        shot->expectBorder(Rect(0, 0, 64, 64), Color::BLACK);
+        shot->expectColor(Rect(0, 16, 32, 64), Color::RED);
+        shot->expectBorder(Rect(0, 16, 32, 64), Color::BLACK);
     }
 
     // Fully out of buffer space bounds
@@ -1043,9 +1031,7 @@
     {
         SCOPED_TRACE("Fully out of bounds");
         auto shot = getScreenCapture();
-        shot->expectColor(Rect(0, 0, 64, 16), Color::BLUE);
-        shot->expectColor(Rect(0, 16, 64, 64), Color::RED);
-        shot->expectBorder(Rect(0, 0, 64, 64), Color::BLACK);
+        shot->expectColor(Rect(0, 0, 64, 64), Color::BLACK);
     }
 }
 
@@ -1068,12 +1054,11 @@
             layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
     ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32));
 
-    const Rect frame(32, 32, 64, 64);
     const Rect crop(8, 8, 24, 24);
-    Transaction().setFrame(layer, frame).setCrop(layer, crop).apply();
+    Transaction().setPosition(layer, 32, 32).setCrop(layer, crop).apply();
     auto shot = getScreenCapture();
-    shot->expectColor(frame, Color::RED);
-    shot->expectBorder(frame, Color::BLACK);
+    shot->expectColor(Rect(40, 40, 56, 56), Color::RED);
+    shot->expectBorder(Rect(40, 40, 56, 56), Color::BLACK);
 }
 
 TEST_P(LayerRenderTypeTransactionTest, SetCropWithScale_BufferQueue) {
@@ -1121,7 +1106,10 @@
     ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32));
     const Rect frame(8, 8, 24, 24);
 
-    Transaction().setFrame(layer, frame).apply();
+    Transaction t;
+    TransactionUtils::setFrame(t, layer, Rect(0, 0, 32, 32), frame);
+    t.apply();
+
     auto shot = getScreenCapture();
     shot->expectColor(frame, Color::RED);
     shot->expectBorder(frame, Color::BLACK);
@@ -1133,16 +1121,23 @@
             layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
     ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32));
 
+    Transaction t;
     {
         SCOPED_TRACE("empty rect");
-        Transaction().setFrame(layer, Rect(8, 8, 8, 8)).apply();
+        TransactionUtils::setFrame(t, layer, Rect(0, 0, 32, 32), Rect(8, 8, 8, 8));
+        t.apply();
+
         getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::BLACK);
     }
 
     {
         SCOPED_TRACE("negative rect");
-        Transaction().setFrame(layer, Rect(8, 8, 0, 0)).apply();
-        getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::BLACK);
+        TransactionUtils::setFrame(t, layer, Rect(0, 0, 32, 32), Rect(8, 8, 0, 0));
+        t.apply();
+
+        auto shot = getScreenCapture();
+        shot->expectColor(Rect(0, 0, 8, 8), Color::RED);
+        shot->expectBorder(Rect(0, 0, 8, 8), Color::BLACK);
     }
 }
 
@@ -1152,10 +1147,10 @@
             layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
     ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 10, 10));
 
-    // A parentless layer will default to a frame with the same size as the buffer
+    // A layer with a buffer will have a computed size that matches the buffer size.
     auto shot = getScreenCapture();
-    shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED);
-    shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK);
+    shot->expectColor(Rect(0, 0, 10, 10), Color::RED);
+    shot->expectBorder(Rect(0, 0, 10, 10), Color::BLACK);
 }
 
 TEST_P(LayerRenderTypeTransactionTest, SetFrameDefaultBSParent_BufferState) {
@@ -1163,17 +1158,16 @@
     ASSERT_NO_FATAL_FAILURE(
             parent = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
     ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(parent, Color::RED, 32, 32));
-    Transaction().setFrame(parent, Rect(0, 0, 32, 32)).apply();
 
     ASSERT_NO_FATAL_FAILURE(
-            child = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+            child = createLayer("test", 10, 10, ISurfaceComposerClient::eFXSurfaceBufferState));
     ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(child, Color::BLUE, 10, 10));
 
     Transaction().reparent(child, parent).apply();
 
-    // A layer will default to the frame of its parent
+    // A layer with a buffer will have a computed size that matches the buffer size.
     auto shot = getScreenCapture();
-    shot->expectColor(Rect(0, 0, 32, 32), Color::BLUE);
+    shot->expectColor(Rect(0, 0, 10, 10), Color::BLUE);
     shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
 }
 
@@ -1183,14 +1177,14 @@
     ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(parent, Color::RED, 32, 32));
 
     ASSERT_NO_FATAL_FAILURE(
-            child = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+            child = createLayer("test", 10, 10, ISurfaceComposerClient::eFXSurfaceBufferState));
     ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(child, Color::BLUE, 10, 10));
 
     Transaction().reparent(child, parent).apply();
 
-    // A layer will default to the frame of its parent
+    // A layer with a buffer will have a computed size that matches the buffer size.
     auto shot = getScreenCapture();
-    shot->expectColor(Rect(0, 0, 32, 32), Color::BLUE);
+    shot->expectColor(Rect(0, 0, 10, 10), Color::BLUE);
     shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
 }
 
@@ -1199,11 +1193,10 @@
     ASSERT_NO_FATAL_FAILURE(
             layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
     ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32));
-    Transaction().setFrame(layer, Rect(0, 0, 32, 32)).apply();
 
     std::this_thread::sleep_for(500ms);
 
-    Transaction().setFrame(layer, Rect(16, 16, 48, 48)).apply();
+    Transaction().setPosition(layer, 16, 16).apply();
 
     auto shot = getScreenCapture();
     shot->expectColor(Rect(16, 16, 48, 48), Color::RED);
@@ -1215,18 +1208,20 @@
     ASSERT_NO_FATAL_FAILURE(
             parent = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
     ASSERT_NO_FATAL_FAILURE(
-            child = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+            child = createLayer("test", 10, 10, ISurfaceComposerClient::eFXSurfaceBufferState));
     Transaction().reparent(child, parent).apply();
 
     ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(parent, Color::RED, 32, 32));
-    Transaction().setFrame(parent, Rect(0, 0, 32, 32)).apply();
 
     ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(child, Color::BLUE, 10, 10));
-    Transaction().setFrame(child, Rect(0, 16, 32, 32)).apply();
+    Rect childDst(0, 16, 32, 32);
+    Transaction t;
+    TransactionUtils::setFrame(t, child, Rect(0, 0, 10, 10), childDst);
+    t.apply();
 
     auto shot = getScreenCapture();
     shot->expectColor(Rect(0, 0, 32, 16), Color::RED);
-    shot->expectColor(Rect(0, 16, 32, 32), Color::BLUE);
+    shot->expectColor(childDst, Color::BLUE);
     shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
 }
 
@@ -1238,8 +1233,8 @@
     ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32));
 
     auto shot = getScreenCapture();
-    shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED);
-    shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK);
+    shot->expectColor(Rect(0, 0, 32, 32), Color::RED);
+    shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
 }
 
 TEST_P(LayerRenderTypeTransactionTest, SetBufferMultipleBuffers_BufferState) {
@@ -1252,8 +1247,8 @@
     {
         SCOPED_TRACE("set buffer 1");
         auto shot = getScreenCapture();
-        shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED);
-        shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK);
+        shot->expectColor(Rect(0, 0, 32, 32), Color::RED);
+        shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
     }
 
     ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::BLUE, 32, 32));
@@ -1261,8 +1256,8 @@
     {
         SCOPED_TRACE("set buffer 2");
         auto shot = getScreenCapture();
-        shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLUE);
-        shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK);
+        shot->expectColor(Rect(0, 0, 32, 32), Color::BLUE);
+        shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
     }
 
     ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32));
@@ -1270,8 +1265,8 @@
     {
         SCOPED_TRACE("set buffer 3");
         auto shot = getScreenCapture();
-        shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED);
-        shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK);
+        shot->expectColor(Rect(0, 0, 32, 32), Color::RED);
+        shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
     }
 }
 
@@ -1286,7 +1281,6 @@
 
     ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer1, Color::RED, 64, 64));
 
-    Transaction().setFrame(layer1, Rect(0, 0, 64, 64)).apply();
     {
         SCOPED_TRACE("set layer 1 buffer red");
         auto shot = getScreenCapture();
@@ -1295,7 +1289,6 @@
 
     ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer2, Color::BLUE, 32, 32));
 
-    Transaction().setFrame(layer2, Rect(0, 0, 32, 32)).apply();
     {
         SCOPED_TRACE("set layer 2 buffer blue");
         auto shot = getScreenCapture();
@@ -1350,8 +1343,8 @@
 
             Color color = colors[idx % colors.size()];
             auto shot = screenshot();
-            shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), color);
-            shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK);
+            shot->expectColor(Rect(0, 0, 32, 32), color);
+            shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
         }
         idx++;
     }
@@ -1383,8 +1376,8 @@
 
             Color color = colors[idx % colors.size()];
             auto shot = screenshot();
-            shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), color);
-            shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK);
+            shot->expectColor(Rect(0, 0, 32, 32), color);
+            shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
         }
         idx++;
     }
@@ -1416,8 +1409,8 @@
 
             Color color = colors[idx % colors.size()];
             auto shot = screenshot();
-            shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), color);
-            shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK);
+            shot->expectColor(Rect(0, 0, 32, 32), color);
+            shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
         }
         if (idx == 0) {
             buffers[0].clear();
@@ -1435,7 +1428,6 @@
                                                          Color::BLUE, Color::WHITE));
 
     Transaction()
-            .setFrame(layer, Rect(0, 0, 32, 32))
             .setTransform(layer, NATIVE_WINDOW_TRANSFORM_ROT_90)
             .apply();
 
@@ -1452,7 +1444,6 @@
                                                          Color::BLUE, Color::WHITE));
 
     Transaction()
-            .setFrame(layer, Rect(0, 0, 32, 32))
             .setTransform(layer, NATIVE_WINDOW_TRANSFORM_FLIP_H)
             .apply();
 
@@ -1469,7 +1460,6 @@
                                                          Color::BLUE, Color::WHITE));
 
     Transaction()
-            .setFrame(layer, Rect(0, 0, 32, 32))
             .setTransform(layer, NATIVE_WINDOW_TRANSFORM_FLIP_V)
             .apply();
 
@@ -1518,8 +1508,8 @@
     Transaction().setBuffer(layer, buffer).setAcquireFence(layer, fence).apply();
 
     auto shot = getScreenCapture();
-    shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED);
-    shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK);
+    shot->expectColor(Rect(0, 0, 32, 32), Color::RED);
+    shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
 }
 
 TEST_P(LayerRenderTypeTransactionTest, SetDataspaceBasic_BufferState) {
@@ -1534,8 +1524,8 @@
     Transaction().setBuffer(layer, buffer).setDataspace(layer, ui::Dataspace::UNKNOWN).apply();
 
     auto shot = getScreenCapture();
-    shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED);
-    shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK);
+    shot->expectColor(Rect(0, 0, 32, 32), Color::RED);
+    shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
 }
 
 TEST_P(LayerRenderTypeTransactionTest, SetHdrMetadataBasic_BufferState) {
@@ -1552,8 +1542,8 @@
     Transaction().setBuffer(layer, buffer).setHdrMetadata(layer, hdrMetadata).apply();
 
     auto shot = getScreenCapture();
-    shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED);
-    shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK);
+    shot->expectColor(Rect(0, 0, 32, 32), Color::RED);
+    shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
 }
 
 TEST_P(LayerRenderTypeTransactionTest, SetSurfaceDamageRegionBasic_BufferState) {
@@ -1570,8 +1560,8 @@
     Transaction().setBuffer(layer, buffer).setSurfaceDamageRegion(layer, region).apply();
 
     auto shot = getScreenCapture();
-    shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED);
-    shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK);
+    shot->expectColor(Rect(0, 0, 32, 32), Color::RED);
+    shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
 }
 
 TEST_P(LayerRenderTypeTransactionTest, SetApiBasic_BufferState) {
@@ -1586,8 +1576,8 @@
     Transaction().setBuffer(layer, buffer).setApi(layer, NATIVE_WINDOW_API_CPU).apply();
 
     auto shot = getScreenCapture();
-    shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED);
-    shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK);
+    shot->expectColor(Rect(0, 0, 32, 32), Color::RED);
+    shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
 }
 
 TEST_P(LayerRenderTypeTransactionTest, SetColorTransformBasic) {
diff --git a/services/surfaceflinger/tests/LayerTransactionTest.h b/services/surfaceflinger/tests/LayerTransactionTest.h
index 87c7b7d..0bc8fe7 100644
--- a/services/surfaceflinger/tests/LayerTransactionTest.h
+++ b/services/surfaceflinger/tests/LayerTransactionTest.h
@@ -244,6 +244,11 @@
         return bufferGenerator.get(outBuffer, outFence);
     }
 
+    static ui::Size getBufferSize() {
+        static BufferGenerator bufferGenerator;
+        return bufferGenerator.getSize();
+    }
+
     sp<SurfaceComposerClient> mClient;
 
     bool deviceSupportsBlurs() {
diff --git a/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp b/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp
index ac5e297..edf55ea 100644
--- a/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp
+++ b/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp
@@ -196,17 +196,7 @@
     ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", size, size));
     ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, size, size));
 
-    if (mLayerType == ISurfaceComposerClient::eFXSurfaceBufferQueue) {
-        Transaction()
-                .setCornerRadius(layer, cornerRadius)
-                .setCrop(layer, Rect(0, 0, size, size))
-                .apply();
-    } else {
-        Transaction()
-                .setCornerRadius(layer, cornerRadius)
-                .setFrame(layer, Rect(0, 0, size, size))
-                .apply();
-    }
+    Transaction().setCornerRadius(layer, cornerRadius).apply();
     {
         const uint8_t bottom = size - 1;
         const uint8_t right = size - 1;
@@ -234,19 +224,13 @@
     ASSERT_NO_FATAL_FAILURE(child = createLayer("child", size, size));
     ASSERT_NO_FATAL_FAILURE(fillLayerColor(child, Color::GREEN, size, size));
 
-    auto transaction = Transaction()
-                               .setCornerRadius(parent, cornerRadius)
-                               .setCrop(parent, Rect(0, 0, size, size))
-                               .reparent(child, parent)
-                               .setPosition(child, 0, size)
-                               // Rotate by half PI
-                               .setMatrix(child, 0.0f, -1.0f, 1.0f, 0.0f);
-    if (mLayerType == ISurfaceComposerClient::eFXSurfaceBufferQueue) {
-        transaction.setCrop(parent, Rect(0, 0, size, size));
-    } else {
-        transaction.setFrame(parent, Rect(0, 0, size, size));
-    }
-    transaction.apply();
+    Transaction()
+            .setCornerRadius(parent, cornerRadius)
+            .reparent(child, parent)
+            .setPosition(child, 0, size)
+            // Rotate by half PI
+            .setMatrix(child, 0.0f, -1.0f, 1.0f, 0.0f)
+            .apply();
 
     {
         const uint8_t bottom = size - 1;
@@ -275,21 +259,12 @@
     ASSERT_NO_FATAL_FAILURE(child = createLayer("child", size, size / 2));
     ASSERT_NO_FATAL_FAILURE(fillLayerColor(child, Color::GREEN, size, size / 2));
 
-    if (mLayerType == ISurfaceComposerClient::eFXSurfaceBufferQueue) {
-        Transaction()
-                .setCornerRadius(parent, cornerRadius)
-                .setCrop(parent, Rect(0, 0, size, size))
-                .reparent(child, parent)
-                .setPosition(child, 0, size / 2)
-                .apply();
-    } else {
-        Transaction()
-                .setCornerRadius(parent, cornerRadius)
-                .setFrame(parent, Rect(0, 0, size, size))
-                .reparent(child, parent)
-                .setFrame(child, Rect(0, size / 2, size, size))
-                .apply();
-    }
+    Transaction()
+            .setCornerRadius(parent, cornerRadius)
+            .reparent(child, parent)
+            .setPosition(child, 0, size / 2)
+            .apply();
+
     {
         const uint8_t bottom = size - 1;
         const uint8_t right = size - 1;
@@ -331,12 +306,9 @@
 
     Transaction()
             .setLayer(greenLayer, mLayerZBase)
-            .setFrame(leftLayer, {0, 0, canvasSize * 2, canvasSize * 2})
             .setLayer(leftLayer, mLayerZBase + 1)
-            .setFrame(leftLayer, leftRect)
             .setLayer(rightLayer, mLayerZBase + 2)
             .setPosition(rightLayer, rightRect.left, rightRect.top)
-            .setFrame(rightLayer, rightRect)
             .apply();
 
     {
@@ -352,7 +324,6 @@
             .setLayer(blurLayer, mLayerZBase + 3)
             .setBackgroundBlurRadius(blurLayer, blurRadius)
             .setCrop(blurLayer, blurRect)
-            .setFrame(blurLayer, blurRect)
             .setSize(blurLayer, blurRect.getWidth(), blurRect.getHeight())
             .setAlpha(blurLayer, 0.0f)
             .apply();
@@ -435,10 +406,8 @@
 
     Transaction()
             .setLayer(left, mLayerZBase + 1)
-            .setFrame(left, {0, 0, size, size})
             .setLayer(right, mLayerZBase + 2)
             .setPosition(right, size, 0)
-            .setFrame(right, {size, 0, size * 2, size})
             .apply();
 
     {
@@ -457,7 +426,6 @@
             .setAlpha(blurParent, 0.5)
             .setLayer(blur, mLayerZBase + 4)
             .setBackgroundBlurRadius(blur, size) // set the blur radius to the size of one rect
-            .setFrame(blur, {0, 0, size * 2, size})
             .reparent(blur, blurParent)
             .apply();
 
diff --git a/services/surfaceflinger/tests/MirrorLayer_test.cpp b/services/surfaceflinger/tests/MirrorLayer_test.cpp
index 613b21e..ccf434d 100644
--- a/services/surfaceflinger/tests/MirrorLayer_test.cpp
+++ b/services/surfaceflinger/tests/MirrorLayer_test.cpp
@@ -195,7 +195,7 @@
             createLayer("BufferStateLayer", 200, 200, ISurfaceComposerClient::eFXSurfaceBufferState,
                         mChildLayer.get());
     fillBufferStateLayerColor(bufferStateLayer, Color::BLUE, 200, 200);
-    Transaction().setFrame(bufferStateLayer, Rect(0, 0, 200, 200)).show(bufferStateLayer).apply();
+    Transaction().show(bufferStateLayer).apply();
 
     {
         SCOPED_TRACE("Initial Mirror BufferStateLayer");
diff --git a/services/surfaceflinger/tests/utils/TransactionUtils.h b/services/surfaceflinger/tests/utils/TransactionUtils.h
index 3cbfed9..8c448e2 100644
--- a/services/surfaceflinger/tests/utils/TransactionUtils.h
+++ b/services/surfaceflinger/tests/utils/TransactionUtils.h
@@ -126,7 +126,7 @@
             const uint8_t* src = pixels + (outBuffer->getStride() * (y + j) + x) * 4;
             for (int32_t i = 0; i < width; i++) {
                 const uint8_t expected[4] = {color.r, color.g, color.b, color.a};
-                EXPECT_TRUE(std::equal(src, src + 4, expected, colorCompare))
+                ASSERT_TRUE(std::equal(src, src + 4, expected, colorCompare))
                         << "pixel @ (" << x + i << ", " << y + j << "): "
                         << "expected (" << color << "), "
                         << "got (" << Color{src[0], src[1], src[2], src[3]} << ")";
@@ -161,6 +161,22 @@
             ASSERT_EQ(NO_ERROR, s->unlockAndPost());
         }
     }
+
+    static void setFrame(Transaction& t, const sp<SurfaceControl>& sc, Rect source, Rect dest,
+                         int32_t transform = 0) {
+        uint32_t sourceWidth = source.getWidth();
+        uint32_t sourceHeight = source.getHeight();
+
+        if (transform & ui::Transform::ROT_90) {
+            std::swap(sourceWidth, sourceHeight);
+        }
+
+        float dsdx = dest.getWidth() / static_cast<float>(sourceWidth);
+        float dsdy = dest.getHeight() / static_cast<float>(sourceHeight);
+
+        t.setMatrix(sc, dsdx, 0, 0, dsdy);
+        t.setPosition(sc, dest.left, dest.top);
+    }
 };
 
 enum class RenderPath { SCREENSHOT, VIRTUAL_DISPLAY };
diff --git a/services/vibratorservice/VibratorManagerHalWrapper.cpp b/services/vibratorservice/VibratorManagerHalWrapper.cpp
index a9d499d..6e660e7 100644
--- a/services/vibratorservice/VibratorManagerHalWrapper.cpp
+++ b/services/vibratorservice/VibratorManagerHalWrapper.cpp
@@ -30,7 +30,7 @@
 const constexpr char* MISSING_VIBRATOR_MESSAGE_PREFIX = "No vibrator with id=";
 
 HalResult<void> LegacyManagerHalWrapper::ping() {
-    auto pingFn = [](std::shared_ptr<HalWrapper> hal) { return hal->ping(); };
+    auto pingFn = [](HalWrapper* hal) { return hal->ping(); };
     return mController->doWithRetry<void>(pingFn, "ping");
 }
 
diff --git a/services/vibratorservice/include/vibratorservice/VibratorHalController.h b/services/vibratorservice/include/vibratorservice/VibratorHalController.h
index 354e56c..6c31e2b 100644
--- a/services/vibratorservice/include/vibratorservice/VibratorHalController.h
+++ b/services/vibratorservice/include/vibratorservice/VibratorHalController.h
@@ -30,7 +30,7 @@
 std::shared_ptr<HalWrapper> connectHal(std::shared_ptr<CallbackScheduler> scheduler);
 
 template <typename T>
-using HalFunction = std::function<T(std::shared_ptr<HalWrapper>)>;
+using HalFunction = std::function<T(HalWrapper*)>;
 
 // Controller for Vibrator HAL handle.
 // This relies on a given Connector to connect to the underlying Vibrator HAL service and reconnects
@@ -64,8 +64,7 @@
      */
     Info getInfo() {
         static Info sDefaultInfo = InfoCache().get();
-        return apply<Info>([](std::shared_ptr<HalWrapper> hal) { return hal->getInfo(); },
-                           sDefaultInfo, "getInfo");
+        return apply<Info>([](HalWrapper* hal) { return hal->getInfo(); }, sDefaultInfo, "getInfo");
     }
 
     /* Calls given HAL function, applying automatic retries to reconnect with the HAL when the
@@ -103,7 +102,7 @@
         }
 
         for (int i = 0; i < MAX_RETRIES; i++) {
-            T result = halFn(hal);
+            T result = halFn(hal.get());
             if (result.checkAndLogFailure(functionName)) {
                 tryReconnect();
             } else {
@@ -111,7 +110,7 @@
             }
         }
 
-        return halFn(hal);
+        return halFn(hal.get());
     }
 };
 
diff --git a/services/vibratorservice/test/VibratorHalControllerTest.cpp b/services/vibratorservice/test/VibratorHalControllerTest.cpp
index 279496a..8e77bc5 100644
--- a/services/vibratorservice/test/VibratorHalControllerTest.cpp
+++ b/services/vibratorservice/test/VibratorHalControllerTest.cpp
@@ -40,11 +40,9 @@
 using namespace std::chrono_literals;
 using namespace testing;
 
-static const auto ON_FN = [](std::shared_ptr<vibrator::HalWrapper> hal) {
-    return hal->on(10ms, []() {});
-};
-static const auto OFF_FN = [](std::shared_ptr<vibrator::HalWrapper> hal) { return hal->off(); };
-static const auto PING_FN = [](std::shared_ptr<vibrator::HalWrapper> hal) { return hal->ping(); };
+static const auto ON_FN = [](vibrator::HalWrapper* hal) { return hal->on(10ms, []() {}); };
+static const auto OFF_FN = [](vibrator::HalWrapper* hal) { return hal->off(); };
+static const auto PING_FN = [](vibrator::HalWrapper* hal) { return hal->ping(); };
 
 // -------------------------------------------------------------------------------------------------
 
@@ -233,7 +231,7 @@
     std::unique_ptr<int32_t> callbackCounter = std::make_unique<int32_t>();
     auto callback = vibrator::TestFactory::createCountingCallback(callbackCounter.get());
 
-    auto onFn = [&](std::shared_ptr<vibrator::HalWrapper> hal) { return hal->on(10ms, callback); };
+    auto onFn = [&](vibrator::HalWrapper* hal) { return hal->on(10ms, callback); };
     ASSERT_TRUE(mController->doWithRetry<void>(onFn, "on").isOk());
     ASSERT_TRUE(mController->doWithRetry<void>(PING_FN, "ping").isFailed());
     mMockHal.reset();
diff --git a/services/vibratorservice/test/VibratorHalWrapperAidlTest.cpp b/services/vibratorservice/test/VibratorHalWrapperAidlTest.cpp
index d1db82b..af0cdb8 100644
--- a/services/vibratorservice/test/VibratorHalWrapperAidlTest.cpp
+++ b/services/vibratorservice/test/VibratorHalWrapperAidlTest.cpp
@@ -644,7 +644,6 @@
                 .Times(Exactly(2))
                 .WillOnce(Return(Status::fromExceptionCode(Status::Exception::EX_SECURITY)))
                 .WillRepeatedly(DoAll(TriggerCallbackInArg1(), Return(Status())));
-        ;
     }
 
     std::unique_ptr<int32_t> callbackCounter = std::make_unique<int32_t>();
diff --git a/services/vibratorservice/test/VibratorManagerHalWrapperAidlTest.cpp b/services/vibratorservice/test/VibratorManagerHalWrapperAidlTest.cpp
index 3de1576..548d028 100644
--- a/services/vibratorservice/test/VibratorManagerHalWrapperAidlTest.cpp
+++ b/services/vibratorservice/test/VibratorManagerHalWrapperAidlTest.cpp
@@ -40,7 +40,7 @@
 using namespace android;
 using namespace testing;
 
-static const auto OFF_FN = [](std::shared_ptr<vibrator::HalWrapper> hal) { return hal->off(); };
+static const auto OFF_FN = [](vibrator::HalWrapper* hal) { return hal->off(); };
 
 class MockBinder : public BBinder {
 public:
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index 020b520..8d6681c 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -1086,7 +1086,8 @@
     ALOGW_IF(err != android::OK, "native_window_api_connect failed: %s (%d)",
              strerror(-err), err);
 
-    err = window->perform(window, NATIVE_WINDOW_SET_DEQUEUE_TIMEOUT, -1);
+    err =
+        window->perform(window, NATIVE_WINDOW_SET_DEQUEUE_TIMEOUT, nsecs_t{-1});
     if (err != android::OK) {
         ALOGE("window->perform(SET_DEQUEUE_TIMEOUT) failed: %s (%d)",
               strerror(-err), err);