Merge "libjpegrecoverymap: refactor"
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index f3a721a..33dceff 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -170,6 +170,7 @@
 #define RECOVERY_DIR "/cache/recovery"
 #define RECOVERY_DATA_DIR "/data/misc/recovery"
 #define UPDATE_ENGINE_LOG_DIR "/data/misc/update_engine_log"
+#define UPDATE_ENGINE_PREF_DIR "/data/misc/update_engine/prefs"
 #define LOGPERSIST_DATA_DIR "/data/misc/logd"
 #define PREREBOOT_DATA_DIR "/data/misc/prereboot"
 #define PROFILE_DATA_DIR_CUR "/data/misc/profiles/cur"
@@ -1865,6 +1866,7 @@
     ds.AddDir(RECOVERY_DIR, true);
     ds.AddDir(RECOVERY_DATA_DIR, true);
     ds.AddDir(UPDATE_ENGINE_LOG_DIR, true);
+    ds.AddDir(UPDATE_ENGINE_PREF_DIR, true);
     ds.AddDir(LOGPERSIST_DATA_DIR, false);
     if (!PropertiesHelper::IsUserBuild()) {
         ds.AddDir(PROFILE_DATA_DIR_CUR, true);
diff --git a/cmds/servicemanager/servicemanager.microdroid.rc b/cmds/servicemanager/servicemanager.microdroid.rc
index c516043..8819e1e 100644
--- a/cmds/servicemanager/servicemanager.microdroid.rc
+++ b/cmds/servicemanager/servicemanager.microdroid.rc
@@ -5,5 +5,4 @@
     critical
     onrestart setprop servicemanager.ready false
     onrestart restart apexd
-    task_profiles ServiceCapacityLow
     shutdown critical
diff --git a/include/ftl/concat.h b/include/ftl/concat.h
index ded48f7..e0774d3 100644
--- a/include/ftl/concat.h
+++ b/include/ftl/concat.h
@@ -20,7 +20,9 @@
 
 namespace android::ftl {
 
-// Lightweight (not allocating nor sprintf-based) concatenation.
+// Lightweight (not allocating nor sprintf-based) concatenation. The variadic arguments can be
+// values of integral type (including bool and char), string literals, or strings whose length
+// is constrained:
 //
 //   std::string_view name = "Volume";
 //   ftl::Concat string(ftl::truncated<3>(name), ": ", -3, " dB");
diff --git a/include/ftl/details/concat.h b/include/ftl/details/concat.h
index 8ce949e..726ba02 100644
--- a/include/ftl/details/concat.h
+++ b/include/ftl/details/concat.h
@@ -19,6 +19,7 @@
 #include <functional>
 #include <string_view>
 
+#include <ftl/details/type_traits.h>
 #include <ftl/string.h>
 
 namespace android::ftl::details {
@@ -26,16 +27,42 @@
 template <typename T, typename = void>
 struct StaticString;
 
+// Booleans.
 template <typename T>
-struct StaticString<T, std::enable_if_t<std::is_integral_v<T>>> {
-  static constexpr std::size_t N = to_chars_length_v<T>;
+struct StaticString<T, std::enable_if_t<is_bool_v<T>>> {
+  static constexpr std::size_t N = 5;  // Length of "false".
 
-  explicit StaticString(T v) : view(to_chars(buffer, v)) {}
+  explicit constexpr StaticString(bool b) : view(b ? "true" : "false") {}
 
-  to_chars_buffer_t<T> buffer;
   const std::string_view view;
 };
 
+// Characters.
+template <typename T>
+struct StaticString<T, std::enable_if_t<is_char_v<T>>> {
+  static constexpr std::size_t N = 1;
+
+  explicit constexpr StaticString(char c) : character(c) {}
+
+  const char character;
+  const std::string_view view{&character, 1u};
+};
+
+// Integers, including the integer value of other character types like char32_t.
+template <typename T>
+struct StaticString<
+    T, std::enable_if_t<std::is_integral_v<remove_cvref_t<T>> && !is_bool_v<T> && !is_char_v<T>>> {
+  using U = remove_cvref_t<T>;
+  static constexpr std::size_t N = to_chars_length_v<U>;
+
+  // TODO: Mark this and to_chars as `constexpr` in C++23.
+  explicit StaticString(U v) : view(to_chars(buffer, v)) {}
+
+  to_chars_buffer_t<U> buffer;
+  const std::string_view view;
+};
+
+// Character arrays.
 template <std::size_t M>
 struct StaticString<const char (&)[M], void> {
   static constexpr std::size_t N = M - 1;
@@ -50,6 +77,7 @@
   std::string_view view;
 };
 
+// Strings with constrained length.
 template <std::size_t M>
 struct StaticString<Truncated<M>, void> {
   static constexpr std::size_t N = M;
diff --git a/include/ftl/details/type_traits.h b/include/ftl/details/type_traits.h
index 7092ec5..47bebc5 100644
--- a/include/ftl/details/type_traits.h
+++ b/include/ftl/details/type_traits.h
@@ -24,4 +24,10 @@
 template <typename U>
 using remove_cvref_t = std::remove_cv_t<std::remove_reference_t<U>>;
 
+template <typename T>
+constexpr bool is_bool_v = std::is_same_v<remove_cvref_t<T>, bool>;
+
+template <typename T>
+constexpr bool is_char_v = std::is_same_v<remove_cvref_t<T>, char>;
+
 }  // namespace android::ftl::details
diff --git a/include/input/InputDevice.h b/include/input/InputDevice.h
index f4a1523..ac9c5a5 100644
--- a/include/input/InputDevice.h
+++ b/include/input/InputDevice.h
@@ -23,6 +23,7 @@
 #include <unordered_map>
 #include <vector>
 
+#include <android/os/IInputConstants.h>
 #include "android/hardware/input/InputDeviceCountryCode.h"
 
 namespace android {
@@ -346,6 +347,8 @@
         const std::string& name, InputDeviceConfigurationFileType type);
 
 enum ReservedInputDeviceId : int32_t {
+    // Device id representing an invalid device
+    INVALID_INPUT_DEVICE_ID = android::os::IInputConstants::INVALID_INPUT_DEVICE_ID,
     // Device id of a special "virtual" keyboard that is always present.
     VIRTUAL_KEYBOARD_ID = -1,
     // Device id of the "built-in" keyboard if there is one.
diff --git a/libs/binder/ndk/include_platform/android/binder_manager.h b/libs/binder/ndk/include_platform/android/binder_manager.h
index dfa8ea2..c234270 100644
--- a/libs/binder/ndk/include_platform/android/binder_manager.h
+++ b/libs/binder/ndk/include_platform/android/binder_manager.h
@@ -143,6 +143,17 @@
 bool AServiceManager_isUpdatableViaApex(const char* instance) __INTRODUCED_IN(31);
 
 /**
+ * Returns the APEX name if a service is declared as updatable via an APEX module.
+ *
+ * \param instance identifier of the service
+ * \param context to pass to callback
+ * \param callback taking the APEX name (e.g. 'com.android.foo') and context
+ */
+void AServiceManager_getUpdatableApexName(const char* instance, void* context,
+                                          void (*callback)(const char*, void*))
+        __INTRODUCED_IN(__ANDROID_API_U__);
+
+/**
  * Prevent lazy services without client from shutting down their process
  *
  * This should only be used if it is every eventually set to false. If a
diff --git a/libs/binder/ndk/libbinder_ndk.map.txt b/libs/binder/ndk/libbinder_ndk.map.txt
index 259a736..32ca564 100644
--- a/libs/binder/ndk/libbinder_ndk.map.txt
+++ b/libs/binder/ndk/libbinder_ndk.map.txt
@@ -152,6 +152,11 @@
     AParcel_unmarshal;
 };
 
+LIBBINDER_NDK34 { # introduced=UpsideDownCake
+  global:
+    AServiceManager_getUpdatableApexName; # systemapi
+};
+
 LIBBINDER_NDK_PLATFORM {
   global:
     AParcel_getAllowFds;
diff --git a/libs/binder/ndk/service_manager.cpp b/libs/binder/ndk/service_manager.cpp
index 7649a26..a12d0e9 100644
--- a/libs/binder/ndk/service_manager.cpp
+++ b/libs/binder/ndk/service_manager.cpp
@@ -113,6 +113,18 @@
     sp<IServiceManager> sm = defaultServiceManager();
     return sm->updatableViaApex(String16(instance)) != std::nullopt;
 }
+void AServiceManager_getUpdatableApexName(const char* instance, void* context,
+                                          void (*callback)(const char*, void*)) {
+    CHECK_NE(instance, nullptr);
+    // context may be nullptr
+    CHECK_NE(callback, nullptr);
+
+    sp<IServiceManager> sm = defaultServiceManager();
+    std::optional<String16> updatableViaApex = sm->updatableViaApex(String16(instance));
+    if (updatableViaApex.has_value()) {
+        callback(String8(updatableViaApex.value()).c_str(), context);
+    }
+}
 void AServiceManager_forceLazyServicesPersist(bool persist) {
     auto serviceRegistrar = android::binder::LazyServiceRegistrar::getInstance();
     serviceRegistrar.forcePersist(persist);
diff --git a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
index 01b9472..e221e4c 100644
--- a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
+++ b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
@@ -33,13 +33,15 @@
 #include <binder/IResultReceiver.h>
 #include <binder/IServiceManager.h>
 #include <binder/IShellCallback.h>
-
 #include <sys/prctl.h>
+
 #include <chrono>
 #include <condition_variable>
 #include <iostream>
 #include <mutex>
+#include <optional>
 #include <thread>
+
 #include "android/binder_ibinder.h"
 
 using namespace android;
@@ -337,6 +339,16 @@
     EXPECT_EQ(isUpdatable, false);
 }
 
+TEST(NdkBinder, GetUpdatableViaApex) {
+    std::optional<std::string> updatableViaApex;
+    AServiceManager_getUpdatableApexName(
+            "android.hardware.light.ILights/default", &updatableViaApex,
+            [](const char* apexName, void* context) {
+                *static_cast<std::optional<std::string>*>(context) = apexName;
+            });
+    EXPECT_EQ(updatableViaApex, std::nullopt) << *updatableViaApex;
+}
+
 // This is too slow
 TEST(NdkBinder, CheckLazyServiceShutDown) {
     ndk::SpAIBinder binder(AServiceManager_waitForService(kLazyBinderNdkUnitTestService));
diff --git a/libs/dumputils/dump_utils.cpp b/libs/dumputils/dump_utils.cpp
index a6585c5..067ce17 100644
--- a/libs/dumputils/dump_utils.cpp
+++ b/libs/dumputils/dump_utils.cpp
@@ -208,5 +208,5 @@
     cmdline = std::string(cmdline.c_str());
 
     return cmdline == "zygote" || cmdline == "zygote64" || cmdline == "usap32" ||
-            cmdline == "usap64";
+            cmdline == "usap64" || cmdline == "webview_zygote";
 }
diff --git a/libs/ftl/concat_test.cpp b/libs/ftl/concat_test.cpp
index 8ecb1b2..771f054 100644
--- a/libs/ftl/concat_test.cpp
+++ b/libs/ftl/concat_test.cpp
@@ -28,8 +28,25 @@
   EXPECT_EQ(string.c_str()[string.size()], '\0');
 }
 
+TEST(Concat, Characters) {
+  EXPECT_EQ(ftl::Concat(u'a', ' ', U'b').str(), "97 98");
+}
+
+TEST(Concat, References) {
+  int i[] = {-1, 2};
+  unsigned u = 3;
+  EXPECT_EQ(ftl::Concat(i[0], std::as_const(i[1]), u).str(), "-123");
+
+  const bool b = false;
+  const char c = 'o';
+  EXPECT_EQ(ftl::Concat(b, "tt", c).str(), "falsetto");
+}
+
 namespace {
 
+static_assert(ftl::Concat{true, false, true}.str() == "truefalsetrue");
+static_assert(ftl::Concat{':', '-', ')'}.str() == ":-)");
+
 static_assert(ftl::Concat{"foo"}.str() == "foo");
 static_assert(ftl::Concat{ftl::truncated<3>("foobar")}.str() == "foo");
 
diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp
index 8b9a878..0021bd6 100644
--- a/libs/gui/BLASTBufferQueue.cpp
+++ b/libs/gui/BLASTBufferQueue.cpp
@@ -167,14 +167,15 @@
     mNumFrameAvailable = 0;
 
     TransactionCompletedListener::getInstance()->addQueueStallListener(
-        [&]() {
-            std::function<void(bool)> callbackCopy;
-            {
-                std::unique_lock _lock{mMutex};
-                callbackCopy = mTransactionHangCallback;
-            }
-            if (callbackCopy) callbackCopy(true);
-        }, this);
+            [&](const std::string& reason) {
+                std::function<void(const std::string&)> callbackCopy;
+                {
+                    std::unique_lock _lock{mMutex};
+                    callbackCopy = mTransactionHangCallback;
+                }
+                if (callbackCopy) callbackCopy(reason);
+            },
+            this);
 
     BQA_LOGV("BLASTBufferQueue created");
 }
@@ -334,9 +335,11 @@
             std::optional<SurfaceControlStats> statsOptional = findMatchingStat(stats, pendingSC);
             if (statsOptional) {
                 SurfaceControlStats stat = *statsOptional;
-                mTransformHint = stat.transformHint;
-                mBufferItemConsumer->setTransformHint(mTransformHint);
-                BQA_LOGV("updated mTransformHint=%d", mTransformHint);
+                if (stat.transformHint) {
+                    mTransformHint = *stat.transformHint;
+                    mBufferItemConsumer->setTransformHint(mTransformHint);
+                    BQA_LOGV("updated mTransformHint=%d", mTransformHint);
+                }
                 // Update frametime stamps if the frame was latched and presented, indicated by a
                 // valid latch time.
                 if (stat.latchTime > 0) {
@@ -1112,7 +1115,8 @@
     return SurfaceControl::isSameSurface(mSurfaceControl, surfaceControl);
 }
 
-void BLASTBufferQueue::setTransactionHangCallback(std::function<void(bool)> callback) {
+void BLASTBufferQueue::setTransactionHangCallback(
+        std::function<void(const std::string&)> callback) {
     std::unique_lock _lock{mMutex};
     mTransactionHangCallback = callback;
 }
diff --git a/libs/gui/ITransactionCompletedListener.cpp b/libs/gui/ITransactionCompletedListener.cpp
index ca91afa..2b25b61 100644
--- a/libs/gui/ITransactionCompletedListener.cpp
+++ b/libs/gui/ITransactionCompletedListener.cpp
@@ -17,6 +17,9 @@
 #define LOG_TAG "ITransactionCompletedListener"
 //#define LOG_NDEBUG 0
 
+#include <cstdint>
+#include <optional>
+
 #include <gui/ISurfaceComposer.h>
 #include <gui/ITransactionCompletedListener.h>
 #include <gui/LayerState.h>
@@ -126,7 +129,12 @@
     } else {
         SAFE_PARCEL(output->writeBool, false);
     }
-    SAFE_PARCEL(output->writeUint32, transformHint);
+
+    SAFE_PARCEL(output->writeBool, transformHint.has_value());
+    if (transformHint.has_value()) {
+        output->writeUint32(transformHint.value());
+    }
+
     SAFE_PARCEL(output->writeUint32, currentMaxAcquiredBufferCount);
     SAFE_PARCEL(output->writeParcelable, eventStats);
     SAFE_PARCEL(output->writeInt32, static_cast<int32_t>(jankData.size()));
@@ -156,7 +164,16 @@
         previousReleaseFence = new Fence();
         SAFE_PARCEL(input->read, *previousReleaseFence);
     }
-    SAFE_PARCEL(input->readUint32, &transformHint);
+    bool hasTransformHint = false;
+    SAFE_PARCEL(input->readBool, &hasTransformHint);
+    if (hasTransformHint) {
+        uint32_t tempTransformHint;
+        SAFE_PARCEL(input->readUint32, &tempTransformHint);
+        transformHint = std::make_optional(tempTransformHint);
+    } else {
+        transformHint = std::nullopt;
+    }
+
     SAFE_PARCEL(input->readUint32, &currentMaxAcquiredBufferCount);
     SAFE_PARCEL(input->readParcelable, &eventStats);
 
@@ -273,15 +290,17 @@
 
     void onReleaseBuffer(ReleaseCallbackId callbackId, sp<Fence> releaseFence,
                          uint32_t currentMaxAcquiredBufferCount) override {
-        callRemoteAsync<decltype(
-                &ITransactionCompletedListener::onReleaseBuffer)>(Tag::ON_RELEASE_BUFFER,
-                                                                  callbackId, releaseFence,
-                                                                  currentMaxAcquiredBufferCount);
+        callRemoteAsync<decltype(&ITransactionCompletedListener::
+                                         onReleaseBuffer)>(Tag::ON_RELEASE_BUFFER, callbackId,
+                                                           releaseFence,
+                                                           currentMaxAcquiredBufferCount);
     }
 
-    void onTransactionQueueStalled() override {
-        callRemoteAsync<decltype(&ITransactionCompletedListener::onTransactionQueueStalled)>(
-            Tag::ON_TRANSACTION_QUEUE_STALLED);
+    void onTransactionQueueStalled(const String8& reason) override {
+        callRemoteAsync<
+                decltype(&ITransactionCompletedListener::
+                                 onTransactionQueueStalled)>(Tag::ON_TRANSACTION_QUEUE_STALLED,
+                                                             reason);
     }
 };
 
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index a5879a7..9c2ce0f 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -386,10 +386,11 @@
                                       surfaceStats.previousReleaseFence, surfaceStats.transformHint,
                                       surfaceStats.eventStats,
                                       surfaceStats.currentMaxAcquiredBufferCount);
-                if (callbacksMap[callbackId].surfaceControls[surfaceStats.surfaceControl]) {
+                if (callbacksMap[callbackId].surfaceControls[surfaceStats.surfaceControl] &&
+                    surfaceStats.transformHint.has_value()) {
                     callbacksMap[callbackId]
                             .surfaceControls[surfaceStats.surfaceControl]
-                            ->setTransformHint(surfaceStats.transformHint);
+                            ->setTransformHint(*surfaceStats.transformHint);
                 }
                 // If there is buffer id set, we look up any pending client release buffer callbacks
                 // and call them. This is a performance optimization when we have a transaction
@@ -455,23 +456,24 @@
     }
 }
 
-void TransactionCompletedListener::onTransactionQueueStalled() {
-      std::unordered_map<void*, std::function<void()>> callbackCopy;
-      {
-          std::scoped_lock<std::mutex> lock(mMutex);
-          callbackCopy = mQueueStallListeners;
-      }
-      for (auto const& it : callbackCopy) {
-          it.second();
-      }
+void TransactionCompletedListener::onTransactionQueueStalled(const String8& reason) {
+    std::unordered_map<void*, std::function<void(const std::string&)>> callbackCopy;
+    {
+        std::scoped_lock<std::mutex> lock(mMutex);
+        callbackCopy = mQueueStallListeners;
+    }
+    for (auto const& it : callbackCopy) {
+        it.second(reason.c_str());
+    }
 }
 
-void TransactionCompletedListener::addQueueStallListener(std::function<void()> stallListener,
-                                                         void* id) {
+void TransactionCompletedListener::addQueueStallListener(
+        std::function<void(const std::string&)> stallListener, void* id) {
     std::scoped_lock<std::mutex> lock(mMutex);
     mQueueStallListeners[id] = stallListener;
 }
-void TransactionCompletedListener::removeQueueStallListener(void *id) {
+
+void TransactionCompletedListener::removeQueueStallListener(void* id) {
     std::scoped_lock<std::mutex> lock(mMutex);
     mQueueStallListeners.erase(id);
 }
diff --git a/libs/gui/include/gui/BLASTBufferQueue.h b/libs/gui/include/gui/BLASTBufferQueue.h
index 827a6cc..957652e 100644
--- a/libs/gui/include/gui/BLASTBufferQueue.h
+++ b/libs/gui/include/gui/BLASTBufferQueue.h
@@ -113,12 +113,10 @@
     uint64_t getLastAcquiredFrameNum();
 
     /**
-     * Set a callback to be invoked when we are hung. The boolean parameter
-     * indicates whether the hang is due to an unfired fence.
-     * TODO: The boolean is always true atm, unfired fence is
-     * the only case we detect.
+     * Set a callback to be invoked when we are hung. The string parameter
+     * indicates the reason for the hang.
      */
-    void setTransactionHangCallback(std::function<void(bool)> callback);
+    void setTransactionHangCallback(std::function<void(const std::string&)> callback);
 
     virtual ~BLASTBufferQueue();
 
@@ -282,7 +280,7 @@
     bool mAppliedLastTransaction = false;
     uint64_t mLastAppliedFrameNumber = 0;
 
-    std::function<void(bool)> mTransactionHangCallback;
+    std::function<void(const std::string&)> mTransactionHangCallback;
 
     std::unordered_set<uint64_t> mSyncedFrameNumbers GUARDED_BY(mMutex);
 };
diff --git a/libs/gui/include/gui/ITransactionCompletedListener.h b/libs/gui/include/gui/ITransactionCompletedListener.h
index cc136bb..453e8f3 100644
--- a/libs/gui/include/gui/ITransactionCompletedListener.h
+++ b/libs/gui/include/gui/ITransactionCompletedListener.h
@@ -132,7 +132,7 @@
 
     SurfaceStats() = default;
     SurfaceStats(const sp<IBinder>& sc, std::variant<nsecs_t, sp<Fence>> acquireTimeOrFence,
-                 const sp<Fence>& prevReleaseFence, uint32_t hint,
+                 const sp<Fence>& prevReleaseFence, std::optional<uint32_t> hint,
                  uint32_t currentMaxAcquiredBuffersCount, FrameEventHistoryStats frameEventStats,
                  std::vector<JankData> jankData, ReleaseCallbackId previousReleaseCallbackId)
           : surfaceControl(sc),
@@ -147,7 +147,7 @@
     sp<IBinder> surfaceControl;
     std::variant<nsecs_t, sp<Fence>> acquireTimeOrFence = -1;
     sp<Fence> previousReleaseFence;
-    uint32_t transformHint = 0;
+    std::optional<uint32_t> transformHint = 0;
     uint32_t currentMaxAcquiredBufferCount = 0;
     FrameEventHistoryStats eventStats;
     std::vector<JankData> jankData;
@@ -194,7 +194,8 @@
 
     virtual void onReleaseBuffer(ReleaseCallbackId callbackId, sp<Fence> releaseFence,
                                  uint32_t currentMaxAcquiredBufferCount) = 0;
-    virtual void onTransactionQueueStalled() = 0;
+
+    virtual void onTransactionQueueStalled(const String8& name) = 0;
 };
 
 class BnTransactionCompletedListener : public SafeBnInterface<ITransactionCompletedListener> {
diff --git a/libs/gui/include/gui/LayerMetadata.h b/libs/gui/include/gui/LayerMetadata.h
index 5af5989..e16f89c 100644
--- a/libs/gui/include/gui/LayerMetadata.h
+++ b/libs/gui/include/gui/LayerMetadata.h
@@ -30,7 +30,8 @@
     METADATA_ACCESSIBILITY_ID = 5,
     METADATA_OWNER_PID = 6,
     METADATA_DEQUEUE_TIME = 7,
-    METADATA_GAME_MODE = 8
+    METADATA_GAME_MODE = 8,
+    METADATA_CALLING_UID = 9,
 };
 
 struct LayerMetadata : public Parcelable {
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 36969db..c450e85 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -69,7 +69,7 @@
     SurfaceControlStats(const sp<SurfaceControl>& sc, nsecs_t latchTime,
                         std::variant<nsecs_t, sp<Fence>> acquireTimeOrFence,
                         const sp<Fence>& presentFence, const sp<Fence>& prevReleaseFence,
-                        uint32_t hint, FrameEventHistoryStats eventStats,
+                        std::optional<uint32_t> hint, FrameEventHistoryStats eventStats,
                         uint32_t currentMaxAcquiredBufferCount)
           : surfaceControl(sc),
             latchTime(latchTime),
@@ -85,7 +85,7 @@
     std::variant<nsecs_t, sp<Fence>> acquireTimeOrFence = -1;
     sp<Fence> presentFence;
     sp<Fence> previousReleaseFence;
-    uint32_t transformHint = 0;
+    std::optional<uint32_t> transformHint = 0;
     FrameEventHistoryStats frameEventStats;
     uint32_t currentMaxAcquiredBufferCount = 0;
 };
@@ -786,7 +786,7 @@
     // This is protected by mSurfaceStatsListenerMutex, but GUARDED_BY isn't supported for
     // std::recursive_mutex
     std::multimap<int32_t, SurfaceStatsCallbackEntry> mSurfaceStatsListeners;
-    std::unordered_map<void*, std::function<void()>> mQueueStallListeners;
+    std::unordered_map<void*, std::function<void(const std::string&)>> mQueueStallListeners;
 
 public:
     static sp<TransactionCompletedListener> getInstance();
@@ -804,7 +804,7 @@
             const sp<SurfaceControl>& surfaceControl,
             const std::unordered_set<CallbackId, CallbackIdHash>& callbackIds);
 
-    void addQueueStallListener(std::function<void()> stallListener, void* id);
+    void addQueueStallListener(std::function<void(const std::string&)> stallListener, void* id);
     void removeQueueStallListener(void *id);
 
     /*
@@ -835,7 +835,7 @@
     // For Testing Only
     static void setInstance(const sp<TransactionCompletedListener>&);
 
-    void onTransactionQueueStalled() override;
+    void onTransactionQueueStalled(const String8& reason) override;
 
 private:
     ReleaseBufferCallback popReleaseBufferCallbackLocked(const ReleaseCallbackId&);
diff --git a/libs/input/android/os/IInputConstants.aidl b/libs/input/android/os/IInputConstants.aidl
index 5ce10a4..dab843b 100644
--- a/libs/input/android/os/IInputConstants.aidl
+++ b/libs/input/android/os/IInputConstants.aidl
@@ -35,6 +35,14 @@
     const int INVALID_INPUT_EVENT_ID = 0;
 
     /**
+     * Every input device has an id. This constant value is used when a valid input device id is not
+     * available.
+     * The virtual keyboard uses -1 as the input device id. Therefore, we use -2 as the value for
+     * an invalid input device.
+     */
+    const int INVALID_INPUT_DEVICE_ID = -2;
+
+    /**
      * The input event was injected from accessibility. Used in policyFlags for input event
      * injection.
      */
diff --git a/libs/renderengine/gl/ProgramCache.cpp b/libs/renderengine/gl/ProgramCache.cpp
index 5ff9240..f7f2d54 100644
--- a/libs/renderengine/gl/ProgramCache.cpp
+++ b/libs/renderengine/gl/ProgramCache.cpp
@@ -601,7 +601,7 @@
     }
 
     if (needs.hasTextureCoords()) {
-        fs << "varying vec2 outTexCoords;";
+        fs << "varying highp vec2 outTexCoords;";
     }
 
     if (needs.hasRoundedCorners()) {
diff --git a/opengl/libs/EGL/getProcAddress.cpp b/opengl/libs/EGL/getProcAddress.cpp
index b3d6f74..e0ba946 100644
--- a/opengl/libs/EGL/getProcAddress.cpp
+++ b/opengl/libs/EGL/getProcAddress.cpp
@@ -118,70 +118,27 @@
             : "rax", "cc"                                       \
             );
 
-#elif defined(__mips64)
+#elif defined(__riscv)
+    #define API_ENTRY(_api) __attribute__((noinline)) _api
 
-        #define API_ENTRY(_api) __attribute__((noinline)) _api
-
-        #define CALL_GL_EXTENSION_API(_api, ...)                    \
-            register unsigned int _t0 asm("$12");                   \
-            register unsigned int _fn asm("$25");                   \
-            register unsigned int _tls asm("$3");                   \
-            asm volatile(                                           \
-                ".set  push\n\t"                                    \
-                ".set  noreorder\n\t"                               \
-                "rdhwr %[tls], $29\n\t"                             \
-                "ld    %[t0], %[OPENGL_API](%[tls])\n\t"            \
-                "beqz  %[t0], 1f\n\t"                               \
-                " move %[fn], $ra\n\t"                              \
-                "ld    %[t0], %[API](%[t0])\n\t"                    \
-                "beqz  %[t0], 1f\n\t"                               \
-                " nop\n\t"                                          \
-                "move  %[fn], %[t0]\n\t"                            \
-                "1:\n\t"                                            \
-                "jalr  $0, %[fn]\n\t"                               \
-                " nop\n\t"                                          \
-                ".set  pop\n\t"                                     \
-                : [fn] "=c"(_fn),                                   \
-                  [tls] "=&r"(_tls),                                \
-                  [t0] "=&r"(_t0)                                   \
-                : [OPENGL_API] "I"(TLS_SLOT_OPENGL_API*4),          \
-                  [API] "I"(__builtin_offsetof(gl_hooks_t,          \
-                                          ext.extensions[_api]))    \
-                :                                                   \
-            );
-
-#elif defined(__mips__)
-
-        #define API_ENTRY(_api) __attribute__((noinline)) _api
-
-        #define CALL_GL_EXTENSION_API(_api, ...)                    \
-            register unsigned int _t0 asm("$8");                    \
-            register unsigned int _fn asm("$25");                    \
-            register unsigned int _tls asm("$3");                   \
-            asm volatile(                                           \
-                ".set  push\n\t"                                    \
-                ".set  noreorder\n\t"                               \
-                ".set  mips32r2\n\t"                                \
-                "rdhwr %[tls], $29\n\t"                             \
-                "lw    %[t0], %[OPENGL_API](%[tls])\n\t"            \
-                "beqz  %[t0], 1f\n\t"                               \
-                " move %[fn], $ra\n\t"                              \
-                "lw    %[t0], %[API](%[t0])\n\t"                    \
-                "beqz  %[t0], 1f\n\t"                               \
-                " nop\n\t"                                          \
-                "move  %[fn], %[t0]\n\t"                            \
-                "1:\n\t"                                            \
-                "jalr  $0, %[fn]\n\t"                               \
-                " nop\n\t"                                          \
-                ".set  pop\n\t"                                     \
-                : [fn] "=c"(_fn),                                   \
-                  [tls] "=&r"(_tls),                                \
-                  [t0] "=&r"(_t0)                                   \
-                : [OPENGL_API] "I"(TLS_SLOT_OPENGL_API*4),          \
-                  [API] "I"(__builtin_offsetof(gl_hooks_t,          \
-                                          ext.extensions[_api]))    \
-                :                                                   \
-            );
+    #define CALL_GL_EXTENSION_API(_api)                             \
+        asm volatile(                                               \
+            "mv t0, tp\n"                                           \
+            "li t1, %[tls]\n"                                       \
+            "add t0, t0, t1\n"                                      \
+            "ld t0, 0(t0)\n"                                        \
+            "beqz t0, 1f\n"                                         \
+            "li t1, %[api]\n"                                       \
+            "add t0, t0, t1\n"                                      \
+            "ld t0, 0(t0)\n"                                        \
+            "jalr x0, t0\n"                                         \
+            "1: ret\n"                                              \
+            :                                                       \
+            : [tls] "i" (TLS_SLOT_OPENGL_API * sizeof(void*)),      \
+              [api] "i" (__builtin_offsetof(gl_hooks_t,             \
+                                        ext.extensions[_api]))      \
+            : "t0", "t1"                                            \
+        );
 
 #endif
 
diff --git a/opengl/libs/GLES2/gl2.cpp b/opengl/libs/GLES2/gl2.cpp
index 65f50f5..5bd5c14 100644
--- a/opengl/libs/GLES2/gl2.cpp
+++ b/opengl/libs/GLES2/gl2.cpp
@@ -191,73 +191,44 @@
             :                              \
         );
 
-#elif defined(__mips64)
+#elif defined(__riscv)
 
     #define API_ENTRY(_api) __attribute__((naked,noinline)) _api
 
-    // t0:  $12
-    // fn:  $25
-    // tls: $3
-    // v0:  $2
-    #define CALL_GL_API_INTERNAL_CALL(_api, ...)                  \
-        asm volatile(                                             \
-            ".set  push\n\t"                                      \
-            ".set  noreorder\n\t"                                 \
-            "rdhwr $3, $29\n\t"                                   \
-            "ld    $12, %[OPENGL_API]($3)\n\t"                    \
-            "beqz  $12, 1f\n\t"                                   \
-            " move $25, $ra\n\t"                                  \
-            "ld    $12, %[API]($12)\n\t"                          \
-            "beqz  $12, 1f\n\t"                                   \
-            " nop\n\t"                                            \
-            "move  $25, $12\n\t"                                  \
-            "1:\n\t"                                              \
-            "jalr  $0, $25\n\t"                                   \
-            " move $2, $0\n\t"                                    \
-            ".set  pop\n\t"                                       \
-            :                                                     \
-            : [OPENGL_API] "I"(TLS_SLOT_OPENGL_API*sizeof(void*)),\
-              [API] "I"(__builtin_offsetof(gl_hooks_t, gl._api))  \
-            : "$2", "$3", "$4", "$5", "$6", "$7", "$8", "$9",     \
-              "$10", "$11", "$12", "$25"                          \
-        );
-
-    #define CALL_GL_API_INTERNAL_SET_RETURN_VALUE
-    #define CALL_GL_API_INTERNAL_DO_RETURN
-
-#elif defined(__mips__)
-
-    #define API_ENTRY(_api) __attribute__((naked,noinline)) _api
-
-    // t0:  $8
-    // fn:  $25
-    // tls: $3
-    // v0:  $2
     #define CALL_GL_API_INTERNAL_CALL(_api, ...)                 \
         asm volatile(                                            \
-            ".set  push\n\t"                                     \
-            ".set  noreorder\n\t"                                \
-            ".set  mips32r2\n\t"                                 \
-            "rdhwr $3, $29\n\t"                                  \
-            "lw    $3, %[OPENGL_API]($3)\n\t"                    \
-            "beqz  $3, 1f\n\t"                                   \
-            " move $25,$ra\n\t"                                  \
-            "lw    $3, %[API]($3)\n\t"                           \
-            "beqz  $3, 1f\n\t"                                   \
-            " nop\n\t"                                           \
-            "move  $25, $3\n\t"                                  \
-            "1:\n\t"                                             \
-            "jalr  $0, $25\n\t"                                  \
-            " move $2, $0\n\t"                                   \
-            ".set  pop\n\t"                                      \
+            "mv t0, tp\n"                                        \
+            "li t1, %[tls]\n"                                    \
+            "add t0, t0, t1\n"                                   \
+            "ld t0, 0(t0)\n"                                     \
+            "beqz t0, 1f\n"                                      \
+            "li t1, %[api]\n"                                    \
+            "add t0, t0, t1\n"                                   \
+            "ld t0, 0(t0)\n"                                     \
+            "jalr x0, t0\n"                                      \
+            "1:\n"                                               \
             :                                                    \
-            : [OPENGL_API] "I"(TLS_SLOT_OPENGL_API*4),           \
-              [API] "I"(__builtin_offsetof(gl_hooks_t, gl._api)) \
-            : "$2", "$3", "$4", "$5", "$6", "$7", "$8", "$25"    \
+            : [tls] "i"(TLS_SLOT_OPENGL_API*sizeof(void *)),     \
+              [api] "i"(__builtin_offsetof(gl_hooks_t, gl._api)) \
+            : "t0", "t1", "t2", "a0", "a1", "a2", "a3", "a4",    \
+              "a5", "t6", "t3", "t4", "t5", "t6"                 \
         );
 
-    #define CALL_GL_API_INTERNAL_SET_RETURN_VALUE
-    #define CALL_GL_API_INTERNAL_DO_RETURN
+    #define CALL_GL_API_INTERNAL_SET_RETURN_VALUE \
+        asm volatile(                             \
+            "li a0, 0\n"                          \
+            :                                     \
+            :                                     \
+            : "a0"                                \
+        );
+
+    #define CALL_GL_API_INTERNAL_DO_RETURN \
+        asm volatile(                      \
+            "ret\n"                        \
+            :                              \
+            :                              \
+            :                              \
+        );
 
 #endif
 
diff --git a/opengl/libs/GLES_CM/gl.cpp b/opengl/libs/GLES_CM/gl.cpp
index bacd4b4..64c0f97 100644
--- a/opengl/libs/GLES_CM/gl.cpp
+++ b/opengl/libs/GLES_CM/gl.cpp
@@ -247,73 +247,44 @@
             :                              \
         );
 
-#elif defined(__mips64)
+#elif defined(__riscv)
 
     #define API_ENTRY(_api) __attribute__((naked,noinline)) _api
 
-    // t0:  $12
-    // fn:  $25
-    // tls: $3
-    // v0:  $2
-    #define CALL_GL_API_INTERNAL_CALL(_api, ...)                  \
-        asm volatile(                                             \
-            ".set  push\n\t"                                      \
-            ".set  noreorder\n\t"                                 \
-            "rdhwr $3, $29\n\t"                                   \
-            "ld    $12, %[OPENGL_API]($3)\n\t"                    \
-            "beqz  $12, 1f\n\t"                                   \
-            " move $25, $ra\n\t"                                  \
-            "ld    $12, %[API]($12)\n\t"                          \
-            "beqz  $12, 1f\n\t"                                   \
-            " nop\n\t"                                            \
-            "move  $25, $12\n\t"                                  \
-            "1:\n\t"                                              \
-            "jalr  $0, $25\n\t"                                   \
-            " move $2, $0\n\t"                                    \
-            ".set  pop\n\t"                                       \
-            :                                                     \
-            : [OPENGL_API] "I"(TLS_SLOT_OPENGL_API*sizeof(void*)),\
-              [API] "I"(__builtin_offsetof(gl_hooks_t, gl._api))  \
-            : "$2", "$3", "$4", "$5", "$6", "$7", "$8", "$9",     \
-              "$10", "$11", "$12", "$25"                          \
-        );
-
-    #define CALL_GL_API_INTERNAL_SET_RETURN_VALUE
-    #define CALL_GL_API_INTERNAL_DO_RETURN
-
-#elif defined(__mips__)
-
-    #define API_ENTRY(_api) __attribute__((naked,noinline)) _api
-
-    // t0:  $8
-    // fn:  $25
-    // tls: $3
-    // v0:  $2
     #define CALL_GL_API_INTERNAL_CALL(_api, ...)                 \
         asm volatile(                                            \
-            ".set  push\n\t"                                     \
-            ".set  noreorder\n\t"                                \
-            ".set  mips32r2\n\t"                                 \
-            "rdhwr $3, $29\n\t"                                  \
-            "lw    $3, %[OPENGL_API]($3)\n\t"                    \
-            "beqz  $3, 1f\n\t"                                   \
-            " move $25,$ra\n\t"                                  \
-            "lw    $3, %[API]($3)\n\t"                           \
-            "beqz  $3, 1f\n\t"                                   \
-            " nop\n\t"                                           \
-            "move  $25, $3\n\t"                                  \
-            "1:\n\t"                                             \
-            "jalr  $0, $25\n\t"                                  \
-            " move $2, $0\n\t"                                   \
-            ".set  pop\n\t"                                      \
+            "mv t0, tp\n"                                        \
+            "li t1, %[tls]\n"                                    \
+            "add t0, t0, t1\n"                                   \
+            "ld t0, 0(t0)\n"                                     \
+            "beqz t0, 1f\n"                                      \
+            "li t1, %[api]\n"                                    \
+            "add t0, t0, t1\n"                                   \
+            "ld t0, 0(t0)\n"                                     \
+            "jalr x0, t0\n"                                      \
+            "1:\n"                                               \
             :                                                    \
-            : [OPENGL_API] "I"(TLS_SLOT_OPENGL_API*4),           \
-              [API] "I"(__builtin_offsetof(gl_hooks_t, gl._api)) \
-            : "$2", "$3", "$4", "$5", "$6", "$7", "$8", "$25"    \
+            : [tls] "i"(TLS_SLOT_OPENGL_API*sizeof(void *)),     \
+              [api] "i"(__builtin_offsetof(gl_hooks_t, gl._api)) \
+            : "t0", "t1", "t2", "a0", "a1", "a2", "a3", "a4",    \
+              "a5", "t6", "t3", "t4", "t5", "t6"                 \
         );
 
-    #define CALL_GL_API_INTERNAL_SET_RETURN_VALUE
-    #define CALL_GL_API_INTERNAL_DO_RETURN
+    #define CALL_GL_API_INTERNAL_SET_RETURN_VALUE \
+        asm volatile(                             \
+            "li a0, 0\n"                          \
+            :                                     \
+            :                                     \
+            : "a0"                                \
+        );
+
+    #define CALL_GL_API_INTERNAL_DO_RETURN \
+        asm volatile(                      \
+            "ret\n"                        \
+            :                              \
+            :                              \
+            :                              \
+        );
 
 #endif
 
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index 84c18fd..acd3d75 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -1071,7 +1071,7 @@
                                                                 int32_t y, TouchState* touchState,
                                                                 bool isStylus,
                                                                 bool addOutsideTargets,
-                                                                bool ignoreDragWindow) {
+                                                                bool ignoreDragWindow) const {
     if (addOutsideTargets && touchState == nullptr) {
         LOG_ALWAYS_FATAL("Must provide a valid touch state if adding outside targets");
     }
@@ -3984,13 +3984,14 @@
     if (DEBUG_INBOUND_EVENT_DETAILS) {
         ALOGD("notifyMotion - id=%" PRIx32 " eventTime=%" PRId64 ", deviceId=%d, source=0x%x, "
               "displayId=%" PRId32 ", policyFlags=0x%x, "
-              "action=0x%x, actionButton=0x%x, flags=0x%x, metaState=0x%x, buttonState=0x%x, "
+              "action=%s, actionButton=0x%x, flags=0x%x, metaState=0x%x, buttonState=0x%x, "
               "edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, xCursorPosition=%f, "
               "yCursorPosition=%f, downTime=%" PRId64,
               args->id, args->eventTime, args->deviceId, args->source, args->displayId,
-              args->policyFlags, args->action, args->actionButton, args->flags, args->metaState,
-              args->buttonState, args->edgeFlags, args->xPrecision, args->yPrecision,
-              args->xCursorPosition, args->yCursorPosition, args->downTime);
+              args->policyFlags, MotionEvent::actionToString(args->action).c_str(),
+              args->actionButton, args->flags, args->metaState, args->buttonState, args->edgeFlags,
+              args->xPrecision, args->yPrecision, args->xCursorPosition, args->yCursorPosition,
+              args->downTime);
         for (uint32_t i = 0; i < args->pointerCount; i++) {
             ALOGD("  Pointer %d: id=%d, toolType=%d, "
                   "x=%f, y=%f, pressure=%f, size=%f, "
@@ -5012,8 +5013,6 @@
                          ? "not set"
                          : std::to_string(mTouchModePerDisplay[displayId]).c_str());
 
-        // TODO(b/198499018): Ensure that WM can guarantee that touch mode is properly set when
-        // display is created.
         auto touchModeIt = mTouchModePerDisplay.find(displayId);
         if (touchModeIt != mTouchModePerDisplay.end() && touchModeIt->second == inTouchMode) {
             return false;
diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h
index 14b046a..b20a548 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.h
+++ b/services/inputflinger/dispatcher/InputDispatcher.h
@@ -239,7 +239,7 @@
 
     sp<android::gui::WindowInfoHandle> findTouchedWindowAtLocked(
             int32_t displayId, int32_t x, int32_t y, TouchState* touchState, bool isStylus = false,
-            bool addOutsideTargets = false, bool ignoreDragWindow = false) REQUIRES(mLock);
+            bool addOutsideTargets = false, bool ignoreDragWindow = false) const REQUIRES(mLock);
 
     std::vector<sp<android::gui::WindowInfoHandle>> findTouchedSpyWindowsAtLocked(
             int32_t displayId, int32_t x, int32_t y, bool isStylus) const REQUIRES(mLock);
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index 67a226e..b65f1b4 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -155,6 +155,8 @@
         "DisplayRenderArea.cpp",
         "Effects/Daltonizer.cpp",
         "EventLog/EventLog.cpp",
+        "FrontEnd/LayerCreationArgs.cpp",
+        "FrontEnd/TransactionHandler.cpp",
         "FlagManager.cpp",
         "FpsReporter.cpp",
         "FrameTracer/FrameTracer.cpp",
@@ -193,7 +195,6 @@
         "Tracing/TransactionTracing.cpp",
         "Tracing/TransactionProtoParser.cpp",
         "TransactionCallbackInvoker.cpp",
-        "TransactionHandler.cpp",
         "TunnelModeEnabledReporter.cpp",
     ],
 }
diff --git a/services/surfaceflinger/Client.cpp b/services/surfaceflinger/Client.cpp
index 30b8759..7202bef 100644
--- a/services/surfaceflinger/Client.cpp
+++ b/services/surfaceflinger/Client.cpp
@@ -24,6 +24,7 @@
 #include <gui/AidlStatusUtil.h>
 
 #include "Client.h"
+#include "FrontEnd/LayerCreationArgs.h"
 #include "Layer.h"
 #include "SurfaceFlinger.h"
 
@@ -83,7 +84,8 @@
     sp<IBinder> handle;
     LayerCreationArgs args(mFlinger.get(), sp<Client>::fromExisting(this), name.c_str(),
                            static_cast<uint32_t>(flags), std::move(metadata));
-    const status_t status = mFlinger->createLayer(args, parent, *outResult);
+    args.parentHandle = parent;
+    const status_t status = mFlinger->createLayer(args, *outResult);
     return binderStatusFromStatusT(status);
 }
 
diff --git a/services/surfaceflinger/ClientCache.cpp b/services/surfaceflinger/ClientCache.cpp
index b01932e..2bd8f32 100644
--- a/services/surfaceflinger/ClientCache.cpp
+++ b/services/surfaceflinger/ClientCache.cpp
@@ -59,16 +59,17 @@
     return true;
 }
 
-bool ClientCache::add(const client_cache_t& cacheId, const sp<GraphicBuffer>& buffer) {
+base::expected<std::shared_ptr<renderengine::ExternalTexture>, ClientCache::AddError>
+ClientCache::add(const client_cache_t& cacheId, const sp<GraphicBuffer>& buffer) {
     auto& [processToken, id] = cacheId;
     if (processToken == nullptr) {
         ALOGE_AND_TRACE("ClientCache::add - invalid (nullptr) process token");
-        return false;
+        return base::unexpected(AddError::Unspecified);
     }
 
     if (!buffer) {
         ALOGE_AND_TRACE("ClientCache::add - invalid (nullptr) buffer");
-        return false;
+        return base::unexpected(AddError::Unspecified);
     }
 
     std::lock_guard lock(mMutex);
@@ -81,7 +82,7 @@
         token = processToken.promote();
         if (!token) {
             ALOGE_AND_TRACE("ClientCache::add - invalid token");
-            return false;
+            return base::unexpected(AddError::Unspecified);
         }
 
         // Only call linkToDeath if not a local binder
@@ -89,7 +90,7 @@
             status_t err = token->linkToDeath(mDeathRecipient);
             if (err != NO_ERROR) {
                 ALOGE_AND_TRACE("ClientCache::add - could not link to death");
-                return false;
+                return base::unexpected(AddError::Unspecified);
             }
         }
         auto [itr, success] =
@@ -104,17 +105,17 @@
 
     if (processBuffers.size() > BUFFER_CACHE_MAX_SIZE) {
         ALOGE_AND_TRACE("ClientCache::add - cache is full");
-        return false;
+        return base::unexpected(AddError::CacheFull);
     }
 
     LOG_ALWAYS_FATAL_IF(mRenderEngine == nullptr,
                         "Attempted to build the ClientCache before a RenderEngine instance was "
                         "ready!");
-    processBuffers[id].buffer = std::make_shared<
-            renderengine::impl::ExternalTexture>(buffer, *mRenderEngine,
-                                                 renderengine::impl::ExternalTexture::Usage::
-                                                         READABLE);
-    return true;
+
+    return (processBuffers[id].buffer = std::make_shared<
+                    renderengine::impl::ExternalTexture>(buffer, *mRenderEngine,
+                                                         renderengine::impl::ExternalTexture::
+                                                                 Usage::READABLE));
 }
 
 void ClientCache::erase(const client_cache_t& cacheId) {
diff --git a/services/surfaceflinger/ClientCache.h b/services/surfaceflinger/ClientCache.h
index a9b8177..cdeac2b 100644
--- a/services/surfaceflinger/ClientCache.h
+++ b/services/surfaceflinger/ClientCache.h
@@ -37,7 +37,10 @@
 public:
     ClientCache();
 
-    bool add(const client_cache_t& cacheId, const sp<GraphicBuffer>& buffer);
+    enum class AddError { CacheFull, Unspecified };
+
+    base::expected<std::shared_ptr<renderengine::ExternalTexture>, AddError> add(
+            const client_cache_t& cacheId, const sp<GraphicBuffer>& buffer);
     void erase(const client_cache_t& cacheId);
 
     std::shared_ptr<renderengine::ExternalTexture> get(const client_cache_t& cacheId);
diff --git a/services/surfaceflinger/FrontEnd/LayerCreationArgs.cpp b/services/surfaceflinger/FrontEnd/LayerCreationArgs.cpp
new file mode 100644
index 0000000..6d492c0
--- /dev/null
+++ b/services/surfaceflinger/FrontEnd/LayerCreationArgs.cpp
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2022 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.
+ */
+
+#include "LayerCreationArgs.h"
+#include <binder/IPCThreadState.h>
+#include <private/android_filesystem_config.h>
+#include "Client.h"
+#include "gui/LayerMetadata.h"
+
+namespace android::surfaceflinger {
+
+std::atomic<uint32_t> LayerCreationArgs::sSequence{1};
+
+LayerCreationArgs::LayerCreationArgs(SurfaceFlinger* flinger, sp<Client> client, std::string name,
+                                     uint32_t flags, gui::LayerMetadata metadataArg,
+                                     std::optional<uint32_t> id)
+      : flinger(flinger),
+        client(std::move(client)),
+        name(std::move(name)),
+        flags(flags),
+        metadata(std::move(metadataArg)) {
+    IPCThreadState* ipc = IPCThreadState::self();
+    ownerPid = ipc->getCallingPid();
+    uid_t callingUid = ipc->getCallingUid();
+    metadata.setInt32(gui::METADATA_CALLING_UID, static_cast<int32_t>(callingUid));
+    ownerUid = callingUid;
+    if (ownerUid == AID_GRAPHICS || ownerUid == AID_SYSTEM) {
+        // System can override the calling UID/PID since it can create layers on behalf of apps.
+        ownerPid = metadata.getInt32(gui::METADATA_OWNER_PID, ownerPid);
+        ownerUid = static_cast<uid_t>(
+                metadata.getInt32(gui::METADATA_OWNER_UID, static_cast<int32_t>(ownerUid)));
+    }
+
+    if (id) {
+        sequence = *id;
+        sSequence = *id + 1;
+    } else {
+        sequence = sSequence++;
+        if (sequence == UNASSIGNED_LAYER_ID) {
+            ALOGW("Layer sequence id rolled over.");
+            sequence = sSequence++;
+        }
+    }
+}
+
+LayerCreationArgs::LayerCreationArgs(const LayerCreationArgs& args)
+      : LayerCreationArgs(args.flinger, args.client, args.name, args.flags, args.metadata) {}
+
+} // namespace android::surfaceflinger
diff --git a/services/surfaceflinger/FrontEnd/LayerCreationArgs.h b/services/surfaceflinger/FrontEnd/LayerCreationArgs.h
new file mode 100644
index 0000000..7b5a157
--- /dev/null
+++ b/services/surfaceflinger/FrontEnd/LayerCreationArgs.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2022 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 <binder/Binder.h>
+#include <gui/LayerMetadata.h>
+#include <utils/StrongPointer.h>
+#include <cstdint>
+#include <limits>
+#include <optional>
+constexpr uint32_t UNASSIGNED_LAYER_ID = std::numeric_limits<uint32_t>::max();
+
+namespace android {
+class SurfaceFlinger;
+class Client;
+} // namespace android
+
+namespace android::surfaceflinger {
+
+struct LayerCreationArgs {
+    static std::atomic<uint32_t> sSequence;
+
+    LayerCreationArgs(android::SurfaceFlinger*, sp<android::Client>, std::string name,
+                      uint32_t flags, gui::LayerMetadata,
+                      std::optional<uint32_t> id = std::nullopt);
+    LayerCreationArgs(const LayerCreationArgs&);
+
+    android::SurfaceFlinger* flinger;
+    sp<android::Client> client;
+    std::string name;
+    uint32_t flags; // ISurfaceComposerClient flags
+    gui::LayerMetadata metadata;
+    pid_t ownerPid;
+    uid_t ownerUid;
+    uint32_t textureName;
+    uint32_t sequence;
+    bool addToRoot = true;
+    wp<IBinder> parentHandle = nullptr;
+    wp<IBinder> mirrorLayerHandle = nullptr;
+};
+
+} // namespace android::surfaceflinger
diff --git a/services/surfaceflinger/TransactionHandler.cpp b/services/surfaceflinger/FrontEnd/TransactionHandler.cpp
similarity index 95%
rename from services/surfaceflinger/TransactionHandler.cpp
rename to services/surfaceflinger/FrontEnd/TransactionHandler.cpp
index 6c6a487..95961fe 100644
--- a/services/surfaceflinger/TransactionHandler.cpp
+++ b/services/surfaceflinger/FrontEnd/TransactionHandler.cpp
@@ -168,15 +168,16 @@
     return !mPendingTransactionQueues.empty() || !mLocklessTransactionQueue.isEmpty();
 }
 
-void TransactionHandler::onTransactionQueueStalled(const TransactionState& transaction,
-                                                   sp<ITransactionCompletedListener>& listener) {
-    if (std::find(mStalledTransactions.begin(), mStalledTransactions.end(), transaction.id) !=
+void TransactionHandler::onTransactionQueueStalled(uint64_t transactionId,
+                                                   sp<ITransactionCompletedListener>& listener,
+                                                   const std::string& reason) {
+    if (std::find(mStalledTransactions.begin(), mStalledTransactions.end(), transactionId) !=
         mStalledTransactions.end()) {
         return;
     }
 
-    mStalledTransactions.push_back(transaction.id);
-    listener->onTransactionQueueStalled();
+    mStalledTransactions.push_back(transactionId);
+    listener->onTransactionQueueStalled(String8(reason.c_str()));
 }
 
 void TransactionHandler::removeFromStalledTransactions(uint64_t id) {
@@ -185,4 +186,4 @@
         mStalledTransactions.erase(it);
     }
 }
-} // namespace android
\ No newline at end of file
+} // namespace android
diff --git a/services/surfaceflinger/TransactionHandler.h b/services/surfaceflinger/FrontEnd/TransactionHandler.h
similarity index 93%
rename from services/surfaceflinger/TransactionHandler.h
rename to services/surfaceflinger/FrontEnd/TransactionHandler.h
index 237b48d..2b6f07d 100644
--- a/services/surfaceflinger/TransactionHandler.h
+++ b/services/surfaceflinger/FrontEnd/TransactionHandler.h
@@ -54,7 +54,8 @@
     std::vector<TransactionState> flushTransactions();
     void addTransactionReadyFilter(TransactionFilter&&);
     void queueTransaction(TransactionState&&);
-    void onTransactionQueueStalled(const TransactionState&, sp<ITransactionCompletedListener>&);
+    void onTransactionQueueStalled(uint64_t transactionId, sp<ITransactionCompletedListener>&,
+                                   const std::string& reason);
     void removeFromStalledTransactions(uint64_t transactionId);
 
 private:
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index b517568..def0dfa 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -62,12 +62,14 @@
 
 #include <algorithm>
 #include <mutex>
+#include <optional>
 #include <sstream>
 
 #include "DisplayDevice.h"
 #include "DisplayHardware/HWComposer.h"
 #include "FrameTimeline.h"
 #include "FrameTracer/FrameTracer.h"
+#include "FrontEnd/LayerCreationArgs.h"
 #include "LayerProtoHelper.h"
 #include "SurfaceFlinger.h"
 #include "TimeStats/TimeStats.h"
@@ -131,10 +133,8 @@
 
 using PresentState = frametimeline::SurfaceFrame::PresentState;
 
-std::atomic<int32_t> Layer::sSequence{1};
-
 Layer::Layer(const LayerCreationArgs& args)
-      : sequence(args.sequence.value_or(sSequence++)),
+      : sequence(args.sequence),
         mFlinger(sp<SurfaceFlinger>::fromExisting(args.flinger)),
         mName(base::StringPrintf("%s#%d", args.name.c_str(), sequence)),
         mClientRef(args.client),
@@ -153,9 +153,6 @@
     if (args.flags & ISurfaceComposerClient::eSecure) layerFlags |= layer_state_t::eLayerSecure;
     if (args.flags & ISurfaceComposerClient::eSkipScreenshot)
         layerFlags |= layer_state_t::eLayerSkipScreenshot;
-    if (args.sequence) {
-        sSequence = *args.sequence + 1;
-    }
     mDrawingState.flags = layerFlags;
     mDrawingState.crop.makeInvalid();
     mDrawingState.z = 0;
@@ -200,18 +197,8 @@
     mFrameTracker.setDisplayRefreshPeriod(
             args.flinger->mScheduler->getVsyncPeriodFromRefreshRateConfigs());
 
-    mCallingPid = args.callingPid;
-    mCallingUid = args.callingUid;
-
-    if (mCallingUid == AID_GRAPHICS || mCallingUid == AID_SYSTEM) {
-        // If the system didn't send an ownerUid, use the callingUid for the ownerUid.
-        mOwnerUid = args.metadata.getInt32(gui::METADATA_OWNER_UID, mCallingUid);
-        mOwnerPid = args.metadata.getInt32(gui::METADATA_OWNER_PID, mCallingPid);
-    } else {
-        // A create layer request from a non system request cannot specify the owner uid
-        mOwnerUid = mCallingUid;
-        mOwnerPid = mCallingPid;
-    }
+    mOwnerUid = args.ownerUid;
+    mOwnerPid = args.ownerPid;
 
     mPremultipliedAlpha = !(args.flags & ISurfaceComposerClient::eNonPremultiplied);
     mPotentialCursor = args.flags & ISurfaceComposerClient::eCursorWindow;
@@ -268,18 +255,6 @@
     }
 }
 
-LayerCreationArgs::LayerCreationArgs(SurfaceFlinger* flinger, sp<Client> client, std::string name,
-                                     uint32_t flags, LayerMetadata metadata)
-      : flinger(flinger),
-        client(std::move(client)),
-        name(std::move(name)),
-        flags(flags),
-        metadata(std::move(metadata)) {
-    IPCThreadState* ipc = IPCThreadState::self();
-    callingPid = ipc->getCallingPid();
-    callingUid = ipc->getCallingUid();
-}
-
 // ---------------------------------------------------------------------------
 // callbacks
 // ---------------------------------------------------------------------------
@@ -1294,7 +1269,6 @@
     if (fps) {
         surfaceFrame->setRenderRate(*fps);
     }
-    // TODO(b/178542907): Implement onSurfaceFrameCreated for BQLayer as well.
     onSurfaceFrameCreated(surfaceFrame);
     return surfaceFrame;
 }
@@ -1356,6 +1330,10 @@
     return usage;
 }
 
+void Layer::skipReportingTransformHint() {
+    mSkipReportingTransformHint = true;
+}
+
 void Layer::updateTransformHint(ui::Transform::RotationFlags transformHint) {
     if (mFlinger->mDebugDisableTransformHint || transformHint & ui::Transform::ROT_INVALID) {
         transformHint = ui::Transform::ROT_0;
@@ -1498,8 +1476,8 @@
 }
 
 void Layer::dumpCallingUidPid(std::string& result) const {
-    StringAppendF(&result, "Layer %s (%s) callingPid:%d callingUid:%d ownerUid:%d\n",
-                  getName().c_str(), getType(), mCallingPid, mCallingUid, mOwnerUid);
+    StringAppendF(&result, "Layer %s (%s) ownerPid:%d ownerUid:%d\n", getName().c_str(), getType(),
+                  mOwnerPid, mOwnerUid);
 }
 
 void Layer::onDisconnect() {
@@ -1559,8 +1537,6 @@
                 newParent->canDrawShadows() ? 0.f : newParent->mEffectiveShadowRadius;
         child->computeBounds(newParent->mBounds, newParent->mEffectiveTransform,
                              parentShadowRadius);
-        child->updateSnapshot(true /* updateGeometry */);
-        child->updateChildrenSnapshots(true /* updateGeometry */);
     }
 }
 
@@ -2703,6 +2679,10 @@
 
 void Layer::onSurfaceFrameCreated(
         const std::shared_ptr<frametimeline::SurfaceFrame>& surfaceFrame) {
+    if (!hasBufferOrSidebandStreamInDrawing()) {
+        return;
+    }
+
     while (mPendingJankClassifications.size() >= kPendingClassificationMaxSurfaceFrames) {
         // Too many SurfaceFrames pending classification. The front of the deque is probably not
         // tracked by FrameTimeline and will never be presented. This will only result in a memory
@@ -2718,7 +2698,9 @@
 
 void Layer::releasePendingBuffer(nsecs_t dequeueReadyTime) {
     for (const auto& handle : mDrawingState.callbackHandles) {
-        handle->transformHint = mTransformHint;
+        handle->transformHint = mSkipReportingTransformHint
+                ? std::nullopt
+                : std::make_optional<uint32_t>(mTransformHint);
         handle->dequeueReadyTime = dequeueReadyTime;
         handle->currentMaxAcquiredBufferCount =
                 mFlinger->getMaxAcquiredBufferCountForCurrentRefreshRate(mOwnerUid);
@@ -3886,6 +3868,7 @@
     if (mTransformHint == ui::Transform::ROT_INVALID) {
         mTransformHint = displayTransformHint;
     }
+    mSkipReportingTransformHint = false;
 }
 
 const std::shared_ptr<renderengine::ExternalTexture>& Layer::getExternalTexture() const {
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 7e46d1c..1773c03 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -82,24 +82,7 @@
 class SurfaceFrame;
 } // namespace frametimeline
 
-struct LayerCreationArgs {
-    LayerCreationArgs(SurfaceFlinger*, sp<Client>, std::string name, uint32_t flags, LayerMetadata);
-
-    SurfaceFlinger* flinger;
-    const sp<Client> client;
-    std::string name;
-    uint32_t flags;
-    LayerMetadata metadata;
-
-    pid_t callingPid;
-    uid_t callingUid;
-    uint32_t textureName;
-    std::optional<uint32_t> sequence = std::nullopt;
-    bool addToRoot = true;
-};
-
 class Layer : public virtual RefBase {
-    static std::atomic<int32_t> sSequence;
     // The following constants represent priority of the window. SF uses this information when
     // deciding which window has a priority when deciding about the refresh rate of the screen.
     // Priority 0 is considered the highest priority. -1 means that the priority is unset.
@@ -678,7 +661,7 @@
      * Sets display transform hint on BufferLayerConsumer.
      */
     void updateTransformHint(ui::Transform::RotationFlags);
-
+    void skipReportingTransformHint();
     inline const State& getDrawingState() const { return mDrawingState; }
     inline State& getDrawingState() { return mDrawingState; }
 
@@ -1082,6 +1065,10 @@
         return ((mSidebandStream != nullptr) || (mBufferInfo.mBuffer != nullptr));
     }
 
+    bool hasBufferOrSidebandStreamInDrawing() const {
+        return ((mDrawingState.sidebandStream != nullptr) || (mDrawingState.buffer != nullptr));
+    }
+
     bool hasSomethingToDraw() const { return hasEffect() || hasBufferOrSidebandStream(); }
 
     void updateChildrenSnapshots(bool updateGeometry);
@@ -1104,11 +1091,6 @@
 
     bool mGetHandleCalled = false;
 
-    // Tracks the process and user id of the caller when creating this layer
-    // to help debugging.
-    pid_t mCallingPid;
-    uid_t mCallingUid;
-
     // The current layer is a clone of mClonedFrom. This means that this layer will update it's
     // properties based on mClonedFrom. When mClonedFrom latches a new buffer for BufferLayers,
     // this layer will update it's buffer. When mClonedFrom updates it's drawing state, children,
@@ -1143,6 +1125,7 @@
     // Transform hint provided to the producer. This must be accessed holding
     // the mStateLock.
     ui::Transform::RotationFlags mTransformHint = ui::Transform::ROT_0;
+    bool mSkipReportingTransformHint = true;
 
     ReleaseCallbackId mPreviousReleaseCallbackId = ReleaseCallbackId::INVALID_ID;
     uint64_t mPreviousReleasedFrameNumber = 0;
@@ -1157,7 +1140,7 @@
 
     std::deque<std::shared_ptr<android::frametimeline::SurfaceFrame>> mPendingJankClassifications;
     // An upper bound on the number of SurfaceFrames in the pending classifications deque.
-    static constexpr int kPendingClassificationMaxSurfaceFrames = 25;
+    static constexpr int kPendingClassificationMaxSurfaceFrames = 50;
 
     const std::string mBlastTransactionName{"BufferTX - " + mName};
     // This integer is incremented everytime a buffer arrives at the server for this layer,
diff --git a/services/surfaceflinger/LayerRenderArea.cpp b/services/surfaceflinger/LayerRenderArea.cpp
index 3e6ed41..554fae4 100644
--- a/services/surfaceflinger/LayerRenderArea.cpp
+++ b/services/surfaceflinger/LayerRenderArea.cpp
@@ -18,6 +18,7 @@
 #include <ui/Transform.h>
 
 #include "DisplayDevice.h"
+#include "FrontEnd/LayerCreationArgs.h"
 #include "Layer.h"
 #include "LayerRenderArea.h"
 #include "SurfaceFlinger.h"
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index f3148cb..029dd9f 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -84,6 +84,7 @@
 #include <ui/DisplayState.h>
 #include <ui/DynamicDisplayInfo.h>
 #include <ui/GraphicBufferAllocator.h>
+#include <ui/LayerStack.h>
 #include <ui/PixelFormat.h>
 #include <ui/StaticDisplayInfo.h>
 #include <utils/StopWatch.h>
@@ -122,6 +123,7 @@
 #include "FpsReporter.h"
 #include "FrameTimeline/FrameTimeline.h"
 #include "FrameTracer/FrameTracer.h"
+#include "FrontEnd/LayerCreationArgs.h"
 #include "HdrLayerInfoReporter.h"
 #include "Layer.h"
 #include "LayerProtoHelper.h"
@@ -2179,8 +2181,8 @@
     std::vector<Layer*> layers;
 
     mDrawingState.traverseInZOrder([&refreshArgs, &layers](Layer* layer) {
-        layer->updateSnapshot(refreshArgs.updatingGeometryThisFrame);
         if (auto layerFE = layer->getCompositionEngineLayerFE()) {
+            layer->updateSnapshot(refreshArgs.updatingGeometryThisFrame);
             refreshArgs.layers.push_back(layerFE);
             layers.push_back(layer);
         }
@@ -3142,20 +3144,21 @@
                 }
             }
 
-            if (!hintDisplay && mDisplays.size() > 0) {
+            if (!hintDisplay) {
                 // NOTE: TEMPORARY FIX ONLY. Real fix should cause layers to
                 // redraw after transform hint changes. See bug 8508397.
-
                 // could be null when this layer is using a layerStack
                 // that is not visible on any display. Also can occur at
                 // screen off/on times.
-                hintDisplay = getDefaultDisplayDeviceLocked();
-            }
-
-            if (hintDisplay) {
-                layer->updateTransformHint(hintDisplay->getTransformHint());
+                // U Update: Don't provide stale hints to the clients. For
+                // special cases where we want the app to draw its
+                // first frame before the display is available, we rely
+                // on WMS and DMS to provide the right information
+                // so the client can calculate the hint.
+                ALOGV("Skipping reporting transform hint update for %s", layer->getDebugName());
+                layer->skipReportingTransformHint();
             } else {
-                ALOGW("Ignoring transform hint update for %s", layer->getDebugName());
+                layer->updateTransformHint(hintDisplay->getTransformHint());
             }
         });
     }
@@ -3600,9 +3603,9 @@
     return !mLayersWithQueuedFrames.empty() && newDataLatched;
 }
 
-status_t SurfaceFlinger::addClientLayer(const sp<Client>& client, const sp<IBinder>& handle,
+status_t SurfaceFlinger::addClientLayer(const LayerCreationArgs& args, const sp<IBinder>& handle,
                                         const sp<Layer>& layer, const wp<Layer>& parent,
-                                        bool addToRoot, uint32_t* outTransformHint) {
+                                        uint32_t* outTransformHint) {
     if (mNumLayers >= MAX_LAYERS) {
         ALOGE("AddClientLayer failed, mNumLayers (%zu) >= MAX_LAYERS (%zu)", mNumLayers.load(),
               MAX_LAYERS);
@@ -3633,12 +3636,12 @@
 
     {
         std::scoped_lock<std::mutex> lock(mCreatedLayersLock);
-        mCreatedLayers.emplace_back(layer, parent, addToRoot);
+        mCreatedLayers.emplace_back(layer, parent, args.addToRoot);
     }
 
     // attach this layer to the client
-    if (client != nullptr) {
-        client->attachLayer(handle, layer);
+    if (args.client != nullptr) {
+        args.client->attachLayer(handle, layer);
     }
 
     setTransactionFlags(eTransactionNeeded);
@@ -3743,7 +3746,10 @@
                 if (listener &&
                     (flushState.queueProcessTime - transaction.postTime) >
                             std::chrono::nanoseconds(4s).count()) {
-                    mTransactionHandler.onTransactionQueueStalled(transaction, listener);
+                    mTransactionHandler
+                            .onTransactionQueueStalled(transaction.id, listener,
+                                                       "Buffer processing hung up due to stuck "
+                                                       "fence. Indicates GPU hang");
                 }
                 return false;
             }
@@ -3959,8 +3965,9 @@
     uint32_t clientStateFlags = 0;
     for (int i = 0; i < states.size(); i++) {
         ComposerState& state = states.editItemAt(i);
-        clientStateFlags |= setClientStateLocked(frameTimelineInfo, state, desiredPresentTime,
-                                                 isAutoTimestamp, postTime, permissions);
+        clientStateFlags |=
+                setClientStateLocked(frameTimelineInfo, state, desiredPresentTime, isAutoTimestamp,
+                                     postTime, permissions, transactionId);
         if ((flags & eAnimation) && state.state.surface) {
             if (const auto layer = fromHandle(state.state.surface).promote()) {
                 using LayerUpdateType = scheduler::LayerHistory::LayerUpdateType;
@@ -4076,7 +4083,8 @@
 uint32_t SurfaceFlinger::setClientStateLocked(const FrameTimelineInfo& frameTimelineInfo,
                                               ComposerState& composerState,
                                               int64_t desiredPresentTime, bool isAutoTimestamp,
-                                              int64_t postTime, uint32_t permissions) {
+                                              int64_t postTime, uint32_t permissions,
+                                              uint64_t transactionId) {
     layer_state_t& s = composerState.state;
     s.sanitize(permissions);
 
@@ -4115,6 +4123,8 @@
         return 0;
     }
 
+    ui::LayerStack oldLayerStack = layer->getLayerStack();
+
     // Only set by BLAST adapter layers
     if (what & layer_state_t::eProducerDisconnect) {
         layer->onDisconnect();
@@ -4367,7 +4377,8 @@
 
     if (what & layer_state_t::eBufferChanged) {
         std::shared_ptr<renderengine::ExternalTexture> buffer =
-                getExternalTextureFromBufferData(*s.bufferData, layer->getDebugName());
+                getExternalTextureFromBufferData(*s.bufferData, layer->getDebugName(),
+                                                 transactionId);
         if (layer->setBuffer(buffer, *s.bufferData, postTime, desiredPresentTime, isAutoTimestamp,
                              dequeueBufferTimestamp, frameTimelineInfo)) {
             flags |= eTraversalNeeded;
@@ -4379,6 +4390,12 @@
     if (layer->setTransactionCompletedListeners(callbackHandles)) flags |= eTraversalNeeded;
     // Do not put anything that updates layer state or modifies flags after
     // setTransactionCompletedListener
+
+    // if the layer has been parented on to a new display, update its transform hint.
+    if (((flags & eTransformHintUpdateNeeded) == 0) && oldLayerStack != layer->getLayerStack()) {
+        flags |= eTransformHintUpdateNeeded;
+    }
+
     return flags;
 }
 
@@ -4402,8 +4419,10 @@
         if (!mirrorFrom) {
             return NAME_NOT_FOUND;
         }
-        LayerCreationArgs mirrorArgs = args;
+        LayerCreationArgs mirrorArgs(args);
         mirrorArgs.flags |= ISurfaceComposerClient::eNoColorFill;
+        mirrorArgs.mirrorLayerHandle = mirrorFromHandle;
+        mirrorArgs.addToRoot = false;
         status_t result = createEffectLayer(mirrorArgs, &outResult.handle, &mirrorLayer);
         if (result != NO_ERROR) {
             return result;
@@ -4419,8 +4438,7 @@
                                                 mirrorLayer->sequence, args.name,
                                                 mirrorFrom->sequence);
     }
-    return addClientLayer(args.client, outResult.handle, mirrorLayer /* layer */,
-                          nullptr /* parent */, false /* addToRoot */,
+    return addClientLayer(args, outResult.handle, mirrorLayer /* layer */, nullptr /* parent */,
                           nullptr /* outTransformHint */);
 }
 
@@ -4446,14 +4464,14 @@
         }
 
         layerStack = display->getLayerStack();
-        LayerCreationArgs mirrorArgs = args;
+        LayerCreationArgs mirrorArgs(args);
         mirrorArgs.flags |= ISurfaceComposerClient::eNoColorFill;
+        mirrorArgs.addToRoot = true;
         result = createEffectLayer(mirrorArgs, &outResult.handle, &rootMirrorLayer);
         outResult.layerId = rootMirrorLayer->sequence;
         outResult.layerName = String16(rootMirrorLayer->getDebugName());
-        result |= addClientLayer(args.client, outResult.handle, rootMirrorLayer /* layer */,
-                                 nullptr /* parent */, true /* addToRoot */,
-                                 nullptr /* outTransformHint */);
+        result |= addClientLayer(args, outResult.handle, rootMirrorLayer /* layer */,
+                                 nullptr /* parent */, nullptr /* outTransformHint */);
     }
 
     if (result != NO_ERROR) {
@@ -4474,8 +4492,7 @@
     return NO_ERROR;
 }
 
-status_t SurfaceFlinger::createLayer(LayerCreationArgs& args, const sp<IBinder>& parentHandle,
-                                     gui::CreateSurfaceResult& outResult) {
+status_t SurfaceFlinger::createLayer(LayerCreationArgs& args, gui::CreateSurfaceResult& outResult) {
     status_t result = NO_ERROR;
 
     sp<Layer> layer;
@@ -4504,11 +4521,11 @@
         return result;
     }
 
-    bool addToRoot = args.addToRoot && callingThreadHasUnscopedSurfaceFlingerAccess();
-    wp<Layer> parent = fromHandle(parentHandle);
-    if (parentHandle != nullptr && parent == nullptr) {
-        ALOGE("Invalid parent handle %p.", parentHandle.get());
-        addToRoot = false;
+    args.addToRoot = args.addToRoot && callingThreadHasUnscopedSurfaceFlingerAccess();
+    wp<Layer> parent = fromHandle(args.parentHandle.promote());
+    if (args.parentHandle != nullptr && parent == nullptr) {
+        ALOGE("Invalid parent handle %p.", args.parentHandle.promote().get());
+        args.addToRoot = false;
     }
 
     int parentId = -1;
@@ -4524,8 +4541,7 @@
     }
 
     uint32_t outTransformHint;
-    result = addClientLayer(args.client, outResult.handle, layer, parent, addToRoot,
-                            &outTransformHint);
+    result = addClientLayer(args, outResult.handle, layer, parent, &outTransformHint);
     if (result != NO_ERROR) {
         return result;
     }
@@ -6447,6 +6463,10 @@
     std::vector<Layer*> renderedLayers;
     bool disableBlurs = false;
     traverseLayers([&](Layer* layer) FTL_FAKE_GUARD(kMainThreadContext) {
+        auto layerFE = layer->getCompositionEngineLayerFE();
+        if (!layerFE) {
+            return;
+        }
         // Layer::prepareClientComposition uses the layer's snapshot to populate the resulting
         // LayerSettings. Calling Layer::updateSnapshot ensures that LayerSettings are
         // generated with the layer's current buffer and geometry.
@@ -6472,11 +6492,6 @@
                 isHdrLayer(layer) ? displayBrightnessNits : sdrWhitePointNits,
 
         };
-        auto layerFE = layer->getCompositionEngineLayerFE();
-        if (!layerFE) {
-            return;
-        }
-
         std::optional<compositionengine::LayerFE::LayerSettings> settings;
         {
             LayerSnapshotGuard layerSnapshotGuard(layer);
@@ -6877,7 +6892,20 @@
         parent->addChild(layer);
     }
 
-    layer->updateTransformHint(mActiveDisplayTransformHint);
+    ui::LayerStack layerStack = layer->getLayerStack();
+    sp<const DisplayDevice> hintDisplay;
+    // Find the display that includes the layer.
+    for (const auto& [token, display] : mDisplays) {
+        if (display->getLayerStack() == layerStack) {
+            hintDisplay = display;
+            break;
+        }
+    }
+
+    if (hintDisplay) {
+        layer->updateTransformHint(hintDisplay->getTransformHint());
+    }
+
     if (mTransactionTracing) {
         mTransactionTracing->onLayerAddedToDrawingState(layer->getSequence(), vsyncId.value);
     }
@@ -6933,34 +6961,44 @@
 }
 
 std::shared_ptr<renderengine::ExternalTexture> SurfaceFlinger::getExternalTextureFromBufferData(
-        const BufferData& bufferData, const char* layerName) const {
-    bool cacheIdChanged = bufferData.flags.test(BufferData::BufferDataChange::cachedBufferChanged);
-    bool bufferSizeExceedsLimit = false;
-    std::shared_ptr<renderengine::ExternalTexture> buffer = nullptr;
-    if (cacheIdChanged && bufferData.buffer != nullptr) {
-        bufferSizeExceedsLimit = exceedsMaxRenderTargetSize(bufferData.buffer->getWidth(),
-                                                            bufferData.buffer->getHeight());
-        if (!bufferSizeExceedsLimit) {
-            ClientCache::getInstance().add(bufferData.cachedBuffer, bufferData.buffer);
-            buffer = ClientCache::getInstance().get(bufferData.cachedBuffer);
-        }
-    } else if (cacheIdChanged) {
-        buffer = ClientCache::getInstance().get(bufferData.cachedBuffer);
-    } else if (bufferData.buffer != nullptr) {
-        bufferSizeExceedsLimit = exceedsMaxRenderTargetSize(bufferData.buffer->getWidth(),
-                                                            bufferData.buffer->getHeight());
-        if (!bufferSizeExceedsLimit) {
-            buffer = std::make_shared<
-                    renderengine::impl::ExternalTexture>(bufferData.buffer, getRenderEngine(),
-                                                         renderengine::impl::ExternalTexture::
-                                                                 Usage::READABLE);
-        }
+        BufferData& bufferData, const char* layerName, uint64_t transactionId) {
+    if (bufferData.buffer &&
+        exceedsMaxRenderTargetSize(bufferData.buffer->getWidth(), bufferData.buffer->getHeight())) {
+        ALOGE("Attempted to create an ExternalTexture for layer %s that exceeds render target "
+              "size limit.",
+              layerName);
+        return nullptr;
     }
-    ALOGE_IF(bufferSizeExceedsLimit,
-             "Attempted to create an ExternalTexture for layer %s that exceeds render target size "
-             "limit.",
-             layerName);
-    return buffer;
+
+    bool cachedBufferChanged =
+            bufferData.flags.test(BufferData::BufferDataChange::cachedBufferChanged);
+    if (cachedBufferChanged && bufferData.buffer) {
+        auto result = ClientCache::getInstance().add(bufferData.cachedBuffer, bufferData.buffer);
+        if (result.ok()) {
+            return result.value();
+        }
+
+        if (result.error() == ClientCache::AddError::CacheFull) {
+            mTransactionHandler
+                    .onTransactionQueueStalled(transactionId, bufferData.releaseBufferListener,
+                                               "Buffer processing hung due to full buffer cache");
+        }
+
+        return nullptr;
+    }
+
+    if (cachedBufferChanged) {
+        return ClientCache::getInstance().get(bufferData.cachedBuffer);
+    }
+
+    if (bufferData.buffer) {
+        return std::make_shared<
+                renderengine::impl::ExternalTexture>(bufferData.buffer, getRenderEngine(),
+                                                     renderengine::impl::ExternalTexture::Usage::
+                                                             READABLE);
+    }
+
+    return nullptr;
 }
 
 bool SurfaceFlinger::commitMirrorDisplays(VsyncId vsyncId) {
@@ -7764,7 +7802,7 @@
     IPCThreadState* ipc = IPCThreadState::self();
     const int pid = ipc->getCallingPid();
     const int uid = ipc->getCallingUid();
-    if ((uid != AID_GRAPHICS) &&
+    if ((uid != AID_GRAPHICS) && (uid != AID_SYSTEM) &&
         !PermissionCache::checkPermission(sControlDisplayBrightness, pid, uid)) {
         ALOGE("Permission Denial: can't control brightness pid=%d, uid=%d", pid, uid);
         return PERMISSION_DENIED;
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index d403f47..b65dec4 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -65,6 +65,8 @@
 #include "DisplayIdGenerator.h"
 #include "Effects/Daltonizer.h"
 #include "FlagManager.h"
+#include "FrontEnd/LayerCreationArgs.h"
+#include "FrontEnd/TransactionHandler.h"
 #include "LayerVector.h"
 #include "Scheduler/RefreshRateConfigs.h"
 #include "Scheduler/RefreshRateStats.h"
@@ -75,7 +77,6 @@
 #include "Tracing/LayerTracing.h"
 #include "Tracing/TransactionTracing.h"
 #include "TransactionCallbackInvoker.h"
-#include "TransactionHandler.h"
 #include "TransactionState.h"
 
 #include <atomic>
@@ -312,7 +313,7 @@
             REQUIRES(mStateLock);
 
     virtual std::shared_ptr<renderengine::ExternalTexture> getExternalTextureFromBufferData(
-            const BufferData& bufferData, const char* layerName) const;
+            BufferData& bufferData, const char* layerName, uint64_t transactionId);
 
     // Returns true if any display matches a `bool(const DisplayDevice&)` predicate.
     template <typename Predicate>
@@ -728,7 +729,8 @@
 
     uint32_t setClientStateLocked(const FrameTimelineInfo&, ComposerState&,
                                   int64_t desiredPresentTime, bool isAutoTimestamp,
-                                  int64_t postTime, uint32_t permissions) REQUIRES(mStateLock);
+                                  int64_t postTime, uint32_t permissions, uint64_t transactionId)
+            REQUIRES(mStateLock);
 
     uint32_t getTransactionFlags() const;
 
@@ -755,8 +757,7 @@
     /*
      * Layer management
      */
-    status_t createLayer(LayerCreationArgs& args, const sp<IBinder>& parentHandle,
-                         gui::CreateSurfaceResult& outResult);
+    status_t createLayer(LayerCreationArgs& args, gui::CreateSurfaceResult& outResult);
 
     status_t createBufferStateLayer(LayerCreationArgs& args, sp<IBinder>* outHandle,
                                     sp<Layer>* outLayer);
@@ -777,8 +778,8 @@
     void markLayerPendingRemovalLocked(const sp<Layer>& layer);
 
     // add a layer to SurfaceFlinger
-    status_t addClientLayer(const sp<Client>& client, const sp<IBinder>& handle,
-                            const sp<Layer>& lbc, const wp<Layer>& parentLayer, bool addToRoot,
+    status_t addClientLayer(const LayerCreationArgs& args, const sp<IBinder>& handle,
+                            const sp<Layer>& layer, const wp<Layer>& parentLayer,
                             uint32_t* outTransformHint);
 
     // Traverse through all the layers and compute and cache its bounds.
diff --git a/services/surfaceflinger/SurfaceFlingerFactory.h b/services/surfaceflinger/SurfaceFlingerFactory.h
index d1f21bf..41edd22 100644
--- a/services/surfaceflinger/SurfaceFlingerFactory.h
+++ b/services/surfaceflinger/SurfaceFlingerFactory.h
@@ -44,7 +44,6 @@
 class TimeStats;
 
 struct DisplayDeviceCreationArgs;
-struct LayerCreationArgs;
 
 namespace compositionengine {
 class CompositionEngine;
@@ -62,6 +61,7 @@
 
 namespace surfaceflinger {
 
+struct LayerCreationArgs;
 class NativeWindowSurface;
 
 // The interface that SurfaceFlinger uses to create all of the implementations
diff --git a/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.cpp b/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.cpp
index 276b3da..25fdd26 100644
--- a/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.cpp
+++ b/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.cpp
@@ -100,7 +100,8 @@
     MockSurfaceFlinger(Factory& factory)
           : SurfaceFlinger(factory, SurfaceFlinger::SkipInitialization) {}
     std::shared_ptr<renderengine::ExternalTexture> getExternalTextureFromBufferData(
-            const BufferData& bufferData, const char* /* layerName */) const override {
+            BufferData& bufferData, const char* /* layerName */,
+            uint64_t /* transactionId */) override {
         return std::make_shared<renderengine::mock::FakeExternalTexture>(bufferData.getWidth(),
                                                                          bufferData.getHeight(),
                                                                          bufferData.getId(),
@@ -213,8 +214,8 @@
 
             gui::CreateSurfaceResult outResult;
             LayerCreationArgs args(mFlinger.flinger(), nullptr /* client */, tracingArgs.name,
-                                   tracingArgs.flags, LayerMetadata());
-            args.sequence = std::make_optional<int32_t>(tracingArgs.layerId);
+                                   tracingArgs.flags, LayerMetadata(),
+                                   std::make_optional<int32_t>(tracingArgs.layerId));
 
             if (tracingArgs.mirrorFromId == -1) {
                 sp<IBinder> parentHandle = nullptr;
diff --git a/services/surfaceflinger/Tracing/tools/main.cpp b/services/surfaceflinger/Tracing/tools/main.cpp
index f3cf42d..9f9ae48 100644
--- a/services/surfaceflinger/Tracing/tools/main.cpp
+++ b/services/surfaceflinger/Tracing/tools/main.cpp
@@ -52,6 +52,10 @@
     ;
     ALOGD("Generating %s...", outputLayersTracePath);
     std::cout << "Generating " << outputLayersTracePath << "\n";
+
+    // sink any log spam from the stubbed surfaceflinger
+    __android_log_set_logger([](const struct __android_log_message* /* log_message */) {});
+
     if (!LayerTraceGenerator().generate(transactionTraceFile, outputLayersTracePath)) {
         std::cout << "Error: Failed to generate layers trace " << outputLayersTracePath;
         return -1;
diff --git a/services/surfaceflinger/TransactionCallbackInvoker.h b/services/surfaceflinger/TransactionCallbackInvoker.h
index 23ea7a5..61ff9bc 100644
--- a/services/surfaceflinger/TransactionCallbackInvoker.h
+++ b/services/surfaceflinger/TransactionCallbackInvoker.h
@@ -19,6 +19,7 @@
 #include <condition_variable>
 #include <deque>
 #include <mutex>
+#include <optional>
 #include <queue>
 #include <thread>
 #include <unordered_map>
@@ -48,7 +49,7 @@
     std::vector<ftl::SharedFuture<FenceResult>> previousReleaseFences;
     std::variant<nsecs_t, sp<Fence>> acquireTimeOrFence = -1;
     nsecs_t latchTime = -1;
-    uint32_t transformHint = 0;
+    std::optional<uint32_t> transformHint = std::nullopt;
     uint32_t currentMaxAcquiredBufferCount = 0;
     std::shared_ptr<FenceTime> gpuCompositionDoneFence{FenceTime::NO_FENCE};
     CompositorTiming compositorTiming;
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_UpdateLayerMetadataSnapshotTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_UpdateLayerMetadataSnapshotTest.cpp
index 0cf3bdf..fed6a1a 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_UpdateLayerMetadataSnapshotTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_UpdateLayerMetadataSnapshotTest.cpp
@@ -44,9 +44,11 @@
                                 std::move(eventThread), std::move(sfEventThread));
     }
 
-    sp<Layer> createLayer(const char* name, LayerMetadata layerMetadata) {
-        return sp<Layer>::make(
-                LayerCreationArgs{mFlinger.flinger(), nullptr, name, 0, layerMetadata});
+    sp<Layer> createLayer(const char* name, LayerMetadata& inOutlayerMetadata) {
+        LayerCreationArgs args =
+                LayerCreationArgs{mFlinger.flinger(), nullptr, name, 0, inOutlayerMetadata};
+        inOutlayerMetadata = args.metadata;
+        return sp<Layer>::make(args);
     }
 
     TestableSurfaceFlinger mFlinger;
@@ -90,7 +92,7 @@
 
     mFlinger.updateLayerMetadataSnapshot();
 
-    ASSERT_EQ(layer->getLayerSnapshot()->layerMetadata, layerMetadata);
+    EXPECT_EQ(layer->getLayerSnapshot()->layerMetadata, layerMetadata);
 }
 
 // Test that snapshot layer metadata is set by merging the child's metadata on top of its
@@ -109,10 +111,10 @@
 
     mFlinger.updateLayerMetadataSnapshot();
 
-    ASSERT_EQ(layerA->getLayerSnapshot()->layerMetadata, layerAMetadata);
+    EXPECT_EQ(layerA->getLayerSnapshot()->layerMetadata, layerAMetadata);
     auto expectedChildMetadata =
             LayerMetadataBuilder(layerAMetadata).setInt32(METADATA_TASK_ID, 3).build();
-    ASSERT_EQ(layerB->getLayerSnapshot()->layerMetadata, expectedChildMetadata);
+    EXPECT_EQ(layerB->getLayerSnapshot()->layerMetadata, expectedChildMetadata);
 }
 
 // Test that snapshot relative layer metadata is set to the parent's layer metadata merged on top of
@@ -129,8 +131,8 @@
 
     mFlinger.updateLayerMetadataSnapshot();
 
-    ASSERT_EQ(layerA->getLayerSnapshot()->relativeLayerMetadata, LayerMetadata{});
-    ASSERT_EQ(layerB->getLayerSnapshot()->relativeLayerMetadata, layerAMetadata);
+    EXPECT_EQ(layerA->getLayerSnapshot()->relativeLayerMetadata, LayerMetadata{});
+    EXPECT_EQ(layerB->getLayerSnapshot()->relativeLayerMetadata, layerAMetadata);
 }
 
 // Test that snapshot relative layer metadata is set correctly when a layer is interleaved within
@@ -154,7 +156,8 @@
                                   .build();
     auto layerB = createLayer("layer-b", layerBMetadata);
     auto layerBHandle = layerB->getHandle();
-    auto layerC = createLayer("layer-c", {});
+    LayerMetadata layerCMetadata;
+    auto layerC = createLayer("layer-c", layerCMetadata);
     auto layerDMetadata = LayerMetadataBuilder().setInt32(METADATA_TASK_ID, 4).build();
     auto layerD = createLayer("layer-d", layerDMetadata);
     auto layerDHandle = layerD->getHandle();
@@ -168,14 +171,18 @@
 
     mFlinger.updateLayerMetadataSnapshot();
 
-    auto expectedLayerDRelativeMetadata = LayerMetadataBuilder()
-                                                  // From layer A, parent of relative parent
-                                                  .setInt32(METADATA_OWNER_UID, 1)
-                                                  // From layer B, relative parent
-                                                  .setInt32(METADATA_TASK_ID, 2)
-                                                  .setInt32(METADATA_OWNER_PID, 3)
-                                                  .build();
-    ASSERT_EQ(layerD->getLayerSnapshot()->relativeLayerMetadata, expectedLayerDRelativeMetadata);
+    auto expectedLayerDRelativeMetadata =
+            LayerMetadataBuilder()
+                    // From layer A, parent of relative parent
+                    .setInt32(METADATA_OWNER_UID, 1)
+                    // From layer B, relative parent
+                    .setInt32(METADATA_TASK_ID, 2)
+                    .setInt32(METADATA_OWNER_PID, 3)
+                    // added by layer creation args
+                    .setInt32(gui::METADATA_CALLING_UID,
+                              layerDMetadata.getInt32(gui::METADATA_CALLING_UID, 0))
+                    .build();
+    EXPECT_EQ(layerD->getLayerSnapshot()->relativeLayerMetadata, expectedLayerDRelativeMetadata);
     auto expectedLayerCRelativeMetadata =
             LayerMetadataBuilder()
                     // From layer A, parent of relative parent
@@ -184,8 +191,11 @@
                     .setInt32(METADATA_OWNER_PID, 3)
                     // From layer D, relative parent
                     .setInt32(METADATA_TASK_ID, 4)
+                    // added by layer creation args
+                    .setInt32(gui::METADATA_CALLING_UID,
+                              layerDMetadata.getInt32(gui::METADATA_CALLING_UID, 0))
                     .build();
-    ASSERT_EQ(layerC->getLayerSnapshot()->relativeLayerMetadata, expectedLayerCRelativeMetadata);
+    EXPECT_EQ(layerC->getLayerSnapshot()->relativeLayerMetadata, expectedLayerCRelativeMetadata);
 }
 
 TEST_F(SurfaceFlingerUpdateLayerMetadataSnapshotTest,
@@ -193,8 +203,10 @@
     auto layerAMetadata = LayerMetadataBuilder().setInt32(METADATA_OWNER_UID, 1).build();
     auto layerA = createLayer("layer-a", layerAMetadata);
     auto layerAHandle = layerA->getHandle();
-    auto layerB = createLayer("layer-b", {});
-    auto layerC = createLayer("layer-c", {});
+    LayerMetadata layerBMetadata;
+    auto layerB = createLayer("layer-b", layerBMetadata);
+    LayerMetadata layerCMetadata;
+    auto layerC = createLayer("layer-c", layerCMetadata);
     layerB->setRelativeLayer(layerAHandle, 1);
     layerC->setRelativeLayer(layerAHandle, 2);
     layerA->commitChildList();
@@ -204,9 +216,9 @@
 
     mFlinger.updateLayerMetadataSnapshot();
 
-    ASSERT_EQ(layerA->getLayerSnapshot()->relativeLayerMetadata, LayerMetadata{});
-    ASSERT_EQ(layerB->getLayerSnapshot()->relativeLayerMetadata, layerAMetadata);
-    ASSERT_EQ(layerC->getLayerSnapshot()->relativeLayerMetadata, layerAMetadata);
+    EXPECT_EQ(layerA->getLayerSnapshot()->relativeLayerMetadata, LayerMetadata{});
+    EXPECT_EQ(layerB->getLayerSnapshot()->relativeLayerMetadata, layerAMetadata);
+    EXPECT_EQ(layerC->getLayerSnapshot()->relativeLayerMetadata, layerAMetadata);
 }
 
 } // namespace android
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index c72fb76..89812aa 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -33,6 +33,7 @@
 #include "DisplayDevice.h"
 #include "FakeVsyncConfiguration.h"
 #include "FrameTracer/FrameTracer.h"
+#include "FrontEnd/LayerCreationArgs.h"
 #include "Layer.h"
 #include "NativeWindowSurface.h"
 #include "Scheduler/MessageQueue.h"
@@ -470,7 +471,8 @@
 
     auto createLayer(LayerCreationArgs& args, const sp<IBinder>& parentHandle,
                      gui::CreateSurfaceResult& outResult) {
-        return mFlinger->createLayer(args, parentHandle, outResult);
+        args.parentHandle = parentHandle;
+        return mFlinger->createLayer(args, outResult);
     }
 
     auto mirrorLayer(const LayerCreationArgs& args, const sp<IBinder>& mirrorFromHandle,
diff --git a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
index db438b7..de84faa 100644
--- a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
@@ -30,8 +30,8 @@
 #include <vector>
 #include <binder/Binder.h>
 
+#include "FrontEnd/TransactionHandler.h"
 #include "TestableSurfaceFlinger.h"
-#include "TransactionHandler.h"
 #include "mock/MockEventThread.h"
 #include "mock/MockVsyncController.h"