Merge changes I7bae2f9d,I0e8f0b15,I09cbb0cb into sc-dev

* changes:
  Consider GPU comp info for jank classification
  Remove hwcDuration from FrameTimeline
  Report deltas as 0 instead of -1 for prediction expired display frames
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/cmds/dumpstate/tests/dumpstate_test.cpp b/cmds/dumpstate/tests/dumpstate_test.cpp
index 2c573e4..db508b5 100644
--- a/cmds/dumpstate/tests/dumpstate_test.cpp
+++ b/cmds/dumpstate/tests/dumpstate_test.cpp
@@ -1032,12 +1032,12 @@
     ZipArchiveHandle handle_;
 };
 
-// Generate a quick wifi report redirected to a file, open it and verify entry exist.
-TEST_F(ZippedBugReportStreamTest, StreamWifiReport) {
-    std::string out_path = kTestDataPath + "out.zip";
+// Generate a quick LimitedOnly report redirected to a file, open it and verify entry exist.
+TEST_F(ZippedBugReportStreamTest, StreamLimitedOnlyReport) {
+    std::string out_path = kTestDataPath + "StreamLimitedOnlyReportOut.zip";
     android::base::unique_fd out_fd;
     CreateFd(out_path, &out_fd);
-    ds_.options_->wifi_only = true;
+    ds_.options_->limited_only = true;
     ds_.options_->stream_to_socket = true;
     RedirectOutputToFd(out_fd);
 
@@ -1051,7 +1051,7 @@
     ExtractToMemory(handle_, &entry, reinterpret_cast<uint8_t*>(bugreport_txt_name.data()),
                     entry.uncompressed_length);
     EXPECT_THAT(bugreport_txt_name,
-                testing::ContainsRegex("(bugreport-.+-wifi(-[[:digit:]]+){6}\\.txt)"));
+                testing::ContainsRegex("(bugreport-.+(-[[:digit:]]+){6}\\.txt)"));
     VerifyEntry(handle_, bugreport_txt_name, &entry);
 }
 
diff --git a/cmds/installd/otapreopt_chroot.cpp b/cmds/installd/otapreopt_chroot.cpp
index c04b558..3a87776 100644
--- a/cmds/installd/otapreopt_chroot.cpp
+++ b/cmds/installd/otapreopt_chroot.cpp
@@ -27,6 +27,7 @@
 #include <android-base/file.h>
 #include <android-base/logging.h>
 #include <android-base/macros.h>
+#include <android-base/scopeguard.h>
 #include <android-base/stringprintf.h>
 #include <android-base/unique_fd.h>
 #include <libdm/dm.h>
@@ -72,6 +73,15 @@
     }
 }
 
+static void DeactivateApexPackages() {
+    std::vector<std::string> apexd_cmd{"/system/bin/apexd", "--unmount-all"};
+    std::string apexd_error_msg;
+    bool exec_result = Exec(apexd_cmd, &apexd_error_msg);
+    if (!exec_result) {
+        PLOG(ERROR) << "Running /system/bin/apexd --unmount-all failed: " << apexd_error_msg;
+    }
+}
+
 static void TryExtraMount(const char* name, const char* slot, const char* target) {
     std::string partition_name = StringPrintf("%s%s", name, slot);
 
@@ -231,10 +241,30 @@
         exit(205);
     }
 
+    // Call apexd --unmount-all to free up loop and dm block devices, so that we can re-use
+    // them during the next invocation. Since otapreopt_chroot calls exit in case something goes
+    // wrong we need to register our own atexit handler.
+    // We want to register this handler before actually activating apex packages. This is mostly
+    // due to the fact that if fail to unmount apexes, then on the next run of otapreopt_chroot
+    // we will ask for new loop devices instead of re-using existing ones, and we really don't want
+    // to do that. :)
+    if (atexit(DeactivateApexPackages) != 0) {
+        LOG(ERROR) << "Failed to register atexit hander";
+        exit(206);
+    }
+
     // Try to mount APEX packages in "/apex" in the chroot dir. We need at least
     // the ART APEX, as it is required by otapreopt to run dex2oat.
     ActivateApexPackages();
 
+    auto cleanup = android::base::make_scope_guard([](){
+        std::vector<std::string> apexd_cmd{"/system/bin/apexd", "--unmount-all"};
+        std::string apexd_error_msg;
+        bool exec_result = Exec(apexd_cmd, &apexd_error_msg);
+        if (!exec_result) {
+            PLOG(ERROR) << "Running /system/bin/apexd --unmount-all failed: " << apexd_error_msg;
+        }
+    });
     // Check that an ART APEX has been activated; clean up and exit
     // early otherwise.
     static constexpr const std::string_view kRequiredApexs[] = {
diff --git a/cmds/surfacereplayer/proto/src/trace.proto b/cmds/surfacereplayer/proto/src/trace.proto
index 79aab82..3798ba7 100644
--- a/cmds/surfacereplayer/proto/src/trace.proto
+++ b/cmds/surfacereplayer/proto/src/trace.proto
@@ -46,11 +46,9 @@
         HiddenFlagChange            hidden_flag             = 12;
         OpaqueFlagChange            opaque_flag             = 13;
         SecureFlagChange            secure_flag             = 14;
-        DeferredTransactionChange   deferred_transaction    = 15;
         CornerRadiusChange          corner_radius           = 16;
         ReparentChange              reparent                = 17;
         RelativeParentChange        relative_parent         = 18;
-        ReparentChildrenChange      reparent_children       = 19;
         BackgroundBlurRadiusChange  background_blur_radius  = 20;
         ShadowRadiusChange          shadow_radius           = 21;
         BlurRegionsChange           blur_regions            = 22;
@@ -114,11 +112,6 @@
     required bool secure_flag = 1;
 }
 
-message DeferredTransactionChange {
-    required int32  layer_id     = 1;
-    required uint64 frame_number = 2;
-}
-
 message DisplayChange {
     required int32 id = 1;
 
@@ -190,10 +183,6 @@
     required int32 parent_id = 1;
 }
 
-message ReparentChildrenChange {
-    required int32 parent_id = 1;
-}
-
 message RelativeParentChange {
     required int32 relative_parent_id = 1;
     required int32 z = 2;
diff --git a/cmds/surfacereplayer/replayer/Replayer.cpp b/cmds/surfacereplayer/replayer/Replayer.cpp
index bbbe6f7..cfd42fe 100644
--- a/cmds/surfacereplayer/replayer/Replayer.cpp
+++ b/cmds/surfacereplayer/replayer/Replayer.cpp
@@ -402,17 +402,9 @@
             case SurfaceChange::SurfaceChangeCase::kSecureFlag:
                 setSecureFlag(transaction, change.id(), change.secure_flag());
                 break;
-            case SurfaceChange::SurfaceChangeCase::kDeferredTransaction:
-                waitUntilDeferredTransactionLayerExists(change.deferred_transaction(), lock);
-                setDeferredTransaction(transaction, change.id(),
-                        change.deferred_transaction());
-                break;
             case SurfaceChange::SurfaceChangeCase::kReparent:
                 setReparentChange(transaction, change.id(), change.reparent());
                 break;
-            case SurfaceChange::SurfaceChangeCase::kReparentChildren:
-                setReparentChildrenChange(transaction, change.id(), change.reparent_children());
-                break;
             case SurfaceChange::SurfaceChangeCase::kRelativeParent:
                 setRelativeParentChange(transaction, change.id(), change.relative_parent());
                 break;
@@ -563,19 +555,6 @@
     t.setFlags(mLayers[id], flag, layer_state_t::eLayerSecure);
 }
 
-void Replayer::setDeferredTransaction(SurfaceComposerClient::Transaction& t,
-        layer_id id, const DeferredTransactionChange& dtc) {
-    ALOGV("Layer %d: Setting Deferred Transaction -- layer_id=%d, "
-          "frame_number=%llu",
-            id, dtc.layer_id(), dtc.frame_number());
-    if (mLayers.count(dtc.layer_id()) == 0 || mLayers[dtc.layer_id()] == nullptr) {
-        ALOGE("Layer %d not found in Deferred Transaction", dtc.layer_id());
-        return;
-    }
-
-    t.deferTransactionUntil_legacy(mLayers[id], mLayers[dtc.layer_id()], dtc.frame_number());
-}
-
 void Replayer::setDisplaySurface(SurfaceComposerClient::Transaction& t,
         display_id id, const DispSurfaceChange& /*dsc*/) {
     sp<IGraphicBufferProducer> outProducer;
@@ -679,13 +658,6 @@
     std::this_thread::sleep_for(std::chrono::nanoseconds(timestamp - mCurrentTime));
 }
 
-void Replayer::waitUntilDeferredTransactionLayerExists(
-        const DeferredTransactionChange& dtc, std::unique_lock<std::mutex>& lock) {
-    if (mLayers.count(dtc.layer_id()) == 0 || mLayers[dtc.layer_id()] == nullptr) {
-        mLayerCond.wait(lock, [&] { return (mLayers[dtc.layer_id()] != nullptr); });
-    }
-}
-
 status_t Replayer::loadSurfaceComposerClient() {
     mComposerClient = new SurfaceComposerClient;
     return mComposerClient->initCheck();
@@ -709,15 +681,6 @@
     t.setRelativeLayer(mLayers[id], mLayers[c.relative_parent_id()], c.z());
 }
 
-void Replayer::setReparentChildrenChange(SurfaceComposerClient::Transaction& t,
-        layer_id id, const ReparentChildrenChange& c) {
-    if (mLayers.count(c.parent_id()) == 0 || mLayers[c.parent_id()] == nullptr) {
-        ALOGE("Layer %d not found in reparent children transaction", c.parent_id());
-        return;
-    }
-    t.reparentChildren(mLayers[id], mLayers[c.parent_id()]);
-}
-
 void Replayer::setShadowRadiusChange(SurfaceComposerClient::Transaction& t,
         layer_id id, const ShadowRadiusChange& c) {
     t.setShadowRadius(mLayers[id], c.radius());
diff --git a/cmds/surfacereplayer/replayer/Replayer.h b/cmds/surfacereplayer/replayer/Replayer.h
index 324d591..d62522a 100644
--- a/cmds/surfacereplayer/replayer/Replayer.h
+++ b/cmds/surfacereplayer/replayer/Replayer.h
@@ -110,14 +110,10 @@
             layer_id id, const OpaqueFlagChange& ofc);
     void setSecureFlag(SurfaceComposerClient::Transaction& t,
             layer_id id, const SecureFlagChange& sfc);
-    void setDeferredTransaction(SurfaceComposerClient::Transaction& t,
-            layer_id id, const DeferredTransactionChange& dtc);
     void setReparentChange(SurfaceComposerClient::Transaction& t,
             layer_id id, const ReparentChange& c);
     void setRelativeParentChange(SurfaceComposerClient::Transaction& t,
             layer_id id, const RelativeParentChange& c);
-    void setReparentChildrenChange(SurfaceComposerClient::Transaction& t,
-            layer_id id, const ReparentChildrenChange& c);
     void setShadowRadiusChange(SurfaceComposerClient::Transaction& t,
             layer_id id, const ShadowRadiusChange& c);
     void setBlurRegionsChange(SurfaceComposerClient::Transaction& t,
@@ -133,8 +129,6 @@
             display_id id, const ProjectionChange& pc);
 
     void waitUntilTimestamp(int64_t timestamp);
-    void waitUntilDeferredTransactionLayerExists(
-            const DeferredTransactionChange& dtc, std::unique_lock<std::mutex>& lock);
     status_t loadSurfaceComposerClient();
 
     Trace mTrace;
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/android/bitmap.h b/include/android/bitmap.h
index a70dffd..6704a1d 100644
--- a/include/android/bitmap.h
+++ b/include/android/bitmap.h
@@ -241,6 +241,7 @@
  *
  *  Available since API level 30.
  *
+ *  @param env Handle to the JNI environment pointer.
  *  @param bitmap Handle to an android.graphics.Bitmap.
  *  @param outBuffer On success, is set to a pointer to the
  *         {@link AHardwareBuffer} associated with bitmap. This acquires
diff --git a/include/android/choreographer.h b/include/android/choreographer.h
index cc5420e..b743f49 100644
--- a/include/android/choreographer.h
+++ b/include/android/choreographer.h
@@ -32,6 +32,11 @@
 __BEGIN_DECLS
 
 struct AChoreographer;
+/**
+ * Opaque type that provides access to an AChoreographer object.
+ *
+ * A pointer can be obtained using {@link AChoreographer_getInstance()}.
+ */
 typedef struct AChoreographer AChoreographer;
 
 /**
diff --git a/include/android/font.h b/include/android/font.h
index a172618..8a3a474 100644
--- a/include/android/font.h
+++ b/include/android/font.h
@@ -189,7 +189,7 @@
  * Available since API level 29.
  *
  * \param font a font object. Passing NULL is not allowed.
- * \return a positive integer less than or equal to {@link ASYSTEM_FONT_MAX_WEIGHT} is returned.
+ * \return a positive integer less than or equal to {@link AFONT_WEIGHT_MAX} is returned.
  */
 uint16_t AFont_getWeight(const AFont* _Nonnull font) __INTRODUCED_IN(29);
 
@@ -241,7 +241,7 @@
  * In this case, AFont_getAxisCount returns 2 and AFont_getAxisTag
  * and AFont_getAxisValue will return following values.
  * \code{.cpp}
- *     AFont* font = AFontIterator_next(ite);
+ *     AFont* font = ASystemFontIterator_next(ite);
  *
  *     // Returns the number of axes
  *     AFont_getAxisCount(font);  // Returns 2
@@ -289,7 +289,7 @@
  *
  * \param font a font object. Passing NULL is not allowed.
  * \param axisIndex an index to the font variation settings. Passing value larger than or
- *         equal to {@link ASYstemFont_getAxisCount} is not allwed.
+ *         equal to {@link AFont_getAxisCount} is not allowed.
  * \return a float value for the given font variation setting.
  */
 float AFont_getAxisValue(const AFont* _Nonnull font, uint32_t axisIndex)
diff --git a/include/android/font_matcher.h b/include/android/font_matcher.h
index 49e478c..4417422 100644
--- a/include/android/font_matcher.h
+++ b/include/android/font_matcher.h
@@ -36,7 +36,7 @@
  *  // Simple font query for the ASCII character.
  *  std::vector<uint16_t> text = { 'A' };
  *  AFontMatcher* matcher = AFontMatcher_create("sans-serif");
- *  ASystemFont* font = AFontMatcher_match(text.data(), text.length(), &runLength);
+ *  AFont* font = AFontMatcher_match(text.data(), text.length(), &runLength);
  *  // runLength will be 1 and the font will points a valid font file.
  *  AFontMatcher_destroy(matcher);
  *
@@ -44,17 +44,17 @@
  *  std::vector<uint16_t> text = { 0x9AA8 };
  *  AFontMatcher* matcher = AFontMatcher_create("sans-serif");
  *  AFontMatcher_setLocales(matcher, "zh-CN,ja-JP");
- *  ASystemFont* font = AFontMatcher_match(text.data(), text.length(), &runLength);
+ *  AFont* font = AFontMatcher_match(text.data(), text.length(), &runLength);
  *  // runLength will be 1 and the font will points a Simplified Chinese font.
  *  AFontMatcher_setLocales(matcher, "ja-JP,zh-CN");
- *  ASystemFont* font = AFontMatcher_match(text.data(), text.length(), &runLength);
+ *  AFont* font = AFontMatcher_match(text.data(), text.length(), &runLength);
  *  // runLength will be 1 and the font will points a Japanese font.
  *  AFontMatcher_destroy(matcher);
  *
  *  // Querying font for text/color emoji
  *  std::vector<uint16_t> text = { 0xD83D, 0xDC68, 0x200D, 0x2764, 0xFE0F, 0x200D, 0xD83D, 0xDC68 };
  *  AFontMatcher* matcher = AFontMatcher_create("sans-serif");
- *  ASystemFont* font = AFontMatcher_match(text.data(), text.length(), &runLength);
+ *  AFont* font = AFontMatcher_match(text.data(), text.length(), &runLength);
  *  // runLength will be 8 and the font will points a color emoji font.
  *  AFontMatcher_destroy(matcher);
  *
@@ -62,7 +62,7 @@
  *  // 0x05D0 is a Hebrew character and 0x0E01 is a Thai character.
  *  std::vector<uint16_t> text = { 0x05D0, 0x0E01 };
  *  AFontMatcher* matcher = AFontMatcher_create("sans-serif");
- *  ASystemFont* font = AFontMatcher_match(text.data(), text.length(), &runLength);
+ *  AFont* font = AFontMatcher_match(text.data(), text.length(), &runLength);
  *  // runLength will be 1 and the font will points a Hebrew font.
  *  AFontMatcher_destroy(matcher);
  * \endcode
@@ -146,7 +146,7 @@
 /**
  * Set font style to matcher.
  *
- * If this function is not called, the matcher performs with {@link ASYSTEM_FONT_WEIGHT_NORMAL}
+ * If this function is not called, the matcher performs with {@link AFONT_WEIGHT_NORMAL}
  * with non-italic style.
  *
  * Available since API level 29.
@@ -206,7 +206,7 @@
  * \param textLength a length of the given text buffer. This must not be zero.
  * \param runLengthOut if not null, the font run length will be filled.
  * \return a font to be used for given text and params. You need to release the returned font by
- *         ASystemFont_close when it is no longer needed.
+ *         AFont_close when it is no longer needed.
  */
 AFont* _Nonnull AFontMatcher_match(
         const AFontMatcher* _Nonnull matcher,
diff --git a/include/android/sensor.h b/include/android/sensor.h
index 92b79c7..36fa326 100644
--- a/include/android/sensor.h
+++ b/include/android/sensor.h
@@ -428,6 +428,10 @@
 } ADynamicSensorEvent;
 
 typedef struct AAdditionalInfoEvent {
+    /**
+     * Event type, such as ASENSOR_ADDITIONAL_INFO_BEGIN, ASENSOR_ADDITIONAL_INFO_END and others.
+     * Refer to {@link ASENSOR_TYPE_ADDITIONAL_INFO} for the expected reporting behavior.
+     */
     int32_t type;
     int32_t serial;
     union {
@@ -436,12 +440,22 @@
     };
 } AAdditionalInfoEvent;
 
+/**
+ * Information that describes a sensor event, refer to
+ * <a href="/reference/android/hardware/SensorEvent">SensorEvent</a> for additional
+ * documentation.
+ */
 /* NOTE: changes to this struct has to be backward compatible */
 typedef struct ASensorEvent {
     int32_t version; /* sizeof(struct ASensorEvent) */
-    int32_t sensor;
-    int32_t type;
-    int32_t reserved0;
+    int32_t sensor;  /** The sensor that generates this event */
+    int32_t type;    /** Sensor type for the event, such as {@link ASENSOR_TYPE_ACCELEROMETER}*/
+    int32_t reserved0; /** do not use */
+    /**
+     * The time in nanoseconds at which the event happened, and its behavior
+     * is identical to <a href="/reference/android/hardware/SensorEvent#timestamp">
+     * SensorEvent::timestamp</a> in Java API.
+     */
     int64_t timestamp;
     union {
         union {
@@ -653,9 +667,10 @@
 /**
  * Destroy a direct channel
  *
- * Destroy a direct channel previously created using {@link ASensorManager_createDirectChannel}.
- * The buffer used for creating direct channel does not get destroyed with
- * {@link ASensorManager_destroy} and has to be close or released separately.
+ * Destroy a direct channel previously created by using one of
+ * ASensorManager_create*DirectChannel() derivative functions.
+ * Note that the buffer used for creating the direct channel does not get destroyed with
+ * ASensorManager_destroyDirectChannel and has to be closed or released separately.
  *
  * Available since API level 26.
  *
@@ -701,7 +716,7 @@
  * \param channelId channel id (a positive integer) returned from
  *                  {@link ASensorManager_createSharedMemoryDirectChannel} or
  *                  {@link ASensorManager_createHardwareBufferDirectChannel}.
- *
+ * \param rate      one of predefined ASENSOR_DIRECT_RATE_... that is supported by the sensor.
  * \return positive token for success or negative error code.
  */
 int ASensorManager_configureDirectReport(ASensorManager* manager,
@@ -718,7 +733,7 @@
  * \param queue {@link ASensorEventQueue} for sensor event to be report to.
  * \param sensor {@link ASensor} to be enabled.
  * \param samplingPeriodUs sampling period of sensor in microseconds.
- * \param maxBatchReportLatencyus maximum time interval between two batch of sensor events are
+ * \param maxBatchReportLatencyUs maximum time interval between two batches of sensor events are
  *                                delievered in microseconds. For sensor streaming, set to 0.
  * \return 0 on success or a negative error code on failure.
  */
@@ -778,7 +793,7 @@
  * Retrieve next available events from the queue to a specified event array.
  *
  * \param queue {@link ASensorEventQueue} to get events from
- * \param events pointer to an array of {@link ASensorEvents}.
+ * \param events pointer to an array of {@link ASensorEvent}.
  * \param count max number of event that can be filled into array event.
  * \return number of events returned on success; negative error code when
  *         no events are pending or an error has occurred.
@@ -798,7 +813,7 @@
  * Request that {@link ASENSOR_TYPE_ADDITIONAL_INFO} events to be delivered on
  * the given {@link ASensorEventQueue}.
  *
- * Sensor data events are always delivered to the {@ASensorEventQueue}.
+ * Sensor data events are always delivered to the {@link ASensorEventQueue}.
  *
  * The {@link ASENSOR_TYPE_ADDITIONAL_INFO} events will be returned through
  * {@link ASensorEventQueue_getEvents}. The client is responsible for checking
@@ -890,7 +905,7 @@
  *
  * \param sensor  a {@link ASensor} to denote the sensor to be checked.
  * \param channelType  Channel type constant, either
- *                     {@ASENSOR_DIRECT_CHANNEL_TYPE_SHARED_MEMORY}
+ *                     {@link ASENSOR_DIRECT_CHANNEL_TYPE_SHARED_MEMORY}
  *                     or {@link ASENSOR_DIRECT_CHANNEL_TYPE_HARDWARE_BUFFER}.
  * \returns true if sensor supports the specified direct channel type.
  */
@@ -920,8 +935,8 @@
  * sensor that generated the event.
  *
  * It is important to note that the value returned by {@link ASensor_getHandle} is not the same as
- * the value returned by the Java API {@link android.hardware.Sensor#getId} and no mapping exists
- * between the values.
+ * the value returned by the Java API <a href="/reference/android/hardware/Sensor#getId()">
+ * android.hardware.Sensor's getId()</a> and no mapping exists between the values.
  *
  * Available since API level 29.
  */
diff --git a/include/android/sharedmem.h b/include/android/sharedmem.h
index 7994aa9..e0a8045 100644
--- a/include/android/sharedmem.h
+++ b/include/android/sharedmem.h
@@ -59,9 +59,10 @@
  *
  * Use close() to release the shared memory region.
  *
- * Use {@link android.os.ParcelFileDescriptor} to pass the file descriptor to
- * another process. File descriptors may also be sent to other processes over a Unix domain
- * socket with sendmsg and SCM_RIGHTS. See sendmsg(3) and cmsg(3) man pages for more information.
+ * Use <a href="/reference/android/os/ParcelFileDescriptor">android.os.ParcelFileDescriptor</a>
+ * to pass the file descriptor to another process. File descriptors may also be sent to other
+ * processes over a Unix domain socket with sendmsg and SCM_RIGHTS. See sendmsg(3) and
+ * cmsg(3) man pages for more information.
  *
  * If you intend to share this file descriptor with a child process after
  * calling exec(3), note that you will need to use fcntl(2) with FD_SETFD
@@ -71,7 +72,8 @@
  *
  * \param name an optional name.
  * \param size size of the shared memory region
- * \return file descriptor that denotes the shared memory; -1 and sets errno on failure, or -EINVAL if the error is that size was 0.
+ * \return file descriptor that denotes the shared memory;
+ *         -1 and sets errno on failure, or -EINVAL if the error is that size was 0.
  */
 int ASharedMemory_create(const char *name, size_t size) __INTRODUCED_IN(26);
 
diff --git a/include/android/thermal.h b/include/android/thermal.h
index 0ea13d3..32580ba 100644
--- a/include/android/thermal.h
+++ b/include/android/thermal.h
@@ -60,6 +60,10 @@
 extern "C" {
 #endif
 
+/**
+ * Thermal status used in function {@link AThermal_getCurrentThermalStatus} and
+ * {@link AThermal_StatusCallback}.
+ */
 enum AThermalStatus {
     /** Error in thermal status. */
     ATHERMAL_STATUS_ERROR = -1,
@@ -194,10 +198,10 @@
  *
  * The value returned is a non-negative float that represents how much of the thermal envelope
  * is in use (or is forecasted to be in use). A value of 1.0 indicates that the device is
- * (or will be) throttled at {@link #THERMAL_STATUS_SEVERE}. Such throttling can affect the
+ * (or will be) throttled at {@link #ATHERMAL_STATUS_SEVERE}. Such throttling can affect the
  * CPU, GPU, and other subsystems. Values may exceed 1.0, but there is no implied mapping
  * to specific thermal levels beyond that point. This means that values greater than 1.0
- * may correspond to {@link #THERMAL_STATUS_SEVERE}, but may also represent heavier throttling.
+ * may correspond to {@link #ATHERMAL_STATUS_SEVERE}, but may also represent heavier throttling.
  *
  * A value of 0.0 corresponds to a fixed distance from 1.0, but does not correspond to any
  * particular thermal status or temperature. Values on (0.0, 1.0] may be expected to scale
diff --git a/include/android/trace.h b/include/android/trace.h
index dcefffb..d11158b 100644
--- a/include/android/trace.h
+++ b/include/android/trace.h
@@ -91,7 +91,7 @@
  *
  * Available since API level 29.
  *
- * \param methodName The method name to appear in the trace.
+ * \param sectionName The method name to appear in the trace.
  * \param cookie Unique identifier for distinguishing simultaneous events
  */
 void ATrace_endAsyncSection(const char* sectionName, int32_t cookie) __INTRODUCED_IN(29);
diff --git a/include/android/window.h b/include/android/window.h
index 436bf3a..c144864 100644
--- a/include/android/window.h
+++ b/include/android/window.h
@@ -103,8 +103,9 @@
      * bar) while this window is displayed.  This allows the window to
      * use the entire display space for itself -- the status bar will
      * be hidden when an app window with this flag set is on the top
-     * layer. A fullscreen window will ignore a value of {@link
-     * AWINDOW_SOFT_INPUT_ADJUST_RESIZE}; the window will stay
+     * layer. A fullscreen window will ignore a value of
+     * <a href="/reference/android/view/WindowManager.LayoutParams#SOFT_INPUT_ADJUST_RESIZE">
+     * SOFT_INPUT_ADJUST_RESIZE</a>; the window will stay
      * fullscreen and will not resize.
      */
     AWINDOW_FLAG_FULLSCREEN                 = 0x00000400,
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/binder/Android.bp b/libs/binder/Android.bp
index cdd8006..6da4e9e 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -60,16 +60,13 @@
 // Currently, these are only on system android (not vendor, not host)
 // TODO(b/183654927) - move these into separate libraries
 libbinder_device_interface_sources = [
-    "ActivityManager.cpp",
     "AppOpsManager.cpp",
-    "IActivityManager.cpp",
     "IAppOpsCallback.cpp",
     "IAppOpsService.cpp",
+
     "IPermissionController.cpp",
-    "IUidObserver.cpp",
     "PermissionCache.cpp",
     "PermissionController.cpp",
-    ":activity_manager_procstate_aidl",
 ]
 
 cc_library {
@@ -163,6 +160,7 @@
         "-Werror",
         "-Wzero-as-null-pointer-constant",
         "-DANDROID_BASE_UNIQUE_FD_DISABLE_IMPLICIT_CONVERSION",
+        "-DANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION",
     ],
     product_variables: {
         binder32bit: {
@@ -294,13 +292,21 @@
     ],
 }
 
-// TODO(b/183654927): initially empty lib to work around some merge conflicts
 cc_library {
     name: "libactivitymanager_aidl",
-    srcs: [],
+    srcs: [
+        "ActivityManager.cpp",
+        "IActivityManager.cpp",
+        "IUidObserver.cpp",
+        ":activity_manager_procstate_aidl",
+    ],
+    export_include_dirs: ["include_activitymanager"],
     shared_libs: [
         "libbinder",
         "libutils",
         "liblog",
     ],
+    aidl: {
+        export_aidl_headers: true,
+    },
 }
diff --git a/libs/binder/AppOpsManager.cpp b/libs/binder/AppOpsManager.cpp
index de42f36..baa9d75 100644
--- a/libs/binder/AppOpsManager.cpp
+++ b/libs/binder/AppOpsManager.cpp
@@ -37,7 +37,7 @@
 
     pthread_mutex_lock(&gClientIdMutex);
     if (gClientId == nullptr) {
-        gClientId = new BBinder();
+        gClientId = sp<BBinder>::make();
     }
     pthread_mutex_unlock(&gClientIdMutex);
     return gClientId;
diff --git a/libs/binder/BpBinder.cpp b/libs/binder/BpBinder.cpp
index 53b36ff..fdcf94a 100644
--- a/libs/binder/BpBinder.cpp
+++ b/libs/binder/BpBinder.cpp
@@ -107,8 +107,7 @@
 
 // ---------------------------------------------------------------------------
 
-
-BpBinder* BpBinder::create(int32_t handle) {
+sp<BpBinder> BpBinder::create(int32_t handle) {
     int32_t trackedUid = -1;
     if (sCountByUidEnabled) {
         trackedUid = IPCThreadState::self()->getCallingUid();
@@ -134,10 +133,10 @@
         }
         sTrackingMap[trackedUid]++;
     }
-    return new BpBinder(BinderHandle{handle}, trackedUid);
+    return sp<BpBinder>::make(BinderHandle{handle}, trackedUid);
 }
 
-BpBinder* BpBinder::create(const sp<RpcConnection>& connection, const RpcAddress& address) {
+sp<BpBinder> BpBinder::create(const sp<RpcConnection>& connection, const RpcAddress& address) {
     LOG_ALWAYS_FATAL_IF(connection == nullptr, "BpBinder::create null connection");
 
     // These are not currently tracked, since there is no UID or other
@@ -145,7 +144,7 @@
     // needed, connection objects keep track of all BpBinder objects on a
     // per-connection basis.
 
-    return new BpBinder(SocketHandle{connection, address});
+    return sp<BpBinder>::make(SocketHandle{connection, address});
 }
 
 BpBinder::BpBinder(Handle&& handle)
@@ -194,7 +193,7 @@
 const String16& BpBinder::getInterfaceDescriptor() const
 {
     if (isDescriptorCached() == false) {
-        sp<BpBinder> thiz = const_cast<BpBinder*>(this);
+        sp<BpBinder> thiz = sp<BpBinder>::fromExisting(const_cast<BpBinder*>(this));
 
         Parcel data;
         data.markForBinder(thiz);
@@ -226,7 +225,7 @@
 status_t BpBinder::pingBinder()
 {
     Parcel data;
-    data.markForBinder(this);
+    data.markForBinder(sp<BpBinder>::fromExisting(this));
     Parcel reply;
     return transact(PING_TRANSACTION, data, &reply);
 }
@@ -403,7 +402,7 @@
     ALOGV("Reporting death to recipient: %p\n", recipient.get());
     if (recipient == nullptr) return;
 
-    recipient->binderDied(this);
+    recipient->binderDied(wp<BpBinder>::fromExisting(this));
 }
 
 
diff --git a/libs/binder/BufferedTextOutput.cpp b/libs/binder/BufferedTextOutput.cpp
index 349658e..a90bfd2 100644
--- a/libs/binder/BufferedTextOutput.cpp
+++ b/libs/binder/BufferedTextOutput.cpp
@@ -254,7 +254,7 @@
         BufferState* bs = ts.states[mIndex].get();
         if (bs != nullptr && bs->seq == mSeq) return bs;
 
-        ts.states.editItemAt(mIndex) = new BufferState(mIndex);
+        ts.states.editItemAt(mIndex) = sp<BufferState>::make(mIndex);
         bs = ts.states[mIndex].get();
         if (bs != nullptr) return bs;
     }
diff --git a/libs/binder/IAppOpsService.cpp b/libs/binder/IAppOpsService.cpp
index 44aa55e..d59f445 100644
--- a/libs/binder/IAppOpsService.cpp
+++ b/libs/binder/IAppOpsService.cpp
@@ -18,8 +18,8 @@
 
 #include <binder/IAppOpsService.h>
 
-#include <utils/Log.h>
 #include <binder/Parcel.h>
+#include <utils/Log.h>
 #include <utils/String8.h>
 
 #include <optional>
@@ -63,6 +63,8 @@
         remote()->transact(NOTE_OPERATION_TRANSACTION, data, &reply);
         // fail on exception
         if (reply.readExceptionCode() != 0) return MODE_ERRORED;
+        // TODO b/184855056: extract to class
+        reply.readInt32();
         reply.readByte();
         return reply.readInt32();
     }
@@ -85,6 +87,8 @@
         remote()->transact(START_OPERATION_TRANSACTION, data, &reply);
         // fail on exception
         if (reply.readExceptionCode() != 0) return MODE_ERRORED;
+        // TODO b/184855056: extract to class
+        reply.readInt32();
         reply.readByte();
         return reply.readInt32();
     }
diff --git a/libs/binder/IInterface.cpp b/libs/binder/IInterface.cpp
index b19004d..2780bd4 100644
--- a/libs/binder/IInterface.cpp
+++ b/libs/binder/IInterface.cpp
@@ -33,14 +33,14 @@
 sp<IBinder> IInterface::asBinder(const IInterface* iface)
 {
     if (iface == nullptr) return nullptr;
-    return const_cast<IInterface*>(iface)->onAsBinder();
+    return sp<IBinder>::fromExisting(const_cast<IInterface*>(iface)->onAsBinder());
 }
 
 // static
 sp<IBinder> IInterface::asBinder(const sp<IInterface>& iface)
 {
     if (iface == nullptr) return nullptr;
-    return iface->onAsBinder();
+    return sp<IBinder>::fromExisting(iface->onAsBinder());
 }
 
 
diff --git a/libs/binder/IMemory.cpp b/libs/binder/IMemory.cpp
index cca8f81..bd974b0 100644
--- a/libs/binder/IMemory.cpp
+++ b/libs/binder/IMemory.cpp
@@ -68,7 +68,7 @@
     // TODO: Reimplemement based on standard C++ container?
 };
 
-static sp<HeapCache> gHeapCache = new HeapCache();
+static sp<HeapCache> gHeapCache = sp<HeapCache>::make();
 
 /******************************************************************************/
 
@@ -288,7 +288,7 @@
     int32_t heapId = mHeapId.load(memory_order_acquire);
     if (heapId == -1) {
         sp<IBinder> binder(IInterface::asBinder(const_cast<BpMemoryHeap*>(this)));
-        sp<BpMemoryHeap> heap(static_cast<BpMemoryHeap*>(find_heap(binder).get()));
+        sp<BpMemoryHeap> heap = sp<BpMemoryHeap>::cast(find_heap(binder));
         heap->assertReallyMapped();
         if (heap->mBase != MAP_FAILED) {
             Mutex::Autolock _l(mLock);
diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp
index ca067e2..61f4581 100644
--- a/libs/binder/IServiceManager.cpp
+++ b/libs/binder/IServiceManager.cpp
@@ -102,7 +102,7 @@
             }
         }
 
-        gDefaultServiceManager = new ServiceManagerShim(sm);
+        gDefaultServiceManager = sp<ServiceManagerShim>::make(sm);
     });
 
     return gDefaultServiceManager;
@@ -324,7 +324,7 @@
     }
     if (out != nullptr) return out;
 
-    sp<Waiter> waiter = new Waiter;
+    sp<Waiter> waiter = sp<Waiter>::make();
     if (!mTheRealServiceManager->registerForNotifications(
             name, waiter).isOk()) {
         return nullptr;
diff --git a/libs/binder/LazyServiceRegistrar.cpp b/libs/binder/LazyServiceRegistrar.cpp
index f96b6bb..b503beb 100644
--- a/libs/binder/LazyServiceRegistrar.cpp
+++ b/libs/binder/LazyServiceRegistrar.cpp
@@ -129,7 +129,9 @@
     }
 
     if (!reRegister) {
-        if(!manager->registerClientCallback(name, service, this).isOk()) {
+        if (!manager->registerClientCallback(name, service,
+                                             sp<android::os::IClientCallback>::fromExisting(this))
+                     .isOk()) {
             ALOGE("Failed to add client callback for service %s", name.c_str());
             return false;
         }
diff --git a/libs/binder/MemoryDealer.cpp b/libs/binder/MemoryDealer.cpp
index b46b3e8..c4475c7 100644
--- a/libs/binder/MemoryDealer.cpp
+++ b/libs/binder/MemoryDealer.cpp
@@ -228,10 +228,8 @@
 // ----------------------------------------------------------------------------
 
 MemoryDealer::MemoryDealer(size_t size, const char* name, uint32_t flags)
-    : mHeap(new MemoryHeapBase(size, flags, name)),
-    mAllocator(new SimpleBestFitAllocator(size))
-{    
-}
+      : mHeap(sp<MemoryHeapBase>::make(size, flags, name)),
+        mAllocator(new SimpleBestFitAllocator(size)) {}
 
 MemoryDealer::~MemoryDealer()
 {
@@ -243,7 +241,7 @@
     sp<IMemory> memory;
     const ssize_t offset = allocator()->allocate(size);
     if (offset >= 0) {
-        memory = new Allocation(this, heap(), offset, size);
+        memory = sp<Allocation>::make(sp<MemoryDealer>::fromExisting(this), heap(), offset, size);
     }
     return memory;
 }
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 4cf4814..a735309 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -293,7 +293,8 @@
     if (flat) {
         switch (flat->hdr.type) {
             case BINDER_TYPE_BINDER: {
-                sp<IBinder> binder = reinterpret_cast<IBinder*>(flat->cookie);
+                sp<IBinder> binder =
+                        sp<IBinder>::fromExisting(reinterpret_cast<IBinder*>(flat->cookie));
                 return finishUnflattenBinder(binder, out);
             }
             case BINDER_TYPE_HANDLE: {
@@ -418,6 +419,11 @@
 
 status_t Parcel::appendFrom(const Parcel *parcel, size_t offset, size_t len)
 {
+    if (parcel->isForRpc() != isForRpc()) {
+        ALOGE("Cannot append Parcel of one format to another.");
+        return BAD_TYPE;
+    }
+
     status_t err;
     const uint8_t *data = parcel->mData;
     const binder_size_t *objects = parcel->mObjects;
diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp
index abb792e..7647a8c 100644
--- a/libs/binder/ProcessState.cpp
+++ b/libs/binder/ProcessState.cpp
@@ -105,7 +105,7 @@
         }
 
         std::lock_guard<std::mutex> l(gProcessMutex);
-        gProcess = new ProcessState(driver);
+        gProcess = sp<ProcessState>::make(driver);
     });
 
     if (requireDefault) {
@@ -299,8 +299,8 @@
                    return nullptr;
             }
 
-            b = BpBinder::create(handle);
-            e->binder = b;
+            sp<BpBinder> b = BpBinder::create(handle);
+            e->binder = b.get();
             if (b) e->refs = b->getWeakRefs();
             result = b;
         } else {
@@ -340,7 +340,7 @@
     if (mThreadPoolStarted) {
         String8 name = makeBinderThreadName();
         ALOGV("Spawning new pooled thread, name=%s\n", name.string());
-        sp<Thread> t = new PoolThread(isMain);
+        sp<Thread> t = sp<PoolThread>::make(isMain);
         t->run(name.string());
     }
 }
diff --git a/libs/binder/RpcConnection.cpp b/libs/binder/RpcConnection.cpp
index dab3246..1bf3d88 100644
--- a/libs/binder/RpcConnection.cpp
+++ b/libs/binder/RpcConnection.cpp
@@ -54,7 +54,7 @@
 }
 
 sp<RpcConnection> RpcConnection::make() {
-    return new RpcConnection;
+    return sp<RpcConnection>::make();
 }
 
 class UnixSocketAddress : public RpcConnection::SocketAddress {
@@ -120,20 +120,21 @@
 #endif // __BIONIC__
 
 sp<IBinder> RpcConnection::getRootObject() {
-    ExclusiveSocket socket(this, SocketUse::CLIENT);
-    return state()->getRootObject(socket.fd(), this);
+    ExclusiveSocket socket(sp<RpcConnection>::fromExisting(this), SocketUse::CLIENT);
+    return state()->getRootObject(socket.fd(), sp<RpcConnection>::fromExisting(this));
 }
 
 status_t RpcConnection::transact(const RpcAddress& address, uint32_t code, const Parcel& data,
                                  Parcel* reply, uint32_t flags) {
-    ExclusiveSocket socket(this,
+    ExclusiveSocket socket(sp<RpcConnection>::fromExisting(this),
                            (flags & IBinder::FLAG_ONEWAY) ? SocketUse::CLIENT_ASYNC
                                                           : SocketUse::CLIENT);
-    return state()->transact(socket.fd(), address, code, data, this, reply, flags);
+    return state()->transact(socket.fd(), address, code, data,
+                             sp<RpcConnection>::fromExisting(this), reply, flags);
 }
 
 status_t RpcConnection::sendDecStrong(const RpcAddress& address) {
-    ExclusiveSocket socket(this, SocketUse::CLIENT_REFCOUNT);
+    ExclusiveSocket socket(sp<RpcConnection>::fromExisting(this), SocketUse::CLIENT_REFCOUNT);
     return state()->sendDecStrong(socket.fd(), address);
 }
 
@@ -157,10 +158,11 @@
     // We may not use the connection we just established (two threads might
     // establish connections for each other), but for now, just use one
     // server/socket connection.
-    ExclusiveSocket socket(this, SocketUse::SERVER);
+    ExclusiveSocket socket(sp<RpcConnection>::fromExisting(this), SocketUse::SERVER);
 
     while (true) {
-        status_t error = state()->getAndExecuteCommand(socket.fd(), this);
+        status_t error =
+                state()->getAndExecuteCommand(socket.fd(), sp<RpcConnection>::fromExisting(this));
 
         if (error != OK) {
             ALOGI("Binder socket thread closing w/ status %s", statusToString(error).c_str());
@@ -221,7 +223,7 @@
     LOG_RPC_DETAIL("Socket at %s client with fd %d", addr.toString().c_str(), serverFd.get());
 
     std::lock_guard<std::mutex> _l(mSocketMutex);
-    sp<ConnectionSocket> connection = new ConnectionSocket();
+    sp<ConnectionSocket> connection = sp<ConnectionSocket>::make();
     connection->fd = std::move(serverFd);
     mClients.push_back(connection);
     return true;
@@ -229,7 +231,7 @@
 
 void RpcConnection::assignServerToThisThread(base::unique_fd&& fd) {
     std::lock_guard<std::mutex> _l(mSocketMutex);
-    sp<ConnectionSocket> connection = new ConnectionSocket();
+    sp<ConnectionSocket> connection = sp<ConnectionSocket>::make();
     connection->fd = std::move(fd);
     mServers.push_back(connection);
 }
diff --git a/libs/binder/RpcServer.cpp b/libs/binder/RpcServer.cpp
index df07916..1fa37ba 100644
--- a/libs/binder/RpcServer.cpp
+++ b/libs/binder/RpcServer.cpp
@@ -36,7 +36,7 @@
 RpcServer::~RpcServer() {}
 
 sp<RpcServer> RpcServer::make() {
-    return new RpcServer;
+    return sp<RpcServer>::make();
 }
 
 void RpcServer::iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction() {
@@ -47,7 +47,7 @@
     LOG_ALWAYS_FATAL_IF(!mAgreedExperimental, "no!");
 
     auto connection = RpcConnection::make();
-    connection->setForServer(this);
+    connection->setForServer(sp<RpcServer>::fromExisting(this));
     mConnections.push_back(connection);
     return connection;
 }
diff --git a/libs/binder/include/binder/AppOpsManager.h b/libs/binder/include/binder/AppOpsManager.h
index be6667d..c048cbe 100644
--- a/libs/binder/include/binder/AppOpsManager.h
+++ b/libs/binder/include/binder/AppOpsManager.h
@@ -144,7 +144,9 @@
         OP_MANAGE_MEDIA = 110,
         OP_BLUETOOTH_CONNECT = 111,
         OP_UWB_RANGING = 112,
-        _NUM_OP = 113
+        OP_ACTIVITY_RECOGNITION_SOURCE = 113,
+        OP_BLUETOOTH_ADVERTISE = 114,
+        _NUM_OP = 115
     };
 
     AppOpsManager();
diff --git a/libs/binder/include/binder/Binder.h b/libs/binder/include/binder/Binder.h
index 7079544..7e9be41 100644
--- a/libs/binder/include/binder/Binder.h
+++ b/libs/binder/include/binder/Binder.h
@@ -131,8 +131,8 @@
     virtual void            onLastStrongRef(const void* id);
     virtual bool            onIncStrongAttempted(uint32_t flags, const void* id);
 
-    inline  IBinder*        remote()                { return mRemote; }
-    inline  IBinder*        remote() const          { return mRemote; }
+    inline IBinder* remote() const { return mRemote; }
+    inline sp<IBinder> remoteStrong() const { return sp<IBinder>::fromExisting(mRemote); }
 
 private:
                             BpRefBase(const BpRefBase& o);
diff --git a/libs/binder/include/binder/BpBinder.h b/libs/binder/include/binder/BpBinder.h
index 8ab7893..ad618f9 100644
--- a/libs/binder/include/binder/BpBinder.h
+++ b/libs/binder/include/binder/BpBinder.h
@@ -40,8 +40,8 @@
 class BpBinder : public IBinder
 {
 public:
-    static BpBinder*    create(int32_t handle);
-    static BpBinder* create(const sp<RpcConnection>& connection, const RpcAddress& address);
+    static sp<BpBinder> create(int32_t handle);
+    static sp<BpBinder> create(const sp<RpcConnection>& connection, const RpcAddress& address);
 
     /**
      * Return value:
@@ -143,6 +143,7 @@
 
 private:
     friend PrivateAccessorForId;
+    friend class sp<BpBinder>;
 
     struct BinderHandle {
         int32_t handle;
diff --git a/libs/binder/include/binder/IInterface.h b/libs/binder/include/binder/IInterface.h
index b86fc0b..ff90b30 100644
--- a/libs/binder/include/binder/IInterface.h
+++ b/libs/binder/include/binder/IInterface.h
@@ -143,11 +143,10 @@
     {                                                                   \
         ::android::sp<I##INTERFACE> intr;                               \
         if (obj != nullptr) {                                           \
-            intr = static_cast<I##INTERFACE*>(                          \
-                obj->queryLocalInterface(                               \
-                        I##INTERFACE::descriptor).get());               \
+            intr = ::android::sp<I##INTERFACE>::cast(                   \
+                obj->queryLocalInterface(I##INTERFACE::descriptor));    \
             if (intr == nullptr) {                                      \
-                intr = new Bp##INTERFACE(obj);                          \
+                intr = ::android::sp<Bp##INTERFACE>::make(obj);         \
             }                                                           \
         }                                                               \
         return intr;                                                    \
diff --git a/libs/binder/include/binder/ProcessState.h b/libs/binder/include/binder/ProcessState.h
index ca29440..0919648 100644
--- a/libs/binder/include/binder/ProcessState.h
+++ b/libs/binder/include/binder/ProcessState.h
@@ -88,7 +88,8 @@
     static  sp<ProcessState>    init(const char *defaultDriver, bool requireDefault);
 
     friend class IPCThreadState;
-    
+    friend class sp<ProcessState>;
+
             explicit            ProcessState(const char* driver);
                                 ~ProcessState();
 
diff --git a/libs/binder/include/binder/RpcServer.h b/libs/binder/include/binder/RpcServer.h
index a2c2aee..d29b651 100644
--- a/libs/binder/include/binder/RpcServer.h
+++ b/libs/binder/include/binder/RpcServer.h
@@ -72,6 +72,7 @@
     ~RpcServer();
 
 private:
+    friend sp<RpcServer>;
     RpcServer();
 
     bool mAgreedExperimental = false;
diff --git a/libs/binder/include/binder/ActivityManager.h b/libs/binder/include_activitymanager/binder/ActivityManager.h
similarity index 93%
rename from libs/binder/include/binder/ActivityManager.h
rename to libs/binder/include_activitymanager/binder/ActivityManager.h
index 830971b..b772b80 100644
--- a/libs/binder/include/binder/ActivityManager.h
+++ b/libs/binder/include_activitymanager/binder/ActivityManager.h
@@ -41,7 +41,11 @@
         // Flag for registerUidObserver: report uid has become idle
         UID_OBSERVER_IDLE = 1<<2,
         // Flag for registerUidObserver: report uid has become active
-        UID_OBSERVER_ACTIVE = 1<<3
+        UID_OBSERVER_ACTIVE = 1<<3,
+        // Flag for registerUidObserver: report uid cached state has changed
+        UID_OBSERVER_CACHED = 1<<4,
+        // Flag for registerUidObserver: report uid capability has changed
+        UID_OBSERVER_CAPABILITY = 1<<5,
     };
 
     // PROCESS_STATE_* must come from frameworks/base/core/java/android/app/ProcessStateEnum.aidl.
diff --git a/libs/binder/include/binder/IActivityManager.h b/libs/binder/include_activitymanager/binder/IActivityManager.h
similarity index 99%
rename from libs/binder/include/binder/IActivityManager.h
rename to libs/binder/include_activitymanager/binder/IActivityManager.h
index 2d58c46..4632b2e 100644
--- a/libs/binder/include/binder/IActivityManager.h
+++ b/libs/binder/include_activitymanager/binder/IActivityManager.h
@@ -18,8 +18,8 @@
 
 #ifndef __ANDROID_VNDK__
 
-#include <binder/IInterface.h>
 #include <binder/IUidObserver.h>
+#include <binder/IInterface.h>
 
 namespace android {
 
diff --git a/libs/binder/include/binder/IUidObserver.h b/libs/binder/include_activitymanager/binder/IUidObserver.h
similarity index 100%
rename from libs/binder/include/binder/IUidObserver.h
rename to libs/binder/include_activitymanager/binder/IUidObserver.h
diff --git a/libs/binder/ndk/ibinder.cpp b/libs/binder/ndk/ibinder.cpp
index 3e6c39f..1dcb41b 100644
--- a/libs/binder/ndk/ibinder.cpp
+++ b/libs/binder/ndk/ibinder.cpp
@@ -363,7 +363,8 @@
 }
 
 void AIBinder_DeathRecipient::TransferDeathRecipient::binderDied(const wp<IBinder>& who) {
-    CHECK(who == mWho);
+    CHECK(who == mWho) << who.unsafe_get() << "(" << who.get_refs() << ") vs " << mWho.unsafe_get()
+                       << " (" << mWho.get_refs() << ")";
 
     mOnDied(mCookie);
 
diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp
index 985d086..a51c987 100644
--- a/libs/binder/tests/binderRpcTest.cpp
+++ b/libs/binder/tests/binderRpcTest.cpp
@@ -406,6 +406,19 @@
     EXPECT_EQ(BAD_TYPE, proc.rootBinder->transact(IBinder::PING_TRANSACTION, data, &reply, 0));
 }
 
+TEST_P(BinderRpc, AppendSeparateFormats) {
+    auto proc = createRpcTestSocketServerProcess(1);
+
+    Parcel p1;
+    p1.markForBinder(proc.rootBinder);
+    p1.writeInt32(3);
+
+    Parcel p2;
+
+    EXPECT_EQ(BAD_TYPE, p1.appendFrom(&p2, 0, p2.dataSize()));
+    EXPECT_EQ(BAD_TYPE, p2.appendFrom(&p1, 0, p1.dataSize()));
+}
+
 TEST_P(BinderRpc, UnknownTransaction) {
     auto proc = createRpcTestSocketServerProcess(1);
     Parcel data;
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index ff059d7..64203f7 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -39,12 +39,50 @@
     min_sdk_version: "29",
 }
 
+cc_library_headers {
+    name: "libgui_aidl_headers",
+    vendor_available: true,
+    static_libs: [
+        "libgui_aidl_static",
+    ],
+
+    export_static_lib_headers: [
+        "libgui_aidl_static",
+    ],
+}
+
 filegroup {
     name: "libgui_aidl",
     srcs: ["aidl/**/*.aidl"],
     path: "aidl/",
 }
 
+cc_library_static {
+    name: "libgui_aidl_static",
+    vendor_available: true,
+    srcs: [
+        ":libgui_aidl",
+    ],
+
+    shared_libs: [
+        "libbinder",
+        "libui",
+    ],
+
+    local_include_dirs: [
+        "include",
+    ],
+
+    export_shared_lib_headers: [
+        "libbinder",
+    ],
+
+    aidl: {
+        export_aidl_headers: true
+    }
+}
+
+
 cc_library_shared {
     name: "libgui",
     vendor_available: true,
@@ -56,10 +94,16 @@
 
     defaults: ["libgui_bufferqueue-defaults"],
 
+    static_libs: [
+        "libgui_aidl_static",
+    ],
+    export_static_lib_headers: [
+        "libgui_aidl_static",
+    ],
+
     srcs: [
         ":framework_native_aidl",
         ":inputconstants_aidl",
-        ":libgui_aidl",
         ":libgui_bufferqueue_sources",
 
         "BitTube.cpp",
@@ -115,6 +159,10 @@
         "libinput",
     ],
 
+    export_header_lib_headers: [
+        "libgui_aidl_headers",
+    ],
+
     // bufferhub is not used when building libgui for vendors
     target: {
         vendor: {
@@ -136,15 +184,16 @@
         },
     },
 
-    header_libs: [
-        "libdvr_headers",
-        "libpdx_headers",
-    ],
-
     aidl: {
         export_aidl_headers: true,
     },
 
+    header_libs: [
+        "libdvr_headers",
+        "libgui_aidl_headers",
+        "libpdx_headers",
+    ],
+
     pgo: {
         sampling: true,
         profile_file: "libgui/libgui.profdata",
@@ -175,8 +224,8 @@
 
     srcs: [
         ":inputconstants_aidl",
-        ":libgui_aidl",
         ":libgui_bufferqueue_sources",
+        ":libgui_aidl",
     ],
 }
 
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/DisplayEventDispatcher.cpp b/libs/gui/DisplayEventDispatcher.cpp
index 9cd3f63..e1b1efc 100644
--- a/libs/gui/DisplayEventDispatcher.cpp
+++ b/libs/gui/DisplayEventDispatcher.cpp
@@ -152,6 +152,7 @@
                     *outCount = ev.vsync.count;
                     outVsyncEventData->id = ev.vsync.vsyncId;
                     outVsyncEventData->deadlineTimestamp = ev.vsync.deadlineTimestamp;
+                    outVsyncEventData->frameInterval = ev.vsync.frameInterval;
                     break;
                 case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG:
                     dispatchHotplug(ev.header.timestamp, ev.header.displayId, ev.hotplug.connected);
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index 2a9a97e..55ed7fe 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -45,7 +45,6 @@
         reserved(0),
         cornerRadius(0.0f),
         backgroundBlurRadius(0),
-        barrierFrameNumber(0),
         transform(0),
         transformToDisplayInverse(false),
         crop(Rect::INVALID_RECT),
@@ -87,9 +86,7 @@
     SAFE_PARCEL(output.writeUint32, mask);
     SAFE_PARCEL(matrix.write, output);
     SAFE_PARCEL(output.write, crop);
-    SAFE_PARCEL(SurfaceControl::writeNullableToParcel, output, barrierSurfaceControl_legacy);
     SAFE_PARCEL(SurfaceControl::writeNullableToParcel, output, reparentSurfaceControl);
-    SAFE_PARCEL(output.writeUint64, barrierFrameNumber);
     SAFE_PARCEL(SurfaceControl::writeNullableToParcel, output, relativeLayerSurfaceControl);
     SAFE_PARCEL(SurfaceControl::writeNullableToParcel, output, parentSurfaceControlForChild);
     SAFE_PARCEL(output.writeFloat, color.r);
@@ -193,9 +190,7 @@
 
     SAFE_PARCEL(matrix.read, input);
     SAFE_PARCEL(input.read, crop);
-    SAFE_PARCEL(SurfaceControl::readNullableFromParcel, input, &barrierSurfaceControl_legacy);
     SAFE_PARCEL(SurfaceControl::readNullableFromParcel, input, &reparentSurfaceControl);
-    SAFE_PARCEL(input.readUint64, &barrierFrameNumber);
 
     SAFE_PARCEL(SurfaceControl::readNullableFromParcel, input, &relativeLayerSurfaceControl);
     SAFE_PARCEL(SurfaceControl::readNullableFromParcel, input, &parentSurfaceControlForChild);
@@ -425,15 +420,6 @@
         what |= eBlurRegionsChanged;
         blurRegions = other.blurRegions;
     }
-    if (other.what & eDeferTransaction_legacy) {
-        what |= eDeferTransaction_legacy;
-        barrierSurfaceControl_legacy = other.barrierSurfaceControl_legacy;
-        barrierFrameNumber = other.barrierFrameNumber;
-    }
-    if (other.what & eReparentChildren) {
-        what |= eReparentChildren;
-        reparentSurfaceControl = other.reparentSurfaceControl;
-    }
     if (other.what & eRelativeLayerChanged) {
         what |= eRelativeLayerChanged;
         what &= ~eLayerChanged;
@@ -459,10 +445,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 879955b..e6baba6 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -1140,37 +1140,6 @@
     return *this;
 }
 
-SurfaceComposerClient::Transaction&
-SurfaceComposerClient::Transaction::deferTransactionUntil_legacy(
-        const sp<SurfaceControl>& sc, const sp<SurfaceControl>& barrierSurfaceControl,
-        uint64_t frameNumber) {
-    layer_state_t* s = getLayerState(sc);
-    if (!s) {
-        mStatus = BAD_INDEX;
-        return *this;
-    }
-    s->what |= layer_state_t::eDeferTransaction_legacy;
-    s->barrierSurfaceControl_legacy = barrierSurfaceControl;
-    s->barrierFrameNumber = frameNumber;
-
-    registerSurfaceControlForCallback(sc);
-    return *this;
-}
-
-SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::reparentChildren(
-        const sp<SurfaceControl>& sc, const sp<SurfaceControl>& newParent) {
-    layer_state_t* s = getLayerState(sc);
-    if (!s) {
-        mStatus = BAD_INDEX;
-        return *this;
-    }
-    s->what |= layer_state_t::eReparentChildren;
-    s->reparentSurfaceControl = newParent;
-
-    registerSurfaceControlForCallback(sc);
-    return *this;
-}
-
 SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::reparent(
         const sp<SurfaceControl>& sc, const sp<SurfaceControl>& newParent) {
     layer_state_t* s = getLayerState(sc);
@@ -1246,20 +1215,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/DisplayEventDispatcher.h b/libs/gui/include/gui/DisplayEventDispatcher.h
index d74c2ba..4ade240 100644
--- a/libs/gui/include/gui/DisplayEventDispatcher.h
+++ b/libs/gui/include/gui/DisplayEventDispatcher.h
@@ -30,6 +30,9 @@
     // The deadline in CLOCK_MONOTONIC that the app needs to complete its
     // frame by (both on the CPU and the GPU)
     int64_t deadlineTimestamp = std::numeric_limits<int64_t>::max();
+
+    // The current frame interval in ns when this frame was scheduled.
+    int64_t frameInterval = 0;
 };
 
 class DisplayEventDispatcher : public LooperCallback {
diff --git a/libs/gui/include/gui/DisplayEventReceiver.h b/libs/gui/include/gui/DisplayEventReceiver.h
index 7179a20..0dffbde 100644
--- a/libs/gui/include/gui/DisplayEventReceiver.h
+++ b/libs/gui/include/gui/DisplayEventReceiver.h
@@ -75,6 +75,7 @@
             uint32_t count;
             nsecs_t expectedVSyncTimestamp __attribute__((aligned(8)));
             nsecs_t deadlineTimestamp __attribute__((aligned(8)));
+            nsecs_t frameInterval __attribute__((aligned(8)));
             int64_t vsyncId;
         };
 
diff --git a/libs/gui/include/gui/FrameTimelineInfo.h b/libs/gui/include/gui/FrameTimelineInfo.h
index 3b4c009..a23c202 100644
--- a/libs/gui/include/gui/FrameTimelineInfo.h
+++ b/libs/gui/include/gui/FrameTimelineInfo.h
@@ -18,7 +18,6 @@
 
 #include <stdint.h>
 
-#include <android/os/IInputConstants.h>
 #include <binder/Parcel.h>
 
 namespace android {
@@ -31,7 +30,11 @@
     int64_t vsyncId = INVALID_VSYNC_ID;
 
     // The id of the input event that caused this buffer
-    int32_t inputEventId = android::os::IInputConstants::INVALID_INPUT_EVENT_ID;
+    // Default is android::os::IInputConstants::INVALID_INPUT_EVENT_ID = 0
+    // We copy the value of the input event ID instead of including the header, because libgui
+    // header libraries containing FrameTimelineInfo must be available to vendors, but libinput is
+    // not directly vendor available.
+    int32_t inputEventId = 0;
 
     status_t write(Parcel& output) const;
     status_t read(const Parcel& input);
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index 6c265c8..d2d1e5b 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -82,11 +82,8 @@
         eTransparentRegionChanged = 0x00000020,
         eFlagsChanged = 0x00000040,
         eLayerStackChanged = 0x00000080,
-        /* was eCropChanged_legacy, now available 0x00000100, */
-        eDeferTransaction_legacy = 0x00000200,
         eReleaseBufferListenerChanged = 0x00000400,
         eShadowRadiusChanged = 0x00000800,
-        eReparentChildren = 0x00001000,
         /* was eDetachChildren, now available 0x00002000, */
         eRelativeLayerChanged = 0x00004000,
         eReparent = 0x00008000,
@@ -106,7 +103,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,
@@ -153,9 +150,7 @@
     matrix22_t matrix;
     float cornerRadius;
     uint32_t backgroundBlurRadius;
-    sp<SurfaceControl> barrierSurfaceControl_legacy;
     sp<SurfaceControl> reparentSurfaceControl;
-    uint64_t barrierFrameNumber;
 
     sp<SurfaceControl> relativeLayerSurfaceControl;
 
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 7ec5d8d..fe6a30a 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -454,20 +454,8 @@
                                     const std::vector<BlurRegion>& regions);
         Transaction& setLayerStack(const sp<SurfaceControl>& sc, uint32_t layerStack);
         Transaction& setMetadata(const sp<SurfaceControl>& sc, uint32_t key, const Parcel& p);
-        // Defers applying any changes made in this transaction until the Layer
-        // identified by handle reaches the given frameNumber. If the Layer identified
-        // by handle is removed, then we will apply this transaction regardless of
-        // what frame number has been reached.
-        Transaction& deferTransactionUntil_legacy(const sp<SurfaceControl>& sc,
-                                                  const sp<SurfaceControl>& barrierSurfaceControl,
-                                                  uint64_t frameNumber);
-        // Reparents all children of this layer to the new parent handle.
-        Transaction& reparentChildren(const sp<SurfaceControl>& sc,
-                                      const sp<SurfaceControl>& newParent);
 
         /// Reparents the current layer to the new parent handle. The new parent must not be null.
-        // This can be used instead of reparentChildren if the caller wants to
-        // only re-parent a specific child.
         Transaction& reparent(const sp<SurfaceControl>& sc, const sp<SurfaceControl>& newParent);
 
         Transaction& setColor(const sp<SurfaceControl>& sc, const half3& color);
@@ -479,7 +467,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/gui/tests/DisplayEventStructLayout_test.cpp b/libs/gui/tests/DisplayEventStructLayout_test.cpp
index 7dbba31..bcd39db 100644
--- a/libs/gui/tests/DisplayEventStructLayout_test.cpp
+++ b/libs/gui/tests/DisplayEventStructLayout_test.cpp
@@ -34,7 +34,8 @@
     CHECK_OFFSET(DisplayEventReceiver::Event::VSync, count, 0);
     CHECK_OFFSET(DisplayEventReceiver::Event::VSync, expectedVSyncTimestamp, 8);
     CHECK_OFFSET(DisplayEventReceiver::Event::VSync, deadlineTimestamp, 16);
-    CHECK_OFFSET(DisplayEventReceiver::Event::VSync, vsyncId, 24);
+    CHECK_OFFSET(DisplayEventReceiver::Event::VSync, frameInterval, 24);
+    CHECK_OFFSET(DisplayEventReceiver::Event::VSync, vsyncId, 32);
 
     CHECK_OFFSET(DisplayEventReceiver::Event::Hotplug, connected, 0);
 
diff --git a/libs/gui/tests/EndToEndNativeInputTest.cpp b/libs/gui/tests/EndToEndNativeInputTest.cpp
index 59e5c13..49c44a7 100644
--- a/libs/gui/tests/EndToEndNativeInputTest.cpp
+++ b/libs/gui/tests/EndToEndNativeInputTest.cpp
@@ -47,6 +47,8 @@
 
 using android::os::IInputFlinger;
 
+using android::hardware::graphics::common::V1_1::BufferUsage;
+
 namespace android::test {
 
 using Transaction = SurfaceComposerClient::Transaction;
@@ -95,15 +97,6 @@
         return std::make_unique<InputSurface>(surfaceControl, width, height);
     }
 
-    static std::unique_ptr<InputSurface> makeBlastInputSurface(const sp<SurfaceComposerClient> &scc,
-                                                               int width, int height) {
-        sp<SurfaceControl> surfaceControl =
-                scc->createSurface(String8("Test Buffer Surface"), width, height,
-                                   PIXEL_FORMAT_RGBA_8888,
-                                   ISurfaceComposerClient::eFXSurfaceBufferState);
-        return std::make_unique<InputSurface>(surfaceControl, width, height);
-    }
-
     static std::unique_ptr<InputSurface> makeContainerInputSurface(
             const sp<SurfaceComposerClient> &scc, int width, int height) {
         sp<SurfaceControl> surfaceControl =
@@ -180,16 +173,19 @@
         EXPECT_EQ(flags, mev->getFlags() & flags);
     }
 
-    ~InputSurface() { mInputFlinger->removeInputChannel(mClientChannel->getConnectionToken()); }
+    virtual ~InputSurface() {
+        mInputFlinger->removeInputChannel(mClientChannel->getConnectionToken());
+    }
 
-    void doTransaction(std::function<void(SurfaceComposerClient::Transaction&,
-                    const sp<SurfaceControl>&)> transactionBody) {
+    virtual void doTransaction(
+            std::function<void(SurfaceComposerClient::Transaction &, const sp<SurfaceControl> &)>
+                    transactionBody) {
         SurfaceComposerClient::Transaction t;
         transactionBody(t, mSurfaceControl);
         t.apply(true);
     }
 
-    void showAt(int x, int y, Rect crop = Rect(0, 0, 100, 100)) {
+    virtual void showAt(int x, int y, Rect crop = Rect(0, 0, 100, 100)) {
         SurfaceComposerClient::Transaction t;
         t.show(mSurfaceControl);
         t.setInputWindowInfo(mSurfaceControl, mInputInfo);
@@ -259,6 +255,57 @@
     InputConsumer* mInputConsumer;
 };
 
+class BlastInputSurface : public InputSurface {
+public:
+    BlastInputSurface(const sp<SurfaceControl> &sc, const sp<SurfaceControl> &parentSc, int width,
+                      int height)
+          : InputSurface(sc, width, height) {
+        mParentSurfaceControl = parentSc;
+    }
+
+    ~BlastInputSurface() = default;
+
+    static std::unique_ptr<BlastInputSurface> makeBlastInputSurface(
+            const sp<SurfaceComposerClient> &scc, int width, int height) {
+        sp<SurfaceControl> parentSc =
+                scc->createSurface(String8("Test Parent Surface"), 0 /* bufHeight */,
+                                   0 /* bufWidth */, PIXEL_FORMAT_RGBA_8888,
+                                   ISurfaceComposerClient::eFXSurfaceContainer);
+
+        sp<SurfaceControl> surfaceControl =
+                scc->createSurface(String8("Test Buffer Surface"), width, height,
+                                   PIXEL_FORMAT_RGBA_8888,
+                                   ISurfaceComposerClient::eFXSurfaceBufferState,
+                                   parentSc->getHandle());
+        return std::make_unique<BlastInputSurface>(surfaceControl, parentSc, width, height);
+    }
+
+    void doTransaction(
+            std::function<void(SurfaceComposerClient::Transaction &, const sp<SurfaceControl> &)>
+                    transactionBody) override {
+        SurfaceComposerClient::Transaction t;
+        transactionBody(t, mParentSurfaceControl);
+        t.apply(true);
+    }
+
+    void showAt(int x, int y, Rect crop = Rect(0, 0, 100, 100)) override {
+        SurfaceComposerClient::Transaction t;
+        t.show(mParentSurfaceControl);
+        t.setLayer(mParentSurfaceControl, LAYER_BASE);
+        t.setPosition(mParentSurfaceControl, x, y);
+        t.setCrop(mParentSurfaceControl, crop);
+
+        t.show(mSurfaceControl);
+        t.setInputWindowInfo(mSurfaceControl, mInputInfo);
+        t.setCrop(mSurfaceControl, crop);
+        t.setAlpha(mSurfaceControl, 1);
+        t.apply(true);
+    }
+
+private:
+    sp<SurfaceControl> mParentSurfaceControl;
+};
+
 class InputSurfacesTest : public ::testing::Test {
 public:
     InputSurfacesTest() {
@@ -289,15 +336,12 @@
         return InputSurface::makeColorInputSurface(mComposerClient, width, height);
     }
 
-    void postBuffer(const sp<SurfaceControl> &layer) {
-        // wait for previous transactions (such as setSize) to complete
-        Transaction().apply(true);
-        ANativeWindow_Buffer buffer = {};
-        EXPECT_EQ(NO_ERROR, layer->getSurface()->lock(&buffer, nullptr));
-        ASSERT_EQ(NO_ERROR, layer->getSurface()->unlockAndPost());
-        // Request an empty transaction to get applied synchronously to ensure the buffer is
-        // latched.
-        Transaction().apply(true);
+    void postBuffer(const sp<SurfaceControl> &layer, int32_t w, int32_t h) {
+        int64_t usageFlags = BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
+                BufferUsage::COMPOSER_OVERLAY | BufferUsage::GPU_TEXTURE;
+        sp<GraphicBuffer> buffer =
+                new GraphicBuffer(w, h, PIXEL_FORMAT_RGBA_8888, 1, usageFlags, "test");
+        Transaction().setBuffer(layer, buffer).apply(true);
         usleep(mBufferPostDelay);
     }
 
@@ -474,8 +518,8 @@
 // Original bug ref: b/120839715
 TEST_F(InputSurfacesTest, input_ignores_buffer_layer_buffer) {
     std::unique_ptr<InputSurface> bgSurface = makeSurface(100, 100);
-    std::unique_ptr<InputSurface> bufferSurface =
-            InputSurface::makeBufferInputSurface(mComposerClient, 100, 100);
+    std::unique_ptr<BlastInputSurface> bufferSurface =
+            BlastInputSurface::makeBlastInputSurface(mComposerClient, 100, 100);
 
     bgSurface->showAt(10, 10);
     bufferSurface->showAt(10, 10);
@@ -483,16 +527,16 @@
     injectTap(11, 11);
     bufferSurface->expectTap(1, 1);
 
-    postBuffer(bufferSurface->mSurfaceControl);
+    postBuffer(bufferSurface->mSurfaceControl, 100, 100);
     injectTap(11, 11);
     bufferSurface->expectTap(1, 1);
 }
 
 TEST_F(InputSurfacesTest, input_ignores_buffer_layer_alpha) {
     std::unique_ptr<InputSurface> bgSurface = makeSurface(100, 100);
-    std::unique_ptr<InputSurface> bufferSurface =
-            InputSurface::makeBufferInputSurface(mComposerClient, 100, 100);
-    postBuffer(bufferSurface->mSurfaceControl);
+    std::unique_ptr<BlastInputSurface> bufferSurface =
+            BlastInputSurface::makeBlastInputSurface(mComposerClient, 100, 100);
+    postBuffer(bufferSurface->mSurfaceControl, 100, 100);
 
     bgSurface->showAt(10, 10);
     bufferSurface->showAt(10, 10);
@@ -720,8 +764,8 @@
 TEST_F(InputSurfacesTest, touch_not_obscured_with_zero_sized_blast) {
     std::unique_ptr<InputSurface> surface = makeSurface(100, 100);
 
-    std::unique_ptr<InputSurface> bufferSurface =
-            InputSurface::makeBlastInputSurface(mComposerClient, 0, 0);
+    std::unique_ptr<BlastInputSurface> bufferSurface =
+            BlastInputSurface::makeBlastInputSurface(mComposerClient, 0, 0);
     bufferSurface->mInputInfo.flags = InputWindowInfo::Flag::NOT_TOUCHABLE;
     bufferSurface->mInputInfo.ownerUid = 22222;
 
diff --git a/libs/nativedisplay/AChoreographer.cpp b/libs/nativedisplay/AChoreographer.cpp
index dc2dd29..0edb213 100644
--- a/libs/nativedisplay/AChoreographer.cpp
+++ b/libs/nativedisplay/AChoreographer.cpp
@@ -130,7 +130,7 @@
     virtual ~Choreographer() override EXCLUDES(gChoreographers.lock);
     int64_t getVsyncId() const;
     int64_t getFrameDeadline() const;
-
+    int64_t getFrameInterval() const;
 
 private:
     Choreographer(const Choreographer&) = delete;
@@ -418,6 +418,10 @@
     return mLastVsyncEventData.deadlineTimestamp;
 }
 
+int64_t Choreographer::getFrameInterval() const {
+    return mLastVsyncEventData.frameInterval;
+}
+
 } // namespace android
 using namespace android;
 
@@ -501,6 +505,10 @@
     return AChoreographer_to_Choreographer(choreographer)->getFrameDeadline();
 }
 
+int64_t AChoreographer_getFrameInterval(const AChoreographer* choreographer) {
+    return AChoreographer_to_Choreographer(choreographer)->getFrameInterval();
+}
+
 } // namespace android
 
 /* Glue for the NDK interface */
diff --git a/libs/nativedisplay/include-private/private/android/choreographer.h b/libs/nativedisplay/include-private/private/android/choreographer.h
index 0f4fd45..7d25ce8 100644
--- a/libs/nativedisplay/include-private/private/android/choreographer.h
+++ b/libs/nativedisplay/include-private/private/android/choreographer.h
@@ -42,6 +42,11 @@
 // value.
 int64_t AChoreographer_getFrameDeadline(const AChoreographer* choreographer);
 
+// Returns the current interval in ns between frames.
+// Client are expected to call this function from their frame callback function.
+// Calling this function from anywhere else will return an undefined value.
+int64_t AChoreographer_getFrameInterval(const AChoreographer* choreographer);
+
 // Trampoline functions allowing libandroid.so to define the NDK symbols without including
 // the entirety of libnativedisplay as a whole static lib. As libnativedisplay
 // maintains global state, libnativedisplay can never be directly statically
diff --git a/libs/nativedisplay/libnativedisplay.map.txt b/libs/nativedisplay/libnativedisplay.map.txt
index fda6a20..9ed4915 100644
--- a/libs/nativedisplay/libnativedisplay.map.txt
+++ b/libs/nativedisplay/libnativedisplay.map.txt
@@ -31,6 +31,7 @@
       android::AChoreographer_signalRefreshRateCallbacks*;
       android::AChoreographer_getVsyncId*;
       android::AChoreographer_getFrameDeadline*;
+      android::AChoreographer_getFrameInterval*;
       android::ADisplay_acquirePhysicalDisplays*;
       android::ADisplay_release*;
       android::ADisplay_getMaxSupportedFps*;
diff --git a/libs/nativewindow/include/android/hardware_buffer.h b/libs/nativewindow/include/android/hardware_buffer.h
index 20a1f74..d93a84c 100644
--- a/libs/nativewindow/include/android/hardware_buffer.h
+++ b/libs/nativewindow/include/android/hardware_buffer.h
@@ -164,45 +164,56 @@
  * Buffer usage flags, specifying how the buffer will be accessed.
  */
 enum AHardwareBuffer_UsageFlags {
-    /// The buffer will never be locked for direct CPU reads using the
-    /// AHardwareBuffer_lock() function. Note that reading the buffer
-    /// using OpenGL or Vulkan functions or memory mappings is still
-    /// allowed.
+    /**
+     * The buffer will never be locked for direct CPU reads using the
+     * AHardwareBuffer_lock() function. Note that reading the buffer
+     * using OpenGL or Vulkan functions or memory mappings is still
+     * allowed.
+     */
     AHARDWAREBUFFER_USAGE_CPU_READ_NEVER        = 0UL,
-    /// The buffer will sometimes be locked for direct CPU reads using
-    /// the AHardwareBuffer_lock() function. Note that reading the
-    /// buffer using OpenGL or Vulkan functions or memory mappings
-    /// does not require the presence of this flag.
+    /**
+     * The buffer will sometimes be locked for direct CPU reads using
+     * the AHardwareBuffer_lock() function. Note that reading the
+     * buffer using OpenGL or Vulkan functions or memory mappings
+     * does not require the presence of this flag.
+     */
     AHARDWAREBUFFER_USAGE_CPU_READ_RARELY       = 2UL,
-    /// The buffer will often be locked for direct CPU reads using
-    /// the AHardwareBuffer_lock() function. Note that reading the
-    /// buffer using OpenGL or Vulkan functions or memory mappings
-    /// does not require the presence of this flag.
+    /**
+     * The buffer will often be locked for direct CPU reads using
+     * the AHardwareBuffer_lock() function. Note that reading the
+     * buffer using OpenGL or Vulkan functions or memory mappings
+     * does not require the presence of this flag.
+     */
     AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN        = 3UL,
-    /// CPU read value mask.
+
+    /** CPU read value mask. */
     AHARDWAREBUFFER_USAGE_CPU_READ_MASK         = 0xFUL,
-
-    /// The buffer will never be locked for direct CPU writes using the
-    /// AHardwareBuffer_lock() function. Note that writing the buffer
-    /// using OpenGL or Vulkan functions or memory mappings is still
-    /// allowed.
+    /**
+     * The buffer will never be locked for direct CPU writes using the
+     * AHardwareBuffer_lock() function. Note that writing the buffer
+     * using OpenGL or Vulkan functions or memory mappings is still
+     * allowed.
+     */
     AHARDWAREBUFFER_USAGE_CPU_WRITE_NEVER       = 0UL << 4,
-    /// The buffer will sometimes be locked for direct CPU writes using
-    /// the AHardwareBuffer_lock() function. Note that writing the
-    /// buffer using OpenGL or Vulkan functions or memory mappings
-    /// does not require the presence of this flag.
+    /**
+     * The buffer will sometimes be locked for direct CPU writes using
+     * the AHardwareBuffer_lock() function. Note that writing the
+     * buffer using OpenGL or Vulkan functions or memory mappings
+     * does not require the presence of this flag.
+     */
     AHARDWAREBUFFER_USAGE_CPU_WRITE_RARELY      = 2UL << 4,
-    /// The buffer will often be locked for direct CPU writes using
-    /// the AHardwareBuffer_lock() function. Note that writing the
-    /// buffer using OpenGL or Vulkan functions or memory mappings
-    /// does not require the presence of this flag.
+    /**
+     * The buffer will often be locked for direct CPU writes using
+     * the AHardwareBuffer_lock() function. Note that writing the
+     * buffer using OpenGL or Vulkan functions or memory mappings
+     * does not require the presence of this flag.
+     */
     AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN       = 3UL << 4,
-    /// CPU write value mask.
+    /** CPU write value mask. */
     AHARDWAREBUFFER_USAGE_CPU_WRITE_MASK        = 0xFUL << 4,
-
-    /// The buffer will be read from by the GPU as a texture.
+    /** The buffer will be read from by the GPU as a texture. */
     AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE     = 1UL << 8,
-    /// The buffer will be written to by the GPU as a framebuffer attachment.
+    /** The buffer will be written to by the GPU as a framebuffer attachment.*/
     AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER       = 1UL << 9,
     /**
      * The buffer will be written to by the GPU as a framebuffer
@@ -237,7 +248,7 @@
      * buffers are expected to behave.
      */
     AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT     = 1UL << 14,
-    /// The buffer will be read by a hardware video encoder.
+    /** The buffer will be read by a hardware video encoder. */
     AHARDWAREBUFFER_USAGE_VIDEO_ENCODE          = 1UL << 16,
     /**
      * The buffer will be used for direct writes from sensors.
diff --git a/libs/nativewindow/include/android/native_window.h b/libs/nativewindow/include/android/native_window.h
index 50e9d53..61b3f94 100644
--- a/libs/nativewindow/include/android/native_window.h
+++ b/libs/nativewindow/include/android/native_window.h
@@ -157,6 +157,7 @@
  * For all of these parameters, if 0 is supplied then the window's base
  * value will come back in force.
  *
+ * \param window pointer to an ANativeWindow object.
  * \param width width of the buffers in pixels.
  * \param height height of the buffers in pixels.
  * \param format one of the AHardwareBuffer_Format constants.
@@ -191,6 +192,7 @@
  *
  * Available since API level 26.
  *
+ * \param window pointer to an ANativeWindow object.
  * \param transform combination of {@link ANativeWindowTransform} flags
  * \return 0 for success, or -EINVAL if \p transform is invalid
  */
@@ -208,6 +210,7 @@
  *
  * Available since API level 28.
  *
+ * \param window pointer to an ANativeWindow object.
  * \param dataSpace data space of all buffers queued after this call.
  * \return 0 for success, -EINVAL if window is invalid or the dataspace is not
  * supported.
@@ -306,6 +309,8 @@
  * valid refresh rate for this device's display - e.g., it's fine to pass 30fps
  * to a device that can only run the display at 60fps.
  *
+ * \param window pointer to an ANativeWindow object.
+ *
  * \param compatibility The frame rate compatibility of this window. The
  * compatibility value may influence the system's choice of display refresh
  * rate. See the ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_* values for more info.
diff --git a/libs/permission/Android.bp b/libs/permission/Android.bp
new file mode 100644
index 0000000..9492bda
--- /dev/null
+++ b/libs/permission/Android.bp
@@ -0,0 +1,5 @@
+// TODO(b/183654927): empty place holder to start moving permission related things out of libbinder
+// (appops, permission controller, etc..)
+cc_library_shared {
+    name: "libpermission",
+}
diff --git a/libs/renderengine/Android.bp b/libs/renderengine/Android.bp
index 026b19a..ec39137 100644
--- a/libs/renderengine/Android.bp
+++ b/libs/renderengine/Android.bp
@@ -91,6 +91,7 @@
         "skia/debug/CaptureTimer.cpp",
         "skia/debug/CommonPool.cpp",
         "skia/debug/SkiaCapture.cpp",
+        "skia/debug/SkiaMemoryReporter.cpp",
         "skia/filters/BlurFilter.cpp",
         "skia/filters/LinearEffect.cpp",
     ],
diff --git a/libs/renderengine/include/renderengine/RenderEngine.h b/libs/renderengine/include/renderengine/RenderEngine.h
index a69d1f0..8dd98c3 100644
--- a/libs/renderengine/include/renderengine/RenderEngine.h
+++ b/libs/renderengine/include/renderengine/RenderEngine.h
@@ -141,7 +141,7 @@
     // do any work.
     virtual bool cleanupPostRender(CleanupMode mode = CleanupMode::CLEAN_OUTPUT_RESOURCES) = 0;
 
-    // queries
+    // queries that are required to be thread safe
     virtual size_t getMaxTextureSize() const = 0;
     virtual size_t getMaxViewportDims() const = 0;
 
@@ -149,8 +149,11 @@
 
     // ----- BEGIN NEW INTERFACE -----
 
+    // queries that are required to be thread safe
     virtual bool isProtected() const = 0;
     virtual bool supportsProtectedContent() const = 0;
+
+    // Attempt to switch RenderEngine into and out of protectedContext mode
     virtual bool useProtectedContext(bool useProtectedContext) = 0;
 
     // Notify RenderEngine of changes to the dimensions of the primary display
@@ -197,7 +200,8 @@
     virtual int getContextPriority() = 0;
 
     // Returns true if blur was requested in the RenderEngineCreationArgs and the implementation
-    // also supports background blur.  If false, no blur will be applied when drawing layers.
+    // also supports background blur.  If false, no blur will be applied when drawing layers. This
+    // query is required to be thread safe.
     virtual bool supportsBackgroundBlur() = 0;
 
     // Returns the current type of RenderEngine instance that was created.
diff --git a/libs/renderengine/skia/AutoBackendTexture.cpp b/libs/renderengine/skia/AutoBackendTexture.cpp
index ae3d88a..c535597 100644
--- a/libs/renderengine/skia/AutoBackendTexture.cpp
+++ b/libs/renderengine/skia/AutoBackendTexture.cpp
@@ -28,19 +28,19 @@
 namespace renderengine {
 namespace skia {
 
-AutoBackendTexture::AutoBackendTexture(GrDirectContext* context, AHardwareBuffer* buffer) {
+AutoBackendTexture::AutoBackendTexture(GrDirectContext* context, AHardwareBuffer* buffer,
+                                       bool isRender) {
     ATRACE_CALL();
     AHardwareBuffer_Desc desc;
     AHardwareBuffer_describe(buffer, &desc);
-    const bool createProtectedImage = 0 != (desc.usage & AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT);
-    const bool isRenderable = 0 != (desc.usage & AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER);
+    bool createProtectedImage = 0 != (desc.usage & AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT);
     GrBackendFormat backendFormat =
             GrAHardwareBufferUtils::GetBackendFormat(context, buffer, desc.format, false);
     mBackendTexture =
             GrAHardwareBufferUtils::MakeBackendTexture(context, buffer, desc.width, desc.height,
                                                        &mDeleteProc, &mUpdateProc, &mImageCtx,
                                                        createProtectedImage, backendFormat,
-                                                       isRenderable);
+                                                       isRender);
     mColorType = GrAHardwareBufferUtils::GetSkColorTypeFromBufferFormat(desc.format);
 }
 
diff --git a/libs/renderengine/skia/AutoBackendTexture.h b/libs/renderengine/skia/AutoBackendTexture.h
index a6f73db..bb75878 100644
--- a/libs/renderengine/skia/AutoBackendTexture.h
+++ b/libs/renderengine/skia/AutoBackendTexture.h
@@ -69,7 +69,7 @@
     };
 
     // Creates a GrBackendTexture whose contents come from the provided buffer.
-    AutoBackendTexture(GrDirectContext* context, AHardwareBuffer* buffer);
+    AutoBackendTexture(GrDirectContext* context, AHardwareBuffer* buffer, bool isRender);
 
     void ref() { mUsageCount++; }
 
diff --git a/libs/renderengine/skia/Cache.cpp b/libs/renderengine/skia/Cache.cpp
index 69c6a09..1db20c0 100644
--- a/libs/renderengine/skia/Cache.cpp
+++ b/libs/renderengine/skia/Cache.cpp
@@ -13,7 +13,6 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 #include "Cache.h"
 #include "AutoBackendTexture.h"
 #include "SkiaRenderEngine.h"
@@ -28,9 +27,24 @@
 
 namespace android::renderengine::skia {
 
+namespace {
 // Warming shader cache, not framebuffer cache.
 constexpr bool kUseFrameBufferCache = false;
 
+// clang-format off
+// Any non-identity matrix will do.
+const auto kScaleAndTranslate = mat4(0.7f,   0.f, 0.f, 0.f,
+                                     0.f,  0.7f, 0.f, 0.f,
+                                     0.f,   0.f, 1.f, 0.f,
+                                   67.3f, 52.2f, 0.f, 1.f);
+// clang-format on
+// When choosing dataspaces below, whether the match the destination or not determined whether
+// a color correction effect is added to the shader. There may be other additional shader details
+// for particular color spaces.
+// TODO(b/184842383) figure out which color related shaders are necessary
+constexpr auto kDestDataSpace = ui::Dataspace::SRGB;
+} // namespace
+
 static void drawShadowLayers(SkiaRenderEngine* renderengine, const DisplaySettings& display,
                              sp<GraphicBuffer> dstBuffer) {
     // Somewhat arbitrary dimensions, but on screen and slightly shorter, based
@@ -51,23 +65,29 @@
                             .lightRadius = 2200.0f,
                             .length = 0.955342f,
                     },
+            // important that this matches dest so the general shadow fragment shader doesn't
+            // have color correction added, and important that it be srgb, so the *vertex* shader
+            // doesn't have color correction added.
+            .sourceDataspace = kDestDataSpace,
     };
 
     auto layers = std::vector<const LayerSettings*>{&layer};
-    // The identity matrix will generate the fast shaders, and the second matrix
-    // (based on one seen while going from dialer to the home screen) will
-    // generate the slower (more general case) version. If we also need a
-    // slow version without color correction, we should use this matrix with
-    // display.outputDataspace set to SRGB.
-    bool identity = true;
-    for (const mat4 transform : { mat4(), mat4(0.728872f,   0.f,          0.f, 0.f,
-                                               0.f,         0.727627f,    0.f, 0.f,
-                                               0.f,         0.f,          1.f, 0.f,
-                                               167.355743f, 1852.257812f, 0.f, 1.f) }) {
-        layer.geometry.positionTransform = transform;
+    // The identity matrix will generate the fast shader
+    renderengine->drawLayers(display, layers, dstBuffer, kUseFrameBufferCache, base::unique_fd(),
+                             nullptr);
+    // This matrix, which has different scales for x and y, will
+    // generate the slower (more general case) version, which has variants for translucent
+    // casters and rounded rects.
+    // clang-format off
+    layer.geometry.positionTransform = mat4(0.7f, 0.f,  0.f, 0.f,
+                                            0.f, 0.8f, 0.f, 0.f,
+                                            0.f, 0.f,  1.f, 0.f,
+                                            0.f, 0.f,  0.f, 1.f);
+    // clang-format on
+    for (auto translucent : {false, true}) {
+        layer.shadow.casterIsTranslucent = translucent;
         renderengine->drawLayers(display, layers, dstBuffer, kUseFrameBufferCache,
                                  base::unique_fd(), nullptr);
-        identity = false;
     }
 }
 
@@ -89,33 +109,25 @@
                                           }},
     };
 
-    // This matrix is based on actual data seen when opening the dialer.
-    //  translate and scale creates new shaders when combined with rounded corners
-    // clang-format off
-    auto scale_and_translate = mat4(.19f,    .0f,  .0f,  .0f,
-                                     .0f,   .19f,  .0f,  .0f,
-                                     .0f,    .0f,  1.f,  .0f,
-                                   169.f, 1527.f,  .0f,  1.f);
-    // clang-format on
+    auto threeCornerRadii = {0.0f, 0.05f, 50.f};
+    auto oneCornerRadius = {50.f};
 
     // Test both drawRect and drawRRect
     auto layers = std::vector<const LayerSettings*>{&layer};
-    for (auto transform : {mat4(), scale_and_translate}) {
-        layer.geometry.positionTransform = transform;
-        // fractional corner radius creates a shader that is used during home button swipe
-        for (float roundedCornersRadius : {0.0f, 0.05f, 500.f}) {
+    for (bool identity : {true, false}) {
+        layer.geometry.positionTransform = identity ? mat4() : kScaleAndTranslate;
+        // Corner radii less than 0.5 creates a special shader. This likely occurs in real usage
+        // due to animating corner radius.
+        // For the non-idenity matrix, only the large corner radius will create a new shader.
+        for (float roundedCornersRadius : identity ? threeCornerRadii : oneCornerRadius) {
             // roundedCornersCrop is always set, but it is this radius that triggers the behavior
             layer.geometry.roundedCornersRadius = roundedCornersRadius;
-            // No need to check UNKNOWN, which is treated as SRGB.
-            for (auto dataspace : {ui::Dataspace::SRGB, ui::Dataspace::DISPLAY_P3}) {
-                layer.sourceDataspace = dataspace;
-                for (bool isOpaque : {true, false}) {
-                    layer.source.buffer.isOpaque = isOpaque;
-                    for (auto alpha : {half(.23999f), half(1.0f)}) {
-                        layer.alpha = alpha;
-                        renderengine->drawLayers(display, layers, dstBuffer, kUseFrameBufferCache,
-                                                 base::unique_fd(), nullptr);
-                    }
+            for (bool isOpaque : {true, false}) {
+                layer.source.buffer.isOpaque = isOpaque;
+                for (auto alpha : {half(.23999f), half(1.0f)}) {
+                    layer.alpha = alpha;
+                    renderengine->drawLayers(display, layers, dstBuffer, kUseFrameBufferCache,
+                                             base::unique_fd(), nullptr);
                 }
             }
         }
@@ -139,11 +151,54 @@
     };
 
     auto layers = std::vector<const LayerSettings*>{&layer};
-    renderengine->drawLayers(display, layers, dstBuffer, kUseFrameBufferCache, base::unique_fd(),
-                             nullptr);
+    for (auto transform : {mat4(), kScaleAndTranslate}) {
+        layer.geometry.positionTransform = transform;
+        for (float roundedCornersRadius : {0.0f, 0.05f, 50.f}) {
+            layer.geometry.roundedCornersRadius = roundedCornersRadius;
+            renderengine->drawLayers(display, layers, dstBuffer, kUseFrameBufferCache,
+                                     base::unique_fd(), nullptr);
+        }
+    }
 }
 
+static void drawBlurLayers(SkiaRenderEngine* renderengine, const DisplaySettings& display,
+                           sp<GraphicBuffer> dstBuffer) {
+    const Rect& displayRect = display.physicalDisplay;
+    FloatRect rect(0, 0, displayRect.width(), displayRect.height());
+    LayerSettings layer{
+            .geometry =
+                    Geometry{
+                            .boundaries = rect,
+                    },
+            .alpha = 1,
+    };
+
+    auto layers = std::vector<const LayerSettings*>{&layer};
+    for (int radius : {9, 60}) {
+        layer.backgroundBlurRadius = radius;
+        renderengine->drawLayers(display, layers, dstBuffer, kUseFrameBufferCache,
+                                 base::unique_fd(), nullptr);
+    }
+}
+
+//
+// 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
+// and reproducing those settings here.
+//
+// It is helpful when debugging this to turn on
+// in SkGLRenderEngine.cpp:
+//    kPrintLayerSettings = true
+//    kFlushAfterEveryLayer = true
+// in external/skia/src/gpu/gl/builders/GrGLShaderStringBuilder.cpp
+//    gPrintSKSL = true
+//
+// TODO(b/184631553) cache the shader involved in youtube pip return.
 void Cache::primeShaderCache(SkiaRenderEngine* renderengine) {
+    const int previousCount = renderengine->reportShadersCompiled();
+    if (previousCount) {
+        ALOGD("%d Shaders already compiled before Cache::primeShaderCache ran\n", previousCount);
+    }
     const nsecs_t timeBefore = systemTime();
     // The dimensions should not matter, so long as we draw inside them.
     const Rect displayRect(0, 0, 1080, 2340);
@@ -151,7 +206,7 @@
             .physicalDisplay = displayRect,
             .clip = displayRect,
             .maxLuminance = 500,
-            .outputDataspace = ui::Dataspace::DISPLAY_P3,
+            .outputDataspace = kDestDataSpace,
     };
 
     const int64_t usage = GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE;
@@ -166,12 +221,30 @@
     sp<GraphicBuffer> srcBuffer =
             new GraphicBuffer(displayRect.width(), displayRect.height(), PIXEL_FORMAT_RGBA_8888, 1,
                               usage, "drawImageLayer_src");
+
     drawSolidLayers(renderengine, display, dstBuffer);
     drawShadowLayers(renderengine, display, srcBuffer);
+    drawBlurLayers(renderengine, display, dstBuffer);
+    // The majority of shaders are related to sampling images.
     drawImageLayers(renderengine, display, dstBuffer, srcBuffer);
+
+    // 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());
+
     const nsecs_t timeAfter = systemTime();
     const float compileTimeMs = static_cast<float>(timeAfter - timeBefore) / 1.0E6;
-    ALOGD("shader cache generated in %f ms\n", compileTimeMs);
+    const int shadersCompiled = renderengine->reportShadersCompiled();
+    ALOGD("Shader cache generated %d shaders in %f ms\n", shadersCompiled, compileTimeMs);
 }
 
 } // namespace android::renderengine::skia
diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.cpp b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
index 0798562..3b2c7e5 100644
--- a/libs/renderengine/skia/SkiaGLRenderEngine.cpp
+++ b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
@@ -28,6 +28,7 @@
 #include <SkColorFilter.h>
 #include <SkColorMatrix.h>
 #include <SkColorSpace.h>
+#include <SkGraphics.h>
 #include <SkImage.h>
 #include <SkImageFilters.h>
 #include <SkRegion.h>
@@ -40,13 +41,13 @@
 #include <ui/DebugUtils.h>
 #include <ui/GraphicBuffer.h>
 #include <utils/Trace.h>
-#include "Cache.h"
 
 #include <cmath>
 #include <cstdint>
 #include <memory>
 
 #include "../gl/GLExtensions.h"
+#include "Cache.h"
 #include "ColorSpaces.h"
 #include "SkBlendMode.h"
 #include "SkImageInfo.h"
@@ -54,8 +55,15 @@
 #include "filters/LinearEffect.h"
 #include "log/log_main.h"
 #include "skia/debug/SkiaCapture.h"
+#include "skia/debug/SkiaMemoryReporter.h"
 #include "system/graphics-base-v1.0.h"
 
+namespace {
+// Debugging settings
+static const bool kPrintLayerSettings = false;
+static const bool kFlushAfterEveryLayer = false;
+} // namespace
+
 bool checkGlError(const char* op, int lineNumber);
 
 namespace android {
@@ -285,6 +293,10 @@
                         numShaders, cached);
 }
 
+int SkiaGLRenderEngine::reportShadersCompiled() {
+    return mSkSLCacheMonitor.shadersCachedSinceLastCall();
+}
+
 SkiaGLRenderEngine::SkiaGLRenderEngine(const RenderEngineCreationArgs& args, EGLDisplay display,
                                        EGLContext ctxt, EGLSurface placeholder,
                                        EGLContext protectedContext, EGLSurface protectedPlaceholder)
@@ -500,7 +512,7 @@
         std::shared_ptr<AutoBackendTexture::LocalRef> imageTextureRef =
                 std::make_shared<AutoBackendTexture::LocalRef>();
         imageTextureRef->setTexture(
-                new AutoBackendTexture(grContext.get(), buffer->toAHardwareBuffer()));
+                new AutoBackendTexture(grContext.get(), buffer->toAHardwareBuffer(), false));
         cache.insert({buffer->getId(), imageTextureRef});
     }
     // restore the original state of the protected context if necessary
@@ -654,7 +666,7 @@
         ATRACE_NAME("Cache miss");
         surfaceTextureRef = std::make_shared<AutoBackendTexture::LocalRef>();
         surfaceTextureRef->setTexture(
-                new AutoBackendTexture(grContext.get(), buffer->toAHardwareBuffer()));
+                new AutoBackendTexture(grContext.get(), buffer->toAHardwareBuffer(), true));
         if (useFramebufferCache) {
             ALOGD("Adding to cache");
             cache.insert({buffer->getId(), surfaceTextureRef});
@@ -735,6 +747,17 @@
     for (const auto& layer : layers) {
         ATRACE_NAME("DrawLayer");
 
+        if (kPrintLayerSettings) {
+            std::stringstream ls;
+            PrintTo(*layer, &ls);
+            auto debugs = ls.str();
+            int pos = 0;
+            while (pos < debugs.size()) {
+                ALOGD("cache_debug %s", debugs.substr(pos, 1000).c_str());
+                pos += 1000;
+            }
+        }
+
         sk_sp<SkImage> blurInput;
         if (blurCompositionLayer == layer) {
             LOG_ALWAYS_FATAL_IF(activeSurface == dstSurface);
@@ -861,8 +884,9 @@
                 imageTextureRef = iter->second;
             } else {
                 imageTextureRef = std::make_shared<AutoBackendTexture::LocalRef>();
-                imageTextureRef->setTexture(
-                        new AutoBackendTexture(grContext.get(), item.buffer->toAHardwareBuffer()));
+                imageTextureRef->setTexture(new AutoBackendTexture(grContext.get(),
+                                                                   item.buffer->toAHardwareBuffer(),
+                                                                   false));
                 cache.insert({item.buffer->getId(), imageTextureRef});
             }
 
@@ -955,6 +979,10 @@
         } else {
             canvas->drawRect(bounds, paint);
         }
+        if (kFlushAfterEveryLayer) {
+            ATRACE_NAME("flush surface");
+            activeSurface->flush();
+        }
     }
     surfaceAutoSaveRestore.restore();
     mCapture->endCapture();
@@ -1223,9 +1251,38 @@
     StringAppendF(&result, "RenderEngine shaders cached since last dump/primeCache: %d\n",
                   mSkSLCacheMonitor.shadersCachedSinceLastCall());
 
+    std::vector<ResourcePair> cpuResourceMap = {
+            {"skia/sk_resource_cache/bitmap_", "Bitmaps"},
+            {"skia/sk_resource_cache/rrect-blur_", "Masks"},
+            {"skia/sk_resource_cache/rects-blur_", "Masks"},
+            {"skia/sk_resource_cache/tessellated", "Shadows"},
+            {"skia", "Other"},
+    };
+    SkiaMemoryReporter cpuReporter(cpuResourceMap, false);
+    SkGraphics::DumpMemoryStatistics(&cpuReporter);
+    StringAppendF(&result, "Skia CPU Caches: ");
+    cpuReporter.logTotals(result);
+    cpuReporter.logOutput(result);
+
     {
         std::lock_guard<std::mutex> lock(mRenderingMutex);
-        StringAppendF(&result, "RenderEngine texture cache size: %zu\n", mTextureCache.size());
+
+        std::vector<ResourcePair> gpuResourceMap = {
+                {"texture_renderbuffer", "Texture/RenderBuffer"},
+                {"texture", "Texture"},
+                {"gr_text_blob_cache", "Text"},
+                {"skia", "Other"},
+        };
+        SkiaMemoryReporter gpuReporter(gpuResourceMap, true);
+        mGrContext->dumpMemoryStatistics(&gpuReporter);
+        StringAppendF(&result, "Skia's GPU Caches: ");
+        gpuReporter.logTotals(result);
+        gpuReporter.logOutput(result);
+        StringAppendF(&result, "Skia's Wrapped Objects:\n");
+        gpuReporter.logOutput(result, true);
+
+        StringAppendF(&result, "RenderEngine AHB/BackendTexture cache size: %zu\n",
+                      mTextureCache.size());
         StringAppendF(&result, "Dumping buffer ids...\n");
         // TODO(178539829): It would be nice to know which layer these are coming from and what
         // the texture sizes are.
@@ -1233,7 +1290,16 @@
             StringAppendF(&result, "- 0x%" PRIx64 "\n", id);
         }
         StringAppendF(&result, "\n");
-        StringAppendF(&result, "RenderEngine protected texture cache size: %zu\n",
+
+        SkiaMemoryReporter gpuProtectedReporter(gpuResourceMap, true);
+        mProtectedGrContext->dumpMemoryStatistics(&gpuProtectedReporter);
+        StringAppendF(&result, "Skia's GPU Protected Caches: ");
+        gpuProtectedReporter.logTotals(result);
+        gpuProtectedReporter.logOutput(result);
+        StringAppendF(&result, "Skia's Protected Wrapped Objects:\n");
+        gpuProtectedReporter.logOutput(result, true);
+
+        StringAppendF(&result, "RenderEngine protected AHB/BackendTexture cache size: %zu\n",
                       mProtectedTextureCache.size());
         StringAppendF(&result, "Dumping buffer ids...\n");
         for (const auto& [id, unused] : mProtectedTextureCache) {
diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.h b/libs/renderengine/skia/SkiaGLRenderEngine.h
index 25557f1..8e77c16 100644
--- a/libs/renderengine/skia/SkiaGLRenderEngine.h
+++ b/libs/renderengine/skia/SkiaGLRenderEngine.h
@@ -66,6 +66,7 @@
     bool supportsBackgroundBlur() override { return mBlurFilter != nullptr; }
     void assertShadersCompiled(int numShaders) override;
     void onPrimaryDisplaySizeChanged(ui::Size size) override;
+    int reportShadersCompiled() override;
 
 protected:
     void dump(std::string& result) override;
diff --git a/libs/renderengine/skia/SkiaRenderEngine.h b/libs/renderengine/skia/SkiaRenderEngine.h
index 59d7e2f..51ef088 100644
--- a/libs/renderengine/skia/SkiaRenderEngine.h
+++ b/libs/renderengine/skia/SkiaRenderEngine.h
@@ -59,6 +59,7 @@
     virtual bool cleanupPostRender(CleanupMode) override { return true; };
     virtual int getContextPriority() override { return 0; }
     virtual void assertShadersCompiled(int numShaders) {}
+    virtual int reportShadersCompiled() { return 0; }
 };
 
 } // namespace skia
diff --git a/libs/renderengine/skia/debug/SkiaMemoryReporter.cpp b/libs/renderengine/skia/debug/SkiaMemoryReporter.cpp
new file mode 100644
index 0000000..f24a4f1
--- /dev/null
+++ b/libs/renderengine/skia/debug/SkiaMemoryReporter.cpp
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+#undef LOG_TAG
+#define LOG_TAG "RenderEngine"
+
+#include "SkiaMemoryReporter.h"
+
+#include <SkString.h>
+#include <android-base/stringprintf.h>
+#include <log/log_main.h>
+
+namespace android {
+namespace renderengine {
+namespace skia {
+
+using base::StringAppendF;
+
+SkiaMemoryReporter::SkiaMemoryReporter(const std::vector<ResourcePair>& resourceMap, bool itemize)
+      : mResourceMap(resourceMap),
+        mItemize(itemize),
+        mTotalSize("bytes", 0),
+        mPurgeableSize("bytes", 0) {}
+
+const char* SkiaMemoryReporter::mapName(const char* resourceName) {
+    for (auto& resource : mResourceMap) {
+        if (SkStrContains(resourceName, resource.first)) {
+            return resource.second;
+        }
+    }
+    return nullptr;
+}
+
+void SkiaMemoryReporter::resetCurrentElement() {
+    mCurrentElement.clear();
+    mCurrentValues.clear();
+    mIsCurrentValueWrapped = false;
+}
+
+void SkiaMemoryReporter::processCurrentElement() {
+    // compute the top level element name using the map
+    const char* resourceName = mCurrentElement.empty() ? nullptr : mapName(mCurrentElement.c_str());
+
+    // if we don't have a resource name then we don't know how to label the
+    // data and should abort.
+    if (resourceName == nullptr) {
+        resetCurrentElement();
+        return;
+    }
+
+    // Only count elements that contain "size"; other values just provide metadata.
+    auto sizeResult = mCurrentValues.find("size");
+    if (sizeResult != mCurrentValues.end() && sizeResult->second.value > 0) {
+        if (!mIsCurrentValueWrapped) {
+            mTotalSize.value += sizeResult->second.value;
+            mTotalSize.count++;
+        }
+    } else {
+        resetCurrentElement();
+        return;
+    }
+
+    // find the purgeable size if one exists
+    auto purgeableResult = mCurrentValues.find("purgeable_size");
+    if (!mIsCurrentValueWrapped && purgeableResult != mCurrentValues.end()) {
+        mPurgeableSize.value += purgeableResult->second.value;
+        mPurgeableSize.count++;
+    }
+
+    // do we store this element in the wrapped list or the skia managed list
+    auto& results = mIsCurrentValueWrapped ? mWrappedResults : mResults;
+
+    // insert a copy of the element and all of its keys. We must make a copy here instead of
+    // std::move() as we will continue to use these values later in the function and again
+    // when we move on to process the next element.
+    results.insert({mCurrentElement, mCurrentValues});
+
+    // insert the item into its mapped category
+    auto result = results.find(resourceName);
+    if (result != results.end()) {
+        auto& resourceValues = result->second;
+        auto totalResult = resourceValues.find(sizeResult->first);
+        if (totalResult != resourceValues.end()) {
+            ALOGE_IF(sizeResult->second.units != totalResult->second.units,
+                     "resource units do not match so the sum of resource type (%s) will be invalid",
+                     resourceName);
+            totalResult->second.value += sizeResult->second.value;
+            totalResult->second.count++;
+        } else {
+            ALOGE("an entry (%s) should not exist in the results without a size", resourceName);
+        }
+    } else {
+        // only store the size for the top level resource
+        results.insert({resourceName, {{sizeResult->first, sizeResult->second}}});
+    }
+
+    resetCurrentElement();
+}
+
+void SkiaMemoryReporter::dumpNumericValue(const char* dumpName, const char* valueName,
+                                          const char* units, uint64_t value) {
+    if (mCurrentElement != dumpName) {
+        processCurrentElement();
+        mCurrentElement = dumpName;
+    }
+    mCurrentValues.insert({valueName, {units, value}});
+}
+
+void SkiaMemoryReporter::dumpWrappedState(const char* dumpName, bool isWrappedObject) {
+    if (mCurrentElement != dumpName) {
+        processCurrentElement();
+        mCurrentElement = dumpName;
+    }
+    mIsCurrentValueWrapped = isWrappedObject;
+}
+
+void SkiaMemoryReporter::logOutput(std::string& log, bool wrappedResources) {
+    // process the current element before logging
+    processCurrentElement();
+
+    const auto& resultsMap = wrappedResources ? mWrappedResults : mResults;
+
+    // log each individual element based on the resource map
+    for (const auto& resourceCategory : mResourceMap) {
+        // find the named item and print the totals
+        const auto categoryItem = resultsMap.find(resourceCategory.second);
+        if (categoryItem != resultsMap.end()) {
+            auto result = categoryItem->second.find("size");
+            if (result != categoryItem->second.end()) {
+                TraceValue traceValue = convertUnits(result->second);
+                const char* entry = (traceValue.count > 1) ? "entries" : "entry";
+                StringAppendF(&log, "  %s: %.2f %s (%d %s)\n", categoryItem->first.c_str(),
+                              traceValue.value, traceValue.units, traceValue.count, entry);
+            }
+            if (mItemize) {
+                for (const auto& individualItem : resultsMap) {
+                    // if the individual item matches the category then print all its details or
+                    // in the case of wrapped resources just print the wrapped size
+                    const char* categoryMatch = mapName(individualItem.first.c_str());
+                    if (categoryMatch && strcmp(categoryMatch, resourceCategory.second) == 0) {
+                        auto result = individualItem.second.find("size");
+                        TraceValue size = convertUnits(result->second);
+                        StringAppendF(&log, "    %s: size[%.2f %s]", individualItem.first.c_str(),
+                                      size.value, size.units);
+                        if (!wrappedResources) {
+                            for (const auto& itemValues : individualItem.second) {
+                                if (strcmp("size", itemValues.first) == 0) {
+                                    continue;
+                                }
+                                TraceValue traceValue = convertUnits(itemValues.second);
+                                if (traceValue.value == 0.0f) {
+                                    StringAppendF(&log, " %s[%s]", itemValues.first,
+                                                  traceValue.units);
+                                } else {
+                                    StringAppendF(&log, " %s[%.2f %s]", itemValues.first,
+                                                  traceValue.value, traceValue.units);
+                                }
+                            }
+                        }
+                        StringAppendF(&log, "\n");
+                    }
+                }
+            }
+        }
+    }
+}
+
+void SkiaMemoryReporter::logTotals(std::string& log) {
+    // process the current element before logging
+    processCurrentElement();
+
+    TraceValue total = convertUnits(mTotalSize);
+    TraceValue purgeable = convertUnits(mPurgeableSize);
+    StringAppendF(&log, " %.0f bytes, %.2f %s (%.2f %s is purgeable)\n", mTotalSize.value,
+                  total.value, total.units, purgeable.value, purgeable.units);
+}
+
+SkiaMemoryReporter::TraceValue SkiaMemoryReporter::convertUnits(const TraceValue& value) {
+    TraceValue output(value);
+    if (SkString("bytes") == SkString(output.units) && output.value >= 1024) {
+        output.value = output.value / 1024.0f;
+        output.units = "KB";
+    }
+    if (SkString("KB") == SkString(output.units) && output.value >= 1024) {
+        output.value = output.value / 1024.0f;
+        output.units = "MB";
+    }
+    return output;
+}
+
+} /* namespace skia */
+} /* namespace renderengine */
+} /* namespace android */
diff --git a/libs/renderengine/skia/debug/SkiaMemoryReporter.h b/libs/renderengine/skia/debug/SkiaMemoryReporter.h
new file mode 100644
index 0000000..dbbd65b
--- /dev/null
+++ b/libs/renderengine/skia/debug/SkiaMemoryReporter.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+#pragma once
+
+#include <SkTraceMemoryDump.h>
+
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+namespace android {
+namespace renderengine {
+namespace skia {
+
+// Mapping of resource substrings (1st element) that if found within a trace "dumpName"
+// should be mapped to the category name (2nd element). All char* used in a resourcePair
+// are expected to have a lifetime longer than the SkiaMemoryReporter in which they are used.
+typedef std::pair<const char*, const char*> ResourcePair;
+
+/*
+ * Utility class for logging the CPU/GPU usage of Skia caches in a format that is specific
+ * to RenderEngine.  HWUI has a similar logging class, but the data collected and the way
+ * it is formatted and reported on are intended to be unique to each use case.
+ */
+class SkiaMemoryReporter : public SkTraceMemoryDump {
+public:
+    /**
+     * Creates the reporter class that can be populated by various Skia entry points, like
+     * SkGraphics and GrContext, as well as format and log the results.
+     * @param resourceMap An array of values that maps a Skia dumpName into a user defined category.
+     *                    The first vector entry that matches the dumpName is used for the mapping.
+     * @param itemize if true when logging the categories the individual elements will be printed
+     *                directly after the category details are printed.  Otherwise, only the category
+     *                totals will be printed.
+     */
+    SkiaMemoryReporter(const std::vector<ResourcePair>& resourceMap, bool itemize);
+    ~SkiaMemoryReporter() override {}
+
+    void logOutput(std::string& log, bool wrappedResources = false);
+    void logTotals(std::string& log);
+
+    void dumpNumericValue(const char* dumpName, const char* valueName, const char* units,
+                          uint64_t value) override;
+
+    void dumpStringValue(const char* dumpName, const char* valueName, const char* value) override {
+        // for convenience we just store this in the same format as numerical values
+        dumpNumericValue(dumpName, valueName, value, 0);
+    }
+    void dumpWrappedState(const char* dumpName, bool isWrappedObject) override;
+
+    LevelOfDetail getRequestedDetails() const override {
+        return SkTraceMemoryDump::kLight_LevelOfDetail;
+    }
+
+    bool shouldDumpWrappedObjects() const override { return true; }
+    void setMemoryBacking(const char*, const char*, const char*) override {}
+    void setDiscardableMemoryBacking(const char*, const SkDiscardableMemory&) override {}
+
+private:
+    struct TraceValue {
+        TraceValue(const char* units, uint64_t value) : units(units), value(value), count(1) {}
+        TraceValue(const TraceValue& v) : units(v.units), value(v.value), count(v.count) {}
+
+        const char* units;
+        float value;
+        int count;
+    };
+
+    const char* mapName(const char* resourceName);
+    void processCurrentElement();
+    void resetCurrentElement();
+    TraceValue convertUnits(const TraceValue& value);
+
+    const std::vector<ResourcePair>& mResourceMap;
+    const bool mItemize;
+
+    // variables storing the size of all non-wrapped elements being dumped
+    TraceValue mTotalSize;
+    TraceValue mPurgeableSize;
+
+    // variables storing information on the current node being dumped
+    std::string mCurrentElement;
+    std::unordered_map<const char*, TraceValue> mCurrentValues;
+    bool mIsCurrentValueWrapped = false;
+
+    // variable that stores the final format of the data after the individual elements are processed
+    std::unordered_map<std::string, std::unordered_map<const char*, TraceValue>> mResults;
+    std::unordered_map<std::string, std::unordered_map<const char*, TraceValue>> mWrappedResults;
+};
+
+} /* namespace skia */
+} /* namespace renderengine */
+} /* namespace android */
\ No newline at end of file
diff --git a/libs/renderengine/skia/filters/BlurFilter.cpp b/libs/renderengine/skia/filters/BlurFilter.cpp
index ec710d9..6dd4161 100644
--- a/libs/renderengine/skia/filters/BlurFilter.cpp
+++ b/libs/renderengine/skia/filters/BlurFilter.cpp
@@ -34,7 +34,7 @@
 
 BlurFilter::BlurFilter() {
     SkString blurString(R"(
-        in shader input;
+        uniform shader input;
         uniform float2 in_blurOffset;
         uniform float2 in_maxSizeXY;
 
@@ -60,8 +60,8 @@
     mBlurEffect = std::move(blurEffect);
 
     SkString mixString(R"(
-        in shader blurredInput;
-        in shader originalInput;
+        uniform shader blurredInput;
+        uniform shader originalInput;
         uniform float mixFactor;
 
         half4 main(float2 xy) {
diff --git a/libs/renderengine/skia/filters/LinearEffect.cpp b/libs/renderengine/skia/filters/LinearEffect.cpp
index 84af016..8e8e42e 100644
--- a/libs/renderengine/skia/filters/LinearEffect.cpp
+++ b/libs/renderengine/skia/filters/LinearEffect.cpp
@@ -390,7 +390,7 @@
 
 static void generateEffectiveOOTF(bool undoPremultipliedAlpha, SkString& shader) {
     shader.append(R"(
-        in shader input;
+        uniform shader input;
         half4 main(float2 xy) {
             float4 c = float4(sample(input, xy));
     )");
diff --git a/libs/renderengine/tests/RenderEngineThreadedTest.cpp b/libs/renderengine/tests/RenderEngineThreadedTest.cpp
index 63aa4c8..b093e88 100644
--- a/libs/renderengine/tests/RenderEngineThreadedTest.cpp
+++ b/libs/renderengine/tests/RenderEngineThreadedTest.cpp
@@ -49,6 +49,9 @@
 TEST_F(RenderEngineThreadedTest, primeCache) {
     EXPECT_CALL(*mRenderEngine, primeCache());
     mThreadedRE->primeCache();
+    // need to call ANY synchronous function after primeCache to ensure that primeCache has
+    // completed asynchronously before the test completes execution.
+    mThreadedRE->getContextPriority();
 }
 
 TEST_F(RenderEngineThreadedTest, genTextures) {
diff --git a/libs/renderengine/threaded/RenderEngineThreaded.cpp b/libs/renderengine/threaded/RenderEngineThreaded.cpp
index 783e37f..194c7da 100644
--- a/libs/renderengine/threaded/RenderEngineThreaded.cpp
+++ b/libs/renderengine/threaded/RenderEngineThreaded.cpp
@@ -74,6 +74,12 @@
     std::unique_lock<std::mutex> lock(mThreadMutex);
     pthread_setname_np(pthread_self(), mThreadName);
 
+    {
+        std::unique_lock<std::mutex> lock(mInitializedMutex);
+        mIsInitialized = true;
+    }
+    mInitializedCondition.notify_all();
+
     while (mRunning) {
         if (!mFunctionCalls.empty()) {
             auto task = mFunctionCalls.front();
@@ -86,19 +92,22 @@
     }
 }
 
+void RenderEngineThreaded::waitUntilInitialized() const {
+    std::unique_lock<std::mutex> lock(mInitializedMutex);
+    mInitializedCondition.wait(lock, [=] { return mIsInitialized; });
+}
+
 void RenderEngineThreaded::primeCache() {
-    std::promise<void> resultPromise;
-    std::future<void> resultFuture = resultPromise.get_future();
+    // This function is designed so it can run asynchronously, so we do not need to wait
+    // for the futures.
     {
         std::lock_guard lock(mThreadMutex);
-        mFunctionCalls.push([&resultPromise](renderengine::RenderEngine& instance) {
+        mFunctionCalls.push([](renderengine::RenderEngine& instance) {
             ATRACE_NAME("REThreaded::primeCache");
             instance.primeCache();
-            resultPromise.set_value();
         });
     }
     mCondition.notify_one();
-    resultFuture.wait();
 }
 
 void RenderEngineThreaded::dump(std::string& result) {
@@ -175,63 +184,26 @@
 }
 
 size_t RenderEngineThreaded::getMaxTextureSize() const {
-    std::promise<size_t> resultPromise;
-    std::future<size_t> resultFuture = resultPromise.get_future();
-    {
-        std::lock_guard lock(mThreadMutex);
-        mFunctionCalls.push([&resultPromise](renderengine::RenderEngine& instance) {
-            ATRACE_NAME("REThreaded::getMaxTextureSize");
-            size_t size = instance.getMaxTextureSize();
-            resultPromise.set_value(size);
-        });
-    }
-    mCondition.notify_one();
-    return resultFuture.get();
+    waitUntilInitialized();
+    return mRenderEngine->getMaxTextureSize();
 }
 
 size_t RenderEngineThreaded::getMaxViewportDims() const {
-    std::promise<size_t> resultPromise;
-    std::future<size_t> resultFuture = resultPromise.get_future();
-    {
-        std::lock_guard lock(mThreadMutex);
-        mFunctionCalls.push([&resultPromise](renderengine::RenderEngine& instance) {
-            ATRACE_NAME("REThreaded::getMaxViewportDims");
-            size_t size = instance.getMaxViewportDims();
-            resultPromise.set_value(size);
-        });
-    }
-    mCondition.notify_one();
-    return resultFuture.get();
+    waitUntilInitialized();
+    return mRenderEngine->getMaxViewportDims();
 }
 
 bool RenderEngineThreaded::isProtected() const {
-    std::promise<bool> resultPromise;
-    std::future<bool> resultFuture = resultPromise.get_future();
-    {
-        std::lock_guard lock(mThreadMutex);
-        mFunctionCalls.push([&resultPromise](renderengine::RenderEngine& instance) {
-            ATRACE_NAME("REThreaded::isProtected");
-            bool returnValue = instance.isProtected();
-            resultPromise.set_value(returnValue);
-        });
-    }
-    mCondition.notify_one();
-    return resultFuture.get();
+    waitUntilInitialized();
+    // ensure that useProtectedContext is not currently being changed by some
+    // other thread.
+    std::lock_guard lock(mThreadMutex);
+    return mRenderEngine->isProtected();
 }
 
 bool RenderEngineThreaded::supportsProtectedContent() const {
-    std::promise<bool> resultPromise;
-    std::future<bool> resultFuture = resultPromise.get_future();
-    {
-        std::lock_guard lock(mThreadMutex);
-        mFunctionCalls.push([&resultPromise](renderengine::RenderEngine& instance) {
-            ATRACE_NAME("REThreaded::supportsProtectedContent");
-            bool returnValue = instance.supportsProtectedContent();
-            resultPromise.set_value(returnValue);
-        });
-    }
-    mCondition.notify_one();
-    return resultFuture.get();
+    waitUntilInitialized();
+    return mRenderEngine->supportsProtectedContent();
 }
 
 bool RenderEngineThreaded::useProtectedContext(bool useProtectedContext) {
@@ -288,18 +260,16 @@
 }
 
 void RenderEngineThreaded::cleanFramebufferCache() {
-    std::promise<void> resultPromise;
-    std::future<void> resultFuture = resultPromise.get_future();
+    // This function is designed so it can run asynchronously, so we do not need to wait
+    // for the futures.
     {
         std::lock_guard lock(mThreadMutex);
-        mFunctionCalls.push([&resultPromise](renderengine::RenderEngine& instance) {
+        mFunctionCalls.push([](renderengine::RenderEngine& instance) {
             ATRACE_NAME("REThreaded::cleanFramebufferCache");
             instance.cleanFramebufferCache();
-            resultPromise.set_value();
         });
     }
     mCondition.notify_one();
-    resultFuture.wait();
 }
 
 int RenderEngineThreaded::getContextPriority() {
@@ -318,33 +288,21 @@
 }
 
 bool RenderEngineThreaded::supportsBackgroundBlur() {
-    std::promise<bool> resultPromise;
-    std::future<bool> resultFuture = resultPromise.get_future();
-    {
-        std::lock_guard lock(mThreadMutex);
-        mFunctionCalls.push([&resultPromise](renderengine::RenderEngine& instance) {
-            ATRACE_NAME("REThreaded::supportsBackgroundBlur");
-            bool returnValue = instance.supportsBackgroundBlur();
-            resultPromise.set_value(returnValue);
-        });
-    }
-    mCondition.notify_one();
-    return resultFuture.get();
+    waitUntilInitialized();
+    return mRenderEngine->supportsBackgroundBlur();
 }
 
 void RenderEngineThreaded::onPrimaryDisplaySizeChanged(ui::Size size) {
-    std::promise<void> resultPromise;
-    std::future<void> resultFuture = resultPromise.get_future();
+    // This function is designed so it can run asynchronously, so we do not need to wait
+    // for the futures.
     {
         std::lock_guard lock(mThreadMutex);
-        mFunctionCalls.push([&resultPromise, size](renderengine::RenderEngine& instance) {
+        mFunctionCalls.push([size](renderengine::RenderEngine& instance) {
             ATRACE_NAME("REThreaded::onPrimaryDisplaySizeChanged");
             instance.onPrimaryDisplaySizeChanged(size);
-            resultPromise.set_value();
         });
     }
     mCondition.notify_one();
-    resultFuture.wait();
 }
 
 } // namespace threaded
diff --git a/libs/renderengine/threaded/RenderEngineThreaded.h b/libs/renderengine/threaded/RenderEngineThreaded.h
index 117257a..61ae9b8 100644
--- a/libs/renderengine/threaded/RenderEngineThreaded.h
+++ b/libs/renderengine/threaded/RenderEngineThreaded.h
@@ -70,6 +70,7 @@
 
 private:
     void threadMain(CreateInstanceFactory factory);
+    void waitUntilInitialized() const;
 
     /* ------------------------------------------------------------------------
      * Threading
@@ -83,6 +84,12 @@
             GUARDED_BY(mThreadMutex);
     mutable std::condition_variable mCondition;
 
+    // Used to allow select thread safe methods to be accessed without requiring the
+    // method to be invoked on the RenderEngine thread
+    bool mIsInitialized = false;
+    mutable std::mutex mInitializedMutex;
+    mutable std::condition_variable mInitializedCondition;
+
     /* ------------------------------------------------------------------------
      * Render Engine
      */
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/memtrackproxy/MemtrackProxy.cpp b/services/memtrackproxy/MemtrackProxy.cpp
index 8da6e89..4676167 100644
--- a/services/memtrackproxy/MemtrackProxy.cpp
+++ b/services/memtrackproxy/MemtrackProxy.cpp
@@ -122,11 +122,9 @@
 
     _aidl_return->clear();
 
-    if (memtrack_aidl_instance_ ||
-        (memtrack_aidl_instance_ = MemtrackProxy::MemtrackAidlInstance())) {
+    if (memtrack_aidl_instance_) {
         return memtrack_aidl_instance_->getMemory(pid, type, _aidl_return);
-    } else if (memtrack_hidl_instance_ ||
-               (memtrack_hidl_instance_ = MemtrackProxy::MemtrackHidlInstance())) {
+    } else if (memtrack_hidl_instance_) {
         ndk::ScopedAStatus aidl_status;
 
         Return<void> ret = memtrack_hidl_instance_->getMemory(
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/sensorservice/Android.bp b/services/sensorservice/Android.bp
index c769e97..9aecaff 100644
--- a/services/sensorservice/Android.bp
+++ b/services/sensorservice/Android.bp
@@ -49,6 +49,7 @@
         "libhardware_legacy",
         "libutils",
         "liblog",
+        "libactivitymanager_aidl",
         "libbatterystats_aidl",
         "libbinder",
         "libsensor",
@@ -69,8 +70,11 @@
 
     generated_headers: ["framework-cppstream-protos"],
 
-    // our public headers depend on libsensor and libsensorprivacy
-    export_shared_lib_headers: ["libsensor", "libsensorprivacy"],
+    export_shared_lib_headers: [
+        "libactivitymanager_aidl",
+        "libsensor",
+        "libsensorprivacy",
+    ],
 }
 
 cc_binary {
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/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index be9bce0..12f63db 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -507,11 +507,6 @@
 
     BufferInfo oldBufferInfo = mBufferInfo;
 
-    if (!allTransactionsSignaled(expectedPresentTime)) {
-        mFlinger->setTransactionFlags(eTraversalNeeded);
-        return false;
-    }
-
     status_t err = updateTexImage(recomputeVisibleRegions, latchTime, expectedPresentTime);
     if (err != NO_ERROR) {
         return false;
@@ -556,53 +551,9 @@
         recomputeVisibleRegions = true;
     }
 
-    // Remove any sync points corresponding to the buffer which was just
-    // latched
-    {
-        Mutex::Autolock lock(mLocalSyncPointMutex);
-        auto point = mLocalSyncPoints.begin();
-        while (point != mLocalSyncPoints.end()) {
-            if (!(*point)->frameIsAvailable() || !(*point)->transactionIsApplied()) {
-                // This sync point must have been added since we started
-                // latching. Don't drop it yet.
-                ++point;
-                continue;
-            }
-
-            if ((*point)->getFrameNumber() <= mCurrentFrameNumber) {
-                std::stringstream ss;
-                ss << "Dropping sync point " << (*point)->getFrameNumber();
-                ATRACE_NAME(ss.str().c_str());
-                point = mLocalSyncPoints.erase(point);
-            } else {
-                ++point;
-            }
-        }
-    }
-
     return true;
 }
 
-// transaction
-void BufferLayer::notifyAvailableFrames(nsecs_t expectedPresentTime) {
-    const auto headFrameNumber = getHeadFrameNumber(expectedPresentTime);
-    const bool headFenceSignaled = fenceHasSignaled();
-    const bool presentTimeIsCurrent = framePresentTimeIsCurrent(expectedPresentTime);
-    Mutex::Autolock lock(mLocalSyncPointMutex);
-    for (auto& point : mLocalSyncPoints) {
-        if (headFrameNumber >= point->getFrameNumber() && headFenceSignaled &&
-            presentTimeIsCurrent) {
-            point->setFrameAvailable();
-            sp<Layer> requestedSyncLayer = point->getRequestedSyncLayer();
-            if (requestedSyncLayer) {
-                // Need to update the transaction flag to ensure the layer's pending transaction
-                // gets applied.
-                requestedSyncLayer->setTransactionFlags(eTransactionNeeded);
-            }
-        }
-    }
-}
-
 bool BufferLayer::hasReadyFrame() const {
     return hasFrameUpdate() || getSidebandStreamChanged() || getAutoRefresh();
 }
@@ -616,33 +567,6 @@
     return (buffer != 0) && (buffer->getUsage() & GRALLOC_USAGE_PROTECTED);
 }
 
-// h/w composer set-up
-bool BufferLayer::allTransactionsSignaled(nsecs_t expectedPresentTime) {
-    const auto headFrameNumber = getHeadFrameNumber(expectedPresentTime);
-    bool matchingFramesFound = false;
-    bool allTransactionsApplied = true;
-    Mutex::Autolock lock(mLocalSyncPointMutex);
-
-    for (auto& point : mLocalSyncPoints) {
-        if (point->getFrameNumber() > headFrameNumber) {
-            break;
-        }
-        matchingFramesFound = true;
-
-        if (!point->frameIsAvailable()) {
-            // We haven't notified the remote layer that the frame for
-            // this point is available yet. Notify it now, and then
-            // abort this attempt to latch.
-            point->setFrameAvailable();
-            allTransactionsApplied = false;
-            break;
-        }
-
-        allTransactionsApplied = allTransactionsApplied && point->transactionIsApplied();
-    }
-    return !matchingFramesFound || allTransactionsApplied;
-}
-
 // As documented in libhardware header, formats in the range
 // 0x100 - 0x1FF are specific to the HAL implementation, and
 // are known to have no alpha channel
diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h
index b8d3f12..0a5235a 100644
--- a/services/surfaceflinger/BufferLayer.h
+++ b/services/surfaceflinger/BufferLayer.h
@@ -90,8 +90,6 @@
 
     bool isBufferLatched() const override { return mRefreshPending; }
 
-    void notifyAvailableFrames(nsecs_t expectedPresentTime) override;
-
     bool hasReadyFrame() const override;
 
     // Returns the current scaling mode
@@ -153,11 +151,6 @@
     bool onPreComposition(nsecs_t) override;
     void preparePerFrameCompositionState() override;
 
-    // Check all of the local sync points to ensure that all transactions
-    // which need to have been applied prior to the frame which is about to
-    // be latched have signaled
-    bool allTransactionsSignaled(nsecs_t expectedPresentTime);
-
     static bool getOpacityForFormat(uint32_t format);
 
     // from graphics API
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index d6becbf..fa9cecf 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -259,28 +259,8 @@
              (mCurrentState.buffer != nullptr || mCurrentState.bgColorLayer != nullptr)));
 }
 
-/* TODO: vhau uncomment once deferred transaction migration complete in
- * WindowManager
-void BufferStateLayer::pushPendingState() {
-    if (!mCurrentState.modified) {
-        return;
-    }
-    mPendingStates.push_back(mCurrentState);
-    ATRACE_INT(mTransactionName.c_str(), mPendingStates.size());
-}
-*/
-
-bool BufferStateLayer::applyPendingStates(Layer::State* stateToCommit) {
-    mCurrentStateModified = mCurrentState.modified;
-    bool stateUpdateAvailable = Layer::applyPendingStates(stateToCommit);
-    mCurrentStateModified = stateUpdateAvailable && mCurrentStateModified;
-    mCurrentState.modified = false;
-    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 +281,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 +404,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 +838,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) {
@@ -931,6 +884,36 @@
     }
 }
 
+/*
+ * We don't want to send the layer's transform to input, but rather the
+ * parent's transform. This is because BufferStateLayer's transform is
+ * information about how the buffer is placed on screen. The parent's
+ * transform makes more sense to send since it's information about how the
+ * layer is placed on screen. This transform is used by input to determine
+ * how to go from screen space back to window space.
+ */
+ui::Transform BufferStateLayer::getInputTransform() const {
+    sp<Layer> parent = mDrawingParent.promote();
+    if (parent == nullptr) {
+        return ui::Transform();
+    }
+
+    return parent->getTransform();
+}
+
+/**
+ * Similar to getInputTransform, we need to update the bounds to include the transform.
+ * This is because bounds for BSL doesn't include buffer transform, where the input assumes
+ * that's already included.
+ */
+Rect BufferStateLayer::getInputBounds() const {
+    Rect bufferBounds = getCroppedBufferSize(getDrawingState());
+    if (mDrawingState.transform.getType() == ui::Transform::IDENTITY || !bufferBounds.isValid()) {
+        return bufferBounds;
+    }
+    return mDrawingState.transform.transform(bufferBounds);
+}
+
 } // namespace android
 
 // TODO(b/129481165): remove the #pragma below and fix conversion issues
diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h
index 7a3da6f..24e0ad2 100644
--- a/services/surfaceflinger/BufferStateLayer.h
+++ b/services/surfaceflinger/BufferStateLayer.h
@@ -50,10 +50,6 @@
     uint32_t doTransactionResize(uint32_t flags, Layer::State* /*stateToCommit*/) override {
         return flags;
     }
-    /*TODO:vhau return to using BufferStateLayer override once WM
-     * has removed deferred transactions!
-    void pushPendingState() override;*/
-    bool applyPendingStates(Layer::State* stateToCommit) override;
 
     uint32_t getActiveWidth(const Layer::State& s) const override { return s.width; }
     uint32_t getActiveHeight(const Layer::State& s) const override { return s.height; }
@@ -66,7 +62,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,23 +76,16 @@
     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*/,
-                                      uint64_t /*frameNumber*/) override {}
 
     Rect getBufferSize(const State& s) const override;
     FloatRect computeSourceBounds(const FloatRect& parentBounds) const override;
-    Layer::RoundedCornerState getRoundedCornerState() const override;
     void setAutoRefresh(bool autoRefresh) override;
 
     // -----------------------------------------------------------------------
@@ -122,6 +110,8 @@
     void gatherBufferInfo() override;
     uint64_t getHeadFrameNumber(nsecs_t expectedPresentTime) const;
     void onSurfaceFrameCreated(const std::shared_ptr<frametimeline::SurfaceFrame>& surfaceFrame);
+    ui::Transform getInputTransform() const override;
+    Rect getInputBounds() const override;
 
 private:
     friend class SlotGenerationTest;
@@ -167,7 +157,6 @@
     uint64_t mPreviousBufferId = 0;
     uint64_t mPreviousReleasedFrameNumber = 0;
 
-    mutable bool mCurrentStateModified = false;
     bool mReleasePreviousBuffer = false;
 
     // Stores the last set acquire fence signal time used to populate the callback handle's acquire
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/include/compositionengine/impl/planner/CachedSet.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/CachedSet.h
index afa02cd..c5d03a7 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/CachedSet.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/CachedSet.h
@@ -108,7 +108,7 @@
 private:
     CachedSet() = default;
 
-    NonBufferHash mFingerprint = 0;
+    const NonBufferHash mFingerprint;
     std::chrono::steady_clock::time_point mLastUpdate = std::chrono::steady_clock::now();
     std::vector<Layer> mLayers;
     Rect mBounds = Rect::EMPTY_RECT;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Flattener.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Flattener.h
index 313a180..2f2ad4c 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Flattener.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Flattener.h
@@ -54,7 +54,7 @@
 
     void resetActivities(NonBufferHash, std::chrono::steady_clock::time_point now);
 
-    void updateLayersHash();
+    NonBufferHash computeLayersHash() const;
 
     bool mergeWithCachedSets(const std::vector<const LayerState*>& layers,
                              std::chrono::steady_clock::time_point now);
@@ -69,7 +69,6 @@
     std::chrono::steady_clock::time_point mLastGeometryUpdate;
 
     std::vector<CachedSet> mLayers;
-    NonBufferHash mLayersHash = 0;
     std::optional<CachedSet> mNewCachedSet;
 
     // Statistics
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/CompositionEngine/src/planner/Flattener.cpp b/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp
index ffca5ba..9c9649c 100644
--- a/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp
@@ -40,13 +40,17 @@
 
     ++mInitialLayerCounts[layers.size()];
 
-    if (mergeWithCachedSets(layers, now)) {
-        hash = mLayersHash;
-    }
+    // Only buildCachedSets if these layers are already stored in mLayers.
+    // Otherwise (i.e. mergeWithCachedSets returns false), the time has not
+    // changed, so buildCachedSets will never find any runs.
+    const bool alreadyHadCachedSets = mergeWithCachedSets(layers, now);
 
     ++mFinalLayerCounts[mLayers.size()];
 
-    buildCachedSets(now);
+    if (alreadyHadCachedSets) {
+        buildCachedSets(now);
+        hash = computeLayersHash();
+    }
 
     return hash;
 }
@@ -157,14 +161,17 @@
     }
 }
 
-void Flattener::updateLayersHash() {
+NonBufferHash Flattener::computeLayersHash() const{
     size_t hash = 0;
     for (const auto& layer : mLayers) {
         android::hashCombineSingleHashed(hash, layer.getNonBufferHash());
     }
-    mLayersHash = hash;
+    return hash;
 }
 
+// Only called if the geometry matches the last frame. Return true if mLayers
+// was already populated with these layers, i.e. on the second and following
+// calls with the same geometry.
 bool Flattener::mergeWithCachedSets(const std::vector<const LayerState*>& layers, time_point now) {
     std::vector<CachedSet> merged;
 
@@ -272,7 +279,6 @@
     }
 
     mLayers = std::move(merged);
-    updateLayersHash();
     return true;
 }
 
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 dbd6b32..b45f2bc 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -202,19 +202,6 @@
  */
 void Layer::onLayerDisplayed(const sp<Fence>& /*releaseFence*/) {}
 
-void Layer::removeRemoteSyncPoints() {
-    for (auto& point : mRemoteSyncPoints) {
-        point->setTransactionApplied();
-    }
-    mRemoteSyncPoints.clear();
-
-    {
-        for (State pendingState : mPendingStates) {
-            pendingState.barrierLayer_legacy = nullptr;
-        }
-    }
-}
-
 void Layer::removeRelativeZ(const std::vector<Layer*>& layersInTree) {
     if (mCurrentState.zOrderRelativeOf == nullptr) {
         return;
@@ -236,21 +223,6 @@
 void Layer::removeFromCurrentState() {
     mRemovedFromCurrentState = true;
 
-    // Since we are no longer reachable from CurrentState SurfaceFlinger
-    // will no longer invoke doTransaction for us, and so we will
-    // never finish applying transactions. We signal the sync point
-    // now so that another layer will not become indefinitely
-    // blocked.
-    removeRemoteSyncPoints();
-
-    {
-    Mutex::Autolock syncLock(mLocalSyncPointMutex);
-    for (auto& point : mLocalSyncPoints) {
-        point->setFrameAvailable();
-    }
-    mLocalSyncPoints.clear();
-    }
-
     mFlinger->markLayerPendingRemovalLocked(this);
 }
 
@@ -775,21 +747,6 @@
     }
 }
 
-bool Layer::addSyncPoint(const std::shared_ptr<SyncPoint>& point) {
-    if (point->getFrameNumber() <= mCurrentFrameNumber) {
-        // Don't bother with a SyncPoint, since we've already latched the
-        // relevant frame
-        return false;
-    }
-    if (isRemovedFromCurrentState()) {
-        return false;
-    }
-
-    Mutex::Autolock lock(mLocalSyncPointMutex);
-    mLocalSyncPoints.push_back(point);
-    return true;
-}
-
 // ----------------------------------------------------------------------------
 // local state
 // ----------------------------------------------------------------------------
@@ -808,132 +765,6 @@
 // transaction
 // ----------------------------------------------------------------------------
 
-void Layer::pushPendingState() {
-    if (!mCurrentState.modified) {
-        return;
-    }
-    ATRACE_CALL();
-
-    // If this transaction is waiting on the receipt of a frame, generate a sync
-    // point and send it to the remote layer.
-    // We don't allow installing sync points after we are removed from the current state
-    // as we won't be able to signal our end.
-    if (mCurrentState.barrierLayer_legacy != nullptr && !isRemovedFromCurrentState()) {
-        sp<Layer> barrierLayer = mCurrentState.barrierLayer_legacy.promote();
-        if (barrierLayer == nullptr) {
-            ALOGE("[%s] Unable to promote barrier Layer.", getDebugName());
-            // If we can't promote the layer we are intended to wait on,
-            // then it is expired or otherwise invalid. Allow this transaction
-            // to be applied as per normal (no synchronization).
-            mCurrentState.barrierLayer_legacy = nullptr;
-        } else {
-            auto syncPoint = std::make_shared<SyncPoint>(mCurrentState.barrierFrameNumber, this,
-                                                         barrierLayer);
-            if (barrierLayer->addSyncPoint(syncPoint)) {
-                std::stringstream ss;
-                ss << "Adding sync point " << mCurrentState.barrierFrameNumber;
-                ATRACE_NAME(ss.str().c_str());
-                mRemoteSyncPoints.push_back(std::move(syncPoint));
-            } else {
-                // We already missed the frame we're supposed to synchronize
-                // on, so go ahead and apply the state update
-                mCurrentState.barrierLayer_legacy = nullptr;
-            }
-        }
-
-        // Wake us up to check if the frame has been received
-        setTransactionFlags(eTransactionNeeded);
-        mFlinger->setTransactionFlags(eTraversalNeeded);
-    }
-    if (mCurrentState.bufferlessSurfaceFramesTX.size() >= State::kStateSurfaceFramesThreshold) {
-        // Ideally, the currentState would only contain one SurfaceFrame per transaction (assuming
-        // each Tx uses a different token). We don't expect the current state to hold a huge amount
-        // of SurfaceFrames. However, in the event it happens, this debug statement will leave a
-        // trail that can help in debugging.
-        ALOGW("Bufferless SurfaceFrames size on current state of layer %s is %" PRIu32 "",
-              mName.c_str(), static_cast<uint32_t>(mCurrentState.bufferlessSurfaceFramesTX.size()));
-    }
-    mPendingStates.push_back(mCurrentState);
-    // Since the current state along with the SurfaceFrames has been pushed into the pendingState,
-    // we no longer need to retain them. If multiple states are pushed and applied together, we have
-    // a merging logic to address the SurfaceFrames at mergeSurfaceFrames().
-    mCurrentState.bufferlessSurfaceFramesTX.clear();
-    ATRACE_INT(mTransactionName.c_str(), mPendingStates.size());
-}
-
-void Layer::mergeSurfaceFrames(State& source, State& target) {
-    // No need to merge BufferSurfaceFrame as the target's surfaceFrame, if it exists, will be used
-    // directly. Dropping of source's SurfaceFrame is taken care of at setBuffer().
-    target.bufferlessSurfaceFramesTX.merge(source.bufferlessSurfaceFramesTX);
-    source.bufferlessSurfaceFramesTX.clear();
-}
-
-void Layer::popPendingState(State* stateToCommit) {
-    ATRACE_CALL();
-
-    mergeSurfaceFrames(*stateToCommit, mPendingStates[0]);
-    *stateToCommit = mPendingStates[0];
-    mPendingStates.pop_front();
-    ATRACE_INT(mTransactionName.c_str(), mPendingStates.size());
-}
-
-bool Layer::applyPendingStates(State* stateToCommit) {
-    bool stateUpdateAvailable = false;
-    while (!mPendingStates.empty()) {
-        if (mPendingStates[0].barrierLayer_legacy != nullptr) {
-            if (mRemoteSyncPoints.empty()) {
-                // If we don't have a sync point for this, apply it anyway. It
-                // will be visually wrong, but it should keep us from getting
-                // into too much trouble.
-                ALOGV("[%s] No local sync point found", getDebugName());
-                popPendingState(stateToCommit);
-                stateUpdateAvailable = true;
-                continue;
-            }
-
-            if (mRemoteSyncPoints.front()->getFrameNumber() !=
-                mPendingStates[0].barrierFrameNumber) {
-                ALOGE("[%s] Unexpected sync point frame number found", getDebugName());
-
-                // Signal our end of the sync point and then dispose of it
-                mRemoteSyncPoints.front()->setTransactionApplied();
-                mRemoteSyncPoints.pop_front();
-                continue;
-            }
-
-            if (mRemoteSyncPoints.front()->frameIsAvailable()) {
-                ATRACE_NAME("frameIsAvailable");
-                // Apply the state update
-                popPendingState(stateToCommit);
-                stateUpdateAvailable = true;
-
-                // Signal our end of the sync point and then dispose of it
-                mRemoteSyncPoints.front()->setTransactionApplied();
-                mRemoteSyncPoints.pop_front();
-            } else {
-                ATRACE_NAME("!frameIsAvailable");
-                mRemoteSyncPoints.front()->checkTimeoutAndLog();
-                break;
-            }
-        } else {
-            popPendingState(stateToCommit);
-            stateUpdateAvailable = true;
-        }
-    }
-
-    // If we still have pending updates, we need to ensure SurfaceFlinger
-    // will keep calling doTransaction, and so we force a traversal.
-    // However, our pending states won't clear until a frame is available,
-    // and so there is no need to specifically trigger a wakeup.
-    if (!mPendingStates.empty()) {
-        setTransactionFlags(eTransactionNeeded);
-        mFlinger->setTraversalNeeded();
-    }
-
-    mCurrentState.modified = false;
-    return stateUpdateAvailable;
-}
-
 uint32_t Layer::doTransactionResize(uint32_t flags, State* stateToCommit) {
     const State& s(getDrawingState());
 
@@ -1014,15 +845,14 @@
         mChildrenChanged = false;
     }
 
-    pushPendingState();
-    State c = getCurrentState();
-    if (!applyPendingStates(&c)) {
-        return flags;
-    }
+    // TODO: This is unfortunate.
+    mCurrentStateModified = mCurrentState.modified;
+    mCurrentState.modified = false;
 
-    flags = doTransactionResize(flags, &c);
+    flags = doTransactionResize(flags, &mCurrentState);
 
     const State& s(getDrawingState());
+    State& c(getCurrentState());
 
     if (getActiveGeometry(c) != getActiveGeometry(s)) {
         // invalidate and recompute the visible regions if needed
@@ -1054,7 +884,6 @@
 
     // Commit the transaction
     commitTransaction(c);
-    mPendingStatesSnapshot = mPendingStates;
     mCurrentState.callbackHandles = {};
 
     return flags;
@@ -1662,25 +1491,6 @@
     return frameRate;
 }
 
-void Layer::deferTransactionUntil_legacy(const sp<Layer>& barrierLayer, uint64_t frameNumber) {
-    ATRACE_CALL();
-
-    mCurrentState.barrierLayer_legacy = barrierLayer;
-    mCurrentState.barrierFrameNumber = frameNumber;
-    // We don't set eTransactionNeeded, because just receiving a deferral
-    // request without any other state updates shouldn't actually induce a delay
-    mCurrentState.modified = true;
-    pushPendingState();
-    mCurrentState.barrierLayer_legacy = nullptr;
-    mCurrentState.barrierFrameNumber = 0;
-    mCurrentState.modified = false;
-}
-
-void Layer::deferTransactionUntil_legacy(const sp<IBinder>& barrierHandle, uint64_t frameNumber) {
-    sp<Handle> handle = static_cast<Handle*>(barrierHandle.get());
-    deferTransactionUntil_legacy(handle->owner.promote(), frameNumber);
-}
-
 // ----------------------------------------------------------------------------
 // pageflip handling...
 // ----------------------------------------------------------------------------
@@ -1949,32 +1759,6 @@
     return removeResult;
 }
 
-void Layer::reparentChildren(const sp<Layer>& newParent) {
-    for (const sp<Layer>& child : mCurrentChildren) {
-        newParent->addChild(child);
-    }
-    mCurrentChildren.clear();
-    updateTreeHasFrameRateVote();
-}
-
-bool Layer::reparentChildren(const sp<IBinder>& newParentHandle) {
-    sp<Handle> handle = nullptr;
-    sp<Layer> newParent = nullptr;
-    if (newParentHandle == nullptr) {
-        return false;
-    }
-    handle = static_cast<Handle*>(newParentHandle.get());
-    newParent = handle->owner.promote();
-    if (newParent == nullptr) {
-        ALOGE("Unable to promote Layer handle");
-        return false;
-    }
-
-    reparentChildren(newParent);
-
-    return true;
-}
-
 void Layer::setChildrenDrawingParent(const sp<Layer>& newParent) {
     for (const sp<Layer>& child : mDrawingChildren) {
         child->mDrawingParent = newParent;
@@ -2290,8 +2074,13 @@
     return parentAlpha * getDrawingState().backgroundBlurRadius;
 }
 
-const std::vector<BlurRegion>& Layer::getBlurRegions() const {
-    return getDrawingState().blurRegions;
+const std::vector<BlurRegion> Layer::getBlurRegions() const {
+    auto regionsCopy(getDrawingState().blurRegions);
+    int layerAlpha = getAlpha();
+    for (auto& region : regionsCopy) {
+        region.alpha = region.alpha * layerAlpha;
+    }
+    return regionsCopy;
 }
 
 Layer::RoundedCornerState Layer::getRoundedCornerState() const {
@@ -2313,8 +2102,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();
 }
 
@@ -2388,14 +2177,6 @@
     const ui::Transform transform = getTransform();
 
     if (traceFlags & SurfaceTracing::TRACE_CRITICAL) {
-        for (const auto& pendingState : mPendingStatesSnapshot) {
-            auto barrierLayer = pendingState.barrierLayer_legacy.promote();
-            if (barrierLayer != nullptr) {
-                BarrierLayerProto* barrierLayerProto = layerInfo->add_barrier_layer();
-                barrierLayerProto->set_id(barrierLayer->sequence);
-                barrierLayerProto->set_frame_number(pendingState.barrierFrameNumber);
-            }
-        }
 
         auto buffer = getBuffer();
         if (buffer != nullptr) {
@@ -2535,14 +2316,22 @@
     return mRemovedFromCurrentState;
 }
 
+ui::Transform Layer::getInputTransform() const {
+    return getTransform();
+}
+
+Rect Layer::getInputBounds() const {
+    return getCroppedBufferSize(getDrawingState());
+}
+
 void Layer::fillInputFrameInfo(InputWindowInfo& info, const ui::Transform& toPhysicalDisplay) {
     // Transform layer size to screen space and inset it by surface insets.
     // If this is a portal window, set the touchableRegion to the layerBounds.
     Rect layerBounds = info.portalToDisplayId == ADISPLAY_ID_NONE
-            ? getBufferSize(getDrawingState())
+            ? getInputBounds()
             : info.touchableRegion.getBounds();
     if (!layerBounds.isValid()) {
-        layerBounds = getCroppedBufferSize(getDrawingState());
+        layerBounds = getInputBounds();
     }
 
     if (!layerBounds.isValid()) {
@@ -2555,7 +2344,7 @@
         return;
     }
 
-    ui::Transform layerToDisplay = getTransform();
+    ui::Transform layerToDisplay = getInputTransform();
     // Transform that takes window coordinates to unrotated display coordinates
     ui::Transform t = toPhysicalDisplay * layerToDisplay;
     int32_t xSurfaceInset = info.surfaceInset;
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index aafe41c..5379d74 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -166,11 +166,6 @@
         Rect crop;
         Rect requestedCrop;
 
-        // If set, defers this state update until the identified Layer
-        // receives a frame with the given frameNumber
-        wp<Layer> barrierLayer_legacy;
-        uint64_t barrierFrameNumber;
-
         // the transparentRegion hint is a bit special, it's latched only
         // when we receive a buffer -- this is because it's "content"
         // dependent.
@@ -398,9 +393,6 @@
     virtual bool setFlags(uint32_t flags, uint32_t mask);
     virtual bool setLayerStack(uint32_t layerStack);
     virtual uint32_t getLayerStack() const;
-    virtual void deferTransactionUntil_legacy(const sp<IBinder>& barrierHandle,
-                                              uint64_t frameNumber);
-    virtual void deferTransactionUntil_legacy(const sp<Layer>& barrierLayer, uint64_t frameNumber);
     virtual bool setMetadata(const LayerMetadata& data);
     virtual void setChildrenDrawingParent(const sp<Layer>&);
     virtual bool reparent(const sp<IBinder>& newParentHandle);
@@ -412,7 +404,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*/,
@@ -579,14 +570,6 @@
 
     virtual int32_t getQueuedFrameCount() const { return 0; }
 
-    virtual void pushPendingState();
-
-    /*
-     * Merges the BufferlessSurfaceFrames from source with the target. If the same token exists in
-     * both source and target, target's SurfaceFrame will be retained.
-     */
-    void mergeSurfaceFrames(State& source, State& target);
-
     /**
      * Returns active buffer size in the correct orientation. Buffer size is determined by undoing
      * any buffer transformations. If the layer has no buffer then return INVALID_RECT.
@@ -616,7 +599,6 @@
     // ignored.
     virtual RoundedCornerState getRoundedCornerState() const;
 
-    virtual void notifyAvailableFrames(nsecs_t /*expectedPresentTime*/) {}
     virtual PixelFormat getPixelFormat() const { return PIXEL_FORMAT_NONE; }
     /**
      * Return whether this layer needs an input info. For most layer types
@@ -638,8 +620,6 @@
     void onLayerDisplayed(const sp<Fence>& releaseFence) override;
     const char* getDebugName() const override;
 
-    bool reparentChildren(const sp<IBinder>& newParentHandle);
-    void reparentChildren(const sp<Layer>& newParent);
     bool setShadowRadius(float shadowRadius);
 
     // Before color management is introduced, contents on Android have to be
@@ -906,65 +886,6 @@
     virtual std::string getPendingBufferCounterName() { return ""; }
 
 protected:
-    class SyncPoint {
-    public:
-        explicit SyncPoint(uint64_t frameNumber, wp<Layer> requestedSyncLayer,
-                           wp<Layer> barrierLayer_legacy)
-              : mFrameNumber(frameNumber),
-                mFrameIsAvailable(false),
-                mTransactionIsApplied(false),
-                mRequestedSyncLayer(requestedSyncLayer),
-                mBarrierLayer_legacy(barrierLayer_legacy) {}
-        uint64_t getFrameNumber() const { return mFrameNumber; }
-
-        bool frameIsAvailable() const { return mFrameIsAvailable; }
-
-        void setFrameAvailable() { mFrameIsAvailable = true; }
-
-        bool transactionIsApplied() const { return mTransactionIsApplied; }
-
-        void setTransactionApplied() { mTransactionIsApplied = true; }
-
-        sp<Layer> getRequestedSyncLayer() { return mRequestedSyncLayer.promote(); }
-
-        sp<Layer> getBarrierLayer() const { return mBarrierLayer_legacy.promote(); }
-
-        bool isTimeout() const {
-            using namespace std::chrono_literals;
-            static constexpr std::chrono::nanoseconds TIMEOUT_THRESHOLD = 1s;
-
-            return std::chrono::steady_clock::now() - mCreateTimeStamp > TIMEOUT_THRESHOLD;
-        }
-
-        void checkTimeoutAndLog() {
-            using namespace std::chrono_literals;
-            static constexpr std::chrono::nanoseconds LOG_PERIOD = 1s;
-
-            if (!frameIsAvailable() && isTimeout()) {
-                const auto now = std::chrono::steady_clock::now();
-                if (now - mLastLogTime > LOG_PERIOD) {
-                    mLastLogTime = now;
-                    sp<Layer> requestedSyncLayer = getRequestedSyncLayer();
-                    sp<Layer> barrierLayer = getBarrierLayer();
-                    ALOGW("[%s] sync point %" PRIu64 " wait timeout %lld for %s",
-                          requestedSyncLayer ? requestedSyncLayer->getDebugName() : "Removed",
-                          mFrameNumber, (now - mCreateTimeStamp).count(),
-                          barrierLayer ? barrierLayer->getDebugName() : "Removed");
-                }
-            }
-        }
-
-    private:
-        const uint64_t mFrameNumber;
-        std::atomic<bool> mFrameIsAvailable;
-        std::atomic<bool> mTransactionIsApplied;
-        wp<Layer> mRequestedSyncLayer;
-        wp<Layer> mBarrierLayer_legacy;
-        const std::chrono::time_point<std::chrono::steady_clock> mCreateTimeStamp =
-                std::chrono::steady_clock::now();
-        std::chrono::time_point<std::chrono::steady_clock> mLastLogTime;
-    };
-
     friend class impl::SurfaceInterceptor;
 
     // For unit tests
@@ -983,7 +904,6 @@
             ui::Dataspace outputDataspace);
     virtual void preparePerFrameCompositionState();
     virtual void commitTransaction(State& stateToCommit);
-    virtual bool applyPendingStates(State* stateToCommit);
     virtual uint32_t doTransactionResize(uint32_t flags, Layer::State* stateToCommit);
     virtual void onSurfaceFrameCreated(const std::shared_ptr<frametimeline::SurfaceFrame>&) {}
 
@@ -1026,20 +946,8 @@
     compositionengine::OutputLayer* findOutputLayerForDisplay(const DisplayDevice*) const;
     bool usingRelativeZ(LayerVector::StateSet) const;
 
-    // SyncPoints which will be signaled when the correct frame is at the head
-    // of the queue and dropped after the frame has been latched. Protected by
-    // mLocalSyncPointMutex.
-    Mutex mLocalSyncPointMutex;
-    std::list<std::shared_ptr<SyncPoint>> mLocalSyncPoints;
-
-    // SyncPoints which will be signaled and then dropped when the transaction
-    // is applied
-    std::list<std::shared_ptr<SyncPoint>> mRemoteSyncPoints;
-
-    // Returns false if the relevant frame has already been latched
-    bool addSyncPoint(const std::shared_ptr<SyncPoint>& point);
-
-    void popPendingState(State* stateToCommit);
+    virtual ui::Transform getInputTransform() const;
+    virtual Rect getInputBounds() const;
 
     // constant
     sp<SurfaceFlinger> mFlinger;
@@ -1050,14 +958,10 @@
 
     // These are only accessed by the main thread or the tracing thread.
     State mDrawingState;
-    // Store a copy of the pending state so that the drawing thread can access the
-    // states without a lock.
-    std::deque<State> mPendingStatesSnapshot;
 
     // these are protected by an external lock (mStateLock)
     State mCurrentState;
     std::atomic<uint32_t> mTransactionFlags{0};
-    std::deque<State> mPendingStates;
 
     // Timestamp history for UIAutomation. Thread safe.
     FrameTracker mFrameTracker;
@@ -1119,6 +1023,8 @@
     // Used in buffer stuffing analysis in FrameTimeline.
     nsecs_t mLastLatchTime = 0;
 
+    mutable bool mCurrentStateModified = false;
+
 private:
     virtual void setTransformHint(ui::Transform::RotationFlags) {}
 
@@ -1143,7 +1049,6 @@
 
     void updateTreeHasFrameRateVote();
     void setZOrderRelativeOf(const wp<Layer>& relativeOf);
-    void removeRemoteSyncPoints();
 
     // Find the root of the cloned hierarchy, this means the first non cloned parent.
     // This will return null if first non cloned parent is not found.
@@ -1191,7 +1096,7 @@
     float mEffectiveShadowRadius = 0.f;
 
     // A list of regions on this layer that should have blurs.
-    const std::vector<BlurRegion>& getBlurRegions() const;
+    const std::vector<BlurRegion> getBlurRegions() const;
 };
 
 std::ostream& operator<<(std::ostream& stream, const Layer::FrameRate& rate);
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/Scheduler/EventThread.cpp b/services/surfaceflinger/Scheduler/EventThread.cpp
index 6553efe..2321e2d 100644
--- a/services/surfaceflinger/Scheduler/EventThread.cpp
+++ b/services/surfaceflinger/Scheduler/EventThread.cpp
@@ -217,12 +217,18 @@
 EventThread::EventThread(std::unique_ptr<VSyncSource> vsyncSource,
                          android::frametimeline::TokenManager* tokenManager,
                          InterceptVSyncsCallback interceptVSyncsCallback,
-                         ThrottleVsyncCallback throttleVsyncCallback)
+                         ThrottleVsyncCallback throttleVsyncCallback,
+                         GetVsyncPeriodFunction getVsyncPeriodFunction)
       : mVSyncSource(std::move(vsyncSource)),
         mTokenManager(tokenManager),
         mInterceptVSyncsCallback(std::move(interceptVSyncsCallback)),
         mThrottleVsyncCallback(std::move(throttleVsyncCallback)),
+        mGetVsyncPeriodFunction(std::move(getVsyncPeriodFunction)),
         mThreadName(mVSyncSource->getName()) {
+
+    LOG_ALWAYS_FATAL_IF(getVsyncPeriodFunction == nullptr,
+            "getVsyncPeriodFunction must not be null");
+
     mVSyncSource->setCallback(this);
 
     mThread = std::thread([this]() NO_THREAD_SAFETY_ANALYSIS {
@@ -565,7 +571,11 @@
 void EventThread::dispatchEvent(const DisplayEventReceiver::Event& event,
                                 const DisplayEventConsumers& consumers) {
     for (const auto& consumer : consumers) {
-        switch (consumer->postEvent(event)) {
+        DisplayEventReceiver::Event copy = event;
+        if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
+            copy.vsync.frameInterval = mGetVsyncPeriodFunction(consumer->mOwnerUid);
+        }
+        switch (consumer->postEvent(copy)) {
             case NO_ERROR:
                 break;
 
diff --git a/services/surfaceflinger/Scheduler/EventThread.h b/services/surfaceflinger/Scheduler/EventThread.h
index 3540604..1e6793f 100644
--- a/services/surfaceflinger/Scheduler/EventThread.h
+++ b/services/surfaceflinger/Scheduler/EventThread.h
@@ -152,9 +152,10 @@
 public:
     using InterceptVSyncsCallback = std::function<void(nsecs_t)>;
     using ThrottleVsyncCallback = std::function<bool(nsecs_t, uid_t)>;
+    using GetVsyncPeriodFunction = std::function<nsecs_t(uid_t)>;
 
     EventThread(std::unique_ptr<VSyncSource>, frametimeline::TokenManager*, InterceptVSyncsCallback,
-                ThrottleVsyncCallback);
+                ThrottleVsyncCallback, GetVsyncPeriodFunction);
     ~EventThread();
 
     sp<EventThreadConnection> createEventConnection(
@@ -210,6 +211,7 @@
 
     const InterceptVSyncsCallback mInterceptVSyncsCallback;
     const ThrottleVsyncCallback mThrottleVsyncCallback;
+    const GetVsyncPeriodFunction mGetVsyncPeriodFunction;
     const char* const mThreadName;
 
     std::thread mThread;
diff --git a/services/surfaceflinger/Scheduler/LayerInfo.cpp b/services/surfaceflinger/Scheduler/LayerInfo.cpp
index 3630ad8..989bf4e 100644
--- a/services/surfaceflinger/Scheduler/LayerInfo.cpp
+++ b/services/surfaceflinger/Scheduler/LayerInfo.cpp
@@ -235,6 +235,8 @@
     if (!isFrequent(now)) {
         ALOGV("%s is infrequent", mName.c_str());
         mLastRefreshRate.animatingOrInfrequent = true;
+        // Infrequent layers vote for mininal refresh rate for
+        // battery saving purposes and also to prevent b/135718869.
         return {LayerHistory::LayerVoteType::Min, Fps(0.0f)};
     }
 
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index 8426737..1d25c72 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -248,15 +248,34 @@
     };
 }
 
+impl::EventThread::GetVsyncPeriodFunction Scheduler::makeGetVsyncPeriodFunction() const {
+    return [this](uid_t uid) {
+        nsecs_t basePeriod = mRefreshRateConfigs.getCurrentRefreshRate().getVsyncPeriod();
+        const auto frameRate = getFrameRateOverride(uid);
+        if (!frameRate.has_value()) {
+            return basePeriod;
+        }
+
+        const auto divider = scheduler::RefreshRateConfigs::getFrameRateDivider(
+            mRefreshRateConfigs.getCurrentRefreshRate().getFps(), *frameRate);
+        if (divider <= 1) {
+            return basePeriod;
+        }
+        return basePeriod * divider;
+    };
+}
+
 Scheduler::ConnectionHandle Scheduler::createConnection(
         const char* connectionName, frametimeline::TokenManager* tokenManager,
         std::chrono::nanoseconds workDuration, std::chrono::nanoseconds readyDuration,
         impl::EventThread::InterceptVSyncsCallback interceptCallback) {
     auto vsyncSource = makePrimaryDispSyncSource(connectionName, workDuration, readyDuration);
     auto throttleVsync = makeThrottleVsyncCallback();
+    auto getVsyncPeriod = makeGetVsyncPeriodFunction();
     auto eventThread = std::make_unique<impl::EventThread>(std::move(vsyncSource), tokenManager,
                                                            std::move(interceptCallback),
-                                                           std::move(throttleVsync));
+                                                           std::move(throttleVsync),
+                                                           std::move(getVsyncPeriod));
     return createConnection(std::move(eventThread));
 }
 
@@ -444,7 +463,8 @@
                 std::make_unique<impl::EventThread>(std::move(vsyncSource),
                                                     /*tokenManager=*/nullptr,
                                                     impl::EventThread::InterceptVSyncsCallback(),
-                                                    impl::EventThread::ThrottleVsyncCallback());
+                                                    impl::EventThread::ThrottleVsyncCallback(),
+                                                    impl::EventThread::GetVsyncPeriodFunction());
 
         // EventThread does not dispatch VSYNC unless the display is connected and powered on.
         eventThread->onHotplugReceived(PhysicalDisplayId::fromPort(0), true);
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index d4932e7..4d1f3c6 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -240,6 +240,7 @@
             EXCLUDES(mFrameRateOverridesMutex);
 
     impl::EventThread::ThrottleVsyncCallback makeThrottleVsyncCallback() const;
+    impl::EventThread::GetVsyncPeriodFunction makeGetVsyncPeriodFunction() const;
 
     // Stores EventThread associated with a given VSyncSource, and an initial EventThreadConnection.
     struct Connection {
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 41f211f..89ce9d2 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -693,12 +693,16 @@
 
     // The pool was empty, so we need to get a new texture name directly using a
     // blocking call to the main thread
-    return schedule([this] {
+    auto genTextures = [this] {
                uint32_t name = 0;
                getRenderEngine().genTextures(1, &name);
                return name;
-           })
-            .get();
+    };
+    if (std::this_thread::get_id() == mMainThreadId) {
+        return genTextures();
+    } else {
+        return schedule(genTextures).get();
+    }
 }
 
 void SurfaceFlinger::deleteTextureAsync(uint32_t texture) {
@@ -1814,10 +1818,6 @@
     if (frameMissed) {
         mFrameMissedCount++;
         mTimeStats->incrementMissedFrames();
-        if (mMissedFrameJankCount == 0) {
-            mMissedFrameJankStart = systemTime();
-        }
-        mMissedFrameJankCount++;
     }
 
     if (hwcFrameMissed) {
@@ -1849,37 +1849,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 +1895,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 +2270,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;
     }
@@ -2859,13 +2819,6 @@
 }
 
 void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) {
-    const nsecs_t expectedPresentTime = mExpectedPresentTime.load();
-
-    // Notify all layers of available frames
-    mCurrentState.traverse([expectedPresentTime](Layer* layer) {
-        layer->notifyAvailableFrames(expectedPresentTime);
-    });
-
     /*
      * Traversal of the children
      * (perform the transaction for each of them if needed)
@@ -3361,8 +3314,12 @@
             }
         }
 
-        if (const auto display = getDefaultDisplayDeviceLocked()) {
-            lbc->updateTransformHint(display->getTransformHint());
+        if (const auto token = getInternalDisplayTokenLocked()) {
+            const ssize_t index = mCurrentState.displays.indexOfKey(token);
+            if (index >= 0) {
+                const DisplayDeviceState& state = mCurrentState.displays.valueAt(index);
+                lbc->updateTransformHint(ui::Transform::toRotationFlags(state.orientation));
+            }
         }
         if (outTransformHint) {
             *outTransformHint = lbc->getTransformHint();
@@ -3873,12 +3830,6 @@
 
     const uint64_t what = s.what;
 
-    // If we are deferring transaction, make sure to push the pending state, as otherwise the
-    // pending state will also be deferred.
-    if (what & layer_state_t::eDeferTransaction_legacy) {
-        layer->pushPendingState();
-    }
-
     // Only set by BLAST adapter layers
     if (what & layer_state_t::eProducerDisconnect) {
         layer->onDisconnect();
@@ -4013,17 +3964,6 @@
             flags |= eTransactionNeeded | eTraversalNeeded | eTransformHintUpdateNeeded;
         }
     }
-    if (what & layer_state_t::eDeferTransaction_legacy) {
-        layer->deferTransactionUntil_legacy(s.barrierSurfaceControl_legacy->getHandle(),
-                                            s.barrierFrameNumber);
-        // We don't trigger a traversal here because if no other state is
-        // changed, we don't want this to cause any more work
-    }
-    if (what & layer_state_t::eReparentChildren) {
-        if (layer->reparentChildren(s.reparentSurfaceControl->getHandle())) {
-            flags |= eTransactionNeeded|eTraversalNeeded;
-        }
-    }
     if (what & layer_state_t::eTransformChanged) {
         if (layer->setTransform(s.transform)) flags |= eTraversalNeeded;
     }
@@ -4034,9 +3974,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;
     }
@@ -5578,9 +5515,24 @@
                 const int modeId = data.readInt32();
                 mDebugDisplayModeSetByBackdoor = false;
 
-                const auto displayId = getInternalDisplayId();
+                const auto displayId = [&]() -> std::optional<PhysicalDisplayId> {
+                    uint64_t inputDisplayId = 0;
+                    if (data.readUint64(&inputDisplayId) == NO_ERROR) {
+                        const auto token = getPhysicalDisplayToken(
+                                static_cast<PhysicalDisplayId>(inputDisplayId));
+                        if (!token) {
+                            ALOGE("No display with id: %" PRIu64, inputDisplayId);
+                            return std::nullopt;
+                        }
+
+                        return std::make_optional<PhysicalDisplayId>(inputDisplayId);
+                    }
+
+                    return getInternalDisplayId();
+                }();
+
                 if (!displayId) {
-                    ALOGE("No internal display found.");
+                    ALOGE("No display found");
                     return NO_ERROR;
                 }
 
@@ -6051,11 +6003,8 @@
     const status_t bufferStatus = buffer->initCheck();
     LOG_ALWAYS_FATAL_IF(bufferStatus != OK, "captureScreenCommon: Buffer failed to allocate: %d",
                         bufferStatus);
-    getRenderEngine().cacheExternalTextureBuffer(buffer);
-    status_t result = captureScreenCommon(std::move(renderAreaFuture), traverseLayers, buffer,
-                                          false /* regionSampling */, grayscale, captureListener);
-    getRenderEngine().unbindExternalTextureBuffer(buffer->getId());
-    return result;
+    return captureScreenCommon(std::move(renderAreaFuture), traverseLayers, buffer,
+                               false /* regionSampling */, grayscale, captureListener);
 }
 
 status_t SurfaceFlinger::captureScreenCommon(RenderAreaFuture renderAreaFuture,
@@ -6095,6 +6044,15 @@
                                             regionSampling, grayscale, captureResults);
         });
 
+        // TODO(b/180767535): Remove this once we optimize buffer lifecycle for RenderEngine
+        // Only do this when we're not doing region sampling, to allow the region sampling thread to
+        // manage buffer lifecycle itself.
+        if (!regionSampling &&
+            getRenderEngine().getRenderEngineType() ==
+                    renderengine::RenderEngine::RenderEngineType::SKIA_GL_THREADED) {
+            getRenderEngine().unbindExternalTextureBuffer(buffer->getId());
+        }
+
         captureResults.result = result;
         captureListener->onScreenCaptureCompleted(captureResults);
     }));
@@ -6287,6 +6245,11 @@
                         "Can only set override policy on the primary display");
     LOG_ALWAYS_FATAL_IF(!policy && !overridePolicy, "Can only clear the override policy");
 
+    if (mDebugDisplayModeSetByBackdoor) {
+        // ignore this request as mode is overridden by backdoor
+        return NO_ERROR;
+    }
+
     if (!display->isPrimary()) {
         // TODO(b/144711714): For non-primary displays we should be able to set an active mode
         // as well. For now, just call directly to initiateModeChange but ideally
@@ -6313,11 +6276,6 @@
         return NO_ERROR;
     }
 
-    if (mDebugDisplayModeSetByBackdoor) {
-        // ignore this request as mode is overridden by backdoor
-        return NO_ERROR;
-    }
-
     status_t setPolicyResult = overridePolicy
             ? mRefreshRateConfigs->setOverridePolicy(policy)
             : mRefreshRateConfigs->setDisplayManagerPolicy(*policy);
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/SurfaceInterceptor.cpp b/services/surfaceflinger/SurfaceInterceptor.cpp
index 8a3be9f..113f463 100644
--- a/services/surfaceflinger/SurfaceInterceptor.cpp
+++ b/services/surfaceflinger/SurfaceInterceptor.cpp
@@ -141,11 +141,6 @@
     addCornerRadiusLocked(transaction, layerId, layer->mCurrentState.cornerRadius);
     addBackgroundBlurRadiusLocked(transaction, layerId, layer->mCurrentState.backgroundBlurRadius);
     addBlurRegionsLocked(transaction, layerId, layer->mCurrentState.blurRegions);
-    if (layer->mCurrentState.barrierLayer_legacy != nullptr) {
-        addDeferTransactionLocked(transaction, layerId,
-                                  layer->mCurrentState.barrierLayer_legacy.promote(),
-                                  layer->mCurrentState.barrierFrameNumber);
-    }
     addFlagsLocked(transaction, layerId, layer->mCurrentState.flags,
                    layer_state_t::eLayerHidden | layer_state_t::eLayerOpaque |
                            layer_state_t::eLayerSecure);
@@ -380,20 +375,6 @@
     }
 }
 
-void SurfaceInterceptor::addDeferTransactionLocked(Transaction* transaction, int32_t layerId,
-        const sp<const Layer>& layer, uint64_t frameNumber)
-{
-    SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId));
-    if (layer == nullptr) {
-        ALOGE("An existing layer could not be retrieved with the handle"
-                " for the deferred transaction");
-        return;
-    }
-    DeferredTransactionChange* deferTransaction(change->mutable_deferred_transaction());
-    deferTransaction->set_layer_id(getLayerId(layer));
-    deferTransaction->set_frame_number(frameNumber);
-}
-
 void SurfaceInterceptor::addReparentLocked(Transaction* transaction, int32_t layerId,
                                            int32_t parentId) {
     SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId));
@@ -401,13 +382,6 @@
     overrideChange->set_parent_id(parentId);
 }
 
-void SurfaceInterceptor::addReparentChildrenLocked(Transaction* transaction, int32_t layerId,
-                                                   int32_t parentId) {
-    SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId));
-    ReparentChildrenChange* overrideChange(change->mutable_reparent_children());
-    overrideChange->set_parent_id(parentId);
-}
-
 void SurfaceInterceptor::addRelativeParentLocked(Transaction* transaction, int32_t layerId,
                                                  int32_t parentId, int z) {
     SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId));
@@ -471,25 +445,12 @@
     if (state.what & layer_state_t::eBlurRegionsChanged) {
         addBlurRegionsLocked(transaction, layerId, state.blurRegions);
     }
-    if (state.what & layer_state_t::eDeferTransaction_legacy) {
-        sp<Layer> otherLayer = nullptr;
-        if (state.barrierSurfaceControl_legacy != nullptr) {
-            otherLayer = static_cast<Layer::Handle*>(
-                                 state.barrierSurfaceControl_legacy->getHandle().get())
-                                 ->owner.promote();
-        }
-        addDeferTransactionLocked(transaction, layerId, otherLayer, state.barrierFrameNumber);
-    }
     if (state.what & layer_state_t::eReparent) {
         auto parentHandle = (state.parentSurfaceControlForChild)
                 ? state.parentSurfaceControlForChild->getHandle()
                 : nullptr;
         addReparentLocked(transaction, layerId, getLayerIdFromHandle(parentHandle));
     }
-    if (state.what & layer_state_t::eReparentChildren) {
-        addReparentChildrenLocked(transaction, layerId,
-                                  getLayerIdFromHandle(state.reparentSurfaceControl->getHandle()));
-    }
     if (state.what & layer_state_t::eRelativeLayerChanged) {
         addRelativeParentLocked(transaction, layerId,
                                 getLayerIdFromHandle(
diff --git a/services/surfaceflinger/SurfaceInterceptor.h b/services/surfaceflinger/SurfaceInterceptor.h
index 3e27e83..30aca83 100644
--- a/services/surfaceflinger/SurfaceInterceptor.h
+++ b/services/surfaceflinger/SurfaceInterceptor.h
@@ -167,8 +167,6 @@
                                        int32_t backgroundBlurRadius);
     void addBlurRegionsLocked(Transaction* transaction, int32_t layerId,
                               const std::vector<BlurRegion>& effectRegions);
-    void addDeferTransactionLocked(Transaction* transaction, int32_t layerId,
-            const sp<const Layer>& layer, uint64_t frameNumber);
     void addSurfaceChangesLocked(Transaction* transaction, const layer_state_t& state);
     void addTransactionLocked(Increment* increment, const Vector<ComposerState>& stateUpdates,
                               const DefaultKeyedVector<wp<IBinder>, DisplayDeviceState>& displays,
@@ -176,7 +174,6 @@
                               uint32_t transactionFlags, int originPid, int originUid,
                               uint64_t transactionId);
     void addReparentLocked(Transaction* transaction, int32_t layerId, int32_t parentId);
-    void addReparentChildrenLocked(Transaction* transaction, int32_t layerId, int32_t parentId);
     void addRelativeParentLocked(Transaction* transaction, int32_t layerId, int32_t parentId,
                                  int z);
     void addShadowRadiusLocked(Transaction* transaction, int32_t layerId, float shadowRadius);
diff --git a/services/surfaceflinger/main_surfaceflinger.cpp b/services/surfaceflinger/main_surfaceflinger.cpp
index 2b8424c..9686523 100644
--- a/services/surfaceflinger/main_surfaceflinger.cpp
+++ b/services/surfaceflinger/main_surfaceflinger.cpp
@@ -89,13 +89,47 @@
     // binder threads to 4.
     ProcessState::self()->setThreadPoolMaxThreadCount(4);
 
+    // The binder threadpool we start will inherit sched policy and priority
+    // of (this) creating thread. We want the binder thread pool to have
+    // SCHED_FIFO policy and priority 1 (lowest RT priority)
+    // Once the pool is created we reset this thread's priority back to
+    // original.
+    int newPriority = 0;
+    int origPolicy = sched_getscheduler(0);
+    struct sched_param origSchedParam;
+
+    int errorInPriorityModification = sched_getparam(0, &origSchedParam);
+    if (errorInPriorityModification == 0) {
+        int policy = SCHED_FIFO;
+        newPriority = sched_get_priority_min(policy);
+
+        struct sched_param param;
+        param.sched_priority = newPriority;
+
+        errorInPriorityModification = sched_setscheduler(0, policy, &param);
+    }
+
     // start the thread pool
     sp<ProcessState> ps(ProcessState::self());
     ps->startThreadPool();
 
+    // Reset current thread's policy and priority
+    if (errorInPriorityModification == 0) {
+        errorInPriorityModification = sched_setscheduler(0, origPolicy, &origSchedParam);
+    } else {
+        ALOGE("Failed to set SurfaceFlinger binder threadpool priority to SCHED_FIFO");
+    }
+
     // instantiate surfaceflinger
     sp<SurfaceFlinger> flinger = surfaceflinger::createSurfaceFlinger();
 
+    // Set the minimum policy of surfaceflinger node to be SCHED_FIFO.
+    // So any thread with policy/priority lower than {SCHED_FIFO, 1}, will run
+    // at least with SCHED_FIFO policy and priority 1.
+    if (errorInPriorityModification == 0) {
+        flinger->setMinSchedulerPolicy(SCHED_FIFO, newPriority);
+    }
+
     setpriority(PRIO_PROCESS, 0, PRIORITY_URGENT_DISPLAY);
 
     set_sched_policy(0, SP_FOREGROUND);
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/LayerUpdate_test.cpp b/services/surfaceflinger/tests/LayerUpdate_test.cpp
index e5c2ec8..adb5d58 100644
--- a/services/surfaceflinger/tests/LayerUpdate_test.cpp
+++ b/services/surfaceflinger/tests/LayerUpdate_test.cpp
@@ -160,61 +160,6 @@
     }
 };
 
-TEST_F(LayerUpdateTest, DeferredTransactionTest) {
-    std::unique_ptr<ScreenCapture> sc;
-    {
-        SCOPED_TRACE("before anything");
-        ScreenCapture::captureScreen(&sc);
-        sc->expectBGColor(32, 32);
-        sc->expectFGColor(96, 96);
-        sc->expectBGColor(160, 160);
-    }
-
-    // set up two deferred transactions on different frames
-    asTransaction([&](Transaction& t) {
-        t.setAlpha(mFGSurfaceControl, 0.75);
-        t.deferTransactionUntil_legacy(mFGSurfaceControl, mSyncSurfaceControl,
-                                       mSyncSurfaceControl->getSurface()->getNextFrameNumber());
-    });
-
-    asTransaction([&](Transaction& t) {
-        t.setPosition(mFGSurfaceControl, 128, 128);
-        t.deferTransactionUntil_legacy(mFGSurfaceControl, mSyncSurfaceControl,
-                                       mSyncSurfaceControl->getSurface()->getNextFrameNumber() + 1);
-    });
-
-    {
-        SCOPED_TRACE("before any trigger");
-        ScreenCapture::captureScreen(&sc);
-        sc->expectBGColor(32, 32);
-        sc->expectFGColor(96, 96);
-        sc->expectBGColor(160, 160);
-    }
-
-    // should trigger the first deferred transaction, but not the second one
-    TransactionUtils::fillSurfaceRGBA8(mSyncSurfaceControl, 31, 31, 31);
-    {
-        SCOPED_TRACE("after first trigger");
-        ScreenCapture::captureScreen(&sc);
-        sc->expectBGColor(32, 32);
-        sc->checkPixel(96, 96, 162, 63, 96);
-        sc->expectBGColor(160, 160);
-    }
-
-    // should show up immediately since it's not deferred
-    asTransaction([&](Transaction& t) { t.setAlpha(mFGSurfaceControl, 1.0); });
-
-    // trigger the second deferred transaction
-    TransactionUtils::fillSurfaceRGBA8(mSyncSurfaceControl, 31, 31, 31);
-    {
-        SCOPED_TRACE("after second trigger");
-        ScreenCapture::captureScreen(&sc);
-        sc->expectBGColor(32, 32);
-        sc->expectBGColor(96, 96);
-        sc->expectFGColor(160, 160);
-    }
-}
-
 TEST_F(LayerUpdateTest, LayerWithNoBuffersResizesImmediately) {
     std::unique_ptr<ScreenCapture> sc;
 
@@ -462,38 +407,6 @@
     }
 }
 
-TEST_F(ChildLayerTest, ReparentChildren) {
-    asTransaction([&](Transaction& t) {
-        t.show(mChild);
-        t.setPosition(mChild, 10, 10);
-        t.setPosition(mFGSurfaceControl, 64, 64);
-    });
-
-    {
-        mCapture = screenshot();
-        // Top left of foreground must now be visible
-        mCapture->expectFGColor(64, 64);
-        // But 10 pixels in we should see the child surface
-        mCapture->expectChildColor(74, 74);
-        // And 10 more pixels we should be back to the foreground surface
-        mCapture->expectFGColor(84, 84);
-    }
-
-    asTransaction(
-            [&](Transaction& t) { t.reparentChildren(mFGSurfaceControl, mBGSurfaceControl); });
-
-    {
-        mCapture = screenshot();
-        mCapture->expectFGColor(64, 64);
-        // In reparenting we should have exposed the entire foreground surface.
-        mCapture->expectFGColor(74, 74);
-        // And the child layer should now begin at 10, 10 (since the BG
-        // layer is at (0, 0)).
-        mCapture->expectBGColor(9, 9);
-        mCapture->expectChildColor(10, 10);
-    }
-}
-
 TEST_F(ChildLayerTest, ChildrenSurviveParentDestruction) {
     sp<SurfaceControl> mGrandChild =
             createSurface(mClient, "Grand Child", 10, 10, PIXEL_FORMAT_RGBA_8888, 0, mChild.get());
@@ -539,7 +452,7 @@
 
     asTransaction([&](Transaction& t) {
         t.reparent(mChild, nullptr);
-        t.reparentChildren(mChild, mFGSurfaceControl);
+        t.reparent(mGrandChild, mFGSurfaceControl);
     });
 
     {
@@ -734,36 +647,6 @@
     }
 }
 
-TEST_F(ChildLayerTest, Bug36858924) {
-    // Destroy the child layer
-    mChild.clear();
-
-    // Now recreate it as hidden
-    mChild = createSurface(mClient, "Child surface", 10, 10, PIXEL_FORMAT_RGBA_8888,
-                           ISurfaceComposerClient::eHidden, mFGSurfaceControl.get());
-
-    // Show the child layer in a deferred transaction
-    asTransaction([&](Transaction& t) {
-        t.deferTransactionUntil_legacy(mChild, mFGSurfaceControl,
-                                       mFGSurfaceControl->getSurface()->getNextFrameNumber());
-        t.show(mChild);
-    });
-
-    // Render the foreground surface a few times
-    //
-    // Prior to the bugfix for b/36858924, this would usually hang while trying to fill the third
-    // frame because SurfaceFlinger would never process the deferred transaction and would therefore
-    // never acquire/release the first buffer
-    ALOGI("Filling 1");
-    TransactionUtils::fillSurfaceRGBA8(mFGSurfaceControl, 0, 255, 0);
-    ALOGI("Filling 2");
-    TransactionUtils::fillSurfaceRGBA8(mFGSurfaceControl, 0, 0, 255);
-    ALOGI("Filling 3");
-    TransactionUtils::fillSurfaceRGBA8(mFGSurfaceControl, 255, 0, 0);
-    ALOGI("Filling 4");
-    TransactionUtils::fillSurfaceRGBA8(mFGSurfaceControl, 0, 255, 0);
-}
-
 TEST_F(ChildLayerTest, Reparent) {
     asTransaction([&](Transaction& t) {
         t.show(mChild);
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/SurfaceInterceptor_test.cpp b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp
index d9cab42..af23e2a 100644
--- a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp
+++ b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp
@@ -44,7 +44,6 @@
 constexpr uint32_t LAYER_UPDATE = INT_MAX - 2;
 constexpr uint32_t SIZE_UPDATE = 134;
 constexpr uint32_t STACK_UPDATE = 1;
-constexpr uint64_t DEFERRED_UPDATE = 0;
 constexpr int32_t RELATIVE_Z = 42;
 constexpr float ALPHA_UPDATE = 0.29f;
 constexpr float CORNER_RADIUS_UPDATE = 0.2f;
@@ -191,10 +190,8 @@
     bool hiddenFlagUpdateFound(const SurfaceChange& change, bool foundHiddenFlag);
     bool opaqueFlagUpdateFound(const SurfaceChange& change, bool foundOpaqueFlag);
     bool secureFlagUpdateFound(const SurfaceChange& change, bool foundSecureFlag);
-    bool deferredTransactionUpdateFound(const SurfaceChange& change, bool foundDeferred);
     bool reparentUpdateFound(const SurfaceChange& change, bool found);
     bool relativeParentUpdateFound(const SurfaceChange& change, bool found);
-    bool reparentChildrenUpdateFound(const SurfaceChange& change, bool found);
     bool shadowRadiusUpdateFound(const SurfaceChange& change, bool found);
     bool surfaceUpdateFound(const Trace& trace, SurfaceChange::SurfaceChangeCase changeCase);
 
@@ -228,10 +225,8 @@
     void hiddenFlagUpdate(Transaction&);
     void opaqueFlagUpdate(Transaction&);
     void secureFlagUpdate(Transaction&);
-    void deferredTransactionUpdate(Transaction&);
     void reparentUpdate(Transaction&);
     void relativeParentUpdate(Transaction&);
-    void reparentChildrenUpdate(Transaction&);
     void shadowRadiusUpdate(Transaction&);
     void surfaceCreation(Transaction&);
     void displayCreation(Transaction&);
@@ -398,10 +393,6 @@
     t.setFlags(mBGSurfaceControl, layer_state_t::eLayerSecure, layer_state_t::eLayerSecure);
 }
 
-void SurfaceInterceptorTest::deferredTransactionUpdate(Transaction& t) {
-    t.deferTransactionUntil_legacy(mBGSurfaceControl, mBGSurfaceControl, DEFERRED_UPDATE);
-}
-
 void SurfaceInterceptorTest::reparentUpdate(Transaction& t) {
     t.reparent(mBGSurfaceControl, mFGSurfaceControl);
 }
@@ -410,10 +401,6 @@
     t.setRelativeLayer(mBGSurfaceControl, mFGSurfaceControl, RELATIVE_Z);
 }
 
-void SurfaceInterceptorTest::reparentChildrenUpdate(Transaction& t) {
-    t.reparentChildren(mBGSurfaceControl, mFGSurfaceControl);
-}
-
 void SurfaceInterceptorTest::shadowRadiusUpdate(Transaction& t) {
     t.setShadowRadius(mBGSurfaceControl, SHADOW_RADIUS_UPDATE);
 }
@@ -443,9 +430,7 @@
     runInTransaction(&SurfaceInterceptorTest::hiddenFlagUpdate);
     runInTransaction(&SurfaceInterceptorTest::opaqueFlagUpdate);
     runInTransaction(&SurfaceInterceptorTest::secureFlagUpdate);
-    runInTransaction(&SurfaceInterceptorTest::deferredTransactionUpdate);
     runInTransaction(&SurfaceInterceptorTest::reparentUpdate);
-    runInTransaction(&SurfaceInterceptorTest::reparentChildrenUpdate);
     runInTransaction(&SurfaceInterceptorTest::relativeParentUpdate);
     runInTransaction(&SurfaceInterceptorTest::shadowRadiusUpdate);
 }
@@ -628,18 +613,6 @@
     return foundSecureFlag;
 }
 
-bool SurfaceInterceptorTest::deferredTransactionUpdateFound(const SurfaceChange& change,
-        bool foundDeferred) {
-    bool hasId(change.deferred_transaction().layer_id() == mBGLayerId);
-    bool hasFrameNumber(change.deferred_transaction().frame_number() == DEFERRED_UPDATE);
-    if (hasId && hasFrameNumber && !foundDeferred) {
-        foundDeferred = true;
-    } else if (hasId && hasFrameNumber && foundDeferred) {
-        [] () { FAIL(); }();
-    }
-    return foundDeferred;
-}
-
 bool SurfaceInterceptorTest::reparentUpdateFound(const SurfaceChange& change, bool found) {
     bool hasId(change.reparent().parent_id() == mFGLayerId);
     if (hasId && !found) {
@@ -660,16 +633,6 @@
     return found;
 }
 
-bool SurfaceInterceptorTest::reparentChildrenUpdateFound(const SurfaceChange& change, bool found) {
-    bool hasId(change.reparent_children().parent_id() == mFGLayerId);
-    if (hasId && !found) {
-        found = true;
-    } else if (hasId && found) {
-        []() { FAIL(); }();
-    }
-    return found;
-}
-
 bool SurfaceInterceptorTest::shadowRadiusUpdateFound(const SurfaceChange& change,
                                                      bool foundShadowRadius) {
     bool hasShadowRadius(change.shadow_radius().radius() == SHADOW_RADIUS_UPDATE);
@@ -732,15 +695,9 @@
                         case SurfaceChange::SurfaceChangeCase::kSecureFlag:
                             foundUpdate = secureFlagUpdateFound(change, foundUpdate);
                             break;
-                        case SurfaceChange::SurfaceChangeCase::kDeferredTransaction:
-                            foundUpdate = deferredTransactionUpdateFound(change, foundUpdate);
-                            break;
                         case SurfaceChange::SurfaceChangeCase::kReparent:
                             foundUpdate = reparentUpdateFound(change, foundUpdate);
                             break;
-                        case SurfaceChange::SurfaceChangeCase::kReparentChildren:
-                            foundUpdate = reparentChildrenUpdateFound(change, foundUpdate);
-                            break;
                         case SurfaceChange::SurfaceChangeCase::kRelativeParent:
                             foundUpdate = relativeParentUpdateFound(change, foundUpdate);
                             break;
@@ -769,9 +726,7 @@
     ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kHiddenFlag));
     ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kOpaqueFlag));
     ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kSecureFlag));
-    ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kDeferredTransaction));
     ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kReparent));
-    ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kReparentChildren));
     ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kRelativeParent));
 }
 
@@ -927,21 +882,11 @@
             SurfaceChange::SurfaceChangeCase::kSecureFlag);
 }
 
-TEST_F(SurfaceInterceptorTest, InterceptDeferredTransactionUpdateWorks) {
-    captureTest(&SurfaceInterceptorTest::deferredTransactionUpdate,
-            SurfaceChange::SurfaceChangeCase::kDeferredTransaction);
-}
-
 TEST_F(SurfaceInterceptorTest, InterceptReparentUpdateWorks) {
     captureTest(&SurfaceInterceptorTest::reparentUpdate,
                 SurfaceChange::SurfaceChangeCase::kReparent);
 }
 
-TEST_F(SurfaceInterceptorTest, InterceptReparentChildrenUpdateWorks) {
-    captureTest(&SurfaceInterceptorTest::reparentChildrenUpdate,
-                SurfaceChange::SurfaceChangeCase::kReparentChildren);
-}
-
 TEST_F(SurfaceInterceptorTest, InterceptRelativeParentUpdateWorks) {
     captureTest(&SurfaceInterceptorTest::relativeParentUpdate,
                 SurfaceChange::SurfaceChangeCase::kRelativeParent);
diff --git a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp
index 820f248..eb31e2e 100644
--- a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp
+++ b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp
@@ -91,7 +91,6 @@
 constexpr static TestColor LIGHT_RED = {255, 177, 177, 255};
 constexpr static TestColor GREEN = {63, 195, 63, 255};
 constexpr static TestColor BLUE = {63, 63, 195, 255};
-constexpr static TestColor DARK_GRAY = {63, 63, 63, 255};
 constexpr static TestColor LIGHT_GRAY = {200, 200, 200, 255};
 
 // Fill an RGBA_8888 formatted surface with a single color.
@@ -1469,77 +1468,6 @@
         }
     }
 
-    void Test_DeferredTransaction() {
-        // Synchronization surface
-        constexpr static int SYNC_LAYER = 2;
-        auto syncSurfaceControl = mComposerClient->createSurface(String8("Sync Test Surface"), 1, 1,
-                                                                 PIXEL_FORMAT_RGBA_8888, 0);
-        ASSERT_TRUE(syncSurfaceControl != nullptr);
-        ASSERT_TRUE(syncSurfaceControl->isValid());
-
-        fillSurfaceRGBA8(syncSurfaceControl, DARK_GRAY);
-
-        {
-            TransactionScope ts(*sFakeComposer);
-            ts.setLayer(syncSurfaceControl, INT32_MAX - 1);
-            ts.setPosition(syncSurfaceControl, mDisplayWidth - 2, mDisplayHeight - 2);
-            ts.show(syncSurfaceControl);
-        }
-        auto referenceFrame = mBaseFrame;
-        referenceFrame.push_back(makeSimpleRect(mDisplayWidth - 2, mDisplayHeight - 2,
-                                                mDisplayWidth - 1, mDisplayHeight - 1));
-        referenceFrame[SYNC_LAYER].mSwapCount = 1;
-        EXPECT_EQ(2, sFakeComposer->getFrameCount());
-        EXPECT_TRUE(framesAreSame(referenceFrame, sFakeComposer->getLatestFrame()));
-
-        // set up two deferred transactions on different frames - these should not yield composited
-        // frames
-        {
-            TransactionScope ts(*sFakeComposer);
-            ts.setAlpha(mFGSurfaceControl, 0.75);
-            ts.deferTransactionUntil_legacy(mFGSurfaceControl, syncSurfaceControl,
-                                            syncSurfaceControl->getSurface()->getNextFrameNumber());
-        }
-        EXPECT_TRUE(framesAreSame(referenceFrame, sFakeComposer->getLatestFrame()));
-
-        {
-            TransactionScope ts(*sFakeComposer);
-            ts.setPosition(mFGSurfaceControl, 128, 128);
-            ts.deferTransactionUntil_legacy(mFGSurfaceControl, syncSurfaceControl,
-                                            syncSurfaceControl->getSurface()->getNextFrameNumber() +
-                                                    1);
-        }
-        EXPECT_EQ(4, sFakeComposer->getFrameCount());
-        EXPECT_TRUE(framesAreSame(referenceFrame, sFakeComposer->getLatestFrame()));
-
-        // should trigger the first deferred transaction, but not the second one
-        fillSurfaceRGBA8(syncSurfaceControl, DARK_GRAY);
-        sFakeComposer->runVSyncAndWait();
-        EXPECT_EQ(5, sFakeComposer->getFrameCount());
-
-        referenceFrame[FG_LAYER].mPlaneAlpha = 0.75f;
-        referenceFrame[SYNC_LAYER].mSwapCount++;
-        EXPECT_TRUE(framesAreSame(referenceFrame, sFakeComposer->getLatestFrame()));
-
-        // should show up immediately since it's not deferred
-        {
-            TransactionScope ts(*sFakeComposer);
-            ts.setAlpha(mFGSurfaceControl, 1.0);
-        }
-        referenceFrame[FG_LAYER].mPlaneAlpha = 1.f;
-        EXPECT_EQ(6, sFakeComposer->getFrameCount());
-        EXPECT_TRUE(framesAreSame(referenceFrame, sFakeComposer->getLatestFrame()));
-
-        // trigger the second deferred transaction
-        fillSurfaceRGBA8(syncSurfaceControl, DARK_GRAY);
-        sFakeComposer->runVSyncAndWait();
-        // TODO: Compute from layer size?
-        referenceFrame[FG_LAYER].mDisplayFrame = hwc_rect_t{128, 128, 128 + 64, 128 + 64};
-        referenceFrame[SYNC_LAYER].mSwapCount++;
-        EXPECT_EQ(7, sFakeComposer->getFrameCount());
-        EXPECT_TRUE(framesAreSame(referenceFrame, sFakeComposer->getLatestFrame()));
-    }
-
     void Test_SetRelativeLayer() {
         constexpr int RELATIVE_LAYER = 2;
         auto relativeSurfaceControl = mComposerClient->createSurface(String8("Test Surface"), 64,
@@ -1625,10 +1553,6 @@
     Test_LayerSetMatrix();
 }
 
-TEST_F(TransactionTest_2_1, DISABLED_DeferredTransaction) {
-    Test_DeferredTransaction();
-}
-
 TEST_F(TransactionTest_2_1, DISABLED_SetRelativeLayer) {
     Test_SetRelativeLayer();
 }
@@ -1766,30 +1690,6 @@
         EXPECT_TRUE(framesAreSame(referenceFrame2, Base::sFakeComposer->getLatestFrame()));
     }
 
-    void Test_ReparentChildren() {
-        {
-            TransactionScope ts(*Base::sFakeComposer);
-            ts.show(mChild);
-            ts.setPosition(mChild, 10, 10);
-            ts.setPosition(Base::mFGSurfaceControl, 64, 64);
-        }
-        auto referenceFrame = Base::mBaseFrame;
-        referenceFrame[Base::FG_LAYER].mDisplayFrame = hwc_rect_t{64, 64, 64 + 64, 64 + 64};
-        referenceFrame[CHILD_LAYER].mDisplayFrame =
-                hwc_rect_t{64 + 10, 64 + 10, 64 + 10 + 10, 64 + 10 + 10};
-        EXPECT_TRUE(framesAreSame(referenceFrame, Base::sFakeComposer->getLatestFrame()));
-
-        {
-            TransactionScope ts(*Base::sFakeComposer);
-            ts.reparentChildren(Base::mFGSurfaceControl, Base::mBGSurfaceControl);
-        }
-
-        auto referenceFrame2 = referenceFrame;
-        referenceFrame2[Base::FG_LAYER].mDisplayFrame = hwc_rect_t{64, 64, 64 + 64, 64 + 64};
-        referenceFrame2[CHILD_LAYER].mDisplayFrame = hwc_rect_t{10, 10, 10 + 10, 10 + 10};
-        EXPECT_TRUE(framesAreSame(referenceFrame2, Base::sFakeComposer->getLatestFrame()));
-    }
-
     // Regression test for b/37673612
     void Test_ChildrenWithParentBufferTransform() {
         {
@@ -1823,44 +1723,6 @@
         EXPECT_TRUE(framesAreSame(referenceFrame, Base::sFakeComposer->getLatestFrame()));
     }
 
-    void Test_Bug36858924() {
-        // Destroy the child layer
-        mChild.clear();
-
-        // Now recreate it as hidden
-        mChild = Base::mComposerClient->createSurface(String8("Child surface"), 10, 10,
-                                                      PIXEL_FORMAT_RGBA_8888,
-                                                      ISurfaceComposerClient::eHidden,
-                                                      Base::mFGSurfaceControl->getHandle());
-
-        // Show the child layer in a deferred transaction
-        {
-            TransactionScope ts(*Base::sFakeComposer);
-            ts.deferTransactionUntil_legacy(mChild, Base::mFGSurfaceControl,
-                                            Base::mFGSurfaceControl->getSurface()
-                                                    ->getNextFrameNumber());
-            ts.show(mChild);
-        }
-
-        // Render the foreground surface a few times
-        //
-        // Prior to the bugfix for b/36858924, this would usually hang while trying to fill the
-        // third frame because SurfaceFlinger would never process the deferred transaction and would
-        // therefore never acquire/release the first buffer
-        ALOGI("Filling 1");
-        fillSurfaceRGBA8(Base::mFGSurfaceControl, GREEN);
-        Base::sFakeComposer->runVSyncAndWait();
-        ALOGI("Filling 2");
-        fillSurfaceRGBA8(Base::mFGSurfaceControl, BLUE);
-        Base::sFakeComposer->runVSyncAndWait();
-        ALOGI("Filling 3");
-        fillSurfaceRGBA8(Base::mFGSurfaceControl, RED);
-        Base::sFakeComposer->runVSyncAndWait();
-        ALOGI("Filling 4");
-        fillSurfaceRGBA8(Base::mFGSurfaceControl, GREEN);
-        Base::sFakeComposer->runVSyncAndWait();
-    }
-
     sp<SurfaceControl> mChild;
 };
 
@@ -1886,19 +1748,11 @@
     Test_LayerAlpha();
 }
 
-TEST_F(ChildLayerTest_2_1, DISABLED_ReparentChildren) {
-    Test_ReparentChildren();
-}
-
 // Regression test for b/37673612
 TEST_F(ChildLayerTest_2_1, DISABLED_ChildrenWithParentBufferTransform) {
     Test_ChildrenWithParentBufferTransform();
 }
 
-TEST_F(ChildLayerTest_2_1, DISABLED_Bug36858924) {
-    Test_Bug36858924();
-}
-
 template <typename FakeComposerService>
 class ChildColorLayerTest : public ChildLayerTest<FakeComposerService> {
     using Base = ChildLayerTest<FakeComposerService>;
diff --git a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
index 7cc0032..b4a1481 100644
--- a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
+++ b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
@@ -44,7 +44,7 @@
 constexpr PhysicalDisplayId INTERNAL_DISPLAY_ID(111);
 constexpr PhysicalDisplayId EXTERNAL_DISPLAY_ID(222);
 constexpr PhysicalDisplayId DISPLAY_ID_64BIT(0xabcd12349876fedcULL);
-
+constexpr std::chrono::duration VSYNC_PERIOD(16ms);
 class MockVSyncSource : public VSyncSource {
 public:
     const char* getName() const override { return "test"; }
@@ -166,11 +166,14 @@
         mThrottleVsyncCallRecorder.getInvocable()(expectedVsyncTimestamp, uid);
         return (uid == mThrottledConnectionUid);
     };
+    const auto getVsyncPeriod = [](uid_t uid) {
+        return VSYNC_PERIOD.count();
+    };
 
     mThread = std::make_unique<impl::EventThread>(std::move(source),
                                                   /*tokenManager=*/nullptr,
                                                   mInterceptVSyncCallRecorder.getInvocable(),
-                                                  throttleVsync);
+                                                  throttleVsync, getVsyncPeriod);
 
     // EventThread should register itself as VSyncSource callback.
     mCallback = expectVSyncSetCallbackCallReceived();
diff --git a/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp
index abecd4b..9c6ad06 100644
--- a/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp
@@ -118,11 +118,8 @@
 }
 
 void RefreshRateSelectionTest::commitTransaction(Layer* layer) {
-    layer->pushPendingState();
     auto c = layer->getCurrentState();
-    if (layer->applyPendingStates(&c)) {
-        layer->commitTransaction(c);
-    }
+    layer->commitTransaction(c);
 }
 
 void RefreshRateSelectionTest::setupScheduler() {
diff --git a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp
index 7e602a2..c088ddc 100644
--- a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp
@@ -122,7 +122,6 @@
 
     void addChild(sp<Layer> layer, sp<Layer> child);
     void removeChild(sp<Layer> layer, sp<Layer> child);
-    void reparentChildren(sp<Layer> layer, sp<Layer> child);
     void commitTransaction();
 
     TestableSurfaceFlinger mFlinger;
@@ -152,17 +151,10 @@
     layer.get()->removeChild(child.get());
 }
 
-void SetFrameRateTest::reparentChildren(sp<Layer> parent, sp<Layer> newParent) {
-    parent.get()->reparentChildren(newParent);
-}
-
 void SetFrameRateTest::commitTransaction() {
     for (auto layer : mLayers) {
-        layer->pushPendingState();
         auto c = layer->getCurrentState();
-        if (layer->applyPendingStates(&c)) {
-            layer->commitTransaction(c);
-        }
+        layer->commitTransaction(c);
     }
 }
 
@@ -433,41 +425,6 @@
     EXPECT_EQ(FRAME_RATE_NO_VOTE, child2_1->getFrameRateForLayerTree());
 }
 
-TEST_P(SetFrameRateTest, SetAndGetReparentChildren) {
-    EXPECT_CALL(*mMessageQueue, invalidate()).Times(1);
-
-    const auto& layerFactory = GetParam();
-
-    auto parent = mLayers.emplace_back(layerFactory->createLayer(mFlinger));
-    auto parent2 = mLayers.emplace_back(layerFactory->createLayer(mFlinger));
-    auto child1 = mLayers.emplace_back(layerFactory->createLayer(mFlinger));
-    auto child2 = mLayers.emplace_back(layerFactory->createLayer(mFlinger));
-
-    addChild(parent, child1);
-    addChild(child1, child2);
-
-    child2->setFrameRate(FRAME_RATE_VOTE1);
-    commitTransaction();
-    EXPECT_EQ(FRAME_RATE_TREE, parent->getFrameRateForLayerTree());
-    EXPECT_EQ(FRAME_RATE_NO_VOTE, parent2->getFrameRateForLayerTree());
-    EXPECT_EQ(FRAME_RATE_TREE, child1->getFrameRateForLayerTree());
-    EXPECT_EQ(FRAME_RATE_VOTE1, child2->getFrameRateForLayerTree());
-
-    reparentChildren(parent, parent2);
-    commitTransaction();
-    EXPECT_EQ(FRAME_RATE_NO_VOTE, parent->getFrameRateForLayerTree());
-    EXPECT_EQ(FRAME_RATE_TREE, parent2->getFrameRateForLayerTree());
-    EXPECT_EQ(FRAME_RATE_TREE, child1->getFrameRateForLayerTree());
-    EXPECT_EQ(FRAME_RATE_VOTE1, child2->getFrameRateForLayerTree());
-
-    child2->setFrameRate(FRAME_RATE_NO_VOTE);
-    commitTransaction();
-    EXPECT_EQ(FRAME_RATE_NO_VOTE, parent->getFrameRateForLayerTree());
-    EXPECT_EQ(FRAME_RATE_NO_VOTE, parent2->getFrameRateForLayerTree());
-    EXPECT_EQ(FRAME_RATE_NO_VOTE, child1->getFrameRateForLayerTree());
-    EXPECT_EQ(FRAME_RATE_NO_VOTE, child2->getFrameRateForLayerTree());
-}
-
 INSTANTIATE_TEST_SUITE_P(PerLayerType, SetFrameRateTest,
                          testing::Values(std::make_shared<BufferQueueLayerFactory>(),
                                          std::make_shared<BufferStateLayerFactory>(),
diff --git a/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp b/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp
index b5ef0a1..ea1ce47 100644
--- a/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp
@@ -60,11 +60,8 @@
     }
 
     void commitTransaction(Layer* layer) {
-        layer->pushPendingState();
         auto c = layer->getCurrentState();
-        if (layer->applyPendingStates(&c)) {
-            layer->commitTransaction(c);
-        }
+        layer->commitTransaction(c);
     }
 
     void setupScheduler() {
@@ -151,4 +148,4 @@
     BLASTTransactionSendsFrameTracerEvents();
 }
 
-} // namespace android
\ No newline at end of file
+} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp b/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp
index c75538f..09a1c2a 100644
--- a/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp
@@ -60,13 +60,8 @@
     }
 
     void commitTransaction(Layer* layer) {
-        layer->pushPendingState();
-        // After pushing the state, the currentState should not store any BufferlessSurfaceFrames
-        EXPECT_EQ(0u, layer->mCurrentState.bufferlessSurfaceFramesTX.size());
         auto c = layer->getCurrentState();
-        if (layer->applyPendingStates(&c)) {
-            layer->commitTransaction(c);
-        }
+        layer->commitTransaction(c);
     }
 
     void setupScheduler() {
@@ -283,69 +278,6 @@
         EXPECT_EQ(PresentState::Presented, bufferSurfaceFrameTX->getPresentState());
     }
 
-    void MergePendingStates_BufferlessSurfaceFramesWithoutOverlappingToken() {
-        sp<BufferStateLayer> layer = createBufferStateLayer();
-        layer->setFrameTimelineVsyncForBufferlessTransaction({/*vsyncId*/ 1, /*inputEventId*/ 0},
-                                                             10);
-        EXPECT_EQ(1u, layer->mCurrentState.bufferlessSurfaceFramesTX.size());
-        ASSERT_EQ(nullptr, layer->mCurrentState.bufferSurfaceFrameTX);
-        const auto bufferlessSurfaceFrame1 =
-                layer->mCurrentState.bufferlessSurfaceFramesTX.at(/*token*/ 1);
-
-        layer->pushPendingState();
-        EXPECT_EQ(0u, layer->mCurrentState.bufferlessSurfaceFramesTX.size());
-
-        layer->setFrameTimelineVsyncForBufferlessTransaction({/*vsyncId*/ 2, /*inputEventId*/ 0},
-                                                             12);
-        EXPECT_EQ(1u, layer->mCurrentState.bufferlessSurfaceFramesTX.size());
-        ASSERT_EQ(nullptr, layer->mCurrentState.bufferSurfaceFrameTX);
-        const auto bufferlessSurfaceFrame2 =
-                layer->mCurrentState.bufferlessSurfaceFramesTX.at(/*token*/ 2);
-
-        commitTransaction(layer.get());
-
-        EXPECT_EQ(1, bufferlessSurfaceFrame1->getToken());
-        EXPECT_EQ(false, bufferlessSurfaceFrame1->getIsBuffer());
-        EXPECT_EQ(PresentState::Presented, bufferlessSurfaceFrame1->getPresentState());
-        EXPECT_EQ(10, bufferlessSurfaceFrame1->getActuals().endTime);
-
-        EXPECT_EQ(2, bufferlessSurfaceFrame2->getToken());
-        EXPECT_EQ(false, bufferlessSurfaceFrame2->getIsBuffer());
-        EXPECT_EQ(PresentState::Presented, bufferlessSurfaceFrame2->getPresentState());
-        EXPECT_EQ(12, bufferlessSurfaceFrame2->getActuals().endTime);
-    }
-
-    void MergePendingStates_BufferlessSurfaceFramesWithOverlappingToken() {
-        sp<BufferStateLayer> layer = createBufferStateLayer();
-        layer->setFrameTimelineVsyncForBufferlessTransaction({/*vsyncId*/ 1, /*inputEventId*/ 0},
-                                                             10);
-        EXPECT_EQ(1u, layer->mCurrentState.bufferlessSurfaceFramesTX.size());
-        ASSERT_EQ(nullptr, layer->mCurrentState.bufferSurfaceFrameTX);
-        const auto bufferlessSurfaceFrame1 =
-                layer->mCurrentState.bufferlessSurfaceFramesTX.at(/*token*/ 1);
-
-        layer->pushPendingState();
-        EXPECT_EQ(0u, layer->mCurrentState.bufferlessSurfaceFramesTX.size());
-
-        layer->setFrameTimelineVsyncForBufferlessTransaction({/*vsyncId*/ 1, /*inputEventId*/ 0},
-                                                             12);
-        EXPECT_EQ(1u, layer->mCurrentState.bufferlessSurfaceFramesTX.size());
-        ASSERT_EQ(nullptr, layer->mCurrentState.bufferSurfaceFrameTX);
-        const auto bufferlessSurfaceFrame2 =
-                layer->mCurrentState.bufferlessSurfaceFramesTX.at(/*token*/ 1);
-
-        commitTransaction(layer.get());
-
-        EXPECT_EQ(1, bufferlessSurfaceFrame1->getToken());
-        EXPECT_EQ(false, bufferlessSurfaceFrame1->getIsBuffer());
-        EXPECT_EQ(PresentState::Unknown, bufferlessSurfaceFrame1->getPresentState());
-
-        EXPECT_EQ(1, bufferlessSurfaceFrame2->getToken());
-        EXPECT_EQ(false, bufferlessSurfaceFrame2->getIsBuffer());
-        EXPECT_EQ(PresentState::Presented, bufferlessSurfaceFrame2->getPresentState());
-        EXPECT_EQ(12, bufferlessSurfaceFrame2->getActuals().endTime);
-    }
-
     void PendingSurfaceFramesRemovedAfterClassification() {
         sp<BufferStateLayer> layer = createBufferStateLayer();
 
@@ -529,16 +461,6 @@
     MultipleSurfaceFramesPresentedTogether();
 }
 
-TEST_F(TransactionSurfaceFrameTest,
-       MergePendingStates_BufferlessSurfaceFramesWithoutOverlappingToken) {
-    MergePendingStates_BufferlessSurfaceFramesWithoutOverlappingToken();
-}
-
-TEST_F(TransactionSurfaceFrameTest,
-       MergePendingStates_BufferlessSurfaceFramesWithOverlappingToken) {
-    MergePendingStates_BufferlessSurfaceFramesWithOverlappingToken();
-}
-
 TEST_F(TransactionSurfaceFrameTest, PendingSurfaceFramesRemovedAfterClassification) {
     PendingSurfaceFramesRemovedAfterClassification();
 }
@@ -552,4 +474,4 @@
     MultipleCommitsBeforeLatch();
 }
 
-} // namespace android
\ No newline at end of file
+} // namespace android
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);