Merge "[SfStats] Temporarily enable timestats by default."
diff --git a/cmds/atrace/Android.bp b/cmds/atrace/Android.bp
index cc2a6f7..e7d0ad0 100644
--- a/cmds/atrace/Android.bp
+++ b/cmds/atrace/Android.bp
@@ -10,9 +10,7 @@
 
     shared_libs: [
         "libbinder",
-        "libhwbinder",
         "libhidlbase",
-        "libhidltransport",
         "liblog",
         "libutils",
         "libcutils",
diff --git a/cmds/dumpstate/Android.bp b/cmds/dumpstate/Android.bp
index 93bbe90..09aee89 100644
--- a/cmds/dumpstate/Android.bp
+++ b/cmds/dumpstate/Android.bp
@@ -88,7 +88,6 @@
         "libdumputils",
         "libhardware_legacy",
         "libhidlbase",
-        "libhidltransport",
         "liblog",
         "libutils",
     ],
@@ -119,6 +118,8 @@
         "kill",
         "librank",
         "logcat",
+        "lpdump",
+        "lpdumpd",
         "lsmod",
         "lsof",
         "netstat",
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index b781da3..3f2469c 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -929,6 +929,14 @@
     RunCommand("IP6TABLES RAW", {"ip6tables", "-t", "raw", "-L", "-nvx"});
 }
 
+static void DumpDynamicPartitionInfo() {
+    if (!::android::base::GetBoolProperty("ro.boot.dynamic_partitions", false)) {
+        return;
+    }
+
+    RunCommand("LPDUMP", {"lpdump", "--all"});
+}
+
 static void AddAnrTraceDir(const bool add_to_zip, const std::string& anr_traces_dir) {
     MYLOGD("AddAnrTraceDir(): dump_traces_file=%s, anr_traces_dir=%s\n", dump_traces_path,
            anr_traces_dir.c_str());
@@ -1515,6 +1523,7 @@
     }
     add_mountinfo();
     DumpIpTablesAsRoot();
+    DumpDynamicPartitionInfo();
 
     // Capture any IPSec policies in play. No keys are exposed here.
     RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"}, CommandOptions::WithTimeout(10).Build());
diff --git a/cmds/lshal/Android.bp b/cmds/lshal/Android.bp
index f8b8c68..5afae4b 100644
--- a/cmds/lshal/Android.bp
+++ b/cmds/lshal/Android.bp
@@ -19,7 +19,6 @@
         "libcutils",
         "libutils",
         "libhidlbase",
-        "libhidltransport",
         "libhidl-gen-hash",
         "libhidl-gen-utils",
         "libvintf",
@@ -51,7 +50,6 @@
         "libcutils",
         "libutils",
         "libhidlbase",
-        "libhidltransport",
         "libhidl-gen-hash",
         "libhidl-gen-utils",
         "libvintf",
@@ -81,9 +79,7 @@
         "libgmock",
     ],
     shared_libs: [
-        "libhwbinder",
         "libhidlbase",
-        "libhidltransport",
         "libvintf",
     ],
     srcs: [
diff --git a/cmds/lshal/test.cpp b/cmds/lshal/test.cpp
index 76f7c7f..3d550ba 100644
--- a/cmds/lshal/test.cpp
+++ b/cmds/lshal/test.cpp
@@ -452,7 +452,7 @@
 }
 
 TEST_F(ListTest, DumpVintf) {
-    const std::string expected = "<manifest version=\"1.0\" type=\"device\">\n"
+    const std::string expected = "<manifest version=\"2.0\" type=\"device\">\n"
                                  "    <hal format=\"hidl\">\n"
                                  "        <name>a.h.foo1</name>\n"
                                  "        <transport>hwbinder</transport>\n"
diff --git a/cmds/servicemanager/ServiceManager.cpp b/cmds/servicemanager/ServiceManager.cpp
index b3aa342..463d67f 100644
--- a/cmds/servicemanager/ServiceManager.cpp
+++ b/cmds/servicemanager/ServiceManager.cpp
@@ -17,8 +17,10 @@
 #include "ServiceManager.h"
 
 #include <android-base/logging.h>
+#include <android-base/properties.h>
 #include <cutils/android_filesystem_config.h>
 #include <cutils/multiuser.h>
+#include <thread>
 
 using ::android::binder::Status;
 
@@ -41,39 +43,44 @@
 }
 
 Status ServiceManager::getService(const std::string& name, sp<IBinder>* outBinder) {
-    // Servicemanager is single-threaded and cannot block. This method exists for legacy reasons.
-    return checkService(name, outBinder);
+    *outBinder = tryGetService(name, true);
+    // returns ok regardless of result for legacy reasons
+    return Status::ok();
 }
 
 Status ServiceManager::checkService(const std::string& name, sp<IBinder>* outBinder) {
+    *outBinder = tryGetService(name, false);
+    // returns ok regardless of result for legacy reasons
+    return Status::ok();
+}
+
+sp<IBinder> ServiceManager::tryGetService(const std::string& name, bool startIfNotFound) {
     auto ctx = mAccess->getCallingContext();
 
-    auto it = mNameToService.find(name);
-    if (it == mNameToService.end()) {
-        *outBinder = nullptr;
-        return Status::ok();
-    }
+    sp<IBinder> out;
+    if (auto it = mNameToService.find(name); it != mNameToService.end()) {
+        const Service& service = it->second;
 
-    const Service& service = it->second;
+        if (!service.allowIsolated) {
+            uid_t appid = multiuser_get_app_id(ctx.uid);
+            bool isIsolated = appid >= AID_ISOLATED_START && appid <= AID_ISOLATED_END;
 
-    if (!service.allowIsolated) {
-        uid_t appid = multiuser_get_app_id(ctx.uid);
-        bool isIsolated = appid >= AID_ISOLATED_START && appid <= AID_ISOLATED_END;
-
-        if (isIsolated) {
-            *outBinder = nullptr;
-            return Status::ok();
+            if (isIsolated) {
+                return nullptr;
+            }
         }
+        out = service.binder;
     }
 
     if (!mAccess->canFind(ctx, name)) {
-        // returns ok and null for legacy reasons
-        *outBinder = nullptr;
-        return Status::ok();
+        return nullptr;
     }
 
-    *outBinder = service.binder;
-    return Status::ok();
+    if (!out && startIfNotFound) {
+        tryStartService(name);
+    }
+
+    return out;
 }
 
 bool isValidServiceName(const std::string& name) {
@@ -253,4 +260,13 @@
     }
 }
 
+void ServiceManager::tryStartService(const std::string& name) {
+    ALOGI("Since '%s' could not be found, trying to start it as a lazy AIDL service",
+          name.c_str());
+
+    std::thread([=] {
+        (void)base::SetProperty("ctl.interface_start", "aidl/" + name);
+    }).detach();
+}
+
 }  // namespace android
diff --git a/cmds/servicemanager/ServiceManager.h b/cmds/servicemanager/ServiceManager.h
index fcc5124..006e519 100644
--- a/cmds/servicemanager/ServiceManager.h
+++ b/cmds/servicemanager/ServiceManager.h
@@ -30,6 +30,7 @@
     ServiceManager(std::unique_ptr<Access>&& access);
     ~ServiceManager();
 
+    // getService will try to start any services it cannot find
     binder::Status getService(const std::string& name, sp<IBinder>* outBinder) override;
     binder::Status checkService(const std::string& name, sp<IBinder>* outBinder) override;
     binder::Status addService(const std::string& name, const sp<IBinder>& binder,
@@ -42,6 +43,9 @@
 
     void binderDied(const wp<IBinder>& who) override;
 
+protected:
+    virtual void tryStartService(const std::string& name);
+
 private:
     struct Service {
         sp<IBinder> binder; // not null
@@ -57,6 +61,7 @@
     void removeCallback(const wp<IBinder>& who,
                         CallbackMap::iterator* it,
                         bool* found);
+    sp<IBinder> tryGetService(const std::string& name, bool startIfNotFound);
 
     CallbackMap mNameToCallback;
     ServiceMap mNameToService;
diff --git a/cmds/servicemanager/main.cpp b/cmds/servicemanager/main.cpp
index 9f6193b..11d43a6 100644
--- a/cmds/servicemanager/main.cpp
+++ b/cmds/servicemanager/main.cpp
@@ -36,8 +36,6 @@
 
     const char* driver = argc == 2 ? argv[1] : "/dev/binder";
 
-    android::base::InitLogging(nullptr, &android::base::KernelLogger);
-
     sp<ProcessState> ps = ProcessState::initWithDriver(driver);
     ps->setThreadPoolMaxThreadCount(0);
     ps->setCallRestriction(ProcessState::CallRestriction::FATAL_IF_NOT_ONEWAY);
diff --git a/cmds/servicemanager/test_sm.cpp b/cmds/servicemanager/test_sm.cpp
index 3c211d2..25245be 100644
--- a/cmds/servicemanager/test_sm.cpp
+++ b/cmds/servicemanager/test_sm.cpp
@@ -57,6 +57,12 @@
     MOCK_METHOD1(canList, bool(const CallingContext&));
 };
 
+class MockServiceManager : public ServiceManager {
+ public:
+    MockServiceManager(std::unique_ptr<Access>&& access) : ServiceManager(std::move(access)) {}
+    MOCK_METHOD1(tryStartService, void(const std::string& name));
+};
+
 static sp<ServiceManager> getPermissiveServiceManager() {
     std::unique_ptr<MockAccess> access = std::make_unique<NiceMock<MockAccess>>();
 
@@ -65,7 +71,7 @@
     ON_CALL(*access, canFind(_, _)).WillByDefault(Return(true));
     ON_CALL(*access, canList(_)).WillByDefault(Return(true));
 
-    sp<ServiceManager> sm = new ServiceManager(std::move(access));
+    sp<ServiceManager> sm = new NiceMock<MockServiceManager>(std::move(access));
     return sm;
 }
 
@@ -113,7 +119,7 @@
             .uid = uid,
         }));
         EXPECT_CALL(*access, canAdd(_, _)).Times(0);
-        sp<ServiceManager> sm = new ServiceManager(std::move(access));
+        sp<ServiceManager> sm = new NiceMock<MockServiceManager>(std::move(access));
 
         EXPECT_FALSE(sm->addService("foo", getBinder(), false /*allowIsolated*/,
             IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
@@ -135,7 +141,7 @@
     EXPECT_CALL(*access, getCallingContext()).WillOnce(Return(Access::CallingContext{}));
     EXPECT_CALL(*access, canAdd(_, _)).WillOnce(Return(false));
 
-    sp<ServiceManager> sm = new ServiceManager(std::move(access));
+    sp<ServiceManager> sm = new NiceMock<MockServiceManager>(std::move(access));
 
     EXPECT_FALSE(sm->addService("foo", getBinder(), false /*allowIsolated*/,
         IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
@@ -168,7 +174,7 @@
     EXPECT_CALL(*access, canAdd(_, _)).WillOnce(Return(true));
     EXPECT_CALL(*access, canFind(_, _)).WillOnce(Return(false));
 
-    sp<ServiceManager> sm = new ServiceManager(std::move(access));
+    sp<ServiceManager> sm = new NiceMock<MockServiceManager>(std::move(access));
 
     EXPECT_TRUE(sm->addService("foo", getBinder(), false /*allowIsolated*/,
         IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
@@ -192,7 +198,7 @@
     EXPECT_CALL(*access, canAdd(_, _)).WillOnce(Return(true));
     EXPECT_CALL(*access, canFind(_, _)).WillOnce(Return(true));
 
-    sp<ServiceManager> sm = new ServiceManager(std::move(access));
+    sp<ServiceManager> sm = new NiceMock<MockServiceManager>(std::move(access));
 
     sp<IBinder> service = getBinder();
     EXPECT_TRUE(sm->addService("foo", service, true /*allowIsolated*/,
@@ -218,7 +224,7 @@
     // TODO(b/136023468): when security check is first, this should be called first
     // EXPECT_CALL(*access, canFind(_, _)).WillOnce(Return(true));
 
-    sp<ServiceManager> sm = new ServiceManager(std::move(access));
+    sp<ServiceManager> sm = new NiceMock<MockServiceManager>(std::move(access));
 
     EXPECT_TRUE(sm->addService("foo", getBinder(), false /*allowIsolated*/,
         IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
@@ -235,7 +241,7 @@
     EXPECT_CALL(*access, getCallingContext()).WillOnce(Return(Access::CallingContext{}));
     EXPECT_CALL(*access, canList(_)).WillOnce(Return(false));
 
-    sp<ServiceManager> sm = new ServiceManager(std::move(access));
+    sp<ServiceManager> sm = new NiceMock<MockServiceManager>(std::move(access));
 
     std::vector<std::string> out;
     EXPECT_FALSE(sm->listServices(IServiceManager::DUMP_FLAG_PRIORITY_ALL, &out).isOk());
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index 6ece4a2..86f19c5 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -86,8 +86,10 @@
         vendor: {
             exclude_srcs: [
                 "ActivityManager.cpp",
+                "AppOpsManager.cpp",
                 "IActivityManager.cpp",
                 "IAppOpsCallback.cpp",
+                "IAppOpsService.cpp",
                 "IBatteryStats.cpp",
                 "IMediaResourceMonitor.cpp",
                 "IPermissionController.cpp",
diff --git a/libs/binder/AppOpsManager.cpp b/libs/binder/AppOpsManager.cpp
index e2af01c..711fed9 100644
--- a/libs/binder/AppOpsManager.cpp
+++ b/libs/binder/AppOpsManager.cpp
@@ -32,7 +32,6 @@
 
 namespace {
 
-#ifndef __ANDROID_VNDK__
 #if defined(__BRILLO__)
 // Because Brillo has no application model, security policy is managed
 // statically (at build time) with SELinux controls.
@@ -41,17 +40,13 @@
 #else
 const int APP_OPS_MANAGER_UNAVAILABLE_MODE = AppOpsManager::MODE_IGNORED;
 #endif  // defined(__BRILLO__)
-#endif // __ANDROID_VNDK__
 
 }  // namespace
 
 static String16 _appops("appops");
-#ifndef __ANDROID_VNDK__
 static pthread_mutex_t gTokenMutex = PTHREAD_MUTEX_INITIALIZER;
-#endif // __ANDROID_VNDK__
 static sp<IBinder> gToken;
 
-#ifndef __ANDROID_VNDK__
 static const sp<IBinder>& getToken(const sp<IAppOpsService>& service) {
     pthread_mutex_lock(&gTokenMutex);
     if (gToken == nullptr || gToken->pingBinder() != NO_ERROR) {
@@ -60,17 +55,12 @@
     pthread_mutex_unlock(&gTokenMutex);
     return gToken;
 }
-#endif // __ANDROID_VNDK__
 
 thread_local uint64_t notedAppOpsInThisBinderTransaction[2];
 thread_local int32_t uidOfThisBinderTransaction = -1;
 
 // Whether an appop should be collected: 0 == not initialized, 1 == don't note, 2 == note
-#ifndef __ANDROID_VNDK__
 uint8_t appOpsToNote[AppOpsManager::_NUM_OP] = {0};
-#else
-uint8_t appOpsToNote[128] = {0};
-#endif // __ANDROID_VNDK__
 
 AppOpsManager::AppOpsManager()
 {
@@ -108,7 +98,6 @@
 }
 #endif  // defined(__BRILLO__)
 
-#ifndef __ANDROID_VNDK__
 int32_t AppOpsManager::checkOp(int32_t op, int32_t uid, const String16& callingPackage)
 {
     sp<IAppOpsService> service = getService();
@@ -200,8 +189,6 @@
     }
 }
 
-#endif // __ANDROID_VNDK__
-
 bool AppOpsManager::shouldCollectNotes(int32_t opcode) {
     sp<IAppOpsService> service = getService();
     if (service != nullptr) {
diff --git a/libs/binder/IAppOpsService.cpp b/libs/binder/IAppOpsService.cpp
index b6360cb..c58ea02 100644
--- a/libs/binder/IAppOpsService.cpp
+++ b/libs/binder/IAppOpsService.cpp
@@ -34,7 +34,6 @@
     {
     }
 
-#ifndef __ANDROID_VNDK__
     virtual int32_t checkOperation(int32_t code, int32_t uid, const String16& packageName) {
         Parcel data, reply;
         data.writeInterfaceToken(IAppOpsService::getInterfaceDescriptor());
@@ -145,7 +144,6 @@
         remote()->transact(SET_CAMERA_AUDIO_RESTRICTION_TRANSACTION, data, &reply);
     }
 
-#endif
     virtual void noteAsyncOp(const String16& callingPackageName, int32_t uid,
             const String16& packageName, int32_t opCode, const String16& message) {
         Parcel data, reply;
@@ -195,7 +193,6 @@
 {
     //printf("AppOpsService received: "); data.print();
     switch(code) {
-#ifndef __ANDROID_VNDK__
         case CHECK_OPERATION_TRANSACTION: {
             CHECK_INTERFACE(IAppOpsService, data, reply);
             int32_t code = data.readInt32();
@@ -288,7 +285,6 @@
             reply->writeNoException();
             return NO_ERROR;
         } break;
-#endif // __ANDROID_VNDK__
         case NOTE_ASYNC_OP_TRANSACTION: {
             CHECK_INTERFACE(IAppOpsService, data, reply);
             String16 callingPackageName = data.readString16();
diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp
index 715a460..eefc5b1 100644
--- a/libs/binder/IServiceManager.cpp
+++ b/libs/binder/IServiceManager.cpp
@@ -232,7 +232,7 @@
         const std::string name = String8(name16).c_str();
 
         sp<IBinder> out;
-        if(!mTheRealServiceManager->checkService(name, &out).isOk()) {
+        if (!mTheRealServiceManager->getService(name, &out).isOk()) {
             return nullptr;
         }
         if(out != nullptr) return out;
@@ -256,13 +256,13 @@
             // Handle race condition for lazy services. Here is what can happen:
             // - the service dies (not processed by init yet).
             // - sm processes death notification.
-            // - sm gets checkService and calls init to start service.
+            // - sm gets getService and calls init to start service.
             // - init gets the start signal, but the service already appears
             //   started, so it does nothing.
             // - init gets death signal, but doesn't know it needs to restart
             //   the service
             // - we need to request service again to get it to start
-            if(!mTheRealServiceManager->checkService(name, &out).isOk()) {
+            if (!mTheRealServiceManager->getService(name, &out).isOk()) {
                 return nullptr;
             }
             if(out != nullptr) return out;
diff --git a/libs/binder/IpPrefix.cpp b/libs/binder/IpPrefix.cpp
index 3a8a63c..8d62266 100644
--- a/libs/binder/IpPrefix.cpp
+++ b/libs/binder/IpPrefix.cpp
@@ -30,7 +30,6 @@
 using android::Parcel;
 using android::status_t;
 using android::UNEXPECTED_NULL;
-using namespace ::android::binder;
 
 namespace android {
 
diff --git a/libs/binder/include/binder/AppOpsManager.h b/libs/binder/include/binder/AppOpsManager.h
index dff4d49..f5a54ce 100644
--- a/libs/binder/include/binder/AppOpsManager.h
+++ b/libs/binder/include/binder/AppOpsManager.h
@@ -21,6 +21,10 @@
 
 #include <utils/threads.h>
 
+#ifdef __ANDROID_VNDK__
+#error "This header is not visible to vendors"
+#endif
+
 // ---------------------------------------------------------------------------
 namespace android {
 
@@ -33,7 +37,6 @@
         MODE_ERRORED = IAppOpsService::MODE_ERRORED
     };
 
-#ifndef __ANDROID_VNDK__
     enum {
         OP_NONE = -1,
         OP_COARSE_LOCATION = 0,
@@ -121,11 +124,9 @@
         OP_READ_DEVICE_IDENTIFIERS = 89,
         _NUM_OP = 90
     };
-#endif // __ANDROID_VNDK__
 
     AppOpsManager();
 
-#ifndef __ANDROID_VNDK__
     int32_t checkOp(int32_t op, int32_t uid, const String16& callingPackage);
     int32_t checkAudioOpNoThrow(int32_t op, int32_t usage, int32_t uid,
             const String16& callingPackage);
@@ -145,7 +146,6 @@
     void stopWatchingMode(const sp<IAppOpsCallback>& callback);
     int32_t permissionToOpCode(const String16& permission);
     void setCameraAudioRestriction(int32_t mode);
-#endif // __ANDROID_VNDK__
     void noteAsyncOp(const String16& callingPackageName, int32_t uid, const String16& packageName,
             int32_t opCode, const String16& message);
 
diff --git a/libs/binder/include/binder/IAppOpsService.h b/libs/binder/include/binder/IAppOpsService.h
index 009ef6c..9784003 100644
--- a/libs/binder/include/binder/IAppOpsService.h
+++ b/libs/binder/include/binder/IAppOpsService.h
@@ -18,11 +18,13 @@
 #ifndef ANDROID_IAPP_OPS_SERVICE_H
 #define ANDROID_IAPP_OPS_SERVICE_H
 
-#ifndef __ANDROID_VNDK__
 #include <binder/IAppOpsCallback.h>
-#endif
 #include <binder/IInterface.h>
 
+#ifdef __ANDROID_VNDK__
+#error "This header is not visible to vendors"
+#endif
+
 namespace android {
 
 // ----------------------------------------------------------------------
@@ -32,7 +34,6 @@
 public:
     DECLARE_META_INTERFACE(AppOpsService)
 
-#ifndef __ANDROID_VNDK__
     virtual int32_t checkOperation(int32_t code, int32_t uid, const String16& packageName) = 0;
     virtual int32_t noteOperation(int32_t code, int32_t uid, const String16& packageName) = 0;
     virtual int32_t startOperation(const sp<IBinder>& token, int32_t code, int32_t uid,
@@ -47,13 +48,11 @@
     virtual int32_t checkAudioOperation(int32_t code, int32_t usage,int32_t uid,
             const String16& packageName) = 0;
     virtual void setCameraAudioRestriction(int32_t mode) = 0;
-#endif // __ANDROID_VNDK__
     virtual void noteAsyncOp(const String16& callingPackageName, int32_t uid,
             const String16& packageName, int32_t opCode, const String16& message) = 0;
     virtual bool shouldCollectNotes(int32_t opCode) = 0;
 
     enum {
-#ifndef __ANDROID_VNDK__
         CHECK_OPERATION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION,
         NOTE_OPERATION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+1,
         START_OPERATION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+2,
@@ -63,13 +62,9 @@
         GET_TOKEN_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+6,
         PERMISSION_TO_OP_CODE_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+7,
         CHECK_AUDIO_OPERATION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+8,
-#endif // __ANDROID_VNDK__
         NOTE_ASYNC_OP_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+9,
         SHOULD_COLLECT_NOTES_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+10,
-#ifndef __ANDROID_VNDK__
         SET_CAMERA_AUDIO_RESTRICTION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+11,
-#endif // __ANDROID_VNDK__
-
     };
 
     enum {
diff --git a/libs/binder/include/binder/Parcel.h b/libs/binder/include/binder/Parcel.h
index f5aafc7..b1b8ff1 100644
--- a/libs/binder/include/binder/Parcel.h
+++ b/libs/binder/include/binder/Parcel.h
@@ -21,8 +21,6 @@
 #include <string>
 #include <vector>
 
-#include <linux/android/binder.h>
-
 #include <android-base/unique_fd.h>
 #include <cutils/native_handle.h>
 #include <utils/Errors.h>
@@ -34,21 +32,25 @@
 #include <binder/IInterface.h>
 #include <binder/Parcelable.h>
 
+#ifdef BINDER_IPC_32BIT
+typedef __u32 binder_size_t;
+#else
+typedef __u64 binder_size_t;
+#endif
+
+
 // ---------------------------------------------------------------------------
 namespace android {
 
 template <typename T> class Flattenable;
 template <typename T> class LightFlattenable;
+struct flat_binder_object;
 class IBinder;
 class IPCThreadState;
 class ProcessState;
 class String8;
 class TextOutput;
 
-namespace binder {
-class Value;
-};
-
 class Parcel {
     friend class IPCThreadState;
 public:
@@ -382,7 +384,6 @@
     // Returns the work source provided by the caller. This can only be trusted for trusted calling
     // uid.
     uid_t               readCallingWorkSourceUid() const;
-    void                readRequestHeaders() const;
 
 private:
     typedef void        (*release_func)(Parcel* parcel,
diff --git a/libs/binder/tests/binderLibTest.cpp b/libs/binder/tests/binderLibTest.cpp
index 5c6cf9d..db4a36b 100644
--- a/libs/binder/tests/binderLibTest.cpp
+++ b/libs/binder/tests/binderLibTest.cpp
@@ -28,6 +28,7 @@
 #include <binder/IPCThreadState.h>
 #include <binder/IServiceManager.h>
 
+#include <private/binder/binder_module.h>
 #include <sys/epoll.h>
 
 #define ARRAY_SIZE(array) (sizeof array / sizeof array[0])
diff --git a/libs/dumputils/Android.bp b/libs/dumputils/Android.bp
index e23de8e..e403d36 100644
--- a/libs/dumputils/Android.bp
+++ b/libs/dumputils/Android.bp
@@ -18,7 +18,6 @@
     shared_libs: [
         "libbase",
         "libhidlbase",
-        "libhidltransport",
         "liblog",
         "libutils",
     ],
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index beb13ad..3f8b436 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -170,8 +170,6 @@
         "libEGL",
         "libGLESv2",
         "libhidlbase",
-        "libhidltransport",
-        "libhwbinder",
         "liblog",
         "libnativewindow",
         "libsync",
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index be58b85..523ed1d 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -291,9 +291,6 @@
         what |= eOverrideScalingModeChanged;
         overrideScalingMode = other.overrideScalingMode;
     }
-    if (other.what & eGeometryAppliesWithResize) {
-        what |= eGeometryAppliesWithResize;
-    }
     if (other.what & eReparentChildren) {
         what |= eReparentChildren;
         reparentHandle = other.reparentHandle;
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index 7e356e4..aad1849 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -1081,6 +1081,9 @@
     case NATIVE_WINDOW_SET_AUTO_PREROTATION:
         res = dispatchSetAutoPrerotation(args);
         break;
+    case NATIVE_WINDOW_GET_LAST_DEQUEUE_START:
+        res = dispatchGetLastDequeueStartTime(args);
+        break;
     default:
         res = NAME_NOT_FOUND;
         break;
@@ -1286,6 +1289,12 @@
     return setAutoPrerotation(autoPrerotation);
 }
 
+int Surface::dispatchGetLastDequeueStartTime(va_list args) {
+    int64_t* lastDequeueStartTime = va_arg(args, int64_t*);
+    *lastDequeueStartTime = mLastDequeueStartTime;
+    return NO_ERROR;
+}
+
 bool Surface::transformToDisplayInverse() {
     return (mTransform & NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY) ==
             NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY;
@@ -1950,11 +1959,6 @@
     return mGraphicBufferProducer->getConsumerUsage(outUsage);
 }
 
-nsecs_t Surface::getLastDequeueStartTime() const {
-    Mutex::Autolock lock(mMutex);
-    return mLastDequeueStartTime;
-}
-
 status_t Surface::getAndFlushRemovedBuffers(std::vector<sp<GraphicBuffer>>* out) {
     if (out == nullptr) {
         ALOGE("%s: out must not be null!", __FUNCTION__);
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 5faf010..67dd726 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -1187,19 +1187,6 @@
     return *this;
 }
 
-SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setGeometryAppliesWithResize(
-        const sp<SurfaceControl>& sc) {
-    layer_state_t* s = getLayerState(sc);
-    if (!s) {
-        mStatus = BAD_INDEX;
-        return *this;
-    }
-    s->what |= layer_state_t::eGeometryAppliesWithResize;
-
-    registerSurfaceControlForCallback(sc);
-    return *this;
-}
-
 #ifndef NO_INPUT
 SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setInputWindowInfo(
         const sp<SurfaceControl>& sc,
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index cbd1c85..2eb5492 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -71,7 +71,7 @@
         eCropChanged_legacy = 0x00000100,
         eDeferTransaction_legacy = 0x00000200,
         eOverrideScalingModeChanged = 0x00000400,
-        eGeometryAppliesWithResize = 0x00000800,
+        // AVAILABLE 0x00000800,
         eReparentChildren = 0x00001000,
         eDetachChildren = 0x00002000,
         eRelativeLayerChanged = 0x00004000,
diff --git a/libs/gui/include/gui/Surface.h b/libs/gui/include/gui/Surface.h
index 28f5a26..5bcfcda 100644
--- a/libs/gui/include/gui/Surface.h
+++ b/libs/gui/include/gui/Surface.h
@@ -179,9 +179,6 @@
     status_t getUniqueId(uint64_t* outId) const;
     status_t getConsumerUsage(uint64_t* outUsage) const;
 
-    // Returns the CLOCK_MONOTONIC start time of the last dequeueBuffer call
-    nsecs_t getLastDequeueStartTime() const;
-
 protected:
     virtual ~Surface();
 
@@ -247,6 +244,7 @@
     int dispatchGetHdrSupport(va_list args);
     int dispatchGetConsumerUsage64(va_list args);
     int dispatchSetAutoPrerotation(va_list args);
+    int dispatchGetLastDequeueStartTime(va_list args);
     bool transformToDisplayInverse();
 
 protected:
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 64ee65f..8a6920c 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -446,12 +446,6 @@
         Transaction& setOverrideScalingMode(const sp<SurfaceControl>& sc,
                 int32_t overrideScalingMode);
 
-        // If the size changes in this transaction, all geometry updates specified
-        // in this transaction will not complete until a buffer of the new size
-        // arrives. As some elements normally apply immediately, this enables
-        // freezing the total geometry of a surface until a resize is completed.
-        Transaction& setGeometryAppliesWithResize(const sp<SurfaceControl>& sc);
-
 #ifndef NO_INPUT
         Transaction& setInputWindowInfo(const sp<SurfaceControl>& sc, const InputWindowInfo& info);
         Transaction& transferTouchFocus(const sp<IBinder>& fromToken, const sp<IBinder>& toToken);
diff --git a/libs/gui/tests/Android.bp b/libs/gui/tests/Android.bp
index ab6dcaa..cbda6b2 100644
--- a/libs/gui/tests/Android.bp
+++ b/libs/gui/tests/Android.bp
@@ -47,7 +47,6 @@
         "libcutils",
         "libgui",
         "libhidlbase",
-        "libhidltransport",
         "libinput",
         "libui",
         "libutils",
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 5a121d7..0b61d92 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -617,7 +617,7 @@
     anw->dequeueBuffer(anw.get(), &buffer, &fenceFd);
     nsecs_t after = systemTime(CLOCK_MONOTONIC);
 
-    nsecs_t lastDequeueTime = mSurface->getLastDequeueStartTime();
+    nsecs_t lastDequeueTime = ANativeWindow_getLastDequeueStartTime(anw.get());
     ASSERT_LE(before, lastDequeueTime);
     ASSERT_GE(after, lastDequeueTime);
 }
diff --git a/libs/nativewindow/ANativeWindow.cpp b/libs/nativewindow/ANativeWindow.cpp
index 4c59e6c..3b195f7 100644
--- a/libs/nativewindow/ANativeWindow.cpp
+++ b/libs/nativewindow/ANativeWindow.cpp
@@ -274,3 +274,13 @@
 int ANativeWindow_getLastDequeueDuration(ANativeWindow* window) {
     return query(window, NATIVE_WINDOW_LAST_DEQUEUE_DURATION);
 }
+
+int ANativeWindow_getLastQueueDuration(ANativeWindow* window) {
+    return query(window, NATIVE_WINDOW_LAST_QUEUE_DURATION);
+}
+
+int64_t ANativeWindow_getLastDequeueStartTime(ANativeWindow* window) {
+    int64_t time;
+    int success = window->perform(window, NATIVE_WINDOW_GET_LAST_DEQUEUE_START, &time);
+    return success < 0 ? success : time;
+}
diff --git a/libs/nativewindow/include/apex/window.h b/libs/nativewindow/include/apex/window.h
index 0260cbc..3ddd549 100644
--- a/libs/nativewindow/include/apex/window.h
+++ b/libs/nativewindow/include/apex/window.h
@@ -31,4 +31,21 @@
  */
 int ANativeWindow_getLastDequeueDuration(ANativeWindow* window);
 
+/**
+ * Retrieves how long it took for the last time a buffer was queued.
+ *
+ * \return a negative value on error, otherwise returns the duration in
+ * microseconds
+ */
+int ANativeWindow_getLastQueueDuration(ANativeWindow* window);
+
+/**
+ * Retrieves the system time in nanoseconds when the last time a buffer
+ * was dequeued.
+ *
+ * \return a negative value on error, otherwise returns the duration in
+ * nanoseconds.
+ */
+int64_t ANativeWindow_getLastDequeueStartTime(ANativeWindow* window);
+
 __END_DECLS
diff --git a/libs/nativewindow/include/system/window.h b/libs/nativewindow/include/system/window.h
index 78354bb..b7ae28a 100644
--- a/libs/nativewindow/include/system/window.h
+++ b/libs/nativewindow/include/system/window.h
@@ -93,7 +93,6 @@
      */
     NATIVE_WINDOW_CONCRETE_TYPE = 5,
 
-
     /*
      * Default width and height of ANativeWindow buffers, these are the
      * dimensions of the window buffers irrespective of the
@@ -240,6 +239,7 @@
     NATIVE_WINDOW_SET_BUFFERS_CTA861_3_METADATA   = 33,
     NATIVE_WINDOW_SET_BUFFERS_HDR10_PLUS_METADATA = 34,
     NATIVE_WINDOW_SET_AUTO_PREROTATION            = 35,
+    NATIVE_WINDOW_GET_LAST_DEQUEUE_START          = 36,    /* private */
     // clang-format on
 };
 
diff --git a/libs/nativewindow/libnativewindow.map.txt b/libs/nativewindow/libnativewindow.map.txt
index 7fe4df0..33c6400 100644
--- a/libs/nativewindow/libnativewindow.map.txt
+++ b/libs/nativewindow/libnativewindow.map.txt
@@ -23,6 +23,8 @@
     ANativeWindow_getFormat;
     ANativeWindow_getHeight;
     ANativeWindow_getLastDequeueDuration; # apex # introduced=30
+    ANativeWindow_getLastDequeueStartTime; # apex # introduced=30
+    ANativeWindow_getLastQueueDuration; # apex # introduced=30
     ANativeWindow_getWidth;
     ANativeWindow_lock;
     ANativeWindow_query; # vndk
diff --git a/libs/nativewindow/tests/ANativeWindowTest.cpp b/libs/nativewindow/tests/ANativeWindowTest.cpp
index 5247e04..947217d 100644
--- a/libs/nativewindow/tests/ANativeWindowTest.cpp
+++ b/libs/nativewindow/tests/ANativeWindowTest.cpp
@@ -36,6 +36,12 @@
 
     // Exposes the internal last dequeue duration that's stored on the Surface.
     nsecs_t getLastDequeueDuration() const { return mLastDequeueDuration; }
+
+    // Exposes the internal last queue duration that's stored on the Surface.
+    nsecs_t getLastQueueDuration() const { return mLastQueueDuration; }
+
+    // Exposes the internal last dequeue start time that's stored on the Surface.
+    nsecs_t getLastDequeueStartTime() const { return mLastDequeueStartTime; }
 };
 
 class ANativeWindowTest : public ::testing::Test {
@@ -82,3 +88,53 @@
     EXPECT_GT(result, 0);
     EXPECT_EQ(result, mWindow->getLastDequeueDuration() / 1000);
 }
+
+TEST_F(ANativeWindowTest, getLastQueueDuration_noDequeue_returnsZero) {
+    int result = ANativeWindow_getLastQueueDuration(mWindow.get());
+    EXPECT_EQ(0, result);
+    EXPECT_EQ(0, mWindow->getLastQueueDuration());
+}
+
+TEST_F(ANativeWindowTest, getLastQueueDuration_noQueue_returnsZero) {
+    ANativeWindowBuffer* buffer;
+    int fd;
+    int result = ANativeWindow_dequeueBuffer(mWindow.get(), &buffer, &fd);
+    close(fd);
+    EXPECT_EQ(0, result);
+
+    result = ANativeWindow_getLastQueueDuration(mWindow.get());
+    EXPECT_EQ(result, 0);
+    EXPECT_EQ(result, mWindow->getLastQueueDuration());
+}
+
+TEST_F(ANativeWindowTest, getLastQueueDuration_withQueue_returnsTime) {
+    ANativeWindowBuffer* buffer;
+    int fd;
+    int result = ANativeWindow_dequeueBuffer(mWindow.get(), &buffer, &fd);
+    close(fd);
+    EXPECT_EQ(0, result);
+
+    result = ANativeWindow_queueBuffer(mWindow.get(), buffer, 0);
+
+    result = ANativeWindow_getLastQueueDuration(mWindow.get());
+    EXPECT_GT(result, 0);
+    EXPECT_EQ(result, mWindow->getLastQueueDuration() / 1000);
+}
+
+TEST_F(ANativeWindowTest, getLastDequeueStartTime_noDequeue_returnsZero) {
+    int64_t result = ANativeWindow_getLastDequeueStartTime(mWindow.get());
+    EXPECT_EQ(0, result);
+    EXPECT_EQ(0, mWindow->getLastQueueDuration());
+}
+
+TEST_F(ANativeWindowTest, getLastDequeueStartTime_withDequeue_returnsTime) {
+    ANativeWindowBuffer* buffer;
+    int fd;
+    int dequeueResult = ANativeWindow_dequeueBuffer(mWindow.get(), &buffer, &fd);
+    close(fd);
+    EXPECT_EQ(0, dequeueResult);
+
+    int64_t result = ANativeWindow_getLastDequeueStartTime(mWindow.get());
+    EXPECT_GT(result, 0);
+    EXPECT_EQ(result, mWindow->getLastDequeueStartTime());
+}
diff --git a/libs/sensor/OWNERS b/libs/sensor/OWNERS
index 81099e8..90c2330 100644
--- a/libs/sensor/OWNERS
+++ b/libs/sensor/OWNERS
@@ -1,3 +1,3 @@
 arthuri@google.com
 bduddie@google.com
-bstack@google.com
+stange@google.com
diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp
index 8462fe7..bb85acc 100644
--- a/libs/ui/Android.bp
+++ b/libs/ui/Android.bp
@@ -99,8 +99,6 @@
         "libbase",
         "libcutils",
         "libhidlbase",
-        "libhidltransport",
-        "libhwbinder",
         "libsync",
         "libutils",
         "liblog",
diff --git a/libs/ui/tests/Android.bp b/libs/ui/tests/Android.bp
index c5170d0..0452f84 100644
--- a/libs/ui/tests/Android.bp
+++ b/libs/ui/tests/Android.bp
@@ -38,7 +38,6 @@
         "android.frameworks.bufferhub@1.0",
         "libcutils",
         "libhidlbase",
-        "libhwbinder",
         "libui",
         "libutils",
     ],
@@ -77,7 +76,6 @@
         "android.frameworks.bufferhub@1.0",
         "libcutils",
         "libhidlbase",
-        "libhwbinder",
         "liblog",
         "libui",
         "libutils"
diff --git a/libs/vr/libdisplay/vsync_service.cpp b/libs/vr/libdisplay/vsync_service.cpp
index 4668b98..04d4f30 100644
--- a/libs/vr/libdisplay/vsync_service.cpp
+++ b/libs/vr/libdisplay/vsync_service.cpp
@@ -45,8 +45,8 @@
       ALOGE("onVsync failed to writeInt64: %d", result);
       return result;
     }
-    result = remote()->transact(
-        BnVsyncCallback::ON_VSYNC, data, &reply, TF_ONE_WAY);
+    result = remote()->transact(BnVsyncCallback::ON_VSYNC, data, &reply,
+                                IBinder::FLAG_ONEWAY);
     if (result != OK) {
       ALOGE("onVsync failed to transact: %d", result);
       return result;
diff --git a/libs/vr/libvrflinger/Android.bp b/libs/vr/libvrflinger/Android.bp
index 4441672..2053344 100644
--- a/libs/vr/libvrflinger/Android.bp
+++ b/libs/vr/libvrflinger/Android.bp
@@ -57,7 +57,6 @@
     "libgui",
     "libsync",
     "libhidlbase",
-    "libhidltransport",
     "libfmq",
     "libpdx_default_transport",
 ]
diff --git a/libs/vr/libvrflinger/hardware_composer.cpp b/libs/vr/libvrflinger/hardware_composer.cpp
index e1240d6..9072d89 100644
--- a/libs/vr/libvrflinger/hardware_composer.cpp
+++ b/libs/vr/libvrflinger/hardware_composer.cpp
@@ -51,8 +51,6 @@
 
 const char kRightEyeOffsetProperty[] = "dvr.right_eye_offset_ns";
 
-const char kUseExternalDisplayProperty[] = "persist.vr.use_external_display";
-
 // Surface flinger uses "VSYNC-sf" and "VSYNC-app" for its version of these
 // events. Name ours similarly.
 const char kVsyncTraceEventName[] = "VSYNC-vrflinger";
@@ -965,18 +963,9 @@
       external_display_ = GetDisplayParams(composer_.get(),
           *displays.external_display, /*is_primary*/ false);
 
-      if (property_get_bool(kUseExternalDisplayProperty, false)) {
-        ALOGI("External display connected. Switching to external display.");
-        target_display_ = &(*external_display_);
-        target_display_changed = true;
-      } else {
-        ALOGI("External display connected, but sysprop %s is unset, so"
-              " using primary display.", kUseExternalDisplayProperty);
-        if (was_using_external_display) {
-          target_display_ = &primary_display_;
-          target_display_changed = true;
-        }
-      }
+      ALOGI("External display connected. Switching to external display.");
+      target_display_ = &(*external_display_);
+      target_display_changed = true;
     } else {
       // External display was disconnected
       external_display_ = std::nullopt;
diff --git a/opengl/libs/Android.bp b/opengl/libs/Android.bp
index 8144c8a..693e48e 100644
--- a/opengl/libs/Android.bp
+++ b/opengl/libs/Android.bp
@@ -153,7 +153,6 @@
         "android.hardware.configstore-utils",
         "libbase",
         "libhidlbase",
-        "libhidltransport",
         "libnativebridge_lazy",
         "libnativeloader_lazy",
         "libutils",
diff --git a/opengl/libs/EGL/egl_platform_entries.cpp b/opengl/libs/EGL/egl_platform_entries.cpp
index e996be6..d1b4a4e 100644
--- a/opengl/libs/EGL/egl_platform_entries.cpp
+++ b/opengl/libs/EGL/egl_platform_entries.cpp
@@ -1379,6 +1379,9 @@
     if (!_s.get())
         return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
 
+    if (n_rects < 0 || (n_rects > 0 && rects == NULL))
+        return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE);
+
     egl_surface_t* const s = get_surface(draw);
 
     if (CC_UNLIKELY(dp->traceGpuCompletion)) {
diff --git a/opengl/tests/EGLTest/Android.bp b/opengl/tests/EGLTest/Android.bp
index a9e873a..19c8b37 100644
--- a/opengl/tests/EGLTest/Android.bp
+++ b/opengl/tests/EGLTest/Android.bp
@@ -22,7 +22,6 @@
         "libbinder",
         "libgui",
         "libhidlbase",
-        "libhidltransport",
         "liblog",
         "libutils",
         "libnativewindow",
diff --git a/services/bufferhub/Android.bp b/services/bufferhub/Android.bp
index cd03bc2..2bb6aef 100644
--- a/services/bufferhub/Android.bp
+++ b/services/bufferhub/Android.bp
@@ -37,8 +37,6 @@
         "libcrypto",
         "libcutils",
         "libhidlbase",
-        "libhidltransport",
-        "libhwbinder",
         "liblog",
         "libui",
         "libutils",
@@ -64,8 +62,6 @@
         "libcrypto",
         "libcutils",
         "libhidlbase",
-        "libhidltransport",
-        "libhwbinder",
         "liblog",
         "libui",
         "libutils",
diff --git a/services/displayservice/Android.bp b/services/displayservice/Android.bp
index 3442cb2..4d2d873 100644
--- a/services/displayservice/Android.bp
+++ b/services/displayservice/Android.bp
@@ -27,7 +27,6 @@
         "liblog",
         "libgui",
         "libhidlbase",
-        "libhidltransport",
         "libutils",
         "android.frameworks.displayservice@1.0",
     ],
diff --git a/services/schedulerservice/Android.bp b/services/schedulerservice/Android.bp
index 0227164..73802db 100644
--- a/services/schedulerservice/Android.bp
+++ b/services/schedulerservice/Android.bp
@@ -6,8 +6,6 @@
     cflags: ["-Wall", "-Werror"],
     shared_libs: [
         "libhidlbase",
-        "libhidltransport",
-        "libhwbinder",
         "libmediautils",
         "liblog",
         "libutils",
diff --git a/services/sensorservice/Android.bp b/services/sensorservice/Android.bp
index 33a2747..1c9a4af 100644
--- a/services/sensorservice/Android.bp
+++ b/services/sensorservice/Android.bp
@@ -45,8 +45,6 @@
         "libcrypto",
         "libbase",
         "libhidlbase",
-        "libhidltransport",
-        "libhwbinder",
         "libfmq",
         "android.hardware.sensors@1.0",
         "android.hardware.sensors@2.0",
diff --git a/services/sensorservice/OWNERS b/services/sensorservice/OWNERS
index 81099e8..90c2330 100644
--- a/services/sensorservice/OWNERS
+++ b/services/sensorservice/OWNERS
@@ -1,3 +1,3 @@
 arthuri@google.com
 bduddie@google.com
-bstack@google.com
+stange@google.com
diff --git a/services/sensorservice/hidl/Android.bp b/services/sensorservice/hidl/Android.bp
index 02c13fa..d0c83d6 100644
--- a/services/sensorservice/hidl/Android.bp
+++ b/services/sensorservice/hidl/Android.bp
@@ -13,8 +13,6 @@
     shared_libs: [
         "libbase",
         "libhidlbase",
-        "libhidltransport",
-        "libhwbinder",
         "libutils",
         "libsensor",
         "android.frameworks.sensorservice@1.0",
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index 93c738d..b404836 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -43,8 +43,6 @@
         "libgui",
         "libhardware",
         "libhidlbase",
-        "libhidltransport",
-        "libhwbinder",
         "liblayers_proto",
         "liblog",
         "libnativewindow",
@@ -75,7 +73,6 @@
         "libtrace_proto",
         "libvr_manager",
         "libvrflinger",
-        "perfetto_src_tracing_ipc",
     ],
     header_libs: [
         "android.hardware.graphics.composer@2.1-command-buffer",
@@ -84,7 +81,6 @@
     ],
     export_static_lib_headers: [
         "libcompositionengine",
-        "libperfetto_client_experimental",
         "librenderengine",
         "libserviceutils",
         "libtimestats",
@@ -98,8 +94,6 @@
         "android.hardware.graphics.composer@2.3",
         "android.hardware.power@1.3",
         "libhidlbase",
-        "libhidltransport",
-        "libhwbinder",
     ],
 }
 
@@ -220,7 +214,6 @@
         "libcutils",
         "libdisplayservicehidl",
         "libhidlbase",
-        "libhidltransport",
         "libinput",
         "liblayers_proto",
         "liblog",
@@ -268,8 +261,6 @@
         "android.hardware.configstore@1.1",
         "android.hardware.graphics.common@1.2",
         "libhidlbase",
-        "libhidltransport",
-        "libhwbinder",
         "libui",
         "libutils",
         "liblog",
@@ -280,8 +271,6 @@
     export_shared_lib_headers: [
         "android.hardware.graphics.common@1.2",
         "libhidlbase",
-        "libhidltransport",
-        "libhwbinder",
     ],
     export_static_lib_headers: [
         "SurfaceFlingerProperties",
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index 90a02b3..486b042 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -81,7 +81,7 @@
     if (mFlinger->mForceFullDamage) {
         surfaceDamageRegion = Region::INVALID_REGION;
     } else {
-        surfaceDamageRegion = getDrawingSurfaceDamage();
+        surfaceDamageRegion = mBufferInfo.mSurfaceDamage;
     }
 }
 
@@ -92,7 +92,7 @@
 bool BufferLayer::isOpaque(const Layer::State& s) const {
     // if we don't have a buffer or sidebandStream yet, we're translucent regardless of the
     // layer's opaque flag.
-    if ((mSidebandStream == nullptr) && (mActiveBuffer == nullptr)) {
+    if ((mSidebandStream == nullptr) && (mBufferInfo.mBuffer == nullptr)) {
         return false;
     }
 
@@ -103,7 +103,7 @@
 
 bool BufferLayer::isVisible() const {
     bool visible = !(isHiddenByPolicy()) && getAlpha() > 0.0f &&
-            (mActiveBuffer != nullptr || mSidebandStream != nullptr);
+            (mBufferInfo.mBuffer != nullptr || mSidebandStream != nullptr);
     mFlinger->mScheduler->setLayerVisibility(mSchedulerLayerHandle, visible);
 
     return visible;
@@ -144,7 +144,7 @@
         return result;
     }
 
-    if (CC_UNLIKELY(mActiveBuffer == 0)) {
+    if (CC_UNLIKELY(mBufferInfo.mBuffer == 0)) {
         // the texture has not been created yet, this Layer has
         // in fact never been drawn into. This happens frequently with
         // SurfaceView because the WindowManager can't know when the client
@@ -161,7 +161,8 @@
                 finished = true;
                 return;
             }
-            under.orSelf(layer->visibleRegion);
+
+            under.orSelf(layer->getScreenBounds());
         });
         // if not everything below us is covered, we plug the holes!
         Region holes(targetSettings.clip.subtract(under));
@@ -175,9 +176,9 @@
     const State& s(getDrawingState());
     auto& layer = *result;
     if (!blackOutLayer) {
-        layer.source.buffer.buffer = mActiveBuffer;
+        layer.source.buffer.buffer = mBufferInfo.mBuffer;
         layer.source.buffer.isOpaque = isOpaque(s);
-        layer.source.buffer.fence = mActiveBufferFence;
+        layer.source.buffer.fence = mBufferInfo.mFence;
         layer.source.buffer.textureName = mTextureName;
         layer.source.buffer.usePremultipliedAlpha = getPremultipledAlpha();
         layer.source.buffer.isY410BT2020 = isHdrY410();
@@ -187,7 +188,7 @@
         // Query the texture matrix given our current filtering mode.
         float textureMatrix[16];
         setFilteringEnabled(useFiltering);
-        getDrawingTransformMatrix(textureMatrix);
+        memcpy(textureMatrix, mBufferInfo.mTransformMatrix, sizeof(mBufferInfo.mTransformMatrix));
 
         if (getTransformToDisplayInverse()) {
             /*
@@ -254,9 +255,9 @@
 
 bool BufferLayer::isHdrY410() const {
     // pixel format is HDR Y410 masquerading as RGBA_1010102
-    return (mCurrentDataSpace == ui::Dataspace::BT2020_ITU_PQ &&
-            getDrawingApi() == NATIVE_WINDOW_API_MEDIA &&
-            mActiveBuffer->getPixelFormat() == HAL_PIXEL_FORMAT_RGBA_1010102);
+    return (mBufferInfo.mDataspace == ui::Dataspace::BT2020_ITU_PQ &&
+            mBufferInfo.mApi == NATIVE_WINDOW_API_MEDIA &&
+            mBufferInfo.mBuffer->getPixelFormat() == HAL_PIXEL_FORMAT_RGBA_1010102);
 }
 
 void BufferLayer::latchPerFrameState(
@@ -268,7 +269,7 @@
         compositionState.compositionType = Hwc2::IComposerClient::Composition::SIDEBAND;
     } else {
         // Normal buffer layers
-        compositionState.hdrMetadata = getDrawingHdrMetadata();
+        compositionState.hdrMetadata = mBufferInfo.mHdrMetadata;
         compositionState.compositionType = mPotentialCursor
                 ? Hwc2::IComposerClient::Composition::CURSOR
                 : Hwc2::IComposerClient::Composition::DEVICE;
@@ -276,7 +277,7 @@
 }
 
 bool BufferLayer::onPreComposition(nsecs_t refreshStartTime) {
-    if (mBufferLatched) {
+    if (mBufferInfo.mBuffer != nullptr) {
         Mutex::Autolock lock(mFrameEventHistoryMutex);
         mFrameEventHistory.addPreComposition(mCurrentFrameNumber, refreshStartTime);
     }
@@ -300,13 +301,13 @@
     }
 
     // Update mFrameTracker.
-    nsecs_t desiredPresentTime = getDesiredPresentTime();
+    nsecs_t desiredPresentTime = mBufferInfo.mDesiredPresentTime;
     mFrameTracker.setDesiredPresentTime(desiredPresentTime);
 
     const int32_t layerID = getSequence();
     mFlinger->mTimeStats->setDesiredTime(layerID, mCurrentFrameNumber, desiredPresentTime);
 
-    std::shared_ptr<FenceTime> frameReadyFence = getCurrentFenceTime();
+    std::shared_ptr<FenceTime> frameReadyFence = mBufferInfo.mFenceTime;
     if (frameReadyFence->isValid()) {
         mFrameTracker.setFrameReadyFence(std::move(frameReadyFence));
     } else {
@@ -370,7 +371,8 @@
     // Capture the old state of the layer for comparisons later
     const State& s(getDrawingState());
     const bool oldOpacity = isOpaque(s);
-    sp<GraphicBuffer> oldBuffer = mActiveBuffer;
+
+    BufferInfo oldBufferInfo = mBufferInfo;
 
     if (!allTransactionsSignaled(expectedPresentTime)) {
         mFlinger->setTransactionFlags(eTraversalNeeded);
@@ -387,65 +389,33 @@
         return false;
     }
 
-    mBufferLatched = true;
-
     err = updateFrameNumber(latchTime);
     if (err != NO_ERROR) {
         return false;
     }
 
+    gatherBufferInfo();
+
     mRefreshPending = true;
     mFrameLatencyNeeded = true;
-    if (oldBuffer == nullptr) {
+    if (oldBufferInfo.mBuffer == nullptr) {
         // the first time we receive a buffer, we need to trigger a
         // geometry invalidation.
         recomputeVisibleRegions = true;
     }
 
-    ui::Dataspace dataSpace = getDrawingDataSpace();
-    // translate legacy dataspaces to modern dataspaces
-    switch (dataSpace) {
-        case ui::Dataspace::SRGB:
-            dataSpace = ui::Dataspace::V0_SRGB;
-            break;
-        case ui::Dataspace::SRGB_LINEAR:
-            dataSpace = ui::Dataspace::V0_SRGB_LINEAR;
-            break;
-        case ui::Dataspace::JFIF:
-            dataSpace = ui::Dataspace::V0_JFIF;
-            break;
-        case ui::Dataspace::BT601_625:
-            dataSpace = ui::Dataspace::V0_BT601_625;
-            break;
-        case ui::Dataspace::BT601_525:
-            dataSpace = ui::Dataspace::V0_BT601_525;
-            break;
-        case ui::Dataspace::BT709:
-            dataSpace = ui::Dataspace::V0_BT709;
-            break;
-        default:
-            break;
-    }
-    mCurrentDataSpace = dataSpace;
-
-    Rect crop(getDrawingCrop());
-    const uint32_t transform(getDrawingTransform());
-    const uint32_t scalingMode(getDrawingScalingMode());
-    const bool transformToDisplayInverse(getTransformToDisplayInverse());
-    if ((crop != mCurrentCrop) || (transform != mCurrentTransform) ||
-        (scalingMode != mCurrentScalingMode) ||
-        (transformToDisplayInverse != mTransformToDisplayInverse)) {
-        mCurrentCrop = crop;
-        mCurrentTransform = transform;
-        mCurrentScalingMode = scalingMode;
-        mTransformToDisplayInverse = transformToDisplayInverse;
+    if ((mBufferInfo.mCrop != oldBufferInfo.mCrop) ||
+        (mBufferInfo.mTransform != oldBufferInfo.mTransform) ||
+        (mBufferInfo.mScaleMode != oldBufferInfo.mScaleMode) ||
+        (mBufferInfo.mTransformToDisplayInverse != oldBufferInfo.mTransformToDisplayInverse)) {
         recomputeVisibleRegions = true;
     }
 
-    if (oldBuffer != nullptr) {
-        uint32_t bufWidth = mActiveBuffer->getWidth();
-        uint32_t bufHeight = mActiveBuffer->getHeight();
-        if (bufWidth != uint32_t(oldBuffer->width) || bufHeight != uint32_t(oldBuffer->height)) {
+    if (oldBufferInfo.mBuffer != nullptr) {
+        uint32_t bufWidth = mBufferInfo.mBuffer->getWidth();
+        uint32_t bufHeight = mBufferInfo.mBuffer->getHeight();
+        if (bufWidth != uint32_t(oldBufferInfo.mBuffer->width) ||
+            bufHeight != uint32_t(oldBufferInfo.mBuffer->height)) {
             recomputeVisibleRegions = true;
         }
     }
@@ -510,11 +480,11 @@
         return mOverrideScalingMode;
     }
 
-    return mCurrentScalingMode;
+    return mBufferInfo.mScaleMode;
 }
 
 bool BufferLayer::isProtected() const {
-    const sp<GraphicBuffer>& buffer(mActiveBuffer);
+    const sp<GraphicBuffer>& buffer(mBufferInfo.mBuffer);
     return (buffer != 0) && (buffer->getUsage() & GRALLOC_USAGE_PROTECTED);
 }
 
@@ -618,15 +588,15 @@
         return Rect(getActiveWidth(s), getActiveHeight(s));
     }
 
-    if (mActiveBuffer == nullptr) {
+    if (mBufferInfo.mBuffer == nullptr) {
         return Rect::INVALID_RECT;
     }
 
-    uint32_t bufWidth = mActiveBuffer->getWidth();
-    uint32_t bufHeight = mActiveBuffer->getHeight();
+    uint32_t bufWidth = mBufferInfo.mBuffer->getWidth();
+    uint32_t bufHeight = mBufferInfo.mBuffer->getHeight();
 
     // Undo any transformations on the buffer and return the result.
-    if (mCurrentTransform & ui::Transform::ROT_90) {
+    if (mBufferInfo.mTransform & ui::Transform::ROT_90) {
         std::swap(bufWidth, bufHeight);
     }
 
@@ -654,15 +624,15 @@
         return FloatRect(0, 0, getActiveWidth(s), getActiveHeight(s));
     }
 
-    if (mActiveBuffer == nullptr) {
+    if (mBufferInfo.mBuffer == nullptr) {
         return parentBounds;
     }
 
-    uint32_t bufWidth = mActiveBuffer->getWidth();
-    uint32_t bufHeight = mActiveBuffer->getHeight();
+    uint32_t bufWidth = mBufferInfo.mBuffer->getWidth();
+    uint32_t bufHeight = mBufferInfo.mBuffer->getHeight();
 
     // Undo any transformations on the buffer and return the result.
-    if (mCurrentTransform & ui::Transform::ROT_90) {
+    if (mBufferInfo.mTransform & ui::Transform::ROT_90) {
         std::swap(bufWidth, bufHeight);
     }
 
@@ -685,6 +655,70 @@
     releasePendingBuffer(systemTime());
 }
 
+PixelFormat BufferLayer::getPixelFormat() const {
+    return mBufferInfo.mPixelFormat;
+}
+
+bool BufferLayer::getTransformToDisplayInverse() const {
+    return mBufferInfo.mTransformToDisplayInverse;
+}
+
+Rect BufferLayer::getBufferCrop() const {
+    // this is the crop rectangle that applies to the buffer
+    // itself (as opposed to the window)
+    if (!mBufferInfo.mCrop.isEmpty()) {
+        // if the buffer crop is defined, we use that
+        return mBufferInfo.mCrop;
+    } else if (mBufferInfo.mBuffer != nullptr) {
+        // otherwise we use the whole buffer
+        return mBufferInfo.mBuffer->getBounds();
+    } else {
+        // if we don't have a buffer yet, we use an empty/invalid crop
+        return Rect();
+    }
+}
+
+uint32_t BufferLayer::getBufferTransform() const {
+    return mBufferInfo.mTransform;
+}
+
+ui::Dataspace BufferLayer::getDataSpace() const {
+    return mBufferInfo.mDataspace;
+}
+
+ui::Dataspace BufferLayer::translateDataspace(ui::Dataspace dataspace) {
+    ui::Dataspace updatedDataspace = dataspace;
+    // translate legacy dataspaces to modern dataspaces
+    switch (dataspace) {
+        case ui::Dataspace::SRGB:
+            updatedDataspace = ui::Dataspace::V0_SRGB;
+            break;
+        case ui::Dataspace::SRGB_LINEAR:
+            updatedDataspace = ui::Dataspace::V0_SRGB_LINEAR;
+            break;
+        case ui::Dataspace::JFIF:
+            updatedDataspace = ui::Dataspace::V0_JFIF;
+            break;
+        case ui::Dataspace::BT601_625:
+            updatedDataspace = ui::Dataspace::V0_BT601_625;
+            break;
+        case ui::Dataspace::BT601_525:
+            updatedDataspace = ui::Dataspace::V0_BT601_525;
+            break;
+        case ui::Dataspace::BT709:
+            updatedDataspace = ui::Dataspace::V0_BT709;
+            break;
+        default:
+            break;
+    }
+
+    return updatedDataspace;
+}
+
+sp<GraphicBuffer> BufferLayer::getBuffer() const {
+    return mBufferInfo.mBuffer;
+}
+
 } // namespace android
 
 #if defined(__gl_h_)
diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h
index ee44cbe..a685ea2 100644
--- a/services/surfaceflinger/BufferLayer.h
+++ b/services/surfaceflinger/BufferLayer.h
@@ -106,6 +106,16 @@
     // Should only be called on the main thread.
     void latchAndReleaseBuffer() override;
 
+    bool getTransformToDisplayInverse() const override;
+
+    Rect getBufferCrop() const override;
+
+    uint32_t getBufferTransform() const override;
+
+    ui::Dataspace getDataSpace() const override;
+
+    sp<GraphicBuffer> getBuffer() const override;
+
     // -----------------------------------------------------------------------
 
     // -----------------------------------------------------------------------
@@ -115,18 +125,7 @@
     virtual bool fenceHasSignaled() const = 0;
     virtual bool framePresentTimeIsCurrent(nsecs_t expectedPresentTime) const = 0;
 
-    virtual nsecs_t getDesiredPresentTime() = 0;
-    virtual std::shared_ptr<FenceTime> getCurrentFenceTime() const = 0;
-
-    virtual void getDrawingTransformMatrix(float *matrix) = 0;
-    virtual uint32_t getDrawingTransform() const = 0;
-    virtual ui::Dataspace getDrawingDataSpace() const = 0;
-    virtual Rect getDrawingCrop() const = 0;
-    virtual uint32_t getDrawingScalingMode() const = 0;
-    virtual Region getDrawingSurfaceDamage() const = 0;
-    virtual const HdrMetadata& getDrawingHdrMetadata() const = 0;
-    virtual int getDrawingApi() const = 0;
-    virtual PixelFormat getPixelFormat() const = 0;
+    PixelFormat getPixelFormat() const;
 
     virtual uint64_t getFrameNumber(nsecs_t expectedPresentTime) const = 0;
 
@@ -148,6 +147,28 @@
     virtual status_t updateFrameNumber(nsecs_t latchTime) = 0;
 
 protected:
+    struct BufferInfo {
+        nsecs_t mDesiredPresentTime;
+        std::shared_ptr<FenceTime> mFenceTime;
+        sp<Fence> mFence;
+        float mTransformMatrix[16];
+        uint32_t mTransform{0};
+        ui::Dataspace mDataspace;
+        Rect mCrop;
+        uint32_t mScaleMode{NATIVE_WINDOW_SCALING_MODE_FREEZE};
+        Region mSurfaceDamage;
+        HdrMetadata mHdrMetadata;
+        int mApi;
+        PixelFormat mPixelFormat;
+        bool mTransformToDisplayInverse{false};
+
+        sp<GraphicBuffer> mBuffer;
+        int mBufferSlot{BufferQueue::INVALID_BUFFER_SLOT};
+    };
+
+    BufferInfo mBufferInfo;
+    virtual void gatherBufferInfo() = 0;
+
     /*
      * compositionengine::LayerFE overrides
      */
@@ -171,19 +192,14 @@
 
     bool mRefreshPending{false};
 
+    ui::Dataspace translateDataspace(ui::Dataspace dataspace);
+
 private:
     // Returns true if this layer requires filtering
     bool needsFiltering(const sp<const DisplayDevice>& displayDevice) const override;
 
     uint64_t getHeadFrameNumber(nsecs_t expectedPresentTime) const;
 
-    uint32_t mCurrentScalingMode{NATIVE_WINDOW_SCALING_MODE_FREEZE};
-
-    bool mTransformToDisplayInverse{false};
-
-    // main thread.
-    bool mBufferLatched{false}; // TODO: Use mActiveBuffer?
-
     // BufferStateLayers can return Rect::INVALID_RECT if the layer does not have a display frame
     // and its parent layer is not bounded
     Rect getBufferSize(const State& s) const override;
diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp
index 4da39e4..a9e364a 100644
--- a/services/surfaceflinger/BufferQueueLayer.cpp
+++ b/services/surfaceflinger/BufferQueueLayer.cpp
@@ -70,10 +70,6 @@
     return history;
 }
 
-bool BufferQueueLayer::getTransformToDisplayInverse() const {
-    return mConsumer->getTransformToDisplayInverse();
-}
-
 void BufferQueueLayer::releasePendingBuffer(nsecs_t dequeueReadyTime) {
     if (!mConsumer->releasePendingBuffer()) {
         return;
@@ -155,55 +151,12 @@
     return mQueueItems[0].mTimestamp <= expectedPresentTime;
 }
 
-nsecs_t BufferQueueLayer::getDesiredPresentTime() {
-    return mConsumer->getTimestamp();
-}
-
-std::shared_ptr<FenceTime> BufferQueueLayer::getCurrentFenceTime() const {
-    return mConsumer->getCurrentFenceTime();
-}
-
-void BufferQueueLayer::getDrawingTransformMatrix(float *matrix) {
-    return mConsumer->getTransformMatrix(matrix);
-}
-
 // NOTE: SurfaceFlinger's definitions of "Current" and "Drawing" do not neatly map to BufferQueue's
 // These functions get the fields for the frame that is currently in SurfaceFlinger's Drawing state
 // so the functions start with "getDrawing". The data is retrieved from the BufferQueueConsumer's
 // current buffer so the consumer functions start with "getCurrent".
 //
 // This results in the rather confusing functions below.
-uint32_t BufferQueueLayer::getDrawingTransform() const {
-    return mConsumer->getCurrentTransform();
-}
-
-ui::Dataspace BufferQueueLayer::getDrawingDataSpace() const {
-    return mConsumer->getCurrentDataSpace();
-}
-
-Rect BufferQueueLayer::getDrawingCrop() const {
-    return mConsumer->getCurrentCrop();
-}
-
-uint32_t BufferQueueLayer::getDrawingScalingMode() const {
-    return mConsumer->getCurrentScalingMode();
-}
-
-Region BufferQueueLayer::getDrawingSurfaceDamage() const {
-    return mConsumer->getSurfaceDamage();
-}
-
-const HdrMetadata& BufferQueueLayer::getDrawingHdrMetadata() const {
-    return mConsumer->getCurrentHdrMetadata();
-}
-
-int BufferQueueLayer::getDrawingApi() const {
-    return mConsumer->getCurrentApi();
-}
-
-PixelFormat BufferQueueLayer::getPixelFormat() const {
-    return mFormat;
-}
 
 uint64_t BufferQueueLayer::getFrameNumber(nsecs_t expectedPresentTime) const {
     Mutex::Autolock lock(mQueueItemLock);
@@ -285,7 +238,7 @@
     const int32_t layerID = getSequence();
     LayerRejecter r(mDrawingState, getCurrentState(), recomputeVisibleRegions,
                     getProducerStickyTransform() != 0, mName.string(), mOverrideScalingMode,
-                    getTransformToDisplayInverse(), mFreezeGeometryUpdates);
+                    getTransformToDisplayInverse());
 
     if (isRemovedFromCurrentState()) {
         expectedPresentTime = 0;
@@ -390,11 +343,12 @@
 status_t BufferQueueLayer::updateActiveBuffer() {
     // update the active buffer
     mPreviousBufferId = getCurrentBufferId();
-    mActiveBuffer = mConsumer->getCurrentBuffer(&mActiveBufferSlot, &mActiveBufferFence);
+    mBufferInfo.mBuffer =
+            mConsumer->getCurrentBuffer(&mBufferInfo.mBufferSlot, &mBufferInfo.mFence);
     auto& layerCompositionState = getCompositionLayer()->editState().frontEnd;
-    layerCompositionState.buffer = mActiveBuffer;
+    layerCompositionState.buffer = mBufferInfo.mBuffer;
 
-    if (mActiveBuffer == nullptr) {
+    if (mBufferInfo.mBuffer == nullptr) {
         // this can only happen if the very first buffer was rejected.
         return BAD_VALUE;
     }
@@ -419,10 +373,11 @@
         return;
     }
 
-    compositionState.buffer = mActiveBuffer;
-    compositionState.bufferSlot =
-            (mActiveBufferSlot == BufferQueue::INVALID_BUFFER_SLOT) ? 0 : mActiveBufferSlot;
-    compositionState.acquireFence = mConsumer->getCurrentFence();
+    compositionState.buffer = mBufferInfo.mBuffer;
+    compositionState.bufferSlot = (mBufferInfo.mBufferSlot == BufferQueue::INVALID_BUFFER_SLOT)
+            ? 0
+            : mBufferInfo.mBufferSlot;
+    compositionState.acquireFence = mBufferInfo.mFence;
 }
 
 // -----------------------------------------------------------------------
@@ -573,4 +528,20 @@
     return static_cast<uint32_t>(producerStickyTransform);
 }
 
+void BufferQueueLayer::gatherBufferInfo() {
+    mBufferInfo.mDesiredPresentTime = mConsumer->getTimestamp();
+    mBufferInfo.mFenceTime = mConsumer->getCurrentFenceTime();
+    mBufferInfo.mFence = mConsumer->getCurrentFence();
+    mConsumer->getTransformMatrix(mBufferInfo.mTransformMatrix);
+    mBufferInfo.mTransform = mConsumer->getCurrentTransform();
+    mBufferInfo.mDataspace = translateDataspace(mConsumer->getCurrentDataSpace());
+    mBufferInfo.mCrop = mConsumer->getCurrentCrop();
+    mBufferInfo.mScaleMode = mConsumer->getCurrentScalingMode();
+    mBufferInfo.mSurfaceDamage = mConsumer->getSurfaceDamage();
+    mBufferInfo.mHdrMetadata = mConsumer->getCurrentHdrMetadata();
+    mBufferInfo.mApi = mConsumer->getCurrentApi();
+    mBufferInfo.mPixelFormat = mFormat;
+    mBufferInfo.mTransformToDisplayInverse = mConsumer->getTransformToDisplayInverse();
+}
+
 } // namespace android
diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h
index bf3f917..43eb3ea 100644
--- a/services/surfaceflinger/BufferQueueLayer.h
+++ b/services/surfaceflinger/BufferQueueLayer.h
@@ -46,7 +46,6 @@
 
     std::vector<OccupancyTracker::Segment> getOccupancyHistory(bool forceFlush) override;
 
-    bool getTransformToDisplayInverse() const override;
 
     // If a buffer was replaced this frame, release the former buffer
     void releasePendingBuffer(nsecs_t dequeueReadyTime) override;
@@ -66,18 +65,6 @@
     bool framePresentTimeIsCurrent(nsecs_t expectedPresentTime) const override;
 
 private:
-    nsecs_t getDesiredPresentTime() override;
-    std::shared_ptr<FenceTime> getCurrentFenceTime() const override;
-
-    void getDrawingTransformMatrix(float *matrix) override;
-    uint32_t getDrawingTransform() const override;
-    ui::Dataspace getDrawingDataSpace() const override;
-    Rect getDrawingCrop() const override;
-    uint32_t getDrawingScalingMode() const override;
-    Region getDrawingSurfaceDamage() const override;
-    const HdrMetadata& getDrawingHdrMetadata() const override;
-    int getDrawingApi() const override;
-    PixelFormat getPixelFormat() const override;
 
     uint64_t getFrameNumber(nsecs_t expectedPresentTime) const override;
 
@@ -103,6 +90,8 @@
     // Interface implementation for BufferLayerConsumer::ContentsChangedListener
     // -----------------------------------------------------------------------
 protected:
+    void gatherBufferInfo() override;
+
     void onFrameAvailable(const BufferItem& item) override;
     void onFrameReplaced(const BufferItem& item) override;
     void onSidebandStreamChanged() override;
@@ -138,7 +127,6 @@
     std::atomic<uint64_t> mLastFrameNumberReceived{0};
 
     bool mAutoRefresh{false};
-    int mActiveBufferSlot{BufferQueue::INVALID_BUFFER_SLOT};
 
     // thread-safe
     std::atomic<int32_t> mQueuedFrames{0};
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index e7d1b63..afbe228 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -53,12 +53,12 @@
 }
 
 BufferStateLayer::~BufferStateLayer() {
-    if (mActiveBuffer != nullptr) {
-        // Ensure that mActiveBuffer is uncached from RenderEngine here, as
+    if (mBufferInfo.mBuffer != nullptr) {
+        // Ensure that mBuffer is uncached from RenderEngine here, as
         // RenderEngine may have been using the buffer as an external texture
         // after the client uncached the buffer.
         auto& engine(mFlinger->getRenderEngine());
-        engine.unbindExternalTextureBuffer(mActiveBuffer->getId());
+        engine.unbindExternalTextureBuffer(mBufferInfo.mBuffer->getId());
     }
 }
 
@@ -125,10 +125,6 @@
              (mCurrentState.buffer != nullptr || mCurrentState.bgColorLayer != nullptr));
 }
 
-bool BufferStateLayer::getTransformToDisplayInverse() const {
-    return mCurrentState.transformToDisplayInverse;
-}
-
 void BufferStateLayer::pushPendingState() {
     if (!mCurrentState.modified) {
         return;
@@ -400,75 +396,6 @@
     return mCurrentState.desiredPresentTime <= expectedPresentTime;
 }
 
-nsecs_t BufferStateLayer::getDesiredPresentTime() {
-    return getDrawingState().desiredPresentTime;
-}
-
-std::shared_ptr<FenceTime> BufferStateLayer::getCurrentFenceTime() const {
-    return std::make_shared<FenceTime>(getDrawingState().acquireFence);
-}
-
-void BufferStateLayer::getDrawingTransformMatrix(float *matrix) {
-    std::copy(std::begin(mTransformMatrix), std::end(mTransformMatrix), matrix);
-}
-
-uint32_t BufferStateLayer::getDrawingTransform() const {
-    return getDrawingState().transform;
-}
-
-ui::Dataspace BufferStateLayer::getDrawingDataSpace() const {
-    return getDrawingState().dataspace;
-}
-
-// Crop that applies to the buffer
-Rect BufferStateLayer::getDrawingCrop() const {
-    const State& s(getDrawingState());
-
-    if (s.crop.isEmpty() && s.buffer) {
-        return s.buffer->getBounds();
-    } else if (s.buffer) {
-        Rect crop = s.crop;
-        crop.left = std::max(crop.left, 0);
-        crop.top = std::max(crop.top, 0);
-        uint32_t bufferWidth = s.buffer->getWidth();
-        uint32_t bufferHeight = s.buffer->getHeight();
-        if (bufferHeight <= std::numeric_limits<int32_t>::max() &&
-            bufferWidth <= std::numeric_limits<int32_t>::max()) {
-            crop.right = std::min(crop.right, static_cast<int32_t>(bufferWidth));
-            crop.bottom = std::min(crop.bottom, static_cast<int32_t>(bufferHeight));
-        }
-        if (!crop.isValid()) {
-            // Crop rect is out of bounds, return whole buffer
-            return s.buffer->getBounds();
-        }
-        return crop;
-    }
-    return s.crop;
-}
-
-uint32_t BufferStateLayer::getDrawingScalingMode() const {
-    return NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW;
-}
-
-Region BufferStateLayer::getDrawingSurfaceDamage() const {
-    return getDrawingState().surfaceDamageRegion;
-}
-
-const HdrMetadata& BufferStateLayer::getDrawingHdrMetadata() const {
-    return getDrawingState().hdrMetadata;
-}
-
-int BufferStateLayer::getDrawingApi() const {
-    return getDrawingState().api;
-}
-
-PixelFormat BufferStateLayer::getPixelFormat() const {
-    if (!mActiveBuffer) {
-        return PIXEL_FORMAT_NONE;
-    }
-    return mActiveBuffer->format;
-}
-
 uint64_t BufferStateLayer::getFrameNumber(nsecs_t /*expectedPresentTime*/) const {
     return mFrameNumber;
 }
@@ -506,8 +433,8 @@
 }
 
 void BufferStateLayer::setFilteringEnabled(bool enabled) {
-    GLConsumer::computeTransformMatrix(mTransformMatrix.data(), mActiveBuffer, mCurrentCrop,
-                                       mCurrentTransform, enabled);
+    GLConsumer::computeTransformMatrix(mTransformMatrix.data(), mBufferInfo.mBuffer,
+                                       mBufferInfo.mCrop, mBufferInfo.mTransform, enabled);
 }
 
 status_t BufferStateLayer::bindTextureImage() {
@@ -576,8 +503,8 @@
     }
 
     const uint64_t bufferID = getCurrentBufferId();
-    mFlinger->mTimeStats->setAcquireFence(layerID, mFrameNumber, getCurrentFenceTime());
-    mFlinger->mFrameTracer->traceFence(layerID, bufferID, mFrameNumber, getCurrentFenceTime(),
+    mFlinger->mTimeStats->setAcquireFence(layerID, mFrameNumber, mBufferInfo.mFenceTime);
+    mFlinger->mFrameTracer->traceFence(layerID, bufferID, mFrameNumber, mBufferInfo.mFenceTime,
                                        FrameTracer::FrameEvent::ACQUIRE_FENCE);
     mFlinger->mTimeStats->setLatchTime(layerID, mFrameNumber, latchTime);
     mFlinger->mFrameTracer->traceTimestamp(layerID, bufferID, mFrameNumber, latchTime,
@@ -596,10 +523,10 @@
     }
 
     mPreviousBufferId = getCurrentBufferId();
-    mActiveBuffer = s.buffer;
-    mActiveBufferFence = s.acquireFence;
+    mBufferInfo.mBuffer = s.buffer;
+    mBufferInfo.mFence = s.acquireFence;
     auto& layerCompositionState = getCompositionLayer()->editState().frontEnd;
-    layerCompositionState.buffer = mActiveBuffer;
+    layerCompositionState.buffer = mBufferInfo.mBuffer;
 
     return NO_ERROR;
 }
@@ -622,7 +549,7 @@
 
     compositionState.buffer = s.buffer;
     compositionState.bufferSlot = mHwcSlotGenerator->getHwcCacheSlot(s.clientCacheId);
-    compositionState.acquireFence = s.acquireFence;
+    compositionState.acquireFence = mBufferInfo.mFence;
 
     mFrameNumber++;
 }
@@ -707,4 +634,48 @@
     mFreeHwcCacheSlots.push(hwcCacheSlot);
     mCachedBuffers.erase(clientCacheId);
 }
+
+void BufferStateLayer::gatherBufferInfo() {
+    const State& s(getDrawingState());
+
+    mBufferInfo.mDesiredPresentTime = s.desiredPresentTime;
+    mBufferInfo.mFenceTime = std::make_shared<FenceTime>(s.acquireFence);
+    mBufferInfo.mFence = s.acquireFence;
+    std::copy(std::begin(mTransformMatrix), std::end(mTransformMatrix),
+              mBufferInfo.mTransformMatrix);
+    mBufferInfo.mTransform = s.transform;
+    mBufferInfo.mDataspace = translateDataspace(s.dataspace);
+    mBufferInfo.mCrop = computeCrop(s);
+    mBufferInfo.mScaleMode = NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW;
+    mBufferInfo.mSurfaceDamage = s.surfaceDamageRegion;
+    mBufferInfo.mHdrMetadata = s.hdrMetadata;
+    mBufferInfo.mApi = s.api;
+    mBufferInfo.mPixelFormat =
+            !mBufferInfo.mBuffer ? PIXEL_FORMAT_NONE : mBufferInfo.mBuffer->format;
+    mBufferInfo.mTransformToDisplayInverse = s.transformToDisplayInverse;
+}
+
+Rect BufferStateLayer::computeCrop(const State& s) {
+    if (s.crop.isEmpty() && s.buffer) {
+        return s.buffer->getBounds();
+    } else if (s.buffer) {
+        Rect crop = s.crop;
+        crop.left = std::max(crop.left, 0);
+        crop.top = std::max(crop.top, 0);
+        uint32_t bufferWidth = s.buffer->getWidth();
+        uint32_t bufferHeight = s.buffer->getHeight();
+        if (bufferHeight <= std::numeric_limits<int32_t>::max() &&
+            bufferWidth <= std::numeric_limits<int32_t>::max()) {
+            crop.right = std::min(crop.right, static_cast<int32_t>(bufferWidth));
+            crop.bottom = std::min(crop.bottom, static_cast<int32_t>(bufferHeight));
+        }
+        if (!crop.isValid()) {
+            // Crop rect is out of bounds, return whole buffer
+            return s.buffer->getBounds();
+        }
+        return crop;
+    }
+    return s.crop;
+}
+
 } // namespace android
diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h
index c060ca8..0b27d64 100644
--- a/services/surfaceflinger/BufferStateLayer.h
+++ b/services/surfaceflinger/BufferStateLayer.h
@@ -48,8 +48,6 @@
 
     bool shouldPresentNow(nsecs_t expectedPresentTime) const override;
 
-    bool getTransformToDisplayInverse() const override;
-
     uint32_t doTransactionResize(uint32_t flags, Layer::State* /*stateToCommit*/) override {
         return flags;
     }
@@ -82,13 +80,13 @@
 
     // Override to ignore legacy layer state properties that are not used by BufferStateLayer
     bool setSize(uint32_t /*w*/, uint32_t /*h*/) override { return false; }
-    bool setPosition(float /*x*/, float /*y*/, bool /*immediate*/) override { return false; }
+    bool setPosition(float /*x*/, float /*y*/) override { return false; }
     bool setTransparentRegionHint(const Region& transparent) override;
     bool setMatrix(const layer_state_t::matrix22_t& /*matrix*/,
                    bool /*allowNonRectPreservingTransforms*/) override {
         return false;
     }
-    bool setCrop_legacy(const Rect& /*crop*/, bool /*immediate*/) override { return false; }
+    bool setCrop_legacy(const Rect& /*crop*/) override { return false; }
     bool setOverrideScalingMode(int32_t /*overrideScalingMode*/) override { return false; }
     void deferTransactionUntil_legacy(const sp<IBinder>& /*barrierHandle*/,
                                       uint64_t /*frameNumber*/) override {}
@@ -106,19 +104,10 @@
     bool fenceHasSignaled() const override;
     bool framePresentTimeIsCurrent(nsecs_t expectedPresentTime) const override;
 
-private:
-    nsecs_t getDesiredPresentTime() override;
-    std::shared_ptr<FenceTime> getCurrentFenceTime() const override;
+protected:
+    void gatherBufferInfo() override;
 
-    void getDrawingTransformMatrix(float *matrix) override;
-    uint32_t getDrawingTransform() const override;
-    ui::Dataspace getDrawingDataSpace() const override;
-    Rect getDrawingCrop() const override;
-    uint32_t getDrawingScalingMode() const override;
-    Region getDrawingSurfaceDamage() const override;
-    const HdrMetadata& getDrawingHdrMetadata() const override;
-    int getDrawingApi() const override;
-    PixelFormat getPixelFormat() const override;
+private:
 
     uint64_t getFrameNumber(nsecs_t expectedPresentTime) const override;
 
@@ -140,6 +129,9 @@
 
     void latchPerFrameState(compositionengine::LayerFECompositionState&) const override;
 
+    // Crop that applies to the buffer
+    Rect computeCrop(const State& s);
+
 private:
     friend class SlotGenerationTest;
     void onFirstRef() override;
diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp
index 2ad7591..49b1810 100644
--- a/services/surfaceflinger/ColorLayer.cpp
+++ b/services/surfaceflinger/ColorLayer.cpp
@@ -99,11 +99,6 @@
     compositionState.compositionType = Hwc2::IComposerClient::Composition::SOLID_COLOR;
 }
 
-void ColorLayer::commitTransaction(const State& stateToCommit) {
-    Layer::commitTransaction(stateToCommit);
-    mCurrentDataSpace = mDrawingState.dataspace;
-}
-
 std::shared_ptr<compositionengine::Layer> ColorLayer::getCompositionLayer() const {
     return mCompositionLayer;
 }
@@ -112,6 +107,10 @@
     return (s.flags & layer_state_t::eLayerOpaque) != 0;
 }
 
+ui::Dataspace ColorLayer::getDataSpace() const {
+    return mDrawingState.dataspace;
+}
+
 // ---------------------------------------------------------------------------
 
 }; // namespace android
diff --git a/services/surfaceflinger/ColorLayer.h b/services/surfaceflinger/ColorLayer.h
index 57c54c7..16921df 100644
--- a/services/surfaceflinger/ColorLayer.h
+++ b/services/surfaceflinger/ColorLayer.h
@@ -37,7 +37,7 @@
 
     bool setDataspace(ui::Dataspace dataspace) override;
 
-    void commitTransaction(const State& stateToCommit) override;
+    ui::Dataspace getDataSpace() const override;
 
     bool isOpaque(const Layer::State& s) const override;
 
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h
index db4f969..57cca69 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h
@@ -39,9 +39,26 @@
     // process.
     virtual bool onPreComposition(nsecs_t refreshStartTime) = 0;
 
-    // Latches the output-independent state. If includeGeometry is false, the
-    // geometry state can be skipped.
-    virtual void latchCompositionState(LayerFECompositionState&, bool includeGeometry) const = 0;
+    // Used with latchCompositionState()
+    enum class StateSubset {
+        // Gets the basic geometry (bounds, transparent region, visibility,
+        // transforms, alpha) for the layer, for computing visibility and
+        // coverage.
+        BasicGeometry,
+
+        // Gets the full geometry (crops, buffer transforms, metadata) and
+        // content (buffer or color) state for the layer.
+        GeometryAndContent,
+
+        // Gets the per frame content (buffer or color) state the layer.
+        Content,
+    };
+
+    // Latches the output-independent composition state for the layer. The
+    // StateSubset argument selects what portion of the state is actually needed
+    // by the CompositionEngine code, since computing everything may be
+    // expensive.
+    virtual void latchCompositionState(LayerFECompositionState&, StateSubset) const = 0;
 
     // Latches the minimal bit of state for the cursor for a fast asynchronous
     // update.
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h
index 6a0caf0..530f49a 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h
@@ -40,6 +40,45 @@
     // the next geometry change.
     bool forceClientComposition{false};
 
+    // TODO(b/121291683): Reorganize and rename the contents of this structure
+
+    /*
+     * Visibility state
+     */
+    // the layer stack this layer belongs to
+    std::optional<uint32_t> layerStackId;
+
+    // If true, this layer should be only visible on the internal display
+    bool internalOnly{false};
+
+    // If false, this layer should not be considered visible
+    bool isVisible{true};
+
+    // True if the layer is completely opaque
+    bool isOpaque{true};
+
+    // If true, invalidates the entire visible region
+    bool contentDirty{false};
+
+    // The alpha value for this layer
+    float alpha{1.f};
+
+    // The transform from layer local coordinates to composition coordinates
+    ui::Transform geomLayerTransform;
+
+    // The inverse of the layer transform
+    ui::Transform geomInverseLayerTransform;
+
+    // The hint from the layer producer as to what portion of the layer is
+    // transparent.
+    Region transparentRegionHint;
+
+    // The blend mode for this layer
+    Hwc2::IComposerClient::BlendMode blendMode{Hwc2::IComposerClient::BlendMode::INVALID};
+
+    // The bounds of the layer in layer local coordinates
+    FloatRect geomLayerBounds;
+
     /*
      * Geometry state
      */
@@ -48,27 +87,9 @@
     bool geomUsesSourceCrop{false};
     bool geomBufferUsesDisplayInverseTransform{false};
     uint32_t geomBufferTransform{0};
-    ui::Transform geomLayerTransform;
-    ui::Transform geomInverseLayerTransform;
     Rect geomBufferSize;
     Rect geomContentCrop;
     Rect geomCrop;
-    Region geomActiveTransparentRegion;
-    FloatRect geomLayerBounds;
-
-    // TODO(lpique): b/121291683 Remove this one we are sure we don't need the
-    // value recomputed / set every frame.
-    Region geomVisibleRegion;
-
-    /*
-     * Presentation
-     */
-
-    // The blend mode for this layer
-    Hwc2::IComposerClient::BlendMode blendMode{Hwc2::IComposerClient::BlendMode::INVALID};
-
-    // The alpha value for this layer
-    float alpha{1.f};
 
     /*
      * Extra metadata
@@ -117,9 +138,6 @@
     mat4 colorTransform;
     bool colorTransformIsIdentity{true};
 
-    // True if the layer is completely opaque
-    bool isOpaque{true};
-
     // True if the layer has protected content
     bool hasProtectedContent{false};
 
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
index a509ca8..2e44c07 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
@@ -132,17 +132,20 @@
     // A layer belongs to the output if its layerStackId matches. Additionally
     // if the layer should only show in the internal (primary) display only and
     // this output allows that.
-    virtual bool belongsInOutput(uint32_t layerStackId, bool internalOnly) const = 0;
+    virtual bool belongsInOutput(std::optional<uint32_t> layerStackId, bool internalOnly) const = 0;
 
     // Returns a pointer to the output layer corresponding to the given layer on
     // this output, or nullptr if the layer does not have one
     virtual OutputLayer* getOutputLayerForLayer(Layer*) const = 0;
 
+    // Creates an OutputLayer instance for this output
+    virtual std::unique_ptr<OutputLayer> createOutputLayer(const std::shared_ptr<Layer>&,
+                                                           const sp<LayerFE>&) const = 0;
+
     // Gets the OutputLayer corresponding to the input Layer instance from the
     // current ordered set of output layers. If there is no such layer, a new
     // one is created and returned.
-    virtual std::unique_ptr<OutputLayer> getOrCreateOutputLayer(std::optional<DisplayId>,
-                                                                std::shared_ptr<Layer>,
+    virtual std::unique_ptr<OutputLayer> getOrCreateOutputLayer(std::shared_ptr<Layer>,
                                                                 sp<LayerFE>) = 0;
 
     // Sets the new ordered set of output layers for this output
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h
index cedd728..389b605 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h
@@ -48,6 +48,9 @@
 public:
     virtual ~OutputLayer();
 
+    // Sets the HWC2::Layer associated with this layer
+    virtual void setHwcLayer(std::shared_ptr<HWC2::Layer>) = 0;
+
     // Gets the output which owns this output layer
     virtual const Output& getOutput() const = 0;
 
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h
index bd1aa08..2e595d6 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h
@@ -40,6 +40,8 @@
 
     // compositionengine::Output overrides
     void dump(std::string&) const override;
+    std::unique_ptr<compositionengine::OutputLayer> createOutputLayer(
+            const std::shared_ptr<Layer>&, const sp<LayerFE>&) const override;
     void setColorTransform(const compositionengine::CompositionRefreshArgs&) override;
     void setColorProfile(const ColorProfile&) override;
     void chooseCompositionStrategy() override;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/LayerCompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/LayerCompositionState.h
index ab01c20..726c850 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/LayerCompositionState.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/LayerCompositionState.h
@@ -21,6 +21,7 @@
 
 #include <compositionengine/LayerFECompositionState.h>
 #include <renderengine/Mesh.h>
+#include <ui/Region.h>
 
 namespace android {
 
@@ -28,7 +29,7 @@
 
 struct LayerCompositionState {
     /*
-     * State intended to be set by LayerFE::getCompositionState
+     * State set by LayerFE::getCompositionState
      */
 
     LayerFECompositionState frontEnd;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
index d826161..bdb35c2 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
@@ -62,13 +62,14 @@
     OutputCompositionState& editState() override;
 
     Region getDirtyRegion(bool repaintEverything) const override;
-    bool belongsInOutput(uint32_t, bool) const override;
+    bool belongsInOutput(std::optional<uint32_t>, bool) const override;
 
     compositionengine::OutputLayer* getOutputLayerForLayer(
             compositionengine::Layer*) const override;
+    std::unique_ptr<compositionengine::OutputLayer> createOutputLayer(
+            const std::shared_ptr<Layer>&, const sp<LayerFE>&) const override;
     std::unique_ptr<compositionengine::OutputLayer> getOrCreateOutputLayer(
-            std::optional<DisplayId>, std::shared_ptr<compositionengine::Layer>,
-            sp<LayerFE>) override;
+            std::shared_ptr<compositionengine::Layer>, sp<LayerFE>) override;
     void setOutputLayersOrderedByZ(OutputLayers&&) override;
     const OutputLayers& getOutputLayersOrderedByZ() const override;
 
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h
index fa4d8cd..1199fea 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h
@@ -34,11 +34,11 @@
 
 class OutputLayer : public compositionengine::OutputLayer {
 public:
-    OutputLayer(const compositionengine::Output&, std::shared_ptr<compositionengine::Layer>,
-                sp<compositionengine::LayerFE>);
+    OutputLayer(const compositionengine::Output&, const std::shared_ptr<compositionengine::Layer>&,
+                const sp<compositionengine::LayerFE>&);
     ~OutputLayer() override;
 
-    void initialize(const CompositionEngine&, std::optional<DisplayId>);
+    void setHwcLayer(std::shared_ptr<HWC2::Layer>) override;
 
     const compositionengine::Output& getOutput() const override;
     compositionengine::Layer& getLayer() const override;
@@ -86,8 +86,8 @@
 };
 
 std::unique_ptr<compositionengine::OutputLayer> createOutputLayer(
-        const CompositionEngine&, std::optional<DisplayId>, const compositionengine::Output&,
-        std::shared_ptr<compositionengine::Layer>, sp<compositionengine::LayerFE>);
+        const compositionengine::Output&, const std::shared_ptr<compositionengine::Layer>&,
+        const sp<compositionengine::LayerFE>&);
 
 } // namespace impl
 } // namespace android::compositionengine
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h
index de0f08a..1347449 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h
@@ -40,9 +40,18 @@
 namespace compositionengine::impl {
 
 struct OutputLayerCompositionState {
-    // The region of this layer which is visible on this output
+    // The portion of the layer that is not obscured by opaque layers on top
     Region visibleRegion;
 
+    // The portion of the layer that is not obscured and is also opaque
+    Region visibleNonTransparentRegion;
+
+    // The portion of the layer that is obscured by opaque layers on top
+    Region coveredRegion;
+
+    // The visibleRegion transformed to output space
+    Region outputSpaceVisibleRegion;
+
     // If true, client composition will be used on this output
     bool forceClientComposition{false};
 
@@ -62,7 +71,7 @@
     ui::Dataspace dataspace{ui::Dataspace::UNKNOWN};
 
     // The Z order index of this layer on this output
-    uint32_t z;
+    uint32_t z{0};
 
     /*
      * HWC state
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h
index e280295..3eada3c 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h
@@ -32,7 +32,8 @@
 
     MOCK_METHOD1(onPreComposition, bool(nsecs_t));
 
-    MOCK_CONST_METHOD2(latchCompositionState, void(LayerFECompositionState&, bool));
+    MOCK_CONST_METHOD2(latchCompositionState,
+                       void(LayerFECompositionState&, compositionengine::LayerFE::StateSubset));
     MOCK_CONST_METHOD1(latchCursorCompositionState, void(LayerFECompositionState&));
     MOCK_METHOD1(prepareClientComposition,
                  std::optional<renderengine::LayerSettings>(
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h
index 33925d5..93274e7 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h
@@ -59,13 +59,17 @@
     MOCK_METHOD0(editState, OutputCompositionState&());
 
     MOCK_CONST_METHOD1(getDirtyRegion, Region(bool));
-    MOCK_CONST_METHOD2(belongsInOutput, bool(uint32_t, bool));
+    MOCK_CONST_METHOD2(belongsInOutput, bool(std::optional<uint32_t>, bool));
 
     MOCK_CONST_METHOD1(getOutputLayerForLayer,
                        compositionengine::OutputLayer*(compositionengine::Layer*));
-    MOCK_METHOD3(getOrCreateOutputLayer,
+    MOCK_CONST_METHOD2(createOutputLayer,
+                       std::unique_ptr<compositionengine::OutputLayer>(
+                               const std::shared_ptr<compositionengine::Layer>&,
+                               const sp<compositionengine::LayerFE>&));
+    MOCK_METHOD2(getOrCreateOutputLayer,
                  std::unique_ptr<compositionengine::OutputLayer>(
-                         std::optional<DisplayId>, std::shared_ptr<compositionengine::Layer>,
+                         std::shared_ptr<compositionengine::Layer>,
                          sp<compositionengine::LayerFE>));
 
     MOCK_METHOD1(setOutputLayersOrderedByZ, void(OutputLayers&&));
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h
index 6b2224a..4f2afac 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h
@@ -31,6 +31,8 @@
     OutputLayer();
     virtual ~OutputLayer();
 
+    MOCK_METHOD1(setHwcLayer, void(std::shared_ptr<HWC2::Layer>));
+
     MOCK_CONST_METHOD0(getOutput, const compositionengine::Output&());
     MOCK_CONST_METHOD0(getLayer, compositionengine::Layer&());
     MOCK_CONST_METHOD0(getLayerFE, compositionengine::LayerFE&());
diff --git a/services/surfaceflinger/CompositionEngine/src/Display.cpp b/services/surfaceflinger/CompositionEngine/src/Display.cpp
index 000a294..49727df 100644
--- a/services/surfaceflinger/CompositionEngine/src/Display.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Display.cpp
@@ -19,6 +19,7 @@
 #include <compositionengine/CompositionRefreshArgs.h>
 #include <compositionengine/DisplayCreationArgs.h>
 #include <compositionengine/DisplaySurface.h>
+#include <compositionengine/LayerFE.h>
 #include <compositionengine/impl/Display.h>
 #include <compositionengine/impl/DisplayColorProfile.h>
 #include <compositionengine/impl/DumpHelpers.h>
@@ -133,6 +134,30 @@
                                                                   std::move(args)));
 }
 
+std::unique_ptr<compositionengine::OutputLayer> Display::createOutputLayer(
+        const std::shared_ptr<compositionengine::Layer>& layer,
+        const sp<compositionengine::LayerFE>& layerFE) const {
+    auto result = Output::createOutputLayer(layer, layerFE);
+
+    if (result && mId) {
+        auto& hwc = getCompositionEngine().getHwComposer();
+        auto displayId = *mId;
+        // Note: For the moment we ensure it is safe to take a reference to the
+        // HWComposer implementation by destroying all the OutputLayers (and
+        // hence the HWC2::Layers they own) before setting a new HWComposer. See
+        // for example SurfaceFlinger::updateVrFlinger().
+        // TODO(b/121291683): Make this safer.
+        auto hwcLayer = std::shared_ptr<HWC2::Layer>(hwc.createLayer(displayId),
+                                                     [&hwc, displayId](HWC2::Layer* layer) {
+                                                         hwc.destroyLayer(displayId, layer);
+                                                     });
+        ALOGE_IF(!hwcLayer, "Failed to create a HWC layer for a HWC supported display %s",
+                 getName().c_str());
+        result->setHwcLayer(std::move(hwcLayer));
+    }
+    return result;
+}
+
 void Display::chooseCompositionStrategy() {
     ATRACE_CALL();
     ALOGV(__FUNCTION__);
diff --git a/services/surfaceflinger/CompositionEngine/src/LayerCompositionState.cpp b/services/surfaceflinger/CompositionEngine/src/LayerCompositionState.cpp
index 0dc4bf1..c5debf6 100644
--- a/services/surfaceflinger/CompositionEngine/src/LayerCompositionState.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/LayerCompositionState.cpp
@@ -45,7 +45,7 @@
     dumpVal(out, "geomBufferTransform", state.geomBufferTransform);
 
     out.append("\n      ");
-    dumpVal(out, "geomActiveTransparentRegion", state.geomActiveTransparentRegion);
+    dumpVal(out, "transparentRegionHint", state.transparentRegionHint);
 
     out.append("      ");
     dumpVal(out, "geomLayerBounds", state.geomLayerBounds);
diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp
index 903ca98..cb04e95 100644
--- a/services/surfaceflinger/CompositionEngine/src/Output.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp
@@ -212,10 +212,11 @@
     return dirty;
 }
 
-bool Output::belongsInOutput(uint32_t layerStackId, bool internalOnly) const {
+bool Output::belongsInOutput(std::optional<uint32_t> layerStackId, bool internalOnly) const {
     // The layerStackId's must match, and also the layer must not be internal
     // only when not on an internal output.
-    return (layerStackId == mState.layerStackId) && (!internalOnly || mState.layerStackInternal);
+    return layerStackId && (*layerStackId == mState.layerStackId) &&
+            (!internalOnly || mState.layerStackInternal);
 }
 
 compositionengine::OutputLayer* Output::getOutputLayerForLayer(
@@ -229,14 +230,20 @@
 }
 
 std::unique_ptr<compositionengine::OutputLayer> Output::getOrCreateOutputLayer(
-        std::optional<DisplayId> displayId, std::shared_ptr<compositionengine::Layer> layer,
-        sp<compositionengine::LayerFE> layerFE) {
+        std::shared_ptr<compositionengine::Layer> layer, sp<compositionengine::LayerFE> layerFE) {
     for (auto& outputLayer : mOutputLayersOrderedByZ) {
         if (outputLayer && &outputLayer->getLayer() == layer.get()) {
             return std::move(outputLayer);
         }
     }
-    return createOutputLayer(mCompositionEngine, displayId, *this, layer, layerFE);
+
+    return createOutputLayer(layer, layerFE);
+}
+
+std::unique_ptr<compositionengine::OutputLayer> Output::createOutputLayer(
+        const std::shared_ptr<compositionengine::Layer>& layer,
+        const sp<compositionengine::LayerFE>& layerFE) const {
+    return impl::createOutputLayer(*this, layer, layerFE);
 }
 
 void Output::setOutputLayersOrderedByZ(OutputLayers&& layers) {
@@ -281,7 +288,9 @@
 void Output::updateLayerStateFromFE(const CompositionRefreshArgs& args) const {
     for (auto& layer : mOutputLayersOrderedByZ) {
         layer->getLayerFE().latchCompositionState(layer->getLayer().editState().frontEnd,
-                                                  args.updatingGeometryThisFrame);
+                                                  args.updatingGeometryThisFrame
+                                                          ? LayerFE::StateSubset::GeometryAndContent
+                                                          : LayerFE::StateSubset::Content);
     }
 }
 
@@ -601,7 +610,7 @@
         const auto& layerFEState = layer->getLayer().getState().frontEnd;
         auto& layerFE = layer->getLayerFE();
 
-        const Region clip(viewportRegion.intersect(layerFEState.geomVisibleRegion));
+        const Region clip(viewportRegion.intersect(layerState.visibleRegion));
         ALOGV("Layer: %s", layerFE.getDebugName());
         if (clip.isEmpty()) {
             ALOGV("  Skipping for empty clip");
diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
index 73bb03b..4eb256f 100644
--- a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
@@ -15,7 +15,6 @@
  */
 
 #include <android-base/stringprintf.h>
-#include <compositionengine/CompositionEngine.h>
 #include <compositionengine/DisplayColorProfile.h>
 #include <compositionengine/Layer.h>
 #include <compositionengine/LayerFE.h>
@@ -46,31 +45,24 @@
 } // namespace
 
 std::unique_ptr<compositionengine::OutputLayer> createOutputLayer(
-        const CompositionEngine& compositionEngine, std::optional<DisplayId> displayId,
-        const compositionengine::Output& output, std::shared_ptr<compositionengine::Layer> layer,
-        sp<compositionengine::LayerFE> layerFE) {
-    auto result = std::make_unique<OutputLayer>(output, layer, layerFE);
-    result->initialize(compositionEngine, displayId);
-    return result;
+        const compositionengine::Output& output,
+        const std::shared_ptr<compositionengine::Layer>& layer,
+        const sp<compositionengine::LayerFE>& layerFE) {
+    return std::make_unique<OutputLayer>(output, layer, layerFE);
 }
 
-OutputLayer::OutputLayer(const Output& output, std::shared_ptr<Layer> layer, sp<LayerFE> layerFE)
+OutputLayer::OutputLayer(const Output& output, const std::shared_ptr<Layer>& layer,
+                         const sp<LayerFE>& layerFE)
       : mOutput(output), mLayer(layer), mLayerFE(layerFE) {}
 
 OutputLayer::~OutputLayer() = default;
 
-void OutputLayer::initialize(const CompositionEngine& compositionEngine,
-                             std::optional<DisplayId> displayId) {
-    if (!displayId) {
-        return;
+void OutputLayer::setHwcLayer(std::shared_ptr<HWC2::Layer> hwcLayer) {
+    if (hwcLayer) {
+        mState.hwc.emplace(hwcLayer);
+    } else {
+        mState.hwc.reset();
     }
-
-    auto& hwc = compositionEngine.getHwComposer();
-
-    mState.hwc.emplace(std::shared_ptr<HWC2::Layer>(hwc.createLayer(*displayId),
-                                                    [&hwc, displayId](HWC2::Layer* layer) {
-                                                        hwc.destroyLayer(*displayId, layer);
-                                                    }));
 }
 
 const compositionengine::Output& OutputLayer::getOutput() const {
@@ -102,7 +94,7 @@
     // pixels in the buffer.
 
     FloatRect activeCropFloat =
-            reduce(layerState.geomLayerBounds, layerState.geomActiveTransparentRegion);
+            reduce(layerState.geomLayerBounds, layerState.transparentRegionHint);
 
     const Rect& viewport = mOutput.getState().viewport;
     const ui::Transform& layerTransform = layerState.geomLayerTransform;
@@ -209,7 +201,7 @@
 
     // apply the layer's transform, followed by the display's global transform
     // here we're guaranteed that the layer's transform preserves rects
-    Region activeTransparentRegion = layerState.geomActiveTransparentRegion;
+    Region activeTransparentRegion = layerState.transparentRegionHint;
     const ui::Transform& layerTransform = layerState.geomLayerTransform;
     const ui::Transform& inverseLayerTransform = layerState.geomInverseLayerTransform;
     const Rect& bufferSize = layerState.geomBufferSize;
@@ -315,11 +307,6 @@
             ? outputState.targetDataspace
             : layerFEState.dataspace;
 
-    // TODO(lpique): b/121291683 Remove this one we are sure we don't need the
-    // value recomputed / set every frame.
-    mState.visibleRegion = outputState.transform.transform(
-            layerFEState.geomVisibleRegion.intersect(outputState.viewport));
-
     // These are evaluated every frame as they can potentially change at any
     // time.
     if (layerFEState.forceClientComposition || !profile.isDataspaceSupported(mState.dataspace)) {
@@ -421,13 +408,13 @@
 void OutputLayer::writeOutputDependentPerFrameStateToHWC(HWC2::Layer* hwcLayer) {
     const auto& outputDependentState = getState();
 
-    // TODO(lpique): b/121291683 visibleRegion is output-dependent geometry
+    // TODO(lpique): b/121291683 outputSpaceVisibleRegion is output-dependent geometry
     // state and should not change every frame.
-    if (auto error = hwcLayer->setVisibleRegion(outputDependentState.visibleRegion);
+    if (auto error = hwcLayer->setVisibleRegion(outputDependentState.outputSpaceVisibleRegion);
         error != HWC2::Error::None) {
         ALOGE("[%s] Failed to set visible region: %s (%d)", mLayerFE->getDebugName(),
               to_string(error).c_str(), static_cast<int32_t>(error));
-        outputDependentState.visibleRegion.dump(LOG_TAG);
+        outputDependentState.outputSpaceVisibleRegion.dump(LOG_TAG);
     }
 
     if (auto error = hwcLayer->setDataspace(outputDependentState.dataspace);
diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayerCompositionState.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayerCompositionState.cpp
index e320bee..ad668b6 100644
--- a/services/surfaceflinger/CompositionEngine/src/OutputLayerCompositionState.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/OutputLayerCompositionState.cpp
@@ -42,6 +42,15 @@
     dumpVal(out, "visibleRegion", visibleRegion);
 
     out.append("      ");
+    dumpVal(out, "visibleNonTransparentRegion", visibleNonTransparentRegion);
+
+    out.append("      ");
+    dumpVal(out, "coveredRegion", coveredRegion);
+
+    out.append("      ");
+    dumpVal(out, "output visibleRegion", outputSpaceVisibleRegion);
+
+    out.append("      ");
     dumpVal(out, "forceClientComposition", forceClientComposition);
     dumpVal(out, "clearClientTarget", clearClientTarget);
     dumpVal(out, "displayFrame", displayFrame);
diff --git a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
index 008e631..6821ec1 100644
--- a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
@@ -23,6 +23,8 @@
 #include <compositionengine/impl/Display.h>
 #include <compositionengine/mock/CompositionEngine.h>
 #include <compositionengine/mock/DisplayColorProfile.h>
+#include <compositionengine/mock/Layer.h>
+#include <compositionengine/mock/LayerFE.h>
 #include <compositionengine/mock/NativeWindow.h>
 #include <compositionengine/mock/OutputLayer.h>
 #include <compositionengine/mock/RenderSurface.h>
@@ -256,6 +258,25 @@
 }
 
 /*
+ * Display::createOutputLayer()
+ */
+
+TEST_F(DisplayTest, createOutputLayerSetsHwcLayer) {
+    sp<mock::LayerFE> layerFE = new StrictMock<mock::LayerFE>();
+    auto layer = std::make_shared<StrictMock<mock::Layer>>();
+    StrictMock<HWC2::mock::Layer> hwcLayer;
+
+    EXPECT_CALL(mHwComposer, createLayer(DEFAULT_DISPLAY_ID)).WillOnce(Return(&hwcLayer));
+
+    auto outputLayer = mDisplay.createOutputLayer(layer, layerFE);
+
+    EXPECT_EQ(&hwcLayer, outputLayer->getHwcLayer());
+
+    EXPECT_CALL(mHwComposer, destroyLayer(DEFAULT_DISPLAY_ID, &hwcLayer));
+    outputLayer.reset();
+}
+
+/*
  * Display::chooseCompositionStrategy()
  */
 
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
index 75e960c..b73c47b 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
@@ -36,8 +36,6 @@
 using testing::ReturnRef;
 using testing::StrictMock;
 
-constexpr DisplayId DEFAULT_DISPLAY_ID = DisplayId{42};
-
 constexpr auto TR_IDENT = 0u;
 constexpr auto TR_FLP_H = HAL_TRANSFORM_FLIP_H;
 constexpr auto TR_FLP_V = HAL_TRANSFORM_FLIP_V;
@@ -83,35 +81,27 @@
 TEST_F(OutputLayerTest, canInstantiateOutputLayer) {}
 
 /*
- * OutputLayer::initialize()
+ * OutputLayer::setHwcLayer()
  */
 
-TEST_F(OutputLayerTest, initializingOutputLayerWithoutHwcDoesNothingInteresting) {
+TEST_F(OutputLayerTest, settingNullHwcLayerSetsEmptyHwcState) {
     StrictMock<compositionengine::mock::CompositionEngine> compositionEngine;
 
-    mOutputLayer.initialize(compositionEngine, std::nullopt);
+    mOutputLayer.setHwcLayer(nullptr);
 
     EXPECT_FALSE(mOutputLayer.getState().hwc);
 }
 
-TEST_F(OutputLayerTest, initializingOutputLayerWithHwcDisplayCreatesHwcLayer) {
-    StrictMock<compositionengine::mock::CompositionEngine> compositionEngine;
-    StrictMock<android::mock::HWComposer> hwc;
-    StrictMock<HWC2::mock::Layer> hwcLayer;
+TEST_F(OutputLayerTest, settingHwcLayerSetsHwcState) {
+    auto hwcLayer = std::make_shared<StrictMock<HWC2::mock::Layer>>();
 
-    EXPECT_CALL(compositionEngine, getHwComposer()).WillOnce(ReturnRef(hwc));
-    EXPECT_CALL(hwc, createLayer(DEFAULT_DISPLAY_ID)).WillOnce(Return(&hwcLayer));
-
-    mOutputLayer.initialize(compositionEngine, DEFAULT_DISPLAY_ID);
+    mOutputLayer.setHwcLayer(hwcLayer);
 
     const auto& outputLayerState = mOutputLayer.getState();
     ASSERT_TRUE(outputLayerState.hwc);
 
     const auto& hwcState = *outputLayerState.hwc;
-    EXPECT_EQ(&hwcLayer, hwcState.hwcLayer.get());
-
-    EXPECT_CALL(hwc, destroyLayer(DEFAULT_DISPLAY_ID, &hwcLayer));
-    mOutputLayer.editState().hwc.reset();
+    EXPECT_EQ(hwcLayer, hwcState.hwcLayer);
 }
 
 /*
@@ -124,7 +114,7 @@
         // set one specific value to something different.
         mLayerState.frontEnd.geomUsesSourceCrop = true;
         mLayerState.frontEnd.geomContentCrop = Rect{0, 0, 1920, 1080};
-        mLayerState.frontEnd.geomActiveTransparentRegion = Region{};
+        mLayerState.frontEnd.transparentRegionHint = Region{};
         mLayerState.frontEnd.geomLayerBounds = FloatRect{0.f, 0.f, 1920.f, 1080.f};
         mLayerState.frontEnd.geomLayerTransform = ui::Transform{TR_IDENT};
         mLayerState.frontEnd.geomBufferSize = Rect{0, 0, 1920, 1080};
@@ -231,7 +221,7 @@
         // Set reasonable default values for a simple case. Each test will
         // set one specific value to something different.
 
-        mLayerState.frontEnd.geomActiveTransparentRegion = Region{};
+        mLayerState.frontEnd.transparentRegionHint = Region{};
         mLayerState.frontEnd.geomLayerTransform = ui::Transform{TR_IDENT};
         mLayerState.frontEnd.geomBufferSize = Rect{0, 0, 1920, 1080};
         mLayerState.frontEnd.geomBufferUsesDisplayInverseTransform = false;
@@ -256,7 +246,7 @@
 }
 
 TEST_F(OutputLayerDisplayFrameTest, fullActiveTransparentRegionReturnsEmptyFrame) {
-    mLayerState.frontEnd.geomActiveTransparentRegion = Region{Rect{0, 0, 1920, 1080}};
+    mLayerState.frontEnd.transparentRegionHint = Region{Rect{0, 0, 1920, 1080}};
     const Rect expected{0, 0, 0, 0};
     EXPECT_THAT(calculateOutputDisplayFrame(), RectEq(expected));
 }
@@ -574,7 +564,7 @@
 
     static const half4 kColor;
     static const Rect kDisplayFrame;
-    static const Region kVisibleRegion;
+    static const Region kOutputSpaceVisibleRegion;
     static const mat4 kColorTransform;
     static const Region kSurfaceDamage;
     static const HdrMetadata kHdrMetadata;
@@ -590,7 +580,7 @@
         outputLayerState.sourceCrop = kSourceCrop;
         outputLayerState.z = kZOrder;
         outputLayerState.bufferTransform = static_cast<Hwc2::Transform>(kBufferTransform);
-        outputLayerState.visibleRegion = kVisibleRegion;
+        outputLayerState.outputSpaceVisibleRegion = kOutputSpaceVisibleRegion;
         outputLayerState.dataspace = kDataspace;
 
         mLayerState.frontEnd.blendMode = kBlendMode;
@@ -629,7 +619,7 @@
     }
 
     void expectPerFrameCommonCalls(SimulateUnsupported unsupported = SimulateUnsupported::None) {
-        EXPECT_CALL(*mHwcLayer, setVisibleRegion(RegionEq(kVisibleRegion)))
+        EXPECT_CALL(*mHwcLayer, setVisibleRegion(RegionEq(kOutputSpaceVisibleRegion)))
                 .WillOnce(Return(kError));
         EXPECT_CALL(*mHwcLayer, setDataspace(kDataspace)).WillOnce(Return(kError));
         EXPECT_CALL(*mHwcLayer, setColorTransform(kColorTransform))
@@ -673,7 +663,8 @@
 const half4 OutputLayerWriteStateToHWCTest::kColor{81.f / 255.f, 82.f / 255.f, 83.f / 255.f,
                                                    84.f / 255.f};
 const Rect OutputLayerWriteStateToHWCTest::kDisplayFrame{1001, 1002, 1003, 10044};
-const Region OutputLayerWriteStateToHWCTest::kVisibleRegion{Rect{1005, 1006, 1007, 1008}};
+const Region OutputLayerWriteStateToHWCTest::kOutputSpaceVisibleRegion{
+        Rect{1005, 1006, 1007, 1008}};
 const mat4 OutputLayerWriteStateToHWCTest::kColorTransform{
         1009, 1010, 1011, 1012, 1013, 1014, 1015, 1016,
         1017, 1018, 1019, 1020, 1021, 1022, 1023, 1024,
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
index 1d5f2f0..10ec1ee 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
@@ -356,6 +356,10 @@
     // If the output accepts layerStack1 and internal-only layers....
     mOutput.setLayerStackFilter(layerStack1, true);
 
+    // A layer with no layerStack does not belong to it, internal-only or not.
+    EXPECT_FALSE(mOutput.belongsInOutput(std::nullopt, false));
+    EXPECT_FALSE(mOutput.belongsInOutput(std::nullopt, true));
+
     // Any layer with layerStack1 belongs to it, internal-only or not.
     EXPECT_TRUE(mOutput.belongsInOutput(layerStack1, false));
     EXPECT_TRUE(mOutput.belongsInOutput(layerStack1, true));
@@ -425,7 +429,7 @@
         // If there is no OutputLayer corresponding to the input layer, a
         // new OutputLayer is constructed and returned.
         EXPECT_CALL(*existingOutputLayer, getLayer()).WillOnce(ReturnRef(otherLayer));
-        auto result = mOutput.getOrCreateOutputLayer(std::nullopt, layer, layerFE);
+        auto result = mOutput.getOrCreateOutputLayer(layer, layerFE);
         EXPECT_NE(existingOutputLayer, result.get());
         EXPECT_TRUE(result.get() != nullptr);
         EXPECT_EQ(layer.get(), &result->getLayer());
@@ -441,7 +445,7 @@
         // If there is an existing OutputLayer for the requested layer, an owned
         // pointer is returned
         EXPECT_CALL(*existingOutputLayer, getLayer()).WillOnce(ReturnRef(*layer));
-        auto result = mOutput.getOrCreateOutputLayer(std::nullopt, layer, layerFE);
+        auto result = mOutput.getOrCreateOutputLayer(layer, layerFE);
         EXPECT_EQ(existingOutputLayer, result.get());
 
         // The corresponding entry in the ordered array should be cleared.
@@ -661,9 +665,9 @@
 
     impl::OutputLayerCompositionState leftOutputLayerState;
     leftOutputLayerState.clearClientTarget = false;
+    leftOutputLayerState.visibleRegion = Region{Rect{0, 0, 1000, 1000}};
 
     impl::LayerCompositionState leftLayerState;
-    leftLayerState.frontEnd.geomVisibleRegion = Region{Rect{0, 0, 1000, 1000}};
     leftLayerState.frontEnd.isOpaque = true;
 
     const half3 leftLayerColor{1.f, 0.f, 0.f};
@@ -672,9 +676,9 @@
 
     impl::OutputLayerCompositionState rightOutputLayerState;
     rightOutputLayerState.clearClientTarget = false;
+    rightOutputLayerState.visibleRegion = Region{Rect{1000, 0, 2000, 1000}};
 
     impl::LayerCompositionState rightLayerState;
-    rightLayerState.frontEnd.geomVisibleRegion = Region{Rect{1000, 0, 2000, 1000}};
     rightLayerState.frontEnd.isOpaque = true;
 
     const half3 rightLayerColor{0.f, 1.f, 0.f};
@@ -735,9 +739,9 @@
 
     impl::OutputLayerCompositionState outputLayerState;
     outputLayerState.clearClientTarget = false;
+    outputLayerState.visibleRegion = Region{Rect{3000, 0, 4000, 1000}};
 
     impl::LayerCompositionState layerState;
-    layerState.frontEnd.geomVisibleRegion = Region{Rect{3000, 0, 4000, 1000}};
     layerState.frontEnd.isOpaque = true;
 
     EXPECT_CALL(*outputLayer, getState()).WillRepeatedly(ReturnRef(outputLayerState));
@@ -790,16 +794,16 @@
 
     impl::OutputLayerCompositionState leftOutputLayerState;
     leftOutputLayerState.clearClientTarget = true;
+    leftOutputLayerState.visibleRegion = Region{Rect{0, 0, 1000, 1000}};
 
     impl::LayerCompositionState leftLayerState;
-    leftLayerState.frontEnd.geomVisibleRegion = Region{Rect{0, 0, 1000, 1000}};
     leftLayerState.frontEnd.isOpaque = true;
 
     impl::OutputLayerCompositionState rightOutputLayerState;
     rightOutputLayerState.clearClientTarget = true;
+    rightOutputLayerState.visibleRegion = Region{Rect{1000, 0, 2000, 1000}};
 
     impl::LayerCompositionState rightLayerState;
-    rightLayerState.frontEnd.geomVisibleRegion = Region{Rect{1000, 0, 2000, 1000}};
     rightLayerState.frontEnd.isOpaque = true;
 
     const half3 rightLayerColor{0.f, 1.f, 0.f};
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index c916f74..8f6672c 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -78,7 +78,6 @@
         mName(args.name),
         mClientRef(args.client),
         mWindowType(args.metadata.getInt32(METADATA_WINDOW_TYPE, 0)) {
-    mCurrentCrop.makeInvalid();
 
     uint32_t layerFlags = 0;
     if (args.flags & ISurfaceComposerClient::eHidden) layerFlags |= layer_state_t::eLayerHidden;
@@ -259,23 +258,6 @@
 // h/w composer set-up
 // ---------------------------------------------------------------------------
 
-Rect Layer::getContentCrop() const {
-    // this is the crop rectangle that applies to the buffer
-    // itself (as opposed to the window)
-    Rect crop;
-    if (!mCurrentCrop.isEmpty()) {
-        // if the buffer crop is defined, we use that
-        crop = mCurrentCrop;
-    } else if (mActiveBuffer != nullptr) {
-        // otherwise we use the whole buffer
-        crop = mActiveBuffer->getBounds();
-    } else {
-        // if we don't have a buffer yet, we use an empty/invalid crop
-        crop.makeInvalid();
-    }
-    return crop;
-}
-
 static Rect reduce(const Rect& win, const Region& exclude) {
     if (CC_LIKELY(exclude.isEmpty())) {
         return win;
@@ -320,7 +302,7 @@
     // If the layer is not using NATIVE_WINDOW_SCALING_MODE_FREEZE (e.g.
     // it isFixedSize) then there may be additional scaling not accounted
     // for in the layer transform.
-    if (!isFixedSize() || !mActiveBuffer) {
+    if (!isFixedSize() || getBuffer() == nullptr) {
         return {};
     }
 
@@ -332,10 +314,10 @@
         return {};
     }
 
-    int bufferWidth = mActiveBuffer->getWidth();
-    int bufferHeight = mActiveBuffer->getHeight();
+    int bufferWidth = getBuffer()->getWidth();
+    int bufferHeight = getBuffer()->getHeight();
 
-    if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
+    if (getBufferTransform() & NATIVE_WINDOW_TRANSFORM_ROT_90) {
         std::swap(bufferWidth, bufferHeight);
     }
 
@@ -350,7 +332,7 @@
 ui::Transform Layer::getTransformWithScale(const ui::Transform& bufferScaleTransform) const {
     // We need to mirror this scaling to child surfaces or we will break the contract where WM can
     // treat child surfaces as pixels in the parent surface.
-    if (!isFixedSize() || !mActiveBuffer) {
+    if (!isFixedSize() || getBuffer() == nullptr) {
         return mEffectiveTransform;
     }
     return mEffectiveTransform * bufferScaleTransform;
@@ -359,7 +341,7 @@
 FloatRect Layer::getBoundsPreScaling(const ui::Transform& bufferScaleTransform) const {
     // We need the pre scaled layer bounds when computing child bounds to make sure the child is
     // cropped to its parent layer after any buffer transform scaling is applied.
-    if (!isFixedSize() || !mActiveBuffer) {
+    if (!isFixedSize() || getBuffer() == nullptr) {
         return mBounds;
     }
     return bufferScaleTransform.inverse().transform(mBounds);
@@ -417,14 +399,43 @@
     win.bottom -= roundedCornersCrop.top;
 }
 
+void Layer::latchBasicGeometry(compositionengine::LayerFECompositionState& compositionState) const {
+    const auto& drawingState{getDrawingState()};
+    const uint32_t layerStack = getLayerStack();
+    const auto alpha = static_cast<float>(getAlpha());
+    const bool opaque = isOpaque(drawingState);
+    const bool usesRoundedCorners = getRoundedCornerState().radius != 0.f;
+
+    auto blendMode = Hwc2::IComposerClient::BlendMode::NONE;
+    if (!opaque || alpha != 1.0f) {
+        blendMode = mPremultipliedAlpha ? Hwc2::IComposerClient::BlendMode::PREMULTIPLIED
+                                        : Hwc2::IComposerClient::BlendMode::COVERAGE;
+    }
+
+    // TODO(b/121291683): Instead of filling in a passed-in compositionState
+    // structure, switch to Layer owning the structure and have
+    // CompositionEngine be able to get a reference to it.
+
+    compositionState.layerStackId =
+            (layerStack != ~0u) ? std::make_optional(layerStack) : std::nullopt;
+    compositionState.internalOnly = getPrimaryDisplayOnly();
+    compositionState.isVisible = isVisible();
+    compositionState.isOpaque = opaque && !usesRoundedCorners && alpha == 1.f;
+
+    compositionState.contentDirty = contentDirty;
+    contentDirty = false;
+
+    compositionState.geomLayerBounds = mBounds;
+    compositionState.geomLayerTransform = getTransform();
+    compositionState.geomInverseLayerTransform = compositionState.geomLayerTransform.inverse();
+    compositionState.transparentRegionHint = getActiveTransparentRegion(drawingState);
+
+    compositionState.blendMode = static_cast<Hwc2::IComposerClient::BlendMode>(blendMode);
+    compositionState.alpha = alpha;
+}
+
 void Layer::latchGeometry(compositionengine::LayerFECompositionState& compositionState) const {
     const auto& drawingState{getDrawingState()};
-    auto alpha = static_cast<float>(getAlpha());
-    auto blendMode = HWC2::BlendMode::None;
-    if (!isOpaque(drawingState) || alpha != 1.0f) {
-        blendMode =
-                mPremultipliedAlpha ? HWC2::BlendMode::Premultiplied : HWC2::BlendMode::Coverage;
-    }
 
     int type = drawingState.metadata.getInt32(METADATA_WINDOW_TYPE, 0);
     int appId = drawingState.metadata.getInt32(METADATA_OWNER_UID, 0);
@@ -439,20 +450,14 @@
         }
     }
 
-    compositionState.geomLayerTransform = getTransform();
-    compositionState.geomInverseLayerTransform = compositionState.geomLayerTransform.inverse();
     compositionState.geomBufferSize = getBufferSize(drawingState);
-    compositionState.geomContentCrop = getContentCrop();
+    compositionState.geomContentCrop = getBufferCrop();
     compositionState.geomCrop = getCrop(drawingState);
-    compositionState.geomBufferTransform = mCurrentTransform;
+    compositionState.geomBufferTransform = getBufferTransform();
     compositionState.geomBufferUsesDisplayInverseTransform = getTransformToDisplayInverse();
-    compositionState.geomActiveTransparentRegion = getActiveTransparentRegion(drawingState);
-    compositionState.geomLayerBounds = mBounds;
     compositionState.geomUsesSourceCrop = usesSourceCrop();
     compositionState.isSecure = isSecure();
 
-    compositionState.blendMode = static_cast<Hwc2::IComposerClient::BlendMode>(blendMode);
-    compositionState.alpha = alpha;
     compositionState.type = type;
     compositionState.appId = appId;
 }
@@ -461,12 +466,8 @@
     const auto& drawingState{getDrawingState()};
     compositionState.forceClientComposition = false;
 
-    // TODO(lpique): b/121291683 Remove this one we are sure we don't need the
-    // value recomputed / set every frame.
-    compositionState.geomVisibleRegion = visibleRegion;
-
     compositionState.isColorspaceAgnostic = isColorSpaceAgnostic();
-    compositionState.dataspace = mCurrentDataSpace;
+    compositionState.dataspace = getDataSpace();
     compositionState.colorTransform = getColorTransform();
     compositionState.colorTransformIsIdentity = !hasColorTransform();
     compositionState.surfaceDamage = surfaceDamageRegion;
@@ -502,12 +503,24 @@
 }
 
 void Layer::latchCompositionState(compositionengine::LayerFECompositionState& compositionState,
-                                  bool includeGeometry) const {
-    if (includeGeometry) {
-        latchGeometry(compositionState);
-    }
+                                  compositionengine::LayerFE::StateSubset subset) const {
+    using StateSubset = compositionengine::LayerFE::StateSubset;
 
-    latchPerFrameState(compositionState);
+    switch (subset) {
+        case StateSubset::BasicGeometry:
+            latchBasicGeometry(compositionState);
+            break;
+
+        case StateSubset::GeometryAndContent:
+            latchBasicGeometry(compositionState);
+            latchGeometry(compositionState);
+            latchPerFrameState(compositionState);
+            break;
+
+        case StateSubset::Content:
+            latchPerFrameState(compositionState);
+            break;
+    }
 }
 
 const char* Layer::getDebugName() const {
@@ -543,7 +556,7 @@
     layerSettings.geometry.roundedCornersCrop = roundedCornerState.cropRect;
 
     layerSettings.alpha = alpha;
-    layerSettings.sourceDataspace = mCurrentDataSpace;
+    layerSettings.sourceDataspace = getDataSpace();
     return layerSettings;
 }
 
@@ -585,27 +598,6 @@
     return (s.flags & layer_state_t::eLayerSecure);
 }
 
-void Layer::setVisibleRegion(const Region& visibleRegion) {
-    // always called from main thread
-    this->visibleRegion = visibleRegion;
-}
-
-void Layer::setCoveredRegion(const Region& coveredRegion) {
-    // always called from main thread
-    this->coveredRegion = coveredRegion;
-}
-
-void Layer::setVisibleNonTransparentRegion(const Region& setVisibleNonTransparentRegion) {
-    // always called from main thread
-    this->visibleNonTransparentRegion = setVisibleNonTransparentRegion;
-}
-
-void Layer::clearVisibilityRegions() {
-    visibleRegion.clear();
-    visibleNonTransparentRegion.clear();
-    coveredRegion.clear();
-}
-
 // ----------------------------------------------------------------------------
 // transaction
 // ----------------------------------------------------------------------------
@@ -726,7 +718,7 @@
                  "            requested={ wh={%4u,%4u} }}\n"
                  "  drawing={ active   ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
                  "            requested={ wh={%4u,%4u} }}\n",
-                 this, getName().string(), mCurrentTransform, getEffectiveScalingMode(),
+                 this, getName().string(), getBufferTransform(), getEffectiveScalingMode(),
                  stateToCommit->active_legacy.w, stateToCommit->active_legacy.h,
                  stateToCommit->crop_legacy.left, stateToCommit->crop_legacy.top,
                  stateToCommit->crop_legacy.right, stateToCommit->crop_legacy.bottom,
@@ -758,7 +750,7 @@
     const bool resizePending =
             ((stateToCommit->requested_legacy.w != stateToCommit->active_legacy.w) ||
              (stateToCommit->requested_legacy.h != stateToCommit->active_legacy.h)) &&
-            (mActiveBuffer != nullptr);
+            (getBuffer() != nullptr);
     if (!isFixedSize()) {
         if (resizePending && mSidebandStream == nullptr) {
             flags |= eDontUpdateGeometryState;
@@ -771,11 +763,6 @@
     if (!(flags & eDontUpdateGeometryState)) {
         State& editCurrentState(getCurrentState());
 
-        // If mFreezeGeometryUpdates is true we are in the setGeometryAppliesWithResize
-        // mode, which causes attributes which normally latch regardless of scaling mode,
-        // to be delayed. We copy the requested state to the active state making sure
-        // to respect these rules (again see Layer.h for a detailed discussion).
-        //
         // There is an awkward asymmetry in the handling of the crop states in the position
         // states, as can be seen below. Largely this arises from position and transform
         // being stored in the same data structure while having different latching rules.
@@ -783,16 +770,8 @@
         //
         // Careful that "stateToCommit" and editCurrentState may not begin as equivalent due to
         // applyPendingStates in the presence of deferred transactions.
-        if (mFreezeGeometryUpdates) {
-            float tx = stateToCommit->active_legacy.transform.tx();
-            float ty = stateToCommit->active_legacy.transform.ty();
-            stateToCommit->active_legacy = stateToCommit->requested_legacy;
-            stateToCommit->active_legacy.transform.set(tx, ty);
-            editCurrentState.active_legacy = stateToCommit->active_legacy;
-        } else {
-            editCurrentState.active_legacy = editCurrentState.requested_legacy;
-            stateToCommit->active_legacy = stateToCommit->requested_legacy;
-        }
+        editCurrentState.active_legacy = editCurrentState.requested_legacy;
+        stateToCommit->active_legacy = stateToCommit->requested_legacy;
     }
 
     return flags;
@@ -859,7 +838,7 @@
     return mTransactionFlags.fetch_or(flags);
 }
 
-bool Layer::setPosition(float x, float y, bool immediate) {
+bool Layer::setPosition(float x, float y) {
     if (mCurrentState.requested_legacy.transform.tx() == x &&
         mCurrentState.requested_legacy.transform.ty() == y)
         return false;
@@ -869,14 +848,11 @@
     // we want to apply the position portion of the transform matrix immediately,
     // but still delay scaling when resizing a SCALING_MODE_FREEZE layer.
     mCurrentState.requested_legacy.transform.set(x, y);
-    if (immediate && !mFreezeGeometryUpdates) {
-        // Here we directly update the active state
-        // unlike other setters, because we store it within
-        // the transform, but use different latching rules.
-        // b/38182305
-        mCurrentState.active_legacy.transform.set(x, y);
-    }
-    mFreezeGeometryUpdates = mFreezeGeometryUpdates || !immediate;
+    // Here we directly update the active state
+    // unlike other setters, because we store it within
+    // the transform, but use different latching rules.
+    // b/38182305
+    mCurrentState.active_legacy.transform.set(x, y);
 
     mCurrentState.modified = true;
     setTransactionFlags(eTransactionNeeded);
@@ -1082,14 +1058,11 @@
     return true;
 }
 
-bool Layer::setCrop_legacy(const Rect& crop, bool immediate) {
+bool Layer::setCrop_legacy(const Rect& crop) {
     if (mCurrentState.requestedCrop_legacy == crop) return false;
     mCurrentState.sequence++;
     mCurrentState.requestedCrop_legacy = crop;
-    if (immediate && !mFreezeGeometryUpdates) {
-        mCurrentState.crop_legacy = crop;
-    }
-    mFreezeGeometryUpdates = mFreezeGeometryUpdates || !immediate;
+    mCurrentState.crop_legacy = crop;
 
     mCurrentState.modified = true;
     setTransactionFlags(eTransactionNeeded);
@@ -1220,7 +1193,8 @@
     info.mParentName = (parent == nullptr ? std::string("none") : parent->getName().string());
     info.mType = getType();
     info.mTransparentRegion = ds.activeTransparentRegion_legacy;
-    info.mVisibleRegion = visibleRegion;
+
+    info.mVisibleRegion = debugGetVisibleRegionOnDefaultDisplay();
     info.mSurfaceDamageRegion = surfaceDamageRegion;
     info.mLayerStack = getLayerStack();
     info.mX = ds.active_legacy.transform.tx();
@@ -1232,13 +1206,13 @@
     info.mColor = ds.color;
     info.mFlags = ds.flags;
     info.mPixelFormat = getPixelFormat();
-    info.mDataSpace = static_cast<android_dataspace>(mCurrentDataSpace);
+    info.mDataSpace = static_cast<android_dataspace>(getDataSpace());
     info.mMatrix[0][0] = ds.active_legacy.transform[0][0];
     info.mMatrix[0][1] = ds.active_legacy.transform[0][1];
     info.mMatrix[1][0] = ds.active_legacy.transform[1][0];
     info.mMatrix[1][1] = ds.active_legacy.transform[1][1];
     {
-        sp<const GraphicBuffer> buffer = mActiveBuffer;
+        sp<const GraphicBuffer> buffer = getBuffer();
         if (buffer != 0) {
             info.mActiveBufferWidth = buffer->getWidth();
             info.mActiveBufferHeight = buffer->getHeight();
@@ -1551,8 +1525,9 @@
 
 bool Layer::isLegacyDataSpace() const {
     // return true when no higher bits are set
-    return !(mCurrentDataSpace & (ui::Dataspace::STANDARD_MASK |
-                ui::Dataspace::TRANSFER_MASK | ui::Dataspace::RANGE_MASK));
+    return !(getDataSpace() &
+             (ui::Dataspace::STANDARD_MASK | ui::Dataspace::TRANSFER_MASK |
+              ui::Dataspace::RANGE_MASK));
 }
 
 void Layer::setParent(const sp<Layer>& layer) {
@@ -1830,17 +1805,16 @@
             }
         }
 
-        auto buffer = mActiveBuffer;
+        auto buffer = getBuffer();
         if (buffer != nullptr) {
             LayerProtoHelper::writeToProto(buffer,
                                            [&]() { return layerInfo->mutable_active_buffer(); });
-            LayerProtoHelper::writeToProto(ui::Transform(mCurrentTransform),
+            LayerProtoHelper::writeToProto(ui::Transform(getBufferTransform()),
                                            layerInfo->mutable_buffer_transform());
         }
         layerInfo->set_invalidate(contentDirty);
         layerInfo->set_is_protected(isProtected());
-        layerInfo->set_dataspace(
-                dataspaceDetails(static_cast<android_dataspace>(mCurrentDataSpace)));
+        layerInfo->set_dataspace(dataspaceDetails(static_cast<android_dataspace>(getDataSpace())));
         layerInfo->set_queued_frames(getQueuedFrameCount());
         layerInfo->set_refresh_pending(isBufferLatched());
         layerInfo->set_curr_frame(mCurrentFrameNumber);
@@ -1851,7 +1825,7 @@
         LayerProtoHelper::writePositionToProto(transform.tx(), transform.ty(),
                                                [&]() { return layerInfo->mutable_position(); });
         LayerProtoHelper::writeToProto(mBounds, [&]() { return layerInfo->mutable_bounds(); });
-        LayerProtoHelper::writeToProto(visibleRegion,
+        LayerProtoHelper::writeToProto(debugGetVisibleRegionOnDefaultDisplay(),
                                        [&]() { return layerInfo->mutable_visible_region(); });
         LayerProtoHelper::writeToProto(surfaceDamageRegion,
                                        [&]() { return layerInfo->mutable_damage_region(); });
@@ -2028,6 +2002,20 @@
     return display->getCompositionDisplay()->getOutputLayerForLayer(getCompositionLayer().get());
 }
 
+Region Layer::debugGetVisibleRegionOnDefaultDisplay() const {
+    sp<DisplayDevice> displayDevice = mFlinger->getDefaultDisplayDeviceLocked();
+    if (displayDevice == nullptr) {
+        return {};
+    }
+
+    auto outputLayer = findOutputLayerForDisplay(displayDevice);
+    if (outputLayer == nullptr) {
+        return {};
+    }
+
+    return outputLayer->getState().visibleRegion;
+}
+
 // ---------------------------------------------------------------------------
 
 }; // namespace android
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 23c1acd..8771ccd 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -98,10 +98,6 @@
 
 public:
     mutable bool contentDirty{false};
-    // regions below are in window-manager space
-    Region visibleRegion;
-    Region coveredRegion;
-    Region visibleNonTransparentRegion;
     Region surfaceDamageRegion;
 
     // Layer serial number.  This gives layers an explicit ordering, so we
@@ -268,9 +264,9 @@
 
     // setPosition operates in parent buffer space (pre parent-transform) or display
     // space for top-level layers.
-    virtual bool setPosition(float x, float y, bool immediate);
+    virtual bool setPosition(float x, float y);
     // Buffer space
-    virtual bool setCrop_legacy(const Rect& crop, bool immediate);
+    virtual bool setCrop_legacy(const Rect& crop);
 
     // TODO(b/38182121): Could we eliminate the various latching modes by
     // using the layer hierarchy?
@@ -330,7 +326,7 @@
     virtual bool setBackgroundColor(const half3& color, float alpha, ui::Dataspace dataspace);
     virtual bool setColorSpaceAgnostic(const bool agnostic);
 
-    ui::Dataspace getDataSpace() const { return mCurrentDataSpace; }
+    virtual ui::Dataspace getDataSpace() const { return ui::Dataspace::UNKNOWN; }
 
     // Before color management is introduced, contents on Android have to be
     // desaturated in order to match what they appears like visually.
@@ -382,7 +378,7 @@
     // creates its tracks by buffer id and has no way of associating a buffer back to the process
     // that created it, the current implementation is only sufficient for cases where a buffer is
     // only used within a single layer.
-    uint64_t getCurrentBufferId() const { return mActiveBuffer ? mActiveBuffer->getId() : 0; }
+    uint64_t getCurrentBufferId() const { return getBuffer() ? getBuffer()->getId() : 0; }
 
     // -----------------------------------------------------------------------
     // Virtuals
@@ -475,7 +471,7 @@
      */
     bool onPreComposition(nsecs_t) override;
     void latchCompositionState(compositionengine::LayerFECompositionState&,
-                               bool includeGeometry) const override;
+                               compositionengine::LayerFE::StateSubset subset) const override;
     void latchCursorCompositionState(compositionengine::LayerFECompositionState&) const override;
     std::optional<renderengine::LayerSettings> prepareClientComposition(
             compositionengine::LayerFE::ClientCompositionTargetSettings&) override;
@@ -483,6 +479,7 @@
     const char* getDebugName() const override;
 
 protected:
+    void latchBasicGeometry(compositionengine::LayerFECompositionState& outState) const;
     void latchGeometry(compositionengine::LayerFECompositionState& outState) const;
     virtual void latchPerFrameState(compositionengine::LayerFECompositionState& outState) const;
 
@@ -519,30 +516,6 @@
     uint32_t doTransaction(uint32_t transactionFlags);
 
     /*
-     * setVisibleRegion - called to set the new visible region. This gives
-     * a chance to update the new visible region or record the fact it changed.
-     */
-    void setVisibleRegion(const Region& visibleRegion);
-
-    /*
-     * setCoveredRegion - called when the covered region changes. The covered
-     * region corresponds to any area of the surface that is covered
-     * (transparently or not) by another surface.
-     */
-    void setCoveredRegion(const Region& coveredRegion);
-
-    /*
-     * setVisibleNonTransparentRegion - called when the visible and
-     * non-transparent region changes.
-     */
-    void setVisibleNonTransparentRegion(const Region& visibleNonTransparentRegion);
-
-    /*
-     * Clear the visible, covered, and non-transparent regions.
-     */
-    void clearVisibilityRegions();
-
-    /*
      * latchBuffer - called each time the screen is redrawn and returns whether
      * the visible regions need to be recomputed (this is a fairly heavy
      * operation, so this should be set only if needed). Typically this is used
@@ -587,7 +560,14 @@
      * returns the rectangle that crops the content of the layer and scales it
      * to the layer's size.
      */
-    Rect getContentCrop() const;
+    virtual Rect getBufferCrop() const { return Rect(); }
+
+    /*
+     * Returns the transform applied to the buffer.
+     */
+    virtual uint32_t getBufferTransform() const { return 0; }
+
+    virtual sp<GraphicBuffer> getBuffer() const { return nullptr; }
 
     /*
      * Returns if a frame is ready
@@ -685,6 +665,8 @@
     compositionengine::OutputLayer* findOutputLayerForDisplay(
             const sp<const DisplayDevice>& display) const;
 
+    Region debugGetVisibleRegionOnDefaultDisplay() const;
+
 protected:
     // constant
     sp<SurfaceFlinger> mFlinger;
@@ -839,16 +821,10 @@
 
     // main thread
     sp<NativeHandle> mSidebandStream;
-    // Active buffer fields
-    sp<GraphicBuffer> mActiveBuffer;
-    sp<Fence> mActiveBufferFence;
     // False if the buffer and its contents have been previously used for GPU
     // composition, true otherwise.
     bool mIsActiveBufferUpdatedForGpu = true;
 
-    ui::Dataspace mCurrentDataSpace = ui::Dataspace::UNKNOWN;
-    Rect mCurrentCrop;
-    uint32_t mCurrentTransform{0};
     // We encode unset as -1.
     int32_t mOverrideScalingMode{-1};
     std::atomic<uint64_t> mCurrentFrameNumber{0};
@@ -869,8 +845,6 @@
     // This layer can be a cursor on some displays.
     bool mPotentialCursor{false};
 
-    bool mFreezeGeometryUpdates{false};
-
     // Child list about to be committed/used for editing.
     LayerVector mCurrentChildren{LayerVector::StateSet::Current};
     // Child list used for rendering.
diff --git a/services/surfaceflinger/LayerRejecter.cpp b/services/surfaceflinger/LayerRejecter.cpp
index 72abea8..8a22183 100644
--- a/services/surfaceflinger/LayerRejecter.cpp
+++ b/services/surfaceflinger/LayerRejecter.cpp
@@ -23,22 +23,16 @@
 
 namespace android {
 
-LayerRejecter::LayerRejecter(Layer::State& front,
-                             Layer::State& current,
-                             bool& recomputeVisibleRegions,
-                             bool stickySet,
-                             const char* name,
-                             int32_t overrideScalingMode,
-                             bool transformToDisplayInverse,
-                             bool& freezePositionUpdates)
-  : mFront(front),
-    mCurrent(current),
-    mRecomputeVisibleRegions(recomputeVisibleRegions),
-    mStickyTransformSet(stickySet),
-    mName(name),
-    mOverrideScalingMode(overrideScalingMode),
-    mTransformToDisplayInverse(transformToDisplayInverse),
-    mFreezeGeometryUpdates(freezePositionUpdates) {}
+LayerRejecter::LayerRejecter(Layer::State& front, Layer::State& current,
+                             bool& recomputeVisibleRegions, bool stickySet, const char* name,
+                             int32_t overrideScalingMode, bool transformToDisplayInverse)
+      : mFront(front),
+        mCurrent(current),
+        mRecomputeVisibleRegions(recomputeVisibleRegions),
+        mStickyTransformSet(stickySet),
+        mName(name),
+        mOverrideScalingMode(overrideScalingMode),
+        mTransformToDisplayInverse(transformToDisplayInverse) {}
 
 bool LayerRejecter::reject(const sp<GraphicBuffer>& buf, const BufferItem& item) {
     if (buf == nullptr) {
@@ -83,8 +77,6 @@
             // recompute visible region
             mRecomputeVisibleRegions = true;
 
-            mFreezeGeometryUpdates = false;
-
             if (mFront.crop_legacy != mFront.requestedCrop_legacy) {
                 mFront.crop_legacy = mFront.requestedCrop_legacy;
                 mCurrent.crop_legacy = mFront.requestedCrop_legacy;
diff --git a/services/surfaceflinger/LayerRejecter.h b/services/surfaceflinger/LayerRejecter.h
index 63d51de..1bd0c26 100644
--- a/services/surfaceflinger/LayerRejecter.h
+++ b/services/surfaceflinger/LayerRejecter.h
@@ -23,14 +23,9 @@
 namespace android {
     class LayerRejecter : public BufferLayerConsumer::BufferRejecter {
     public:
-        LayerRejecter(Layer::State &front,
-                      Layer::State &current,
-                      bool &recomputeVisibleRegions,
-                      bool stickySet,
-                      const char *name,
-                      int32_t overrideScalingMode,
-                      bool transformToDisplayInverse,
-                      bool &freezePositionUpdates);
+        LayerRejecter(Layer::State &front, Layer::State &current, bool &recomputeVisibleRegions,
+                      bool stickySet, const char *name, int32_t overrideScalingMode,
+                      bool transformToDisplayInverse);
 
         virtual bool reject(const sp<GraphicBuffer> &buf, const BufferItem &item);
 
@@ -42,7 +37,6 @@
         const char *mName;
         int32_t mOverrideScalingMode;
         bool mTransformToDisplayInverse;
-        bool &mFreezeGeometryUpdates;
     };
 }  // namespace android
 
diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp
index 5b4bec9..976fedb 100644
--- a/services/surfaceflinger/RefreshRateOverlay.cpp
+++ b/services/surfaceflinger/RefreshRateOverlay.cpp
@@ -39,7 +39,7 @@
 
     Mutex::Autolock _l(mFlinger.mStateLock);
     mLayer = mClient->getLayerUser(mIBinder);
-    mLayer->setCrop_legacy(Rect(50, 70, 200, 100), true);
+    mLayer->setCrop_legacy(Rect(50, 70, 200, 100));
 
     // setting Layer's Z requires resorting layersSortedByZ
     ssize_t idx = mFlinger.mCurrentState.layersSortedByZ.indexOf(mLayer);
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index eb52d3f..e2a880a 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -514,8 +514,13 @@
     // Content detection is on, find the appropriate refresh rate with minimal error
     // TODO(b/139751853): Scan allowed refresh rates only (SurfaceFlinger::mAllowedDisplayConfigs)
     const float rate = static_cast<float>(mFeatures.contentRefreshRate);
-    auto iter = min_element(mRefreshRateConfigs.getRefreshRates().cbegin(),
-                            mRefreshRateConfigs.getRefreshRates().cend(),
+    auto begin = mRefreshRateConfigs.getRefreshRates().cbegin();
+
+    // Skip POWER_SAVING config as it is not a real config
+    if (begin->first == RefreshRateType::POWER_SAVING) {
+        ++begin;
+    }
+    auto iter = min_element(begin, mRefreshRateConfigs.getRefreshRates().cend(),
                             [rate](const auto& lhs, const auto& rhs) -> bool {
                                 return std::abs(lhs.second->fps - rate) <
                                         std::abs(rhs.second->fps - rate);
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 914a79d..4361a94 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -112,6 +112,7 @@
 
 #include <cutils/compiler.h>
 
+#include "android-base/parseint.h"
 #include "android-base/stringprintf.h"
 
 #include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
@@ -2757,11 +2758,22 @@
             return;
         }
 
-        // start with the whole surface at its current location
-        const Layer::State& s(layer->getDrawingState());
+        // Note: Converts a wp<LayerFE> to a sp<LayerFE>
+        auto layerFE = compositionLayer->getLayerFE();
+        if (layerFE == nullptr) {
+            return;
+        }
+
+        // Request a snapshot of the subset of state relevant to visibility
+        // determination
+        layerFE->latchCompositionState(compositionLayer->editState().frontEnd,
+                                       compositionengine::LayerFE::StateSubset::BasicGeometry);
+
+        // Work with a read-only copy of the snapshot
+        const auto& layerFEState = compositionLayer->getState().frontEnd;
 
         // only consider the layers on the given layer stack
-        if (!display->belongsInOutput(layer->getLayerStack(), layer->getPrimaryDisplayOnly())) {
+        if (!display->belongsInOutput(layerFEState.layerStackId, layerFEState.internalOnly)) {
             return;
         }
 
@@ -2794,20 +2806,18 @@
          */
         Region transparentRegion;
 
-
         // handle hidden surfaces by setting the visible region to empty
-        if (CC_LIKELY(layer->isVisible())) {
-            const bool translucent = !layer->isOpaque(s);
-            Rect bounds(layer->getScreenBounds());
-
-            visibleRegion.set(bounds);
-            ui::Transform tr = layer->getTransform();
+        if (CC_LIKELY(layerFEState.isVisible)) {
+            // Get the visible region
+            visibleRegion.set(
+                    Rect(layerFEState.geomLayerTransform.transform(layerFEState.geomLayerBounds)));
+            const ui::Transform& tr = layerFEState.geomLayerTransform;
             if (!visibleRegion.isEmpty()) {
                 // Remove the transparent area from the visible region
-                if (translucent) {
+                if (!layerFEState.isOpaque) {
                     if (tr.preserveRects()) {
                         // transform the transparent region
-                        transparentRegion = tr.transform(layer->getActiveTransparentRegion(s));
+                        transparentRegion = tr.transform(layerFEState.transparentRegionHint);
                     } else {
                         // transformation too complex, can't do the
                         // transparent region optimization.
@@ -2817,9 +2827,8 @@
 
                 // compute the opaque region
                 const int32_t layerOrientation = tr.getOrientation();
-                if (layer->getAlpha() == 1.0f && !translucent &&
-                        layer->getRoundedCornerState().radius == 0.0f &&
-                        ((layerOrientation & ui::Transform::ROT_INVALID) == false)) {
+                if (layerFEState.isOpaque &&
+                    ((layerOrientation & ui::Transform::ROT_INVALID) == false)) {
                     // the opaque region is the layer's footprint
                     opaqueRegion = visibleRegion;
                 }
@@ -2827,7 +2836,6 @@
         }
 
         if (visibleRegion.isEmpty()) {
-            layer->clearVisibilityRegions();
             return;
         }
 
@@ -2840,13 +2848,21 @@
         // subtract the opaque region covered by the layers above us
         visibleRegion.subtractSelf(aboveOpaqueLayers);
 
+        //  Get coverage information for the layer as previously displayed
+        auto prevOutputLayer = display->getOutputLayerForLayer(compositionLayer.get());
+        // TODO(b/121291683): Define this as a constant in Region.h
+        const Region kEmptyRegion;
+        const Region& oldVisibleRegion =
+                prevOutputLayer ? prevOutputLayer->getState().visibleRegion : kEmptyRegion;
+        const Region& oldCoveredRegion =
+                prevOutputLayer ? prevOutputLayer->getState().coveredRegion : kEmptyRegion;
+
         // compute this layer's dirty region
-        if (layer->contentDirty) {
+        if (layerFEState.contentDirty) {
             // we need to invalidate the whole region
             dirty = visibleRegion;
             // as well, as the old visible region
-            dirty.orSelf(layer->visibleRegion);
-            layer->contentDirty = false;
+            dirty.orSelf(oldVisibleRegion);
         } else {
             /* compute the exposed region:
              *   the exposed region consists of two components:
@@ -2861,8 +2877,6 @@
              * exposed because of a resize.
              */
             const Region newExposed = visibleRegion - coveredRegion;
-            const Region oldVisibleRegion = layer->visibleRegion;
-            const Region oldCoveredRegion = layer->coveredRegion;
             const Region oldExposed = oldVisibleRegion - oldCoveredRegion;
             dirty = (visibleRegion&oldCoveredRegion) | (newExposed-oldExposed);
         }
@@ -2874,30 +2888,25 @@
         // Update aboveOpaqueLayers for next (lower) layer
         aboveOpaqueLayers.orSelf(opaqueRegion);
 
-        // Store the visible region in screen space
-        layer->setVisibleRegion(visibleRegion);
-        layer->setCoveredRegion(coveredRegion);
-        layer->setVisibleNonTransparentRegion(
-                visibleRegion.subtract(transparentRegion));
+        // Compute the visible non-transparent region
+        Region visibleNonTransparentRegion = visibleRegion.subtract(transparentRegion);
 
-        // Setup an output layer for this output if the layer is
-        // visible on this output
+        // Setup an output layer for this output if the layer is visible on this
+        // output
         const auto& displayState = display->getState();
-        Region drawRegion(displayState.transform.transform(layer->visibleNonTransparentRegion));
+        Region drawRegion(displayState.transform.transform(visibleNonTransparentRegion));
         drawRegion.andSelf(displayState.bounds);
         if (drawRegion.isEmpty()) {
             return;
         }
 
-        const auto displayId = displayDevice->getId();
-        sp<compositionengine::LayerFE> layerFE = compositionLayer->getLayerFE();
-        LOG_ALWAYS_FATAL_IF(layerFE.get() == nullptr);
-
-        outLayersSortedByZ.emplace_back(
-                display->getOrCreateOutputLayer(displayId, compositionLayer, layerFE));
+        outLayersSortedByZ.emplace_back(display->getOrCreateOutputLayer(compositionLayer, layerFE));
         auto& outputLayerState = outLayersSortedByZ.back()->editState();
-        outputLayerState.visibleRegion = displayState.transform.transform(
-                layer->visibleRegion.intersect(displayState.viewport));
+        outputLayerState.visibleRegion = std::move(visibleRegion);
+        outputLayerState.visibleNonTransparentRegion = std::move(visibleNonTransparentRegion);
+        outputLayerState.coveredRegion = std::move(coveredRegion);
+        outputLayerState.outputSpaceVisibleRegion = displayState.transform.transform(
+                outputLayerState.visibleRegion.intersect(displayState.viewport));
     });
 
     outOpaqueRegion = aboveOpaqueLayers;
@@ -3387,8 +3396,6 @@
     uint32_t flags = 0;
 
     const uint64_t what = s.what;
-    bool geometryAppliesWithResize =
-            what & layer_state_t::eGeometryAppliesWithResize;
 
     // If we are deferring transaction, make sure to push the pending state, as otherwise the
     // pending state will also be deferred.
@@ -3397,7 +3404,7 @@
     }
 
     if (what & layer_state_t::ePositionChanged) {
-        if (layer->setPosition(s.x, s.y, !geometryAppliesWithResize)) {
+        if (layer->setPosition(s.x, s.y)) {
             flags |= eTraversalNeeded;
         }
     }
@@ -3488,8 +3495,7 @@
             flags |= eTraversalNeeded;
     }
     if (what & layer_state_t::eCropChanged_legacy) {
-        if (layer->setCrop_legacy(s.crop_legacy, !geometryAppliesWithResize))
-            flags |= eTraversalNeeded;
+        if (layer->setCrop_legacy(s.crop_legacy)) flags |= eTraversalNeeded;
     }
     if (what & layer_state_t::eCornerRadiusChanged) {
         if (layer->setCornerRadius(s.cornerRadius))
@@ -4048,6 +4054,7 @@
                 {"--display-id"s, dumper(&SurfaceFlinger::dumpDisplayIdentificationData)},
                 {"--dispsync"s,
                  dumper([this](std::string& s) { mScheduler->getPrimaryDispSync().dump(s); })},
+                {"--edid"s, argsDumper(&SurfaceFlinger::dumpRawDisplayIdentificationData)},
                 {"--frame-events"s, dumper(&SurfaceFlinger::dumpFrameEventsLocked)},
                 {"--latency"s, argsDumper(&SurfaceFlinger::dumpStatsLocked)},
                 {"--latency-clear"s, argsDumper(&SurfaceFlinger::clearStatsLocked)},
@@ -4276,21 +4283,13 @@
         }
 
         if (!isEdid(data)) {
-            result.append("unknown identification data: ");
-            for (uint8_t byte : data) {
-                StringAppendF(&result, "%x ", byte);
-            }
-            result.append("\n");
+            result.append("unknown identification data\n");
             continue;
         }
 
         const auto edid = parseEdid(data);
         if (!edid) {
-            result.append("invalid EDID: ");
-            for (uint8_t byte : data) {
-                StringAppendF(&result, "%x ", byte);
-            }
-            result.append("\n");
+            result.append("invalid EDID\n");
             continue;
         }
 
@@ -4300,6 +4299,18 @@
     }
 }
 
+void SurfaceFlinger::dumpRawDisplayIdentificationData(const DumpArgs& args,
+                                                      std::string& result) const {
+    hwc2_display_t hwcDisplayId;
+    uint8_t port;
+    DisplayIdentificationData data;
+
+    if (args.size() > 1 && base::ParseUint(String8(args[1]), &hwcDisplayId) &&
+        getHwComposer().getDisplayIdentificationData(hwcDisplayId, &port, &data)) {
+        result.append(reinterpret_cast<const char*>(data.data()), data.size());
+    }
+}
+
 void SurfaceFlinger::dumpWideColorInfo(std::string& result) const {
     StringAppendF(&result, "Device has wide color built-in display: %d\n", hasWideColorDisplay);
     StringAppendF(&result, "Device uses color management: %d\n", useColorManagement);
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index f220c26..beb43d0 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -865,6 +865,7 @@
             std::vector<OccupancyTracker::Segment>&& history);
     void dumpBufferingStats(std::string& result) const;
     void dumpDisplayIdentificationData(std::string& result) const;
+    void dumpRawDisplayIdentificationData(const DumpArgs&, std::string& result) const;
     void dumpWideColorInfo(std::string& result) const;
     LayersProto dumpDrawingStateProto(uint32_t traceFlags = SurfaceTracing::TRACE_ALL) const;
     void dumpOffscreenLayersProto(LayersProto& layersProto,
diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp
index acb263a..d765f68 100644
--- a/services/surfaceflinger/tests/Transaction_test.cpp
+++ b/services/surfaceflinger/tests/Transaction_test.cpp
@@ -136,7 +136,9 @@
                                            int32_t bufferWidth, int32_t bufferHeight) {
         ANativeWindow_Buffer buffer;
         ASSERT_NO_FATAL_FAILURE(buffer = getBufferQueueLayerBuffer(layer));
-        fillANativeWindowBufferColor(buffer, Rect(0, 0, bufferWidth, bufferHeight), color);
+        TransactionUtils::fillANativeWindowBufferColor(buffer,
+                                                       Rect(0, 0, bufferWidth, bufferHeight),
+                                                       color);
         postBufferQueueLayerBuffer(layer);
     }
 
@@ -147,7 +149,8 @@
                                   BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
                                           BufferUsage::COMPOSER_OVERLAY,
                                   "test");
-        fillGraphicBufferColor(buffer, Rect(0, 0, bufferWidth, bufferHeight), color);
+        TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, bufferWidth, bufferHeight),
+                                                 color);
         Transaction().setBuffer(layer, buffer).apply();
     }
 
@@ -193,11 +196,15 @@
 
         const int32_t halfW = bufferWidth / 2;
         const int32_t halfH = bufferHeight / 2;
-        fillANativeWindowBufferColor(buffer, Rect(0, 0, halfW, halfH), topLeft);
-        fillANativeWindowBufferColor(buffer, Rect(halfW, 0, bufferWidth, halfH), topRight);
-        fillANativeWindowBufferColor(buffer, Rect(0, halfH, halfW, bufferHeight), bottomLeft);
-        fillANativeWindowBufferColor(buffer, Rect(halfW, halfH, bufferWidth, bufferHeight),
-                                     bottomRight);
+        TransactionUtils::fillANativeWindowBufferColor(buffer, Rect(0, 0, halfW, halfH), topLeft);
+        TransactionUtils::fillANativeWindowBufferColor(buffer, Rect(halfW, 0, bufferWidth, halfH),
+                                                       topRight);
+        TransactionUtils::fillANativeWindowBufferColor(buffer, Rect(0, halfH, halfW, bufferHeight),
+                                                       bottomLeft);
+        TransactionUtils::fillANativeWindowBufferColor(buffer,
+                                                       Rect(halfW, halfH, bufferWidth,
+                                                            bufferHeight),
+                                                       bottomRight);
 
         postBufferQueueLayerBuffer(layer);
     }
@@ -216,10 +223,14 @@
 
         const int32_t halfW = bufferWidth / 2;
         const int32_t halfH = bufferHeight / 2;
-        fillGraphicBufferColor(buffer, Rect(0, 0, halfW, halfH), topLeft);
-        fillGraphicBufferColor(buffer, Rect(halfW, 0, bufferWidth, halfH), topRight);
-        fillGraphicBufferColor(buffer, Rect(0, halfH, halfW, bufferHeight), bottomLeft);
-        fillGraphicBufferColor(buffer, Rect(halfW, halfH, bufferWidth, bufferHeight), bottomRight);
+        TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, halfW, halfH), topLeft);
+        TransactionUtils::fillGraphicBufferColor(buffer, Rect(halfW, 0, bufferWidth, halfH),
+                                                 topRight);
+        TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, halfH, halfW, bufferHeight),
+                                                 bottomLeft);
+        TransactionUtils::fillGraphicBufferColor(buffer,
+                                                 Rect(halfW, halfH, bufferWidth, bufferHeight),
+                                                 bottomRight);
 
         Transaction().setBuffer(layer, buffer).setSize(layer, bufferWidth, bufferHeight).apply();
     }
@@ -551,62 +562,6 @@
     }
 }
 
-TEST_P(LayerRenderTypeTransactionTest, SetPositionWithNextResize_BufferQueue) {
-    sp<SurfaceControl> layer;
-    ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
-    ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
-
-    // request setPosition to be applied with the next resize
-    Transaction().setPosition(layer, 5, 10).setGeometryAppliesWithResize(layer).apply();
-    {
-        SCOPED_TRACE("new position pending");
-        getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::RED);
-    }
-
-    Transaction().setPosition(layer, 15, 20).apply();
-    {
-        SCOPED_TRACE("pending new position modified");
-        getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::RED);
-    }
-
-    Transaction().setSize(layer, 64, 64).apply();
-    {
-        SCOPED_TRACE("resize pending");
-        getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::RED);
-    }
-
-    // finally resize and latch the buffer
-    ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 64, 64));
-    {
-        SCOPED_TRACE("new position applied");
-        getScreenCapture()->expectColor(Rect(15, 20, 79, 84), Color::RED);
-    }
-}
-
-TEST_P(LayerRenderTypeTransactionTest, SetPositionWithNextResizeScaleToWindow_BufferQueue) {
-    sp<SurfaceControl> layer;
-    ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
-    ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
-
-    // setPosition is not immediate even with SCALE_TO_WINDOW override
-    Transaction()
-            .setPosition(layer, 5, 10)
-            .setSize(layer, 64, 64)
-            .setOverrideScalingMode(layer, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW)
-            .setGeometryAppliesWithResize(layer)
-            .apply();
-    {
-        SCOPED_TRACE("new position pending");
-        getScreenCapture()->expectColor(Rect(0, 0, 64, 64), Color::RED);
-    }
-
-    ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 64, 64));
-    {
-        SCOPED_TRACE("new position applied");
-        getScreenCapture()->expectColor(Rect(5, 10, 69, 74), Color::RED);
-    }
-}
-
 TEST_P(LayerRenderTypeTransactionTest, SetSizeBasic_BufferQueue) {
     sp<SurfaceControl> layer;
     ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
@@ -1093,8 +1048,10 @@
 
     ANativeWindow_Buffer buffer;
     ASSERT_NO_FATAL_FAILURE(buffer = getBufferQueueLayerBuffer(layer));
-    ASSERT_NO_FATAL_FAILURE(fillANativeWindowBufferColor(buffer, top, Color::TRANSPARENT));
-    ASSERT_NO_FATAL_FAILURE(fillANativeWindowBufferColor(buffer, bottom, Color::RED));
+    ASSERT_NO_FATAL_FAILURE(
+            TransactionUtils::fillANativeWindowBufferColor(buffer, top, Color::TRANSPARENT));
+    ASSERT_NO_FATAL_FAILURE(
+            TransactionUtils::fillANativeWindowBufferColor(buffer, bottom, Color::RED));
     // setTransparentRegionHint always applies to the following buffer
     Transaction().setTransparentRegionHint(layer, Region(top)).apply();
     ASSERT_NO_FATAL_FAILURE(postBufferQueueLayerBuffer(layer));
@@ -1114,8 +1071,10 @@
     }
 
     ASSERT_NO_FATAL_FAILURE(buffer = getBufferQueueLayerBuffer(layer));
-    ASSERT_NO_FATAL_FAILURE(fillANativeWindowBufferColor(buffer, top, Color::RED));
-    ASSERT_NO_FATAL_FAILURE(fillANativeWindowBufferColor(buffer, bottom, Color::TRANSPARENT));
+    ASSERT_NO_FATAL_FAILURE(
+            TransactionUtils::fillANativeWindowBufferColor(buffer, top, Color::RED));
+    ASSERT_NO_FATAL_FAILURE(
+            TransactionUtils::fillANativeWindowBufferColor(buffer, bottom, Color::TRANSPARENT));
     ASSERT_NO_FATAL_FAILURE(postBufferQueueLayerBuffer(layer));
     {
         SCOPED_TRACE("bottom transparent");
@@ -1138,8 +1097,9 @@
                                       BufferUsage::COMPOSER_OVERLAY,
                               "test");
 
-    ASSERT_NO_FATAL_FAILURE(fillGraphicBufferColor(buffer, top, Color::TRANSPARENT));
-    ASSERT_NO_FATAL_FAILURE(fillGraphicBufferColor(buffer, bottom, Color::RED));
+    ASSERT_NO_FATAL_FAILURE(
+            TransactionUtils::fillGraphicBufferColor(buffer, top, Color::TRANSPARENT));
+    ASSERT_NO_FATAL_FAILURE(TransactionUtils::fillGraphicBufferColor(buffer, bottom, Color::RED));
     Transaction()
             .setTransparentRegionHint(layer, Region(top))
             .setBuffer(layer, buffer)
@@ -1165,8 +1125,9 @@
                                        BufferUsage::COMPOSER_OVERLAY,
                                "test");
 
-    ASSERT_NO_FATAL_FAILURE(fillGraphicBufferColor(buffer, top, Color::RED));
-    ASSERT_NO_FATAL_FAILURE(fillGraphicBufferColor(buffer, bottom, Color::TRANSPARENT));
+    ASSERT_NO_FATAL_FAILURE(TransactionUtils::fillGraphicBufferColor(buffer, top, Color::RED));
+    ASSERT_NO_FATAL_FAILURE(
+            TransactionUtils::fillGraphicBufferColor(buffer, bottom, Color::TRANSPARENT));
     Transaction().setBuffer(layer, buffer).apply();
     {
         SCOPED_TRACE("bottom transparent");
@@ -1907,8 +1868,8 @@
                               BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
                                       BufferUsage::COMPOSER_OVERLAY,
                               "test");
-    fillGraphicBufferColor(buffer, Rect(0, 0, 32, 16), Color::BLUE);
-    fillGraphicBufferColor(buffer, Rect(0, 16, 32, 64), Color::RED);
+    TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, 32, 16), Color::BLUE);
+    TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 16, 32, 64), Color::RED);
 
     Transaction().setFrame(layer, Rect(0, 0, 64, 64)).apply();
 
@@ -2008,74 +1969,6 @@
     }
 }
 
-TEST_P(LayerRenderTypeTransactionTest, SetCropWithNextResize_BufferQueue) {
-    sp<SurfaceControl> layer;
-    ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
-    ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
-
-    // request setCrop_legacy to be applied with the next resize
-    Transaction()
-            .setCrop_legacy(layer, Rect(8, 8, 24, 24))
-            .setGeometryAppliesWithResize(layer)
-            .apply();
-    {
-        SCOPED_TRACE("waiting for next resize");
-        getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::RED);
-    }
-
-    Transaction().setCrop_legacy(layer, Rect(4, 4, 12, 12)).apply();
-    {
-        SCOPED_TRACE("pending crop modified");
-        getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::RED);
-    }
-
-    Transaction().setSize(layer, 16, 16).apply();
-    {
-        SCOPED_TRACE("resize pending");
-        getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::RED);
-    }
-
-    // finally resize
-    ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 16, 16));
-    {
-        SCOPED_TRACE("new crop applied");
-        auto shot = getScreenCapture();
-        shot->expectColor(Rect(4, 4, 12, 12), Color::RED);
-        shot->expectBorder(Rect(4, 4, 12, 12), Color::BLACK);
-    }
-}
-
-TEST_P(LayerRenderTypeTransactionTest, SetCropWithNextResizeScaleToWindow_BufferQueue) {
-    sp<SurfaceControl> layer;
-    ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
-    ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
-
-    // setCrop_legacy is not immediate even with SCALE_TO_WINDOW override
-    Transaction()
-            .setCrop_legacy(layer, Rect(4, 4, 12, 12))
-            .setSize(layer, 16, 16)
-            .setOverrideScalingMode(layer, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW)
-            .setGeometryAppliesWithResize(layer)
-            .apply();
-    {
-        SCOPED_TRACE("new crop pending");
-        auto shot = getScreenCapture();
-        shot->expectColor(Rect(0, 0, 16, 16), Color::RED);
-        shot->expectBorder(Rect(0, 0, 16, 16), Color::BLACK);
-    }
-
-    // XXX crop is never latched without other geometry change (b/69315677)
-    Transaction().setPosition(layer, 1, 0).setGeometryAppliesWithResize(layer).apply();
-    ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 16, 16));
-    Transaction().setPosition(layer, 0, 0).apply();
-    {
-        SCOPED_TRACE("new crop applied");
-        auto shot = getScreenCapture();
-        shot->expectColor(Rect(4, 4, 12, 12), Color::RED);
-        shot->expectBorder(Rect(4, 4, 12, 12), Color::BLACK);
-    }
-}
-
 TEST_P(LayerRenderTypeTransactionTest, SetFrameBasic_BufferState) {
     sp<SurfaceControl> layer;
     ASSERT_NO_FATAL_FAILURE(
@@ -2302,7 +2195,7 @@
                                            BufferUsage::COMPOSER_OVERLAY,
                                    "test");
         Color color = colors[idx % colors.size()];
-        fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), color);
+        TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), color);
         idx++;
     }
 
@@ -2338,7 +2231,7 @@
                                            BufferUsage::COMPOSER_OVERLAY,
                                    "test");
         Color color = colors[idx % colors.size()];
-        fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), color);
+        TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), color);
         idx++;
     }
 
@@ -2374,7 +2267,7 @@
                                            BufferUsage::COMPOSER_OVERLAY,
                                    "test");
         Color color = colors[idx % colors.size()];
-        fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), color);
+        TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), color);
         idx++;
     }
 
@@ -2471,7 +2364,7 @@
                               BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
                                       BufferUsage::COMPOSER_OVERLAY,
                               "test");
-    fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::RED);
+    TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::RED);
 
     sp<Fence> fence;
     if (getBuffer(nullptr, &fence) != NO_ERROR) {
@@ -2500,7 +2393,7 @@
                               BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
                                       BufferUsage::COMPOSER_OVERLAY,
                               "test");
-    fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::RED);
+    TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::RED);
 
     sp<Fence> fence = Fence::NO_FENCE;
 
@@ -2524,7 +2417,7 @@
                               BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
                                       BufferUsage::COMPOSER_OVERLAY,
                               "test");
-    fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::RED);
+    TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::RED);
 
     Transaction()
             .setBuffer(layer, buffer)
@@ -2546,7 +2439,7 @@
                               BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
                                       BufferUsage::COMPOSER_OVERLAY,
                               "test");
-    fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::RED);
+    TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::RED);
 
     HdrMetadata hdrMetadata;
     hdrMetadata.validTypes = 0;
@@ -2570,7 +2463,7 @@
                               BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
                                       BufferUsage::COMPOSER_OVERLAY,
                               "test");
-    fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::RED);
+    TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::RED);
 
     Region region;
     region.set(32, 32);
@@ -2594,7 +2487,7 @@
                               BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
                                       BufferUsage::COMPOSER_OVERLAY,
                               "test");
-    fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::RED);
+    TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::RED);
 
     Transaction()
             .setBuffer(layer, buffer)
@@ -3661,7 +3554,7 @@
                                                displayHeight, 0);
         ASSERT_TRUE(mBGSurfaceControl != nullptr);
         ASSERT_TRUE(mBGSurfaceControl->isValid());
-        fillSurfaceRGBA8(mBGSurfaceControl, 63, 63, 195);
+        TransactionUtils::fillSurfaceRGBA8(mBGSurfaceControl, 63, 63, 195);
 
         // Foreground surface
         mFGSurfaceControl = createLayer(String8("FG Test Surface"), 64, 64, 0);
@@ -3669,14 +3562,14 @@
         ASSERT_TRUE(mFGSurfaceControl != nullptr);
         ASSERT_TRUE(mFGSurfaceControl->isValid());
 
-        fillSurfaceRGBA8(mFGSurfaceControl, 195, 63, 63);
+        TransactionUtils::fillSurfaceRGBA8(mFGSurfaceControl, 195, 63, 63);
 
         // Synchronization surface
         mSyncSurfaceControl = createLayer(String8("Sync Test Surface"), 1, 1, 0);
         ASSERT_TRUE(mSyncSurfaceControl != nullptr);
         ASSERT_TRUE(mSyncSurfaceControl->isValid());
 
-        fillSurfaceRGBA8(mSyncSurfaceControl, 31, 31, 31);
+        TransactionUtils::fillSurfaceRGBA8(mSyncSurfaceControl, 31, 31, 31);
 
         asTransaction([&](Transaction& t) {
             t.setDisplayLayerStack(display, 0);
@@ -3705,9 +3598,9 @@
         // posting three buffers to it should ensure that at least two
         // SurfaceFlinger::handlePageFlip calls have been made, which should
         // guaranteed that a buffer posted to another Surface has been retired.
-        fillSurfaceRGBA8(mSyncSurfaceControl, 31, 31, 31);
-        fillSurfaceRGBA8(mSyncSurfaceControl, 31, 31, 31);
-        fillSurfaceRGBA8(mSyncSurfaceControl, 31, 31, 31);
+        TransactionUtils::fillSurfaceRGBA8(mSyncSurfaceControl, 31, 31, 31);
+        TransactionUtils::fillSurfaceRGBA8(mSyncSurfaceControl, 31, 31, 31);
+        TransactionUtils::fillSurfaceRGBA8(mSyncSurfaceControl, 31, 31, 31);
     }
 
 
@@ -3724,7 +3617,7 @@
     std::unique_ptr<ScreenCapture> sc;
 
     sp<SurfaceControl> relative = createLayer(String8("relativeTestSurface"), 10, 10, 0);
-    fillSurfaceRGBA8(relative, 10, 10, 10);
+    TransactionUtils::fillSurfaceRGBA8(relative, 10, 10, 10);
     waitForPostedBuffers();
 
     Transaction{}
@@ -3765,7 +3658,9 @@
         sc->expectBGColor(128, 128);
     }
 
-    void lockAndFillFGBuffer() { fillSurfaceRGBA8(mFGSurfaceControl, 195, 63, 63, false); }
+    void lockAndFillFGBuffer() {
+        TransactionUtils::fillSurfaceRGBA8(mFGSurfaceControl, 195, 63, 63, false);
+    }
 
     void unlockFGBuffer() {
         sp<Surface> s = mFGSurfaceControl->getSurface();
@@ -3774,7 +3669,7 @@
     }
 
     void completeFGResize() {
-        fillSurfaceRGBA8(mFGSurfaceControl, 195, 63, 63);
+        TransactionUtils::fillSurfaceRGBA8(mFGSurfaceControl, 195, 63, 63);
         waitForPostedBuffers();
     }
     void restoreInitialState() {
@@ -3842,7 +3737,7 @@
     }
 
     // should trigger the first deferred transaction, but not the second one
-    fillSurfaceRGBA8(mSyncSurfaceControl, 31, 31, 31);
+    TransactionUtils::fillSurfaceRGBA8(mSyncSurfaceControl, 31, 31, 31);
     {
         SCOPED_TRACE("after first trigger");
         ScreenCapture::captureScreen(&sc);
@@ -3855,7 +3750,7 @@
     asTransaction([&](Transaction& t) { t.setAlpha(mFGSurfaceControl, 1.0); });
 
     // trigger the second deferred transaction
-    fillSurfaceRGBA8(mSyncSurfaceControl, 31, 31, 31);
+    TransactionUtils::fillSurfaceRGBA8(mSyncSurfaceControl, 31, 31, 31);
     {
         SCOPED_TRACE("after second trigger");
         ScreenCapture::captureScreen(&sc);
@@ -3873,7 +3768,7 @@
                           PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
     sp<SurfaceControl> childBuffer = createSurface(mClient, "Buffered child", 20, 20,
                                                    PIXEL_FORMAT_RGBA_8888, 0, childNoBuffer.get());
-    fillSurfaceRGBA8(childBuffer, 200, 200, 200);
+    TransactionUtils::fillSurfaceRGBA8(childBuffer, 200, 200, 200);
     SurfaceComposerClient::Transaction{}
             .setCrop_legacy(childNoBuffer, Rect(0, 0, 10, 10))
             .show(childNoBuffer)
@@ -3948,7 +3843,7 @@
         LayerUpdateTest::SetUp();
         mChild = createSurface(mClient, "Child surface", 10, 15, PIXEL_FORMAT_RGBA_8888, 0,
                                mFGSurfaceControl.get());
-        fillSurfaceRGBA8(mChild, 200, 200, 200);
+        TransactionUtils::fillSurfaceRGBA8(mChild, 200, 200, 200);
 
         {
             SCOPED_TRACE("before anything");
@@ -4079,9 +3974,9 @@
 }
 
 TEST_F(ChildLayerTest, ChildLayerAlpha) {
-    fillSurfaceRGBA8(mBGSurfaceControl, 0, 0, 254);
-    fillSurfaceRGBA8(mFGSurfaceControl, 254, 0, 0);
-    fillSurfaceRGBA8(mChild, 0, 254, 0);
+    TransactionUtils::fillSurfaceRGBA8(mBGSurfaceControl, 0, 0, 254);
+    TransactionUtils::fillSurfaceRGBA8(mFGSurfaceControl, 254, 0, 0);
+    TransactionUtils::fillSurfaceRGBA8(mChild, 0, 254, 0);
     waitForPostedBuffers();
 
     asTransaction([&](Transaction& t) {
@@ -4149,7 +4044,7 @@
 TEST_F(ChildLayerTest, ChildrenSurviveParentDestruction) {
     sp<SurfaceControl> mGrandChild =
             createSurface(mClient, "Grand Child", 10, 10, PIXEL_FORMAT_RGBA_8888, 0, mChild.get());
-    fillSurfaceRGBA8(mGrandChild, 111, 111, 111);
+    TransactionUtils::fillSurfaceRGBA8(mGrandChild, 111, 111, 111);
 
     {
         SCOPED_TRACE("Grandchild visible");
@@ -4179,7 +4074,7 @@
 TEST_F(ChildLayerTest, ChildrenRelativeZSurvivesParentDestruction) {
     sp<SurfaceControl> mGrandChild =
             createSurface(mClient, "Grand Child", 10, 10, PIXEL_FORMAT_RGBA_8888, 0, mChild.get());
-    fillSurfaceRGBA8(mGrandChild, 111, 111, 111);
+    TransactionUtils::fillSurfaceRGBA8(mGrandChild, 111, 111, 111);
 
     // draw grand child behind the foreground surface
     asTransaction([&](Transaction& t) {
@@ -4244,7 +4139,7 @@
 
     ASSERT_TRUE(mChildNewClient->isValid());
 
-    fillSurfaceRGBA8(mChildNewClient, 200, 200, 200);
+    TransactionUtils::fillSurfaceRGBA8(mChildNewClient, 200, 200, 200);
 
     asTransaction([&](Transaction& t) {
         t.hide(mChild);
@@ -4285,7 +4180,7 @@
     ASSERT_TRUE(childNewClient != nullptr);
     ASSERT_TRUE(childNewClient->isValid());
 
-    fillSurfaceRGBA8(childNewClient, 200, 200, 200);
+    TransactionUtils::fillSurfaceRGBA8(childNewClient, 200, 200, 200);
 
     Transaction()
             .hide(mChild)
@@ -4339,7 +4234,7 @@
     ASSERT_TRUE(childNewClient != nullptr);
     ASSERT_TRUE(childNewClient->isValid());
 
-    fillSurfaceRGBA8(childNewClient, 200, 200, 200);
+    TransactionUtils::fillSurfaceRGBA8(childNewClient, 200, 200, 200);
 
     Transaction()
             .hide(mChild)
@@ -4428,7 +4323,7 @@
     auto anw = static_cast<ANativeWindow*>(s.get());
     native_window_set_buffers_transform(anw, NATIVE_WINDOW_TRANSFORM_ROT_90);
     native_window_set_buffers_dimensions(anw, 64, 128);
-    fillSurfaceRGBA8(mFGSurfaceControl, 195, 63, 63);
+    TransactionUtils::fillSurfaceRGBA8(mFGSurfaceControl, 195, 63, 63);
     waitForPostedBuffers();
 
     {
@@ -4448,7 +4343,7 @@
         t.setPosition(mFGSurfaceControl, 0, 0);
         t.setSize(mChild, 100, 100);
     });
-    fillSurfaceRGBA8(mChild, 200, 200, 200);
+    TransactionUtils::fillSurfaceRGBA8(mChild, 200, 200, 200);
 
     {
         mCapture = screenshot();
@@ -4464,7 +4359,7 @@
     // Apply a 90 transform on the buffer.
     native_window_set_buffers_transform(anw, NATIVE_WINDOW_TRANSFORM_ROT_90);
     native_window_set_buffers_dimensions(anw, 64, 128);
-    fillSurfaceRGBA8(mFGSurfaceControl, 195, 63, 63);
+    TransactionUtils::fillSurfaceRGBA8(mFGSurfaceControl, 195, 63, 63);
     waitForPostedBuffers();
 
     // The child should be cropped by the new parent bounds.
@@ -4485,7 +4380,7 @@
         t.setPosition(mFGSurfaceControl, 0, 0);
         t.setSize(mChild, 200, 200);
     });
-    fillSurfaceRGBA8(mChild, 200, 200, 200);
+    TransactionUtils::fillSurfaceRGBA8(mChild, 200, 200, 200);
 
     {
         mCapture = screenshot();
@@ -4537,7 +4432,7 @@
     // have an effective scale of 2.0 applied to the buffer along with a rotation transform.
     native_window_set_buffers_transform(anw, NATIVE_WINDOW_TRANSFORM_ROT_90);
     native_window_set_buffers_dimensions(anw, 32, 64);
-    fillSurfaceRGBA8(mFGSurfaceControl, 195, 63, 63);
+    TransactionUtils::fillSurfaceRGBA8(mFGSurfaceControl, 195, 63, 63);
     waitForPostedBuffers();
 
     // The child should ignore the buffer transform but apply the 2.0 scale from parent.
@@ -4570,13 +4465,13 @@
     // frame because SurfaceFlinger would never process the deferred transaction and would therefore
     // never acquire/release the first buffer
     ALOGI("Filling 1");
-    fillSurfaceRGBA8(mFGSurfaceControl, 0, 255, 0);
+    TransactionUtils::fillSurfaceRGBA8(mFGSurfaceControl, 0, 255, 0);
     ALOGI("Filling 2");
-    fillSurfaceRGBA8(mFGSurfaceControl, 0, 0, 255);
+    TransactionUtils::fillSurfaceRGBA8(mFGSurfaceControl, 0, 0, 255);
     ALOGI("Filling 3");
-    fillSurfaceRGBA8(mFGSurfaceControl, 255, 0, 0);
+    TransactionUtils::fillSurfaceRGBA8(mFGSurfaceControl, 255, 0, 0);
     ALOGI("Filling 4");
-    fillSurfaceRGBA8(mFGSurfaceControl, 0, 255, 0);
+    TransactionUtils::fillSurfaceRGBA8(mFGSurfaceControl, 0, 255, 0);
 }
 
 TEST_F(ChildLayerTest, Reparent) {
@@ -4641,7 +4536,7 @@
     ASSERT_TRUE(newSurface != nullptr);
     ASSERT_TRUE(newSurface->isValid());
 
-    fillSurfaceRGBA8(newSurface, 63, 195, 63);
+    TransactionUtils::fillSurfaceRGBA8(newSurface, 63, 195, 63);
     asTransaction([&](Transaction& t) {
         t.hide(mChild);
         t.show(newSurface);
@@ -4673,7 +4568,7 @@
 TEST_F(ChildLayerTest, NestedChildren) {
     sp<SurfaceControl> grandchild = createSurface(mClient, "Grandchild surface", 10, 10,
                                                   PIXEL_FORMAT_RGBA_8888, 0, mChild.get());
-    fillSurfaceRGBA8(grandchild, 50, 50, 50);
+    TransactionUtils::fillSurfaceRGBA8(grandchild, 50, 50, 50);
 
     {
         mCapture = screenshot();
@@ -4685,7 +4580,7 @@
 
 TEST_F(ChildLayerTest, ChildLayerRelativeLayer) {
     sp<SurfaceControl> relative = createLayer(String8("Relative surface"), 128, 128, 0);
-    fillSurfaceRGBA8(relative, 255, 255, 255);
+    TransactionUtils::fillSurfaceRGBA8(relative, 255, 255, 255);
 
     Transaction t;
     t.setLayer(relative, INT32_MAX)
@@ -4922,7 +4817,7 @@
 
     sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10,
                                              PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
-    fillSurfaceRGBA8(child, 200, 200, 200);
+    TransactionUtils::fillSurfaceRGBA8(child, 200, 200, 200);
 
     SurfaceComposerClient::Transaction().show(child).apply(true);
 
@@ -4937,7 +4832,7 @@
 
     sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10,
                                              PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
-    fillSurfaceRGBA8(child, 200, 200, 200);
+    TransactionUtils::fillSurfaceRGBA8(child, 200, 200, 200);
 
     SurfaceComposerClient::Transaction().show(child).apply(true);
 
@@ -4952,10 +4847,10 @@
 
     sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10,
                                              PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
-    fillSurfaceRGBA8(child, 200, 200, 200);
+    TransactionUtils::fillSurfaceRGBA8(child, 200, 200, 200);
     sp<SurfaceControl> child2 = createSurface(mClient, "Child surface", 10, 10,
                                               PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
-    fillSurfaceRGBA8(child2, 200, 0, 200);
+    TransactionUtils::fillSurfaceRGBA8(child2, 200, 0, 200);
 
     SurfaceComposerClient::Transaction()
             .show(child)
@@ -4976,13 +4871,13 @@
 
     sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10,
                                              PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
-    fillSurfaceRGBA8(child, 200, 200, 200);
+    TransactionUtils::fillSurfaceRGBA8(child, 200, 200, 200);
     sp<SurfaceControl> child2 = createSurface(mClient, "Child surface", 10, 10,
                                               PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
-    fillSurfaceRGBA8(child2, 200, 0, 200);
+    TransactionUtils::fillSurfaceRGBA8(child2, 200, 0, 200);
     sp<SurfaceControl> child3 = createSurface(mClient, "Child surface", 10, 10,
                                               PIXEL_FORMAT_RGBA_8888, 0, child2.get());
-    fillSurfaceRGBA8(child2, 200, 0, 200);
+    TransactionUtils::fillSurfaceRGBA8(child2, 200, 0, 200);
 
     SurfaceComposerClient::Transaction()
             .show(child)
@@ -5002,7 +4897,7 @@
     sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10,
                                              PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
 
-    fillSurfaceRGBA8(child, 200, 200, 200);
+    TransactionUtils::fillSurfaceRGBA8(child, 200, 200, 200);
 
     SurfaceComposerClient::Transaction().show(child).apply(true);
 
@@ -5022,8 +4917,8 @@
                                              PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
     ASSERT_NE(nullptr, child.get()) << "failed to create surface";
     sp<SurfaceControl> relative = createLayer(String8("Relative surface"), 10, 10, 0);
-    fillSurfaceRGBA8(child, 200, 200, 200);
-    fillSurfaceRGBA8(relative, 100, 100, 100);
+    TransactionUtils::fillSurfaceRGBA8(child, 200, 200, 200);
+    TransactionUtils::fillSurfaceRGBA8(relative, 100, 100, 100);
 
     SurfaceComposerClient::Transaction()
             .show(child)
@@ -5045,8 +4940,8 @@
                                              PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
     sp<SurfaceControl> relative = createSurface(mClient, "Relative surface", 10, 10,
                                                 PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
-    fillSurfaceRGBA8(child, 200, 200, 200);
-    fillSurfaceRGBA8(relative, 100, 100, 100);
+    TransactionUtils::fillSurfaceRGBA8(child, 200, 200, 200);
+    TransactionUtils::fillSurfaceRGBA8(relative, 100, 100, 100);
 
     SurfaceComposerClient::Transaction()
             .show(child)
@@ -5075,7 +4970,7 @@
 
         mChild = createSurface(mClient, "Child surface", 10, 10, PIXEL_FORMAT_RGBA_8888, 0,
                                mFGSurfaceControl.get());
-        fillSurfaceRGBA8(mChild, 200, 200, 200);
+        TransactionUtils::fillSurfaceRGBA8(mChild, 200, 200, 200);
 
         SurfaceComposerClient::Transaction().show(mChild).apply(true);
     }
@@ -5138,12 +5033,12 @@
 
     sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10,
                                              PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
-    fillSurfaceRGBA8(child, 200, 200, 200);
+    TransactionUtils::fillSurfaceRGBA8(child, 200, 200, 200);
 
     sp<SurfaceControl> grandchild = createSurface(mClient, "Grandchild surface", 5, 5,
                                                   PIXEL_FORMAT_RGBA_8888, 0, child.get());
 
-    fillSurfaceRGBA8(grandchild, 50, 50, 50);
+    TransactionUtils::fillSurfaceRGBA8(grandchild, 50, 50, 50);
     SurfaceComposerClient::Transaction()
             .show(child)
             .setPosition(grandchild, 5, 5)
@@ -5160,7 +5055,7 @@
 TEST_F(ScreenCaptureTest, CaptureChildOnly) {
     sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10,
                                              PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
-    fillSurfaceRGBA8(child, 200, 200, 200);
+    TransactionUtils::fillSurfaceRGBA8(child, 200, 200, 200);
     auto childHandle = child->getHandle();
 
     SurfaceComposerClient::Transaction().setPosition(child, 5, 5).show(child).apply(true);
@@ -5174,12 +5069,12 @@
 TEST_F(ScreenCaptureTest, CaptureGrandchildOnly) {
     sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10,
                                              PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
-    fillSurfaceRGBA8(child, 200, 200, 200);
+    TransactionUtils::fillSurfaceRGBA8(child, 200, 200, 200);
     auto childHandle = child->getHandle();
 
     sp<SurfaceControl> grandchild = createSurface(mClient, "Grandchild surface", 5, 5,
                                                   PIXEL_FORMAT_RGBA_8888, 0, child.get());
-    fillSurfaceRGBA8(grandchild, 50, 50, 50);
+    TransactionUtils::fillSurfaceRGBA8(grandchild, 50, 50, 50);
 
     SurfaceComposerClient::Transaction()
             .show(child)
@@ -5674,8 +5569,8 @@
         ASSERT_NO_FATAL_FAILURE(slotToBuffer(slot1, &buf1));
         sp<GraphicBuffer> buf2;
         ASSERT_NO_FATAL_FAILURE(slotToBuffer(slot2, &buf2));
-        fillGraphicBufferColor(buf1, Rect(width, height), color);
-        fillGraphicBufferColor(buf2, Rect(width, height), color);
+        TransactionUtils::fillGraphicBufferColor(buf1, Rect(width, height), color);
+        TransactionUtils::fillGraphicBufferColor(buf2, Rect(width, height), color);
 
         const auto displayTime = systemTime() + milliseconds_to_nanoseconds(100);
         ASSERT_NO_FATAL_FAILURE(queue(slot1, Region::INVALID_REGION, displayTime));
diff --git a/services/surfaceflinger/tests/fakehwc/Android.bp b/services/surfaceflinger/tests/fakehwc/Android.bp
index 3e29016..9d74761 100644
--- a/services/surfaceflinger/tests/fakehwc/Android.bp
+++ b/services/surfaceflinger/tests/fakehwc/Android.bp
@@ -22,8 +22,6 @@
         "libgui",
         "libhardware",
         "libhidlbase",
-        "libhidltransport",
-        "libhwbinder",
         "liblayers_proto",
         "liblog",
         "libnativewindow",
diff --git a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp
index a892a2a..093bcf5 100644
--- a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp
+++ b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp
@@ -1331,16 +1331,6 @@
 
     restoreInitialState();
 
-    // Now we repeat with setGeometryAppliesWithResize
-    // and verify the position DOESN'T latch.
-    {
-        TransactionScope ts(*sFakeComposer);
-        ts.setGeometryAppliesWithResize(mFGSurfaceControl);
-        ts.setSize(mFGSurfaceControl, 32, 32);
-        ts.setPosition(mFGSurfaceControl, 100, 100);
-    }
-    EXPECT_TRUE(framesAreSame(mBaseFrame, sFakeComposer->getLatestFrame()));
-
     completeFGResize();
 
     auto referenceFrame2 = mBaseFrame;
@@ -1365,14 +1355,6 @@
 
     restoreInitialState();
 
-    {
-        TransactionScope ts(*sFakeComposer);
-        ts.setSize(mFGSurfaceControl, 128, 128);
-        ts.setGeometryAppliesWithResize(mFGSurfaceControl);
-        ts.setCrop_legacy(mFGSurfaceControl, Rect(0, 0, 63, 63));
-    }
-    EXPECT_TRUE(framesAreSame(mBaseFrame, sFakeComposer->getLatestFrame()));
-
     completeFGResize();
 
     auto referenceFrame2 = mBaseFrame;
diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index 425768e..20dfed6 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -614,6 +614,12 @@
                               displaySettings.clip);
                     // screen capture adds an additional color layer as an alpha
                     // prefill, so gtet the back layer.
+                    if (layerSettings.empty()) {
+                        ADD_FAILURE() << "layerSettings was not expected to be empty in "
+                                         "setupREBufferCompositionCommonCallExpectations "
+                                         "verification lambda";
+                        return NO_ERROR;
+                    }
                     renderengine::LayerSettings layer = layerSettings.back();
                     EXPECT_THAT(layer.source.buffer.buffer, Not(IsNull()));
                     EXPECT_THAT(layer.source.buffer.fence, Not(IsNull()));
@@ -657,6 +663,12 @@
                               displaySettings.clip);
                     // screen capture adds an additional color layer as an alpha
                     // prefill, so get the back layer.
+                    if (layerSettings.empty()) {
+                        ADD_FAILURE()
+                                << "layerSettings was not expected to be empty in "
+                                   "setupREColorCompositionCallExpectations verification lambda";
+                        return NO_ERROR;
+                    }
                     renderengine::LayerSettings layer = layerSettings.back();
                     EXPECT_THAT(layer.source.buffer.buffer, IsNull());
                     EXPECT_EQ(half3(LayerProperties::COLOR[0], LayerProperties::COLOR[1],
@@ -727,6 +739,12 @@
                               displaySettings.clip);
                     // screen capture adds an additional color layer as an alpha
                     // prefill, so get the back layer.
+                    if (layerSettings.empty()) {
+                        ADD_FAILURE() << "layerSettings was not expected to be empty in "
+                                         "setupInsecureREBufferCompositionCommonCallExpectations "
+                                         "verification lambda";
+                        return NO_ERROR;
+                    }
                     renderengine::LayerSettings layer = layerSettings.back();
                     EXPECT_THAT(layer.source.buffer.buffer, IsNull());
                     EXPECT_EQ(half3(0.0f, 0.0f, 0.0f), layer.source.solidColor);
@@ -786,7 +804,6 @@
         layerDrawingState.color = half4(LayerProperties::COLOR[0], LayerProperties::COLOR[1],
                                         LayerProperties::COLOR[2], LayerProperties::COLOR[3]);
         layer->computeBounds(FloatRect(0, 0, 100, 100), ui::Transform());
-        layer->setVisibleRegion(Region(Rect(0, 0, 100, 100)));
 
         return layer;
     }
@@ -797,9 +814,10 @@
 
         std::vector<std::unique_ptr<compositionengine::OutputLayer>> outputLayers;
         outputLayers.emplace_back(test->mDisplay->getCompositionDisplay()
-                                          ->getOrCreateOutputLayer(DEFAULT_DISPLAY_ID,
-                                                                   layer->getCompositionLayer(),
-                                                                   layer));
+                                          ->createOutputLayer(layer->getCompositionLayer(), layer));
+
+        outputLayers.back()->editState().visibleRegion = Region(Rect(0, 0, 100, 100));
+        outputLayers.back()->editState().outputSpaceVisibleRegion = Region(Rect(0, 0, 100, 100));
 
         test->mDisplay->getCompositionDisplay()->setOutputLayersOrderedByZ(std::move(outputLayers));
 
diff --git a/services/surfaceflinger/tests/utils/ScreenshotUtils.h b/services/surfaceflinger/tests/utils/ScreenshotUtils.h
index 02e7623..5480b00 100644
--- a/services/surfaceflinger/tests/utils/ScreenshotUtils.h
+++ b/services/surfaceflinger/tests/utils/ScreenshotUtils.h
@@ -76,7 +76,7 @@
 
     void expectColor(const Rect& rect, const Color& color, uint8_t tolerance = 0) {
         ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mOutBuffer->getPixelFormat());
-        expectBufferColor(mOutBuffer, mPixels, rect, color, tolerance);
+        TransactionUtils::expectBufferColor(mOutBuffer, mPixels, rect, color, tolerance);
     }
 
     void expectBorder(const Rect& rect, const Color& color, uint8_t tolerance = 0) {
diff --git a/services/surfaceflinger/tests/utils/TransactionUtils.h b/services/surfaceflinger/tests/utils/TransactionUtils.h
index f6b33a9..22df255 100644
--- a/services/surfaceflinger/tests/utils/TransactionUtils.h
+++ b/services/surfaceflinger/tests/utils/TransactionUtils.h
@@ -16,13 +16,7 @@
 
 #pragma once
 
-//#include <algorithm>
 #include <chrono>
-//#include <cinttypes>
-//#include <functional>
-//#include <limits>
-//#include <ostream>
-//#include <thread>
 #include <gtest/gtest.h>
 
 #include <android/native_window.h>
@@ -39,130 +33,131 @@
 #include <ui/Rect.h>
 
 #include "ColorUtils.h"
-//#include <sys/types.h>
-//#include <unistd.h>
 
 namespace android {
 
 namespace {
 
 using namespace std::chrono_literals;
+using Transaction = SurfaceComposerClient::Transaction;
 
 std::ostream& operator<<(std::ostream& os, const Color& color) {
     os << int(color.r) << ", " << int(color.g) << ", " << int(color.b) << ", " << int(color.a);
     return os;
 }
 
-// Fill a region with the specified color.
-void fillANativeWindowBufferColor(const ANativeWindow_Buffer& buffer, const Rect& rect,
-                                  const Color& color) {
-    Rect r(0, 0, buffer.width, buffer.height);
-    if (!r.intersect(rect, &r)) {
-        return;
-    }
+class TransactionUtils {
+public:
+    // Fill a region with the specified color.
+    static void fillANativeWindowBufferColor(const ANativeWindow_Buffer& buffer, const Rect& rect,
+                                             const Color& color) {
+        Rect r(0, 0, buffer.width, buffer.height);
+        if (!r.intersect(rect, &r)) {
+            return;
+        }
 
-    int32_t width = r.right - r.left;
-    int32_t height = r.bottom - r.top;
+        int32_t width = r.right - r.left;
+        int32_t height = r.bottom - r.top;
 
-    for (int32_t row = 0; row < height; row++) {
-        uint8_t* dst =
-                static_cast<uint8_t*>(buffer.bits) + (buffer.stride * (r.top + row) + r.left) * 4;
-        for (int32_t column = 0; column < width; column++) {
-            dst[0] = color.r;
-            dst[1] = color.g;
-            dst[2] = color.b;
-            dst[3] = color.a;
-            dst += 4;
+        for (int32_t row = 0; row < height; row++) {
+            uint8_t* dst = static_cast<uint8_t*>(buffer.bits) +
+                    (buffer.stride * (r.top + row) + r.left) * 4;
+            for (int32_t column = 0; column < width; column++) {
+                dst[0] = color.r;
+                dst[1] = color.g;
+                dst[2] = color.b;
+                dst[3] = color.a;
+                dst += 4;
+            }
         }
     }
-}
 
-// Fill a region with the specified color.
-void fillGraphicBufferColor(const sp<GraphicBuffer>& buffer, const Rect& rect, const Color& color) {
-    Rect r(0, 0, buffer->width, buffer->height);
-    if (!r.intersect(rect, &r)) {
-        return;
+    // Fill a region with the specified color.
+    static void fillGraphicBufferColor(const sp<GraphicBuffer>& buffer, const Rect& rect,
+                                       const Color& color) {
+        Rect r(0, 0, buffer->width, buffer->height);
+        if (!r.intersect(rect, &r)) {
+            return;
+        }
+
+        int32_t width = r.right - r.left;
+        int32_t height = r.bottom - r.top;
+
+        uint8_t* pixels;
+        buffer->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
+                     reinterpret_cast<void**>(&pixels));
+
+        for (int32_t row = 0; row < height; row++) {
+            uint8_t* dst = pixels + (buffer->getStride() * (r.top + row) + r.left) * 4;
+            for (int32_t column = 0; column < width; column++) {
+                dst[0] = color.r;
+                dst[1] = color.g;
+                dst[2] = color.b;
+                dst[3] = color.a;
+                dst += 4;
+            }
+        }
+        buffer->unlock();
     }
 
-    int32_t width = r.right - r.left;
-    int32_t height = r.bottom - r.top;
+    // Check if a region has the specified color.
+    static void expectBufferColor(const sp<GraphicBuffer>& outBuffer, uint8_t* pixels,
+                                  const Rect& rect, const Color& color, uint8_t tolerance) {
+        int32_t x = rect.left;
+        int32_t y = rect.top;
+        int32_t width = rect.right - rect.left;
+        int32_t height = rect.bottom - rect.top;
 
-    uint8_t* pixels;
-    buffer->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
-                 reinterpret_cast<void**>(&pixels));
+        int32_t bufferWidth = int32_t(outBuffer->getWidth());
+        int32_t bufferHeight = int32_t(outBuffer->getHeight());
+        if (x + width > bufferWidth) {
+            x = std::min(x, bufferWidth);
+            width = bufferWidth - x;
+        }
+        if (y + height > bufferHeight) {
+            y = std::min(y, bufferHeight);
+            height = bufferHeight - y;
+        }
 
-    for (int32_t row = 0; row < height; row++) {
-        uint8_t* dst = pixels + (buffer->getStride() * (r.top + row) + r.left) * 4;
-        for (int32_t column = 0; column < width; column++) {
-            dst[0] = color.r;
-            dst[1] = color.g;
-            dst[2] = color.b;
-            dst[3] = color.a;
-            dst += 4;
+        auto colorCompare = [tolerance](uint8_t a, uint8_t b) {
+            uint8_t tmp = a >= b ? a - b : b - a;
+            return tmp <= tolerance;
+        };
+        for (int32_t j = 0; j < height; j++) {
+            const uint8_t* src = pixels + (outBuffer->getStride() * (y + j) + x) * 4;
+            for (int32_t i = 0; i < width; i++) {
+                const uint8_t expected[4] = {color.r, color.g, color.b, color.a};
+                EXPECT_TRUE(std::equal(src, src + 4, expected, colorCompare))
+                        << "pixel @ (" << x + i << ", " << y + j << "): "
+                        << "expected (" << color << "), "
+                        << "got (" << Color{src[0], src[1], src[2], src[3]} << ")";
+                src += 4;
+            }
         }
     }
-    buffer->unlock();
-}
 
-// Check if a region has the specified color.
-void expectBufferColor(const sp<GraphicBuffer>& outBuffer, uint8_t* pixels, const Rect& rect,
-                       const Color& color, uint8_t tolerance) {
-    int32_t x = rect.left;
-    int32_t y = rect.top;
-    int32_t width = rect.right - rect.left;
-    int32_t height = rect.bottom - rect.top;
-
-    int32_t bufferWidth = int32_t(outBuffer->getWidth());
-    int32_t bufferHeight = int32_t(outBuffer->getHeight());
-    if (x + width > bufferWidth) {
-        x = std::min(x, bufferWidth);
-        width = bufferWidth - x;
-    }
-    if (y + height > bufferHeight) {
-        y = std::min(y, bufferHeight);
-        height = bufferHeight - y;
-    }
-
-    auto colorCompare = [tolerance](uint8_t a, uint8_t b) {
-        uint8_t tmp = a >= b ? a - b : b - a;
-        return tmp <= tolerance;
-    };
-    for (int32_t j = 0; j < height; j++) {
-        const uint8_t* src = pixels + (outBuffer->getStride() * (y + j) + x) * 4;
-        for (int32_t i = 0; i < width; i++) {
-            const uint8_t expected[4] = {color.r, color.g, color.b, color.a};
-            EXPECT_TRUE(std::equal(src, src + 4, expected, colorCompare))
-                    << "pixel @ (" << x + i << ", " << y + j << "): "
-                    << "expected (" << color << "), "
-                    << "got (" << Color{src[0], src[1], src[2], src[3]} << ")";
-            src += 4;
+    // Fill an RGBA_8888 formatted surface with a single color.
+    static void fillSurfaceRGBA8(const sp<SurfaceControl>& sc, uint8_t r, uint8_t g, uint8_t b,
+                                 bool unlock = true) {
+        ANativeWindow_Buffer outBuffer;
+        sp<Surface> s = sc->getSurface();
+        ASSERT_TRUE(s != nullptr);
+        ASSERT_EQ(NO_ERROR, s->lock(&outBuffer, nullptr));
+        uint8_t* img = reinterpret_cast<uint8_t*>(outBuffer.bits);
+        for (int y = 0; y < outBuffer.height; y++) {
+            for (int x = 0; x < outBuffer.width; x++) {
+                uint8_t* pixel = img + (4 * (y * outBuffer.stride + x));
+                pixel[0] = r;
+                pixel[1] = g;
+                pixel[2] = b;
+                pixel[3] = 255;
+            }
+        }
+        if (unlock) {
+            ASSERT_EQ(NO_ERROR, s->unlockAndPost());
         }
     }
-}
-
-using Transaction = SurfaceComposerClient::Transaction;
-
-// Fill an RGBA_8888 formatted surface with a single color.
-static void fillSurfaceRGBA8(const sp<SurfaceControl>& sc, uint8_t r, uint8_t g, uint8_t b,
-                             bool unlock = true) {
-    ANativeWindow_Buffer outBuffer;
-    sp<Surface> s = sc->getSurface();
-    ASSERT_TRUE(s != nullptr);
-    ASSERT_EQ(NO_ERROR, s->lock(&outBuffer, nullptr));
-    uint8_t* img = reinterpret_cast<uint8_t*>(outBuffer.bits);
-    for (int y = 0; y < outBuffer.height; y++) {
-        for (int x = 0; x < outBuffer.width; x++) {
-            uint8_t* pixel = img + (4 * (y * outBuffer.stride + x));
-            pixel[0] = r;
-            pixel[1] = g;
-            pixel[2] = b;
-            pixel[3] = 255;
-        }
-    }
-    if (unlock) {
-        ASSERT_EQ(NO_ERROR, s->unlockAndPost());
-    }
-}
+};
 
 enum class RenderPath { SCREENSHOT, VIRTUAL_DISPLAY };
 
diff --git a/services/vr/hardware_composer/Android.bp b/services/vr/hardware_composer/Android.bp
index 4e461f9..4df7b7c 100644
--- a/services/vr/hardware_composer/Android.bp
+++ b/services/vr/hardware_composer/Android.bp
@@ -27,7 +27,6 @@
         "libfmq",
         "libhardware",
         "libhidlbase",
-        "libhidltransport",
         "liblog",
         "libsync",
         "libui",
@@ -115,7 +114,6 @@
         "libbinder",
         "liblog",
         "libhardware",
-        "libhwbinder",
         "libhidlbase",
         "libui",
         "libutils",
diff --git a/vulkan/libvulkan/Android.bp b/vulkan/libvulkan/Android.bp
index 85ef475..651c94d 100644
--- a/vulkan/libvulkan/Android.bp
+++ b/vulkan/libvulkan/Android.bp
@@ -88,7 +88,6 @@
         "libbase",
         "libdl_android",
         "libhidlbase",
-        "libhidltransport",
         "liblog",
         "libui",
         "libgraphicsenv",