Merge changes I9b4b0d4c,I1faca3aa,I38b538c1,I176c6641 into sc-dev

* changes:
  SF: do not skip validate if it is called more than a vsync earlier
  SF: region sampling scheduling optimization
  SF: return the expected wakeup time from VSyncDispatch
  SurfaceFlinger: previousFrameFence needs to check the current time
diff --git a/cmds/bugreport/OWNERS b/cmds/bugreport/OWNERS
index 2a9b681..5f56531 100644
--- a/cmds/bugreport/OWNERS
+++ b/cmds/bugreport/OWNERS
@@ -1,4 +1,5 @@
 set noparent
 
+gavincorkery@google.com
 nandana@google.com
 jsharkey@android.com
diff --git a/cmds/bugreportz/OWNERS b/cmds/bugreportz/OWNERS
index 2a9b681..5f56531 100644
--- a/cmds/bugreportz/OWNERS
+++ b/cmds/bugreportz/OWNERS
@@ -1,4 +1,5 @@
 set noparent
 
+gavincorkery@google.com
 nandana@google.com
 jsharkey@android.com
diff --git a/cmds/dumpstate/OWNERS b/cmds/dumpstate/OWNERS
index 2a9b681..5f56531 100644
--- a/cmds/dumpstate/OWNERS
+++ b/cmds/dumpstate/OWNERS
@@ -1,4 +1,5 @@
 set noparent
 
+gavincorkery@google.com
 nandana@google.com
 jsharkey@android.com
diff --git a/cmds/dumpsys/OWNERS b/cmds/dumpsys/OWNERS
index 4f6a89e..97a63ca 100644
--- a/cmds/dumpsys/OWNERS
+++ b/cmds/dumpsys/OWNERS
@@ -1,5 +1,6 @@
 set noparent
 
+gavincorkery@google.com
 nandana@google.com
 jsharkey@android.com
 
diff --git a/cmds/installd/OWNERS b/cmds/installd/OWNERS
index fc745d0..d6807ff 100644
--- a/cmds/installd/OWNERS
+++ b/cmds/installd/OWNERS
@@ -9,3 +9,4 @@
 ngeoffray@google.com
 rpl@google.com
 toddke@google.com
+patb@google.com
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
index ef7fd44..18b77e6 100644
--- a/libs/binder/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -366,19 +366,45 @@
 
 pid_t IPCThreadState::getCallingPid() const
 {
+    checkContextIsBinderForUse(__func__);
     return mCallingPid;
 }
 
 const char* IPCThreadState::getCallingSid() const
 {
+    checkContextIsBinderForUse(__func__);
     return mCallingSid;
 }
 
 uid_t IPCThreadState::getCallingUid() const
 {
+    checkContextIsBinderForUse(__func__);
     return mCallingUid;
 }
 
+IPCThreadState::SpGuard* IPCThreadState::pushGetCallingSpGuard(SpGuard* guard) {
+    SpGuard* orig = mServingStackPointerGuard;
+    mServingStackPointerGuard = guard;
+    return orig;
+}
+
+void IPCThreadState::restoreGetCallingSpGuard(SpGuard* guard) {
+    mServingStackPointerGuard = guard;
+}
+
+void IPCThreadState::checkContextIsBinderForUse(const char* use) const {
+    if (mServingStackPointerGuard == nullptr) return;
+
+    if (!mServingStackPointer || mServingStackPointerGuard < mServingStackPointer) {
+        LOG_ALWAYS_FATAL("In context %s, %s does not make sense.",
+                         mServingStackPointerGuard->context, use);
+    }
+
+    // in the case mServingStackPointer is deeper in the stack than the guard,
+    // we must be serving a binder transaction (maybe nested). This is a binder
+    // context, so we don't abort
+}
+
 int64_t IPCThreadState::clearCallingIdentity()
 {
     // ignore mCallingSid for legacy reasons
@@ -847,15 +873,15 @@
 }
 
 IPCThreadState::IPCThreadState()
-    : mProcess(ProcessState::self()),
-      mServingStackPointer(nullptr),
-      mWorkSource(kUnsetWorkSource),
-      mPropagateWorkSource(false),
-      mIsLooper(false),
-      mStrictModePolicy(0),
-      mLastTransactionBinderFlags(0),
-      mCallRestriction(mProcess->mCallRestriction)
-{
+      : mProcess(ProcessState::self()),
+        mServingStackPointer(nullptr),
+        mServingStackPointerGuard(nullptr),
+        mWorkSource(kUnsetWorkSource),
+        mPropagateWorkSource(false),
+        mIsLooper(false),
+        mStrictModePolicy(0),
+        mLastTransactionBinderFlags(0),
+        mCallRestriction(mProcess->mCallRestriction) {
     pthread_setspecific(gTLS, this);
     clearCaller();
     mIn.setDataCapacity(256);
diff --git a/libs/binder/RpcServer.cpp b/libs/binder/RpcServer.cpp
index 3c63789..9cc6e7f 100644
--- a/libs/binder/RpcServer.cpp
+++ b/libs/binder/RpcServer.cpp
@@ -134,7 +134,7 @@
 
 bool RpcServer::acceptOne() {
     LOG_ALWAYS_FATAL_IF(!mAgreedExperimental, "no!");
-    LOG_ALWAYS_FATAL_IF(mServer.get() == -1, "RpcServer must be setup to join.");
+    LOG_ALWAYS_FATAL_IF(!hasServer(), "RpcServer must be setup to join.");
 
     unique_fd clientFd(
             TEMP_FAILURE_RETRY(accept4(mServer.get(), nullptr, nullptr /*length*/, SOCK_CLOEXEC)));
@@ -232,11 +232,7 @@
 
 bool RpcServer::setupSocketServer(const RpcSocketAddress& addr) {
     LOG_RPC_DETAIL("Setting up socket server %s", addr.toString().c_str());
-
-    {
-        std::lock_guard<std::mutex> _l(mLock);
-        LOG_ALWAYS_FATAL_IF(mServer.get() != -1, "Each RpcServer can only have one server.");
-    }
+    LOG_ALWAYS_FATAL_IF(hasServer(), "Each RpcServer can only have one server.");
 
     unique_fd serverFd(
             TEMP_FAILURE_RETRY(socket(addr.addr()->sa_family, SOCK_STREAM | SOCK_CLOEXEC, 0)));
@@ -275,4 +271,27 @@
     (void)mSessions.erase(it);
 }
 
+bool RpcServer::hasServer() {
+    LOG_ALWAYS_FATAL_IF(!mAgreedExperimental, "no!");
+    std::lock_guard<std::mutex> _l(mLock);
+    return mServer.ok();
+}
+
+unique_fd RpcServer::releaseServer() {
+    LOG_ALWAYS_FATAL_IF(!mAgreedExperimental, "no!");
+    std::lock_guard<std::mutex> _l(mLock);
+    return std::move(mServer);
+}
+
+bool RpcServer::setupExternalServer(base::unique_fd serverFd) {
+    LOG_ALWAYS_FATAL_IF(!mAgreedExperimental, "no!");
+    std::lock_guard<std::mutex> _l(mLock);
+    if (mServer.ok()) {
+        ALOGE("Each RpcServer can only have one server.");
+        return false;
+    }
+    mServer = std::move(serverFd);
+    return true;
+}
+
 } // namespace android
diff --git a/libs/binder/RpcState.cpp b/libs/binder/RpcState.cpp
index 2ba9fa2..e5a6026 100644
--- a/libs/binder/RpcState.cpp
+++ b/libs/binder/RpcState.cpp
@@ -18,7 +18,9 @@
 
 #include "RpcState.h"
 
+#include <android-base/scopeguard.h>
 #include <binder/BpBinder.h>
+#include <binder/IPCThreadState.h>
 #include <binder/RpcServer.h>
 
 #include "Debug.h"
@@ -28,6 +30,8 @@
 
 namespace android {
 
+using base::ScopeGuard;
+
 RpcState::RpcState() {}
 RpcState::~RpcState() {}
 
@@ -470,6 +474,18 @@
 
 status_t RpcState::processServerCommand(const base::unique_fd& fd, const sp<RpcSession>& session,
                                         const RpcWireHeader& command) {
+    IPCThreadState* kernelBinderState = IPCThreadState::selfOrNull();
+    IPCThreadState::SpGuard spGuard{"processing binder RPC command"};
+    IPCThreadState::SpGuard* origGuard;
+    if (kernelBinderState != nullptr) {
+        origGuard = kernelBinderState->pushGetCallingSpGuard(&spGuard);
+    }
+    ScopeGuard guardUnguard = [&]() {
+        if (kernelBinderState != nullptr) {
+            kernelBinderState->restoreGetCallingSpGuard(origGuard);
+        }
+    };
+
     switch (command.command) {
         case RPC_COMMAND_TRANSACT:
             return processTransact(fd, session, command);
diff --git a/libs/binder/include/binder/IPCThreadState.h b/libs/binder/include/binder/IPCThreadState.h
index 23a0cb0..5220b62 100644
--- a/libs/binder/include/binder/IPCThreadState.h
+++ b/libs/binder/include/binder/IPCThreadState.h
@@ -81,6 +81,32 @@
              */
             uid_t               getCallingUid() const;
 
+            /**
+             * Make it an abort to rely on getCalling* for a section of
+             * execution.
+             *
+             * Usage:
+             *     IPCThreadState::SpGuard guard { "..." };
+             *     auto* orig = pushGetCallingSpGuard(&guard);
+             *     {
+             *         // will abort if you call getCalling*, unless you are
+             *         // serving a nested binder transaction
+             *     }
+             *     restoreCallingSpGuard(orig);
+             */
+            struct SpGuard {
+                const char* context;
+            };
+            SpGuard* pushGetCallingSpGuard(SpGuard* guard);
+            void restoreGetCallingSpGuard(SpGuard* guard);
+            /**
+             * Used internally by getCalling*. Can also be used to assert that
+             * you are in a binder context (getCalling* is valid). This is
+             * intentionally not exposed as a boolean API since code should be
+             * written to know its environment.
+             */
+            void checkContextIsBinderForUse(const char* use) const;
+
             void                setStrictModePolicy(int32_t policy);
             int32_t             getStrictModePolicy() const;
 
@@ -203,6 +229,7 @@
             Parcel              mOut;
             status_t            mLastError;
             const void*         mServingStackPointer;
+            SpGuard* mServingStackPointerGuard;
             pid_t               mCallingPid;
             const char*         mCallingSid;
             uid_t               mCallingUid;
diff --git a/libs/binder/include/binder/LazyServiceRegistrar.h b/libs/binder/include/binder/LazyServiceRegistrar.h
index 9659732..f3ba830 100644
--- a/libs/binder/include/binder/LazyServiceRegistrar.h
+++ b/libs/binder/include/binder/LazyServiceRegistrar.h
@@ -50,8 +50,12 @@
                               int dumpFlags = IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT);
      /**
       * Force the service to persist, even when it has 0 clients.
-      * If setting this flag from the server side, make sure to do so before calling registerService,
-      * or there may be a race with the default dynamic shutdown.
+      * If setting this flag from the server side, make sure to do so before calling
+      * registerService, or there may be a race with the default dynamic shutdown.
+      *
+      * This should only be used if it is every eventually set to false. If a
+      * service needs to persist but doesn't need to dynamically shut down,
+      * prefer to control it with another mechanism such as ctl.start.
       */
      void forcePersist(bool persist);
 
diff --git a/libs/binder/include/binder/RpcServer.h b/libs/binder/include/binder/RpcServer.h
index 6e27540..8f0c6fd 100644
--- a/libs/binder/include/binder/RpcServer.h
+++ b/libs/binder/include/binder/RpcServer.h
@@ -74,6 +74,22 @@
      */
     [[nodiscard]] bool setupInetServer(unsigned int port, unsigned int* assignedPort);
 
+    /**
+     * If setup*Server has been successful, return true. Otherwise return false.
+     */
+    [[nodiscard]] bool hasServer();
+
+    /**
+     * If hasServer(), return the server FD. Otherwise return invalid FD.
+     */
+    [[nodiscard]] base::unique_fd releaseServer();
+
+    /**
+     * Set up server using an external FD previously set up by releaseServer().
+     * Return false if there's already a server.
+     */
+    bool setupExternalServer(base::unique_fd serverFd);
+
     void iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction();
 
     /**
diff --git a/libs/binder/ndk/include_platform/android/binder_manager.h b/libs/binder/ndk/include_platform/android/binder_manager.h
index a90b4aa..2a66941 100644
--- a/libs/binder/ndk/include_platform/android/binder_manager.h
+++ b/libs/binder/ndk/include_platform/android/binder_manager.h
@@ -35,7 +35,7 @@
  * \return EX_NONE on success.
  */
 __attribute__((warn_unused_result)) binder_exception_t AServiceManager_addService(
-        AIBinder* binder, const char* instance);
+        AIBinder* binder, const char* instance) __INTRODUCED_IN(29);
 
 /**
  * Gets a binder object with this specific instance name. Will return nullptr immediately if the
@@ -47,7 +47,8 @@
  *
  * \param instance identifier of the service used to lookup the service.
  */
-__attribute__((warn_unused_result)) AIBinder* AServiceManager_checkService(const char* instance);
+__attribute__((warn_unused_result)) AIBinder* AServiceManager_checkService(const char* instance)
+        __INTRODUCED_IN(29);
 
 /**
  * Gets a binder object with this specific instance name. Blocks for a couple of seconds waiting on
@@ -59,7 +60,8 @@
  *
  * \param instance identifier of the service used to lookup the service.
  */
-__attribute__((warn_unused_result)) AIBinder* AServiceManager_getService(const char* instance);
+__attribute__((warn_unused_result)) AIBinder* AServiceManager_getService(const char* instance)
+        __INTRODUCED_IN(29);
 
 /**
  * Registers a lazy service with the default service manager under the 'instance' name.
@@ -135,6 +137,10 @@
 /**
  * Prevent lazy services without client from shutting down their process
  *
+ * This should only be used if it is every eventually set to false. If a
+ * service needs to persist but doesn't need to dynamically shut down,
+ * prefer to control it with another mechanism.
+ *
  * \param persist 'true' if the process should not exit.
  */
 void AServiceManager_forceLazyServicesPersist(bool persist) __INTRODUCED_IN(31);
diff --git a/libs/binder/tests/IBinderRpcTest.aidl b/libs/binder/tests/IBinderRpcTest.aidl
index ef4198d..41daccc 100644
--- a/libs/binder/tests/IBinderRpcTest.aidl
+++ b/libs/binder/tests/IBinderRpcTest.aidl
@@ -55,4 +55,6 @@
     oneway void sleepMsAsync(int ms);
 
     void die(boolean cleanup);
+
+    void useKernelBinderCallingId();
 }
diff --git a/libs/binder/tests/binderLibTest.cpp b/libs/binder/tests/binderLibTest.cpp
index 0c3fbcd..45b2776 100644
--- a/libs/binder/tests/binderLibTest.cpp
+++ b/libs/binder/tests/binderLibTest.cpp
@@ -73,6 +73,7 @@
     BINDER_LIB_TEST_REGISTER_SERVER,
     BINDER_LIB_TEST_ADD_SERVER,
     BINDER_LIB_TEST_ADD_POLL_SERVER,
+    BINDER_LIB_TEST_USE_CALLING_GUARD_TRANSACTION,
     BINDER_LIB_TEST_CALL_BACK,
     BINDER_LIB_TEST_CALL_BACK_VERIFY_BUF,
     BINDER_LIB_TEST_DELAYED_CALL_BACK,
@@ -604,6 +605,24 @@
     EXPECT_THAT(callBack->getResult(), StatusEq(NO_ERROR));
 }
 
+TEST_F(BinderLibTest, NoBinderCallContextGuard) {
+    IPCThreadState::SpGuard spGuard{"NoBinderCallContext"};
+    IPCThreadState::SpGuard *origGuard = IPCThreadState::self()->pushGetCallingSpGuard(&spGuard);
+
+    // yes, this test uses threads, but it's careful and uses fork in addServer
+    EXPECT_DEATH({ IPCThreadState::self()->getCallingPid(); },
+                 "In context NoBinderCallContext, getCallingPid does not make sense.");
+
+    IPCThreadState::self()->restoreGetCallingSpGuard(origGuard);
+}
+
+TEST_F(BinderLibTest, BinderCallContextGuard) {
+    sp<IBinder> binder = addServer();
+    Parcel data, reply;
+    EXPECT_THAT(binder->transact(BINDER_LIB_TEST_USE_CALLING_GUARD_TRANSACTION, data, &reply),
+                StatusEq(DEAD_OBJECT));
+}
+
 TEST_F(BinderLibTest, AddServer)
 {
     sp<IBinder> server = addServer();
@@ -1262,6 +1281,18 @@
                 pthread_mutex_unlock(&m_serverWaitMutex);
                 return ret;
             }
+            case BINDER_LIB_TEST_USE_CALLING_GUARD_TRANSACTION: {
+                IPCThreadState::SpGuard spGuard{"GuardInBinderTransaction"};
+                IPCThreadState::SpGuard *origGuard =
+                        IPCThreadState::self()->pushGetCallingSpGuard(&spGuard);
+
+                // if the guard works, this should abort
+                (void)IPCThreadState::self()->getCallingPid();
+
+                IPCThreadState::self()->restoreGetCallingSpGuard(origGuard);
+                return NO_ERROR;
+            }
+
             case BINDER_LIB_TEST_GETPID:
                 reply->writeInt32(getpid());
                 return NO_ERROR;
@@ -1489,6 +1520,11 @@
 {
     binderLibTestServiceName += String16(binderserversuffix);
 
+    // Testing to make sure that calls that we are serving can use getCallin*
+    // even though we don't here.
+    IPCThreadState::SpGuard spGuard{"main server thread"};
+    (void)IPCThreadState::self()->pushGetCallingSpGuard(&spGuard);
+
     status_t ret;
     sp<IServiceManager> sm = defaultServiceManager();
     BinderLibTestService* testServicePtr;
diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp
index 260be57..3f94df2 100644
--- a/libs/binder/tests/binderRpcTest.cpp
+++ b/libs/binder/tests/binderRpcTest.cpp
@@ -23,6 +23,7 @@
 #include <android/binder_libbinder.h>
 #include <binder/Binder.h>
 #include <binder/BpBinder.h>
+#include <binder/IPCThreadState.h>
 #include <binder/IServiceManager.h>
 #include <binder/ProcessState.h>
 #include <binder/RpcServer.h>
@@ -49,6 +50,19 @@
     EXPECT_DEATH(p.markForBinder(sp<BBinder>::make()), "");
 }
 
+TEST(BinderRpc, SetExternalServer) {
+    base::unique_fd sink(TEMP_FAILURE_RETRY(open("/dev/null", O_RDWR)));
+    int sinkFd = sink.get();
+    auto server = RpcServer::make();
+    server->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction();
+    ASSERT_FALSE(server->hasServer());
+    ASSERT_TRUE(server->setupExternalServer(std::move(sink)));
+    ASSERT_TRUE(server->hasServer());
+    base::unique_fd retrieved = server->releaseServer();
+    ASSERT_FALSE(server->hasServer());
+    ASSERT_EQ(sinkFd, retrieved.get());
+}
+
 using android::binder::Status;
 
 #define EXPECT_OK(status)                 \
@@ -178,6 +192,13 @@
             _exit(1);
         }
     }
+    Status useKernelBinderCallingId() override {
+        // this is WRONG! It does not make sense when using RPC binder, and
+        // because it is SO wrong, and so much code calls this, it should abort!
+
+        (void)IPCThreadState::self()->getCallingPid();
+        return Status::ok();
+    }
 };
 sp<IBinder> MyBinderRpcTest::mHeldBinder;
 
@@ -874,6 +895,19 @@
     }
 }
 
+TEST_P(BinderRpc, UseKernelBinderCallingId) {
+    auto proc = createRpcTestSocketServerProcess(1);
+
+    // we can't allocate IPCThreadState so actually the first time should
+    // succeed :(
+    EXPECT_OK(proc.rootIface->useKernelBinderCallingId());
+
+    // second time! we catch the error :)
+    EXPECT_EQ(DEAD_OBJECT, proc.rootIface->useKernelBinderCallingId().transactionError());
+
+    proc.expectInvalid = true;
+}
+
 TEST_P(BinderRpc, WorksWithLibbinderNdkPing) {
     auto proc = createRpcTestSocketServerProcess(1);
 
diff --git a/libs/renderengine/gl/GLESRenderEngine.cpp b/libs/renderengine/gl/GLESRenderEngine.cpp
index 9400037..3c58238 100644
--- a/libs/renderengine/gl/GLESRenderEngine.cpp
+++ b/libs/renderengine/gl/GLESRenderEngine.cpp
@@ -1233,8 +1233,10 @@
             }
         }
 
-        mState.maxMasteringLuminance = layer->source.buffer.maxMasteringLuminance;
-        mState.maxContentLuminance = layer->source.buffer.maxContentLuminance;
+        // Ensure luminance is at least 100 nits to avoid div-by-zero
+        const float maxLuminance = std::max(100.f, layer->source.buffer.maxLuminanceNits);
+        mState.maxMasteringLuminance = maxLuminance;
+        mState.maxContentLuminance = maxLuminance;
         mState.projectionMatrix = projectionMatrix * layer->geometry.positionTransform;
 
         const FloatRect bounds = layer->geometry.boundaries;
diff --git a/libs/renderengine/include/renderengine/DisplaySettings.h b/libs/renderengine/include/renderengine/DisplaySettings.h
index a637796..53fa622 100644
--- a/libs/renderengine/include/renderengine/DisplaySettings.h
+++ b/libs/renderengine/include/renderengine/DisplaySettings.h
@@ -60,6 +60,9 @@
     // capture of a device in landscape while the buffer is in portrait
     // orientation.
     uint32_t orientation = ui::Transform::ROT_0;
+
+    // SDR white point, -1f if unknown
+    float sdrWhitePointNits = -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 6e98352..bfb7465 100644
--- a/libs/renderengine/include/renderengine/LayerSettings.h
+++ b/libs/renderengine/include/renderengine/LayerSettings.h
@@ -64,8 +64,8 @@
 
     // HDR color-space setting for Y410.
     bool isY410BT2020 = false;
-    float maxMasteringLuminance = 0.0;
-    float maxContentLuminance = 0.0;
+
+    float maxLuminanceNits = 0.0;
 };
 
 // Metadata describing the layer geometry.
@@ -175,8 +175,7 @@
             lhs.textureTransform == rhs.textureTransform &&
             lhs.usePremultipliedAlpha == rhs.usePremultipliedAlpha &&
             lhs.isOpaque == rhs.isOpaque && lhs.isY410BT2020 == rhs.isY410BT2020 &&
-            lhs.maxMasteringLuminance == rhs.maxMasteringLuminance &&
-            lhs.maxContentLuminance == rhs.maxContentLuminance;
+            lhs.maxLuminanceNits == rhs.maxLuminanceNits;
 }
 
 static inline bool operator==(const Geometry& lhs, const Geometry& rhs) {
@@ -239,8 +238,7 @@
     *os << "\n    .usePremultipliedAlpha = " << settings.usePremultipliedAlpha;
     *os << "\n    .isOpaque = " << settings.isOpaque;
     *os << "\n    .isY410BT2020 = " << settings.isY410BT2020;
-    *os << "\n    .maxMasteringLuminance = " << settings.maxMasteringLuminance;
-    *os << "\n    .maxContentLuminance = " << settings.maxContentLuminance;
+    *os << "\n    .maxLuminanceNits = " << settings.maxLuminanceNits;
     *os << "\n}";
 }
 
diff --git a/libs/renderengine/skia/Cache.cpp b/libs/renderengine/skia/Cache.cpp
index 48d76cc..0eee564 100644
--- a/libs/renderengine/skia/Cache.cpp
+++ b/libs/renderengine/skia/Cache.cpp
@@ -108,8 +108,7 @@
             .source = PixelSource{.buffer =
                                           Buffer{
                                                   .buffer = srcTexture,
-                                                  .maxMasteringLuminance = 1000.f,
-                                                  .maxContentLuminance = 1000.f,
+                                                  .maxLuminanceNits = 1000.f,
                                           }},
     };
 
@@ -205,8 +204,7 @@
             .source = PixelSource{.buffer =
                                           Buffer{
                                                   .buffer = srcTexture,
-                                                  .maxMasteringLuminance = 1000.f,
-                                                  .maxContentLuminance = 1000.f,
+                                                  .maxLuminanceNits = 1000.f,
                                                   .textureTransform = kScaleYOnly,
                                           }},
             .sourceDataspace = kOtherDataSpace,
diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.cpp b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
index 6d2af4a..05bbc12 100644
--- a/libs/renderengine/skia/SkiaGLRenderEngine.cpp
+++ b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
@@ -590,10 +590,14 @@
         } 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,
-                                        layer->source.buffer.maxMasteringLuminance,
-                                        layer->source.buffer.maxContentLuminance);
+                                        display.maxLuminance, maxLuminance);
     }
     return shader;
 }
@@ -904,7 +908,9 @@
 
         const bool requiresLinearEffect = layer->colorTransform != mat4() ||
                 (mUseColorManagement &&
-                 needsToneMapping(layer->sourceDataspace, display.outputDataspace));
+                 needsToneMapping(layer->sourceDataspace, display.outputDataspace)) ||
+                (display.sdrWhitePointNits > 0.f &&
+                 display.sdrWhitePointNits != display.maxLuminance);
 
         // quick abort from drawing the remaining portion of the layer
         if (layer->alpha == 0 && !requiresLinearEffect && !layer->disableBlending &&
diff --git a/libs/renderengine/skia/filters/LinearEffect.cpp b/libs/renderengine/skia/filters/LinearEffect.cpp
index 0fbd669..9b044e1 100644
--- a/libs/renderengine/skia/filters/LinearEffect.cpp
+++ b/libs/renderengine/skia/filters/LinearEffect.cpp
@@ -127,7 +127,7 @@
         default:
             shader.append(R"(
                     float3 ScaleLuminance(float3 xyz) {
-                        return xyz * in_displayMaxLuminance;
+                        return xyz * in_inputMaxLuminance;
                     }
                 )");
             break;
@@ -448,7 +448,7 @@
 sk_sp<SkShader> createLinearEffectShader(sk_sp<SkShader> shader, const LinearEffect& linearEffect,
                                          sk_sp<SkRuntimeEffect> runtimeEffect,
                                          const mat4& colorTransform, float maxDisplayLuminance,
-                                         float maxMasteringLuminance, float maxContentLuminance) {
+                                         float maxLuminance) {
     ATRACE_CALL();
     SkRuntimeShaderBuilder effectBuilder(runtimeEffect);
 
@@ -467,8 +467,10 @@
     }
 
     effectBuilder.uniform("in_displayMaxLuminance") = maxDisplayLuminance;
+    // If the input luminance is unknown, use display luminance (aka, no-op any luminance changes)
+    // This will be the case for eg screenshots in addition to uncalibrated displays
     effectBuilder.uniform("in_inputMaxLuminance") =
-            std::min(maxMasteringLuminance, maxContentLuminance);
+            maxLuminance > 0 ? maxLuminance : maxDisplayLuminance;
     return effectBuilder.makeShader(nullptr, false);
 }
 
diff --git a/libs/renderengine/skia/filters/LinearEffect.h b/libs/renderengine/skia/filters/LinearEffect.h
index 20b8338..9e989ea 100644
--- a/libs/renderengine/skia/filters/LinearEffect.h
+++ b/libs/renderengine/skia/filters/LinearEffect.h
@@ -98,7 +98,7 @@
                                          const LinearEffect& linearEffect,
                                          sk_sp<SkRuntimeEffect> runtimeEffect,
                                          const mat4& colorTransform, float maxDisplayLuminance,
-                                         float maxMasteringLuminance, float maxContentLuminance);
+                                         float maxLuminance);
 } // namespace skia
 } // namespace renderengine
 } // namespace android
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index 4c73b6e..cacad52 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -58,8 +58,7 @@
 
 namespace android {
 
-static constexpr float defaultMaxMasteringLuminance = 1000.0;
-static constexpr float defaultMaxContentLuminance = 1000.0;
+static constexpr float defaultMaxLuminance = 1000.0;
 
 BufferLayer::BufferLayer(const LayerCreationArgs& args)
       : Layer(args),
@@ -206,12 +205,24 @@
     layer.source.buffer.isY410BT2020 = isHdrY410();
     bool hasSmpte2086 = mBufferInfo.mHdrMetadata.validTypes & HdrMetadata::SMPTE2086;
     bool hasCta861_3 = mBufferInfo.mHdrMetadata.validTypes & HdrMetadata::CTA861_3;
-    layer.source.buffer.maxMasteringLuminance = hasSmpte2086
-            ? mBufferInfo.mHdrMetadata.smpte2086.maxLuminance
-            : defaultMaxMasteringLuminance;
-    layer.source.buffer.maxContentLuminance = hasCta861_3
-            ? mBufferInfo.mHdrMetadata.cta8613.maxContentLightLevel
-            : defaultMaxContentLuminance;
+    float maxLuminance = 0.f;
+    if (hasSmpte2086 && hasCta861_3) {
+        maxLuminance = std::min(mBufferInfo.mHdrMetadata.smpte2086.maxLuminance,
+                                mBufferInfo.mHdrMetadata.cta8613.maxContentLightLevel);
+    } else if (hasSmpte2086) {
+        maxLuminance = mBufferInfo.mHdrMetadata.smpte2086.maxLuminance;
+    } else if (hasCta861_3) {
+        maxLuminance = mBufferInfo.mHdrMetadata.cta8613.maxContentLightLevel;
+    } else {
+        switch (layer.sourceDataspace & HAL_DATASPACE_TRANSFER_MASK) {
+            case HAL_DATASPACE_TRANSFER_ST2084:
+            case HAL_DATASPACE_TRANSFER_HLG:
+                // Behavior-match previous releases for HDR content
+                maxLuminance = defaultMaxLuminance;
+                break;
+        }
+    }
+    layer.source.buffer.maxLuminanceNits = maxLuminance;
     layer.frameNumber = mCurrentFrameNumber;
     layer.bufferId = mBufferInfo.mBuffer ? mBufferInfo.mBuffer->getBuffer()->getId() : 0;
 
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
index 9fba7aa..257974f 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
@@ -184,6 +184,9 @@
     // Sets the output color mode
     virtual void setColorProfile(const ColorProfile&) = 0;
 
+    // Sets current calibrated display brightness information
+    virtual void setDisplayBrightness(float sdrWhitePointNits, float displayBrightnessNits) = 0;
+
     // Outputs a string with a state dump
     virtual void dump(std::string&) const = 0;
 
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
index 2893c3f..f10ff25 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
@@ -49,6 +49,7 @@
 
     void setColorTransform(const compositionengine::CompositionRefreshArgs&) override;
     void setColorProfile(const ColorProfile&) override;
+    void setDisplayBrightness(float sdrWhitePointNits, float displayBrightnessNits) override;
 
     void dump(std::string&) const override;
     void dumpPlannerInfo(const Vector<String16>& args, std::string&) const override;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h
index f0ef6d6..d41c2dd 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h
@@ -118,6 +118,12 @@
     // The earliest time to send the present command to the HAL
     std::chrono::steady_clock::time_point earliestPresentTime;
 
+    // Current display brightness
+    float displayBrightnessNits{-1.f};
+
+    // SDR white point
+    float sdrWhitePointNits{-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 2488c66..2ffd472 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h
@@ -78,9 +78,10 @@
     void writeSidebandStateToHWC(HWC2::Layer*, const LayerFECompositionState&);
     void writeBufferStateToHWC(HWC2::Layer*, const LayerFECompositionState&);
     void writeCompositionTypeToHWC(HWC2::Layer*, Hwc2::IComposerClient::Composition,
-                                   bool isPeekingThrough);
+                                   bool isPeekingThrough, bool skipLayer);
     void detectDisallowedCompositionTypeChange(Hwc2::IComposerClient::Composition from,
                                                Hwc2::IComposerClient::Composition to) const;
+    bool isClientCompositionForced(bool isPeekingThrough) const;
 };
 
 // This template factory function standardizes the implementation details of the
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h
index b98043b..3f670a1 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h
@@ -125,6 +125,9 @@
 
         // Set to true when overridden info has been sent to HW composer
         bool stateOverridden = false;
+
+        // True when this layer was skipped as part of SF-side layer caching.
+        bool layerSkipped = false;
     };
 
     // The HWC state is optional, and is only set up if there is any potential
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h
index 749675d..4b4d375 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h
@@ -44,6 +44,7 @@
 
     MOCK_METHOD1(setColorTransform, void(const compositionengine::CompositionRefreshArgs&));
     MOCK_METHOD1(setColorProfile, void(const ColorProfile&));
+    MOCK_METHOD2(setDisplayBrightness, void(float, float));
 
     MOCK_CONST_METHOD1(dump, void(std::string&));
     MOCK_CONST_METHOD2(dumpPlannerInfo, void(const Vector<String16>&, std::string&));
diff --git a/services/surfaceflinger/CompositionEngine/src/ClientCompositionRequestCache.cpp b/services/surfaceflinger/CompositionEngine/src/ClientCompositionRequestCache.cpp
index b1ee3fb..7e020ee 100644
--- a/services/surfaceflinger/CompositionEngine/src/ClientCompositionRequestCache.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/ClientCompositionRequestCache.cpp
@@ -46,8 +46,7 @@
             lhs.textureTransform == rhs.textureTransform &&
             lhs.usePremultipliedAlpha == rhs.usePremultipliedAlpha &&
             lhs.isOpaque == rhs.isOpaque && lhs.isY410BT2020 == rhs.isY410BT2020 &&
-            lhs.maxMasteringLuminance == rhs.maxMasteringLuminance &&
-            lhs.maxContentLuminance == rhs.maxContentLuminance;
+            lhs.maxLuminanceNits == rhs.maxLuminanceNits;
 }
 
 inline bool equalIgnoringBuffer(const renderengine::LayerSettings& lhs,
diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp
index 796fe7d..bf36355 100644
--- a/services/surfaceflinger/CompositionEngine/src/Output.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp
@@ -259,6 +259,18 @@
     dirtyEntireOutput();
 }
 
+void Output::setDisplayBrightness(float sdrWhitePointNits, float displayBrightnessNits) {
+    auto& outputState = editState();
+    if (outputState.sdrWhitePointNits == sdrWhitePointNits &&
+        outputState.displayBrightnessNits == displayBrightnessNits) {
+        // Nothing changed
+        return;
+    }
+    outputState.sdrWhitePointNits = sdrWhitePointNits;
+    outputState.displayBrightnessNits = displayBrightnessNits;
+    dirtyEntireOutput();
+}
+
 void Output::dump(std::string& out) const {
     using android::base::StringAppendF;
 
@@ -1035,8 +1047,13 @@
     clientCompositionDisplay.outputDataspace = mDisplayColorProfile->hasWideColorGamut()
             ? outputState.dataspace
             : ui::Dataspace::UNKNOWN;
-    clientCompositionDisplay.maxLuminance =
-            mDisplayColorProfile->getHdrCapabilities().getDesiredMaxLuminance();
+
+    // If we have a valid current display brightness use that, otherwise fall back to the
+    // display's max desired
+    clientCompositionDisplay.maxLuminance = outputState.displayBrightnessNits > 0.f
+            ? outputState.displayBrightnessNits
+            : mDisplayColorProfile->getHdrCapabilities().getDesiredMaxLuminance();
+    clientCompositionDisplay.sdrWhitePointNits = outputState.sdrWhitePointNits;
 
     // Compute the global color transform matrix.
     if (!outputState.usesDeviceComposition && !getSkipColorTransform()) {
diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
index 01da070..cd14327 100644
--- a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <DisplayHardware/Hal.h>
 #include <android-base/stringprintf.h>
 #include <compositionengine/DisplayColorProfile.h>
 #include <compositionengine/LayerFECompositionState.h>
@@ -350,12 +351,14 @@
     writeOutputDependentPerFrameStateToHWC(hwcLayer.get());
     writeOutputIndependentPerFrameStateToHWC(hwcLayer.get(), *outputIndependentState);
 
-    writeCompositionTypeToHWC(hwcLayer.get(), requestedCompositionType, isPeekingThrough);
+    writeCompositionTypeToHWC(hwcLayer.get(), requestedCompositionType, isPeekingThrough,
+                              skipLayer);
 
     // Always set the layer color after setting the composition type.
     writeSolidColorStateToHWC(hwcLayer.get(), *outputIndependentState);
 
     editState().hwc->stateOverridden = isOverridden;
+    editState().hwc->layerSkipped = skipLayer;
 }
 
 void OutputLayer::writeOutputDependentGeometryStateToHWC(HWC2::Layer* hwcLayer,
@@ -482,7 +485,8 @@
 
     const Region& surfaceDamage = getState().overrideInfo.buffer
             ? getState().overrideInfo.damageRegion
-            : outputIndependentState.surfaceDamage;
+            : (getState().hwc->stateOverridden ? Region::INVALID_REGION
+                                               : outputIndependentState.surfaceDamage);
 
     if (auto error = hwcLayer->setSurfaceDamage(surfaceDamage); error != hal::Error::NONE) {
         ALOGE("[%s] Failed to set surface damage: %s (%d)", getLayerFE().getDebugName(),
@@ -573,17 +577,19 @@
 
 void OutputLayer::writeCompositionTypeToHWC(HWC2::Layer* hwcLayer,
                                             hal::Composition requestedCompositionType,
-                                            bool isPeekingThrough) {
+                                            bool isPeekingThrough, bool skipLayer) {
     auto& outputDependentState = editState();
 
-    // If we are forcing client composition, we need to tell the HWC
-    if (outputDependentState.forceClientComposition ||
-        (!isPeekingThrough && getLayerFE().hasRoundedCorners())) {
+    if (isClientCompositionForced(isPeekingThrough)) {
+        // If we are forcing client composition, we need to tell the HWC
         requestedCompositionType = hal::Composition::CLIENT;
     }
 
     // Set the requested composition type with the HWC whenever it changes
-    if (outputDependentState.hwc->hwcCompositionType != requestedCompositionType) {
+    // We also resend the composition type when this layer was previously skipped, to ensure that
+    // the composition type is up-to-date.
+    if (outputDependentState.hwc->hwcCompositionType != requestedCompositionType ||
+        (outputDependentState.hwc->layerSkipped && !skipLayer)) {
         outputDependentState.hwc->hwcCompositionType = requestedCompositionType;
 
         if (auto error = hwcLayer->setCompositionType(requestedCompositionType);
@@ -663,12 +669,22 @@
     }
 }
 
+bool OutputLayer::isClientCompositionForced(bool isPeekingThrough) const {
+    return getState().forceClientComposition ||
+            (!isPeekingThrough && getLayerFE().hasRoundedCorners());
+}
+
 void OutputLayer::applyDeviceCompositionTypeChange(hal::Composition compositionType) {
     auto& state = editState();
     LOG_FATAL_IF(!state.hwc);
     auto& hwcState = *state.hwc;
 
-    detectDisallowedCompositionTypeChange(hwcState.hwcCompositionType, compositionType);
+    // Only detected disallowed changes if this was not a skip layer, because the
+    // validated composition type may be arbitrary (usually DEVICE, to reflect that there were
+    // fewer GPU layers)
+    if (!hwcState.layerSkipped) {
+        detectDisallowedCompositionTypeChange(hwcState.hwcCompositionType, compositionType);
+    }
 
     hwcState.hwcCompositionType = compositionType;
 }
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
index 3adfe40..5bd1216 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
@@ -1065,12 +1065,62 @@
                               kOverrideSurfaceDamage);
     expectSetHdrMetadataAndBufferCalls(kOverrideHwcSlot, kOverrideBuffer, kOverrideFence);
     expectSetCompositionTypeCall(Hwc2::IComposerClient::Composition::DEVICE);
+    EXPECT_CALL(*mLayerFE, hasRoundedCorners()).WillRepeatedly(Return(false));
+
+    mOutputLayer.writeStateToHWC(/*includeGeometry*/ true, /*skipLayer*/ false, 0,
+                                 /*zIsOverridden*/ false, /*isPeekingThrough*/ false);
+}
+
+TEST_F(OutputLayerWriteStateToHWCTest, previousOverriddenLayerSendsSurfaceDamage) {
+    mLayerFEState.compositionType = Hwc2::IComposerClient::Composition::DEVICE;
+    mOutputLayer.editState().hwc->stateOverridden = true;
+
+    expectGeometryCommonCalls();
+    expectPerFrameCommonCalls(SimulateUnsupported::None, kDataspace, kOutputSpaceVisibleRegion,
+                              Region::INVALID_REGION);
+    expectSetHdrMetadataAndBufferCalls();
+    expectSetCompositionTypeCall(Hwc2::IComposerClient::Composition::DEVICE);
+    EXPECT_CALL(*mLayerFE, hasRoundedCorners()).WillRepeatedly(Return(false));
+
+    mOutputLayer.writeStateToHWC(/*includeGeometry*/ true, /*skipLayer*/ false, 0,
+                                 /*zIsOverridden*/ false, /*isPeekingThrough*/ false);
+}
+
+TEST_F(OutputLayerWriteStateToHWCTest, previousSkipLayerSendsUpdatedDeviceCompositionInfo) {
+    mLayerFEState.compositionType = Hwc2::IComposerClient::Composition::DEVICE;
+    mOutputLayer.editState().hwc->stateOverridden = true;
+    mOutputLayer.editState().hwc->layerSkipped = true;
+    mOutputLayer.editState().hwc->hwcCompositionType = Hwc2::IComposerClient::Composition::DEVICE;
+
+    expectGeometryCommonCalls();
+    expectPerFrameCommonCalls(SimulateUnsupported::None, kDataspace, kOutputSpaceVisibleRegion,
+                              Region::INVALID_REGION);
+    expectSetHdrMetadataAndBufferCalls();
+    expectSetCompositionTypeCall(Hwc2::IComposerClient::Composition::DEVICE);
     EXPECT_CALL(*mLayerFE, hasRoundedCorners()).WillOnce(Return(false));
 
     mOutputLayer.writeStateToHWC(/*includeGeometry*/ true, /*skipLayer*/ false, 0,
                                  /*zIsOverridden*/ false, /*isPeekingThrough*/ false);
 }
 
+TEST_F(OutputLayerWriteStateToHWCTest, previousSkipLayerSendsUpdatedClientCompositionInfo) {
+    mLayerFEState.compositionType = Hwc2::IComposerClient::Composition::DEVICE;
+    mOutputLayer.editState().forceClientComposition = true;
+    mOutputLayer.editState().hwc->stateOverridden = true;
+    mOutputLayer.editState().hwc->layerSkipped = true;
+    mOutputLayer.editState().hwc->hwcCompositionType = Hwc2::IComposerClient::Composition::CLIENT;
+
+    expectGeometryCommonCalls();
+    expectPerFrameCommonCalls(SimulateUnsupported::None, kDataspace, kOutputSpaceVisibleRegion,
+                              Region::INVALID_REGION);
+    expectSetHdrMetadataAndBufferCalls();
+    expectSetCompositionTypeCall(Hwc2::IComposerClient::Composition::CLIENT);
+    EXPECT_CALL(*mLayerFE, hasRoundedCorners()).WillRepeatedly(Return(false));
+
+    mOutputLayer.writeStateToHWC(/*includeGeometry*/ true, /*skipLayer*/ false, 0,
+                                 /*zIsOverridden*/ false, /*isPeekingThrough*/ false);
+}
+
 TEST_F(OutputLayerWriteStateToHWCTest, peekThroughChangesBlendMode) {
     auto peekThroughLayerFE = sp<compositionengine::mock::LayerFE>::make();
     OutputLayer peekThroughLayer{mOutput, peekThroughLayerFE};
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 4fee723..7713749 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -221,7 +221,10 @@
 }
 
 void Layer::removeFromCurrentState() {
-    mRemovedFromCurrentState = true;
+    if (!mRemovedFromCurrentState) {
+        mRemovedFromCurrentState = true;
+        mFlinger->mScheduler->deregisterLayer(this);
+    }
 
     mFlinger->markLayerPendingRemovalLocked(this);
 }
@@ -246,7 +249,10 @@
 }
 
 void Layer::addToCurrentState() {
-    mRemovedFromCurrentState = false;
+    if (mRemovedFromCurrentState) {
+        mRemovedFromCurrentState = false;
+        mFlinger->mScheduler->registerLayer(this);
+    }
 
     for (const auto& child : mCurrentChildren) {
         child->addToCurrentState();
diff --git a/services/surfaceflinger/Scheduler/LayerHistory.cpp b/services/surfaceflinger/Scheduler/LayerHistory.cpp
index f4bc2a1..0563795 100644
--- a/services/surfaceflinger/Scheduler/LayerHistory.cpp
+++ b/services/surfaceflinger/Scheduler/LayerHistory.cpp
@@ -84,8 +84,11 @@
 LayerHistory::~LayerHistory() = default;
 
 void LayerHistory::registerLayer(Layer* layer, LayerVoteType type) {
-    auto info = std::make_unique<LayerInfo>(layer->getName(), layer->getOwnerUid(), type);
     std::lock_guard lock(mLock);
+    for (const auto& info : mLayerInfos) {
+        LOG_ALWAYS_FATAL_IF(info.first == layer, "%s already registered", layer->getName().c_str());
+    }
+    auto info = std::make_unique<LayerInfo>(layer->getName(), layer->getOwnerUid(), type);
     mLayerInfos.emplace_back(layer, std::move(info));
 }
 
@@ -94,7 +97,7 @@
 
     const auto it = std::find_if(mLayerInfos.begin(), mLayerInfos.end(),
                                  [layer](const auto& pair) { return pair.first == layer; });
-    LOG_FATAL_IF(it == mLayerInfos.end(), "%s: unknown layer %p", __FUNCTION__, layer);
+    LOG_ALWAYS_FATAL_IF(it == mLayerInfos.end(), "%s: unknown layer %p", __FUNCTION__, layer);
 
     const size_t i = static_cast<size_t>(it - mLayerInfos.begin());
     if (i < mActiveLayersEnd) {
@@ -111,7 +114,11 @@
 
     const auto it = std::find_if(mLayerInfos.begin(), mLayerInfos.end(),
                                  [layer](const auto& pair) { return pair.first == layer; });
-    LOG_FATAL_IF(it == mLayerInfos.end(), "%s: unknown layer %p", __FUNCTION__, layer);
+    if (it == mLayerInfos.end()) {
+        // Offscreen layer
+        ALOGV("LayerHistory::record: %s not registered", layer->getName().c_str());
+        return;
+    }
 
     const auto& info = it->second;
     const auto layerProps = LayerInfo::LayerProps{
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 41aacc0..a5b7107 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -287,6 +287,8 @@
 const String16 sReadFramebuffer("android.permission.READ_FRAME_BUFFER");
 const String16 sControlDisplayBrightness("android.permission.CONTROL_DISPLAY_BRIGHTNESS");
 const String16 sDump("android.permission.DUMP");
+const String16 sCaptureBlackoutContent("android.permission.CAPTURE_BLACKOUT_CONTENT");
+
 const char* KERNEL_IDLE_TIMER_PROP = "graphics.display.kernel_idle_timer.enabled";
 
 // ---------------------------------------------------------------------------
@@ -306,6 +308,7 @@
 Dataspace SurfaceFlinger::wideColorGamutCompositionDataspace = Dataspace::V0_SRGB;
 ui::PixelFormat SurfaceFlinger::wideColorGamutCompositionPixelFormat = ui::PixelFormat::RGBA_8888;
 bool SurfaceFlinger::useFrameRateApi;
+bool SurfaceFlinger::enableSdrDimming;
 
 std::string decodeDisplayColorSetting(DisplayColorSetting displayColorSetting) {
     switch(displayColorSetting) {
@@ -477,6 +480,9 @@
     base::SetProperty(KERNEL_IDLE_TIMER_PROP, mKernelIdleTimerEnabled ? "true" : "false");
 
     mRefreshRateOverlaySpinner = property_get_bool("sf.debug.show_refresh_rate_overlay_spinner", 0);
+
+    // Debug property overrides ro. property
+    enableSdrDimming = property_get_bool("debug.sf.enable_sdr_dimming", enable_sdr_dimming(false));
 }
 
 SurfaceFlinger::~SurfaceFlinger() = default;
@@ -1486,8 +1492,13 @@
     }
 
     return ftl::chain(schedule([=]() MAIN_THREAD {
-               if (const auto displayId = getPhysicalDisplayIdLocked(displayToken)) {
-                   return getHwComposer().setDisplayBrightness(*displayId,
+               if (const auto display = getDisplayDeviceLocked(displayToken)) {
+                   if (enableSdrDimming) {
+                       display->getCompositionDisplay()
+                               ->setDisplayBrightness(brightness.sdrWhitePointNits,
+                                                      brightness.displayBrightnessNits);
+                   }
+                   return getHwComposer().setDisplayBrightness(display->getPhysicalId(),
                                                                brightness.displayBrightness);
                } else {
                    ALOGE("%s: Invalid display token %p", __FUNCTION__, displayToken.get());
@@ -2197,20 +2208,10 @@
         mDrawingState.traverse([&, compositionDisplay = compositionDisplay](Layer* layer) {
             if (layer->isVisible() &&
                 compositionDisplay->belongsInOutput(layer->getCompositionEngineLayerFE())) {
-                bool isHdr = false;
-                switch (layer->getDataSpace()) {
-                    case ui::Dataspace::BT2020:
-                    case ui::Dataspace::BT2020_HLG:
-                    case ui::Dataspace::BT2020_PQ:
-                    case ui::Dataspace::BT2020_ITU:
-                    case ui::Dataspace::BT2020_ITU_HLG:
-                    case ui::Dataspace::BT2020_ITU_PQ:
-                        isHdr = true;
-                        break;
-                    default:
-                        isHdr = false;
-                        break;
-                }
+                const Dataspace transfer =
+                        static_cast<Dataspace>(layer->getDataSpace() & Dataspace::TRANSFER_MASK);
+                const bool isHdr = (transfer == Dataspace::TRANSFER_ST2084 ||
+                                    transfer == Dataspace::TRANSFER_HLG);
 
                 if (isHdr) {
                     info.numberOfHdrLayers++;
@@ -5714,6 +5715,14 @@
     }
 }
 
+static bool hasCaptureBlackoutContentPermission() {
+    IPCThreadState* ipc = IPCThreadState::self();
+    const int pid = ipc->getCallingPid();
+    const int uid = ipc->getCallingUid();
+    return uid == AID_GRAPHICS || uid == AID_SYSTEM ||
+            PermissionCache::checkPermission(sCaptureBlackoutContent, pid, uid);
+}
+
 static status_t validateScreenshotPermissions(const CaptureArgs& captureArgs) {
     IPCThreadState* ipc = IPCThreadState::self();
     const int pid = ipc->getCallingPid();
@@ -5884,6 +5893,10 @@
     Rect layerStackSpaceRect;
     ui::Dataspace dataspace;
     bool captureSecureLayers;
+
+    // Call this before holding mStateLock to avoid any deadlocking.
+    bool canCaptureBlackoutContent = hasCaptureBlackoutContentPermission();
+
     {
         Mutex::Autolock lock(mStateLock);
 
@@ -5893,9 +5906,8 @@
             return NAME_NOT_FOUND;
         }
 
-        const int uid = IPCThreadState::self()->getCallingUid();
-        const bool forSystem = uid == AID_GRAPHICS || uid == AID_SYSTEM;
-        if (!forSystem && parent->getCurrentState().flags & layer_state_t::eLayerSecure) {
+        if (!canCaptureBlackoutContent &&
+            parent->getCurrentState().flags & layer_state_t::eLayerSecure) {
             ALOGW("Attempting to capture secure layer: PERMISSION_DENIED");
             return PERMISSION_DENIED;
         }
@@ -6045,8 +6057,7 @@
         return BAD_VALUE;
     }
 
-    const int uid = IPCThreadState::self()->getCallingUid();
-    const bool forSystem = uid == AID_GRAPHICS || uid == AID_SYSTEM;
+    bool canCaptureBlackoutContent = hasCaptureBlackoutContentPermission();
 
     static_cast<void>(schedule([=, renderAreaFuture = std::move(renderAreaFuture)]() mutable {
         if (mRefreshPending) {
@@ -6066,8 +6077,9 @@
 
         status_t result = NO_ERROR;
         renderArea->render([&] {
-            result = renderScreenImplLocked(*renderArea, traverseLayers, buffer, forSystem,
-                                            regionSampling, grayscale, captureResults);
+            result = renderScreenImplLocked(*renderArea, traverseLayers, buffer,
+                                            canCaptureBlackoutContent, regionSampling, grayscale,
+                                            captureResults);
         });
 
         captureResults.result = result;
@@ -6079,8 +6091,9 @@
 
 status_t SurfaceFlinger::renderScreenImplLocked(
         const RenderArea& renderArea, TraverseLayersFunction traverseLayers,
-        const std::shared_ptr<renderengine::ExternalTexture>& buffer, bool forSystem,
-        bool regionSampling, bool grayscale, ScreenCaptureResults& captureResults) {
+        const std::shared_ptr<renderengine::ExternalTexture>& buffer,
+        bool canCaptureBlackoutContent, bool regionSampling, bool grayscale,
+        ScreenCaptureResults& captureResults) {
     ATRACE_CALL();
 
     traverseLayers([&](Layer* layer) {
@@ -6093,7 +6106,7 @@
     // We allow the system server to take screenshots of secure layers for
     // use in situations like the Screen-rotation animation and place
     // the impetus on WindowManager to not persist them.
-    if (captureResults.capturedSecureLayers && !forSystem) {
+    if (captureResults.capturedSecureLayers && !canCaptureBlackoutContent) {
         ALOGW("FB is protected: PERMISSION_DENIED");
         return PERMISSION_DENIED;
     }
@@ -6433,13 +6446,17 @@
 
 void SurfaceFlinger::onLayerFirstRef(Layer* layer) {
     mNumLayers++;
-    mScheduler->registerLayer(layer);
+    if (!layer->isRemovedFromCurrentState()) {
+        mScheduler->registerLayer(layer);
+    }
 }
 
 void SurfaceFlinger::onLayerDestroyed(Layer* layer) {
-    mScheduler->deregisterLayer(layer);
     mNumLayers--;
     removeFromOffscreenLayers(layer);
+    if (!layer->isRemovedFromCurrentState()) {
+        mScheduler->deregisterLayer(layer);
+    }
 }
 
 // WARNING: ONLY CALL THIS FROM LAYER DTOR
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index ea40cb5..cb8d312 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -271,6 +271,10 @@
 
     static constexpr SkipInitializationTag SkipInitialization;
 
+    // Whether or not SDR layers should be dimmed to the desired SDR white point instead of
+    // being treated as native display brightness
+    static bool enableSdrDimming;
+
     // must be called before clients can connect
     void init() ANDROID_API;
 
@@ -911,8 +915,8 @@
                                  const sp<IScreenCaptureListener>&);
     status_t renderScreenImplLocked(const RenderArea&, TraverseLayersFunction,
                                     const std::shared_ptr<renderengine::ExternalTexture>&,
-                                    bool forSystem, bool regionSampling, bool grayscale,
-                                    ScreenCaptureResults&);
+                                    bool canCaptureBlackoutContent, bool regionSampling,
+                                    bool grayscale, ScreenCaptureResults&);
 
     sp<DisplayDevice> getDisplayByIdOrLayerStack(uint64_t displayOrLayerStack) REQUIRES(mStateLock);
     sp<DisplayDevice> getDisplayById(DisplayId displayId) const REQUIRES(mStateLock);
diff --git a/services/surfaceflinger/SurfaceFlingerProperties.cpp b/services/surfaceflinger/SurfaceFlingerProperties.cpp
index b3dca78..4a69c8f 100644
--- a/services/surfaceflinger/SurfaceFlingerProperties.cpp
+++ b/services/surfaceflinger/SurfaceFlingerProperties.cpp
@@ -321,6 +321,10 @@
     return defaultValue;
 }
 
+bool enable_sdr_dimming(bool defaultValue) {
+    return SurfaceFlingerProperties::enable_sdr_dimming().value_or(defaultValue);
+}
+
 int32_t display_update_imminent_timeout_ms(int32_t defaultValue) {
     auto temp = SurfaceFlingerProperties::display_update_imminent_timeout_ms();
     if (temp.has_value()) {
diff --git a/services/surfaceflinger/SurfaceFlingerProperties.h b/services/surfaceflinger/SurfaceFlingerProperties.h
index b19d216..039d316 100644
--- a/services/surfaceflinger/SurfaceFlingerProperties.h
+++ b/services/surfaceflinger/SurfaceFlingerProperties.h
@@ -102,6 +102,8 @@
 
 bool enable_layer_caching(bool defaultValue);
 
+bool enable_sdr_dimming(bool defaultValue);
+
 } // namespace sysprop
 } // namespace android
 #endif // SURFACEFLINGERPROPERTIES_H_
diff --git a/services/surfaceflinger/TimeStats/TimeStats.cpp b/services/surfaceflinger/TimeStats/TimeStats.cpp
index 10d58a6..d6a0787 100644
--- a/services/surfaceflinger/TimeStats/TimeStats.cpp
+++ b/services/surfaceflinger/TimeStats/TimeStats.cpp
@@ -351,12 +351,16 @@
             std::max(mTimeStats.displayEventConnectionsCountLegacy, count);
 }
 
+static int32_t toMs(nsecs_t nanos) {
+    int64_t millis =
+            std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::nanoseconds(nanos))
+                    .count();
+    millis = std::clamp(millis, int64_t(INT32_MIN), int64_t(INT32_MAX));
+    return static_cast<int32_t>(millis);
+}
+
 static int32_t msBetween(nsecs_t start, nsecs_t end) {
-    int64_t delta = std::chrono::duration_cast<std::chrono::milliseconds>(
-                            std::chrono::nanoseconds(end - start))
-                            .count();
-    delta = std::clamp(delta, int64_t(INT32_MIN), int64_t(INT32_MAX));
-    return static_cast<int32_t>(delta);
+    return toMs(end - start);
 }
 
 void TimeStats::recordFrameDuration(nsecs_t startTime, nsecs_t endTime) {
@@ -829,10 +833,9 @@
         // TimeStats Histograms only retain positive values, so we don't need to check if these
         // deadlines were really missed if we know that the frame had jank, since deadlines
         // that were met will be dropped.
-        timelineStats.displayDeadlineDeltas.insert(static_cast<int32_t>(info.displayDeadlineDelta));
-        timelineStats.displayPresentDeltas.insert(static_cast<int32_t>(info.displayPresentJitter));
-        timeStatsLayer.deltas["appDeadlineDeltas"].insert(
-                static_cast<int32_t>(info.appDeadlineDelta));
+        timelineStats.displayDeadlineDeltas.insert(toMs(info.displayDeadlineDelta));
+        timelineStats.displayPresentDeltas.insert(toMs(info.displayPresentJitter));
+        timeStatsLayer.deltas["appDeadlineDeltas"].insert(toMs(info.appDeadlineDelta));
     }
 }
 
diff --git a/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop b/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop
index ee5542d..78f8a2f 100644
--- a/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop
+++ b/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop
@@ -463,3 +463,12 @@
     access: Readonly
     prop_name: "ro.surface_flinger.enable_layer_caching"
 }
+
+# Enables SDR layer dimming
+prop {
+    api_name: "enable_sdr_dimming"
+    type: Boolean
+    scope: Public
+    access: Readonly
+    prop_name: "ro.surface_flinger.enable_sdr_dimming"
+}
\ No newline at end of file
diff --git a/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt b/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt
index 47e14f6..9c567d6 100644
--- a/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt
+++ b/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt
@@ -53,6 +53,10 @@
     prop_name: "ro.surface_flinger.protected_contents"
   }
   prop {
+    api_name: "enable_sdr_dimming"
+    prop_name: "ro.surface_flinger.enable_sdr_dimming"
+  }
+  prop {
     api_name: "force_hwc_copy_for_virtual_displays"
     prop_name: "ro.surface_flinger.force_hwc_copy_for_virtual_displays"
   }
diff --git a/services/surfaceflinger/tests/LayerTypeTransaction_test.cpp b/services/surfaceflinger/tests/LayerTypeTransaction_test.cpp
index 4753362..34c9182 100644
--- a/services/surfaceflinger/tests/LayerTypeTransaction_test.cpp
+++ b/services/surfaceflinger/tests/LayerTypeTransaction_test.cpp
@@ -19,6 +19,7 @@
 #pragma clang diagnostic ignored "-Wconversion"
 
 #include <gui/BufferItemConsumer.h>
+#include <private/android_filesystem_config.h>
 #include "TransactionTestHarnesses.h"
 
 namespace android {
@@ -170,7 +171,11 @@
     args.displayToken = mDisplay;
 
     ScreenCaptureResults captureResults;
-    ASSERT_EQ(PERMISSION_DENIED, ScreenCapture::captureDisplay(args, captureResults));
+    {
+        // Ensure the UID is not root because root has all permissions
+        UIDFaker f(AID_APP_START);
+        ASSERT_EQ(PERMISSION_DENIED, ScreenCapture::captureDisplay(args, captureResults));
+    }
 
     Transaction().setFlags(layer, 0, layer_state_t::eLayerSecure).apply(true);
     ASSERT_EQ(NO_ERROR, ScreenCapture::captureDisplay(args, captureResults));
diff --git a/services/surfaceflinger/tests/ScreenCapture_test.cpp b/services/surfaceflinger/tests/ScreenCapture_test.cpp
index 2e9c10c..6912fcf 100644
--- a/services/surfaceflinger/tests/ScreenCapture_test.cpp
+++ b/services/surfaceflinger/tests/ScreenCapture_test.cpp
@@ -84,7 +84,11 @@
 
     Transaction().show(layer).setLayer(layer, INT32_MAX).apply(true);
 
-    ASSERT_EQ(PERMISSION_DENIED, ScreenCapture::captureDisplay(mCaptureArgs, mCaptureResults));
+    {
+        // Ensure the UID is not root because root has all permissions
+        UIDFaker f(AID_APP_START);
+        ASSERT_EQ(PERMISSION_DENIED, ScreenCapture::captureDisplay(mCaptureArgs, mCaptureResults));
+    }
 
     UIDFaker f(AID_SYSTEM);
 
@@ -528,7 +532,7 @@
     ASSERT_EQ(NAME_NOT_FOUND, ScreenCapture::captureLayers(args, captureResults));
 }
 
-TEST_F(ScreenCaptureTest, CaputureSecureLayer) {
+TEST_F(ScreenCaptureTest, CaptureSecureLayer) {
     sp<SurfaceControl> redLayer = createLayer(String8("Red surface"), 60, 60,
                                               ISurfaceComposerClient::eFXSurfaceBufferState);
     sp<SurfaceControl> secureLayer =
@@ -552,8 +556,12 @@
     args.childrenOnly = false;
     ScreenCaptureResults captureResults;
 
-    // Call from outside system with secure layers will result in permission denied
-    ASSERT_EQ(PERMISSION_DENIED, ScreenCapture::captureLayers(args, captureResults));
+    {
+        // Ensure the UID is not root because root has all permissions
+        UIDFaker f(AID_APP_START);
+        // Call from outside system with secure layers will result in permission denied
+        ASSERT_EQ(PERMISSION_DENIED, ScreenCapture::captureLayers(args, captureResults));
+    }
 
     UIDFaker f(AID_SYSTEM);
 
diff --git a/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp b/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp
index ff53a7b..3e4e130 100644
--- a/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp
@@ -1011,6 +1011,9 @@
     constexpr size_t MISSED_FRAMES = 4;
     constexpr size_t CLIENT_COMPOSITION_FRAMES = 3;
     constexpr size_t DISPLAY_EVENT_CONNECTIONS = 14;
+    constexpr nsecs_t DISPLAY_DEADLINE_DELTA = 1'000'000;
+    constexpr nsecs_t DISPLAY_PRESENT_JITTER = 2'000'000;
+    constexpr nsecs_t APP_DEADLINE_DELTA = 3'000'000;
 
     EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
 
@@ -1036,24 +1039,35 @@
     mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(5000000));
 
     mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
-                                      JankType::SurfaceFlingerCpuDeadlineMissed, 1, 2, 3});
+                                      JankType::SurfaceFlingerCpuDeadlineMissed,
+                                      DISPLAY_DEADLINE_DELTA, DISPLAY_PRESENT_JITTER,
+                                      APP_DEADLINE_DELTA});
     mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
-                                      JankType::SurfaceFlingerGpuDeadlineMissed, 1, 2, 3});
+                                      JankType::SurfaceFlingerGpuDeadlineMissed,
+                                      DISPLAY_DEADLINE_DELTA, DISPLAY_PRESENT_JITTER,
+                                      APP_DEADLINE_DELTA});
     mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
-                                      JankType::DisplayHAL, 1, 2, 3});
+                                      JankType::DisplayHAL, DISPLAY_DEADLINE_DELTA,
+                                      DISPLAY_PRESENT_JITTER, APP_DEADLINE_DELTA});
     mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
-                                      JankType::AppDeadlineMissed, 1, 2, 3});
+                                      JankType::AppDeadlineMissed, DISPLAY_DEADLINE_DELTA,
+                                      DISPLAY_PRESENT_JITTER, APP_DEADLINE_DELTA});
     mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
-                                      JankType::SurfaceFlingerScheduling, 1, 2, 3});
+                                      JankType::SurfaceFlingerScheduling, DISPLAY_DEADLINE_DELTA,
+                                      DISPLAY_PRESENT_JITTER, APP_DEADLINE_DELTA});
     mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
-                                      JankType::PredictionError, 1, 2, 3});
+                                      JankType::PredictionError, DISPLAY_DEADLINE_DELTA,
+                                      DISPLAY_PRESENT_JITTER, APP_DEADLINE_DELTA});
     mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
-                                      JankType::AppDeadlineMissed | JankType::BufferStuffing, 1, 2,
-                                      3});
+                                      JankType::AppDeadlineMissed | JankType::BufferStuffing,
+                                      DISPLAY_DEADLINE_DELTA, DISPLAY_PRESENT_JITTER,
+                                      APP_DEADLINE_DELTA});
     mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
-                                      JankType::BufferStuffing, 1, 2, 3});
+                                      JankType::BufferStuffing, DISPLAY_DEADLINE_DELTA,
+                                      DISPLAY_PRESENT_JITTER, APP_DEADLINE_DELTA});
     mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
-                                      JankType::None, 1, 2, 3});
+                                      JankType::None, DISPLAY_DEADLINE_DELTA,
+                                      DISPLAY_PRESENT_JITTER, APP_DEADLINE_DELTA});
 
     std::string pulledData;
     EXPECT_TRUE(mTimeStats->onPullAtom(10062 /*SURFACEFLINGER_STATS_GLOBAL_INFO*/, &pulledData));
@@ -1137,6 +1151,10 @@
 TEST_F(TimeStatsTest, layerStatsCallback_pullsAllAndClears) {
     constexpr size_t LATE_ACQUIRE_FRAMES = 2;
     constexpr size_t BAD_DESIRED_PRESENT_FRAMES = 3;
+    constexpr nsecs_t DISPLAY_DEADLINE_DELTA = 1'000'000;
+    constexpr nsecs_t DISPLAY_PRESENT_JITTER = 2'000'000;
+    constexpr nsecs_t APP_DEADLINE_DELTA_2MS = 2'000'000;
+    constexpr nsecs_t APP_DEADLINE_DELTA_3MS = 3'000'000;
     EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
 
     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
@@ -1155,22 +1173,32 @@
     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000, frameRate60);
 
     mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
-                                      JankType::SurfaceFlingerCpuDeadlineMissed, 1, 2, 3});
+                                      JankType::SurfaceFlingerCpuDeadlineMissed,
+                                      DISPLAY_DEADLINE_DELTA, DISPLAY_PRESENT_JITTER,
+                                      APP_DEADLINE_DELTA_3MS});
     mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
-                                      JankType::SurfaceFlingerGpuDeadlineMissed, 1, 2, 3});
+                                      JankType::SurfaceFlingerGpuDeadlineMissed,
+                                      DISPLAY_DEADLINE_DELTA, DISPLAY_PRESENT_JITTER,
+                                      APP_DEADLINE_DELTA_3MS});
     mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
-                                      JankType::DisplayHAL, 1, 2, 3});
+                                      JankType::DisplayHAL, DISPLAY_DEADLINE_DELTA,
+                                      DISPLAY_PRESENT_JITTER, APP_DEADLINE_DELTA_3MS});
     mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
-                                      JankType::AppDeadlineMissed, 1, 2, 3});
+                                      JankType::AppDeadlineMissed, DISPLAY_DEADLINE_DELTA,
+                                      DISPLAY_PRESENT_JITTER, APP_DEADLINE_DELTA_3MS});
     mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
-                                      JankType::SurfaceFlingerScheduling, 1, 2, 2});
+                                      JankType::SurfaceFlingerScheduling, DISPLAY_DEADLINE_DELTA,
+                                      DISPLAY_PRESENT_JITTER, APP_DEADLINE_DELTA_2MS});
     mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
-                                      JankType::PredictionError, 1, 2, 2});
+                                      JankType::PredictionError, DISPLAY_DEADLINE_DELTA,
+                                      DISPLAY_PRESENT_JITTER, APP_DEADLINE_DELTA_2MS});
     mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
-                                      JankType::AppDeadlineMissed | JankType::BufferStuffing, 1, 2,
-                                      2});
+                                      JankType::AppDeadlineMissed | JankType::BufferStuffing,
+                                      DISPLAY_DEADLINE_DELTA, APP_DEADLINE_DELTA_2MS,
+                                      APP_DEADLINE_DELTA_2MS});
     mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
-                                      JankType::None, 1, 2, 3});
+                                      JankType::None, DISPLAY_DEADLINE_DELTA,
+                                      DISPLAY_PRESENT_JITTER, APP_DEADLINE_DELTA_3MS});
 
     std::string pulledData;
     EXPECT_TRUE(mTimeStats->onPullAtom(10063 /*SURFACEFLINGER_STATS_LAYER_INFO*/, &pulledData));