Merge "Add incrementValue method"
diff --git a/include/input/Input.h b/include/input/Input.h
index 29503af..e1cacac 100644
--- a/include/input/Input.h
+++ b/include/input/Input.h
@@ -945,8 +945,8 @@
  */
 struct __attribute__((__packed__)) VerifiedKeyEvent : public VerifiedInputEvent {
     int32_t action;
-    nsecs_t downTimeNanos;
     int32_t flags;
+    nsecs_t downTimeNanos;
     int32_t keyCode;
     int32_t scanCode;
     int32_t metaState;
@@ -961,8 +961,8 @@
     float rawX;
     float rawY;
     int32_t actionMasked;
-    nsecs_t downTimeNanos;
     int32_t flags;
+    nsecs_t downTimeNanos;
     int32_t metaState;
     int32_t buttonState;
 };
diff --git a/libs/binder/ndk/Android.bp b/libs/binder/ndk/Android.bp
index ee46fcb..4289574 100644
--- a/libs/binder/ndk/Android.bp
+++ b/libs/binder/ndk/Android.bp
@@ -38,7 +38,7 @@
         host: {
             cflags: [
                 "-D__INTRODUCED_IN(n)=",
-                "-D__assert(a,b,c)=",
+                "-D__assert(a,b,c)=do { syslog(LOG_ERR, a \": \" c); abort(); } while(false)",
                 // We want all the APIs to be available on the host.
                 "-D__ANDROID_API__=10000",
             ],
diff --git a/libs/binder/ndk/include_cpp/android/binder_parcel_utils.h b/libs/binder/ndk/include_cpp/android/binder_parcel_utils.h
index 67623a6..c1487c0 100644
--- a/libs/binder/ndk/include_cpp/android/binder_parcel_utils.h
+++ b/libs/binder/ndk/include_cpp/android/binder_parcel_utils.h
@@ -560,7 +560,7 @@
             *p = std::nullopt;
             return STATUS_OK;
         }
-        *p = std::optional<first_template_type_t<P>>(first_template_type_t<P>{});
+        p->emplace(first_template_type_t<P>());
         return (*p)->readFromParcel(parcel);
     } else {
         static_assert(is_specialization_v<P, std::unique_ptr>);
diff --git a/libs/binder/rust/src/binder.rs b/libs/binder/rust/src/binder.rs
index 3d2eddf..4d6b294 100644
--- a/libs/binder/rust/src/binder.rs
+++ b/libs/binder/rust/src/binder.rs
@@ -66,6 +66,35 @@
     }
 }
 
+/// Implemented by sync interfaces to specify what the associated async interface is.
+/// Generic to handle the fact that async interfaces are generic over a thread pool.
+///
+/// The binder in any object implementing this trait should be compatible with the
+/// `Target` associated type, and using `FromIBinder` to convert it to the target
+/// should not fail.
+pub trait ToAsyncInterface<P>
+where
+    Self: Interface,
+    Self::Target: FromIBinder,
+{
+    /// The async interface associated with this sync interface.
+    type Target: ?Sized;
+}
+
+/// Implemented by async interfaces to specify what the associated sync interface is.
+///
+/// The binder in any object implementing this trait should be compatible with the
+/// `Target` associated type, and using `FromIBinder` to convert it to the target
+/// should not fail.
+pub trait ToSyncInterface
+where
+    Self: Interface,
+    Self::Target: FromIBinder,
+{
+    /// The sync interface associated with this async interface.
+    type Target: ?Sized;
+}
+
 /// Interface stability promise
 ///
 /// An interface can promise to be a stable vendor interface ([`Vintf`]), or
@@ -337,6 +366,26 @@
     pub fn downgrade(this: &Strong<I>) -> Weak<I> {
         Weak::new(this)
     }
+
+    /// Convert this synchronous binder handle into an asynchronous one.
+    pub fn into_async<P>(self) -> Strong<<I as ToAsyncInterface<P>>::Target>
+    where
+        I: ToAsyncInterface<P>,
+    {
+        // By implementing the ToAsyncInterface trait, it is guaranteed that the binder
+        // object is also valid for the target type.
+        FromIBinder::try_from(self.0.as_binder()).unwrap()
+    }
+
+    /// Convert this asynchronous binder handle into a synchronous one.
+    pub fn into_sync(self) -> Strong<<I as ToSyncInterface>::Target>
+    where
+        I: ToSyncInterface,
+    {
+        // By implementing the ToSyncInterface trait, it is guaranteed that the binder
+        // object is also valid for the target type.
+        FromIBinder::try_from(self.0.as_binder()).unwrap()
+    }
 }
 
 impl<I: FromIBinder + ?Sized> Clone for Strong<I> {
@@ -1017,6 +1066,14 @@
                     .expect(concat!("Error cloning interface ", stringify!($async_interface)))
             }
         }
+
+        impl<P: $crate::BinderAsyncPool> $crate::ToAsyncInterface<P> for dyn $interface {
+            type Target = dyn $async_interface<P>;
+        }
+
+        impl<P: $crate::BinderAsyncPool> $crate::ToSyncInterface for dyn $async_interface<P> {
+            type Target = dyn $interface;
+        }
         )?
     };
 }
diff --git a/libs/binder/rust/src/lib.rs b/libs/binder/rust/src/lib.rs
index b94dfa1..7c04a72 100644
--- a/libs/binder/rust/src/lib.rs
+++ b/libs/binder/rust/src/lib.rs
@@ -109,8 +109,8 @@
 
 pub use crate::binder::{
     BinderFeatures, FromIBinder, IBinder, IBinderInternal, Interface, InterfaceClass, Remotable,
-    Stability, Strong, TransactionCode, TransactionFlags, Weak, FIRST_CALL_TRANSACTION,
-    FLAG_CLEAR_BUF, FLAG_ONEWAY, FLAG_PRIVATE_LOCAL, LAST_CALL_TRANSACTION,
+    Stability, Strong, ToAsyncInterface, ToSyncInterface, TransactionCode, TransactionFlags, Weak,
+    FIRST_CALL_TRANSACTION, FLAG_CLEAR_BUF, FLAG_ONEWAY, FLAG_PRIVATE_LOCAL, LAST_CALL_TRANSACTION,
 };
 pub use crate::binder_async::{BoxFuture, BinderAsyncPool};
 pub use error::{status_t, ExceptionCode, Result, Status, StatusCode};
diff --git a/libs/binder/rust/tests/integration.rs b/libs/binder/rust/tests/integration.rs
index 40359b4..80dc476 100644
--- a/libs/binder/rust/tests/integration.rs
+++ b/libs/binder/rust/tests/integration.rs
@@ -100,6 +100,7 @@
     Test = FIRST_CALL_TRANSACTION,
     GetDumpArgs,
     GetSelinuxContext,
+    GetIsHandlingTransaction,
 }
 
 impl TryFrom<u32> for TestTransactionCode {
@@ -112,6 +113,7 @@
             _ if c == TestTransactionCode::GetSelinuxContext as u32 => {
                 Ok(TestTransactionCode::GetSelinuxContext)
             }
+            _ if c == TestTransactionCode::GetIsHandlingTransaction as u32 => Ok(TestTransactionCode::GetIsHandlingTransaction),
             _ => Err(StatusCode::UNKNOWN_TRANSACTION),
         }
     }
@@ -140,6 +142,10 @@
             ThreadState::with_calling_sid(|sid| sid.map(|s| s.to_string_lossy().into_owned()));
         sid.ok_or(StatusCode::UNEXPECTED_NULL)
     }
+
+    fn get_is_handling_transaction(&self) -> binder::Result<bool> {
+        Ok(binder::is_handling_transaction())
+    }
 }
 
 /// Trivial testing binder interface
@@ -152,6 +158,9 @@
 
     /// Returns the caller's SELinux context
     fn get_selinux_context(&self) -> binder::Result<String>;
+
+    /// Returns the value of calling `is_handling_transaction`.
+    fn get_is_handling_transaction(&self) -> binder::Result<bool>;
 }
 
 /// Async trivial testing binder interface
@@ -164,6 +173,9 @@
 
     /// Returns the caller's SELinux context
     fn get_selinux_context(&self) -> binder::BoxFuture<'static, binder::Result<String>>;
+
+    /// Returns the value of calling `is_handling_transaction`.
+    fn get_is_handling_transaction(&self) -> binder::BoxFuture<'static, binder::Result<bool>>;
 }
 
 declare_binder_interface! {
@@ -186,6 +198,7 @@
         TestTransactionCode::Test => reply.write(&service.test()?),
         TestTransactionCode::GetDumpArgs => reply.write(&service.get_dump_args()?),
         TestTransactionCode::GetSelinuxContext => reply.write(&service.get_selinux_context()?),
+        TestTransactionCode::GetIsHandlingTransaction => reply.write(&service.get_is_handling_transaction()?),
     }
 }
 
@@ -212,6 +225,15 @@
         )?;
         reply.read()
     }
+
+    fn get_is_handling_transaction(&self) -> binder::Result<bool> {
+        let reply = self.binder.transact(
+            TestTransactionCode::GetIsHandlingTransaction as TransactionCode,
+            0,
+            |_| Ok(()),
+        )?;
+        reply.read()
+    }
 }
 
 impl<P: binder::BinderAsyncPool> IATest<P> for BpTest {
@@ -238,6 +260,14 @@
             |reply| async move { reply?.read() }
         )
     }
+
+    fn get_is_handling_transaction(&self) -> binder::BoxFuture<'static, binder::Result<bool>> {
+        let binder = self.binder.clone();
+        P::spawn(
+            move || binder.transact(TestTransactionCode::GetIsHandlingTransaction as TransactionCode, 0, |_| Ok(())),
+            |reply| async move { reply?.read() }
+        )
+    }
 }
 
 impl ITest for Binder<BnTest> {
@@ -252,6 +282,10 @@
     fn get_selinux_context(&self) -> binder::Result<String> {
         self.0.get_selinux_context()
     }
+
+    fn get_is_handling_transaction(&self) -> binder::Result<bool> {
+        self.0.get_is_handling_transaction()
+    }
 }
 
 impl<P: binder::BinderAsyncPool> IATest<P> for Binder<BnTest> {
@@ -269,6 +303,11 @@
         let res = self.0.get_selinux_context();
         Box::pin(async move { res })
     }
+
+    fn get_is_handling_transaction(&self) -> binder::BoxFuture<'static, binder::Result<bool>> {
+        let res = self.0.get_is_handling_transaction();
+        Box::pin(async move { res })
+    }
 }
 
 /// Trivial testing binder interface
@@ -500,7 +539,7 @@
 
     #[tokio::test]
     async fn get_selinux_context_async() {
-        let service_name = "get_selinux_context";
+        let service_name = "get_selinux_context_async";
         let _process = ScopedServiceProcess::new(service_name);
         let test_client: Strong<dyn IATest<Tokio>> =
             binder_tokio::get_interface(service_name).await.expect("Did not get manager binder service");
@@ -510,6 +549,32 @@
         );
     }
 
+    #[tokio::test]
+    async fn get_selinux_context_sync_to_async() {
+        let service_name = "get_selinux_context";
+        let _process = ScopedServiceProcess::new(service_name);
+        let test_client: Strong<dyn ITest> =
+            binder::get_interface(service_name).expect("Did not get manager binder service");
+        let test_client = test_client.into_async::<Tokio>();
+        assert_eq!(
+            test_client.get_selinux_context().await.unwrap(),
+            get_expected_selinux_context()
+        );
+    }
+
+    #[tokio::test]
+    async fn get_selinux_context_async_to_sync() {
+        let service_name = "get_selinux_context";
+        let _process = ScopedServiceProcess::new(service_name);
+        let test_client: Strong<dyn IATest<Tokio>> =
+            binder_tokio::get_interface(service_name).await.expect("Did not get manager binder service");
+        let test_client = test_client.into_sync();
+        assert_eq!(
+            test_client.get_selinux_context().unwrap(),
+            get_expected_selinux_context()
+        );
+    }
+
     struct Bools {
         binder_died: Arc<AtomicBool>,
         binder_dealloc: Arc<AtomicBool>,
@@ -867,4 +932,45 @@
             Err(err) => assert_eq!(err, binder::StatusCode::BAD_VALUE),
         }
     }
+
+    #[test]
+    fn get_is_handling_transaction() {
+        let service_name = "get_is_handling_transaction";
+        let _process = ScopedServiceProcess::new(service_name);
+        let test_client: Strong<dyn ITest> =
+            binder::get_interface(service_name).expect("Did not get manager binder service");
+        // Should be true externally.
+        assert!(test_client.get_is_handling_transaction().unwrap());
+
+        // Should be false locally.
+        assert!(!binder::is_handling_transaction());
+
+        // Should also be false in spawned thread.
+        std::thread::spawn(|| {
+            assert!(!binder::is_handling_transaction());
+        }).join().unwrap();
+    }
+
+    #[tokio::test]
+    async fn get_is_handling_transaction_async() {
+        let service_name = "get_is_handling_transaction_async";
+        let _process = ScopedServiceProcess::new(service_name);
+        let test_client: Strong<dyn IATest<Tokio>> =
+            binder_tokio::get_interface(service_name).await.expect("Did not get manager binder service");
+        // Should be true externally.
+        assert!(test_client.get_is_handling_transaction().await.unwrap());
+
+        // Should be false locally.
+        assert!(!binder::is_handling_transaction());
+
+        // Should also be false in spawned task.
+        tokio::spawn(async {
+            assert!(!binder::is_handling_transaction());
+        }).await.unwrap();
+
+        // And in spawn_blocking task.
+        tokio::task::spawn_blocking(|| {
+            assert!(!binder::is_handling_transaction());
+        }).await.unwrap();
+    }
 }
diff --git a/libs/graphicsenv/GpuStatsInfo.cpp b/libs/graphicsenv/GpuStatsInfo.cpp
index f2d0943..858739c 100644
--- a/libs/graphicsenv/GpuStatsInfo.cpp
+++ b/libs/graphicsenv/GpuStatsInfo.cpp
@@ -88,6 +88,7 @@
     if ((status = parcel->writeBool(cpuVulkanInUse)) != OK) return status;
     if ((status = parcel->writeBool(falsePrerotation)) != OK) return status;
     if ((status = parcel->writeBool(gles1InUse)) != OK) return status;
+    if ((status = parcel->writeBool(angleInUse)) != OK) return status;
     return OK;
 }
 
@@ -101,6 +102,7 @@
     if ((status = parcel->readBool(&cpuVulkanInUse)) != OK) return status;
     if ((status = parcel->readBool(&falsePrerotation)) != OK) return status;
     if ((status = parcel->readBool(&gles1InUse)) != OK) return status;
+    if ((status = parcel->readBool(&angleInUse)) != OK) return status;
     return OK;
 }
 
@@ -111,6 +113,7 @@
     StringAppendF(&result, "cpuVulkanInUse = %d\n", cpuVulkanInUse);
     StringAppendF(&result, "falsePrerotation = %d\n", falsePrerotation);
     StringAppendF(&result, "gles1InUse = %d\n", gles1InUse);
+    StringAppendF(&result, "angleInUse = %d\n", angleInUse);
     result.append("glDriverLoadingTime:");
     for (int32_t loadingTime : glDriverLoadingTime) {
         StringAppendF(&result, " %d", loadingTime);
diff --git a/libs/graphicsenv/include/graphicsenv/GpuStatsInfo.h b/libs/graphicsenv/include/graphicsenv/GpuStatsInfo.h
index 9aba69f..5b513d2 100644
--- a/libs/graphicsenv/include/graphicsenv/GpuStatsInfo.h
+++ b/libs/graphicsenv/include/graphicsenv/GpuStatsInfo.h
@@ -16,6 +16,7 @@
 
 #pragma once
 
+#include <chrono>
 #include <string>
 #include <vector>
 
@@ -52,7 +53,7 @@
 };
 
 /*
- * class for transporting gpu app stats from GpuService to authorized recipents.
+ * class for transporting gpu app stats from GpuService to authorized recipients.
  * This class is intended to be a data container.
  */
 class GpuStatsAppInfo : public Parcelable {
@@ -72,6 +73,9 @@
     bool cpuVulkanInUse = false;
     bool falsePrerotation = false;
     bool gles1InUse = false;
+    bool angleInUse = false;
+
+    std::chrono::time_point<std::chrono::system_clock> lastAccessTime;
 };
 
 /*
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index e1fe26a..aafa5e4 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -62,6 +62,14 @@
 
 ANDROID_SINGLETON_STATIC_INSTANCE(ComposerService);
 
+namespace {
+// Initialize transaction id counter used to generate transaction ids
+std::atomic<uint32_t> idCounter = 0;
+int64_t generateId() {
+    return (((int64_t)getpid()) << 32) | ++idCounter;
+}
+} // namespace
+
 ComposerService::ComposerService()
 : Singleton<ComposerService>() {
     Mutex::Autolock _l(mLock);
@@ -535,10 +543,6 @@
 
 // ---------------------------------------------------------------------------
 
-// Initialize transaction id counter used to generate transaction ids
-// Transactions will start counting at 1, 0 is used for invalid transactions
-std::atomic<uint32_t> SurfaceComposerClient::Transaction::idCounter = 1;
-
 SurfaceComposerClient::Transaction::Transaction() {
     mId = generateId();
 }
@@ -570,9 +574,6 @@
     return nullptr;
 }
 
-int64_t SurfaceComposerClient::Transaction::generateId() {
-    return (((int64_t)getpid()) << 32) | idCounter++;
-}
 
 status_t SurfaceComposerClient::Transaction::readFromParcel(const Parcel* parcel) {
     const uint32_t forceSynchronous = parcel->readUint32();
@@ -825,7 +826,7 @@
 
     sp<IBinder> applyToken = IInterface::asBinder(TransactionCompletedListener::getIInstance());
     sf->setTransactionState(FrameTimelineInfo{}, {}, {}, 0, applyToken, {}, systemTime(), true,
-                            uncacheBuffer, false, {}, 0 /* Undefined transactionId */);
+                            uncacheBuffer, false, {}, generateId());
 }
 
 void SurfaceComposerClient::Transaction::cacheBuffers() {
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 0fe1253..17b4846 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -366,8 +366,6 @@
 
     class Transaction : public Parcelable {
     private:
-        static std::atomic<uint32_t> idCounter;
-        int64_t generateId();
         void releaseBufferIfOverwriting(const layer_state_t& state);
 
     protected:
diff --git a/libs/input/Input.cpp b/libs/input/Input.cpp
index 44487c3..f0b97a7 100644
--- a/libs/input/Input.cpp
+++ b/libs/input/Input.cpp
@@ -192,8 +192,8 @@
     return {{VerifiedInputEvent::Type::KEY, event.getDeviceId(), event.getEventTime(),
              event.getSource(), event.getDisplayId()},
             event.getAction(),
-            event.getDownTime(),
             event.getFlags() & VERIFIED_KEY_EVENT_FLAGS,
+            event.getDownTime(),
             event.getKeyCode(),
             event.getScanCode(),
             event.getMetaState(),
@@ -206,8 +206,8 @@
             event.getRawX(0),
             event.getRawY(0),
             event.getActionMasked(),
-            event.getDownTime(),
             event.getFlags() & VERIFIED_MOTION_EVENT_FLAGS,
+            event.getDownTime(),
             event.getMetaState(),
             event.getButtonState()};
 }
diff --git a/libs/nativewindow/ANativeWindow.cpp b/libs/nativewindow/ANativeWindow.cpp
index c447d31..18a4b2d 100644
--- a/libs/nativewindow/ANativeWindow.cpp
+++ b/libs/nativewindow/ANativeWindow.cpp
@@ -176,6 +176,8 @@
         static_cast<int>(HAL_DATASPACE_BT2020_HLG));
     static_assert(static_cast<int>(ADATASPACE_BT2020_ITU_HLG) ==
         static_cast<int>(HAL_DATASPACE_BT2020_ITU_HLG));
+    static_assert(static_cast<int>(DEPTH) == static_cast<int>(HAL_DATASPACE_DEPTH));
+    static_assert(static_cast<int>(DYNAMIC_DEPTH) == static_cast<int>(HAL_DATASPACE_DYNAMIC_DEPTH));
 
     if (!window || !query(window, NATIVE_WINDOW_IS_VALID) ||
             !isDataSpaceValid(window, dataSpace)) {
diff --git a/libs/nativewindow/include/android/data_space.h b/libs/nativewindow/include/android/data_space.h
index 30ac220..771844f 100644
--- a/libs/nativewindow/include/android/data_space.h
+++ b/libs/nativewindow/include/android/data_space.h
@@ -541,7 +541,21 @@
      *
      * Use limited range, hybrid log gamma transfer and BT2020 standard.
      */
-    ADATASPACE_BT2020_ITU_HLG = 302383104 // STANDARD_BT2020 | TRANSFER_HLG | RANGE_LIMITED
+    ADATASPACE_BT2020_ITU_HLG = 302383104, // STANDARD_BT2020 | TRANSFER_HLG | RANGE_LIMITED
+
+    /**
+     * Depth:
+     *
+     * This value is valid with formats HAL_PIXEL_FORMAT_Y16 and HAL_PIXEL_FORMAT_BLOB.
+     */
+    DEPTH = 4096,
+
+    /**
+     * ISO 16684-1:2011(E) Dynamic Depth:
+     *
+     * Embedded depth metadata following the dynamic depth specification.
+     */
+    DYNAMIC_DEPTH = 4098
 };
 
 __END_DECLS
diff --git a/libs/renderengine/include/renderengine/DisplaySettings.h b/libs/renderengine/include/renderengine/DisplaySettings.h
index d395d06..b4cab39 100644
--- a/libs/renderengine/include/renderengine/DisplaySettings.h
+++ b/libs/renderengine/include/renderengine/DisplaySettings.h
@@ -57,8 +57,10 @@
     // orientation.
     uint32_t orientation = ui::Transform::ROT_0;
 
-    // SDR white point, -1f if unknown
-    float sdrWhitePointNits = -1.f;
+    // Target luminance of the display. -1f if unknown.
+    // All layers will be dimmed by (max(layer white points) / targetLuminanceNits).
+    // If the target luminance is unknown, then no display-level dimming occurs.
+    float targetLuminanceNits = -1.f;
 };
 
 static inline bool operator==(const DisplaySettings& lhs, const DisplaySettings& rhs) {
diff --git a/libs/renderengine/include/renderengine/LayerSettings.h b/libs/renderengine/include/renderengine/LayerSettings.h
index 715f3f8..702e8b0 100644
--- a/libs/renderengine/include/renderengine/LayerSettings.h
+++ b/libs/renderengine/include/renderengine/LayerSettings.h
@@ -171,6 +171,12 @@
 
     // Name associated with the layer for debugging purposes.
     std::string name;
+
+    // Luminance of the white point for this layer. Used for linear dimming.
+    // Individual layers will be dimmed by (whitePointNits / maxWhitePoint).
+    // If white point nits are unknown, then this layer is assumed to have the
+    // same luminance as the brightest layer in the scene.
+    float whitePointNits = -1.f;
 };
 
 // Keep in sync with custom comparison function in
diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.cpp b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
index 376e279..cc90946 100644
--- a/libs/renderengine/skia/SkiaGLRenderEngine.cpp
+++ b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
@@ -46,6 +46,7 @@
 #include <cmath>
 #include <cstdint>
 #include <memory>
+#include <numeric>
 
 #include "../gl/GLExtensions.h"
 #include "Cache.h"
@@ -612,33 +613,33 @@
     AutoBackendTexture::CleanupManager& mMgr;
 };
 
-sk_sp<SkShader> SkiaGLRenderEngine::createRuntimeEffectShader(sk_sp<SkShader> shader,
-                                                              const LayerSettings& layer,
-                                                              const DisplaySettings& display,
-                                                              bool undoPremultipliedAlpha,
-                                                              bool requiresLinearEffect) {
-    const auto stretchEffect = layer.stretchEffect;
+sk_sp<SkShader> SkiaGLRenderEngine::createRuntimeEffectShader(
+        const RuntimeEffectShaderParameters& parameters) {
     // The given surface will be stretched by HWUI via matrix transformation
     // which gets similar results for most surfaces
     // Determine later on if we need to leverage the stertch shader within
     // surface flinger
+    const auto& stretchEffect = parameters.layer.stretchEffect;
+    auto shader = parameters.shader;
     if (stretchEffect.hasEffect()) {
-        const auto targetBuffer = layer.source.buffer.buffer;
+        const auto targetBuffer = parameters.layer.source.buffer.buffer;
         const auto graphicBuffer = targetBuffer ? targetBuffer->getBuffer() : nullptr;
-        if (graphicBuffer && shader) {
+        if (graphicBuffer && parameters.shader) {
             shader = mStretchShaderFactory.createSkShader(shader, stretchEffect);
         }
     }
 
-    if (requiresLinearEffect) {
-        const ui::Dataspace inputDataspace =
-                mUseColorManagement ? layer.sourceDataspace : ui::Dataspace::V0_SRGB_LINEAR;
-        const ui::Dataspace outputDataspace =
-                mUseColorManagement ? display.outputDataspace : ui::Dataspace::V0_SRGB_LINEAR;
+    if (parameters.requiresLinearEffect) {
+        const ui::Dataspace inputDataspace = mUseColorManagement ? parameters.layer.sourceDataspace
+                                                                 : ui::Dataspace::V0_SRGB_LINEAR;
+        const ui::Dataspace outputDataspace = mUseColorManagement
+                ? parameters.display.outputDataspace
+                : ui::Dataspace::V0_SRGB_LINEAR;
 
-        auto effect = shaders::LinearEffect{.inputDataspace = inputDataspace,
-                                            .outputDataspace = outputDataspace,
-                                            .undoPremultipliedAlpha = undoPremultipliedAlpha};
+        auto effect =
+                shaders::LinearEffect{.inputDataspace = inputDataspace,
+                                      .outputDataspace = outputDataspace,
+                                      .undoPremultipliedAlpha = parameters.undoPremultipliedAlpha};
 
         auto effectIter = mRuntimeEffects.find(effect);
         sk_sp<SkRuntimeEffect> runtimeEffect = nullptr;
@@ -648,16 +649,16 @@
         } else {
             runtimeEffect = effectIter->second;
         }
-        float maxLuminance = layer.source.buffer.maxLuminanceNits;
-        // If the buffer doesn't have a max luminance, treat it as SDR & use the display's SDR
-        // white point
-        if (maxLuminance <= 0.f) {
-            maxLuminance = display.sdrWhitePointNits;
-        }
-        return createLinearEffectShader(shader, effect, runtimeEffect, layer.colorTransform,
-                                        display.maxLuminance, maxLuminance);
+        mat4 colorTransform = parameters.layer.colorTransform;
+
+        colorTransform *=
+                mat4::scale(vec4(parameters.layerDimmingRatio, parameters.layerDimmingRatio,
+                                 parameters.layerDimmingRatio, 1.f));
+        return createLinearEffectShader(parameters.shader, effect, runtimeEffect, colorTransform,
+                                        parameters.display.maxLuminance,
+                                        parameters.layer.source.buffer.maxLuminanceNits);
     }
-    return shader;
+    return parameters.shader;
 }
 
 void SkiaGLRenderEngine::initCanvas(SkCanvas* canvas, const DisplaySettings& display) {
@@ -730,6 +731,11 @@
     return roundedRect;
 }
 
+static bool equalsWithinMargin(float expected, float value, float margin) {
+    LOG_ALWAYS_FATAL_IF(margin < 0.f, "Margin is negative!");
+    return std::abs(expected - value) < margin;
+}
+
 void SkiaGLRenderEngine::drawLayersInternal(
         const std::shared_ptr<std::promise<RenderEngineResult>>&& resultPromise,
         const DisplaySettings& display, const std::vector<LayerSettings>& layers,
@@ -791,6 +797,18 @@
     const bool ctModifiesAlpha =
             displayColorTransform && !displayColorTransform->isAlphaUnchanged();
 
+    // Find the max layer white point to determine the max luminance of the scene...
+    const float maxLayerWhitePoint = std::transform_reduce(
+            layers.cbegin(), layers.cend(), 0.f,
+            [](float left, float right) { return std::max(left, right); },
+            [&](const auto& l) { return l.whitePointNits; });
+
+    // ...and compute the dimming ratio if dimming is requested
+    const float displayDimmingRatio = display.targetLuminanceNits > 0.f &&
+                    maxLayerWhitePoint > 0.f && display.targetLuminanceNits > maxLayerWhitePoint
+            ? maxLayerWhitePoint / display.targetLuminanceNits
+            : 1.f;
+
     // Find if any layers have requested blur, we'll use that info to decide when to render to an
     // offscreen buffer and when to render to the native buffer.
     sk_sp<SkSurface> activeSurface(dstSurface);
@@ -964,11 +982,14 @@
             drawShadow(canvas, rrect, layer.shadow);
         }
 
+        const float layerDimmingRatio = layer.whitePointNits <= 0.f
+                ? displayDimmingRatio
+                : (layer.whitePointNits / maxLayerWhitePoint) * displayDimmingRatio;
+
         const bool requiresLinearEffect = layer.colorTransform != mat4() ||
                 (mUseColorManagement &&
                  needsToneMapping(layer.sourceDataspace, display.outputDataspace)) ||
-                (display.sdrWhitePointNits > 0.f &&
-                 display.sdrWhitePointNits != display.maxLuminance);
+                !equalsWithinMargin(1.f, layerDimmingRatio, 0.001f);
 
         // quick abort from drawing the remaining portion of the layer
         if (layer.skipContentDraw ||
@@ -1067,9 +1088,20 @@
                                                            toSkColorSpace(layerDataspace)));
             }
 
-            paint.setShader(createRuntimeEffectShader(shader, layer, display,
-                                                      !item.isOpaque && item.usePremultipliedAlpha,
-                                                      requiresLinearEffect));
+            paint.setShader(createRuntimeEffectShader(
+                    RuntimeEffectShaderParameters{.shader = shader,
+                                                  .layer = layer,
+                                                  .display = display,
+                                                  .undoPremultipliedAlpha = !item.isOpaque &&
+                                                          item.usePremultipliedAlpha,
+                                                  .requiresLinearEffect = requiresLinearEffect,
+                                                  .layerDimmingRatio = layerDimmingRatio}));
+
+            // Turn on dithering when dimming beyond this threshold.
+            static constexpr float kDimmingThreshold = 0.2f;
+            if (layerDimmingRatio <= kDimmingThreshold) {
+                paint.setDither(true);
+            }
             paint.setAlphaf(layer.alpha);
         } else {
             ATRACE_NAME("DrawColor");
@@ -1079,9 +1111,13 @@
                                                                 .fB = color.b,
                                                                 .fA = layer.alpha},
                                                       toSkColorSpace(layerDataspace));
-            paint.setShader(createRuntimeEffectShader(shader, layer, display,
-                                                      /* undoPremultipliedAlpha */ false,
-                                                      requiresLinearEffect));
+            paint.setShader(createRuntimeEffectShader(
+                    RuntimeEffectShaderParameters{.shader = shader,
+                                                  .layer = layer,
+                                                  .display = display,
+                                                  .undoPremultipliedAlpha = false,
+                                                  .requiresLinearEffect = requiresLinearEffect,
+                                                  .layerDimmingRatio = layerDimmingRatio}));
         }
 
         if (layer.disableBlending) {
diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.h b/libs/renderengine/skia/SkiaGLRenderEngine.h
index 53792f9..a650313 100644
--- a/libs/renderengine/skia/SkiaGLRenderEngine.h
+++ b/libs/renderengine/skia/SkiaGLRenderEngine.h
@@ -106,12 +106,18 @@
     void initCanvas(SkCanvas* canvas, const DisplaySettings& display);
     void drawShadow(SkCanvas* canvas, const SkRRect& casterRRect,
                     const ShadowSettings& shadowSettings);
+
     // If requiresLinearEffect is true or the layer has a stretchEffect a new shader is returned.
     // Otherwise it returns the input shader.
-    sk_sp<SkShader> createRuntimeEffectShader(sk_sp<SkShader> shader, const LayerSettings& layer,
-                                              const DisplaySettings& display,
-                                              bool undoPremultipliedAlpha,
-                                              bool requiresLinearEffect);
+    struct RuntimeEffectShaderParameters {
+        sk_sp<SkShader> shader;
+        const LayerSettings& layer;
+        const DisplaySettings& display;
+        bool undoPremultipliedAlpha;
+        bool requiresLinearEffect;
+        float layerDimmingRatio;
+    };
+    sk_sp<SkShader> createRuntimeEffectShader(const RuntimeEffectShaderParameters&);
 
     EGLDisplay mEGLDisplay;
     EGLContext mEGLContext;
diff --git a/libs/renderengine/tests/RenderEngineTest.cpp b/libs/renderengine/tests/RenderEngineTest.cpp
index 8259063..eb2b2dc 100644
--- a/libs/renderengine/tests/RenderEngineTest.cpp
+++ b/libs/renderengine/tests/RenderEngineTest.cpp
@@ -208,6 +208,21 @@
                                                  renderengine::ExternalTexture::Usage::WRITEABLE);
     }
 
+    std::shared_ptr<renderengine::ExternalTexture> allocateAndFillSourceBuffer(uint32_t width,
+                                                                               uint32_t height,
+                                                                               ubyte4 color) {
+        const auto buffer = allocateSourceBuffer(width, height);
+        uint8_t* pixels;
+        buffer->getBuffer()->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
+                                  reinterpret_cast<void**>(&pixels));
+        pixels[0] = color.r;
+        pixels[1] = color.g;
+        pixels[2] = color.b;
+        pixels[3] = color.a;
+        buffer->getBuffer()->unlock();
+        return buffer;
+    }
+
     RenderEngineTest() {
         const ::testing::TestInfo* const test_info =
                 ::testing::UnitTest::GetInstance()->current_test_info();
@@ -2195,6 +2210,133 @@
     expectBufferColor(rect, 0, 128, 0, 128);
 }
 
+TEST_P(RenderEngineTest, testDimming) {
+    if (GetParam()->type() == renderengine::RenderEngine::RenderEngineType::GLES) {
+        return;
+    }
+    initializeRenderEngine();
+
+    const auto displayRect = Rect(3, 1);
+    const renderengine::DisplaySettings display{
+            .physicalDisplay = displayRect,
+            .clip = displayRect,
+            .outputDataspace = ui::Dataspace::V0_SRGB_LINEAR,
+            .targetLuminanceNits = 1000.f,
+    };
+
+    const auto greenBuffer = allocateAndFillSourceBuffer(1, 1, ubyte4(0, 255, 0, 255));
+    const auto blueBuffer = allocateAndFillSourceBuffer(1, 1, ubyte4(0, 0, 255, 255));
+    const auto redBuffer = allocateAndFillSourceBuffer(1, 1, ubyte4(255, 0, 0, 255));
+
+    const renderengine::LayerSettings greenLayer{
+            .geometry.boundaries = FloatRect(0.f, 0.f, 1.f, 1.f),
+            .source =
+                    renderengine::PixelSource{
+                            .buffer =
+                                    renderengine::Buffer{
+                                            .buffer = greenBuffer,
+                                            .usePremultipliedAlpha = true,
+                                    },
+                    },
+            .alpha = 1.0f,
+            .sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR,
+            .whitePointNits = 200.f,
+    };
+
+    const renderengine::LayerSettings blueLayer{
+            .geometry.boundaries = FloatRect(1.f, 0.f, 2.f, 1.f),
+            .source =
+                    renderengine::PixelSource{
+                            .buffer =
+                                    renderengine::Buffer{
+                                            .buffer = blueBuffer,
+                                            .usePremultipliedAlpha = true,
+                                    },
+                    },
+            .alpha = 1.0f,
+            .sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR,
+            .whitePointNits = 1000.f / 51.f,
+    };
+
+    const renderengine::LayerSettings redLayer{
+            .geometry.boundaries = FloatRect(2.f, 0.f, 3.f, 1.f),
+            .source =
+                    renderengine::PixelSource{
+                            .buffer =
+                                    renderengine::Buffer{
+                                            .buffer = redBuffer,
+                                            .usePremultipliedAlpha = true,
+                                    },
+                    },
+            .alpha = 1.0f,
+            .sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR,
+            // When the white point is not set for a layer, just ignore it and treat it as the same
+            // as the max layer
+            .whitePointNits = -1.f,
+    };
+
+    std::vector<renderengine::LayerSettings> layers{greenLayer, blueLayer, redLayer};
+    invokeDraw(display, layers);
+
+    expectBufferColor(Rect(1, 1), 0, 51, 0, 255, 1);
+    expectBufferColor(Rect(1, 0, 2, 1), 0, 0, 5, 255, 1);
+    expectBufferColor(Rect(2, 0, 3, 1), 51, 0, 0, 255, 1);
+}
+
+TEST_P(RenderEngineTest, testDimming_withoutTargetLuminance) {
+    initializeRenderEngine();
+    if (GetParam()->type() == renderengine::RenderEngine::RenderEngineType::GLES) {
+        return;
+    }
+
+    const auto displayRect = Rect(2, 1);
+    const renderengine::DisplaySettings display{
+            .physicalDisplay = displayRect,
+            .clip = displayRect,
+            .outputDataspace = ui::Dataspace::V0_SRGB_LINEAR,
+            .targetLuminanceNits = -1.f,
+    };
+
+    const auto greenBuffer = allocateAndFillSourceBuffer(1, 1, ubyte4(0, 255, 0, 255));
+    const auto blueBuffer = allocateAndFillSourceBuffer(1, 1, ubyte4(0, 0, 255, 255));
+
+    const renderengine::LayerSettings greenLayer{
+            .geometry.boundaries = FloatRect(0.f, 0.f, 1.f, 1.f),
+            .source =
+                    renderengine::PixelSource{
+                            .buffer =
+                                    renderengine::Buffer{
+                                            .buffer = greenBuffer,
+                                            .usePremultipliedAlpha = true,
+                                    },
+                    },
+            .alpha = 1.0f,
+            .sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR,
+            .whitePointNits = 200.f,
+    };
+
+    const renderengine::LayerSettings blueLayer{
+            .geometry.boundaries = FloatRect(1.f, 0.f, 2.f, 1.f),
+            .source =
+                    renderengine::PixelSource{
+                            .buffer =
+                                    renderengine::Buffer{
+                                            .buffer = blueBuffer,
+                                            .usePremultipliedAlpha = true,
+                                    },
+                    },
+            .alpha = 1.0f,
+            .sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR,
+            .whitePointNits = 1000.f,
+    };
+
+    std::vector<renderengine::LayerSettings> layers{greenLayer, blueLayer};
+    invokeDraw(display, layers);
+
+    expectBufferColor(Rect(1, 1), 0, 51, 0, 255, 1);
+    expectBufferColor(Rect(1, 0, 2, 1), 0, 0, 255, 255);
+}
+
 TEST_P(RenderEngineTest, test_isOpaque) {
     initializeRenderEngine();
 
diff --git a/libs/ui/include_types/ui/DataspaceUtils.h b/libs/ui/include_types/ui/DataspaceUtils.h
new file mode 100644
index 0000000..a461cb4
--- /dev/null
+++ b/libs/ui/include_types/ui/DataspaceUtils.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <ui/GraphicTypes.h>
+
+namespace android {
+
+inline bool isHdrDataspace(ui::Dataspace dataspace) {
+    const auto transfer = dataspace & HAL_DATASPACE_TRANSFER_MASK;
+
+    return transfer == HAL_DATASPACE_TRANSFER_ST2084 || transfer == HAL_DATASPACE_TRANSFER_HLG;
+}
+
+} // namespace android
\ No newline at end of file
diff --git a/libs/ui/tests/Android.bp b/libs/ui/tests/Android.bp
index 0ee15f2..22fbf45 100644
--- a/libs/ui/tests/Android.bp
+++ b/libs/ui/tests/Android.bp
@@ -163,3 +163,13 @@
         "-Werror",
     ],
 }
+
+cc_test {
+    name: "DataspaceUtils_test",
+    shared_libs: ["libui"],
+    srcs: ["DataspaceUtils_test.cpp"],
+    cflags: [
+        "-Wall",
+        "-Werror",
+    ],
+}
diff --git a/libs/ui/tests/DataspaceUtils_test.cpp b/libs/ui/tests/DataspaceUtils_test.cpp
new file mode 100644
index 0000000..3e09671
--- /dev/null
+++ b/libs/ui/tests/DataspaceUtils_test.cpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#undef LOG_TAG
+#define LOG_TAG "DataspaceUtilsTest"
+
+#include <gtest/gtest.h>
+#include <ui/DataspaceUtils.h>
+
+namespace android {
+
+class DataspaceUtilsTest : public testing::Test {};
+
+TEST_F(DataspaceUtilsTest, isHdrDataspace) {
+    EXPECT_TRUE(isHdrDataspace(ui::Dataspace::BT2020_ITU_HLG));
+    EXPECT_TRUE(isHdrDataspace(ui::Dataspace::BT2020_ITU_PQ));
+    EXPECT_TRUE(isHdrDataspace(ui::Dataspace::BT2020_PQ));
+    EXPECT_TRUE(isHdrDataspace(ui::Dataspace::BT2020_HLG));
+
+    EXPECT_FALSE(isHdrDataspace(ui::Dataspace::V0_SRGB_LINEAR));
+    // scRGB defines a very wide gamut but not an expanded luminance range
+    EXPECT_FALSE(isHdrDataspace(ui::Dataspace::V0_SCRGB_LINEAR));
+    EXPECT_FALSE(isHdrDataspace(ui::Dataspace::V0_SRGB));
+    EXPECT_FALSE(isHdrDataspace(ui::Dataspace::V0_SCRGB));
+    EXPECT_FALSE(isHdrDataspace(ui::Dataspace::V0_JFIF));
+    EXPECT_FALSE(isHdrDataspace(ui::Dataspace::V0_BT601_625));
+    EXPECT_FALSE(isHdrDataspace(ui::Dataspace::V0_BT601_525));
+    EXPECT_FALSE(isHdrDataspace(ui::Dataspace::V0_BT709));
+    EXPECT_FALSE(isHdrDataspace(ui::Dataspace::DCI_P3_LINEAR));
+    EXPECT_FALSE(isHdrDataspace(ui::Dataspace::DCI_P3));
+    EXPECT_FALSE(isHdrDataspace(ui::Dataspace::DISPLAY_P3_LINEAR));
+    EXPECT_FALSE(isHdrDataspace(ui::Dataspace::DISPLAY_P3));
+    EXPECT_FALSE(isHdrDataspace(ui::Dataspace::ADOBE_RGB));
+    EXPECT_FALSE(isHdrDataspace(ui::Dataspace::BT2020_LINEAR));
+    EXPECT_FALSE(isHdrDataspace(ui::Dataspace::BT2020));
+    EXPECT_FALSE(isHdrDataspace(ui::Dataspace::BT2020_ITU));
+    EXPECT_FALSE(isHdrDataspace(ui::Dataspace::DISPLAY_BT2020));
+}
+
+} // namespace android
diff --git a/opengl/libs/EGL/egl_platform_entries.cpp b/opengl/libs/EGL/egl_platform_entries.cpp
index de36a7a..f4dbe49 100644
--- a/opengl/libs/EGL/egl_platform_entries.cpp
+++ b/opengl/libs/EGL/egl_platform_entries.cpp
@@ -29,6 +29,7 @@
 #include <private/android/AHardwareBufferHelpers.h>
 #include <stdlib.h>
 #include <string.h>
+#include <aidl/android/hardware/graphics/common/PixelFormat.h>
 
 #include <condition_variable>
 #include <deque>
@@ -564,9 +565,11 @@
     newList.push_back(EGL_NONE);
 }
 
+using PixelFormat = aidl::android::hardware::graphics::common::PixelFormat;
+
 // Gets the native pixel format corrsponding to the passed EGLConfig.
 void getNativePixelFormat(EGLDisplay dpy, egl_connection_t* cnx, EGLConfig config,
-                          android_pixel_format* format) {
+                          PixelFormat* format) {
     // Set the native window's buffers format to match what this config requests.
     // Whether to use sRGB gamma is not part of the EGLconfig, but is part
     // of our native format. So if sRGB gamma is requested, we have to
@@ -599,28 +602,30 @@
     //    strip colorspace from attribs.
     // endif
     if (a == 0) {
-        if (colorDepth <= 16) {
-            *format = HAL_PIXEL_FORMAT_RGB_565;
+        if (8 == r && 0 == g && 0 == b) {
+            *format = PixelFormat::R_8;
+        } else if (colorDepth <= 16) {
+            *format = PixelFormat::RGB_565;
         } else {
             if (componentType == EGL_COLOR_COMPONENT_TYPE_FIXED_EXT) {
                 if (colorDepth > 24) {
-                    *format = HAL_PIXEL_FORMAT_RGBA_1010102;
+                    *format = PixelFormat::RGBA_1010102;
                 } else {
-                    *format = HAL_PIXEL_FORMAT_RGBX_8888;
+                    *format = PixelFormat::RGBX_8888;
                 }
             } else {
-                *format = HAL_PIXEL_FORMAT_RGBA_FP16;
+                *format = PixelFormat::RGBA_FP16;
             }
         }
     } else {
         if (componentType == EGL_COLOR_COMPONENT_TYPE_FIXED_EXT) {
             if (colorDepth > 24) {
-                *format = HAL_PIXEL_FORMAT_RGBA_1010102;
+                *format = PixelFormat::RGBA_1010102;
             } else {
-                *format = HAL_PIXEL_FORMAT_RGBA_8888;
+                *format = PixelFormat::RGBA_8888;
             }
         } else {
-            *format = HAL_PIXEL_FORMAT_RGBA_FP16;
+            *format = PixelFormat::RGBA_FP16;
         }
     }
 }
@@ -678,7 +683,7 @@
     }
 
     EGLDisplay iDpy = dp->disp.dpy;
-    android_pixel_format format;
+    PixelFormat format;
     getNativePixelFormat(iDpy, cnx, config, &format);
 
     // now select correct colorspace and dataspace based on user's attribute list
@@ -694,7 +699,7 @@
     attrib_list = strippedAttribList.data();
 
     if (!cnx->useAngle) {
-        int err = native_window_set_buffers_format(window, format);
+        int err = native_window_set_buffers_format(window, static_cast<int>(format));
         if (err != 0) {
             ALOGE("error setting native window pixel format: %s (%d)", strerror(-err), err);
             native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
@@ -818,7 +823,7 @@
     if (!dp) return EGL_NO_SURFACE;
 
     EGLDisplay iDpy = dp->disp.dpy;
-    android_pixel_format format;
+    PixelFormat format;
     getNativePixelFormat(iDpy, cnx, config, &format);
 
     // Select correct colorspace based on user's attribute list
diff --git a/services/gpuservice/gpustats/GpuStats.cpp b/services/gpuservice/gpustats/GpuStats.cpp
index 220952d..d033453 100644
--- a/services/gpuservice/gpustats/GpuStats.cpp
+++ b/services/gpuservice/gpustats/GpuStats.cpp
@@ -84,6 +84,38 @@
     }
 }
 
+void GpuStats::purgeOldDriverStats() {
+    ALOG_ASSERT(mAppStats.size() == MAX_NUM_APP_RECORDS);
+
+    struct GpuStatsApp {
+        // Key is <app package name>+<driver version code>.
+        const std::string *appStatsKey = nullptr;
+        const std::chrono::time_point<std::chrono::system_clock> *lastAccessTime = nullptr;
+    };
+    std::vector<GpuStatsApp> gpuStatsApps(MAX_NUM_APP_RECORDS);
+
+    // Create a list of pointers to package names and their last access times.
+    int index = 0;
+    for (const auto & [appStatsKey, gpuStatsAppInfo] : mAppStats) {
+        GpuStatsApp &gpuStatsApp = gpuStatsApps[index];
+        gpuStatsApp.appStatsKey = &appStatsKey;
+        gpuStatsApp.lastAccessTime = &gpuStatsAppInfo.lastAccessTime;
+        ++index;
+    }
+
+    // Sort the list with the oldest access times at the front.
+    std::sort(gpuStatsApps.begin(), gpuStatsApps.end(), [](GpuStatsApp a, GpuStatsApp b) -> bool {
+        return *a.lastAccessTime < *b.lastAccessTime;
+    });
+
+    // Remove the oldest packages from mAppStats to make room for new apps.
+    for (int i = 0; i < APP_RECORD_HEADROOM; ++i) {
+        mAppStats.erase(*gpuStatsApps[i].appStatsKey);
+        gpuStatsApps[i].appStatsKey = nullptr;
+        gpuStatsApps[i].lastAccessTime = nullptr;
+    }
+}
+
 void GpuStats::insertDriverStats(const std::string& driverPackageName,
                                  const std::string& driverVersionName, uint64_t driverVersionCode,
                                  int64_t driverBuildTime, const std::string& appPackageName,
@@ -123,19 +155,22 @@
     const std::string appStatsKey = appPackageName + std::to_string(driverVersionCode);
     if (!mAppStats.count(appStatsKey)) {
         if (mAppStats.size() >= MAX_NUM_APP_RECORDS) {
-            ALOGV("GpuStatsAppInfo has reached maximum size. Ignore new stats.");
-            return;
+            ALOGV("GpuStatsAppInfo has reached maximum size. Removing old stats to make room.");
+            purgeOldDriverStats();
         }
 
         GpuStatsAppInfo appInfo;
         addLoadingTime(driver, driverLoadingTime, &appInfo);
         appInfo.appPackageName = appPackageName;
         appInfo.driverVersionCode = driverVersionCode;
+        appInfo.angleInUse = driverPackageName == "angle";
+        appInfo.lastAccessTime = std::chrono::system_clock::now();
         mAppStats.insert({appStatsKey, appInfo});
-        return;
+    } else {
+        mAppStats[appStatsKey].angleInUse = driverPackageName == "angle";
+        addLoadingTime(driver, driverLoadingTime, &mAppStats[appStatsKey]);
+        mAppStats[appStatsKey].lastAccessTime = std::chrono::system_clock::now();
     }
-
-    addLoadingTime(driver, driverLoadingTime, &mAppStats[appStatsKey]);
 }
 
 void GpuStats::insertTargetStats(const std::string& appPackageName,
@@ -311,7 +346,8 @@
                                               angleDriverBytes.length()),
                     ele.second.cpuVulkanInUse,
                     ele.second.falsePrerotation,
-                    ele.second.gles1InUse);
+                    ele.second.gles1InUse,
+                    ele.second.angleInUse);
         }
     }
 
diff --git a/services/gpuservice/gpustats/include/gpustats/GpuStats.h b/services/gpuservice/gpustats/include/gpustats/GpuStats.h
index 55f0da1..2aba651 100644
--- a/services/gpuservice/gpustats/include/gpustats/GpuStats.h
+++ b/services/gpuservice/gpustats/include/gpustats/GpuStats.h
@@ -46,6 +46,11 @@
 
     // This limits the worst case number of loading times tracked.
     static const size_t MAX_NUM_LOADING_TIMES = 50;
+    // Below limits the memory usage of GpuStats to be less than 10KB. This is
+    // the preferred number for statsd while maintaining nice data quality.
+    static const size_t MAX_NUM_APP_RECORDS = 100;
+    // The number of apps to remove when mAppStats fills up.
+    static const size_t APP_RECORD_HEADROOM = 10;
 
 private:
     // Friend class for testing.
@@ -55,6 +60,10 @@
     static AStatsManager_PullAtomCallbackReturn pullAtomCallback(int32_t atomTag,
                                                                  AStatsEventList* data,
                                                                  void* cookie);
+
+    // Remove old packages from mAppStats.
+    void purgeOldDriverStats();
+
     // Pull global into into global atom.
     AStatsManager_PullAtomCallbackReturn pullGlobalInfoAtom(AStatsEventList* data);
     // Pull app into into app atom.
@@ -68,9 +77,6 @@
     // Registers statsd callbacks if they have not already been registered
     void registerStatsdCallbacksIfNeeded();
 
-    // Below limits the memory usage of GpuStats to be less than 10KB. This is
-    // the preferred number for statsd while maintaining nice data quality.
-    static const size_t MAX_NUM_APP_RECORDS = 100;
     // GpuStats access should be guarded by mLock.
     std::mutex mLock;
     // True if statsd callbacks have been registered.
diff --git a/services/gpuservice/tests/unittests/GpuStatsTest.cpp b/services/gpuservice/tests/unittests/GpuStatsTest.cpp
index 37ebeae..20c8ccf 100644
--- a/services/gpuservice/tests/unittests/GpuStatsTest.cpp
+++ b/services/gpuservice/tests/unittests/GpuStatsTest.cpp
@@ -17,6 +17,7 @@
 #undef LOG_TAG
 #define LOG_TAG "gpuservice_unittest"
 
+#include <unistd.h>
 #include <cutils/properties.h>
 #include <gmock/gmock.h>
 #include <gpustats/GpuStats.h>
@@ -221,6 +222,51 @@
     EXPECT_THAT(inputCommand(InputCommand::DUMP_APP), HasSubstr("gles1InUse = 1"));
 }
 
+// Verify we always have the most recently used apps in mAppStats, even when we fill it.
+TEST_F(GpuStatsTest, canInsertMoreThanMaxNumAppRecords) {
+    constexpr int kNumExtraApps = 15;
+    static_assert(kNumExtraApps > GpuStats::APP_RECORD_HEADROOM);
+
+    // Insert stats for GpuStats::MAX_NUM_APP_RECORDS so we fill it up.
+    for (int i = 0; i < GpuStats::MAX_NUM_APP_RECORDS + kNumExtraApps; ++i) {
+        std::stringstream nameStream;
+        nameStream << "testapp" << "_" << i;
+        std::string fullPkgName = nameStream.str();
+
+        mGpuStats->insertDriverStats(BUILTIN_DRIVER_PKG_NAME, BUILTIN_DRIVER_VER_NAME,
+                                     BUILTIN_DRIVER_VER_CODE, BUILTIN_DRIVER_BUILD_TIME,
+                                     fullPkgName, VULKAN_VERSION, GpuStatsInfo::Driver::GL, true,
+                                     DRIVER_LOADING_TIME_1);
+        mGpuStats->insertTargetStats(fullPkgName, BUILTIN_DRIVER_VER_CODE,
+                                     GpuStatsInfo::Stats::CPU_VULKAN_IN_USE, 0);
+        mGpuStats->insertTargetStats(fullPkgName, BUILTIN_DRIVER_VER_CODE,
+                                     GpuStatsInfo::Stats::FALSE_PREROTATION, 0);
+        mGpuStats->insertTargetStats(fullPkgName, BUILTIN_DRIVER_VER_CODE,
+                                     GpuStatsInfo::Stats::GLES_1_IN_USE, 0);
+
+        EXPECT_THAT(inputCommand(InputCommand::DUMP_APP), HasSubstr(fullPkgName.c_str()));
+        EXPECT_THAT(inputCommand(InputCommand::DUMP_APP), HasSubstr("cpuVulkanInUse = 1"));
+        EXPECT_THAT(inputCommand(InputCommand::DUMP_APP), HasSubstr("falsePrerotation = 1"));
+        EXPECT_THAT(inputCommand(InputCommand::DUMP_APP), HasSubstr("gles1InUse = 1"));
+    }
+
+    // mAppStats purges GpuStats::APP_RECORD_HEADROOM apps removed everytime it's filled up.
+    int numPurges = kNumExtraApps / GpuStats::APP_RECORD_HEADROOM;
+    numPurges += (kNumExtraApps % GpuStats::APP_RECORD_HEADROOM) == 0 ? 0 : 1;
+
+    // Verify the remaining apps are present.
+    for (int i = numPurges * GpuStats::APP_RECORD_HEADROOM;
+         i < GpuStats::MAX_NUM_APP_RECORDS + kNumExtraApps;
+         ++i) {
+        std::stringstream nameStream;
+        // Add a newline to search for the exact package name.
+        nameStream << "testapp" << "_" << i << "\n";
+        std::string fullPkgName = nameStream.str();
+
+        EXPECT_THAT(inputCommand(InputCommand::DUMP_APP), HasSubstr(fullPkgName.c_str()));
+    }
+}
+
 TEST_F(GpuStatsTest, canDumpAllBeforeClearAll) {
     mGpuStats->insertDriverStats(BUILTIN_DRIVER_PKG_NAME, BUILTIN_DRIVER_VER_NAME,
                                  BUILTIN_DRIVER_VER_CODE, BUILTIN_DRIVER_BUILD_TIME, APP_PKG_NAME_1,
diff --git a/services/inputflinger/dispatcher/Entry.cpp b/services/inputflinger/dispatcher/Entry.cpp
index f6bb6a6..936ecf9 100644
--- a/services/inputflinger/dispatcher/Entry.cpp
+++ b/services/inputflinger/dispatcher/Entry.cpp
@@ -32,8 +32,8 @@
     return {{VerifiedInputEvent::Type::KEY, entry.deviceId, entry.eventTime, entry.source,
              entry.displayId},
             entry.action,
-            entry.downTime,
             entry.flags & VERIFIED_KEY_EVENT_FLAGS,
+            entry.downTime,
             entry.keyCode,
             entry.scanCode,
             entry.metaState,
@@ -50,8 +50,8 @@
             rawXY.x,
             rawXY.y,
             actionMasked,
-            entry.downTime,
             entry.flags & VERIFIED_MOTION_EVENT_FLAGS,
+            entry.downTime,
             entry.metaState,
             entry.buttonState};
 }
diff --git a/services/inputflinger/reader/InputDevice.cpp b/services/inputflinger/reader/InputDevice.cpp
index d07be3b..7cff672 100644
--- a/services/inputflinger/reader/InputDevice.cpp
+++ b/services/inputflinger/reader/InputDevice.cpp
@@ -379,21 +379,22 @@
     // gamepad button presses are handled by different mappers but they should be dispatched
     // in the order received.
     for (const RawEvent* rawEvent = rawEvents; count != 0; rawEvent++) {
-#if DEBUG_RAW_EVENTS
-        ALOGD("Input event: device=%d type=0x%04x code=0x%04x value=0x%08x when=%" PRId64,
-              rawEvent->deviceId, rawEvent->type, rawEvent->code, rawEvent->value, rawEvent->when);
-#endif
+        if (DEBUG_RAW_EVENTS) {
+            ALOGD("Input event: device=%d type=0x%04x code=0x%04x value=0x%08x when=%" PRId64,
+                  rawEvent->deviceId, rawEvent->type, rawEvent->code, rawEvent->value,
+                  rawEvent->when);
+        }
 
         if (mDropUntilNextSync) {
             if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
                 mDropUntilNextSync = false;
-#if DEBUG_RAW_EVENTS
-                ALOGD("Recovered from input event buffer overrun.");
-#endif
+                if (DEBUG_RAW_EVENTS) {
+                    ALOGD("Recovered from input event buffer overrun.");
+                }
             } else {
-#if DEBUG_RAW_EVENTS
-                ALOGD("Dropped input event while waiting for next input sync.");
-#endif
+                if (DEBUG_RAW_EVENTS) {
+                    ALOGD("Dropped input event while waiting for next input sync.");
+                }
             }
         } else if (rawEvent->type == EV_SYN && rawEvent->code == SYN_DROPPED) {
             ALOGI("Detected input event buffer overrun for device %s.", getName().c_str());
diff --git a/services/inputflinger/reader/InputReader.cpp b/services/inputflinger/reader/InputReader.cpp
index 0b632f7..7704a84 100644
--- a/services/inputflinger/reader/InputReader.cpp
+++ b/services/inputflinger/reader/InputReader.cpp
@@ -113,9 +113,9 @@
         if (mNextTimeout != LLONG_MAX) {
             nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
             if (now >= mNextTimeout) {
-#if DEBUG_RAW_EVENTS
-                ALOGD("Timeout expired, latency=%0.3fms", (now - mNextTimeout) * 0.000001f);
-#endif
+                if (DEBUG_RAW_EVENTS) {
+                    ALOGD("Timeout expired, latency=%0.3fms", (now - mNextTimeout) * 0.000001f);
+                }
                 mNextTimeout = LLONG_MAX;
                 timeoutExpiredLocked(now);
             }
@@ -155,9 +155,9 @@
                 }
                 batchSize += 1;
             }
-#if DEBUG_RAW_EVENTS
-            ALOGD("BatchSize: %zu Count: %zu", batchSize, count);
-#endif
+            if (DEBUG_RAW_EVENTS) {
+                ALOGD("BatchSize: %zu Count: %zu", batchSize, count);
+            }
             processEventsForDeviceLocked(deviceId, rawEvent, batchSize);
         } else {
             switch (rawEvent->type) {
@@ -782,12 +782,8 @@
 
     std::optional<int32_t> associatedDisplayId = device->getAssociatedDisplayId();
     // No associated display. By default, can dispatch to all displays.
-    if (!associatedDisplayId) {
-        return true;
-    }
-
-    if (*associatedDisplayId == ADISPLAY_ID_NONE) {
-        ALOGW("Device %s is associated with display ADISPLAY_ID_NONE.", device->getName().c_str());
+    if (!associatedDisplayId ||
+            *associatedDisplayId == ADISPLAY_ID_NONE) {
         return true;
     }
 
diff --git a/services/inputflinger/reader/Macros.h b/services/inputflinger/reader/Macros.h
index 0dfe7f1..d837689 100644
--- a/services/inputflinger/reader/Macros.h
+++ b/services/inputflinger/reader/Macros.h
@@ -22,28 +22,25 @@
 //#define LOG_NDEBUG 0
 
 // Log debug messages for each raw event received from the EventHub.
-#define DEBUG_RAW_EVENTS 0
-
-// Log debug messages about touch screen filtering hacks.
-#define DEBUG_HACKS 0
+static constexpr bool DEBUG_RAW_EVENTS = false;
 
 // Log debug messages about virtual key processing.
-#define DEBUG_VIRTUAL_KEYS 0
+static constexpr bool DEBUG_VIRTUAL_KEYS = false;
 
 // Log debug messages about pointers.
 static constexpr bool DEBUG_POINTERS = false;
 
 // Log debug messages about pointer assignment calculations.
-#define DEBUG_POINTER_ASSIGNMENT 0
+static constexpr bool DEBUG_POINTER_ASSIGNMENT = false;
 
 // Log debug messages about gesture detection.
-#define DEBUG_GESTURES 0
+static constexpr bool DEBUG_GESTURES = false;
 
 // Log debug messages about the vibrator.
-#define DEBUG_VIBRATOR 0
+static constexpr bool DEBUG_VIBRATOR = false;
 
 // Log debug messages about fusing stylus data.
-#define DEBUG_STYLUS_FUSION 0
+static constexpr bool DEBUG_STYLUS_FUSION = false;
 
 #define INDENT "  "
 #define INDENT2 "    "
diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.cpp b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
index 913c666..6f49f31 100644
--- a/services/inputflinger/reader/mapper/TouchInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
@@ -1465,14 +1465,14 @@
         assignPointerIds(last, next);
     }
 
-#if DEBUG_RAW_EVENTS
-    ALOGD("syncTouch: pointerCount %d -> %d, touching ids 0x%08x -> 0x%08x, "
-          "hovering ids 0x%08x -> 0x%08x, canceled ids 0x%08x",
-          last.rawPointerData.pointerCount, next.rawPointerData.pointerCount,
-          last.rawPointerData.touchingIdBits.value, next.rawPointerData.touchingIdBits.value,
-          last.rawPointerData.hoveringIdBits.value, next.rawPointerData.hoveringIdBits.value,
-          next.rawPointerData.canceledIdBits.value);
-#endif
+    if (DEBUG_RAW_EVENTS) {
+        ALOGD("syncTouch: pointerCount %d -> %d, touching ids 0x%08x -> 0x%08x, "
+              "hovering ids 0x%08x -> 0x%08x, canceled ids 0x%08x",
+              last.rawPointerData.pointerCount, next.rawPointerData.pointerCount,
+              last.rawPointerData.touchingIdBits.value, next.rawPointerData.touchingIdBits.value,
+              last.rawPointerData.hoveringIdBits.value, next.rawPointerData.hoveringIdBits.value,
+              next.rawPointerData.canceledIdBits.value);
+    }
 
     if (!next.rawPointerData.touchingIdBits.isEmpty() &&
         !next.rawPointerData.hoveringIdBits.isEmpty() &&
@@ -1526,9 +1526,9 @@
             nsecs_t when = mExternalStylusFusionTimeout - STYLUS_DATA_LATENCY;
             clearStylusDataPendingFlags();
             mCurrentRawState.copyFrom(mLastRawState);
-#if DEBUG_STYLUS_FUSION
-            ALOGD("Timeout expired, synthesizing event with new stylus data");
-#endif
+            if (DEBUG_STYLUS_FUSION) {
+                ALOGD("Timeout expired, synthesizing event with new stylus data");
+            }
             const nsecs_t readTime = when; // consider this synthetic event to be zero latency
             cookAndDispatch(when, readTime);
         } else if (mExternalStylusFusionTimeout == LLONG_MAX) {
@@ -1715,24 +1715,24 @@
             state.rawPointerData.pointerCount != 0;
     if (initialDown) {
         if (mExternalStylusState.pressure != 0.0f) {
-#if DEBUG_STYLUS_FUSION
-            ALOGD("Have both stylus and touch data, beginning fusion");
-#endif
+            if (DEBUG_STYLUS_FUSION) {
+                ALOGD("Have both stylus and touch data, beginning fusion");
+            }
             mExternalStylusId = state.rawPointerData.touchingIdBits.firstMarkedBit();
         } else if (timeout) {
-#if DEBUG_STYLUS_FUSION
-            ALOGD("Timeout expired, assuming touch is not a stylus.");
-#endif
+            if (DEBUG_STYLUS_FUSION) {
+                ALOGD("Timeout expired, assuming touch is not a stylus.");
+            }
             resetExternalStylus();
         } else {
             if (mExternalStylusFusionTimeout == LLONG_MAX) {
                 mExternalStylusFusionTimeout = state.when + EXTERNAL_STYLUS_DATA_TIMEOUT;
             }
-#if DEBUG_STYLUS_FUSION
-            ALOGD("No stylus data but stylus is connected, requesting timeout "
-                  "(%" PRId64 "ms)",
-                  mExternalStylusFusionTimeout);
-#endif
+            if (DEBUG_STYLUS_FUSION) {
+                ALOGD("No stylus data but stylus is connected, requesting timeout "
+                      "(%" PRId64 "ms)",
+                      mExternalStylusFusionTimeout);
+            }
             getContext()->requestTimeoutAtTime(mExternalStylusFusionTimeout);
             return true;
         }
@@ -1740,9 +1740,9 @@
 
     // Check if the stylus pointer has gone up.
     if (mExternalStylusId != -1 && !state.rawPointerData.touchingIdBits.hasBit(mExternalStylusId)) {
-#if DEBUG_STYLUS_FUSION
-        ALOGD("Stylus pointer is going up");
-#endif
+        if (DEBUG_STYLUS_FUSION) {
+            ALOGD("Stylus pointer is going up");
+        }
         mExternalStylusId = -1;
     }
 
@@ -1783,10 +1783,10 @@
             // Pointer went up while virtual key was down.
             mCurrentVirtualKey.down = false;
             if (!mCurrentVirtualKey.ignored) {
-#if DEBUG_VIRTUAL_KEYS
-                ALOGD("VirtualKeys: Generating key up: keyCode=%d, scanCode=%d",
-                      mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
-#endif
+                if (DEBUG_VIRTUAL_KEYS) {
+                    ALOGD("VirtualKeys: Generating key up: keyCode=%d, scanCode=%d",
+                          mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
+                }
                 dispatchVirtualKey(when, readTime, policyFlags, AKEY_EVENT_ACTION_UP,
                                    AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY);
             }
@@ -1810,10 +1810,10 @@
         // into the main display surface.
         mCurrentVirtualKey.down = false;
         if (!mCurrentVirtualKey.ignored) {
-#if DEBUG_VIRTUAL_KEYS
-            ALOGD("VirtualKeys: Canceling key: keyCode=%d, scanCode=%d", mCurrentVirtualKey.keyCode,
-                  mCurrentVirtualKey.scanCode);
-#endif
+            if (DEBUG_VIRTUAL_KEYS) {
+                ALOGD("VirtualKeys: Canceling key: keyCode=%d, scanCode=%d",
+                      mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
+            }
             dispatchVirtualKey(when, readTime, policyFlags, AKEY_EVENT_ACTION_UP,
                                AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY |
                                        AKEY_EVENT_FLAG_CANCELED);
@@ -1843,10 +1843,10 @@
                                                                virtualKey->scanCode);
 
                     if (!mCurrentVirtualKey.ignored) {
-#if DEBUG_VIRTUAL_KEYS
-                        ALOGD("VirtualKeys: Generating key down: keyCode=%d, scanCode=%d",
-                              mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
-#endif
+                        if (DEBUG_VIRTUAL_KEYS) {
+                            ALOGD("VirtualKeys: Generating key down: keyCode=%d, scanCode=%d",
+                                  mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
+                        }
                         dispatchVirtualKey(when, readTime, policyFlags, AKEY_EVENT_ACTION_DOWN,
                                            AKEY_EVENT_FLAG_FROM_SYSTEM |
                                                    AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY);
@@ -2634,9 +2634,9 @@
 
     // Handle TAP timeout.
     if (isTimeout) {
-#if DEBUG_GESTURES
-        ALOGD("Gestures: Processing timeout");
-#endif
+        if (DEBUG_GESTURES) {
+            ALOGD("Gestures: Processing timeout");
+        }
 
         if (mPointerGesture.lastGestureMode == PointerGesture::Mode::TAP) {
             if (when <= mPointerGesture.tapUpTime + mConfig.pointerGestureTapDragInterval) {
@@ -2645,9 +2645,9 @@
                                                    mConfig.pointerGestureTapDragInterval);
             } else {
                 // The tap is finished.
-#if DEBUG_GESTURES
-                ALOGD("Gestures: TAP finished");
-#endif
+                if (DEBUG_GESTURES) {
+                    ALOGD("Gestures: TAP finished");
+                }
                 *outFinishPreviousGesture = true;
 
                 mPointerGesture.activeGestureId = -1;
@@ -2743,10 +2743,11 @@
     // Switch states based on button and pointer state.
     if (isQuietTime) {
         // Case 1: Quiet time. (QUIET)
-#if DEBUG_GESTURES
-        ALOGD("Gestures: QUIET for next %0.3fms",
-              (mPointerGesture.quietTime + mConfig.pointerGestureQuietInterval - when) * 0.000001f);
-#endif
+        if (DEBUG_GESTURES) {
+            ALOGD("Gestures: QUIET for next %0.3fms",
+                  (mPointerGesture.quietTime + mConfig.pointerGestureQuietInterval - when) *
+                          0.000001f);
+        }
         if (mPointerGesture.lastGestureMode != PointerGesture::Mode::QUIET) {
             *outFinishPreviousGesture = true;
         }
@@ -2770,11 +2771,11 @@
         // active.  If the user first puts one finger down to click then adds another
         // finger to drag then the active pointer should switch to the finger that is
         // being dragged.
-#if DEBUG_GESTURES
-        ALOGD("Gestures: BUTTON_CLICK_OR_DRAG activeTouchId=%d, "
-              "currentFingerCount=%d",
-              activeTouchId, currentFingerCount);
-#endif
+        if (DEBUG_GESTURES) {
+            ALOGD("Gestures: BUTTON_CLICK_OR_DRAG activeTouchId=%d, "
+                  "currentFingerCount=%d",
+                  activeTouchId, currentFingerCount);
+        }
         // Reset state when just starting.
         if (mPointerGesture.lastGestureMode != PointerGesture::Mode::BUTTON_CLICK_OR_DRAG) {
             *outFinishPreviousGesture = true;
@@ -2799,11 +2800,11 @@
             }
             if (bestId >= 0 && bestId != activeTouchId) {
                 mPointerGesture.activeTouchId = activeTouchId = bestId;
-#if DEBUG_GESTURES
-                ALOGD("Gestures: BUTTON_CLICK_OR_DRAG switched pointers, "
-                      "bestId=%d, bestSpeed=%0.3f",
-                      bestId, bestSpeed);
-#endif
+                if (DEBUG_GESTURES) {
+                    ALOGD("Gestures: BUTTON_CLICK_OR_DRAG switched pointers, "
+                          "bestId=%d, bestSpeed=%0.3f",
+                          bestId, bestSpeed);
+                }
             }
         }
 
@@ -2858,9 +2859,9 @@
                 mPointerController->getPosition(&x, &y);
                 if (fabs(x - mPointerGesture.tapX) <= mConfig.pointerGestureTapSlop &&
                     fabs(y - mPointerGesture.tapY) <= mConfig.pointerGestureTapSlop) {
-#if DEBUG_GESTURES
-                    ALOGD("Gestures: TAP");
-#endif
+                    if (DEBUG_GESTURES) {
+                        ALOGD("Gestures: TAP");
+                    }
 
                     mPointerGesture.tapUpTime = when;
                     getContext()->requestTimeoutAtTime(when +
@@ -2886,29 +2887,29 @@
 
                     tapped = true;
                 } else {
-#if DEBUG_GESTURES
-                    ALOGD("Gestures: Not a TAP, deltaX=%f, deltaY=%f", x - mPointerGesture.tapX,
-                          y - mPointerGesture.tapY);
-#endif
+                    if (DEBUG_GESTURES) {
+                        ALOGD("Gestures: Not a TAP, deltaX=%f, deltaY=%f", x - mPointerGesture.tapX,
+                              y - mPointerGesture.tapY);
+                    }
                 }
             } else {
-#if DEBUG_GESTURES
-                if (mPointerGesture.tapDownTime != LLONG_MIN) {
-                    ALOGD("Gestures: Not a TAP, %0.3fms since down",
-                          (when - mPointerGesture.tapDownTime) * 0.000001f);
-                } else {
-                    ALOGD("Gestures: Not a TAP, incompatible mode transitions");
+                if (DEBUG_GESTURES) {
+                    if (mPointerGesture.tapDownTime != LLONG_MIN) {
+                        ALOGD("Gestures: Not a TAP, %0.3fms since down",
+                              (when - mPointerGesture.tapDownTime) * 0.000001f);
+                    } else {
+                        ALOGD("Gestures: Not a TAP, incompatible mode transitions");
+                    }
                 }
-#endif
             }
         }
 
         mPointerVelocityControl.reset();
 
         if (!tapped) {
-#if DEBUG_GESTURES
-            ALOGD("Gestures: NEUTRAL");
-#endif
+            if (DEBUG_GESTURES) {
+                ALOGD("Gestures: NEUTRAL");
+            }
             mPointerGesture.activeGestureId = -1;
             mPointerGesture.currentGestureMode = PointerGesture::Mode::NEUTRAL;
             mPointerGesture.currentGestureIdBits.clear();
@@ -2929,16 +2930,16 @@
                     fabs(y - mPointerGesture.tapY) <= mConfig.pointerGestureTapSlop) {
                     mPointerGesture.currentGestureMode = PointerGesture::Mode::TAP_DRAG;
                 } else {
-#if DEBUG_GESTURES
-                    ALOGD("Gestures: Not a TAP_DRAG, deltaX=%f, deltaY=%f",
-                          x - mPointerGesture.tapX, y - mPointerGesture.tapY);
-#endif
+                    if (DEBUG_GESTURES) {
+                        ALOGD("Gestures: Not a TAP_DRAG, deltaX=%f, deltaY=%f",
+                              x - mPointerGesture.tapX, y - mPointerGesture.tapY);
+                    }
                 }
             } else {
-#if DEBUG_GESTURES
-                ALOGD("Gestures: Not a TAP_DRAG, %0.3fms time since up",
-                      (when - mPointerGesture.tapUpTime) * 0.000001f);
-#endif
+                if (DEBUG_GESTURES) {
+                    ALOGD("Gestures: Not a TAP_DRAG, %0.3fms time since up",
+                          (when - mPointerGesture.tapUpTime) * 0.000001f);
+                }
             }
         } else if (mPointerGesture.lastGestureMode == PointerGesture::Mode::TAP_DRAG) {
             mPointerGesture.currentGestureMode = PointerGesture::Mode::TAP_DRAG;
@@ -2965,14 +2966,14 @@
 
         bool down;
         if (mPointerGesture.currentGestureMode == PointerGesture::Mode::TAP_DRAG) {
-#if DEBUG_GESTURES
-            ALOGD("Gestures: TAP_DRAG");
-#endif
+            if (DEBUG_GESTURES) {
+                ALOGD("Gestures: TAP_DRAG");
+            }
             down = true;
         } else {
-#if DEBUG_GESTURES
-            ALOGD("Gestures: HOVER");
-#endif
+            if (DEBUG_GESTURES) {
+                ALOGD("Gestures: HOVER");
+            }
             if (mPointerGesture.lastGestureMode != PointerGesture::Mode::HOVER) {
                 *outFinishPreviousGesture = true;
             }
@@ -3026,12 +3027,13 @@
         } else if (!settled && currentFingerCount > lastFingerCount) {
             // Additional pointers have gone down but not yet settled.
             // Reset the gesture.
-#if DEBUG_GESTURES
-            ALOGD("Gestures: Resetting gesture since additional pointers went down for MULTITOUCH, "
-                  "settle time remaining %0.3fms",
-                  (mPointerGesture.firstTouchTime + mConfig.pointerGestureMultitouchSettleInterval -
-                   when) * 0.000001f);
-#endif
+            if (DEBUG_GESTURES) {
+                ALOGD("Gestures: Resetting gesture since additional pointers went down for "
+                      "MULTITOUCH, settle time remaining %0.3fms",
+                      (mPointerGesture.firstTouchTime +
+                       mConfig.pointerGestureMultitouchSettleInterval - when) *
+                              0.000001f);
+            }
             *outCancelPreviousGesture = true;
         } else {
             // Continue previous gesture.
@@ -3045,12 +3047,13 @@
             mPointerVelocityControl.reset();
 
             // Use the centroid and pointer location as the reference points for the gesture.
-#if DEBUG_GESTURES
-            ALOGD("Gestures: Using centroid as reference for MULTITOUCH, "
-                  "settle time remaining %0.3fms",
-                  (mPointerGesture.firstTouchTime + mConfig.pointerGestureMultitouchSettleInterval -
-                   when) * 0.000001f);
-#endif
+            if (DEBUG_GESTURES) {
+                ALOGD("Gestures: Using centroid as reference for MULTITOUCH, "
+                      "settle time remaining %0.3fms",
+                      (mPointerGesture.firstTouchTime +
+                       mConfig.pointerGestureMultitouchSettleInterval - when) *
+                              0.000001f);
+            }
             mCurrentRawState.rawPointerData
                     .getCentroidOfTouchingPointers(&mPointerGesture.referenceTouchX,
                                                    &mPointerGesture.referenceTouchY);
@@ -3108,10 +3111,10 @@
             if (distOverThreshold >= 2) {
                 if (currentFingerCount > 2) {
                     // There are more than two pointers, switch to FREEFORM.
-#if DEBUG_GESTURES
-                    ALOGD("Gestures: PRESS transitioned to FREEFORM, number of pointers %d > 2",
-                          currentFingerCount);
-#endif
+                    if (DEBUG_GESTURES) {
+                        ALOGD("Gestures: PRESS transitioned to FREEFORM, number of pointers %d > 2",
+                              currentFingerCount);
+                    }
                     *outCancelPreviousGesture = true;
                     mPointerGesture.currentGestureMode = PointerGesture::Mode::FREEFORM;
                 } else {
@@ -3127,10 +3130,11 @@
                     if (mutualDistance > mPointerGestureMaxSwipeWidth) {
                         // There are two pointers but they are too far apart for a SWIPE,
                         // switch to FREEFORM.
-#if DEBUG_GESTURES
-                        ALOGD("Gestures: PRESS transitioned to FREEFORM, distance %0.3f > %0.3f",
-                              mutualDistance, mPointerGestureMaxSwipeWidth);
-#endif
+                        if (DEBUG_GESTURES) {
+                            ALOGD("Gestures: PRESS transitioned to FREEFORM, distance %0.3f > "
+                                  "%0.3f",
+                                  mutualDistance, mPointerGestureMaxSwipeWidth);
+                        }
                         *outCancelPreviousGesture = true;
                         mPointerGesture.currentGestureMode = PointerGesture::Mode::FREEFORM;
                     } else {
@@ -3155,25 +3159,25 @@
                             float cosine = dot / (dist1 * dist2); // denominator always > 0
                             if (cosine >= mConfig.pointerGestureSwipeTransitionAngleCosine) {
                                 // Pointers are moving in the same direction.  Switch to SWIPE.
-#if DEBUG_GESTURES
-                                ALOGD("Gestures: PRESS transitioned to SWIPE, "
-                                      "dist1 %0.3f >= %0.3f, dist2 %0.3f >= %0.3f, "
-                                      "cosine %0.3f >= %0.3f",
-                                      dist1, mConfig.pointerGestureMultitouchMinDistance, dist2,
-                                      mConfig.pointerGestureMultitouchMinDistance, cosine,
-                                      mConfig.pointerGestureSwipeTransitionAngleCosine);
-#endif
+                                if (DEBUG_GESTURES) {
+                                    ALOGD("Gestures: PRESS transitioned to SWIPE, "
+                                          "dist1 %0.3f >= %0.3f, dist2 %0.3f >= %0.3f, "
+                                          "cosine %0.3f >= %0.3f",
+                                          dist1, mConfig.pointerGestureMultitouchMinDistance, dist2,
+                                          mConfig.pointerGestureMultitouchMinDistance, cosine,
+                                          mConfig.pointerGestureSwipeTransitionAngleCosine);
+                                }
                                 mPointerGesture.currentGestureMode = PointerGesture::Mode::SWIPE;
                             } else {
                                 // Pointers are moving in different directions.  Switch to FREEFORM.
-#if DEBUG_GESTURES
-                                ALOGD("Gestures: PRESS transitioned to FREEFORM, "
-                                      "dist1 %0.3f >= %0.3f, dist2 %0.3f >= %0.3f, "
-                                      "cosine %0.3f < %0.3f",
-                                      dist1, mConfig.pointerGestureMultitouchMinDistance, dist2,
-                                      mConfig.pointerGestureMultitouchMinDistance, cosine,
-                                      mConfig.pointerGestureSwipeTransitionAngleCosine);
-#endif
+                                if (DEBUG_GESTURES) {
+                                    ALOGD("Gestures: PRESS transitioned to FREEFORM, "
+                                          "dist1 %0.3f >= %0.3f, dist2 %0.3f >= %0.3f, "
+                                          "cosine %0.3f < %0.3f",
+                                          dist1, mConfig.pointerGestureMultitouchMinDistance, dist2,
+                                          mConfig.pointerGestureMultitouchMinDistance, cosine,
+                                          mConfig.pointerGestureSwipeTransitionAngleCosine);
+                                }
                                 *outCancelPreviousGesture = true;
                                 mPointerGesture.currentGestureMode = PointerGesture::Mode::FREEFORM;
                             }
@@ -3185,10 +3189,10 @@
             // Switch from SWIPE to FREEFORM if additional pointers go down.
             // Cancel previous gesture.
             if (currentFingerCount > 2) {
-#if DEBUG_GESTURES
-                ALOGD("Gestures: SWIPE transitioned to FREEFORM, number of pointers %d > 2",
-                      currentFingerCount);
-#endif
+                if (DEBUG_GESTURES) {
+                    ALOGD("Gestures: SWIPE transitioned to FREEFORM, number of pointers %d > 2",
+                          currentFingerCount);
+                }
                 *outCancelPreviousGesture = true;
                 mPointerGesture.currentGestureMode = PointerGesture::Mode::FREEFORM;
             }
@@ -3222,11 +3226,11 @@
         if (mPointerGesture.currentGestureMode == PointerGesture::Mode::PRESS ||
             mPointerGesture.currentGestureMode == PointerGesture::Mode::SWIPE) {
             // PRESS or SWIPE mode.
-#if DEBUG_GESTURES
-            ALOGD("Gestures: PRESS or SWIPE activeTouchId=%d,"
-                  "activeGestureId=%d, currentTouchPointerCount=%d",
-                  activeTouchId, mPointerGesture.activeGestureId, currentFingerCount);
-#endif
+            if (DEBUG_GESTURES) {
+                ALOGD("Gestures: PRESS or SWIPE activeTouchId=%d,"
+                      "activeGestureId=%d, currentTouchPointerCount=%d",
+                      activeTouchId, mPointerGesture.activeGestureId, currentFingerCount);
+            }
             ALOG_ASSERT(mPointerGesture.activeGestureId >= 0);
 
             mPointerGesture.currentGestureIdBits.clear();
@@ -3243,11 +3247,11 @@
             mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
         } else if (mPointerGesture.currentGestureMode == PointerGesture::Mode::FREEFORM) {
             // FREEFORM mode.
-#if DEBUG_GESTURES
-            ALOGD("Gestures: FREEFORM activeTouchId=%d,"
-                  "activeGestureId=%d, currentTouchPointerCount=%d",
-                  activeTouchId, mPointerGesture.activeGestureId, currentFingerCount);
-#endif
+            if (DEBUG_GESTURES) {
+                ALOGD("Gestures: FREEFORM activeTouchId=%d,"
+                      "activeGestureId=%d, currentTouchPointerCount=%d",
+                      activeTouchId, mPointerGesture.activeGestureId, currentFingerCount);
+            }
             ALOG_ASSERT(mPointerGesture.activeGestureId >= 0);
 
             mPointerGesture.currentGestureIdBits.clear();
@@ -3286,13 +3290,13 @@
                 }
             }
 
-#if DEBUG_GESTURES
-            ALOGD("Gestures: FREEFORM follow up "
-                  "mappedTouchIdBits=0x%08x, usedGestureIdBits=0x%08x, "
-                  "activeGestureId=%d",
-                  mappedTouchIdBits.value, usedGestureIdBits.value,
-                  mPointerGesture.activeGestureId);
-#endif
+            if (DEBUG_GESTURES) {
+                ALOGD("Gestures: FREEFORM follow up "
+                      "mappedTouchIdBits=0x%08x, usedGestureIdBits=0x%08x, "
+                      "activeGestureId=%d",
+                      mappedTouchIdBits.value, usedGestureIdBits.value,
+                      mPointerGesture.activeGestureId);
+            }
 
             BitSet32 idBits(mCurrentCookedState.fingerIdBits);
             for (uint32_t i = 0; i < currentFingerCount; i++) {
@@ -3301,18 +3305,18 @@
                 if (!mappedTouchIdBits.hasBit(touchId)) {
                     gestureId = usedGestureIdBits.markFirstUnmarkedBit();
                     mPointerGesture.freeformTouchToGestureIdMap[touchId] = gestureId;
-#if DEBUG_GESTURES
-                    ALOGD("Gestures: FREEFORM "
-                          "new mapping for touch id %d -> gesture id %d",
-                          touchId, gestureId);
-#endif
+                    if (DEBUG_GESTURES) {
+                        ALOGD("Gestures: FREEFORM "
+                              "new mapping for touch id %d -> gesture id %d",
+                              touchId, gestureId);
+                    }
                 } else {
                     gestureId = mPointerGesture.freeformTouchToGestureIdMap[touchId];
-#if DEBUG_GESTURES
-                    ALOGD("Gestures: FREEFORM "
-                          "existing mapping for touch id %d -> gesture id %d",
-                          touchId, gestureId);
-#endif
+                    if (DEBUG_GESTURES) {
+                        ALOGD("Gestures: FREEFORM "
+                              "existing mapping for touch id %d -> gesture id %d",
+                              touchId, gestureId);
+                    }
                 }
                 mPointerGesture.currentGestureIdBits.markBit(gestureId);
                 mPointerGesture.currentGestureIdToIndex[gestureId] = i;
@@ -3341,47 +3345,46 @@
             if (mPointerGesture.activeGestureId < 0) {
                 mPointerGesture.activeGestureId =
                         mPointerGesture.currentGestureIdBits.firstMarkedBit();
-#if DEBUG_GESTURES
-                ALOGD("Gestures: FREEFORM new "
-                      "activeGestureId=%d",
-                      mPointerGesture.activeGestureId);
-#endif
+                if (DEBUG_GESTURES) {
+                    ALOGD("Gestures: FREEFORM new activeGestureId=%d",
+                          mPointerGesture.activeGestureId);
+                }
             }
         }
     }
 
     mPointerController->setButtonState(mCurrentRawState.buttonState);
 
-#if DEBUG_GESTURES
-    ALOGD("Gestures: finishPreviousGesture=%s, cancelPreviousGesture=%s, "
-          "currentGestureMode=%d, currentGestureIdBits=0x%08x, "
-          "lastGestureMode=%d, lastGestureIdBits=0x%08x",
-          toString(*outFinishPreviousGesture), toString(*outCancelPreviousGesture),
-          mPointerGesture.currentGestureMode, mPointerGesture.currentGestureIdBits.value,
-          mPointerGesture.lastGestureMode, mPointerGesture.lastGestureIdBits.value);
-    for (BitSet32 idBits = mPointerGesture.currentGestureIdBits; !idBits.isEmpty();) {
-        uint32_t id = idBits.clearFirstMarkedBit();
-        uint32_t index = mPointerGesture.currentGestureIdToIndex[id];
-        const PointerProperties& properties = mPointerGesture.currentGestureProperties[index];
-        const PointerCoords& coords = mPointerGesture.currentGestureCoords[index];
-        ALOGD("  currentGesture[%d]: index=%d, toolType=%d, "
-              "x=%0.3f, y=%0.3f, pressure=%0.3f",
-              id, index, properties.toolType, coords.getAxisValue(AMOTION_EVENT_AXIS_X),
-              coords.getAxisValue(AMOTION_EVENT_AXIS_Y),
-              coords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE));
+    if (DEBUG_GESTURES) {
+        ALOGD("Gestures: finishPreviousGesture=%s, cancelPreviousGesture=%s, "
+              "currentGestureMode=%d, currentGestureIdBits=0x%08x, "
+              "lastGestureMode=%d, lastGestureIdBits=0x%08x",
+              toString(*outFinishPreviousGesture), toString(*outCancelPreviousGesture),
+              mPointerGesture.currentGestureMode, mPointerGesture.currentGestureIdBits.value,
+              mPointerGesture.lastGestureMode, mPointerGesture.lastGestureIdBits.value);
+        for (BitSet32 idBits = mPointerGesture.currentGestureIdBits; !idBits.isEmpty();) {
+            uint32_t id = idBits.clearFirstMarkedBit();
+            uint32_t index = mPointerGesture.currentGestureIdToIndex[id];
+            const PointerProperties& properties = mPointerGesture.currentGestureProperties[index];
+            const PointerCoords& coords = mPointerGesture.currentGestureCoords[index];
+            ALOGD("  currentGesture[%d]: index=%d, toolType=%d, "
+                  "x=%0.3f, y=%0.3f, pressure=%0.3f",
+                  id, index, properties.toolType, coords.getAxisValue(AMOTION_EVENT_AXIS_X),
+                  coords.getAxisValue(AMOTION_EVENT_AXIS_Y),
+                  coords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE));
+        }
+        for (BitSet32 idBits = mPointerGesture.lastGestureIdBits; !idBits.isEmpty();) {
+            uint32_t id = idBits.clearFirstMarkedBit();
+            uint32_t index = mPointerGesture.lastGestureIdToIndex[id];
+            const PointerProperties& properties = mPointerGesture.lastGestureProperties[index];
+            const PointerCoords& coords = mPointerGesture.lastGestureCoords[index];
+            ALOGD("  lastGesture[%d]: index=%d, toolType=%d, "
+                  "x=%0.3f, y=%0.3f, pressure=%0.3f",
+                  id, index, properties.toolType, coords.getAxisValue(AMOTION_EVENT_AXIS_X),
+                  coords.getAxisValue(AMOTION_EVENT_AXIS_Y),
+                  coords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE));
+        }
     }
-    for (BitSet32 idBits = mPointerGesture.lastGestureIdBits; !idBits.isEmpty();) {
-        uint32_t id = idBits.clearFirstMarkedBit();
-        uint32_t index = mPointerGesture.lastGestureIdToIndex[id];
-        const PointerProperties& properties = mPointerGesture.lastGestureProperties[index];
-        const PointerCoords& coords = mPointerGesture.lastGestureCoords[index];
-        ALOGD("  lastGesture[%d]: index=%d, toolType=%d, "
-              "x=%0.3f, y=%0.3f, pressure=%0.3f",
-              id, index, properties.toolType, coords.getAxisValue(AMOTION_EVENT_AXIS_X),
-              coords.getAxisValue(AMOTION_EVENT_AXIS_Y),
-              coords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE));
-    }
-#endif
     return true;
 }
 
@@ -3755,12 +3758,12 @@
 
 const TouchInputMapper::VirtualKey* TouchInputMapper::findVirtualKeyHit(int32_t x, int32_t y) {
     for (const VirtualKey& virtualKey : mVirtualKeys) {
-#if DEBUG_VIRTUAL_KEYS
-        ALOGD("VirtualKeys: Hit test (%d, %d): keyCode=%d, scanCode=%d, "
-              "left=%d, top=%d, right=%d, bottom=%d",
-              x, y, virtualKey.keyCode, virtualKey.scanCode, virtualKey.hitLeft, virtualKey.hitTop,
-              virtualKey.hitRight, virtualKey.hitBottom);
-#endif
+        if (DEBUG_VIRTUAL_KEYS) {
+            ALOGD("VirtualKeys: Hit test (%d, %d): keyCode=%d, scanCode=%d, "
+                  "left=%d, top=%d, right=%d, bottom=%d",
+                  x, y, virtualKey.keyCode, virtualKey.scanCode, virtualKey.hitLeft,
+                  virtualKey.hitTop, virtualKey.hitRight, virtualKey.hitBottom);
+        }
 
         if (virtualKey.isHit(x, y)) {
             return &virtualKey;
@@ -3857,13 +3860,13 @@
         }
     }
 
-#if DEBUG_POINTER_ASSIGNMENT
-    ALOGD("assignPointerIds - initial distance min-heap: size=%d", heapSize);
-    for (size_t i = 0; i < heapSize; i++) {
-        ALOGD("  heap[%zu]: cur=%" PRIu32 ", last=%" PRIu32 ", distance=%" PRIu64, i,
-              heap[i].currentPointerIndex, heap[i].lastPointerIndex, heap[i].distance);
+    if (DEBUG_POINTER_ASSIGNMENT) {
+        ALOGD("assignPointerIds - initial distance min-heap: size=%d", heapSize);
+        for (size_t i = 0; i < heapSize; i++) {
+            ALOGD("  heap[%zu]: cur=%" PRIu32 ", last=%" PRIu32 ", distance=%" PRIu64, i,
+                  heap[i].currentPointerIndex, heap[i].lastPointerIndex, heap[i].distance);
+        }
     }
-#endif
 
     // Pull matches out by increasing order of distance.
     // To avoid reassigning pointers that have already been matched, the loop keeps track
@@ -3902,13 +3905,14 @@
                     parentIndex = childIndex;
                 }
 
-#if DEBUG_POINTER_ASSIGNMENT
-                ALOGD("assignPointerIds - reduced distance min-heap: size=%d", heapSize);
-                for (size_t j = 0; j < heapSize; j++) {
-                    ALOGD("  heap[%zu]: cur=%" PRIu32 ", last=%" PRIu32 ", distance=%" PRIu64, j,
-                          heap[j].currentPointerIndex, heap[j].lastPointerIndex, heap[j].distance);
+                if (DEBUG_POINTER_ASSIGNMENT) {
+                    ALOGD("assignPointerIds - reduced distance min-heap: size=%d", heapSize);
+                    for (size_t j = 0; j < heapSize; j++) {
+                        ALOGD("  heap[%zu]: cur=%" PRIu32 ", last=%" PRIu32 ", distance=%" PRIu64,
+                              j, heap[j].currentPointerIndex, heap[j].lastPointerIndex,
+                              heap[j].distance);
+                    }
                 }
-#endif
             }
 
             heapSize -= 1;
@@ -3930,11 +3934,11 @@
                                                      currentPointerIndex));
             usedIdBits.markBit(id);
 
-#if DEBUG_POINTER_ASSIGNMENT
-            ALOGD("assignPointerIds - matched: cur=%" PRIu32 ", last=%" PRIu32 ", id=%" PRIu32
-                  ", distance=%" PRIu64,
-                  lastPointerIndex, currentPointerIndex, id, heap[0].distance);
-#endif
+            if (DEBUG_POINTER_ASSIGNMENT) {
+                ALOGD("assignPointerIds - matched: cur=%" PRIu32 ", last=%" PRIu32 ", id=%" PRIu32
+                      ", distance=%" PRIu64,
+                      lastPointerIndex, currentPointerIndex, id, heap[0].distance);
+            }
             break;
         }
     }
@@ -3949,9 +3953,10 @@
         current.rawPointerData.markIdBit(id,
                                          current.rawPointerData.isHovering(currentPointerIndex));
 
-#if DEBUG_POINTER_ASSIGNMENT
-        ALOGD("assignPointerIds - assigned: cur=%" PRIu32 ", id=%" PRIu32, currentPointerIndex, id);
-#endif
+        if (DEBUG_POINTER_ASSIGNMENT) {
+            ALOGD("assignPointerIds - assigned: cur=%" PRIu32 ", id=%" PRIu32, currentPointerIndex,
+                  id);
+        }
     }
 }
 
diff --git a/services/inputflinger/reader/mapper/VibratorInputMapper.cpp b/services/inputflinger/reader/mapper/VibratorInputMapper.cpp
index 8c7879b..1976fed 100644
--- a/services/inputflinger/reader/mapper/VibratorInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/VibratorInputMapper.cpp
@@ -41,10 +41,10 @@
 
 void VibratorInputMapper::vibrate(const VibrationSequence& sequence, ssize_t repeat,
                                   int32_t token) {
-#if DEBUG_VIBRATOR
-    ALOGD("vibrate: deviceId=%d, pattern=[%s], repeat=%zd, token=%d", getDeviceId(),
-          sequence.toString().c_str(), repeat, token);
-#endif
+    if (DEBUG_VIBRATOR) {
+        ALOGD("vibrate: deviceId=%d, pattern=[%s], repeat=%zd, token=%d", getDeviceId(),
+              sequence.toString().c_str(), repeat, token);
+    }
 
     mVibrating = true;
     mSequence = sequence;
@@ -59,9 +59,9 @@
 }
 
 void VibratorInputMapper::cancelVibrate(int32_t token) {
-#if DEBUG_VIBRATOR
-    ALOGD("cancelVibrate: deviceId=%d, token=%d", getDeviceId(), token);
-#endif
+    if (DEBUG_VIBRATOR) {
+        ALOGD("cancelVibrate: deviceId=%d, token=%d", getDeviceId(), token);
+    }
 
     if (mVibrating && mToken == token) {
         stopVibrating();
@@ -87,9 +87,9 @@
 }
 
 void VibratorInputMapper::nextStep() {
-#if DEBUG_VIBRATOR
-    ALOGD("nextStep: index=%d, vibrate deviceId=%d", (int)mIndex, getDeviceId());
-#endif
+    if (DEBUG_VIBRATOR) {
+        ALOGD("nextStep: index=%d, vibrate deviceId=%d", (int)mIndex, getDeviceId());
+    }
     mIndex += 1;
     if (size_t(mIndex) >= mSequence.pattern.size()) {
         if (mRepeat < 0) {
@@ -102,16 +102,16 @@
 
     const VibrationElement& element = mSequence.pattern[mIndex];
     if (element.isOn()) {
-#if DEBUG_VIBRATOR
-        std::string description = element.toString();
-        ALOGD("nextStep: sending vibrate deviceId=%d, element=%s", getDeviceId(),
-              description.c_str());
-#endif
+        if (DEBUG_VIBRATOR) {
+            std::string description = element.toString();
+            ALOGD("nextStep: sending vibrate deviceId=%d, element=%s", getDeviceId(),
+                  description.c_str());
+        }
         getDeviceContext().vibrate(element);
     } else {
-#if DEBUG_VIBRATOR
-        ALOGD("nextStep: sending cancel vibrate deviceId=%d", getDeviceId());
-#endif
+        if (DEBUG_VIBRATOR) {
+            ALOGD("nextStep: sending cancel vibrate deviceId=%d", getDeviceId());
+        }
         getDeviceContext().cancelVibrate();
     }
     nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
@@ -119,16 +119,16 @@
             std::chrono::duration_cast<std::chrono::nanoseconds>(element.duration);
     mNextStepTime = now + duration.count();
     getContext()->requestTimeoutAtTime(mNextStepTime);
-#if DEBUG_VIBRATOR
-    ALOGD("nextStep: scheduled timeout in %lldms", element.duration.count());
-#endif
+    if (DEBUG_VIBRATOR) {
+        ALOGD("nextStep: scheduled timeout in %lldms", element.duration.count());
+    }
 }
 
 void VibratorInputMapper::stopVibrating() {
     mVibrating = false;
-#if DEBUG_VIBRATOR
-    ALOGD("stopVibrating: sending cancel vibrate deviceId=%d", getDeviceId());
-#endif
+    if (DEBUG_VIBRATOR) {
+        ALOGD("stopVibrating: sending cancel vibrate deviceId=%d", getDeviceId());
+    }
     getDeviceContext().cancelVibrate();
 
     // Request InputReader to notify InputManagerService for vibration complete.
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index 39c5262..2c64271 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -3145,8 +3145,8 @@
     const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
 
     ASSERT_EQ(keyArgs.action, verifiedKey.action);
-    ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
     ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
+    ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
     ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
     ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
     ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
@@ -3194,8 +3194,8 @@
     EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
     EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
     EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
-    EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
     EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
+    EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
     EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
     EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
 }
@@ -4179,7 +4179,7 @@
         }
     }
 
-    void touchAndAssertPositions(int32_t action, std::vector<PointF> touchedPoints,
+    void touchAndAssertPositions(int32_t action, const std::vector<PointF>& touchedPoints,
                                  std::vector<PointF> expectedPoints) {
         NotifyMotionArgs motionArgs = generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
                                                          ADISPLAY_ID_DEFAULT, touchedPoints);
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index 64ddd68..e26c763 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -292,14 +292,15 @@
     // Sideband layers
     auto* compositionState = editCompositionState();
     if (compositionState->sidebandStream.get() && !compositionState->sidebandStreamHasFrame) {
-        compositionState->compositionType = Hwc2::IComposerClient::Composition::SIDEBAND;
+        compositionState->compositionType =
+                aidl::android::hardware::graphics::composer3::Composition::SIDEBAND;
         return;
     } else {
         // Normal buffer layers
         compositionState->hdrMetadata = mBufferInfo.mHdrMetadata;
         compositionState->compositionType = mPotentialCursor
-                ? Hwc2::IComposerClient::Composition::CURSOR
-                : Hwc2::IComposerClient::Composition::DEVICE;
+                ? aidl::android::hardware::graphics::composer3::Composition::CURSOR
+                : aidl::android::hardware::graphics::composer3::Composition::DEVICE;
     }
 
     compositionState->buffer = mBufferInfo.mBuffer->getBuffer();
diff --git a/services/surfaceflinger/Client.cpp b/services/surfaceflinger/Client.cpp
index 0a8ebec..6d7b732 100644
--- a/services/surfaceflinger/Client.cpp
+++ b/services/surfaceflinger/Client.cpp
@@ -98,7 +98,8 @@
 
 status_t Client::mirrorSurface(const sp<IBinder>& mirrorFromHandle, sp<IBinder>* outHandle,
                                int32_t* outLayerId) {
-    return mFlinger->mirrorLayer(this, mirrorFromHandle, outHandle, outLayerId);
+    LayerCreationArgs args(mFlinger.get(), this, "MirrorRoot", 0 /* flags */, LayerMetadata());
+    return mFlinger->mirrorLayer(args, mirrorFromHandle, outHandle, outLayerId);
 }
 
 status_t Client::clearLayerFrameStats(const sp<IBinder>& handle) const {
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h
index ac243c0..e77e155 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h
@@ -134,6 +134,9 @@
 
         // Configure layer settings for using blurs
         BlurSetting blurSetting;
+
+        // Requested white point of the layer in nits
+        const float whitePointNits;
     };
 
     // A superset of LayerSettings required by RenderEngine to compose a layer
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h
index 36594ea..8bf7f8f 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h
@@ -39,6 +39,8 @@
 
 #include "DisplayHardware/Hal.h"
 
+#include <aidl/android/hardware/graphics/composer3/Composition.h>
+
 // TODO(b/129481165): remove the #pragma below and fix conversion issues
 #pragma clang diagnostic pop // ignored "-Wconversion -Wextra"
 
@@ -156,12 +158,13 @@
      */
 
     // The type of composition for this layer
-    hal::Composition compositionType{hal::Composition::INVALID};
+    aidl::android::hardware::graphics::composer3::Composition compositionType{
+            aidl::android::hardware::graphics::composer3::Composition::INVALID};
 
     // The buffer and related state
     sp<GraphicBuffer> buffer;
     int bufferSlot{BufferQueue::INVALID_BUFFER_SLOT};
-    sp<Fence> acquireFence;
+    sp<Fence> acquireFence = Fence::NO_FENCE;
     Region surfaceDamage;
 
     // The handle to use for a sideband stream for this layer
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h
index ead941d..a2824f5 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h
@@ -33,6 +33,8 @@
 
 #include "LayerFE.h"
 
+#include <aidl/android/hardware/graphics/composer3/Composition.h>
+
 // TODO(b/129481165): remove the #pragma below and fix conversion issues
 #pragma clang diagnostic pop // ignored "-Wconversion -Wextra"
 
@@ -112,7 +114,8 @@
     virtual bool isHardwareCursor() const = 0;
 
     // Applies a HWC device requested composition type change
-    virtual void applyDeviceCompositionTypeChange(Hwc2::IComposerClient::Composition) = 0;
+    virtual void applyDeviceCompositionTypeChange(
+            aidl::android::hardware::graphics::composer3::Composition) = 0;
 
     // Prepares to apply any HWC device layer requests
     virtual void prepareForDeviceLayerRequests() = 0;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h
index b407267..3571e11 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h
@@ -76,7 +76,7 @@
     virtual void applyChangedTypesToLayers(const ChangedTypes&);
     virtual void applyDisplayRequests(const DisplayRequests&);
     virtual void applyLayerRequestsToLayers(const LayerRequests&);
-    virtual void applyClientTargetRequests(const ClientTargetProperty&);
+    virtual void applyClientTargetRequests(const ClientTargetProperty&, float whitePointNits);
 
     // Internal
     virtual void setConfiguration(const compositionengine::DisplayCreationArgs&);
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h
index 44f754f..c5b6443 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h
@@ -127,6 +127,9 @@
     // SDR white point
     float sdrWhitePointNits{-1.f};
 
+    // White point of the client target
+    float clientTargetWhitePointNits{-1.f};
+
     // Debugging
     void dump(std::string& result) const;
 };
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h
index c15249d..0082dac 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h
@@ -27,6 +27,8 @@
 
 #include "DisplayHardware/DisplayIdentification.h"
 
+#include <aidl/android/hardware/graphics/composer3/Composition.h>
+
 namespace android::compositionengine {
 
 struct LayerFECompositionState;
@@ -50,7 +52,8 @@
     HWC2::Layer* getHwcLayer() const override;
     bool requiresClientComposition() const override;
     bool isHardwareCursor() const override;
-    void applyDeviceCompositionTypeChange(Hwc2::IComposerClient::Composition) override;
+    void applyDeviceCompositionTypeChange(
+            aidl::android::hardware::graphics::composer3::Composition) override;
     void prepareForDeviceLayerRequests() override;
     void applyDeviceLayerRequest(Hwc2::IComposerClient::LayerRequest request) override;
     bool needsFiltering() const override;
@@ -68,21 +71,24 @@
 
 private:
     Rect calculateInitialCrop() const;
-    void writeOutputDependentGeometryStateToHWC(HWC2::Layer*, Hwc2::IComposerClient::Composition,
-                                                uint32_t z);
+    void writeOutputDependentGeometryStateToHWC(
+            HWC2::Layer*, aidl::android::hardware::graphics::composer3::Composition, uint32_t z);
     void writeOutputIndependentGeometryStateToHWC(HWC2::Layer*, const LayerFECompositionState&,
                                                   bool skipLayer);
     void writeOutputDependentPerFrameStateToHWC(HWC2::Layer*);
     void writeOutputIndependentPerFrameStateToHWC(
             HWC2::Layer*, const LayerFECompositionState&,
-            Hwc2::IComposerClient::Composition compositionType, bool skipLayer);
+            aidl::android::hardware::graphics::composer3::Composition compositionType,
+            bool skipLayer);
     void writeSolidColorStateToHWC(HWC2::Layer*, const LayerFECompositionState&);
     void writeSidebandStateToHWC(HWC2::Layer*, const LayerFECompositionState&);
     void writeBufferStateToHWC(HWC2::Layer*, const LayerFECompositionState&, bool skipLayer);
-    void writeCompositionTypeToHWC(HWC2::Layer*, Hwc2::IComposerClient::Composition,
+    void writeCompositionTypeToHWC(HWC2::Layer*,
+                                   aidl::android::hardware::graphics::composer3::Composition,
                                    bool isPeekingThrough, bool skipLayer);
-    void detectDisallowedCompositionTypeChange(Hwc2::IComposerClient::Composition from,
-                                               Hwc2::IComposerClient::Composition to) const;
+    void detectDisallowedCompositionTypeChange(
+            aidl::android::hardware::graphics::composer3::Composition from,
+            aidl::android::hardware::graphics::composer3::Composition to) const;
     bool isClientCompositionForced(bool isPeekingThrough) const;
 };
 
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h
index 7564c54..49cb912 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h
@@ -35,6 +35,8 @@
 
 #include "DisplayHardware/ComposerHal.h"
 
+#include <aidl/android/hardware/graphics/composer3/Composition.h>
+
 // TODO(b/129481165): remove the #pragma below and fix conversion issues
 #pragma clang diagnostic pop // ignored "-Wconversion -Wextra"
 
@@ -123,8 +125,8 @@
         std::shared_ptr<HWC2::Layer> hwcLayer;
 
         // The most recently set HWC composition type for this layer
-        Hwc2::IComposerClient::Composition hwcCompositionType{
-                Hwc2::IComposerClient::Composition::INVALID};
+        aidl::android::hardware::graphics::composer3::Composition hwcCompositionType{
+                aidl::android::hardware::graphics::composer3::Composition::INVALID};
 
         // The buffer cache for this layer. This is used to lower the
         // cost of sending reused buffers to the HWC.
@@ -146,6 +148,10 @@
 
     // Timestamp for when the layer is queued for client composition
     nsecs_t clientCompositionTimestamp{0};
+
+    // White point of the layer, in nits.
+    static constexpr float kDefaultWhitePointNits = 200.f;
+    float whitePointNits = kDefaultWhitePointNits;
 };
 
 } // namespace compositionengine::impl
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/LayerState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/LayerState.h
index 7397c19..14324de 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/LayerState.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/LayerState.h
@@ -28,6 +28,8 @@
 #include "DisplayHardware/Hal.h"
 #include "math/HashCombine.h"
 
+#include <aidl/android/hardware/graphics/composer3/Composition.h>
+
 namespace std {
 template <typename T>
 struct hash<android::sp<T>> {
@@ -232,7 +234,7 @@
         return mBackgroundBlurRadius.get() > 0 || !mBlurRegions.get().empty();
     }
     int32_t getBackgroundBlurRadius() const { return mBackgroundBlurRadius.get(); }
-    hardware::graphics::composer::hal::Composition getCompositionType() const {
+    aidl::android::hardware::graphics::composer3::Composition getCompositionType() const {
         return mCompositionType.get();
     }
 
@@ -370,17 +372,18 @@
 
     OutputLayerState<mat4, LayerStateField::ColorTransform> mColorTransform;
 
-    using CompositionTypeState = OutputLayerState<hardware::graphics::composer::hal::Composition,
-                                                  LayerStateField::CompositionType>;
-    CompositionTypeState
-            mCompositionType{[](auto layer) {
-                                 return layer->getState().forceClientComposition
-                                         ? hardware::graphics::composer::hal::Composition::CLIENT
-                                         : layer->getLayerFE()
-                                                   .getCompositionState()
-                                                   ->compositionType;
-                             },
-                             CompositionTypeState::getHalToStrings()};
+    using CompositionTypeState =
+            OutputLayerState<aidl::android::hardware::graphics::composer3::Composition,
+                             LayerStateField::CompositionType>;
+    CompositionTypeState mCompositionType{[](auto layer) {
+                                              return layer->getState().forceClientComposition
+                                                      ? aidl::android::hardware::graphics::
+                                                                composer3::Composition::CLIENT
+                                                      : layer->getLayerFE()
+                                                                .getCompositionState()
+                                                                ->compositionType;
+                                          },
+                                          CompositionTypeState::getHalToStrings()};
 
     OutputLayerState<void*, LayerStateField::SidebandStream>
             mSidebandStream{[](auto layer) {
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Predictor.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Predictor.h
index fe486d3..ef1560e 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Predictor.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Predictor.h
@@ -109,7 +109,7 @@
     static std::optional<Plan> fromString(const std::string&);
 
     void reset() { mLayerTypes.clear(); }
-    void addLayerType(hardware::graphics::composer::hal::Composition type) {
+    void addLayerType(aidl::android::hardware::graphics::composer3::Composition type) {
         mLayerTypes.emplace_back(type);
     }
 
@@ -125,7 +125,7 @@
     }
 
 private:
-    std::vector<hardware::graphics::composer::hal::Composition> mLayerTypes;
+    std::vector<aidl::android::hardware::graphics::composer3::Composition> mLayerTypes;
 };
 
 } // namespace android::compositionengine::impl::planner
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h
index 358ed5a..a6cb811 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h
@@ -46,7 +46,8 @@
     MOCK_CONST_METHOD0(getHwcLayer, HWC2::Layer*());
     MOCK_CONST_METHOD0(requiresClientComposition, bool());
     MOCK_CONST_METHOD0(isHardwareCursor, bool());
-    MOCK_METHOD1(applyDeviceCompositionTypeChange, void(Hwc2::IComposerClient::Composition));
+    MOCK_METHOD1(applyDeviceCompositionTypeChange,
+                 void(aidl::android::hardware::graphics::composer3::Composition));
     MOCK_METHOD0(prepareForDeviceLayerRequests, void());
     MOCK_METHOD1(applyDeviceLayerRequest, void(Hwc2::IComposerClient::LayerRequest request));
     MOCK_CONST_METHOD0(needsFiltering, bool());
diff --git a/services/surfaceflinger/CompositionEngine/src/Display.cpp b/services/surfaceflinger/CompositionEngine/src/Display.cpp
index 02fa49f..3571319 100644
--- a/services/surfaceflinger/CompositionEngine/src/Display.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Display.cpp
@@ -237,7 +237,8 @@
         applyChangedTypesToLayers(changes->changedTypes);
         applyDisplayRequests(changes->displayRequests);
         applyLayerRequestsToLayers(changes->layerRequests);
-        applyClientTargetRequests(changes->clientTargetProperty);
+        applyClientTargetRequests(changes->clientTargetProperty,
+                                  changes->clientTargetWhitePointNits);
     }
 
     // Determine what type of composition we are doing from the final state
@@ -281,7 +282,8 @@
 
         if (auto it = changedTypes.find(hwcLayer); it != changedTypes.end()) {
             layer->applyDeviceCompositionTypeChange(
-                    static_cast<Hwc2::IComposerClient::Composition>(it->second));
+                    static_cast<aidl::android::hardware::graphics::composer3::Composition>(
+                            it->second));
         }
     }
 }
@@ -309,12 +311,14 @@
     }
 }
 
-void Display::applyClientTargetRequests(const ClientTargetProperty& clientTargetProperty) {
+void Display::applyClientTargetRequests(const ClientTargetProperty& clientTargetProperty,
+                                        float whitePointNits) {
     if (clientTargetProperty.dataspace == ui::Dataspace::UNKNOWN) {
         return;
     }
 
     editState().dataspace = clientTargetProperty.dataspace;
+    editState().clientTargetWhitePointNits = whitePointNits;
     getRenderSurface()->setBufferDataspace(clientTargetProperty.dataspace);
     getRenderSurface()->setBufferPixelFormat(clientTargetProperty.pixelFormat);
 }
diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp
index 6800004..d503153 100644
--- a/services/surfaceflinger/CompositionEngine/src/Output.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp
@@ -1057,7 +1057,7 @@
     clientCompositionDisplay.maxLuminance = outputState.displayBrightnessNits > 0.f
             ? outputState.displayBrightnessNits
             : mDisplayColorProfile->getHdrCapabilities().getDesiredMaxLuminance();
-    clientCompositionDisplay.sdrWhitePointNits = outputState.sdrWhitePointNits;
+    clientCompositionDisplay.targetLuminanceNits = outputState.clientTargetWhitePointNits;
 
     // Compute the global color transform matrix.
     if (!outputState.usesDeviceComposition && !getSkipColorTransform()) {
@@ -1217,7 +1217,8 @@
                                        .dataspace = outputDataspace,
                                        .realContentIsVisible = realContentIsVisible,
                                        .clearContent = !clientComposition,
-                                       .blurSetting = blurSetting};
+                                       .blurSetting = blurSetting,
+                                       .whitePointNits = layerState.whitePointNits};
                 results = layerFE.prepareClientCompositionList(targetSettings);
                 if (realContentIsVisible && !results.empty()) {
                     layer->editState().clientCompositionTimestamp = systemTime();
diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
index cf76183..e6bcec8 100644
--- a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
@@ -24,6 +24,9 @@
 #include <compositionengine/impl/OutputLayer.h>
 #include <compositionengine/impl/OutputLayerCompositionState.h>
 #include <cstdint>
+#include "system/graphics-base-v1.0.h"
+
+#include <ui/DataspaceUtils.h>
 
 // TODO(b/129481165): remove the #pragma below and fix conversion issues
 #pragma clang diagnostic push
@@ -34,6 +37,8 @@
 // TODO(b/129481165): remove the #pragma below and fix conversion issues
 #pragma clang diagnostic pop // ignored "-Wconversion"
 
+using aidl::android::hardware::graphics::composer3::Composition;
+
 namespace android::compositionengine {
 
 OutputLayer::~OutputLayer() = default;
@@ -317,6 +322,14 @@
             ? outputState.targetDataspace
             : layerFEState->dataspace;
 
+    // For hdr content, treat the white point as the display brightness - HDR content should not be
+    // boosted or dimmed.
+    if (isHdrDataspace(state.dataspace)) {
+        state.whitePointNits = getOutput().getState().displayBrightnessNits;
+    } else {
+        state.whitePointNits = getOutput().getState().sdrWhitePointNits;
+    }
+
     // These are evaluated every frame as they can potentially change at any
     // time.
     if (layerFEState->forceClientComposition || !profile.isDataspaceSupported(state.dataspace) ||
@@ -347,8 +360,8 @@
 
     auto requestedCompositionType = outputIndependentState->compositionType;
 
-    if (requestedCompositionType == hal::Composition::SOLID_COLOR && state.overrideInfo.buffer) {
-        requestedCompositionType = hal::Composition::DEVICE;
+    if (requestedCompositionType == Composition::SOLID_COLOR && state.overrideInfo.buffer) {
+        requestedCompositionType = Composition::DEVICE;
     }
 
     // TODO(b/181172795): We now update geometry for all flattened layers. We should update it
@@ -369,7 +382,7 @@
     writeCompositionTypeToHWC(hwcLayer.get(), requestedCompositionType, isPeekingThrough,
                               skipLayer);
 
-    if (requestedCompositionType == hal::Composition::SOLID_COLOR) {
+    if (requestedCompositionType == Composition::SOLID_COLOR) {
         writeSolidColorStateToHWC(hwcLayer.get(), *outputIndependentState);
     }
 
@@ -378,7 +391,7 @@
 }
 
 void OutputLayer::writeOutputDependentGeometryStateToHWC(HWC2::Layer* hwcLayer,
-                                                         hal::Composition requestedCompositionType,
+                                                         Composition requestedCompositionType,
                                                          uint32_t z) {
     const auto& outputDependentState = getState();
 
@@ -412,7 +425,7 @@
     }
 
     // Solid-color layers and overridden buffers should always use an identity transform.
-    const auto bufferTransform = (requestedCompositionType != hal::Composition::SOLID_COLOR &&
+    const auto bufferTransform = (requestedCompositionType != Composition::SOLID_COLOR &&
                                   getState().overrideInfo.buffer == nullptr)
             ? outputDependentState.bufferTransform
             : static_cast<hal::Transform>(0);
@@ -479,11 +492,21 @@
         ALOGE("[%s] Failed to set dataspace %d: %s (%d)", getLayerFE().getDebugName(), dataspace,
               to_string(error).c_str(), static_cast<int32_t>(error));
     }
+
+    // Don't dim cached layers
+    const auto whitePointNits = outputDependentState.overrideInfo.buffer
+            ? getOutput().getState().displayBrightnessNits
+            : outputDependentState.whitePointNits;
+
+    if (auto error = hwcLayer->setWhitePointNits(whitePointNits); error != hal::Error::NONE) {
+        ALOGE("[%s] Failed to set white point %f: %s (%d)", getLayerFE().getDebugName(),
+              whitePointNits, to_string(error).c_str(), static_cast<int32_t>(error));
+    }
 }
 
 void OutputLayer::writeOutputIndependentPerFrameStateToHWC(
         HWC2::Layer* hwcLayer, const LayerFECompositionState& outputIndependentState,
-        hal::Composition compositionType, bool skipLayer) {
+        Composition compositionType, bool skipLayer) {
     switch (auto error = hwcLayer->setColorTransform(outputIndependentState.colorTransform)) {
         case hal::Error::NONE:
             break;
@@ -508,18 +531,18 @@
 
     // Content-specific per-frame state
     switch (compositionType) {
-        case hal::Composition::SOLID_COLOR:
+        case Composition::SOLID_COLOR:
             // For compatibility, should be written AFTER the composition type.
             break;
-        case hal::Composition::SIDEBAND:
+        case Composition::SIDEBAND:
             writeSidebandStateToHWC(hwcLayer, outputIndependentState);
             break;
-        case hal::Composition::CURSOR:
-        case hal::Composition::DEVICE:
+        case Composition::CURSOR:
+        case Composition::DEVICE:
             writeBufferStateToHWC(hwcLayer, outputIndependentState, skipLayer);
             break;
-        case hal::Composition::INVALID:
-        case hal::Composition::CLIENT:
+        case Composition::INVALID:
+        case Composition::CLIENT:
             // Ignored
             break;
     }
@@ -585,13 +608,13 @@
 }
 
 void OutputLayer::writeCompositionTypeToHWC(HWC2::Layer* hwcLayer,
-                                            hal::Composition requestedCompositionType,
+                                            Composition requestedCompositionType,
                                             bool isPeekingThrough, bool skipLayer) {
     auto& outputDependentState = editState();
 
     if (isClientCompositionForced(isPeekingThrough)) {
         // If we are forcing client composition, we need to tell the HWC
-        requestedCompositionType = hal::Composition::CLIENT;
+        requestedCompositionType = Composition::CLIENT;
     }
 
     // Set the requested composition type with the HWC whenever it changes
@@ -604,7 +627,7 @@
         if (auto error = hwcLayer->setCompositionType(requestedCompositionType);
             error != hal::Error::NONE) {
             ALOGE("[%s] Failed to set composition type %s: %s (%d)", getLayerFE().getDebugName(),
-                  toString(requestedCompositionType).c_str(), to_string(error).c_str(),
+                  to_string(requestedCompositionType).c_str(), to_string(error).c_str(),
                   static_cast<int32_t>(error));
         }
     }
@@ -643,38 +666,37 @@
 
 bool OutputLayer::requiresClientComposition() const {
     const auto& state = getState();
-    return !state.hwc || state.hwc->hwcCompositionType == hal::Composition::CLIENT;
+    return !state.hwc || state.hwc->hwcCompositionType == Composition::CLIENT;
 }
 
 bool OutputLayer::isHardwareCursor() const {
     const auto& state = getState();
-    return state.hwc && state.hwc->hwcCompositionType == hal::Composition::CURSOR;
+    return state.hwc && state.hwc->hwcCompositionType == Composition::CURSOR;
 }
 
-void OutputLayer::detectDisallowedCompositionTypeChange(hal::Composition from,
-                                                        hal::Composition to) const {
+void OutputLayer::detectDisallowedCompositionTypeChange(Composition from, Composition to) const {
     bool result = false;
     switch (from) {
-        case hal::Composition::INVALID:
-        case hal::Composition::CLIENT:
+        case Composition::INVALID:
+        case Composition::CLIENT:
             result = false;
             break;
 
-        case hal::Composition::DEVICE:
-        case hal::Composition::SOLID_COLOR:
-            result = (to == hal::Composition::CLIENT);
+        case Composition::DEVICE:
+        case Composition::SOLID_COLOR:
+            result = (to == Composition::CLIENT);
             break;
 
-        case hal::Composition::CURSOR:
-        case hal::Composition::SIDEBAND:
-            result = (to == hal::Composition::CLIENT || to == hal::Composition::DEVICE);
+        case Composition::CURSOR:
+        case Composition::SIDEBAND:
+            result = (to == Composition::CLIENT || to == Composition::DEVICE);
             break;
     }
 
     if (!result) {
         ALOGE("[%s] Invalid device requested composition type change: %s (%d) --> %s (%d)",
-              getLayerFE().getDebugName(), toString(from).c_str(), static_cast<int>(from),
-              toString(to).c_str(), static_cast<int>(to));
+              getLayerFE().getDebugName(), to_string(from).c_str(), static_cast<int>(from),
+              to_string(to).c_str(), static_cast<int>(to));
     }
 }
 
@@ -683,7 +705,7 @@
             (!isPeekingThrough && getLayerFE().hasRoundedCorners());
 }
 
-void OutputLayer::applyDeviceCompositionTypeChange(hal::Composition compositionType) {
+void OutputLayer::applyDeviceCompositionTypeChange(Composition compositionType) {
     auto& state = editState();
     LOG_FATAL_IF(!state.hwc);
     auto& hwcState = *state.hwc;
diff --git a/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp b/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp
index ff96d94..2203f22 100644
--- a/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp
@@ -170,6 +170,7 @@
             .clip = viewport,
             .outputDataspace = outputDataspace,
             .orientation = orientation,
+            .targetLuminanceNits = outputState.displayBrightnessNits,
     };
 
     LayerFE::ClientCompositionTargetSettings targetSettings{
@@ -182,6 +183,7 @@
             .realContentIsVisible = true,
             .clearContent = false,
             .blurSetting = LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled,
+            .whitePointNits = outputState.displayBrightnessNits,
     };
 
     std::vector<renderengine::LayerSettings> layerSettings;
diff --git a/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp b/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp
index c14effc..0918510 100644
--- a/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp
@@ -211,7 +211,8 @@
         displayCost += static_cast<size_t>(layer->getDisplayFrame().width() *
                                            layer->getDisplayFrame().height());
 
-        hasClientComposition |= layer->getCompositionType() == hal::Composition::CLIENT;
+        hasClientComposition |= layer->getCompositionType() ==
+                aidl::android::hardware::graphics::composer3::Composition::CLIENT;
     }
 
     if (hasClientComposition) {
diff --git a/services/surfaceflinger/CompositionEngine/src/planner/LayerState.cpp b/services/surfaceflinger/CompositionEngine/src/planner/LayerState.cpp
index 2532e3d..c79ca0d 100644
--- a/services/surfaceflinger/CompositionEngine/src/planner/LayerState.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/planner/LayerState.cpp
@@ -160,7 +160,8 @@
             lhs.mColorTransform == rhs.mColorTransform &&
             lhs.mCompositionType == rhs.mCompositionType &&
             lhs.mSidebandStream == rhs.mSidebandStream && lhs.mBuffer == rhs.mBuffer &&
-            (lhs.mCompositionType.get() != hal::Composition::SOLID_COLOR ||
+            (lhs.mCompositionType.get() !=
+                     aidl::android::hardware::graphics::composer3::Composition::SOLID_COLOR ||
              lhs.mSolidColor == rhs.mSolidColor);
 }
 
diff --git a/services/surfaceflinger/CompositionEngine/src/planner/Planner.cpp b/services/surfaceflinger/CompositionEngine/src/planner/Planner.cpp
index f5b1cee..74d2701 100644
--- a/services/surfaceflinger/CompositionEngine/src/planner/Planner.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/planner/Planner.cpp
@@ -193,7 +193,7 @@
 
         finalPlan.addLayerType(
                 forcedOrRequestedClient
-                        ? hardware::graphics::composer::hal::Composition::CLIENT
+                        ? aidl::android::hardware::graphics::composer3::Composition::CLIENT
                         : layer->getLayerFE().getCompositionState()->compositionType);
     }
 
diff --git a/services/surfaceflinger/CompositionEngine/src/planner/Predictor.cpp b/services/surfaceflinger/CompositionEngine/src/planner/Predictor.cpp
index 8226ef7..074673e 100644
--- a/services/surfaceflinger/CompositionEngine/src/planner/Predictor.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/planner/Predictor.cpp
@@ -39,8 +39,10 @@
 
         // Skip layers where both are client-composited, since that doesn't change the
         // composition plan
-        if (mLayers[i].getCompositionType() == hal::Composition::CLIENT &&
-            other[i]->getCompositionType() == hal::Composition::CLIENT) {
+        if (mLayers[i].getCompositionType() ==
+                    aidl::android::hardware::graphics::composer3::Composition::CLIENT &&
+            other[i]->getCompositionType() ==
+                    aidl::android::hardware::graphics::composer3::Composition::CLIENT) {
             continue;
         }
 
@@ -89,22 +91,28 @@
     for (char c : string) {
         switch (c) {
             case 'C':
-                plan.addLayerType(hal::Composition::CLIENT);
+                plan.addLayerType(
+                        aidl::android::hardware::graphics::composer3::Composition::CLIENT);
                 continue;
             case 'U':
-                plan.addLayerType(hal::Composition::CURSOR);
+                plan.addLayerType(
+                        aidl::android::hardware::graphics::composer3::Composition::CURSOR);
                 continue;
             case 'D':
-                plan.addLayerType(hal::Composition::DEVICE);
+                plan.addLayerType(
+                        aidl::android::hardware::graphics::composer3::Composition::DEVICE);
                 continue;
             case 'I':
-                plan.addLayerType(hal::Composition::INVALID);
+                plan.addLayerType(
+                        aidl::android::hardware::graphics::composer3::Composition::INVALID);
                 continue;
             case 'B':
-                plan.addLayerType(hal::Composition::SIDEBAND);
+                plan.addLayerType(
+                        aidl::android::hardware::graphics::composer3::Composition::SIDEBAND);
                 continue;
             case 'S':
-                plan.addLayerType(hal::Composition::SOLID_COLOR);
+                plan.addLayerType(
+                        aidl::android::hardware::graphics::composer3::Composition::SOLID_COLOR);
                 continue;
             default:
                 return std::nullopt;
@@ -117,22 +125,22 @@
     std::string result;
     for (auto type : plan.mLayerTypes) {
         switch (type) {
-            case hal::Composition::CLIENT:
+            case aidl::android::hardware::graphics::composer3::Composition::CLIENT:
                 result.append("C");
                 break;
-            case hal::Composition::CURSOR:
+            case aidl::android::hardware::graphics::composer3::Composition::CURSOR:
                 result.append("U");
                 break;
-            case hal::Composition::DEVICE:
+            case aidl::android::hardware::graphics::composer3::Composition::DEVICE:
                 result.append("D");
                 break;
-            case hal::Composition::INVALID:
+            case aidl::android::hardware::graphics::composer3::Composition::INVALID:
                 result.append("I");
                 break;
-            case hal::Composition::SIDEBAND:
+            case aidl::android::hardware::graphics::composer3::Composition::SIDEBAND:
                 result.append("B");
                 break;
-            case hal::Composition::SOLID_COLOR:
+            case aidl::android::hardware::graphics::composer3::Composition::SOLID_COLOR:
                 result.append("S");
                 break;
         }
diff --git a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
index ed235b8..3bdb2c0 100644
--- a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
@@ -38,6 +38,10 @@
 #include "MockHWComposer.h"
 #include "MockPowerAdvisor.h"
 
+#include <aidl/android/hardware/graphics/composer3/Composition.h>
+
+using aidl::android::hardware::graphics::composer3::Composition;
+
 namespace android::compositionengine {
 namespace {
 
@@ -592,10 +596,11 @@
 
 TEST_F(DisplayChooseCompositionStrategyTest, normalOperationWithChanges) {
     android::HWComposer::DeviceRequestedChanges changes{
-            {{nullptr, hal::Composition::CLIENT}},
+            {{nullptr, Composition::CLIENT}},
             hal::DisplayRequest::FLIP_CLIENT_TARGET,
             {{nullptr, hal::LayerRequest::CLEAR_CLIENT_TARGET}},
             {hal::PixelFormat::RGBA_8888, hal::Dataspace::UNKNOWN},
+            -1.f,
     };
 
     // Since two calls are made to anyLayersRequireClientComposition with different return
@@ -699,17 +704,15 @@
 }
 
 TEST_F(DisplayApplyChangedTypesToLayersTest, appliesChanges) {
-    EXPECT_CALL(*mLayer1.outputLayer,
-                applyDeviceCompositionTypeChange(Hwc2::IComposerClient::Composition::CLIENT))
+    EXPECT_CALL(*mLayer1.outputLayer, applyDeviceCompositionTypeChange(Composition::CLIENT))
             .Times(1);
-    EXPECT_CALL(*mLayer2.outputLayer,
-                applyDeviceCompositionTypeChange(Hwc2::IComposerClient::Composition::DEVICE))
+    EXPECT_CALL(*mLayer2.outputLayer, applyDeviceCompositionTypeChange(Composition::DEVICE))
             .Times(1);
 
     mDisplay->applyChangedTypesToLayers(impl::Display::ChangedTypes{
-            {&mLayer1.hwc2Layer, hal::Composition::CLIENT},
-            {&mLayer2.hwc2Layer, hal::Composition::DEVICE},
-            {&hwc2LayerUnknown, hal::Composition::SOLID_COLOR},
+            {&mLayer1.hwc2Layer, Composition::CLIENT},
+            {&mLayer2.hwc2Layer, Composition::DEVICE},
+            {&hwc2LayerUnknown, Composition::SOLID_COLOR},
     });
 }
 
@@ -788,15 +791,18 @@
             .dataspace = hal::Dataspace::STANDARD_BT470M,
     };
 
+    static constexpr float kWhitePointNits = 800.f;
+
     mock::RenderSurface* renderSurface = new StrictMock<mock::RenderSurface>();
     mDisplay->setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(renderSurface));
 
     EXPECT_CALL(*renderSurface, setBufferPixelFormat(clientTargetProperty.pixelFormat));
     EXPECT_CALL(*renderSurface, setBufferDataspace(clientTargetProperty.dataspace));
-    mDisplay->applyClientTargetRequests(clientTargetProperty);
+    mDisplay->applyClientTargetRequests(clientTargetProperty, kWhitePointNits);
 
     auto& state = mDisplay->getState();
     EXPECT_EQ(clientTargetProperty.dataspace, state.dataspace);
+    EXPECT_EQ(kWhitePointNits, state.clientTargetWhitePointNits);
 }
 
 /*
diff --git a/services/surfaceflinger/CompositionEngine/tests/MockHWC2.h b/services/surfaceflinger/CompositionEngine/tests/MockHWC2.h
index 9518659..ff68053 100644
--- a/services/surfaceflinger/CompositionEngine/tests/MockHWC2.h
+++ b/services/surfaceflinger/CompositionEngine/tests/MockHWC2.h
@@ -32,6 +32,8 @@
 #include <ui/GraphicTypes.h>
 #include "DisplayHardware/HWC2.h"
 
+#include <aidl/android/hardware/graphics/composer3/Composition.h>
+
 // TODO(b/129481165): remove the #pragma below and fix conversion issues
 #pragma clang diagnostic pop // ignored "-Wconversion -Wextra"
 
@@ -57,7 +59,8 @@
     MOCK_METHOD1(setSurfaceDamage, Error(const android::Region&));
     MOCK_METHOD1(setBlendMode, Error(hal::BlendMode));
     MOCK_METHOD1(setColor, Error(hal::Color));
-    MOCK_METHOD1(setCompositionType, Error(hal::Composition));
+    MOCK_METHOD1(setCompositionType,
+                 Error(aidl::android::hardware::graphics::composer3::Composition));
     MOCK_METHOD1(setDataspace, Error(android::ui::Dataspace));
     MOCK_METHOD2(setPerFrameMetadata, Error(const int32_t, const android::HdrMetadata&));
     MOCK_METHOD1(setDisplayFrame, Error(const android::Rect&));
@@ -71,6 +74,7 @@
     MOCK_METHOD1(setColorTransform, Error(const android::mat4&));
     MOCK_METHOD3(setLayerGenericMetadata,
                  Error(const std::string&, bool, const std::vector<uint8_t>&));
+    MOCK_METHOD1(setWhitePointNits, Error(float));
 };
 
 } // namespace mock
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
index 31b131a..ad7976f 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
@@ -30,6 +30,10 @@
 #include "MockHWComposer.h"
 #include "RegionMatcher.h"
 
+#include <aidl/android/hardware/graphics/composer3/Composition.h>
+
+using aidl::android::hardware::graphics::composer3::Composition;
+
 namespace android::compositionengine {
 namespace {
 
@@ -652,6 +656,22 @@
     EXPECT_EQ(ui::Dataspace::V0_SCRGB, mOutputLayer.getState().dataspace);
 }
 
+TEST_F(OutputLayerUpdateCompositionStateTest, setsWhitePointNitsCorrectly) {
+    mOutputState.sdrWhitePointNits = 200.f;
+    mOutputState.displayBrightnessNits = 800.f;
+
+    mLayerFEState.dataspace = ui::Dataspace::DISPLAY_P3;
+    mLayerFEState.isColorspaceAgnostic = false;
+    mOutputLayer.updateCompositionState(false, false, ui::Transform::RotationFlags::ROT_0);
+    EXPECT_EQ(mOutputState.sdrWhitePointNits, mOutputLayer.getState().whitePointNits);
+
+    mLayerFEState.dataspace = ui::Dataspace::BT2020_ITU_PQ;
+    mLayerFEState.isColorspaceAgnostic = false;
+    mOutputLayer.updateCompositionState(false, false, ui::Transform::RotationFlags::ROT_0);
+
+    EXPECT_EQ(mOutputState.displayBrightnessNits, mOutputLayer.getState().whitePointNits);
+}
+
 TEST_F(OutputLayerUpdateCompositionStateTest, doesNotRecomputeGeometryIfNotRequested) {
     mOutputLayer.editState().forceClientComposition = false;
 
@@ -728,6 +748,8 @@
     static constexpr int kOverrideHwcSlot = impl::HwcBufferCache::FLATTENER_CACHING_SLOT;
     static constexpr bool kLayerGenericMetadata1Mandatory = true;
     static constexpr bool kLayerGenericMetadata2Mandatory = true;
+    static constexpr float kWhitePointNits = 200.f;
+    static constexpr float kDisplayBrightnessNits = 400.f;
 
     static const half4 kColor;
     static const Rect kDisplayFrame;
@@ -758,6 +780,7 @@
         outputLayerState.bufferTransform = static_cast<Hwc2::Transform>(kBufferTransform);
         outputLayerState.outputSpaceVisibleRegion = kOutputSpaceVisibleRegion;
         outputLayerState.dataspace = kDataspace;
+        outputLayerState.whitePointNits = kWhitePointNits;
 
         mLayerFEState.blendMode = kBlendMode;
         mLayerFEState.alpha = kAlpha;
@@ -770,6 +793,8 @@
         mLayerFEState.bufferSlot = BufferQueue::INVALID_BUFFER_SLOT;
         mLayerFEState.acquireFence = kFence;
 
+        mOutputState.displayBrightnessNits = kDisplayBrightnessNits;
+
         EXPECT_CALL(mOutput, getDisplayColorProfile())
                 .WillRepeatedly(Return(&mDisplayColorProfile));
         EXPECT_CALL(mDisplayColorProfile, getSupportedPerFrameMetadata())
@@ -818,9 +843,11 @@
     void expectPerFrameCommonCalls(SimulateUnsupported unsupported = SimulateUnsupported::None,
                                    ui::Dataspace dataspace = kDataspace,
                                    const Region& visibleRegion = kOutputSpaceVisibleRegion,
-                                   const Region& surfaceDamage = kSurfaceDamage) {
+                                   const Region& surfaceDamage = kSurfaceDamage,
+                                   float whitePointNits = kWhitePointNits) {
         EXPECT_CALL(*mHwcLayer, setVisibleRegion(RegionEq(visibleRegion))).WillOnce(Return(kError));
         EXPECT_CALL(*mHwcLayer, setDataspace(dataspace)).WillOnce(Return(kError));
+        EXPECT_CALL(*mHwcLayer, setWhitePointNits(whitePointNits)).WillOnce(Return(kError));
         EXPECT_CALL(*mHwcLayer, setColorTransform(kColorTransform))
                 .WillOnce(Return(unsupported == SimulateUnsupported::ColorTransform
                                          ? hal::Error::UNSUPPORTED
@@ -828,7 +855,7 @@
         EXPECT_CALL(*mHwcLayer, setSurfaceDamage(RegionEq(surfaceDamage))).WillOnce(Return(kError));
     }
 
-    void expectSetCompositionTypeCall(Hwc2::IComposerClient::Composition compositionType) {
+    void expectSetCompositionTypeCall(Composition compositionType) {
         EXPECT_CALL(*mHwcLayer, setCompositionType(compositionType)).WillOnce(Return(kError));
     }
 
@@ -952,7 +979,7 @@
 }
 
 TEST_F(OutputLayerWriteStateToHWCTest, canSetPerFrameStateForSolidColor) {
-    mLayerFEState.compositionType = Hwc2::IComposerClient::Composition::SOLID_COLOR;
+    mLayerFEState.compositionType = Composition::SOLID_COLOR;
 
     expectPerFrameCommonCalls();
     EXPECT_CALL(*mLayerFE, hasRoundedCorners()).WillOnce(Return(false));
@@ -961,7 +988,7 @@
     // check this in this test only by setting up an testing::InSeqeuence
     // instance before setting up the two expectations.
     InSequence s;
-    expectSetCompositionTypeCall(Hwc2::IComposerClient::Composition::SOLID_COLOR);
+    expectSetCompositionTypeCall(Composition::SOLID_COLOR);
     expectSetColorCall();
 
     mOutputLayer.writeStateToHWC(/*includeGeometry*/ false, /*skipLayer*/ false, 0,
@@ -969,11 +996,11 @@
 }
 
 TEST_F(OutputLayerWriteStateToHWCTest, canSetPerFrameStateForSideband) {
-    mLayerFEState.compositionType = Hwc2::IComposerClient::Composition::SIDEBAND;
+    mLayerFEState.compositionType = Composition::SIDEBAND;
 
     expectPerFrameCommonCalls();
     expectSetSidebandHandleCall();
-    expectSetCompositionTypeCall(Hwc2::IComposerClient::Composition::SIDEBAND);
+    expectSetCompositionTypeCall(Composition::SIDEBAND);
 
     EXPECT_CALL(*mLayerFE, hasRoundedCorners()).WillOnce(Return(false));
 
@@ -982,11 +1009,11 @@
 }
 
 TEST_F(OutputLayerWriteStateToHWCTest, canSetPerFrameStateForCursor) {
-    mLayerFEState.compositionType = Hwc2::IComposerClient::Composition::CURSOR;
+    mLayerFEState.compositionType = Composition::CURSOR;
 
     expectPerFrameCommonCalls();
     expectSetHdrMetadataAndBufferCalls();
-    expectSetCompositionTypeCall(Hwc2::IComposerClient::Composition::CURSOR);
+    expectSetCompositionTypeCall(Composition::CURSOR);
 
     EXPECT_CALL(*mLayerFE, hasRoundedCorners()).WillOnce(Return(false));
 
@@ -995,11 +1022,11 @@
 }
 
 TEST_F(OutputLayerWriteStateToHWCTest, canSetPerFrameStateForDevice) {
-    mLayerFEState.compositionType = Hwc2::IComposerClient::Composition::DEVICE;
+    mLayerFEState.compositionType = Composition::DEVICE;
 
     expectPerFrameCommonCalls();
     expectSetHdrMetadataAndBufferCalls();
-    expectSetCompositionTypeCall(Hwc2::IComposerClient::Composition::DEVICE);
+    expectSetCompositionTypeCall(Composition::DEVICE);
 
     EXPECT_CALL(*mLayerFE, hasRoundedCorners()).WillOnce(Return(false));
 
@@ -1008,10 +1035,9 @@
 }
 
 TEST_F(OutputLayerWriteStateToHWCTest, compositionTypeIsNotSetIfUnchanged) {
-    (*mOutputLayer.editState().hwc).hwcCompositionType =
-            Hwc2::IComposerClient::Composition::SOLID_COLOR;
+    (*mOutputLayer.editState().hwc).hwcCompositionType = Composition::SOLID_COLOR;
 
-    mLayerFEState.compositionType = Hwc2::IComposerClient::Composition::SOLID_COLOR;
+    mLayerFEState.compositionType = Composition::SOLID_COLOR;
 
     expectPerFrameCommonCalls();
     expectSetColorCall();
@@ -1024,11 +1050,11 @@
 }
 
 TEST_F(OutputLayerWriteStateToHWCTest, compositionTypeIsSetToClientIfColorTransformNotSupported) {
-    mLayerFEState.compositionType = Hwc2::IComposerClient::Composition::SOLID_COLOR;
+    mLayerFEState.compositionType = Composition::SOLID_COLOR;
 
     expectPerFrameCommonCalls(SimulateUnsupported::ColorTransform);
     expectSetColorCall();
-    expectSetCompositionTypeCall(Hwc2::IComposerClient::Composition::CLIENT);
+    expectSetCompositionTypeCall(Composition::CLIENT);
 
     mOutputLayer.writeStateToHWC(/*includeGeometry*/ false, /*skipLayer*/ false, 0,
                                  /*zIsOverridden*/ false, /*isPeekingThrough*/ false);
@@ -1037,25 +1063,25 @@
 TEST_F(OutputLayerWriteStateToHWCTest, compositionTypeIsSetToClientIfClientCompositionForced) {
     mOutputLayer.editState().forceClientComposition = true;
 
-    mLayerFEState.compositionType = Hwc2::IComposerClient::Composition::SOLID_COLOR;
+    mLayerFEState.compositionType = Composition::SOLID_COLOR;
 
     expectPerFrameCommonCalls();
     expectSetColorCall();
-    expectSetCompositionTypeCall(Hwc2::IComposerClient::Composition::CLIENT);
+    expectSetCompositionTypeCall(Composition::CLIENT);
 
     mOutputLayer.writeStateToHWC(/*includeGeometry*/ false, /*skipLayer*/ false, 0,
                                  /*zIsOverridden*/ false, /*isPeekingThrough*/ false);
 }
 
 TEST_F(OutputLayerWriteStateToHWCTest, allStateIncludesMetadataIfPresent) {
-    mLayerFEState.compositionType = Hwc2::IComposerClient::Composition::DEVICE;
+    mLayerFEState.compositionType = Composition::DEVICE;
     includeGenericLayerMetadataInState();
 
     expectGeometryCommonCalls();
     expectPerFrameCommonCalls();
     expectSetHdrMetadataAndBufferCalls();
     expectGenericLayerMetadataCalls();
-    expectSetCompositionTypeCall(Hwc2::IComposerClient::Composition::DEVICE);
+    expectSetCompositionTypeCall(Composition::DEVICE);
 
     EXPECT_CALL(*mLayerFE, hasRoundedCorners()).WillOnce(Return(false));
 
@@ -1064,12 +1090,12 @@
 }
 
 TEST_F(OutputLayerWriteStateToHWCTest, perFrameStateDoesNotIncludeMetadataIfPresent) {
-    mLayerFEState.compositionType = Hwc2::IComposerClient::Composition::DEVICE;
+    mLayerFEState.compositionType = Composition::DEVICE;
     includeGenericLayerMetadataInState();
 
     expectPerFrameCommonCalls();
     expectSetHdrMetadataAndBufferCalls();
-    expectSetCompositionTypeCall(Hwc2::IComposerClient::Composition::DEVICE);
+    expectSetCompositionTypeCall(Composition::DEVICE);
 
     EXPECT_CALL(*mLayerFE, hasRoundedCorners()).WillOnce(Return(false));
 
@@ -1078,15 +1104,31 @@
 }
 
 TEST_F(OutputLayerWriteStateToHWCTest, overriddenSkipLayerDoesNotSendBuffer) {
-    mLayerFEState.compositionType = Hwc2::IComposerClient::Composition::DEVICE;
+    mLayerFEState.compositionType = Composition::DEVICE;
     includeOverrideInfo();
 
     expectGeometryCommonCalls(kOverrideDisplayFrame, kOverrideSourceCrop, kOverrideBufferTransform,
                               kOverrideBlendMode, kSkipAlpha);
     expectPerFrameCommonCalls(SimulateUnsupported::None, kOverrideDataspace, kOverrideVisibleRegion,
-                              kOverrideSurfaceDamage);
+                              kOverrideSurfaceDamage, kDisplayBrightnessNits);
     expectSetHdrMetadataAndBufferCalls();
-    expectSetCompositionTypeCall(Hwc2::IComposerClient::Composition::DEVICE);
+    expectSetCompositionTypeCall(Composition::DEVICE);
+    EXPECT_CALL(*mLayerFE, hasRoundedCorners()).WillRepeatedly(Return(false));
+
+    mOutputLayer.writeStateToHWC(/*includeGeometry*/ true, /*skipLayer*/ true, 0,
+                                 /*zIsOverridden*/ false, /*isPeekingThrough*/ false);
+}
+
+TEST_F(OutputLayerWriteStateToHWCTest, overriddenSkipLayerForSolidColorDoesNotSendBuffer) {
+    mLayerFEState.compositionType = Composition::SOLID_COLOR;
+    includeOverrideInfo();
+
+    expectGeometryCommonCalls(kOverrideDisplayFrame, kOverrideSourceCrop, kOverrideBufferTransform,
+                              kOverrideBlendMode, kSkipAlpha);
+    expectPerFrameCommonCalls(SimulateUnsupported::None, kOverrideDataspace, kOverrideVisibleRegion,
+                              kOverrideSurfaceDamage, kDisplayBrightnessNits);
+    expectSetHdrMetadataAndBufferCalls();
+    expectSetCompositionTypeCall(Composition::DEVICE);
     EXPECT_CALL(*mLayerFE, hasRoundedCorners()).WillRepeatedly(Return(false));
 
     mOutputLayer.writeStateToHWC(/*includeGeometry*/ true, /*skipLayer*/ true, 0,
@@ -1094,15 +1136,15 @@
 }
 
 TEST_F(OutputLayerWriteStateToHWCTest, includesOverrideInfoIfPresent) {
-    mLayerFEState.compositionType = Hwc2::IComposerClient::Composition::DEVICE;
+    mLayerFEState.compositionType = Composition::DEVICE;
     includeOverrideInfo();
 
     expectGeometryCommonCalls(kOverrideDisplayFrame, kOverrideSourceCrop, kOverrideBufferTransform,
                               kOverrideBlendMode, kOverrideAlpha);
     expectPerFrameCommonCalls(SimulateUnsupported::None, kOverrideDataspace, kOverrideVisibleRegion,
-                              kOverrideSurfaceDamage);
+                              kOverrideSurfaceDamage, kDisplayBrightnessNits);
     expectSetHdrMetadataAndBufferCalls(kOverrideHwcSlot, kOverrideBuffer, kOverrideFence);
-    expectSetCompositionTypeCall(Hwc2::IComposerClient::Composition::DEVICE);
+    expectSetCompositionTypeCall(Composition::DEVICE);
     EXPECT_CALL(*mLayerFE, hasRoundedCorners()).WillRepeatedly(Return(false));
 
     mOutputLayer.writeStateToHWC(/*includeGeometry*/ true, /*skipLayer*/ false, 0,
@@ -1110,15 +1152,15 @@
 }
 
 TEST_F(OutputLayerWriteStateToHWCTest, includesOverrideInfoForSolidColorIfPresent) {
-    mLayerFEState.compositionType = Hwc2::IComposerClient::Composition::SOLID_COLOR;
+    mLayerFEState.compositionType = Composition::SOLID_COLOR;
     includeOverrideInfo();
 
     expectGeometryCommonCalls(kOverrideDisplayFrame, kOverrideSourceCrop, kOverrideBufferTransform,
                               kOverrideBlendMode, kOverrideAlpha);
     expectPerFrameCommonCalls(SimulateUnsupported::None, kOverrideDataspace, kOverrideVisibleRegion,
-                              kOverrideSurfaceDamage);
+                              kOverrideSurfaceDamage, kDisplayBrightnessNits);
     expectSetHdrMetadataAndBufferCalls(kOverrideHwcSlot, kOverrideBuffer, kOverrideFence);
-    expectSetCompositionTypeCall(Hwc2::IComposerClient::Composition::DEVICE);
+    expectSetCompositionTypeCall(Composition::DEVICE);
     EXPECT_CALL(*mLayerFE, hasRoundedCorners()).WillRepeatedly(Return(false));
 
     mOutputLayer.writeStateToHWC(/*includeGeometry*/ true, /*skipLayer*/ false, 0,
@@ -1126,14 +1168,14 @@
 }
 
 TEST_F(OutputLayerWriteStateToHWCTest, previousOverriddenLayerSendsSurfaceDamage) {
-    mLayerFEState.compositionType = Hwc2::IComposerClient::Composition::DEVICE;
+    mLayerFEState.compositionType = Composition::DEVICE;
     mOutputLayer.editState().hwc->stateOverridden = true;
 
     expectGeometryCommonCalls();
     expectPerFrameCommonCalls(SimulateUnsupported::None, kDataspace, kOutputSpaceVisibleRegion,
                               Region::INVALID_REGION);
     expectSetHdrMetadataAndBufferCalls();
-    expectSetCompositionTypeCall(Hwc2::IComposerClient::Composition::DEVICE);
+    expectSetCompositionTypeCall(Composition::DEVICE);
     EXPECT_CALL(*mLayerFE, hasRoundedCorners()).WillRepeatedly(Return(false));
 
     mOutputLayer.writeStateToHWC(/*includeGeometry*/ true, /*skipLayer*/ false, 0,
@@ -1141,16 +1183,16 @@
 }
 
 TEST_F(OutputLayerWriteStateToHWCTest, previousSkipLayerSendsUpdatedDeviceCompositionInfo) {
-    mLayerFEState.compositionType = Hwc2::IComposerClient::Composition::DEVICE;
+    mLayerFEState.compositionType = Composition::DEVICE;
     mOutputLayer.editState().hwc->stateOverridden = true;
     mOutputLayer.editState().hwc->layerSkipped = true;
-    mOutputLayer.editState().hwc->hwcCompositionType = Hwc2::IComposerClient::Composition::DEVICE;
+    mOutputLayer.editState().hwc->hwcCompositionType = Composition::DEVICE;
 
     expectGeometryCommonCalls();
     expectPerFrameCommonCalls(SimulateUnsupported::None, kDataspace, kOutputSpaceVisibleRegion,
                               Region::INVALID_REGION);
     expectSetHdrMetadataAndBufferCalls();
-    expectSetCompositionTypeCall(Hwc2::IComposerClient::Composition::DEVICE);
+    expectSetCompositionTypeCall(Composition::DEVICE);
     EXPECT_CALL(*mLayerFE, hasRoundedCorners()).WillOnce(Return(false));
 
     mOutputLayer.writeStateToHWC(/*includeGeometry*/ true, /*skipLayer*/ false, 0,
@@ -1158,17 +1200,17 @@
 }
 
 TEST_F(OutputLayerWriteStateToHWCTest, previousSkipLayerSendsUpdatedClientCompositionInfo) {
-    mLayerFEState.compositionType = Hwc2::IComposerClient::Composition::DEVICE;
+    mLayerFEState.compositionType = Composition::DEVICE;
     mOutputLayer.editState().forceClientComposition = true;
     mOutputLayer.editState().hwc->stateOverridden = true;
     mOutputLayer.editState().hwc->layerSkipped = true;
-    mOutputLayer.editState().hwc->hwcCompositionType = Hwc2::IComposerClient::Composition::CLIENT;
+    mOutputLayer.editState().hwc->hwcCompositionType = Composition::CLIENT;
 
     expectGeometryCommonCalls();
     expectPerFrameCommonCalls(SimulateUnsupported::None, kDataspace, kOutputSpaceVisibleRegion,
                               Region::INVALID_REGION);
     expectSetHdrMetadataAndBufferCalls();
-    expectSetCompositionTypeCall(Hwc2::IComposerClient::Composition::CLIENT);
+    expectSetCompositionTypeCall(Composition::CLIENT);
     EXPECT_CALL(*mLayerFE, hasRoundedCorners()).WillRepeatedly(Return(false));
 
     mOutputLayer.writeStateToHWC(/*includeGeometry*/ true, /*skipLayer*/ false, 0,
@@ -1214,7 +1256,7 @@
     expectGeometryCommonCalls();
     expectPerFrameCommonCalls();
     EXPECT_CALL(*mLayerFE, hasRoundedCorners()).WillOnce(Return(true));
-    expectSetCompositionTypeCall(Hwc2::IComposerClient::Composition::CLIENT);
+    expectSetCompositionTypeCall(Composition::CLIENT);
 
     mOutputLayer.writeStateToHWC(/*includeGeometry*/ true, /*skipLayer*/ false, 0,
                                  /*zIsOverridden*/ false, /*isPeekingThrough*/
@@ -1226,14 +1268,13 @@
     expectPerFrameCommonCalls();
     expectSetHdrMetadataAndBufferCalls();
     EXPECT_CALL(*mLayerFE, hasRoundedCorners()).WillRepeatedly(Return(true));
-    expectSetCompositionTypeCall(Hwc2::IComposerClient::Composition::DEVICE);
+    expectSetCompositionTypeCall(Composition::DEVICE);
 
-    mLayerFEState.compositionType = Hwc2::IComposerClient::Composition::DEVICE;
+    mLayerFEState.compositionType = Composition::DEVICE;
     mOutputLayer.writeStateToHWC(/*includeGeometry*/ true, /*skipLayer*/ false, 0,
                                  /*zIsOverridden*/ false, /*isPeekingThrough*/
                                  true);
-    EXPECT_EQ(Hwc2::IComposerClient::Composition::DEVICE,
-              mOutputLayer.getState().hwc->hwcCompositionType);
+    EXPECT_EQ(Composition::DEVICE, mOutputLayer.getState().hwc->hwcCompositionType);
 }
 
 /*
@@ -1332,14 +1373,14 @@
 
 TEST_F(OutputLayerTest, requiresClientCompositionReturnsTrueIfSetToClientComposition) {
     mOutputLayer.editState().hwc = impl::OutputLayerCompositionState::Hwc{nullptr};
-    mOutputLayer.editState().hwc->hwcCompositionType = Hwc2::IComposerClient::Composition::CLIENT;
+    mOutputLayer.editState().hwc->hwcCompositionType = Composition::CLIENT;
 
     EXPECT_TRUE(mOutputLayer.requiresClientComposition());
 }
 
 TEST_F(OutputLayerTest, requiresClientCompositionReturnsFalseIfSetToDeviceComposition) {
     mOutputLayer.editState().hwc = impl::OutputLayerCompositionState::Hwc{nullptr};
-    mOutputLayer.editState().hwc->hwcCompositionType = Hwc2::IComposerClient::Composition::DEVICE;
+    mOutputLayer.editState().hwc->hwcCompositionType = Composition::DEVICE;
 
     EXPECT_FALSE(mOutputLayer.requiresClientComposition());
 }
@@ -1356,14 +1397,14 @@
 
 TEST_F(OutputLayerTest, isHardwareCursorReturnsTrueIfSetToCursorComposition) {
     mOutputLayer.editState().hwc = impl::OutputLayerCompositionState::Hwc{nullptr};
-    mOutputLayer.editState().hwc->hwcCompositionType = Hwc2::IComposerClient::Composition::CURSOR;
+    mOutputLayer.editState().hwc->hwcCompositionType = Composition::CURSOR;
 
     EXPECT_TRUE(mOutputLayer.isHardwareCursor());
 }
 
 TEST_F(OutputLayerTest, isHardwareCursorReturnsFalseIfSetToDeviceComposition) {
     mOutputLayer.editState().hwc = impl::OutputLayerCompositionState::Hwc{nullptr};
-    mOutputLayer.editState().hwc->hwcCompositionType = Hwc2::IComposerClient::Composition::DEVICE;
+    mOutputLayer.editState().hwc->hwcCompositionType = Composition::DEVICE;
 
     EXPECT_FALSE(mOutputLayer.isHardwareCursor());
 }
@@ -1374,13 +1415,12 @@
 
 TEST_F(OutputLayerTest, applyDeviceCompositionTypeChangeSetsNewType) {
     mOutputLayer.editState().hwc = impl::OutputLayerCompositionState::Hwc{nullptr};
-    mOutputLayer.editState().hwc->hwcCompositionType = Hwc2::IComposerClient::Composition::DEVICE;
+    mOutputLayer.editState().hwc->hwcCompositionType = Composition::DEVICE;
 
-    mOutputLayer.applyDeviceCompositionTypeChange(Hwc2::IComposerClient::Composition::CLIENT);
+    mOutputLayer.applyDeviceCompositionTypeChange(Composition::CLIENT);
 
     ASSERT_TRUE(mOutputLayer.getState().hwc);
-    EXPECT_EQ(Hwc2::IComposerClient::Composition::CLIENT,
-              mOutputLayer.getState().hwc->hwcCompositionType);
+    EXPECT_EQ(Composition::CLIENT, mOutputLayer.getState().hwc->hwcCompositionType);
 }
 
 /*
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
index cf63ef5..6d96260 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
@@ -3023,6 +3023,7 @@
         mOutput.mState.usesDeviceComposition = false;
         mOutput.mState.reusedClientComposition = false;
         mOutput.mState.flipClientTarget = false;
+        mOutput.mState.clientTargetWhitePointNits = kClientTargetLuminanceNits;
 
         EXPECT_CALL(mOutput, getCompositionEngine()).WillRepeatedly(ReturnRef(mCompositionEngine));
         EXPECT_CALL(mCompositionEngine, getRenderEngine()).WillRepeatedly(ReturnRef(mRenderEngine));
@@ -3057,6 +3058,7 @@
     static constexpr float kDefaultMaxLuminance = 0.9f;
     static constexpr float kDefaultAvgLuminance = 0.7f;
     static constexpr float kDefaultMinLuminance = 0.1f;
+    static constexpr float kClientTargetLuminanceNits = 200.f;
 
     static const Rect kDefaultOutputFrame;
     static const Rect kDefaultOutputViewport;
@@ -3424,7 +3426,8 @@
             .andIfSkipColorTransform(false)
             .thenExpectDisplaySettingsUsed({kDefaultOutputDestinationClip, kDefaultOutputViewport,
                                             kDefaultMaxLuminance, kDefaultOutputDataspace, mat4(),
-                                            kDefaultOutputOrientationFlags})
+                                            kDefaultOutputOrientationFlags,
+                                            kClientTargetLuminanceNits})
             .execute()
             .expectAFenceWasReturned();
 }
@@ -3435,7 +3438,8 @@
             .andIfSkipColorTransform(false)
             .thenExpectDisplaySettingsUsed({kDefaultOutputDestinationClip, kDefaultOutputViewport,
                                             kDefaultMaxLuminance, kDefaultOutputDataspace, mat4(),
-                                            kDefaultOutputOrientationFlags})
+                                            kDefaultOutputOrientationFlags,
+                                            kClientTargetLuminanceNits})
             .execute()
             .expectAFenceWasReturned();
 }
@@ -3444,10 +3448,10 @@
     verify().ifMixedCompositionIs(false)
             .andIfUsesHdr(true)
             .andIfSkipColorTransform(false)
-            .thenExpectDisplaySettingsUsed({kDefaultOutputDestinationClip, kDefaultOutputViewport,
-                                            kDefaultMaxLuminance, kDefaultOutputDataspace,
-                                            kDefaultColorTransformMat,
-                                            kDefaultOutputOrientationFlags})
+            .thenExpectDisplaySettingsUsed(
+                    {kDefaultOutputDestinationClip, kDefaultOutputViewport, kDefaultMaxLuminance,
+                     kDefaultOutputDataspace, kDefaultColorTransformMat,
+                     kDefaultOutputOrientationFlags, kClientTargetLuminanceNits})
             .execute()
             .expectAFenceWasReturned();
 }
@@ -3456,10 +3460,10 @@
     verify().ifMixedCompositionIs(false)
             .andIfUsesHdr(false)
             .andIfSkipColorTransform(false)
-            .thenExpectDisplaySettingsUsed({kDefaultOutputDestinationClip, kDefaultOutputViewport,
-                                            kDefaultMaxLuminance, kDefaultOutputDataspace,
-                                            kDefaultColorTransformMat,
-                                            kDefaultOutputOrientationFlags})
+            .thenExpectDisplaySettingsUsed(
+                    {kDefaultOutputDestinationClip, kDefaultOutputViewport, kDefaultMaxLuminance,
+                     kDefaultOutputDataspace, kDefaultColorTransformMat,
+                     kDefaultOutputOrientationFlags, kClientTargetLuminanceNits})
             .execute()
             .expectAFenceWasReturned();
 }
@@ -3471,7 +3475,8 @@
             .andIfSkipColorTransform(true)
             .thenExpectDisplaySettingsUsed({kDefaultOutputDestinationClip, kDefaultOutputViewport,
                                             kDefaultMaxLuminance, kDefaultOutputDataspace, mat4(),
-                                            kDefaultOutputOrientationFlags})
+                                            kDefaultOutputOrientationFlags,
+                                            kClientTargetLuminanceNits})
             .execute()
             .expectAFenceWasReturned();
 }
@@ -3729,6 +3734,8 @@
         mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
     }
 
+    static constexpr float kLayerWhitePointNits = 200.f;
+
     mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
     mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
     StrictMock<OutputPartialMock> mOutput;
@@ -3768,6 +3775,7 @@
 
     static constexpr ui::Rotation kDisplayOrientation = ui::ROTATION_0;
     static constexpr ui::Dataspace kDisplayDataspace = ui::Dataspace::UNKNOWN;
+    static constexpr float kLayerWhitePointNits = 200.f;
 
     static const Rect kDisplayFrame;
     static const Rect kDisplayViewport;
@@ -3930,14 +3938,15 @@
 
     compositionengine::LayerFE::ClientCompositionTargetSettings layer1TargetSettings{
             Region(kDisplayFrame),
-            false,      /* needs filtering */
-            false,      /* secure */
-            false,      /* supports protected content */
+            false, /* needs filtering */
+            false, /* secure */
+            false, /* supports protected content */
             kDisplayViewport,
             kDisplayDataspace,
             false /* realContentIsVisible */,
             true /* clearContent */,
             compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled,
+            kLayerWhitePointNits,
     };
     compositionengine::LayerFE::ClientCompositionTargetSettings layer2TargetSettings{
             Region(kDisplayFrame),
@@ -3949,6 +3958,7 @@
             true /* realContentIsVisible */,
             false /* clearContent */,
             compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled,
+            kLayerWhitePointNits,
     };
 
     LayerFE::LayerSettings mBlackoutSettings = mLayers[1].mLayerSettings;
@@ -3988,6 +3998,7 @@
             true /* realContentIsVisible */,
             false /* clearContent */,
             compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled,
+            kLayerWhitePointNits,
     };
     compositionengine::LayerFE::ClientCompositionTargetSettings layer1TargetSettings{
             Region(Rect(0, 0, 30, 30)),
@@ -3999,6 +4010,7 @@
             true /* realContentIsVisible */,
             false /* clearContent */,
             compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled,
+            kLayerWhitePointNits,
     };
     compositionengine::LayerFE::ClientCompositionTargetSettings layer2TargetSettings{
             Region(Rect(0, 0, 40, 201)),
@@ -4010,6 +4022,7 @@
             true /* realContentIsVisible */,
             false /* clearContent */,
             compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled,
+            kLayerWhitePointNits,
     };
 
     EXPECT_CALL(*mLayers[0].mLayerFE, prepareClientCompositionList(Eq(ByRef(layer0TargetSettings))))
@@ -4039,6 +4052,7 @@
             true /* realContentIsVisible */,
             false /* clearContent */,
             compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled,
+            kLayerWhitePointNits,
     };
     compositionengine::LayerFE::ClientCompositionTargetSettings layer1TargetSettings{
             Region(kDisplayFrame),
@@ -4050,6 +4064,7 @@
             true /* realContentIsVisible */,
             false /* clearContent */,
             compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled,
+            kLayerWhitePointNits,
     };
     compositionengine::LayerFE::ClientCompositionTargetSettings layer2TargetSettings{
             Region(kDisplayFrame),
@@ -4061,6 +4076,7 @@
             true /* realContentIsVisible */,
             false /* clearContent */,
             compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled,
+            kLayerWhitePointNits,
     };
 
     EXPECT_CALL(*mLayers[0].mLayerFE, prepareClientCompositionList(Eq(ByRef(layer0TargetSettings))))
@@ -4090,7 +4106,7 @@
             true /* realContentIsVisible */,
             false /* clearContent */,
             compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled,
-
+            kLayerWhitePointNits,
     };
     compositionengine::LayerFE::ClientCompositionTargetSettings layer1TargetSettings{
             Region(kDisplayFrame),
@@ -4102,6 +4118,7 @@
             true /* realContentIsVisible */,
             false /* clearContent */,
             compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled,
+            kLayerWhitePointNits,
     };
     compositionengine::LayerFE::ClientCompositionTargetSettings layer2TargetSettings{
             Region(kDisplayFrame),
@@ -4113,6 +4130,7 @@
             true /* realContentIsVisible */,
             false /* clearContent */,
             compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled,
+            kLayerWhitePointNits,
     };
 
     EXPECT_CALL(*mLayers[0].mLayerFE, prepareClientCompositionList(Eq(ByRef(layer0TargetSettings))))
@@ -4141,6 +4159,7 @@
             true /* realContentIsVisible */,
             false /* clearContent */,
             compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled,
+            kLayerWhitePointNits,
     };
     compositionengine::LayerFE::ClientCompositionTargetSettings layer1TargetSettings{
             Region(kDisplayFrame),
@@ -4152,6 +4171,7 @@
             true /* realContentIsVisible */,
             false /* clearContent */,
             compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled,
+            kLayerWhitePointNits,
     };
     compositionengine::LayerFE::ClientCompositionTargetSettings layer2TargetSettings{
             Region(kDisplayFrame),
@@ -4163,6 +4183,7 @@
             true /* realContentIsVisible */,
             false /* clearContent */,
             compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled,
+            kLayerWhitePointNits,
     };
 
     EXPECT_CALL(*mLayers[0].mLayerFE, prepareClientCompositionList(Eq(ByRef(layer0TargetSettings))))
@@ -4179,7 +4200,6 @@
 
 TEST_F(GenerateClientCompositionRequestsTest_ThreeLayers,
        protectedContentSupportUsedToGenerateRequests) {
-
     compositionengine::LayerFE::ClientCompositionTargetSettings layer0TargetSettings{
             Region(kDisplayFrame),
             false, /* needs filtering */
@@ -4190,6 +4210,7 @@
             true /* realContentIsVisible */,
             false /* clearContent */,
             compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled,
+            kLayerWhitePointNits,
     };
     compositionengine::LayerFE::ClientCompositionTargetSettings layer1TargetSettings{
             Region(kDisplayFrame),
@@ -4201,6 +4222,7 @@
             true /* realContentIsVisible */,
             false /* clearContent */,
             compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled,
+            kLayerWhitePointNits,
     };
     compositionengine::LayerFE::ClientCompositionTargetSettings layer2TargetSettings{
             Region(kDisplayFrame),
@@ -4212,6 +4234,7 @@
             true /* realContentIsVisible */,
             false /* clearContent */,
             compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled,
+            kLayerWhitePointNits,
     };
 
     EXPECT_CALL(*mLayers[0].mLayerFE, prepareClientCompositionList(Eq(ByRef(layer0TargetSettings))))
@@ -4379,6 +4402,7 @@
             true /* realContentIsVisible */,
             false /* clearContent */,
             compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled,
+            kLayerWhitePointNits,
     };
 
     EXPECT_CALL(leftLayer.mOutputLayer, requiresClientComposition()).WillRepeatedly(Return(true));
@@ -4396,6 +4420,7 @@
             true /* realContentIsVisible */,
             false /* clearContent */,
             compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled,
+            kLayerWhitePointNits,
     };
 
     EXPECT_CALL(rightLayer.mOutputLayer, requiresClientComposition()).WillRepeatedly(Return(true));
@@ -4428,6 +4453,7 @@
             false /* realContentIsVisible */,
             false /* clearContent */,
             compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled,
+            kLayerWhitePointNits,
     };
 
     LayerFE::LayerSettings mShadowSettings;
@@ -4472,6 +4498,7 @@
             true /* realContentIsVisible */,
             false /* clearContent */,
             compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled,
+            kLayerWhitePointNits,
     };
 
     EXPECT_CALL(mLayers[0].mOutputLayer, requiresClientComposition()).WillOnce(Return(false));
diff --git a/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp b/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp
index 42b3d97..d5a117a 100644
--- a/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp
@@ -55,13 +55,21 @@
 }
 
 MATCHER_P(ClientCompositionTargetSettingsSecureEq, expectedSecureSetting, "") {
-    *result_listener << "ClientCompositionTargetSettings' SecureSettings aren't equal \n";
+    *result_listener << "ClientCompositionTargetSettings' isSecure bits aren't equal \n";
     *result_listener << "expected " << expectedSecureSetting << "\n";
     *result_listener << "actual " << arg.isSecure << "\n";
 
     return expectedSecureSetting == arg.isSecure;
 }
 
+MATCHER_P(ClientCompositionTargetSettingsWhitePointEq, expectedWhitePoint, "") {
+    *result_listener << "ClientCompositionTargetSettings' white points aren't equal \n";
+    *result_listener << "expected " << expectedWhitePoint << "\n";
+    *result_listener << "actual " << arg.whitePointNits << "\n";
+
+    return expectedWhitePoint == arg.whitePointNits;
+}
+
 static const ui::Size kOutputSize = ui::Size(1, 1);
 
 class CachedSetTest : public testing::Test {
@@ -431,6 +439,54 @@
     cachedSet.append(CachedSet(layer3));
 }
 
+TEST_F(CachedSetTest, renderWhitePoint) {
+    // Skip the 0th layer to ensure that the bounding box of the layers is offset from (0, 0)
+    CachedSet::Layer& layer1 = *mTestLayers[1]->cachedSetLayer.get();
+    sp<mock::LayerFE> layerFE1 = mTestLayers[1]->layerFE;
+    CachedSet::Layer& layer2 = *mTestLayers[2]->cachedSetLayer.get();
+    sp<mock::LayerFE> layerFE2 = mTestLayers[2]->layerFE;
+
+    CachedSet cachedSet(layer1);
+    cachedSet.append(CachedSet(layer2));
+
+    std::vector<compositionengine::LayerFE::LayerSettings> clientCompList1;
+    clientCompList1.push_back({});
+
+    std::vector<compositionengine::LayerFE::LayerSettings> clientCompList2;
+    clientCompList2.push_back({});
+
+    mOutputState.displayBrightnessNits = 400.f;
+
+    const auto drawLayers =
+            [&](const renderengine::DisplaySettings& displaySettings,
+                const std::vector<renderengine::LayerSettings>&,
+                const std::shared_ptr<renderengine::ExternalTexture>&, const bool,
+                base::unique_fd&&) -> std::future<renderengine::RenderEngineResult> {
+        EXPECT_EQ(mOutputState.displayBrightnessNits, displaySettings.targetLuminanceNits);
+        return futureOf<renderengine::RenderEngineResult>({NO_ERROR, base::unique_fd()});
+    };
+
+    EXPECT_CALL(*layerFE1,
+                prepareClientCompositionList(ClientCompositionTargetSettingsWhitePointEq(
+                        mOutputState.displayBrightnessNits)))
+            .WillOnce(Return(clientCompList1));
+    EXPECT_CALL(*layerFE2,
+                prepareClientCompositionList(ClientCompositionTargetSettingsWhitePointEq(
+                        mOutputState.displayBrightnessNits)))
+            .WillOnce(Return(clientCompList2));
+    EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _)).WillOnce(Invoke(drawLayers));
+    mOutputState.isSecure = true;
+    cachedSet.render(mRenderEngine, mTexturePool, mOutputState);
+    expectReadyBuffer(cachedSet);
+
+    EXPECT_EQ(mOutputState.framebufferSpace, cachedSet.getOutputSpace());
+    EXPECT_EQ(Rect(kOutputSize.width, kOutputSize.height), cachedSet.getTextureBounds());
+
+    // Now check that appending a new cached set properly cleans up RenderEngine resources.
+    CachedSet::Layer& layer3 = *mTestLayers[2]->cachedSetLayer.get();
+    cachedSet.append(CachedSet(layer3));
+}
+
 TEST_F(CachedSetTest, rendersWithOffsetFramebufferContent) {
     // Skip the 0th layer to ensure that the bounding box of the layers is offset from (0, 0)
     CachedSet::Layer& layer1 = *mTestLayers[1]->cachedSetLayer.get();
diff --git a/services/surfaceflinger/CompositionEngine/tests/planner/LayerStateTest.cpp b/services/surfaceflinger/CompositionEngine/tests/planner/LayerStateTest.cpp
index 9ad3ab4..84b3fc5 100644
--- a/services/surfaceflinger/CompositionEngine/tests/planner/LayerStateTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/planner/LayerStateTest.cpp
@@ -27,6 +27,10 @@
 #include "android/hardware_buffer.h"
 #include "compositionengine/LayerFECompositionState.h"
 
+#include <aidl/android/hardware/graphics/composer3/Composition.h>
+
+using aidl::android::hardware::graphics::composer3::Composition;
+
 namespace android::compositionengine::impl::planner {
 namespace {
 
@@ -277,33 +281,28 @@
 TEST_F(LayerStateTest, getCompositionType) {
     OutputLayerCompositionState outputLayerCompositionState;
     LayerFECompositionState layerFECompositionState;
-    layerFECompositionState.compositionType =
-            hardware::graphics::composer::hal::Composition::DEVICE;
+    layerFECompositionState.compositionType = Composition::DEVICE;
     setupMocksForLayer(mOutputLayer, mLayerFE, outputLayerCompositionState,
                        layerFECompositionState);
     mLayerState = std::make_unique<LayerState>(&mOutputLayer);
-    EXPECT_EQ(hardware::graphics::composer::hal::Composition::DEVICE,
-              mLayerState->getCompositionType());
+    EXPECT_EQ(Composition::DEVICE, mLayerState->getCompositionType());
 }
 
 TEST_F(LayerStateTest, getCompositionType_forcedClient) {
     OutputLayerCompositionState outputLayerCompositionState;
     outputLayerCompositionState.forceClientComposition = true;
     LayerFECompositionState layerFECompositionState;
-    layerFECompositionState.compositionType =
-            hardware::graphics::composer::hal::Composition::DEVICE;
+    layerFECompositionState.compositionType = Composition::DEVICE;
     setupMocksForLayer(mOutputLayer, mLayerFE, outputLayerCompositionState,
                        layerFECompositionState);
     mLayerState = std::make_unique<LayerState>(&mOutputLayer);
-    EXPECT_EQ(hardware::graphics::composer::hal::Composition::CLIENT,
-              mLayerState->getCompositionType());
+    EXPECT_EQ(Composition::CLIENT, mLayerState->getCompositionType());
 }
 
 TEST_F(LayerStateTest, updateCompositionType) {
     OutputLayerCompositionState outputLayerCompositionState;
     LayerFECompositionState layerFECompositionState;
-    layerFECompositionState.compositionType =
-            hardware::graphics::composer::hal::Composition::DEVICE;
+    layerFECompositionState.compositionType = Composition::DEVICE;
     setupMocksForLayer(mOutputLayer, mLayerFE, outputLayerCompositionState,
                        layerFECompositionState);
     mLayerState = std::make_unique<LayerState>(&mOutputLayer);
@@ -311,29 +310,25 @@
     mock::OutputLayer newOutputLayer;
     mock::LayerFE newLayerFE;
     LayerFECompositionState layerFECompositionStateTwo;
-    layerFECompositionStateTwo.compositionType =
-            hardware::graphics::composer::hal::Composition::SOLID_COLOR;
+    layerFECompositionStateTwo.compositionType = Composition::SOLID_COLOR;
     setupMocksForLayer(newOutputLayer, newLayerFE, outputLayerCompositionState,
                        layerFECompositionStateTwo);
     Flags<LayerStateField> updates = mLayerState->update(&newOutputLayer);
-    EXPECT_EQ(hardware::graphics::composer::hal::Composition::SOLID_COLOR,
-              mLayerState->getCompositionType());
+    EXPECT_EQ(Composition::SOLID_COLOR, mLayerState->getCompositionType());
     EXPECT_EQ(Flags<LayerStateField>(LayerStateField::CompositionType), updates);
 }
 
 TEST_F(LayerStateTest, compareCompositionType) {
     OutputLayerCompositionState outputLayerCompositionState;
     LayerFECompositionState layerFECompositionState;
-    layerFECompositionState.compositionType =
-            hardware::graphics::composer::hal::Composition::DEVICE;
+    layerFECompositionState.compositionType = Composition::DEVICE;
     setupMocksForLayer(mOutputLayer, mLayerFE, outputLayerCompositionState,
                        layerFECompositionState);
     mLayerState = std::make_unique<LayerState>(&mOutputLayer);
     mock::OutputLayer newOutputLayer;
     mock::LayerFE newLayerFE;
     LayerFECompositionState layerFECompositionStateTwo;
-    layerFECompositionStateTwo.compositionType =
-            hardware::graphics::composer::hal::Composition::SOLID_COLOR;
+    layerFECompositionStateTwo.compositionType = Composition::SOLID_COLOR;
     setupMocksForLayer(newOutputLayer, newLayerFE, outputLayerCompositionState,
                        layerFECompositionStateTwo);
     auto otherLayerState = std::make_unique<LayerState>(&newOutputLayer);
diff --git a/services/surfaceflinger/CompositionEngine/tests/planner/PredictorTest.cpp b/services/surfaceflinger/CompositionEngine/tests/planner/PredictorTest.cpp
index 1492707..6038268 100644
--- a/services/surfaceflinger/CompositionEngine/tests/planner/PredictorTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/planner/PredictorTest.cpp
@@ -24,6 +24,10 @@
 #include <gtest/gtest.h>
 #include <log/log.h>
 
+#include <aidl/android/hardware/graphics/composer3/Composition.h>
+
+using aidl::android::hardware::graphics::composer3::Composition;
+
 namespace android::compositionengine::impl::planner {
 namespace {
 
@@ -103,7 +107,7 @@
     mock::LayerFE layerFEOne;
     OutputLayerCompositionState outputLayerCompositionStateOne;
     LayerFECompositionState layerFECompositionStateOne;
-    layerFECompositionStateOne.compositionType = hal::Composition::DEVICE;
+    layerFECompositionStateOne.compositionType = Composition::DEVICE;
     setupMocksForLayer(outputLayerOne, layerFEOne, outputLayerCompositionStateOne,
                        layerFECompositionStateOne);
     LayerState layerStateOne(&outputLayerOne);
@@ -112,7 +116,7 @@
     mock::LayerFE layerFETwo;
     OutputLayerCompositionState outputLayerCompositionStateTwo;
     LayerFECompositionState layerFECompositionStateTwo;
-    layerFECompositionStateTwo.compositionType = hal::Composition::SOLID_COLOR;
+    layerFECompositionStateTwo.compositionType = Composition::SOLID_COLOR;
     setupMocksForLayer(outputLayerTwo, layerFETwo, outputLayerCompositionStateTwo,
                        layerFECompositionStateTwo);
     LayerState layerStateTwo(&outputLayerTwo);
@@ -370,7 +374,7 @@
 
 TEST_F(PredictionTest, constructPrediction) {
     Plan plan;
-    plan.addLayerType(hal::Composition::DEVICE);
+    plan.addLayerType(Composition::DEVICE);
 
     Prediction prediction({}, plan);
 
@@ -442,13 +446,13 @@
     mock::LayerFE layerFEOne;
     OutputLayerCompositionState outputLayerCompositionStateOne;
     LayerFECompositionState layerFECompositionStateOne;
-    layerFECompositionStateOne.compositionType = hal::Composition::DEVICE;
+    layerFECompositionStateOne.compositionType = Composition::DEVICE;
     setupMocksForLayer(outputLayerOne, layerFEOne, outputLayerCompositionStateOne,
                        layerFECompositionStateOne);
     LayerState layerStateOne(&outputLayerOne);
 
     Plan plan;
-    plan.addLayerType(hal::Composition::DEVICE);
+    plan.addLayerType(Composition::DEVICE);
 
     Predictor predictor;
 
@@ -484,7 +488,7 @@
     LayerState layerStateTwo(&outputLayerTwo);
 
     Plan plan;
-    plan.addLayerType(hal::Composition::DEVICE);
+    plan.addLayerType(Composition::DEVICE);
 
     Predictor predictor;
 
@@ -521,7 +525,7 @@
     LayerState layerStateTwo(&outputLayerTwo);
 
     Plan plan;
-    plan.addLayerType(hal::Composition::DEVICE);
+    plan.addLayerType(Composition::DEVICE);
 
     Predictor predictor;
 
@@ -535,7 +539,7 @@
     EXPECT_EQ(Prediction::Type::Approximate, predictedPlan->type);
 
     Plan planTwo;
-    planTwo.addLayerType(hal::Composition::CLIENT);
+    planTwo.addLayerType(Composition::CLIENT);
     predictor.recordResult(predictedPlan, hashTwo, {&layerStateTwo}, false, planTwo);
     // Now trying to retrieve the predicted plan again returns a nullopt instead.
     // TODO(b/158790260): Even though this is enforced in this test, we might want to reassess this.
diff --git a/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp b/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp
index 200bb65..8763579 100644
--- a/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp
@@ -375,13 +375,11 @@
 
 Error AidlComposer::getChangedCompositionTypes(
         Display display, std::vector<Layer>* outLayers,
-        std::vector<IComposerClient::Composition>* outTypes) {
+        std::vector<aidl::android::hardware::graphics::composer3::Composition>* outTypes) {
     std::vector<int64_t> layers;
-    std::vector<Composition> types;
-    mReader.takeChangedCompositionTypes(translate<int64_t>(display), &layers, &types);
+    mReader.takeChangedCompositionTypes(translate<int64_t>(display), &layers, outTypes);
 
     *outLayers = translate<Layer>(layers);
-    *outTypes = translate<IComposerClient::Composition>(types);
     return Error::NONE;
 }
 
@@ -649,10 +647,10 @@
     return Error::NONE;
 }
 
-Error AidlComposer::setLayerCompositionType(Display display, Layer layer,
-                                            IComposerClient::Composition type) {
-    mWriter.setLayerCompositionType(translate<int64_t>(display), translate<int64_t>(layer),
-                                    translate<Composition>(type));
+Error AidlComposer::setLayerCompositionType(
+        Display display, Layer layer,
+        aidl::android::hardware::graphics::composer3::Composition type) {
+    mWriter.setLayerCompositionType(translate<int64_t>(display), translate<int64_t>(layer), type);
     return Error::NONE;
 }
 
@@ -1005,12 +1003,19 @@
 }
 
 Error AidlComposer::getClientTargetProperty(
-        Display display, IComposerClient::ClientTargetProperty* outClientTargetProperty) {
+        Display display, IComposerClient::ClientTargetProperty* outClientTargetProperty,
+        float* whitePointNits) {
     ClientTargetProperty property;
-    mReader.takeClientTargetProperty(translate<int64_t>(display), &property);
+    mReader.takeClientTargetProperty(translate<int64_t>(display), &property, whitePointNits);
     *outClientTargetProperty = translate<IComposerClient::ClientTargetProperty>(property);
     return Error::NONE;
 }
 
+Error AidlComposer::setLayerWhitePointNits(Display display, Layer layer, float whitePointNits) {
+    mWriter.setLayerWhitePointNits(translate<int64_t>(display), translate<int64_t>(layer),
+                                   whitePointNits);
+    return Error::NONE;
+}
+
 } // namespace Hwc2
 } // namespace android
diff --git a/services/surfaceflinger/DisplayHardware/AidlComposerHal.h b/services/surfaceflinger/DisplayHardware/AidlComposerHal.h
index 418a8cc..d82d815 100644
--- a/services/surfaceflinger/DisplayHardware/AidlComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/AidlComposerHal.h
@@ -36,6 +36,8 @@
 #include <aidl/android/hardware/graphics/composer3/IComposerClient.h>
 #include <android/hardware/graphics/composer3/command-buffer.h>
 
+#include <aidl/android/hardware/graphics/composer3/Composition.h>
+
 // TODO(b/129481165): remove the #pragma below and fix conversion issues
 #pragma clang diagnostic pop // ignored "-Wconversion -Wextra"
 
@@ -78,8 +80,10 @@
     Error destroyLayer(Display display, Layer layer) override;
 
     Error getActiveConfig(Display display, Config* outConfig) override;
-    Error getChangedCompositionTypes(Display display, std::vector<Layer>* outLayers,
-                                     std::vector<IComposerClient::Composition>* outTypes) override;
+    Error getChangedCompositionTypes(
+            Display display, std::vector<Layer>* outLayers,
+            std::vector<aidl::android::hardware::graphics::composer3::Composition>* outTypes)
+            override;
     Error getColorModes(Display display, std::vector<ColorMode>* outModes) override;
     Error getDisplayAttribute(Display display, Config config, IComposerClient::Attribute attribute,
                               int32_t* outValue) override;
@@ -132,8 +136,9 @@
                                 const std::vector<IComposerClient::Rect>& damage) override;
     Error setLayerBlendMode(Display display, Layer layer, IComposerClient::BlendMode mode) override;
     Error setLayerColor(Display display, Layer layer, const IComposerClient::Color& color) override;
-    Error setLayerCompositionType(Display display, Layer layer,
-                                  IComposerClient::Composition type) override;
+    Error setLayerCompositionType(
+            Display display, Layer layer,
+            aidl::android::hardware::graphics::composer3::Composition type) override;
     Error setLayerDataspace(Display display, Layer layer, Dataspace dataspace) override;
     Error setLayerDisplayFrame(Display display, Layer layer,
                                const IComposerClient::Rect& frame) override;
@@ -194,9 +199,10 @@
                                         bool mandatory, const std::vector<uint8_t>& value) override;
     V2_4::Error getLayerGenericMetadataKeys(
             std::vector<IComposerClient::LayerGenericMetadataKey>* outKeys) override;
-    Error getClientTargetProperty(
-            Display display,
-            IComposerClient::ClientTargetProperty* outClientTargetProperty) override;
+    Error getClientTargetProperty(Display display,
+                                  IComposerClient::ClientTargetProperty* outClientTargetProperty,
+                                  float* outClientTargetWhitePointNits) override;
+    Error setLayerWhitePointNits(Display display, Layer layer, float whitePointNits) override;
 
 private:
     // Many public functions above simply write a command into the command
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.h b/services/surfaceflinger/DisplayHardware/ComposerHal.h
index 3bbce7b..b4ba8ab 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.h
@@ -31,6 +31,8 @@
 #include <ui/GraphicBuffer.h>
 #include <utils/StrongPointer.h>
 
+#include <aidl/android/hardware/graphics/composer3/Composition.h>
+
 // TODO(b/129481165): remove the #pragma below and fix conversion issues
 #pragma clang diagnostic pop // ignored "-Wconversion -Wextra"
 
@@ -98,7 +100,7 @@
     virtual Error getActiveConfig(Display display, Config* outConfig) = 0;
     virtual Error getChangedCompositionTypes(
             Display display, std::vector<Layer>* outLayers,
-            std::vector<IComposerClient::Composition>* outTypes) = 0;
+            std::vector<aidl::android::hardware::graphics::composer3::Composition>* outTypes) = 0;
     virtual Error getColorModes(Display display, std::vector<ColorMode>* outModes) = 0;
     virtual Error getDisplayAttribute(Display display, Config config,
                                       IComposerClient::Attribute attribute, int32_t* outValue) = 0;
@@ -155,8 +157,9 @@
                                     IComposerClient::BlendMode mode) = 0;
     virtual Error setLayerColor(Display display, Layer layer,
                                 const IComposerClient::Color& color) = 0;
-    virtual Error setLayerCompositionType(Display display, Layer layer,
-                                          IComposerClient::Composition type) = 0;
+    virtual Error setLayerCompositionType(
+            Display display, Layer layer,
+            aidl::android::hardware::graphics::composer3::Composition type) = 0;
     virtual Error setLayerDataspace(Display display, Layer layer, Dataspace dataspace) = 0;
     virtual Error setLayerDisplayFrame(Display display, Layer layer,
                                        const IComposerClient::Rect& frame) = 0;
@@ -221,7 +224,11 @@
     virtual V2_4::Error getLayerGenericMetadataKeys(
             std::vector<IComposerClient::LayerGenericMetadataKey>* outKeys) = 0;
     virtual Error getClientTargetProperty(
-            Display display, IComposerClient::ClientTargetProperty* outClientTargetProperty) = 0;
+            Display display, IComposerClient::ClientTargetProperty* outClientTargetProperty,
+            float* outWhitePointNits) = 0;
+
+    // AIDL Composer
+    virtual Error setLayerWhitePointNits(Display display, Layer layer, float whitePointNits) = 0;
 };
 
 } // namespace android::Hwc2
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index e21b0da..82f463e 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -39,6 +39,8 @@
 
 #include "ComposerHal.h"
 
+using aidl::android::hardware::graphics::composer3::Composition;
+
 namespace android {
 
 using android::Fence;
@@ -147,7 +149,7 @@
 
 Error Display::getChangedCompositionTypes(std::unordered_map<HWC2::Layer*, Composition>* outTypes) {
     std::vector<Hwc2::Layer> layerIds;
-    std::vector<Hwc2::IComposerClient::Composition> types;
+    std::vector<Composition> types;
     auto intError = mComposer.getChangedCompositionTypes(
             mId, &layerIds, &types);
     uint32_t numElements = layerIds.size();
@@ -555,8 +557,10 @@
     return static_cast<Error>(intError);
 }
 
-Error Display::getClientTargetProperty(ClientTargetProperty* outClientTargetProperty) {
-    const auto error = mComposer.getClientTargetProperty(mId, outClientTargetProperty);
+Error Display::getClientTargetProperty(ClientTargetProperty* outClientTargetProperty,
+                                       float* outWhitePointNits) {
+    const auto error =
+            mComposer.getClientTargetProperty(mId, outClientTargetProperty, outWhitePointNits);
     return static_cast<Error>(error);
 }
 
@@ -919,6 +923,16 @@
     return static_cast<Error>(intError);
 }
 
+// AIDL HAL
+Error Layer::setWhitePointNits(float whitePointNits) {
+    if (CC_UNLIKELY(!mDisplay)) {
+        return Error::BAD_DISPLAY;
+    }
+
+    auto intError = mComposer.setLayerWhitePointNits(mDisplay->getId(), mId, whitePointNits);
+    return static_cast<Error>(intError);
+}
+
 } // namespace impl
 } // namespace HWC2
 } // namespace android
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h
index a65efb2..1425c61 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2.h
@@ -36,6 +36,8 @@
 
 #include "Hal.h"
 
+#include <aidl/android/hardware/graphics/composer3/Composition.h>
+
 namespace android {
 
 class Fence;
@@ -88,7 +90,8 @@
     [[clang::warn_unused_result]] virtual base::expected<std::shared_ptr<HWC2::Layer>, hal::Error>
     createLayer() = 0;
     [[clang::warn_unused_result]] virtual hal::Error getChangedCompositionTypes(
-            std::unordered_map<Layer*, hal::Composition>* outTypes) = 0;
+            std::unordered_map<Layer*, aidl::android::hardware::graphics::composer3::Composition>*
+                    outTypes) = 0;
     [[clang::warn_unused_result]] virtual hal::Error getColorModes(
             std::vector<hal::ColorMode>* outModes) const = 0;
     // Returns a bitmask which contains HdrMetadata::Type::*.
@@ -146,7 +149,7 @@
             std::vector<hal::ContentType>*) const = 0;
     [[clang::warn_unused_result]] virtual hal::Error setContentType(hal::ContentType) = 0;
     [[clang::warn_unused_result]] virtual hal::Error getClientTargetProperty(
-            hal::ClientTargetProperty* outClientTargetProperty) = 0;
+            hal::ClientTargetProperty* outClientTargetProperty, float* outWhitePointNits) = 0;
 };
 
 namespace impl {
@@ -163,7 +166,9 @@
     hal::Error acceptChanges() override;
     base::expected<std::shared_ptr<HWC2::Layer>, hal::Error> createLayer() override;
     hal::Error getChangedCompositionTypes(
-            std::unordered_map<HWC2::Layer*, hal::Composition>* outTypes) override;
+            std::unordered_map<HWC2::Layer*,
+                               aidl::android::hardware::graphics::composer3::Composition>* outTypes)
+            override;
     hal::Error getColorModes(std::vector<hal::ColorMode>* outModes) const override;
     // Returns a bitmask which contains HdrMetadata::Type::*.
     int32_t getSupportedPerFrameMetadata() const override;
@@ -209,7 +214,8 @@
     hal::Error getSupportedContentTypes(
             std::vector<hal::ContentType>* outSupportedContentTypes) const override;
     hal::Error setContentType(hal::ContentType) override;
-    hal::Error getClientTargetProperty(hal::ClientTargetProperty* outClientTargetProperty) override;
+    hal::Error getClientTargetProperty(hal::ClientTargetProperty* outClientTargetProperty,
+                                       float* outWhitePointNits) override;
 
     // Other Display methods
     hal::HWDisplayId getId() const override { return mId; }
@@ -265,7 +271,8 @@
 
     [[clang::warn_unused_result]] virtual hal::Error setBlendMode(hal::BlendMode mode) = 0;
     [[clang::warn_unused_result]] virtual hal::Error setColor(hal::Color color) = 0;
-    [[clang::warn_unused_result]] virtual hal::Error setCompositionType(hal::Composition type) = 0;
+    [[clang::warn_unused_result]] virtual hal::Error setCompositionType(
+            aidl::android::hardware::graphics::composer3::Composition type) = 0;
     [[clang::warn_unused_result]] virtual hal::Error setDataspace(hal::Dataspace dataspace) = 0;
     [[clang::warn_unused_result]] virtual hal::Error setPerFrameMetadata(
             const int32_t supportedPerFrameMetadata, const android::HdrMetadata& metadata) = 0;
@@ -288,6 +295,9 @@
     // Composer HAL 2.4
     [[clang::warn_unused_result]] virtual hal::Error setLayerGenericMetadata(
             const std::string& name, bool mandatory, const std::vector<uint8_t>& value) = 0;
+
+    // AIDL HAL
+    [[clang::warn_unused_result]] virtual hal::Error setWhitePointNits(float whitePointNits) = 0;
 };
 
 namespace impl {
@@ -312,7 +322,8 @@
 
     hal::Error setBlendMode(hal::BlendMode mode) override;
     hal::Error setColor(hal::Color color) override;
-    hal::Error setCompositionType(hal::Composition type) override;
+    hal::Error setCompositionType(
+            aidl::android::hardware::graphics::composer3::Composition type) override;
     hal::Error setDataspace(hal::Dataspace dataspace) override;
     hal::Error setPerFrameMetadata(const int32_t supportedPerFrameMetadata,
                                    const android::HdrMetadata& metadata) override;
@@ -331,6 +342,9 @@
     hal::Error setLayerGenericMetadata(const std::string& name, bool mandatory,
                                        const std::vector<uint8_t>& value) override;
 
+    // AIDL HAL
+    hal::Error setWhitePointNits(float whitePointNits) override;
+
 private:
     // These are references to data owned by HWC2::Device, which will outlive
     // this HWC2::Layer, so these references are guaranteed to be valid for
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 06f5df5..d851e22 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -522,11 +522,13 @@
     RETURN_IF_HWC_ERROR_FOR("getRequests", error, displayId, BAD_INDEX);
 
     DeviceRequestedChanges::ClientTargetProperty clientTargetProperty;
-    error = hwcDisplay->getClientTargetProperty(&clientTargetProperty);
+    float clientTargetWhitePointNits;
+    error = hwcDisplay->getClientTargetProperty(&clientTargetProperty, &clientTargetWhitePointNits);
 
     outChanges->emplace(DeviceRequestedChanges{std::move(changedTypes), std::move(displayRequests),
                                                std::move(layerRequests),
-                                               std::move(clientTargetProperty)});
+                                               std::move(clientTargetProperty),
+                                               clientTargetWhitePointNits});
     error = hwcDisplay->acceptChanges();
     RETURN_IF_HWC_ERROR_FOR("acceptChanges", error, displayId, BAD_INDEX);
 
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 0a090da..aa4abdf 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -43,6 +43,8 @@
 #include "HWC2.h"
 #include "Hal.h"
 
+#include <aidl/android/hardware/graphics/composer3/Composition.h>
+
 namespace android {
 
 namespace hal = hardware::graphics::composer::hal;
@@ -70,7 +72,9 @@
 class HWComposer {
 public:
     struct DeviceRequestedChanges {
-        using ChangedTypes = std::unordered_map<HWC2::Layer*, hal::Composition>;
+        using ChangedTypes =
+                std::unordered_map<HWC2::Layer*,
+                                   aidl::android::hardware::graphics::composer3::Composition>;
         using ClientTargetProperty = hal::ClientTargetProperty;
         using DisplayRequests = hal::DisplayRequest;
         using LayerRequests = std::unordered_map<HWC2::Layer*, hal::LayerRequest>;
@@ -79,6 +83,7 @@
         DisplayRequests displayRequests;
         LayerRequests layerRequests;
         ClientTargetProperty clientTargetProperty;
+        float clientTargetWhitePointNits;
     };
 
     struct HWCDisplayMode {
diff --git a/services/surfaceflinger/DisplayHardware/Hal.h b/services/surfaceflinger/DisplayHardware/Hal.h
index 02d0658..77e704f 100644
--- a/services/surfaceflinger/DisplayHardware/Hal.h
+++ b/services/surfaceflinger/DisplayHardware/Hal.h
@@ -20,6 +20,8 @@
 #include <android/hardware/graphics/composer/2.4/IComposer.h>
 #include <android/hardware/graphics/composer/2.4/IComposerClient.h>
 
+#include <aidl/android/hardware/graphics/composer3/Composition.h>
+
 #define ERROR_HAS_CHANGES 5
 
 namespace android {
@@ -49,7 +51,6 @@
 using Attribute = IComposerClient::Attribute;
 using BlendMode = IComposerClient::BlendMode;
 using Color = IComposerClient::Color;
-using Composition = IComposerClient::Composition;
 using Connection = IComposerCallback::Connection;
 using ContentType = IComposerClient::ContentType;
 using Capability = IComposer::Capability;
@@ -95,19 +96,20 @@
     }
 }
 
-inline std::string to_string(hardware::graphics::composer::hal::Composition composition) {
+inline std::string to_string(
+        aidl::android::hardware::graphics::composer3::Composition composition) {
     switch (composition) {
-        case hardware::graphics::composer::hal::Composition::INVALID:
+        case aidl::android::hardware::graphics::composer3::Composition::INVALID:
             return "Invalid";
-        case hardware::graphics::composer::hal::Composition::CLIENT:
+        case aidl::android::hardware::graphics::composer3::Composition::CLIENT:
             return "Client";
-        case hardware::graphics::composer::hal::Composition::DEVICE:
+        case aidl::android::hardware::graphics::composer3::Composition::DEVICE:
             return "Device";
-        case hardware::graphics::composer::hal::Composition::SOLID_COLOR:
+        case aidl::android::hardware::graphics::composer3::Composition::SOLID_COLOR:
             return "SolidColor";
-        case hardware::graphics::composer::hal::Composition::CURSOR:
+        case aidl::android::hardware::graphics::composer3::Composition::CURSOR:
             return "Cursor";
-        case hardware::graphics::composer::hal::Composition::SIDEBAND:
+        case aidl::android::hardware::graphics::composer3::Composition::SIDEBAND:
             return "Sideband";
         default:
             return "Unknown";
diff --git a/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp b/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp
index 6c40598..18f24c1 100644
--- a/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp
@@ -278,7 +278,7 @@
 
 Error HidlComposer::getChangedCompositionTypes(
         Display display, std::vector<Layer>* outLayers,
-        std::vector<IComposerClient::Composition>* outTypes) {
+        std::vector<aidl::android::hardware::graphics::composer3::Composition>* outTypes) {
     mReader.takeChangedCompositionTypes(display, outLayers, outTypes);
     return Error::NONE;
 }
@@ -618,11 +618,17 @@
     return Error::NONE;
 }
 
-Error HidlComposer::setLayerCompositionType(Display display, Layer layer,
-                                            IComposerClient::Composition type) {
+static IComposerClient::Composition to_hidl_type(
+        aidl::android::hardware::graphics::composer3::Composition type) {
+    return static_cast<IComposerClient::Composition>(type);
+}
+
+Error HidlComposer::setLayerCompositionType(
+        Display display, Layer layer,
+        aidl::android::hardware::graphics::composer3::Composition type) {
     mWriter.selectDisplay(display);
     mWriter.selectLayer(layer);
-    mWriter.setLayerCompositionType(type);
+    mWriter.setLayerCompositionType(to_hidl_type(type));
     return Error::NONE;
 }
 
@@ -1164,8 +1170,14 @@
 }
 
 Error HidlComposer::getClientTargetProperty(
-        Display display, IComposerClient::ClientTargetProperty* outClientTargetProperty) {
+        Display display, IComposerClient::ClientTargetProperty* outClientTargetProperty,
+        float* outWhitePointNits) {
     mReader.takeClientTargetProperty(display, outClientTargetProperty);
+    *outWhitePointNits = -1.f;
+    return Error::NONE;
+}
+
+Error HidlComposer::setLayerWhitePointNits(Display, Layer, float) {
     return Error::NONE;
 }
 
@@ -1260,7 +1272,8 @@
     mCurrentReturnData->compositionTypes.reserve(count);
     while (count > 0) {
         auto layer = read64();
-        auto type = static_cast<IComposerClient::Composition>(readSigned());
+        auto type = static_cast<aidl::android::hardware::graphics::composer3::Composition>(
+                readSigned());
 
         mCurrentReturnData->changedLayers.push_back(layer);
         mCurrentReturnData->compositionTypes.push_back(type);
@@ -1388,7 +1401,7 @@
 
 void CommandReader::takeChangedCompositionTypes(
         Display display, std::vector<Layer>* outLayers,
-        std::vector<IComposerClient::Composition>* outTypes) {
+        std::vector<aidl::android::hardware::graphics::composer3::Composition>* outTypes) {
     auto found = mReturnData.find(display);
     if (found == mReturnData.end()) {
         outLayers->clear();
diff --git a/services/surfaceflinger/DisplayHardware/HidlComposerHal.h b/services/surfaceflinger/DisplayHardware/HidlComposerHal.h
index ad253a2..5b2219e 100644
--- a/services/surfaceflinger/DisplayHardware/HidlComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/HidlComposerHal.h
@@ -37,6 +37,8 @@
 #include <ui/GraphicBuffer.h>
 #include <utils/StrongPointer.h>
 
+#include <aidl/android/hardware/graphics/composer3/Composition.h>
+
 // TODO(b/129481165): remove the #pragma below and fix conversion issues
 #pragma clang diagnostic pop // ignored "-Wconversion -Wextra"
 
@@ -92,8 +94,9 @@
                     uint32_t* outNumLayerRequestMasks) const;
 
     // Get and clear saved changed composition types.
-    void takeChangedCompositionTypes(Display display, std::vector<Layer>* outLayers,
-                                     std::vector<IComposerClient::Composition>* outTypes);
+    void takeChangedCompositionTypes(
+            Display display, std::vector<Layer>* outLayers,
+            std::vector<aidl::android::hardware::graphics::composer3::Composition>* outTypes);
 
     // Get and clear saved display requests.
     void takeDisplayRequests(Display display, uint32_t* outDisplayRequestMask,
@@ -130,7 +133,7 @@
         uint32_t displayRequests = 0;
 
         std::vector<Layer> changedLayers;
-        std::vector<IComposerClient::Composition> compositionTypes;
+        std::vector<aidl::android::hardware::graphics::composer3::Composition> compositionTypes;
 
         std::vector<Layer> requestedLayers;
         std::vector<uint32_t> requestMasks;
@@ -188,8 +191,10 @@
     Error destroyLayer(Display display, Layer layer) override;
 
     Error getActiveConfig(Display display, Config* outConfig) override;
-    Error getChangedCompositionTypes(Display display, std::vector<Layer>* outLayers,
-                                     std::vector<IComposerClient::Composition>* outTypes) override;
+    Error getChangedCompositionTypes(
+            Display display, std::vector<Layer>* outLayers,
+            std::vector<aidl::android::hardware::graphics::composer3::Composition>* outTypes)
+            override;
     Error getColorModes(Display display, std::vector<ColorMode>* outModes) override;
     Error getDisplayAttribute(Display display, Config config, IComposerClient::Attribute attribute,
                               int32_t* outValue) override;
@@ -242,8 +247,9 @@
                                 const std::vector<IComposerClient::Rect>& damage) override;
     Error setLayerBlendMode(Display display, Layer layer, IComposerClient::BlendMode mode) override;
     Error setLayerColor(Display display, Layer layer, const IComposerClient::Color& color) override;
-    Error setLayerCompositionType(Display display, Layer layer,
-                                  IComposerClient::Composition type) override;
+    Error setLayerCompositionType(
+            Display display, Layer layer,
+            aidl::android::hardware::graphics::composer3::Composition type) override;
     Error setLayerDataspace(Display display, Layer layer, Dataspace dataspace) override;
     Error setLayerDisplayFrame(Display display, Layer layer,
                                const IComposerClient::Rect& frame) override;
@@ -304,9 +310,10 @@
                                         bool mandatory, const std::vector<uint8_t>& value) override;
     V2_4::Error getLayerGenericMetadataKeys(
             std::vector<IComposerClient::LayerGenericMetadataKey>* outKeys) override;
-    Error getClientTargetProperty(
-            Display display,
-            IComposerClient::ClientTargetProperty* outClientTargetProperty) override;
+    Error getClientTargetProperty(Display display,
+                                  IComposerClient::ClientTargetProperty* outClientTargetProperty,
+                                  float* outWhitePointNits) override;
+    Error setLayerWhitePointNits(Display display, Layer layer, float whitePointNits) override;
 
 private:
     class CommandWriter : public CommandWriterBase {
diff --git a/services/surfaceflinger/EffectLayer.cpp b/services/surfaceflinger/EffectLayer.cpp
index 845176c..cc85352 100644
--- a/services/surfaceflinger/EffectLayer.cpp
+++ b/services/surfaceflinger/EffectLayer.cpp
@@ -109,7 +109,8 @@
 
     auto* compositionState = editCompositionState();
     compositionState->color = getColor();
-    compositionState->compositionType = Hwc2::IComposerClient::Composition::SOLID_COLOR;
+    compositionState->compositionType =
+            aidl::android::hardware::graphics::composer3::Composition::SOLID_COLOR;
 }
 
 sp<compositionengine::LayerFE> EffectLayer::getCompositionEngineLayerFE() const {
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 4606746..6e9138c 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -46,6 +46,7 @@
 #include <stdint.h>
 #include <stdlib.h>
 #include <sys/types.h>
+#include <ui/DataspaceUtils.h>
 #include <ui/DebugUtils.h>
 #include <ui/GraphicBuffer.h>
 #include <ui/PixelFormat.h>
@@ -585,6 +586,8 @@
 
     layerSettings.alpha = alpha;
     layerSettings.sourceDataspace = getDataSpace();
+
+    layerSettings.whitePointNits = targetSettings.whitePointNits;
     switch (targetSettings.blurSetting) {
         case LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled:
             layerSettings.backgroundBlurRadius = getBackgroundBlurRadius();
@@ -647,15 +650,16 @@
     return {*layerSettings};
 }
 
-Hwc2::IComposerClient::Composition Layer::getCompositionType(const DisplayDevice& display) const {
+aidl::android::hardware::graphics::composer3::Composition Layer::getCompositionType(
+        const DisplayDevice& display) const {
     const auto outputLayer = findOutputLayerForDisplay(&display);
     if (outputLayer == nullptr) {
-        return Hwc2::IComposerClient::Composition::INVALID;
+        return aidl::android::hardware::graphics::composer3::Composition::INVALID;
     }
     if (outputLayer->getState().hwc) {
         return (*outputLayer->getState().hwc).hwcCompositionType;
     } else {
-        return Hwc2::IComposerClient::Composition::CLIENT;
+        return aidl::android::hardware::graphics::composer3::Composition::CLIENT;
     }
 }
 
@@ -2001,7 +2005,7 @@
     if (traceFlags & LayerTracing::TRACE_COMPOSITION) {
         // Only populate for the primary display.
         if (display) {
-            const Hwc2::IComposerClient::Composition compositionType = getCompositionType(*display);
+            const auto compositionType = getCompositionType(*display);
             layerProto->set_hwc_composition_type(static_cast<HwcCompositionType>(compositionType));
         }
     }
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 3f4d48b..31cdf0b 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -1037,7 +1037,8 @@
     // Returns true if the layer can draw shadows on its border.
     virtual bool canDrawShadows() const { return true; }
 
-    Hwc2::IComposerClient::Composition getCompositionType(const DisplayDevice&) const;
+    aidl::android::hardware::graphics::composer3::Composition getCompositionType(
+            const DisplayDevice&) const;
 
     /**
      * Returns an unsorted vector of all layers that are part of this tree.
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index b7327b2..4f38588 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -67,6 +67,7 @@
 #include <renderengine/RenderEngine.h>
 #include <sys/types.h>
 #include <ui/ColorSpace.h>
+#include <ui/DataspaceUtils.h>
 #include <ui/DebugUtils.h>
 #include <ui/DisplayId.h>
 #include <ui/DisplayMode.h>
@@ -493,7 +494,8 @@
 
     enableLatchUnsignaledConfig = getLatchUnsignaledConfig();
 
-    mTransactionTracingEnabled = property_get_bool("debug.sf.enable_transaction_tracing", false);
+    mTransactionTracingEnabled =
+            !mIsUserBuild && property_get_bool("debug.sf.enable_transaction_tracing", true);
     if (mTransactionTracingEnabled) {
         mTransactionTracing.enable();
     }
@@ -2316,12 +2318,7 @@
             mDrawingState.traverse([&, compositionDisplay = compositionDisplay](Layer* layer) {
                 const auto layerFe = layer->getCompositionEngineLayerFE();
                 if (layer->isVisible() && compositionDisplay->includesLayer(layerFe)) {
-                    const Dataspace transfer =
-                        static_cast<Dataspace>(layer->getDataSpace() & Dataspace::TRANSFER_MASK);
-                    const bool isHdr = (transfer == Dataspace::TRANSFER_ST2084 ||
-                                        transfer == Dataspace::TRANSFER_HLG);
-
-                    if (isHdr) {
+                    if (isHdrDataspace(layer->getDataSpace())) {
                         const auto* outputLayer =
                             compositionDisplay->getOutputLayerForLayer(layerFe);
                         if (outputLayer) {
@@ -3122,9 +3119,6 @@
             const auto& [secure, transform] = it->second;
             isSecure = secure;
             displayTransform = transform;
-        } else {
-            ALOGE("No input-enabled display found for layer `%s` on layer stack id: %d",
-                  layer->getDebugName(), layerStackId);
         }
 
         outWindowInfos.push_back(layer->fillInputInfo(displayTransform, isSecure));
@@ -4344,8 +4338,9 @@
     return hasChanges ? eTraversalNeeded : 0;
 }
 
-status_t SurfaceFlinger::mirrorLayer(const sp<Client>& client, const sp<IBinder>& mirrorFromHandle,
-                                     sp<IBinder>* outHandle, int32_t* outLayerId) {
+status_t SurfaceFlinger::mirrorLayer(const LayerCreationArgs& args,
+                                     const sp<IBinder>& mirrorFromHandle, sp<IBinder>* outHandle,
+                                     int32_t* outLayerId) {
     if (!mirrorFromHandle) {
         return NAME_NOT_FOUND;
     }
@@ -4358,7 +4353,6 @@
         if (!mirrorFrom) {
             return NAME_NOT_FOUND;
         }
-        LayerCreationArgs args(this, client, "MirrorRoot", 0, LayerMetadata());
         status_t result = createContainerLayer(args, outHandle, &mirrorLayer);
         if (result != NO_ERROR) {
             return result;
@@ -4368,7 +4362,11 @@
     }
 
     *outLayerId = mirrorLayer->sequence;
-    return addClientLayer(client, *outHandle, mirrorLayer /* layer */, nullptr /* parent */,
+    if (mTransactionTracingEnabled) {
+        mTransactionTracing.onMirrorLayerAdded((*outHandle)->localBinder(), mirrorLayer->sequence,
+                                               args.name, mirrorFrom->sequence);
+    }
+    return addClientLayer(args.client, *outHandle, mirrorLayer /* layer */, nullptr /* parent */,
                           false /* addAsRoot */, nullptr /* outTransformHint */);
 }
 
@@ -4418,10 +4416,6 @@
     if (parentLayer != nullptr) {
         addToRoot = false;
     }
-    result = addClientLayer(args.client, *outHandle, layer, parent, addToRoot, outTransformHint);
-    if (result != NO_ERROR) {
-        return result;
-    }
 
     int parentId = -1;
     // We can safely promote the layer in binder thread because we have a strong reference
@@ -4430,8 +4424,15 @@
     if (parentSp != nullptr) {
         parentId = parentSp->getSequence();
     }
-    mTransactionTracing.onLayerAdded((*outHandle)->localBinder(), layer->sequence, args.name,
-                                     args.flags, parentId);
+    if (mTransactionTracingEnabled) {
+        mTransactionTracing.onLayerAdded((*outHandle)->localBinder(), layer->sequence, args.name,
+                                         args.flags, parentId);
+    }
+
+    result = addClientLayer(args.client, *outHandle, layer, parent, addToRoot, outTransformHint);
+    if (result != NO_ERROR) {
+        return result;
+    }
 
     setTransactionFlags(eTransactionNeeded);
     *outLayerId = layer->sequence;
@@ -4482,14 +4483,14 @@
     return NO_ERROR;
 }
 
-status_t SurfaceFlinger::createEffectLayer(LayerCreationArgs& args, sp<IBinder>* handle,
+status_t SurfaceFlinger::createEffectLayer(const LayerCreationArgs& args, sp<IBinder>* handle,
                                            sp<Layer>* outLayer) {
     *outLayer = getFactory().createEffectLayer(args);
     *handle = (*outLayer)->getHandle();
     return NO_ERROR;
 }
 
-status_t SurfaceFlinger::createContainerLayer(LayerCreationArgs& args, sp<IBinder>* handle,
+status_t SurfaceFlinger::createContainerLayer(const LayerCreationArgs& args, sp<IBinder>* handle,
                                               sp<Layer>* outLayer) {
     *outLayer = getFactory().createContainerLayer(args);
     *handle = (*outLayer)->getHandle();
@@ -4515,6 +4516,9 @@
     markLayerPendingRemovalLocked(layer);
     mBufferCountTracker.remove(handle);
     layer.clear();
+    if (mTransactionTracingEnabled) {
+        mTransactionTracing.onHandleRemoved(handle);
+    }
 }
 
 // ---------------------------------------------------------------------------
@@ -6425,6 +6429,8 @@
                                        BlurSetting::Disabled
                              : compositionengine::LayerFE::ClientCompositionTargetSettings::
                                        BlurSetting::Enabled,
+                DisplayDevice::sDefaultMaxLumiance,
+
         };
         std::vector<compositionengine::LayerFE::LayerSettings> results =
                 layer->prepareClientCompositionList(targetSettings);
@@ -6669,7 +6675,9 @@
     if (!layer->isRemovedFromCurrentState()) {
         mScheduler->deregisterLayer(layer);
     }
-    mTransactionTracing.onLayerRemoved(layer->getSequence());
+    if (mTransactionTracingEnabled) {
+        mTransactionTracing.onLayerRemoved(layer->getSequence());
+    }
 }
 
 void SurfaceFlinger::onLayerUpdate() {
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 17dfef9..e1b52c5 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -770,13 +770,13 @@
     status_t createBufferStateLayer(LayerCreationArgs& args, sp<IBinder>* outHandle,
                                     sp<Layer>* outLayer);
 
-    status_t createEffectLayer(LayerCreationArgs& args, sp<IBinder>* outHandle,
+    status_t createEffectLayer(const LayerCreationArgs& args, sp<IBinder>* outHandle,
                                sp<Layer>* outLayer);
 
-    status_t createContainerLayer(LayerCreationArgs& args, sp<IBinder>* outHandle,
+    status_t createContainerLayer(const LayerCreationArgs& args, sp<IBinder>* outHandle,
                                   sp<Layer>* outLayer);
 
-    status_t mirrorLayer(const sp<Client>& client, const sp<IBinder>& mirrorFromHandle,
+    status_t mirrorLayer(const LayerCreationArgs& args, const sp<IBinder>& mirrorFromHandle,
                          sp<IBinder>* outHandle, int32_t* outLayerId);
 
     // called when all clients have released all their references to
diff --git a/services/surfaceflinger/Tracing/RingBuffer.h b/services/surfaceflinger/Tracing/RingBuffer.h
index 281cd19..3b2626d 100644
--- a/services/surfaceflinger/Tracing/RingBuffer.h
+++ b/services/surfaceflinger/Tracing/RingBuffer.h
@@ -37,22 +37,21 @@
     size_t used() const { return mUsedInBytes; }
     size_t frameCount() const { return mStorage.size(); }
     void setSize(size_t newSize) { mSizeInBytes = newSize; }
-    EntryProto& front() { return mStorage.front(); }
-    const EntryProto& front() const { return mStorage.front(); }
-    const EntryProto& back() const { return mStorage.back(); }
+    const std::string& front() const { return mStorage.front(); }
+    const std::string& back() const { return mStorage.back(); }
 
     void reset() {
         // use the swap trick to make sure memory is released
-        std::deque<EntryProto>().swap(mStorage);
+        std::deque<std::string>().swap(mStorage);
         mUsedInBytes = 0U;
     }
 
     void writeToProto(FileProto& fileProto) {
         fileProto.mutable_entry()->Reserve(static_cast<int>(mStorage.size()) +
                                            fileProto.entry().size());
-        for (const EntryProto& entry : mStorage) {
+        for (const std::string& entry : mStorage) {
             EntryProto* entryProto = fileProto.add_entry();
-            *entryProto = entry;
+            entryProto->ParseFromString(entry);
         }
     }
 
@@ -74,28 +73,35 @@
         return NO_ERROR;
     }
 
-    std::vector<EntryProto> emplace(EntryProto&& proto) {
-        std::vector<EntryProto> replacedEntries;
-        size_t protoSize = static_cast<size_t>(proto.ByteSize());
+    std::vector<std::string> emplace(std::string&& serializedProto) {
+        std::vector<std::string> replacedEntries;
+        size_t protoSize = static_cast<size_t>(serializedProto.size());
         while (mUsedInBytes + protoSize > mSizeInBytes) {
             if (mStorage.empty()) {
                 return {};
             }
-            mUsedInBytes -= static_cast<size_t>(mStorage.front().ByteSize());
+            mUsedInBytes -= static_cast<size_t>(mStorage.front().size());
             replacedEntries.emplace_back(mStorage.front());
             mStorage.pop_front();
         }
         mUsedInBytes += protoSize;
-        mStorage.emplace_back();
-        mStorage.back().Swap(&proto);
+        mStorage.emplace_back(serializedProto);
         return replacedEntries;
     }
 
+    std::vector<std::string> emplace(EntryProto&& proto) {
+        std::string serializedProto;
+        proto.SerializeToString(&serializedProto);
+        return emplace(std::move(serializedProto));
+    }
+
     void dump(std::string& result) const {
         std::chrono::milliseconds duration(0);
         if (frameCount() > 0) {
+            EntryProto entry;
+            entry.ParseFromString(mStorage.front());
             duration = std::chrono::duration_cast<std::chrono::milliseconds>(
-                    std::chrono::nanoseconds(systemTime() - front().elapsed_realtime_nanos()));
+                    std::chrono::nanoseconds(systemTime() - entry.elapsed_realtime_nanos()));
         }
         const int64_t durationCount = duration.count();
         base::StringAppendF(&result,
@@ -107,7 +113,7 @@
 private:
     size_t mUsedInBytes = 0U;
     size_t mSizeInBytes = 0U;
-    std::deque<EntryProto> mStorage;
+    std::deque<std::string> mStorage;
 };
 
 } // namespace android
diff --git a/services/surfaceflinger/Tracing/TransactionProtoParser.cpp b/services/surfaceflinger/Tracing/TransactionProtoParser.cpp
index 7e12313..378deb0 100644
--- a/services/surfaceflinger/Tracing/TransactionProtoParser.cpp
+++ b/services/surfaceflinger/Tracing/TransactionProtoParser.cpp
@@ -43,7 +43,7 @@
 }
 
 proto::TransactionState TransactionProtoParser::toProto(
-        const std::unordered_map<int32_t /* layerId */, TracingLayerState> states) {
+        const std::map<int32_t /* layerId */, TracingLayerState>& states) {
     proto::TransactionState proto;
     for (auto& [layerId, state] : states) {
         proto::LayerState layerProto = toProto(state, nullptr);
@@ -278,6 +278,7 @@
     proto.set_name(args.name);
     proto.set_flags(args.flags);
     proto.set_parent_id(args.parentId);
+    proto.set_mirror_from_id(args.mirrorFromId);
     return proto;
 }
 
@@ -312,6 +313,7 @@
     outArgs.name = proto.name();
     outArgs.flags = proto.flags();
     outArgs.parentId = proto.parent_id();
+    outArgs.mirrorFromId = proto.mirror_from_id();
 }
 
 void TransactionProtoParser::fromProto(const proto::LayerState& proto,
@@ -320,6 +322,7 @@
     fromProto(proto, getLayerHandle, static_cast<layer_state_t&>(outState));
     if (proto.what() & layer_state_t::eReparent) {
         outState.parentId = proto.parent_id();
+        outState.args.parentId = outState.parentId;
     }
     if (proto.what() & layer_state_t::eRelativeLayerChanged) {
         outState.relativeParentId = proto.relative_parent_id();
@@ -508,7 +511,9 @@
                                                DisplayIdToHandleFn getDisplayHandle) {
     DisplayState display;
     display.what = proto.what();
-    display.token = getDisplayHandle(proto.id());
+    if (getDisplayHandle != nullptr) {
+        display.token = getDisplayHandle(proto.id());
+    }
 
     if (display.what & DisplayState::eLayerStackChanged) {
         display.layerStack.id = proto.layer_stack();
diff --git a/services/surfaceflinger/Tracing/TransactionProtoParser.h b/services/surfaceflinger/Tracing/TransactionProtoParser.h
index 619ee05..b78d3d9 100644
--- a/services/surfaceflinger/Tracing/TransactionProtoParser.h
+++ b/services/surfaceflinger/Tracing/TransactionProtoParser.h
@@ -25,8 +25,9 @@
 struct TracingLayerCreationArgs {
     int32_t layerId;
     std::string name;
-    uint32_t flags;
-    int32_t parentId;
+    uint32_t flags = 0;
+    int32_t parentId = -1;
+    int32_t mirrorFromId = -1;
 };
 
 struct TracingLayerState : layer_state_t {
@@ -37,8 +38,7 @@
     int32_t parentId;
     int32_t relativeParentId;
     int32_t inputCropId;
-    std::string name;
-    uint32_t layerCreationFlags;
+    TracingLayerCreationArgs args;
 };
 
 class TransactionProtoParser {
@@ -51,7 +51,7 @@
     static proto::TransactionState toProto(const TransactionState&, LayerHandleToIdFn getLayerIdFn,
                                            DisplayHandleToIdFn getDisplayIdFn);
     static proto::TransactionState toProto(
-            const std::unordered_map<int32_t /* layerId */, TracingLayerState>);
+            const std::map<int32_t /* layerId */, TracingLayerState>&);
 
     static proto::LayerCreationArgs toProto(const TracingLayerCreationArgs& args);
 
@@ -70,4 +70,4 @@
     static DisplayState fromProto(const proto::DisplayState&, DisplayIdToHandleFn getDisplayHandle);
 };
 
-} // namespace android::surfaceflinger
\ No newline at end of file
+} // namespace android::surfaceflinger
diff --git a/services/surfaceflinger/Tracing/TransactionTracing.cpp b/services/surfaceflinger/Tracing/TransactionTracing.cpp
index cf488c2..b5966d5 100644
--- a/services/surfaceflinger/Tracing/TransactionTracing.cpp
+++ b/services/surfaceflinger/Tracing/TransactionTracing.cpp
@@ -177,9 +177,9 @@
                                   const std::vector<int32_t>& removedLayers) {
     ATRACE_CALL();
     std::scoped_lock lock(mTraceLock);
-    std::vector<proto::TransactionTraceEntry> removedEntries;
+    std::vector<std::string> removedEntries;
+    proto::TransactionTraceEntry entryProto;
     for (const CommittedTransactions& entry : committedTransactions) {
-        proto::TransactionTraceEntry entryProto;
         entryProto.set_elapsed_realtime_nanos(entry.timestamp);
         entryProto.set_vsync_id(entry.vsyncId);
         entryProto.mutable_added_layers()->Reserve(static_cast<int32_t>(mCreatedLayers.size()));
@@ -199,16 +199,24 @@
                 entryProto.mutable_transactions()->Add(std::move(it->second));
                 mQueuedTransactions.erase(it);
             } else {
-                ALOGE("Could not find transaction id %" PRIu64, id);
+                ALOGW("Could not find transaction id %" PRIu64, id);
             }
         }
-        std::vector<proto::TransactionTraceEntry> entries = mBuffer->emplace(std::move(entryProto));
+
+        std::string serializedProto;
+        entryProto.SerializeToString(&serializedProto);
+        entryProto.Clear();
+        std::vector<std::string> entries = mBuffer->emplace(std::move(serializedProto));
+        removedEntries.reserve(removedEntries.size() + entries.size());
         removedEntries.insert(removedEntries.end(), std::make_move_iterator(entries.begin()),
                               std::make_move_iterator(entries.end()));
     }
 
-    for (const proto::TransactionTraceEntry& removedEntry : removedEntries) {
-        updateStartingStateLocked(removedEntry);
+    proto::TransactionTraceEntry removedEntryProto;
+    for (const std::string& removedEntry : removedEntries) {
+        removedEntryProto.ParseFromString(removedEntry);
+        updateStartingStateLocked(removedEntryProto);
+        removedEntryProto.Clear();
     }
     mTransactionsAddedToBufferCv.notify_one();
 }
@@ -220,14 +228,34 @@
     std::unique_lock<std::mutex> lock(mTraceLock);
     base::ScopedLockAssertion assumeLocked(mTraceLock);
     mTransactionsAddedToBufferCv.wait(lock, [&]() REQUIRES(mTraceLock) {
-        return mBuffer->used() > 0 && mBuffer->back().vsync_id() >= vsyncId;
+        proto::TransactionTraceEntry entry;
+        if (mBuffer->used() > 0) {
+            entry.ParseFromString(mBuffer->back());
+        }
+        return mBuffer->used() > 0 && entry.vsync_id() >= vsyncId;
     });
 }
 
 void TransactionTracing::onLayerAdded(BBinder* layerHandle, int layerId, const std::string& name,
                                       uint32_t flags, int parentId) {
     std::scoped_lock lock(mTraceLock);
-    TracingLayerCreationArgs args{layerId, name, flags, parentId};
+    TracingLayerCreationArgs args{layerId, name, flags, parentId, -1 /* mirrorFromId */};
+    if (mLayerHandles.find(layerHandle) != mLayerHandles.end()) {
+        ALOGW("Duplicate handles found. %p", layerHandle);
+    }
+    mLayerHandles[layerHandle] = layerId;
+    proto::LayerCreationArgs protoArgs = TransactionProtoParser::toProto(args);
+    proto::LayerCreationArgs protoArgsCopy = protoArgs;
+    mCreatedLayers.push_back(protoArgs);
+}
+
+void TransactionTracing::onMirrorLayerAdded(BBinder* layerHandle, int layerId,
+                                            const std::string& name, int mirrorFromId) {
+    std::scoped_lock lock(mTraceLock);
+    TracingLayerCreationArgs args{layerId, name, 0 /* flags */, -1 /* parentId */, mirrorFromId};
+    if (mLayerHandles.find(layerHandle) != mLayerHandles.end()) {
+        ALOGW("Duplicate handles found. %p", layerHandle);
+    }
     mLayerHandles[layerHandle] = layerId;
     mCreatedLayers.emplace_back(TransactionProtoParser::toProto(args));
 }
@@ -237,6 +265,11 @@
     tryPushToTracingThread();
 }
 
+void TransactionTracing::onHandleRemoved(BBinder* layerHandle) {
+    std::scoped_lock lock(mTraceLock);
+    mLayerHandles.erase(layerHandle);
+}
+
 void TransactionTracing::tryPushToTracingThread() {
     // Try to acquire the lock from main thread.
     if (mMainThreadLock.try_lock()) {
@@ -260,7 +293,11 @@
         return -1;
     }
     auto it = mLayerHandles.find(layerHandle->localBinder());
-    return it == mLayerHandles.end() ? -1 : it->second;
+    if (it == mLayerHandles.end()) {
+        ALOGW("Could not find layer handle %p", layerHandle->localBinder());
+        return -1;
+    }
+    return it->second;
 }
 
 void TransactionTracing::updateStartingStateLocked(
@@ -270,9 +307,7 @@
     for (const proto::LayerCreationArgs& addedLayer : removedEntry.added_layers()) {
         TracingLayerState& startingState = mStartingStates[addedLayer.layer_id()];
         startingState.layerId = addedLayer.layer_id();
-        startingState.name = addedLayer.name();
-        startingState.layerCreationFlags = addedLayer.flags();
-        startingState.parentId = addedLayer.parent_id();
+        TransactionProtoParser::fromProto(addedLayer, startingState.args);
     }
 
     // Merge layer states to starting transaction state.
@@ -280,7 +315,7 @@
         for (const proto::LayerState& layerState : transaction.layer_changes()) {
             auto it = mStartingStates.find(layerState.layer_id());
             if (it == mStartingStates.end()) {
-                ALOGE("Could not find layer id %d", layerState.layer_id());
+                ALOGW("Could not find layer id %d", layerState.layer_id());
                 continue;
             }
             TransactionProtoParser::fromProto(layerState, nullptr, it->second);
@@ -290,13 +325,6 @@
     // Clean up stale starting states since the layer has been removed and the buffer does not
     // contain any references to the layer.
     for (const int32_t removedLayerId : removedEntry.removed_layers()) {
-        auto it = std::find_if(mLayerHandles.begin(), mLayerHandles.end(),
-                               [removedLayerId](auto& layer) {
-                                   return layer.second == removedLayerId;
-                               });
-        if (it != mLayerHandles.end()) {
-            mLayerHandles.erase(it);
-        }
         mStartingStates.erase(removedLayerId);
     }
 }
@@ -305,11 +333,13 @@
     proto::TransactionTraceEntry* entryProto = proto.add_entry();
     entryProto->set_elapsed_realtime_nanos(mStartingTimestamp);
     entryProto->set_vsync_id(0);
+    if (mStartingStates.size() == 0) {
+        return;
+    }
+
     entryProto->mutable_added_layers()->Reserve(static_cast<int32_t>(mStartingStates.size()));
     for (auto& [layerId, state] : mStartingStates) {
-        TracingLayerCreationArgs args{layerId, state.name, state.layerCreationFlags,
-                                      state.parentId};
-        entryProto->mutable_added_layers()->Add(TransactionProtoParser::toProto(args));
+        entryProto->mutable_added_layers()->Add(TransactionProtoParser::toProto(state.args));
     }
 
     proto::TransactionState transactionProto = TransactionProtoParser::toProto(mStartingStates);
diff --git a/services/surfaceflinger/Tracing/TransactionTracing.h b/services/surfaceflinger/Tracing/TransactionTracing.h
index 0aa22ed..26a3758 100644
--- a/services/surfaceflinger/Tracing/TransactionTracing.h
+++ b/services/surfaceflinger/Tracing/TransactionTracing.h
@@ -64,7 +64,10 @@
     void setBufferSize(size_t bufferSizeInBytes);
     void onLayerAdded(BBinder* layerHandle, int layerId, const std::string& name, uint32_t flags,
                       int parentId);
+    void onMirrorLayerAdded(BBinder* layerHandle, int layerId, const std::string& name,
+                            int mirrorFromId);
     void onLayerRemoved(int layerId);
+    void onHandleRemoved(BBinder* layerHandle);
     void dump(std::string&) const;
     static constexpr auto CONTINUOUS_TRACING_BUFFER_SIZE = 512 * 1024;
     static constexpr auto ACTIVE_TRACING_BUFFER_SIZE = 100 * 1024 * 1024;
@@ -85,8 +88,7 @@
     std::vector<proto::LayerCreationArgs> mCreatedLayers GUARDED_BY(mTraceLock);
     std::unordered_map<BBinder* /* layerHandle */, int32_t /* layerId */> mLayerHandles
             GUARDED_BY(mTraceLock);
-    std::unordered_map<int32_t /* layerId */, TracingLayerState> mStartingStates
-            GUARDED_BY(mTraceLock);
+    std::map<int32_t /* layerId */, TracingLayerState> mStartingStates GUARDED_BY(mTraceLock);
 
     // We do not want main thread to block so main thread will try to acquire mMainThreadLock,
     // otherwise will push data to temporary container.
diff --git a/services/surfaceflinger/layerproto/transactions.proto b/services/surfaceflinger/layerproto/transactions.proto
index 10222cc..e31b502 100644
--- a/services/surfaceflinger/layerproto/transactions.proto
+++ b/services/surfaceflinger/layerproto/transactions.proto
@@ -53,6 +53,7 @@
     string name = 2;
     uint32 flags = 3;
     int32 parent_id = 4;
+    int32 mirror_from_id = 5;
 }
 
 message TransactionState {
diff --git a/services/surfaceflinger/surfaceflinger.rc b/services/surfaceflinger/surfaceflinger.rc
index 575e70d..39d7bd9 100644
--- a/services/surfaceflinger/surfaceflinger.rc
+++ b/services/surfaceflinger/surfaceflinger.rc
@@ -3,7 +3,7 @@
     user system
     group graphics drmrpc readproc
     capabilities SYS_NICE
-    onrestart restart zygote
+    onrestart restart --only-if-running zygote
     task_profiles HighPerformance
     socket pdx/system/vr/display/client     stream 0666 system graphics u:object_r:pdx_display_client_endpoint_socket:s0
     socket pdx/system/vr/display/manager    stream 0666 system graphics u:object_r:pdx_display_manager_endpoint_socket:s0
diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index f1e6e48..554e454 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -1029,9 +1029,10 @@
     }
 };
 
-template <IComposerClient::Composition CompositionType>
+template <aidl::android::hardware::graphics::composer3::Composition CompositionType>
 struct KeepCompositionTypeVariant {
-    static constexpr hal::Composition TYPE = CompositionType;
+    static constexpr aidl::android::hardware::graphics::composer3::Composition TYPE =
+            CompositionType;
 
     static void setupHwcSetCallExpectations(CompositionTest* test) {
         if (!test->mDisplayOff) {
@@ -1046,10 +1047,11 @@
     }
 };
 
-template <IComposerClient::Composition InitialCompositionType,
-          IComposerClient::Composition FinalCompositionType>
+template <aidl::android::hardware::graphics::composer3::Composition InitialCompositionType,
+          aidl::android::hardware::graphics::composer3::Composition FinalCompositionType>
 struct ChangeCompositionTypeVariant {
-    static constexpr hal::Composition TYPE = FinalCompositionType;
+    static constexpr aidl::android::hardware::graphics::composer3::Composition TYPE =
+            FinalCompositionType;
 
     static void setupHwcSetCallExpectations(CompositionTest* test) {
         if (!test->mDisplayOff) {
@@ -1063,8 +1065,9 @@
         EXPECT_CALL(*test->mComposer, getChangedCompositionTypes(HWC_DISPLAY, _, _))
                 .WillOnce(DoAll(SetArgPointee<1>(std::vector<Hwc2::Layer>{
                                         static_cast<Hwc2::Layer>(HWC_LAYER)}),
-                                SetArgPointee<2>(std::vector<IComposerClient::Composition>{
-                                        FinalCompositionType}),
+                                SetArgPointee<2>(
+                                        std::vector<aidl::android::hardware::graphics::composer3::
+                                                            Composition>{FinalCompositionType}),
                                 Return(Error::NONE)));
     }
 };
@@ -1258,25 +1261,28 @@
  */
 
 TEST_F(CompositionTest, HWCComposedNormalBufferLayerWithDirtyGeometry) {
-    displayRefreshCompositionDirtyGeometry<
-            CompositionCase<DefaultDisplaySetupVariant, BufferLayerVariant<DefaultLayerProperties>,
-                            KeepCompositionTypeVariant<IComposerClient::Composition::DEVICE>,
-                            HwcCompositionResultVariant>>();
+    displayRefreshCompositionDirtyGeometry<CompositionCase<
+            DefaultDisplaySetupVariant, BufferLayerVariant<DefaultLayerProperties>,
+            KeepCompositionTypeVariant<
+                    aidl::android::hardware::graphics::composer3::Composition::DEVICE>,
+            HwcCompositionResultVariant>>();
 }
 
 TEST_F(CompositionTest, HWCComposedNormalBufferLayerWithDirtyFrame) {
-    displayRefreshCompositionDirtyFrame<
-            CompositionCase<DefaultDisplaySetupVariant, BufferLayerVariant<DefaultLayerProperties>,
-                            KeepCompositionTypeVariant<IComposerClient::Composition::DEVICE>,
-                            HwcCompositionResultVariant>>();
+    displayRefreshCompositionDirtyFrame<CompositionCase<
+            DefaultDisplaySetupVariant, BufferLayerVariant<DefaultLayerProperties>,
+            KeepCompositionTypeVariant<
+                    aidl::android::hardware::graphics::composer3::Composition::DEVICE>,
+            HwcCompositionResultVariant>>();
 }
 
 TEST_F(CompositionTest, REComposedNormalBufferLayer) {
-    displayRefreshCompositionDirtyFrame<
-            CompositionCase<DefaultDisplaySetupVariant, BufferLayerVariant<DefaultLayerProperties>,
-                            ChangeCompositionTypeVariant<IComposerClient::Composition::DEVICE,
-                                                         IComposerClient::Composition::CLIENT>,
-                            RECompositionResultVariant>>();
+    displayRefreshCompositionDirtyFrame<CompositionCase<
+            DefaultDisplaySetupVariant, BufferLayerVariant<DefaultLayerProperties>,
+            ChangeCompositionTypeVariant<
+                    aidl::android::hardware::graphics::composer3::Composition::DEVICE,
+                    aidl::android::hardware::graphics::composer3::Composition::CLIENT>,
+            RECompositionResultVariant>>();
 }
 
 TEST_F(CompositionTest, captureScreenNormalBufferLayer) {
@@ -1290,25 +1296,28 @@
  */
 
 TEST_F(CompositionTest, HWCComposedEffectLayerWithDirtyGeometry) {
-    displayRefreshCompositionDirtyGeometry<
-            CompositionCase<DefaultDisplaySetupVariant, EffectLayerVariant<EffectLayerProperties>,
-                            KeepCompositionTypeVariant<IComposerClient::Composition::SOLID_COLOR>,
-                            HwcCompositionResultVariant>>();
+    displayRefreshCompositionDirtyGeometry<CompositionCase<
+            DefaultDisplaySetupVariant, EffectLayerVariant<EffectLayerProperties>,
+            KeepCompositionTypeVariant<
+                    aidl::android::hardware::graphics::composer3::Composition::SOLID_COLOR>,
+            HwcCompositionResultVariant>>();
 }
 
 TEST_F(CompositionTest, HWCComposedEffectLayerWithDirtyFrame) {
-    displayRefreshCompositionDirtyFrame<
-            CompositionCase<DefaultDisplaySetupVariant, EffectLayerVariant<EffectLayerProperties>,
-                            KeepCompositionTypeVariant<IComposerClient::Composition::SOLID_COLOR>,
-                            HwcCompositionResultVariant>>();
+    displayRefreshCompositionDirtyFrame<CompositionCase<
+            DefaultDisplaySetupVariant, EffectLayerVariant<EffectLayerProperties>,
+            KeepCompositionTypeVariant<
+                    aidl::android::hardware::graphics::composer3::Composition::SOLID_COLOR>,
+            HwcCompositionResultVariant>>();
 }
 
 TEST_F(CompositionTest, REComposedEffectLayer) {
-    displayRefreshCompositionDirtyFrame<
-            CompositionCase<DefaultDisplaySetupVariant, EffectLayerVariant<EffectLayerProperties>,
-                            ChangeCompositionTypeVariant<IComposerClient::Composition::SOLID_COLOR,
-                                                         IComposerClient::Composition::CLIENT>,
-                            RECompositionResultVariant>>();
+    displayRefreshCompositionDirtyFrame<CompositionCase<
+            DefaultDisplaySetupVariant, EffectLayerVariant<EffectLayerProperties>,
+            ChangeCompositionTypeVariant<
+                    aidl::android::hardware::graphics::composer3::Composition::SOLID_COLOR,
+                    aidl::android::hardware::graphics::composer3::Composition::CLIENT>,
+            RECompositionResultVariant>>();
 }
 
 TEST_F(CompositionTest, captureScreenEffectLayer) {
@@ -1322,25 +1331,28 @@
  */
 
 TEST_F(CompositionTest, HWCComposedSidebandBufferLayerWithDirtyGeometry) {
-    displayRefreshCompositionDirtyGeometry<
-            CompositionCase<DefaultDisplaySetupVariant, BufferLayerVariant<SidebandLayerProperties>,
-                            KeepCompositionTypeVariant<IComposerClient::Composition::SIDEBAND>,
-                            HwcCompositionResultVariant>>();
+    displayRefreshCompositionDirtyGeometry<CompositionCase<
+            DefaultDisplaySetupVariant, BufferLayerVariant<SidebandLayerProperties>,
+            KeepCompositionTypeVariant<
+                    aidl::android::hardware::graphics::composer3::Composition::SIDEBAND>,
+            HwcCompositionResultVariant>>();
 }
 
 TEST_F(CompositionTest, HWCComposedSidebandBufferLayerWithDirtyFrame) {
-    displayRefreshCompositionDirtyFrame<
-            CompositionCase<DefaultDisplaySetupVariant, BufferLayerVariant<SidebandLayerProperties>,
-                            KeepCompositionTypeVariant<IComposerClient::Composition::SIDEBAND>,
-                            HwcCompositionResultVariant>>();
+    displayRefreshCompositionDirtyFrame<CompositionCase<
+            DefaultDisplaySetupVariant, BufferLayerVariant<SidebandLayerProperties>,
+            KeepCompositionTypeVariant<
+                    aidl::android::hardware::graphics::composer3::Composition::SIDEBAND>,
+            HwcCompositionResultVariant>>();
 }
 
 TEST_F(CompositionTest, REComposedSidebandBufferLayer) {
-    displayRefreshCompositionDirtyFrame<
-            CompositionCase<DefaultDisplaySetupVariant, BufferLayerVariant<SidebandLayerProperties>,
-                            ChangeCompositionTypeVariant<IComposerClient::Composition::SIDEBAND,
-                                                         IComposerClient::Composition::CLIENT>,
-                            RECompositionResultVariant>>();
+    displayRefreshCompositionDirtyFrame<CompositionCase<
+            DefaultDisplaySetupVariant, BufferLayerVariant<SidebandLayerProperties>,
+            ChangeCompositionTypeVariant<
+                    aidl::android::hardware::graphics::composer3::Composition::SIDEBAND,
+                    aidl::android::hardware::graphics::composer3::Composition::CLIENT>,
+            RECompositionResultVariant>>();
 }
 
 TEST_F(CompositionTest, captureScreenSidebandBufferLayer) {
@@ -1354,25 +1366,28 @@
  */
 
 TEST_F(CompositionTest, HWCComposedSecureBufferLayerWithDirtyGeometry) {
-    displayRefreshCompositionDirtyGeometry<
-            CompositionCase<DefaultDisplaySetupVariant, BufferLayerVariant<SecureLayerProperties>,
-                            KeepCompositionTypeVariant<IComposerClient::Composition::DEVICE>,
-                            HwcCompositionResultVariant>>();
+    displayRefreshCompositionDirtyGeometry<CompositionCase<
+            DefaultDisplaySetupVariant, BufferLayerVariant<SecureLayerProperties>,
+            KeepCompositionTypeVariant<
+                    aidl::android::hardware::graphics::composer3::Composition::DEVICE>,
+            HwcCompositionResultVariant>>();
 }
 
 TEST_F(CompositionTest, HWCComposedSecureBufferLayerWithDirtyFrame) {
-    displayRefreshCompositionDirtyFrame<
-            CompositionCase<DefaultDisplaySetupVariant, BufferLayerVariant<SecureLayerProperties>,
-                            KeepCompositionTypeVariant<IComposerClient::Composition::DEVICE>,
-                            HwcCompositionResultVariant>>();
+    displayRefreshCompositionDirtyFrame<CompositionCase<
+            DefaultDisplaySetupVariant, BufferLayerVariant<SecureLayerProperties>,
+            KeepCompositionTypeVariant<
+                    aidl::android::hardware::graphics::composer3::Composition::DEVICE>,
+            HwcCompositionResultVariant>>();
 }
 
 TEST_F(CompositionTest, REComposedSecureBufferLayer) {
-    displayRefreshCompositionDirtyFrame<
-            CompositionCase<DefaultDisplaySetupVariant, BufferLayerVariant<SecureLayerProperties>,
-                            ChangeCompositionTypeVariant<IComposerClient::Composition::DEVICE,
-                                                         IComposerClient::Composition::CLIENT>,
-                            RECompositionResultVariant>>();
+    displayRefreshCompositionDirtyFrame<CompositionCase<
+            DefaultDisplaySetupVariant, BufferLayerVariant<SecureLayerProperties>,
+            ChangeCompositionTypeVariant<
+                    aidl::android::hardware::graphics::composer3::Composition::DEVICE,
+                    aidl::android::hardware::graphics::composer3::Composition::CLIENT>,
+            RECompositionResultVariant>>();
 }
 
 TEST_F(CompositionTest, captureScreenSecureBufferLayerOnSecureDisplay) {
@@ -1386,17 +1401,19 @@
  */
 
 TEST_F(CompositionTest, HWCComposedSecureBufferLayerOnInsecureDisplayWithDirtyGeometry) {
-    displayRefreshCompositionDirtyGeometry<
-            CompositionCase<InsecureDisplaySetupVariant, BufferLayerVariant<SecureLayerProperties>,
-                            KeepCompositionTypeVariant<IComposerClient::Composition::CLIENT>,
-                            ForcedClientCompositionResultVariant>>();
+    displayRefreshCompositionDirtyGeometry<CompositionCase<
+            InsecureDisplaySetupVariant, BufferLayerVariant<SecureLayerProperties>,
+            KeepCompositionTypeVariant<
+                    aidl::android::hardware::graphics::composer3::Composition::CLIENT>,
+            ForcedClientCompositionResultVariant>>();
 }
 
 TEST_F(CompositionTest, HWCComposedSecureBufferLayerOnInsecureDisplayWithDirtyFrame) {
-    displayRefreshCompositionDirtyFrame<
-            CompositionCase<InsecureDisplaySetupVariant, BufferLayerVariant<SecureLayerProperties>,
-                            KeepCompositionTypeVariant<IComposerClient::Composition::CLIENT>,
-                            ForcedClientCompositionResultVariant>>();
+    displayRefreshCompositionDirtyFrame<CompositionCase<
+            InsecureDisplaySetupVariant, BufferLayerVariant<SecureLayerProperties>,
+            KeepCompositionTypeVariant<
+                    aidl::android::hardware::graphics::composer3::Composition::CLIENT>,
+            ForcedClientCompositionResultVariant>>();
 }
 
 TEST_F(CompositionTest, captureScreenSecureBufferLayerOnInsecureDisplay) {
@@ -1411,22 +1428,24 @@
 
 TEST_F(CompositionTest,
        HWCComposedBufferLayerWithSecureParentLayerOnInsecureDisplayWithDirtyGeometry) {
-    displayRefreshCompositionDirtyGeometry<
-            CompositionCase<InsecureDisplaySetupVariant,
-                            ChildLayerVariant<BufferLayerVariant<ParentSecureLayerProperties>,
-                                              ContainerLayerVariant<SecureLayerProperties>>,
-                            KeepCompositionTypeVariant<IComposerClient::Composition::CLIENT>,
-                            ForcedClientCompositionResultVariant>>();
+    displayRefreshCompositionDirtyGeometry<CompositionCase<
+            InsecureDisplaySetupVariant,
+            ChildLayerVariant<BufferLayerVariant<ParentSecureLayerProperties>,
+                              ContainerLayerVariant<SecureLayerProperties>>,
+            KeepCompositionTypeVariant<
+                    aidl::android::hardware::graphics::composer3::Composition::CLIENT>,
+            ForcedClientCompositionResultVariant>>();
 }
 
 TEST_F(CompositionTest,
        HWCComposedBufferLayerWithSecureParentLayerOnInsecureDisplayWithDirtyFrame) {
-    displayRefreshCompositionDirtyFrame<
-            CompositionCase<InsecureDisplaySetupVariant,
-                            ChildLayerVariant<BufferLayerVariant<ParentSecureLayerProperties>,
-                                              ContainerLayerVariant<SecureLayerProperties>>,
-                            KeepCompositionTypeVariant<IComposerClient::Composition::CLIENT>,
-                            ForcedClientCompositionResultVariant>>();
+    displayRefreshCompositionDirtyFrame<CompositionCase<
+            InsecureDisplaySetupVariant,
+            ChildLayerVariant<BufferLayerVariant<ParentSecureLayerProperties>,
+                              ContainerLayerVariant<SecureLayerProperties>>,
+            KeepCompositionTypeVariant<
+                    aidl::android::hardware::graphics::composer3::Composition::CLIENT>,
+            ForcedClientCompositionResultVariant>>();
 }
 
 TEST_F(CompositionTest, captureScreenBufferLayerWithSecureParentLayerOnInsecureDisplay) {
@@ -1442,25 +1461,28 @@
  */
 
 TEST_F(CompositionTest, HWCComposedCursorLayerWithDirtyGeometry) {
-    displayRefreshCompositionDirtyGeometry<
-            CompositionCase<DefaultDisplaySetupVariant, BufferLayerVariant<CursorLayerProperties>,
-                            KeepCompositionTypeVariant<IComposerClient::Composition::CURSOR>,
-                            HwcCompositionResultVariant>>();
+    displayRefreshCompositionDirtyGeometry<CompositionCase<
+            DefaultDisplaySetupVariant, BufferLayerVariant<CursorLayerProperties>,
+            KeepCompositionTypeVariant<
+                    aidl::android::hardware::graphics::composer3::Composition::CURSOR>,
+            HwcCompositionResultVariant>>();
 }
 
 TEST_F(CompositionTest, HWCComposedCursorLayerWithDirtyFrame) {
-    displayRefreshCompositionDirtyFrame<
-            CompositionCase<DefaultDisplaySetupVariant, BufferLayerVariant<CursorLayerProperties>,
-                            KeepCompositionTypeVariant<IComposerClient::Composition::CURSOR>,
-                            HwcCompositionResultVariant>>();
+    displayRefreshCompositionDirtyFrame<CompositionCase<
+            DefaultDisplaySetupVariant, BufferLayerVariant<CursorLayerProperties>,
+            KeepCompositionTypeVariant<
+                    aidl::android::hardware::graphics::composer3::Composition::CURSOR>,
+            HwcCompositionResultVariant>>();
 }
 
 TEST_F(CompositionTest, REComposedCursorLayer) {
-    displayRefreshCompositionDirtyFrame<
-            CompositionCase<DefaultDisplaySetupVariant, BufferLayerVariant<CursorLayerProperties>,
-                            ChangeCompositionTypeVariant<IComposerClient::Composition::CURSOR,
-                                                         IComposerClient::Composition::CLIENT>,
-                            RECompositionResultVariant>>();
+    displayRefreshCompositionDirtyFrame<CompositionCase<
+            DefaultDisplaySetupVariant, BufferLayerVariant<CursorLayerProperties>,
+            ChangeCompositionTypeVariant<
+                    aidl::android::hardware::graphics::composer3::Composition::CURSOR,
+                    aidl::android::hardware::graphics::composer3::Composition::CLIENT>,
+            RECompositionResultVariant>>();
 }
 
 TEST_F(CompositionTest, captureScreenCursorLayer) {
@@ -1477,7 +1499,8 @@
     mDisplayOff = true;
     displayRefreshCompositionDirtyGeometry<CompositionCase<
             PoweredOffDisplaySetupVariant, BufferLayerVariant<DefaultLayerProperties>,
-            KeepCompositionTypeVariant<IComposerClient::Composition::DEVICE>,
+            KeepCompositionTypeVariant<
+                    aidl::android::hardware::graphics::composer3::Composition::DEVICE>,
             HwcCompositionResultVariant>>();
 }
 
@@ -1485,7 +1508,8 @@
     mDisplayOff = true;
     displayRefreshCompositionDirtyFrame<CompositionCase<
             PoweredOffDisplaySetupVariant, BufferLayerVariant<DefaultLayerProperties>,
-            KeepCompositionTypeVariant<IComposerClient::Composition::DEVICE>,
+            KeepCompositionTypeVariant<
+                    aidl::android::hardware::graphics::composer3::Composition::DEVICE>,
             HwcCompositionResultVariant>>();
 }
 
@@ -1493,8 +1517,9 @@
     mDisplayOff = true;
     displayRefreshCompositionDirtyFrame<CompositionCase<
             PoweredOffDisplaySetupVariant, BufferLayerVariant<DefaultLayerProperties>,
-            ChangeCompositionTypeVariant<IComposerClient::Composition::DEVICE,
-                                         IComposerClient::Composition::CLIENT>,
+            ChangeCompositionTypeVariant<
+                    aidl::android::hardware::graphics::composer3::Composition::DEVICE,
+                    aidl::android::hardware::graphics::composer3::Composition::CLIENT>,
             RECompositionResultVariant>>();
 }
 
@@ -1509,17 +1534,19 @@
  */
 
 TEST_F(CompositionTest, DebugOptionForcingClientCompositionOfBufferLayerWithDirtyGeometry) {
-    displayRefreshCompositionDirtyGeometry<
-            CompositionCase<DefaultDisplaySetupVariant, BufferLayerVariant<DefaultLayerProperties>,
-                            KeepCompositionTypeVariant<IComposerClient::Composition::CLIENT>,
-                            ForcedClientCompositionViaDebugOptionResultVariant>>();
+    displayRefreshCompositionDirtyGeometry<CompositionCase<
+            DefaultDisplaySetupVariant, BufferLayerVariant<DefaultLayerProperties>,
+            KeepCompositionTypeVariant<
+                    aidl::android::hardware::graphics::composer3::Composition::CLIENT>,
+            ForcedClientCompositionViaDebugOptionResultVariant>>();
 }
 
 TEST_F(CompositionTest, DebugOptionForcingClientCompositionOfBufferLayerWithDirtyFrame) {
-    displayRefreshCompositionDirtyFrame<
-            CompositionCase<DefaultDisplaySetupVariant, BufferLayerVariant<DefaultLayerProperties>,
-                            KeepCompositionTypeVariant<IComposerClient::Composition::CLIENT>,
-                            ForcedClientCompositionViaDebugOptionResultVariant>>();
+    displayRefreshCompositionDirtyFrame<CompositionCase<
+            DefaultDisplaySetupVariant, BufferLayerVariant<DefaultLayerProperties>,
+            KeepCompositionTypeVariant<
+                    aidl::android::hardware::graphics::composer3::Composition::CLIENT>,
+            ForcedClientCompositionViaDebugOptionResultVariant>>();
 }
 
 } // namespace
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index 100a78d..0067997 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -270,7 +270,8 @@
         layer->editCompositionState()->sidebandStream = sidebandStream;
     }
 
-    void setLayerCompositionType(const sp<Layer>& layer, hal::Composition type) {
+    void setLayerCompositionType(const sp<Layer>& layer,
+                                 aidl::android::hardware::graphics::composer3::Composition type) {
         auto outputLayer = findOutputLayerForDisplay(layer, mFlinger->getDefaultDisplayDevice());
         LOG_ALWAYS_FATAL_IF(!outputLayer);
         auto& state = outputLayer->editState();
diff --git a/services/surfaceflinger/tests/unittests/TransactionTracingTest.cpp b/services/surfaceflinger/tests/unittests/TransactionTracingTest.cpp
index ffe5671..43b09fd 100644
--- a/services/surfaceflinger/tests/unittests/TransactionTracingTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TransactionTracingTest.cpp
@@ -56,7 +56,9 @@
 
     auto bufferFront() {
         std::scoped_lock<std::mutex> lock(mTracing->mTraceLock);
-        return mTracing->mBuffer->front();
+        proto::TransactionTraceEntry entry;
+        entry.ParseFromString(mTracing->mBuffer->front());
+        return entry;
     }
 
     bool threadIsJoinable() {
@@ -165,7 +167,7 @@
         mTracing->onLayerAdded(fakeLayerHandle->localBinder(), mParentLayerId, "parent",
                                123 /* flags */, -1 /* parentId */);
         const sp<IBinder> fakeChildLayerHandle = new BBinder();
-        mTracing->onLayerAdded(fakeChildLayerHandle->localBinder(), 2 /* layerId */, "child",
+        mTracing->onLayerAdded(fakeChildLayerHandle->localBinder(), mChildLayerId, "child",
                                456 /* flags */, mParentLayerId);
 
         // add some layer transaction
@@ -179,7 +181,8 @@
             transaction.states.add(layerState);
             ComposerState childState;
             childState.state.surface = fakeChildLayerHandle;
-            layerState.state.z = 43;
+            childState.state.what = layer_state_t::eLayerChanged;
+            childState.state.z = 43;
             transaction.states.add(childState);
             mTracing->addQueuedTransaction(transaction);
 
@@ -227,6 +230,7 @@
     }
 
     int mParentLayerId = 1;
+    int mChildLayerId = 2;
     int64_t mVsyncId = 0;
     int64_t VSYNC_ID_FIRST_LAYER_CHANGE;
     int64_t VSYNC_ID_SECOND_LAYER_CHANGE;
@@ -244,8 +248,11 @@
     EXPECT_GT(proto.entry().size(), 0);
     EXPECT_GT(proto.entry(0).transactions().size(), 0);
     EXPECT_GT(proto.entry(0).added_layers().size(), 0);
-    EXPECT_GT(proto.entry(0).transactions(0).layer_changes().size(), 0);
+    EXPECT_EQ(proto.entry(0).transactions(0).layer_changes().size(), 2);
+    EXPECT_EQ(proto.entry(0).transactions(0).layer_changes(0).layer_id(), mParentLayerId);
     EXPECT_EQ(proto.entry(0).transactions(0).layer_changes(0).z(), 42);
+    EXPECT_EQ(proto.entry(0).transactions(0).layer_changes(1).layer_id(), mChildLayerId);
+    EXPECT_EQ(proto.entry(0).transactions(0).layer_changes(1).z(), 43);
 }
 
 TEST_F(TransactionTracingLayerHandlingTest, updateStartingState) {
@@ -288,4 +295,69 @@
     EXPECT_EQ(proto.entry(0).transactions(0).layer_changes(0).layer_id(), mParentLayerId);
 }
 
+class TransactionTracingMirrorLayerTest : public TransactionTracingTest {
+protected:
+    void SetUp() override {
+        TransactionTracingTest::SetUp();
+        mTracing->enable();
+        // add layers
+        mTracing->setBufferSize(SMALL_BUFFER_SIZE);
+        const sp<IBinder> fakeLayerHandle = new BBinder();
+        mTracing->onLayerAdded(fakeLayerHandle->localBinder(), mLayerId, "Test Layer",
+                               123 /* flags */, -1 /* parentId */);
+        const sp<IBinder> fakeMirrorLayerHandle = new BBinder();
+        mTracing->onMirrorLayerAdded(fakeMirrorLayerHandle->localBinder(), mMirrorLayerId, "Mirror",
+                                     mLayerId);
+
+        // add some layer transaction
+        {
+            TransactionState transaction;
+            transaction.id = 50;
+            ComposerState layerState;
+            layerState.state.surface = fakeLayerHandle;
+            layerState.state.what = layer_state_t::eLayerChanged;
+            layerState.state.z = 42;
+            transaction.states.add(layerState);
+            ComposerState mirrorState;
+            mirrorState.state.surface = fakeMirrorLayerHandle;
+            mirrorState.state.what = layer_state_t::eLayerChanged;
+            mirrorState.state.z = 43;
+            transaction.states.add(mirrorState);
+            mTracing->addQueuedTransaction(transaction);
+
+            std::vector<TransactionState> transactions;
+            transactions.emplace_back(transaction);
+            mTracing->addCommittedTransactions(transactions, ++mVsyncId);
+            flush(mVsyncId);
+        }
+    }
+
+    void TearDown() override {
+        mTracing->disable();
+        verifyDisabledTracingState();
+        TransactionTracingTest::TearDown();
+    }
+
+    int mLayerId = 5;
+    int mMirrorLayerId = 55;
+    int64_t mVsyncId = 0;
+    int64_t VSYNC_ID_FIRST_LAYER_CHANGE;
+    int64_t VSYNC_ID_SECOND_LAYER_CHANGE;
+    int64_t VSYNC_ID_CHILD_LAYER_REMOVED;
+};
+
+TEST_F(TransactionTracingMirrorLayerTest, canAddMirrorLayers) {
+    proto::TransactionTraceFile proto = writeToProto();
+    // We don't have any starting states since no layer was removed from.
+    EXPECT_EQ(proto.entry().size(), 2);
+    EXPECT_EQ(proto.entry(0).transactions().size(), 0);
+    EXPECT_EQ(proto.entry(0).added_layers().size(), 0);
+
+    // Verify the mirror layer was added
+    EXPECT_EQ(proto.entry(1).transactions().size(), 1);
+    EXPECT_EQ(proto.entry(1).added_layers().size(), 2);
+    EXPECT_EQ(proto.entry(1).added_layers(1).layer_id(), mMirrorLayerId);
+    EXPECT_EQ(proto.entry(1).transactions(0).layer_changes().size(), 2);
+    EXPECT_EQ(proto.entry(1).transactions(0).layer_changes(1).z(), 43);
+}
 } // namespace android
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
index 1ba3c0f..c3250d5 100644
--- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
+++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
@@ -61,7 +61,8 @@
     MOCK_METHOD2(destroyLayer, Error(Display, Layer));
     MOCK_METHOD2(getActiveConfig, Error(Display, Config*));
     MOCK_METHOD3(getChangedCompositionTypes,
-                 Error(Display, std::vector<Layer>*, std::vector<IComposerClient::Composition>*));
+                 Error(Display, std::vector<Layer>*,
+                       std::vector<aidl::android::hardware::graphics::composer3::Composition>*));
     MOCK_METHOD2(getColorModes, Error(Display, std::vector<ColorMode>*));
     MOCK_METHOD4(getDisplayAttribute,
                  Error(Display, Config config, IComposerClient::Attribute, int32_t*));
@@ -95,7 +96,8 @@
                  Error(Display, Layer, const std::vector<IComposerClient::Rect>&));
     MOCK_METHOD3(setLayerBlendMode, Error(Display, Layer, IComposerClient::BlendMode));
     MOCK_METHOD3(setLayerColor, Error(Display, Layer, const IComposerClient::Color&));
-    MOCK_METHOD3(setLayerCompositionType, Error(Display, Layer, IComposerClient::Composition));
+    MOCK_METHOD3(setLayerCompositionType,
+                 Error(Display, Layer, aidl::android::hardware::graphics::composer3::Composition));
     MOCK_METHOD3(setLayerDataspace, Error(Display, Layer, Dataspace));
     MOCK_METHOD3(setLayerPerFrameMetadata,
                  Error(Display, Layer, const std::vector<IComposerClient::PerFrameMetadata>&));
@@ -136,7 +138,9 @@
                              const std::vector<uint8_t>&));
     MOCK_METHOD1(getLayerGenericMetadataKeys,
                  V2_4::Error(std::vector<IComposerClient::LayerGenericMetadataKey>*));
-    MOCK_METHOD2(getClientTargetProperty, Error(Display, IComposerClient::ClientTargetProperty*));
+    MOCK_METHOD3(getClientTargetProperty,
+                 Error(Display, IComposerClient::ClientTargetProperty*, float*));
+    MOCK_METHOD3(setLayerWhitePointNits, Error(Display, Layer, float));
 };
 
 } // namespace Hwc2::mock
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockHWC2.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockHWC2.h
index fe1544e..d4fefee 100644
--- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockHWC2.h
+++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockHWC2.h
@@ -38,7 +38,9 @@
     MOCK_METHOD((base::expected<std::shared_ptr<HWC2::Layer>, hal::Error>), createLayer, (),
                 (override));
     MOCK_METHOD(hal::Error, getChangedCompositionTypes,
-                ((std::unordered_map<Layer *, hal::Composition> *)), (override));
+                ((std::unordered_map<Layer *,
+                                     aidl::android::hardware::graphics::composer3::Composition> *)),
+                (override));
     MOCK_METHOD(hal::Error, getColorModes, (std::vector<hal::ColorMode> *), (const, override));
     MOCK_METHOD(int32_t, getSupportedPerFrameMetadata, (), (const, override));
     MOCK_METHOD(hal::Error, getRenderIntents, (hal::ColorMode, std::vector<hal::RenderIntent> *),
@@ -85,7 +87,8 @@
     MOCK_METHOD(hal::Error, getSupportedContentTypes, (std::vector<hal::ContentType> *),
                 (const, override));
     MOCK_METHOD(hal::Error, setContentType, (hal::ContentType), (override));
-    MOCK_METHOD(hal::Error, getClientTargetProperty, (hal::ClientTargetProperty *), (override));
+    MOCK_METHOD(hal::Error, getClientTargetProperty, (hal::ClientTargetProperty *, float *),
+                (override));
 };
 
 class Layer : public HWC2::Layer {
@@ -102,7 +105,8 @@
     MOCK_METHOD(hal::Error, setSurfaceDamage, (const android::Region &), (override));
     MOCK_METHOD(hal::Error, setBlendMode, (hal::BlendMode), (override));
     MOCK_METHOD(hal::Error, setColor, (hal::Color), (override));
-    MOCK_METHOD(hal::Error, setCompositionType, (hal::Composition), (override));
+    MOCK_METHOD(hal::Error, setCompositionType,
+                (aidl::android::hardware::graphics::composer3::Composition), (override));
     MOCK_METHOD(hal::Error, setDataspace, (android::ui::Dataspace), (override));
     MOCK_METHOD(hal::Error, setPerFrameMetadata, (const int32_t, const android::HdrMetadata &),
                 (override));
@@ -116,6 +120,7 @@
     MOCK_METHOD(hal::Error, setColorTransform, (const android::mat4 &), (override));
     MOCK_METHOD(hal::Error, setLayerGenericMetadata,
                 (const std::string &, bool, const std::vector<uint8_t> &), (override));
+    MOCK_METHOD(hal::Error, setWhitePointNits, (float whitePointNits), (override));
 };
 
 } // namespace android::HWC2::mock
diff --git a/vulkan/libvulkan/debug_report.h b/vulkan/libvulkan/debug_report.h
index e5b1587..416c0bc 100644
--- a/vulkan/libvulkan/debug_report.h
+++ b/vulkan/libvulkan/debug_report.h
@@ -78,8 +78,7 @@
         VkDebugReportCallbackEXT driver_handle;
     };
 
-    // TODO(b/143295577): use std::shared_mutex when available in libc++
-    mutable std::shared_timed_mutex rwmutex_;
+    mutable std::shared_mutex rwmutex_;
     Node head_;
 };
 
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index b5a0bdf..eb4befd 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -23,6 +23,8 @@
 #include <sync/sync.h>
 #include <system/window.h>
 #include <ui/BufferQueueDefs.h>
+#include <ui/DebugUtils.h>
+#include <ui/PixelFormat.h>
 #include <utils/StrongPointer.h>
 #include <utils/Timers.h>
 #include <utils/Trace.h>
@@ -462,21 +464,24 @@
     *count = num_copied;
 }
 
-android_pixel_format GetNativePixelFormat(VkFormat format) {
-    android_pixel_format native_format = HAL_PIXEL_FORMAT_RGBA_8888;
+android::PixelFormat GetNativePixelFormat(VkFormat format) {
+    android::PixelFormat native_format = android::PIXEL_FORMAT_RGBA_8888;
     switch (format) {
         case VK_FORMAT_R8G8B8A8_UNORM:
         case VK_FORMAT_R8G8B8A8_SRGB:
-            native_format = HAL_PIXEL_FORMAT_RGBA_8888;
+            native_format = android::PIXEL_FORMAT_RGBA_8888;
             break;
         case VK_FORMAT_R5G6B5_UNORM_PACK16:
-            native_format = HAL_PIXEL_FORMAT_RGB_565;
+            native_format = android::PIXEL_FORMAT_RGB_565;
             break;
         case VK_FORMAT_R16G16B16A16_SFLOAT:
-            native_format = HAL_PIXEL_FORMAT_RGBA_FP16;
+            native_format = android::PIXEL_FORMAT_RGBA_FP16;
             break;
         case VK_FORMAT_A2B10G10R10_UNORM_PACK32:
-            native_format = HAL_PIXEL_FORMAT_RGBA_1010102;
+            native_format = android::PIXEL_FORMAT_RGBA_1010102;
+            break;
+        case VK_FORMAT_R8_UNORM:
+            native_format = android::PIXEL_FORMAT_R_8;
             break;
         default:
             ALOGV("unsupported swapchain format %d", format);
@@ -758,6 +763,13 @@
         }
     }
 
+    desc.format = AHARDWAREBUFFER_FORMAT_R8_UNORM;
+    if (AHardwareBuffer_isSupported(&desc)) {
+        all_formats.emplace_back(
+            VkSurfaceFormatKHR{VK_FORMAT_R8_UNORM,
+                               VK_COLOR_SPACE_PASS_THROUGH_EXT});
+    }
+
     VkResult result = VK_SUCCESS;
     if (formats) {
         uint32_t transfer_count = all_formats.size();
@@ -1034,7 +1046,7 @@
     if (!allocator)
         allocator = &GetData(device).allocator;
 
-    android_pixel_format native_pixel_format =
+    android::PixelFormat native_pixel_format =
         GetNativePixelFormat(create_info->imageFormat);
     android_dataspace native_dataspace =
         GetNativeDataspace(create_info->imageColorSpace);
@@ -1131,8 +1143,8 @@
 
     err = native_window_set_buffers_format(window, native_pixel_format);
     if (err != android::OK) {
-        ALOGE("native_window_set_buffers_format(%d) failed: %s (%d)",
-              native_pixel_format, strerror(-err), err);
+        ALOGE("native_window_set_buffers_format(%s) failed: %s (%d)",
+              decodePixelFormat(native_pixel_format).c_str(), strerror(-err), err);
         return VK_ERROR_SURFACE_LOST_KHR;
     }
     err = native_window_set_buffers_data_space(window, native_dataspace);