Merge "Add meta transactions in fuzzService" into main
diff --git a/cmds/installd/otapreopt_script.sh b/cmds/installd/otapreopt_script.sh
index b7ad331..5690e2f 100644
--- a/cmds/installd/otapreopt_script.sh
+++ b/cmds/installd/otapreopt_script.sh
@@ -23,6 +23,9 @@
 TARGET_SLOT="$1"
 STATUS_FD="$2"
 
+# "1" if the script is triggered by the `UpdateEngine.triggerPostinstall` API. Empty otherwise.
+TRIGGERED_BY_API="$3"
+
 # Maximum number of packages/steps.
 MAXIMUM_PACKAGES=1000
 
@@ -53,25 +56,43 @@
 # A source that infinitely emits arbitrary lines.
 # When connected to STDIN of another process, this source keeps STDIN open until
 # the consumer process closes STDIN or this script dies.
+# In practice, the pm command keeps consuming STDIN, so we don't need to worry
+# about running out of buffer space.
 function infinite_source {
   while echo .; do
     sleep 1
   done
 }
 
+if [[ "$TRIGGERED_BY_API" = "1" ]]; then
+  # During OTA installation, the script is called the first time, and
+  # `TRIGGERED_BY_API` can never be "1". `TRIGGERED_BY_API` being "1" means this
+  # is the second call to this script, through the
+  # `UpdateEngine.triggerPostinstall` API.
+  # When we reach here, it means Pre-reboot Dexopt is enabled in asynchronous
+  # mode and the job scheduler determined that it's the time to run the job.
+  # Start Pre-reboot Dexopt now and wait for it to finish.
+  infinite_source | pm art on-ota-staged --start
+  exit $?
+fi
+
 PR_DEXOPT_JOB_VERSION="$(pm art pr-dexopt-job --version)"
 if (( $? == 0 )) && (( $PR_DEXOPT_JOB_VERSION >= 3 )); then
   # Delegate to Pre-reboot Dexopt, a feature of ART Service.
   # ART Service decides what to do with this request:
   # - If Pre-reboot Dexopt is disabled or unsupported, the command returns
-  #   non-zero. This is always the case if the current system is Android 14 or
-  #   earlier.
+  #   non-zero.
+  #   This is always the case if the current system is Android 14 or earlier.
   # - If Pre-reboot Dexopt is enabled in synchronous mode, the command blocks
-  #   until Pre-reboot Dexopt finishes, and returns zero no matter it succeeds or
-  #   not. This is the default behavior if the current system is Android 15.
-  # - If Pre-reboot Dexopt is enabled in asynchronous mode, the command schedules
-  #   an asynchronous job and returns 0 immediately. The job will then run by the
-  #   job scheduler when the device is idle and charging.
+  #   until Pre-reboot Dexopt finishes, and returns zero no matter it succeeds
+  #   or not.
+  #   This is the default behavior if the current system is Android 15.
+  # - If Pre-reboot Dexopt is enabled in asynchronous mode, the command
+  #   schedules an asynchronous job and returns 0 immediately.
+  #   Later, when the device is idle and charging, the job will be run by the
+  #   job scheduler. It will call this script again through the
+  #   `UpdateEngine.triggerPostinstall` API, with `TRIGGERED_BY_API` being "1".
+  #   This is always the case if the current system is Android 16 or later.
   if infinite_source | pm art on-ota-staged --slot "$TARGET_SLOT_SUFFIX"; then
     # Handled by Pre-reboot Dexopt.
     exit 0
diff --git a/include/OWNERS b/include/OWNERS
index c98e87a..7f847e8 100644
--- a/include/OWNERS
+++ b/include/OWNERS
@@ -1,5 +1,4 @@
 alecmouri@google.com
-alexeykuzmin@google.com
 dangittik@google.com
 jreck@google.com
 lajos@google.com
diff --git a/libs/attestation/OWNERS b/libs/attestation/OWNERS
index 4dbb0ea..76811f2 100644
--- a/libs/attestation/OWNERS
+++ b/libs/attestation/OWNERS
@@ -1,2 +1 @@
-chaviw@google.com
-svv@google.com
\ No newline at end of file
+svv@google.com
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index aac369d..9d9ae31 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -826,6 +826,7 @@
     // so we restrict its visibility to the Trusty-specific packages.
     visibility: [
         ":__subpackages__",
+        "//hardware/interfaces/security/see:__subpackages__",
         "//system/core/trusty:__subpackages__",
         "//vendor:__subpackages__",
     ],
diff --git a/libs/binder/RpcTransportTipcAndroid.cpp b/libs/binder/RpcTransportTipcAndroid.cpp
index 3819fb6..14c0bde 100644
--- a/libs/binder/RpcTransportTipcAndroid.cpp
+++ b/libs/binder/RpcTransportTipcAndroid.cpp
@@ -21,6 +21,7 @@
 #include <log/log.h>
 #include <poll.h>
 #include <trusty/tipc.h>
+#include <type_traits>
 
 #include "FdTrigger.h"
 #include "RpcState.h"
@@ -32,6 +33,9 @@
 
 namespace android {
 
+// Corresponds to IPC_MAX_MSG_HANDLES in the Trusty kernel
+constexpr size_t kMaxTipcHandles = 8;
+
 // RpcTransport for writing Trusty IPC clients in Android.
 class RpcTransportTipcAndroid : public RpcTransport {
 public:
@@ -78,12 +82,28 @@
             FdTrigger* fdTrigger, iovec* iovs, int niovs,
             const std::optional<SmallFunction<status_t()>>& altPoll,
             const std::vector<std::variant<unique_fd, borrowed_fd>>* ancillaryFds) override {
+        bool sentFds = false;
         auto writeFn = [&](iovec* iovs, size_t niovs) -> ssize_t {
-            // TODO: send ancillaryFds. For now, we just abort if anyone tries
-            // to send any.
-            LOG_ALWAYS_FATAL_IF(ancillaryFds != nullptr && !ancillaryFds->empty(),
-                                "File descriptors are not supported on Trusty yet");
-            return TEMP_FAILURE_RETRY(tipc_send(mSocket.fd.get(), iovs, niovs, nullptr, 0));
+            trusty_shm shms[kMaxTipcHandles] = {{0}};
+            ssize_t shm_count = 0;
+
+            if (!sentFds && ancillaryFds != nullptr && !ancillaryFds->empty()) {
+                if (ancillaryFds->size() > kMaxTipcHandles) {
+                    ALOGE("Too many file descriptors for TIPC: %zu", ancillaryFds->size());
+                    errno = EINVAL;
+                    return -1;
+                }
+                for (const auto& fdVariant : *ancillaryFds) {
+                    shms[shm_count++] = {std::visit([](const auto& fd) { return fd.get(); },
+                                                    fdVariant),
+                                         TRUSTY_SEND_SECURE_OR_SHARE};
+                }
+            }
+
+            auto ret = TEMP_FAILURE_RETRY(tipc_send(mSocket.fd.get(), iovs, niovs,
+                                                    (shm_count == 0) ? nullptr : shms, shm_count));
+            sentFds |= ret >= 0;
+            return ret;
         };
 
         status_t status = interruptableReadOrWrite(mSocket, fdTrigger, iovs, niovs, writeFn,
diff --git a/libs/binder/aidl/android/content/pm/OWNERS b/libs/binder/aidl/android/content/pm/OWNERS
index 3100518..2617a16 100644
--- a/libs/binder/aidl/android/content/pm/OWNERS
+++ b/libs/binder/aidl/android/content/pm/OWNERS
@@ -1,5 +1,4 @@
+michaelwr@google.com
 narayan@google.com
 patb@google.com
-svetoslavganov@google.com
-toddke@google.com
-patb@google.com
\ No newline at end of file
+schfan@google.com
diff --git a/libs/binder/ndk/include_platform/android/binder_ibinder_platform.h b/libs/binder/ndk/include_platform/android/binder_ibinder_platform.h
index 89f21dd..783e11f 100644
--- a/libs/binder/ndk/include_platform/android/binder_ibinder_platform.h
+++ b/libs/binder/ndk/include_platform/android/binder_ibinder_platform.h
@@ -62,6 +62,8 @@
  * This must be called before the object is sent to another process.
  * Aborts on invalid values. Not thread safe.
  *
+ * This overrides the setting in ABinderProcess_disableBackgroundScheduling.
+ *
  * \param binder local server binder to set the policy for
  * \param policy scheduler policy as defined in linux UAPI
  * \param priority priority. [-20..19] for SCHED_NORMAL, [1..99] for RT
diff --git a/libs/binder/ndk/include_platform/android/binder_process.h b/libs/binder/ndk/include_platform/android/binder_process.h
index 6aff994..2432099 100644
--- a/libs/binder/ndk/include_platform/android/binder_process.h
+++ b/libs/binder/ndk/include_platform/android/binder_process.h
@@ -75,6 +75,19 @@
 void ABinderProcess_joinThreadPool(void);
 
 /**
+ * Disables (or enables) background scheduling.
+ *
+ * By default, binder threads execute at a lower priority. However, this can cause
+ * priority inversion, so it is recommended to be disabled in high priority
+ * or in system processes.
+ *
+ * See also AIBinder_setMinSchedulerPolicy, which overrides this setting.
+ *
+ * \param disable whether to disable background scheduling
+ */
+void ABinderProcess_disableBackgroundScheduling(bool disable);
+
+/**
  * This gives you an fd to wait on. Whenever data is available on the fd,
  * ABinderProcess_handlePolledCommands can be called to handle binder queries.
  * This is expected to be used in a single threaded process which waits on
diff --git a/libs/binder/ndk/include_platform/android/binder_stability.h b/libs/binder/ndk/include_platform/android/binder_stability.h
index 089c775..8050205 100644
--- a/libs/binder/ndk/include_platform/android/binder_stability.h
+++ b/libs/binder/ndk/include_platform/android/binder_stability.h
@@ -27,6 +27,10 @@
 
 #if defined(__ANDROID_VENDOR__)
 
+#if defined(__ANDROID_PRODUCT__)
+#error "build bug: product is not part of the vendor half of the Treble system/vendor split"
+#endif
+
 /**
  * Private addition to binder_flag_t.
  */
diff --git a/libs/binder/ndk/libbinder_ndk.map.txt b/libs/binder/ndk/libbinder_ndk.map.txt
index a637165..d4eb8c7 100644
--- a/libs/binder/ndk/libbinder_ndk.map.txt
+++ b/libs/binder/ndk/libbinder_ndk.map.txt
@@ -229,6 +229,7 @@
         AIBinder_fromPlatformBinder*;
         AIBinder_toPlatformBinder*;
         AParcel_viewPlatformParcel*;
+        ABinderProcess_disableBackgroundScheduling;
     };
   local:
     *;
diff --git a/libs/binder/ndk/process.cpp b/libs/binder/ndk/process.cpp
index 0072ac3..bcdb959 100644
--- a/libs/binder/ndk/process.cpp
+++ b/libs/binder/ndk/process.cpp
@@ -36,6 +36,10 @@
     IPCThreadState::self()->joinThreadPool();
 }
 
+void ABinderProcess_disableBackgroundScheduling(bool disable) {
+    IPCThreadState::disableBackgroundScheduling(disable);
+}
+
 binder_status_t ABinderProcess_setupPolling(int* fd) {
     return IPCThreadState::self()->setupPolling(fd);
 }
diff --git a/libs/binder/rust/rpcbinder/Android.bp b/libs/binder/rust/rpcbinder/Android.bp
index 4036551..46651ce 100644
--- a/libs/binder/rust/rpcbinder/Android.bp
+++ b/libs/binder/rust/rpcbinder/Android.bp
@@ -26,6 +26,7 @@
     ],
     visibility: [
         "//device/google/cuttlefish/shared/minidroid/sample",
+        "//hardware/interfaces/security/see:__subpackages__",
         "//packages/modules/Virtualization:__subpackages__",
     ],
     apex_available: [
diff --git a/libs/binder/rust/src/binder.rs b/libs/binder/rust/src/binder.rs
index 8c0501b..6a8a698 100644
--- a/libs/binder/rust/src/binder.rs
+++ b/libs/binder/rust/src/binder.rs
@@ -1201,5 +1201,45 @@
                 Ok(v.map(|v| v.into_iter().map(Self).collect()))
             }
         }
+
+        impl std::ops::BitOr for $enum {
+            type Output = Self;
+            fn bitor(self, rhs: Self) -> Self {
+                Self(self.0 | rhs.0)
+            }
+        }
+
+        impl std::ops::BitOrAssign for $enum {
+            fn bitor_assign(&mut self, rhs: Self) {
+                self.0 = self.0 | rhs.0;
+            }
+        }
+
+        impl std::ops::BitAnd for $enum {
+            type Output = Self;
+            fn bitand(self, rhs: Self) -> Self {
+                Self(self.0 & rhs.0)
+            }
+        }
+
+        impl std::ops::BitAndAssign for $enum {
+            fn bitand_assign(&mut self, rhs: Self) {
+                self.0 = self.0 & rhs.0;
+            }
+        }
+
+        impl std::ops::BitXor for $enum {
+            type Output = Self;
+            fn bitxor(self, rhs: Self) -> Self {
+                Self(self.0 ^ rhs.0)
+            }
+        }
+
+        impl std::ops::BitXorAssign for $enum {
+            fn bitxor_assign(&mut self, rhs: Self) {
+                self.0 = self.0 ^ rhs.0;
+            }
+        }
+
     };
 }
diff --git a/libs/binder/rust/src/state.rs b/libs/binder/rust/src/state.rs
index 8a06274..145ae65 100644
--- a/libs/binder/rust/src/state.rs
+++ b/libs/binder/rust/src/state.rs
@@ -28,8 +28,9 @@
     /// `num_threads` additional threads as specified by
     /// [`set_thread_pool_max_thread_count`](Self::set_thread_pool_max_thread_count).
     ///
-    /// This should be done before creating any Binder client or server. If
-    /// neither this nor [`join_thread_pool`](Self::join_thread_pool) are
+    /// If this is called, it must be done before creating any Binder client or server.
+    ///
+    /// If neither this nor [`join_thread_pool`](Self::join_thread_pool) are
     /// called, then some things (such as callbacks and
     /// [`IBinder::link_to_death`](crate::IBinder::link_to_death)) will silently
     /// not work: the callbacks will be queued but never called as there is no
diff --git a/libs/binder/tests/binderStabilityIntegrationTest.cpp b/libs/binder/tests/binderStabilityIntegrationTest.cpp
index a3fc9cc..cbc4180 100644
--- a/libs/binder/tests/binderStabilityIntegrationTest.cpp
+++ b/libs/binder/tests/binderStabilityIntegrationTest.cpp
@@ -47,6 +47,7 @@
 
     Stability::Level level = Stability::Level::UNDECLARED;
     switch (partition) {
+        case Partition::PRODUCT:
         case Partition::SYSTEM:
         case Partition::SYSTEM_EXT:
             level = Stability::Level::SYSTEM;
diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp
index 25e6a52..ba82046 100644
--- a/libs/gui/BLASTBufferQueue.cpp
+++ b/libs/gui/BLASTBufferQueue.cpp
@@ -210,8 +210,6 @@
     ComposerServiceAIDL::getComposerService()->getMaxAcquiredBufferCount(&mMaxAcquiredBuffers);
     mBufferItemConsumer->setMaxAcquiredBufferCount(mMaxAcquiredBuffers);
     mCurrentMaxAcquiredBufferCount = mMaxAcquiredBuffers;
-    mNumAcquired = 0;
-    mNumFrameAvailable = 0;
 
     TransactionCompletedListener::getInstance()->addQueueStallListener(
             [&](const std::string& reason) {
@@ -436,7 +434,7 @@
 
 void BLASTBufferQueue::flushShadowQueue() {
     BQA_LOGV("flushShadowQueue");
-    int numFramesToFlush = mNumFrameAvailable;
+    int32_t numFramesToFlush = mNumFrameAvailable;
     while (numFramesToFlush > 0) {
         acquireNextBufferLocked(std::nullopt);
         numFramesToFlush--;
diff --git a/libs/math/OWNERS b/libs/math/OWNERS
index 82ae422..08f0c5f 100644
--- a/libs/math/OWNERS
+++ b/libs/math/OWNERS
@@ -1,5 +1,4 @@
 mathias@google.com
-randolphs@google.com
 romainguy@google.com
 sumir@google.com
 jreck@google.com
diff --git a/libs/renderengine/OWNERS b/libs/renderengine/OWNERS
index 17ab29f..e296283 100644
--- a/libs/renderengine/OWNERS
+++ b/libs/renderengine/OWNERS
@@ -7,4 +7,3 @@
 lpy@google.com
 nscobie@google.com
 sallyqi@google.com
-scroggo@google.com
diff --git a/libs/renderengine/skia/Cache.cpp b/libs/renderengine/skia/Cache.cpp
index 57041ee..3b0f036 100644
--- a/libs/renderengine/skia/Cache.cpp
+++ b/libs/renderengine/skia/Cache.cpp
@@ -337,17 +337,17 @@
     LayerSettings layer{
             .geometry =
                     Geometry{
+                            .boundaries = rect,
                             // The position transform doesn't matter when the reduced shader mode
                             // in in effect. A matrix transform stage is always included.
                             .positionTransform = mat4(),
-                            .boundaries = rect,
-                            .roundedCornersCrop = rect,
                             .roundedCornersRadius = {0.f, 0.f},
+                            .roundedCornersCrop = rect,
                     },
             .source = PixelSource{.buffer = Buffer{.buffer = srcTexture,
-                                                   .maxLuminanceNits = 1000.f,
                                                    .usePremultipliedAlpha = true,
-                                                   .isOpaque = true}},
+                                                   .isOpaque = true,
+                                                   .maxLuminanceNits = 1000.f}},
             .alpha = 1.f,
             .sourceDataspace = kDestDataSpace,
     };
@@ -370,16 +370,16 @@
     LayerSettings layer{
             .geometry =
                     Geometry{
-                            .positionTransform = mat4(),
                             .boundaries = rect,
+                            .positionTransform = mat4(),
                             .roundedCornersCrop = rect,
                     },
             .source = PixelSource{.buffer =
                                           Buffer{
                                                   .buffer = srcTexture,
-                                                  .maxLuminanceNits = 1000.f,
                                                   .usePremultipliedAlpha = true,
                                                   .isOpaque = false,
+                                                  .maxLuminanceNits = 1000.f,
                                           }},
             .sourceDataspace = kDestDataSpace,
     };
@@ -421,17 +421,17 @@
     LayerSettings layer{
             .geometry =
                     Geometry{
-                            .positionTransform = mat4(),
                             .boundaries = boundary,
-                            .roundedCornersCrop = rect,
+                            .positionTransform = mat4(),
                             .roundedCornersRadius = {27.f, 27.f},
+                            .roundedCornersCrop = rect,
                     },
             .source = PixelSource{.buffer =
                                           Buffer{
                                                   .buffer = srcTexture,
-                                                  .maxLuminanceNits = 1000.f,
                                                   .usePremultipliedAlpha = true,
                                                   .isOpaque = false,
+                                                  .maxLuminanceNits = 1000.f,
                                           }},
             .alpha = 1.f,
             .sourceDataspace = kDestDataSpace,
@@ -489,17 +489,17 @@
     LayerSettings layer{
             .geometry =
                     Geometry{
+                            .boundaries = rect,
                             // The position transform doesn't matter when the reduced shader mode
                             // in in effect. A matrix transform stage is always included.
                             .positionTransform = mat4(),
-                            .boundaries = rect,
-                            .roundedCornersCrop = rect,
                             .roundedCornersRadius = {0.f, 0.f},
+                            .roundedCornersCrop = rect,
                     },
             .source = PixelSource{.buffer = Buffer{.buffer = srcTexture,
-                                                   .maxLuminanceNits = 1000.f,
                                                    .usePremultipliedAlpha = true,
-                                                   .isOpaque = true}},
+                                                   .isOpaque = true,
+                                                   .maxLuminanceNits = 1000.f}},
             .alpha = 1.f,
             .sourceDataspace = kBT2020DataSpace,
     };
@@ -527,17 +527,17 @@
     LayerSettings layer{
             .geometry =
                     Geometry{
-                            .positionTransform = kScaleAsymmetric,
                             .boundaries = boundary,
-                            .roundedCornersCrop = rect,
+                            .positionTransform = kScaleAsymmetric,
                             .roundedCornersRadius = {64.1f, 64.1f},
+                            .roundedCornersCrop = rect,
                     },
             .source = PixelSource{.buffer =
                                           Buffer{
                                                   .buffer = srcTexture,
-                                                  .maxLuminanceNits = 1000.f,
                                                   .usePremultipliedAlpha = true,
                                                   .isOpaque = true,
+                                                  .maxLuminanceNits = 1000.f,
                                           }},
             .alpha = 0.5f,
             .sourceDataspace = kBT2020DataSpace,
@@ -556,17 +556,17 @@
     LayerSettings layer{
             .geometry =
                     Geometry{
+                            .boundaries = rect,
                             // The position transform doesn't matter when the reduced shader mode
                             // in in effect. A matrix transform stage is always included.
                             .positionTransform = mat4(),
-                            .boundaries = rect,
-                            .roundedCornersCrop = rect,
                             .roundedCornersRadius = {50.f, 50.f},
+                            .roundedCornersCrop = rect,
                     },
             .source = PixelSource{.buffer = Buffer{.buffer = srcTexture,
-                                                   .maxLuminanceNits = 1000.f,
                                                    .usePremultipliedAlpha = true,
-                                                   .isOpaque = true}},
+                                                   .isOpaque = true,
+                                                   .maxLuminanceNits = 1000.f}},
             .alpha = 0.5f,
             .sourceDataspace = kExtendedHdrDataSpce,
     };
@@ -594,17 +594,17 @@
     LayerSettings layer{
             .geometry =
                     Geometry{
+                            .boundaries = rect,
                             // The position transform doesn't matter when the reduced shader mode
                             // in in effect. A matrix transform stage is always included.
                             .positionTransform = mat4(),
-                            .boundaries = rect,
-                            .roundedCornersCrop = rect,
                             .roundedCornersRadius = {50.f, 50.f},
+                            .roundedCornersCrop = rect,
                     },
             .source = PixelSource{.buffer = Buffer{.buffer = srcTexture,
-                                                   .maxLuminanceNits = 1000.f,
                                                    .usePremultipliedAlpha = true,
-                                                   .isOpaque = false}},
+                                                   .isOpaque = false,
+                                                   .maxLuminanceNits = 1000.f}},
             .alpha = 0.5f,
             .sourceDataspace = kOtherDataSpace,
     };
diff --git a/libs/renderengine/skia/debug/CaptureTimer.cpp b/libs/renderengine/skia/debug/CaptureTimer.cpp
index 11bcdb8..1c1ee0a 100644
--- a/libs/renderengine/skia/debug/CaptureTimer.cpp
+++ b/libs/renderengine/skia/debug/CaptureTimer.cpp
@@ -30,7 +30,7 @@
 
 void CaptureTimer::setTimeout(TimeoutCallback function, std::chrono::milliseconds delay) {
     this->clear = false;
-    CommonPool::post([=]() {
+    CommonPool::post([=,this]() {
         if (this->clear) return;
         std::this_thread::sleep_for(delay);
         if (this->clear) return;
diff --git a/libs/shaders/OWNERS b/libs/shaders/OWNERS
index 6d91da3..6977a49 100644
--- a/libs/shaders/OWNERS
+++ b/libs/shaders/OWNERS
@@ -1,4 +1,3 @@
 alecmouri@google.com
 jreck@google.com
 sallyqi@google.com
-scroggo@google.com
\ No newline at end of file
diff --git a/libs/tonemap/OWNERS b/libs/tonemap/OWNERS
index 6d91da3..6977a49 100644
--- a/libs/tonemap/OWNERS
+++ b/libs/tonemap/OWNERS
@@ -1,4 +1,3 @@
 alecmouri@google.com
 jreck@google.com
 sallyqi@google.com
-scroggo@google.com
\ No newline at end of file
diff --git a/libs/ui/OWNERS b/libs/ui/OWNERS
index a0b5fe7..2a85a4b 100644
--- a/libs/ui/OWNERS
+++ b/libs/ui/OWNERS
@@ -2,6 +2,5 @@
 alecmouri@google.com
 chrisforbes@google.com
 jreck@google.com
-lpy@google.com
 mathias@google.com
 romainguy@google.com
diff --git a/services/displayservice/OWNERS b/services/displayservice/OWNERS
index 7a3e4c2..40164aa 100644
--- a/services/displayservice/OWNERS
+++ b/services/displayservice/OWNERS
@@ -1,2 +1 @@
 smoreland@google.com
-lpy@google.com
diff --git a/services/gpuservice/vts/OWNERS b/services/gpuservice/vts/OWNERS
index a63de1c..13a089f 100644
--- a/services/gpuservice/vts/OWNERS
+++ b/services/gpuservice/vts/OWNERS
@@ -1,8 +1,5 @@
 # Bug component: 653544
 kocdemir@google.com
 paulthomson@google.com
-pbaiget@google.com
-lfy@google.com
 chrisforbes@google.com
-lpy@google.com
 alecmouri@google.com
diff --git a/services/stats/OWNERS b/services/stats/OWNERS
index a61babf..791b711 100644
--- a/services/stats/OWNERS
+++ b/services/stats/OWNERS
@@ -1,9 +1,7 @@
 jeffreyhuang@google.com
 joeo@google.com
-jtnguyen@google.com
 muhammadq@google.com
 ruchirr@google.com
 singhtejinder@google.com
 tsaichristine@google.com
 yaochen@google.com
-yro@google.com
diff --git a/services/surfaceflinger/CompositionEngine/src/ClientCompositionRequestCache.cpp b/services/surfaceflinger/CompositionEngine/src/ClientCompositionRequestCache.cpp
index d9018bc..dc84195 100644
--- a/services/surfaceflinger/CompositionEngine/src/ClientCompositionRequestCache.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/ClientCompositionRequestCache.cpp
@@ -38,7 +38,8 @@
             lhs.disableBlending == rhs.disableBlending && lhs.shadow == rhs.shadow &&
             lhs.backgroundBlurRadius == rhs.backgroundBlurRadius &&
             lhs.stretchEffect == rhs.stretchEffect &&
-            lhs.edgeExtensionEffect == rhs.edgeExtensionEffect;
+            lhs.edgeExtensionEffect == rhs.edgeExtensionEffect &&
+            lhs.whitePointNits == rhs.whitePointNits;
 }
 
 inline bool equalIgnoringBuffer(const renderengine::Buffer& lhs, const renderengine::Buffer& rhs) {
diff --git a/services/surfaceflinger/OWNERS b/services/surfaceflinger/OWNERS
index fa0ecee..13edd16 100644
--- a/services/surfaceflinger/OWNERS
+++ b/services/surfaceflinger/OWNERS
@@ -12,6 +12,5 @@
 ramindani@google.com
 rnlee@google.com
 sallyqi@google.com
-scroggo@google.com
 vishnun@google.com
 xwxw@google.com
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 6cce334..326bf57 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -4354,27 +4354,6 @@
 status_t SurfaceFlinger::addClientLayer(LayerCreationArgs& args, const sp<IBinder>& handle,
                                         const sp<Layer>& layer, const wp<Layer>& parent,
                                         uint32_t* outTransformHint) {
-    if (mNumLayers >= MAX_LAYERS) {
-        static std::atomic<nsecs_t> lasttime{0};
-        nsecs_t now = systemTime();
-        if (lasttime != 0 && ns2s(now - lasttime.load()) < 10) {
-            ALOGE("AddClientLayer already dumped 10s before");
-            return NO_MEMORY;
-        } else {
-            lasttime = now;
-        }
-
-        ALOGE("AddClientLayer failed, mNumLayers (%zu) >= MAX_LAYERS (%zu)", mNumLayers.load(),
-              MAX_LAYERS);
-        static_cast<void>(mScheduler->schedule([&]() FTL_FAKE_GUARD(kMainThreadContext) {
-            ALOGE("Dumping on-screen layers.");
-            mLayerHierarchyBuilder.dumpLayerSample(mLayerHierarchyBuilder.getHierarchy());
-            ALOGE("Dumping off-screen layers.");
-            mLayerHierarchyBuilder.dumpLayerSample(mLayerHierarchyBuilder.getOffscreenHierarchy());
-        }));
-        return NO_MEMORY;
-    }
-
     if (outTransformHint) {
         *outTransformHint = mActiveDisplayTransformHint;
     }
@@ -5145,16 +5124,15 @@
         mirrorArgs.addToRoot = true;
         mirrorArgs.layerStackToMirror = layerStack;
         result = createEffectLayer(mirrorArgs, &outResult.handle, &rootMirrorLayer);
+        if (result != NO_ERROR) {
+            return result;
+        }
         outResult.layerId = rootMirrorLayer->sequence;
         outResult.layerName = String16(rootMirrorLayer->getDebugName());
-        result |= addClientLayer(mirrorArgs, outResult.handle, rootMirrorLayer /* layer */,
+        addClientLayer(mirrorArgs, outResult.handle, rootMirrorLayer /* layer */,
                                  nullptr /* parent */, nullptr /* outTransformHint */);
     }
 
-    if (result != NO_ERROR) {
-        return result;
-    }
-
     setTransactionFlags(eTransactionFlushNeeded);
     return NO_ERROR;
 }
@@ -5172,6 +5150,9 @@
             [[fallthrough]];
         case ISurfaceComposerClient::eFXSurfaceEffect: {
             result = createBufferStateLayer(args, &outResult.handle, &layer);
+            if (result != NO_ERROR) {
+                return result;
+            }
             std::atomic<int32_t>* pendingBufferCounter = layer->getPendingBufferCounter();
             if (pendingBufferCounter) {
                 std::string counterName = layer->getPendingBufferCounterName();
@@ -5211,6 +5192,9 @@
 
 status_t SurfaceFlinger::createBufferStateLayer(LayerCreationArgs& args, sp<IBinder>* handle,
                                                 sp<Layer>* outLayer) {
+    if (checkLayerLeaks() != NO_ERROR) {
+        return NO_MEMORY;
+    }
     *outLayer = getFactory().createBufferStateLayer(args);
     *handle = (*outLayer)->getHandle();
     return NO_ERROR;
@@ -5218,11 +5202,38 @@
 
 status_t SurfaceFlinger::createEffectLayer(const LayerCreationArgs& args, sp<IBinder>* handle,
                                            sp<Layer>* outLayer) {
+    if (checkLayerLeaks() != NO_ERROR) {
+        return NO_MEMORY;
+    }
     *outLayer = getFactory().createEffectLayer(args);
     *handle = (*outLayer)->getHandle();
     return NO_ERROR;
 }
 
+status_t SurfaceFlinger::checkLayerLeaks() {
+    if (mNumLayers >= MAX_LAYERS) {
+        static std::atomic<nsecs_t> lasttime{0};
+        nsecs_t now = systemTime();
+        if (lasttime != 0 && ns2s(now - lasttime.load()) < 10) {
+            ALOGE("CreateLayer already dumped 10s before");
+            return NO_MEMORY;
+        } else {
+            lasttime = now;
+        }
+
+        ALOGE("CreateLayer failed, mNumLayers (%zu) >= MAX_LAYERS (%zu)", mNumLayers.load(),
+              MAX_LAYERS);
+        static_cast<void>(mScheduler->schedule([&]() FTL_FAKE_GUARD(kMainThreadContext) {
+            ALOGE("Dumping on-screen layers.");
+            mLayerHierarchyBuilder.dumpLayerSample(mLayerHierarchyBuilder.getHierarchy());
+            ALOGE("Dumping off-screen layers.");
+            mLayerHierarchyBuilder.dumpLayerSample(mLayerHierarchyBuilder.getOffscreenHierarchy());
+        }));
+        return NO_MEMORY;
+    }
+    return NO_ERROR;
+}
+
 void SurfaceFlinger::onHandleDestroyed(BBinder* handle, sp<Layer>& layer, uint32_t layerId) {
     {
         // Used to remove stalled transactions which uses an internal lock.
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 0808c12..24194b1 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -835,6 +835,9 @@
     status_t createEffectLayer(const LayerCreationArgs& args, sp<IBinder>* outHandle,
                                sp<Layer>* outLayer);
 
+    // Checks if there are layer leaks before creating layer
+    status_t checkLayerLeaks();
+
     status_t mirrorLayer(const LayerCreationArgs& args, const sp<IBinder>& mirrorFromHandle,
                          gui::CreateSurfaceResult& outResult);