Merge "SF: Merge BufferStateLayer into Layer"
diff --git a/cmds/installd/Android.bp b/cmds/installd/Android.bp
index 0f7c489..8e37ce9 100644
--- a/cmds/installd/Android.bp
+++ b/cmds/installd/Android.bp
@@ -25,6 +25,7 @@
         "CrateManager.cpp",
         "InstalldNativeService.cpp",
         "QuotaUtils.cpp",
+        "SysTrace.cpp",
         "dexopt.cpp",
         "execv_helper.cpp",
         "globals.cpp",
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index 8f163b9..d26d301 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -16,8 +16,6 @@
 
 #include "InstalldNativeService.h"
 
-#define ATRACE_TAG ATRACE_TAG_PACKAGE_MANAGER
-
 #include <errno.h>
 #include <fts.h>
 #include <inttypes.h>
@@ -75,6 +73,7 @@
 #include "CrateManager.h"
 #include "MatchExtensionGen.h"
 #include "QuotaUtils.h"
+#include "SysTrace.h"
 
 #ifndef LOG_TAG
 #define LOG_TAG "installd"
@@ -1327,7 +1326,7 @@
     const char* uuid_ = uuid ? uuid->c_str() : nullptr;
     for (auto userId : get_known_users(uuid_)) {
         LOCK_USER();
-        ATRACE_BEGIN("fixup user");
+        atrace_pm_begin("fixup user");
         FTS* fts;
         FTSENT* p;
         auto ce_path = create_data_user_ce_path(uuid_, userId);
@@ -1417,7 +1416,7 @@
             }
         }
         fts_close(fts);
-        ATRACE_END();
+        atrace_pm_end();
     }
     return ok();
 }
@@ -1970,7 +1969,7 @@
         // files from the UIDs which are most over their allocated quota
 
         // 1. Create trackers for every known UID
-        ATRACE_BEGIN("create");
+        atrace_pm_begin("create");
         const auto users = get_known_users(uuid_);
 #ifdef GRANULAR_LOCKS
         std::vector<UserLock> userLocks;
@@ -2051,10 +2050,10 @@
             }
             fts_close(fts);
         }
-        ATRACE_END();
+        atrace_pm_end();
 
         // 2. Populate tracker stats and insert into priority queue
-        ATRACE_BEGIN("populate");
+        atrace_pm_begin("populate");
         auto cmp = [](std::shared_ptr<CacheTracker> left, std::shared_ptr<CacheTracker> right) {
             return (left->getCacheRatio() < right->getCacheRatio());
         };
@@ -2064,11 +2063,11 @@
             it.second->loadStats();
             queue.push(it.second);
         }
-        ATRACE_END();
+        atrace_pm_end();
 
         // 3. Bounce across the queue, freeing items from whichever tracker is
         // the most over their assigned quota
-        ATRACE_BEGIN("bounce");
+        atrace_pm_begin("bounce");
         std::shared_ptr<CacheTracker> active;
         while (active || !queue.empty()) {
             // Only look at apps under quota when explicitly requested
@@ -2124,7 +2123,7 @@
                 }
             }
         }
-        ATRACE_END();
+        atrace_pm_end();
 
     } else {
         return error("Legacy cache logic no longer supported");
@@ -2469,84 +2468,84 @@
         flags &= ~FLAG_USE_QUOTA;
     }
 
-    ATRACE_BEGIN("obb");
+    atrace_pm_begin("obb");
     for (const auto& packageName : packageNames) {
         auto obbCodePath = create_data_media_package_path(uuid_, userId,
                 "obb", packageName.c_str());
         calculate_tree_size(obbCodePath, &extStats.codeSize);
     }
-    ATRACE_END();
+    atrace_pm_end();
     // Calculating the app size of the external storage owning app in a manual way, since
     // calculating it through quota apis also includes external media storage in the app storage
     // numbers
     if (flags & FLAG_USE_QUOTA && appId >= AID_APP_START && !ownsExternalStorage(appId)) {
-        ATRACE_BEGIN("code");
+        atrace_pm_begin("code");
         for (const auto& codePath : codePaths) {
             calculate_tree_size(codePath, &stats.codeSize, -1,
                     multiuser_get_shared_gid(0, appId));
         }
-        ATRACE_END();
+        atrace_pm_end();
 
-        ATRACE_BEGIN("quota");
+        atrace_pm_begin("quota");
         collectQuotaStats(uuidString, userId, appId, &stats, &extStats);
-        ATRACE_END();
+        atrace_pm_end();
     } else {
-        ATRACE_BEGIN("code");
+        atrace_pm_begin("code");
         for (const auto& codePath : codePaths) {
             calculate_tree_size(codePath, &stats.codeSize);
         }
-        ATRACE_END();
+        atrace_pm_end();
 
         for (size_t i = 0; i < packageNames.size(); i++) {
             const char* pkgname = packageNames[i].c_str();
 
-            ATRACE_BEGIN("data");
+            atrace_pm_begin("data");
             auto cePath = create_data_user_ce_package_path(uuid_, userId, pkgname, ceDataInodes[i]);
             collectManualStats(cePath, &stats);
             auto dePath = create_data_user_de_package_path(uuid_, userId, pkgname);
             collectManualStats(dePath, &stats);
-            ATRACE_END();
+            atrace_pm_end();
 
             // In case of sdk sandbox storage (e.g. /data/misc_ce/0/sdksandbox/<package-name>),
             // collect individual stats of each subdirectory (shared, storage of each sdk etc.)
             if (appId >= AID_APP_START && appId <= AID_APP_END) {
-                ATRACE_BEGIN("sdksandbox");
+                atrace_pm_begin("sdksandbox");
                 auto sdkSandboxCePath =
                         create_data_misc_sdk_sandbox_package_path(uuid_, true, userId, pkgname);
                 collectManualStatsForSubDirectories(sdkSandboxCePath, &stats);
                 auto sdkSandboxDePath =
                         create_data_misc_sdk_sandbox_package_path(uuid_, false, userId, pkgname);
                 collectManualStatsForSubDirectories(sdkSandboxDePath, &stats);
-                ATRACE_END();
+                atrace_pm_end();
             }
 
             if (!uuid) {
-                ATRACE_BEGIN("profiles");
+                atrace_pm_begin("profiles");
                 calculate_tree_size(
                         create_primary_current_profile_package_dir_path(userId, pkgname),
                         &stats.dataSize);
                 calculate_tree_size(
                         create_primary_reference_profile_package_dir_path(pkgname),
                         &stats.codeSize);
-                ATRACE_END();
+                atrace_pm_end();
             }
 
-            ATRACE_BEGIN("external");
+            atrace_pm_begin("external");
             auto extPath = create_data_media_package_path(uuid_, userId, "data", pkgname);
             collectManualStats(extPath, &extStats);
             auto mediaPath = create_data_media_package_path(uuid_, userId, "media", pkgname);
             calculate_tree_size(mediaPath, &extStats.dataSize);
-            ATRACE_END();
+            atrace_pm_end();
         }
 
         if (!uuid) {
-            ATRACE_BEGIN("dalvik");
+            atrace_pm_begin("dalvik");
             int32_t sharedGid = multiuser_get_shared_gid(0, appId);
             if (sharedGid != -1) {
                 calculate_tree_size(create_data_dalvik_cache_path(), &stats.codeSize,
                         sharedGid, -1);
             }
-            ATRACE_END();
+            atrace_pm_end();
         }
     }
 
@@ -2692,41 +2691,41 @@
     }
 
     if (flags & FLAG_USE_QUOTA) {
-        ATRACE_BEGIN("code");
+        atrace_pm_begin("code");
         calculate_tree_size(create_data_app_path(uuid_), &stats.codeSize, -1, -1, true);
-        ATRACE_END();
+        atrace_pm_end();
 
-        ATRACE_BEGIN("data");
+        atrace_pm_begin("data");
         auto cePath = create_data_user_ce_path(uuid_, userId);
         collectManualStatsForUser(cePath, &stats, true);
         auto dePath = create_data_user_de_path(uuid_, userId);
         collectManualStatsForUser(dePath, &stats, true);
-        ATRACE_END();
+        atrace_pm_end();
 
         if (!uuid) {
-            ATRACE_BEGIN("profile");
+            atrace_pm_begin("profile");
             auto userProfilePath = create_primary_cur_profile_dir_path(userId);
             calculate_tree_size(userProfilePath, &stats.dataSize, -1, -1, true);
             auto refProfilePath = create_primary_ref_profile_dir_path();
             calculate_tree_size(refProfilePath, &stats.codeSize, -1, -1, true);
-            ATRACE_END();
+            atrace_pm_end();
         }
 
-        ATRACE_BEGIN("external");
+        atrace_pm_begin("external");
         auto sizes = getExternalSizesForUserWithQuota(uuidString, userId, appIds);
         extStats.dataSize += sizes.totalSize;
         extStats.codeSize += sizes.obbSize;
-        ATRACE_END();
+        atrace_pm_end();
 
         if (!uuid) {
-            ATRACE_BEGIN("dalvik");
+            atrace_pm_begin("dalvik");
             calculate_tree_size(create_data_dalvik_cache_path(), &stats.codeSize,
                     -1, -1, true);
             calculate_tree_size(create_primary_cur_profile_dir_path(userId), &stats.dataSize,
                     -1, -1, true);
-            ATRACE_END();
+            atrace_pm_end();
         }
-        ATRACE_BEGIN("quota");
+        atrace_pm_begin("quota");
         int64_t dataSize = extStats.dataSize;
         for (auto appId : appIds) {
             if (appId >= AID_APP_START) {
@@ -2738,54 +2737,54 @@
             }
         }
         extStats.dataSize = dataSize;
-        ATRACE_END();
+        atrace_pm_end();
     } else {
-        ATRACE_BEGIN("obb");
+        atrace_pm_begin("obb");
         auto obbPath = create_data_path(uuid_) + "/media/obb";
         calculate_tree_size(obbPath, &extStats.codeSize);
-        ATRACE_END();
+        atrace_pm_end();
 
-        ATRACE_BEGIN("code");
+        atrace_pm_begin("code");
         calculate_tree_size(create_data_app_path(uuid_), &stats.codeSize);
-        ATRACE_END();
+        atrace_pm_end();
 
-        ATRACE_BEGIN("data");
+        atrace_pm_begin("data");
         auto cePath = create_data_user_ce_path(uuid_, userId);
         collectManualStatsForUser(cePath, &stats);
         auto dePath = create_data_user_de_path(uuid_, userId);
         collectManualStatsForUser(dePath, &stats);
-        ATRACE_END();
+        atrace_pm_end();
 
-        ATRACE_BEGIN("sdksandbox");
+        atrace_pm_begin("sdksandbox");
         auto sdkSandboxCePath = create_data_misc_sdk_sandbox_path(uuid_, true, userId);
         collectManualStatsForUser(sdkSandboxCePath, &stats, false, true);
         auto sdkSandboxDePath = create_data_misc_sdk_sandbox_path(uuid_, false, userId);
         collectManualStatsForUser(sdkSandboxDePath, &stats, false, true);
-        ATRACE_END();
+        atrace_pm_end();
 
         if (!uuid) {
-            ATRACE_BEGIN("profile");
+            atrace_pm_begin("profile");
             auto userProfilePath = create_primary_cur_profile_dir_path(userId);
             calculate_tree_size(userProfilePath, &stats.dataSize);
             auto refProfilePath = create_primary_ref_profile_dir_path();
             calculate_tree_size(refProfilePath, &stats.codeSize);
-            ATRACE_END();
+            atrace_pm_end();
         }
 
-        ATRACE_BEGIN("external");
+        atrace_pm_begin("external");
         auto dataMediaPath = create_data_media_path(uuid_, userId);
         collectManualExternalStatsForUser(dataMediaPath, &extStats);
 #if MEASURE_DEBUG
         LOG(DEBUG) << "Measured external data " << extStats.dataSize << " cache "
                 << extStats.cacheSize;
 #endif
-        ATRACE_END();
+        atrace_pm_end();
 
         if (!uuid) {
-            ATRACE_BEGIN("dalvik");
+            atrace_pm_begin("dalvik");
             calculate_tree_size(create_data_dalvik_cache_path(), &stats.codeSize);
             calculate_tree_size(create_primary_cur_profile_dir_path(userId), &stats.dataSize);
-            ATRACE_END();
+            atrace_pm_end();
         }
     }
 
@@ -2833,16 +2832,16 @@
     }
 
     if (flags & FLAG_USE_QUOTA) {
-        ATRACE_BEGIN("quota");
+        atrace_pm_begin("quota");
         auto sizes = getExternalSizesForUserWithQuota(uuidString, userId, appIds);
         totalSize = sizes.totalSize;
         audioSize = sizes.audioSize;
         videoSize = sizes.videoSize;
         imageSize = sizes.imageSize;
         obbSize = sizes.obbSize;
-        ATRACE_END();
+        atrace_pm_end();
 
-        ATRACE_BEGIN("apps");
+        atrace_pm_begin("apps");
         struct stats extStats;
         memset(&extStats, 0, sizeof(extStats));
         for (auto appId : appIds) {
@@ -2851,9 +2850,9 @@
             }
         }
         appSize = extStats.dataSize;
-        ATRACE_END();
+        atrace_pm_end();
     } else {
-        ATRACE_BEGIN("manual");
+        atrace_pm_begin("manual");
         FTS *fts;
         FTSENT *p;
         auto path = create_data_media_path(uuid_, userId);
@@ -2896,16 +2895,16 @@
             }
         }
         fts_close(fts);
-        ATRACE_END();
+        atrace_pm_end();
 
-        ATRACE_BEGIN("obb");
+        atrace_pm_begin("obb");
         auto obbPath = StringPrintf("%s/Android/obb",
                 create_data_media_path(uuid_, userId).c_str());
         calculate_tree_size(obbPath, &obbSize);
         if (!(flags & FLAG_USE_QUOTA)) {
             totalSize -= obbSize;
         }
-        ATRACE_END();
+        atrace_pm_end();
     }
 
     std::vector<int64_t> ret;
diff --git a/cmds/installd/SysTrace.cpp b/cmds/installd/SysTrace.cpp
new file mode 100644
index 0000000..fa65c77
--- /dev/null
+++ b/cmds/installd/SysTrace.cpp
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define ATRACE_TAG ATRACE_TAG_PACKAGE_MANAGER
+
+#include "SysTrace.h"
+#include <utils/Trace.h>
+
+namespace android::installd {
+void atrace_pm_begin(const char* name) {
+    ATRACE_BEGIN(name);
+}
+
+void atrace_pm_end() {
+    ATRACE_END();
+}
+} /* namespace android::installd */
diff --git a/cmds/installd/SysTrace.h b/cmds/installd/SysTrace.h
new file mode 100644
index 0000000..18506a9
--- /dev/null
+++ b/cmds/installd/SysTrace.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+namespace android::installd {
+void atrace_pm_begin(const char*);
+void atrace_pm_end();
+} /* namespace android::installd */
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index 364937d..246963a 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -89,6 +89,7 @@
         "Stability.cpp",
         "Status.cpp",
         "TextOutput.cpp",
+        "Trace.cpp",
         "Utils.cpp",
     ],
 
diff --git a/libs/binder/Trace.cpp b/libs/binder/Trace.cpp
new file mode 100644
index 0000000..1ebfa1a
--- /dev/null
+++ b/libs/binder/Trace.cpp
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <binder/Trace.h>
+#include <cutils/trace.h>
+
+namespace android {
+namespace binder {
+
+void atrace_begin(uint64_t tag, const char* name) {
+    ::atrace_begin(tag, name);
+}
+
+void atrace_end(uint64_t tag) {
+    ::atrace_end(tag);
+}
+
+} // namespace binder
+} // namespace android
diff --git a/libs/binder/include/binder/Trace.h b/libs/binder/include/binder/Trace.h
new file mode 100644
index 0000000..9937842
--- /dev/null
+++ b/libs/binder/include/binder/Trace.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <cutils/trace.h>
+#include <stdint.h>
+
+namespace android {
+namespace binder {
+
+// Trampoline functions allowing generated aidls to trace binder transactions without depending on
+// libcutils/libutils
+void atrace_begin(uint64_t tag, const char* name);
+void atrace_end(uint64_t tag);
+
+class ScopedTrace {
+public:
+    inline ScopedTrace(uint64_t tag, const char* name) : mTag(tag) { atrace_begin(mTag, name); }
+
+    inline ~ScopedTrace() { atrace_end(mTag); }
+
+private:
+    uint64_t mTag;
+};
+
+} // namespace binder
+} // namespace android
diff --git a/libs/binder/ndk/Android.bp b/libs/binder/ndk/Android.bp
index 32e018d..33d28e6 100644
--- a/libs/binder/ndk/Android.bp
+++ b/libs/binder/ndk/Android.bp
@@ -57,6 +57,7 @@
     srcs: [
         "ibinder.cpp",
         "ibinder_jni.cpp",
+        "libbinder.cpp",
         "parcel.cpp",
         "parcel_jni.cpp",
         "process.cpp",
diff --git a/libs/binder/ndk/ibinder.cpp b/libs/binder/ndk/ibinder.cpp
index 9778ec0..28d1f16 100644
--- a/libs/binder/ndk/ibinder.cpp
+++ b/libs/binder/ndk/ibinder.cpp
@@ -14,21 +14,19 @@
  * limitations under the License.
  */
 
+#include <android-base/logging.h>
 #include <android/binder_ibinder.h>
 #include <android/binder_ibinder_platform.h>
-#include <android/binder_libbinder.h>
-#include "ibinder_internal.h"
-
 #include <android/binder_stability.h>
 #include <android/binder_status.h>
-#include "parcel_internal.h"
-#include "status_internal.h"
-
-#include <android-base/logging.h>
 #include <binder/IPCThreadState.h>
 #include <binder/IResultReceiver.h>
 #include <private/android_filesystem_config.h>
 
+#include "ibinder_internal.h"
+#include "parcel_internal.h"
+#include "status_internal.h"
+
 using DeathRecipient = ::android::IBinder::DeathRecipient;
 
 using ::android::IBinder;
@@ -782,17 +780,6 @@
     return ::android::IPCThreadState::self()->getCallingSid();
 }
 
-android::sp<android::IBinder> AIBinder_toPlatformBinder(AIBinder* binder) {
-    if (binder == nullptr) return nullptr;
-    return binder->getBinder();
-}
-
-AIBinder* AIBinder_fromPlatformBinder(const android::sp<android::IBinder>& binder) {
-    sp<AIBinder> ndkBinder = ABpBinder::lookupOrCreateFromBinder(binder);
-    AIBinder_incStrong(ndkBinder.get());
-    return ndkBinder.get();
-}
-
 void AIBinder_setMinSchedulerPolicy(AIBinder* binder, int policy, int priority) {
     binder->asABBinder()->setMinSchedulerPolicy(policy, priority);
 }
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 0bf1e3d..95eee26 100644
--- a/libs/binder/ndk/include_cpp/android/binder_parcel_utils.h
+++ b/libs/binder/ndk/include_cpp/android/binder_parcel_utils.h
@@ -1639,7 +1639,6 @@
         return AParcel_writeParcelable(parcel, value);
     } else {
         static_assert(dependent_false_v<T>, "unrecognized type");
-        return STATUS_OK;
     }
 }
 
@@ -1707,7 +1706,6 @@
         return AParcel_readParcelable(parcel, value);
     } else {
         static_assert(dependent_false_v<T>, "unrecognized type");
-        return STATUS_OK;
     }
 }
 
diff --git a/libs/binder/ndk/include_cpp/android/binder_to_string.h b/libs/binder/ndk/include_cpp/android/binder_to_string.h
index ef71a81..d7840ec 100644
--- a/libs/binder/ndk/include_cpp/android/binder_to_string.h
+++ b/libs/binder/ndk/include_cpp/android/binder_to_string.h
@@ -162,7 +162,12 @@
     } else if constexpr (std::is_same_v<bool, _T>) {
         return t ? "true" : "false";
     } else if constexpr (std::is_same_v<char16_t, _T>) {
+        // TODO(b/244494451): codecvt is deprecated in C++17 -- suppress the
+        // warnings. There's no replacement in the standard library yet.
+        _Pragma("clang diagnostic push")
+                _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"");
         return std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t>().to_bytes(t);
+        _Pragma("clang diagnostic pop");
     } else if constexpr (std::is_arithmetic_v<_T>) {
         return std::to_string(t);
     } else if constexpr (std::is_same_v<std::string, _T>) {
diff --git a/libs/binder/ndk/include_platform/android/binder_libbinder.h b/libs/binder/ndk/include_platform/android/binder_libbinder.h
index f0c00e8..dfe12a1 100644
--- a/libs/binder/ndk/include_platform/android/binder_libbinder.h
+++ b/libs/binder/ndk/include_platform/android/binder_libbinder.h
@@ -19,7 +19,9 @@
 #if !defined(__ANDROID_APEX__) && !defined(__ANDROID_VNDK__)
 
 #include <android/binder_ibinder.h>
+#include <android/binder_parcel.h>
 #include <binder/IBinder.h>
+#include <binder/Parcel.h>
 
 /**
  * Get libbinder version of binder from AIBinder.
@@ -47,4 +49,26 @@
  */
 AIBinder* AIBinder_fromPlatformBinder(const android::sp<android::IBinder>& binder);
 
+/**
+ * View libbinder version of parcel from AParcel (mutable).
+ *
+ * The lifetime of the returned parcel is the lifetime of the input AParcel.
+ * Do not ues this reference after dropping the AParcel.
+ *
+ * \param parcel non-null parcel with ownership retained by client
+ * \return platform parcel object
+ */
+android::Parcel* AParcel_viewPlatformParcel(AParcel* parcel);
+
+/**
+ * View libbinder version of parcel from AParcel (const version).
+ *
+ * The lifetime of the returned parcel is the lifetime of the input AParcel.
+ * Do not ues this reference after dropping the AParcel.
+ *
+ * \param parcel non-null parcel with ownership retained by client
+ * \return platform parcel object
+ */
+const android::Parcel* AParcel_viewPlatformParcel(const AParcel* parcel);
+
 #endif
diff --git a/libs/binder/ndk/libbinder.cpp b/libs/binder/ndk/libbinder.cpp
new file mode 100644
index 0000000..f94d81d
--- /dev/null
+++ b/libs/binder/ndk/libbinder.cpp
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android/binder_libbinder.h>
+
+#include "ibinder_internal.h"
+#include "parcel_internal.h"
+
+using ::android::IBinder;
+using ::android::Parcel;
+using ::android::sp;
+
+sp<IBinder> AIBinder_toPlatformBinder(AIBinder* binder) {
+    if (binder == nullptr) return nullptr;
+    return binder->getBinder();
+}
+
+AIBinder* AIBinder_fromPlatformBinder(const sp<IBinder>& binder) {
+    sp<AIBinder> ndkBinder = ABpBinder::lookupOrCreateFromBinder(binder);
+    AIBinder_incStrong(ndkBinder.get());
+    return ndkBinder.get();
+}
+
+Parcel* AParcel_viewPlatformParcel(AParcel* parcel) {
+    return parcel->get();
+}
+
+const Parcel* AParcel_viewPlatformParcel(const AParcel* parcel) {
+    return parcel->get();
+}
diff --git a/libs/binder/ndk/libbinder_ndk.map.txt b/libs/binder/ndk/libbinder_ndk.map.txt
index 6bc9814..259a736 100644
--- a/libs/binder/ndk/libbinder_ndk.map.txt
+++ b/libs/binder/ndk/libbinder_ndk.map.txt
@@ -158,6 +158,7 @@
     extern "C++" {
         AIBinder_fromPlatformBinder*;
         AIBinder_toPlatformBinder*;
+        AParcel_viewPlatformParcel*;
     };
   local:
     *;
diff --git a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
index 1b136dc..6d29238 100644
--- a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
+++ b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
@@ -661,6 +661,15 @@
     }
 }
 
+TEST(NdkBinder, ConvertToPlatformParcel) {
+    ndk::ScopedAParcel parcel = ndk::ScopedAParcel(AParcel_create());
+    EXPECT_EQ(OK, AParcel_writeInt32(parcel.get(), 42));
+
+    android::Parcel* pparcel = AParcel_viewPlatformParcel(parcel.get());
+    pparcel->setDataPosition(0);
+    EXPECT_EQ(42, pparcel->readInt32());
+}
+
 class MyResultReceiver : public BnResultReceiver {
    public:
     Mutex mMutex;
diff --git a/libs/binder/tests/parcel_fuzzer/binder_ndk.h b/libs/binder/tests/parcel_fuzzer/binder_ndk.h
index 81e79b5..d19f25b 100644
--- a/libs/binder/tests/parcel_fuzzer/binder_ndk.h
+++ b/libs/binder/tests/parcel_fuzzer/binder_ndk.h
@@ -18,29 +18,27 @@
 #include <android/binder_auto_utils.h>
 #include <vector>
 
+#include <android/binder_libbinder.h>
 #include <android/binder_parcel.h>
 #include "parcel_fuzzer.h"
 
-// libbinder_ndk doesn't export this header which breaks down its API for NDK
-// and APEX users, but we need access to it to fuzz.
-#include "../../ndk/parcel_internal.h"
-
 class NdkParcelAdapter {
 public:
-    NdkParcelAdapter() : mParcel(new AParcel(nullptr /*binder*/)) {}
+    NdkParcelAdapter() : mParcel(AParcel_create()) {}
 
     const AParcel* aParcel() const { return mParcel.get(); }
     AParcel* aParcel() { return mParcel.get(); }
 
-    android::Parcel* parcel() { return aParcel()->get(); }
+    const android::Parcel* parcel() const { return AParcel_viewPlatformParcel(aParcel()); }
+    android::Parcel* parcel() { return AParcel_viewPlatformParcel(aParcel()); }
 
-    const uint8_t* data() const { return aParcel()->get()->data(); }
-    size_t dataSize() const { return aParcel()->get()->dataSize(); }
-    size_t dataAvail() const { return aParcel()->get()->dataAvail(); }
-    size_t dataPosition() const { return aParcel()->get()->dataPosition(); }
-    size_t dataCapacity() const { return aParcel()->get()->dataCapacity(); }
+    const uint8_t* data() const { return parcel()->data(); }
+    size_t dataSize() const { return parcel()->dataSize(); }
+    size_t dataAvail() const { return parcel()->dataAvail(); }
+    size_t dataPosition() const { return parcel()->dataPosition(); }
+    size_t dataCapacity() const { return parcel()->dataCapacity(); }
     android::status_t setData(const uint8_t* buffer, size_t len) {
-        return aParcel()->get()->setData(buffer, len);
+        return parcel()->setData(buffer, len);
     }
 
     android::status_t appendFrom(const NdkParcelAdapter* parcel, int32_t start, int32_t len) {
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 34edd65..3671a15 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -2715,12 +2715,16 @@
             ComposerServiceAIDL::getComposerService()->getDisplayDecorationSupport(displayToken,
                                                                                    &gsupport);
     std::optional<DisplayDecorationSupport> support;
-    if (status.isOk() && gsupport.has_value()) {
-        support->format = static_cast<aidl::android::hardware::graphics::common::PixelFormat>(
-                gsupport->format);
-        support->alphaInterpretation =
+    // TODO (b/241277093): Remove `false && ` once b/241278870 is fixed.
+    if (false && status.isOk() && gsupport.has_value()) {
+        support.emplace(DisplayDecorationSupport{
+          .format =
+                static_cast<aidl::android::hardware::graphics::common::PixelFormat>(
+                gsupport->format),
+          .alphaInterpretation =
                 static_cast<aidl::android::hardware::graphics::common::AlphaInterpretation>(
-                        gsupport->alphaInterpretation);
+                        gsupport->alphaInterpretation)
+        });
     }
     return support;
 }
diff --git a/services/inputflinger/Android.bp b/services/inputflinger/Android.bp
index 29a0e4f..5b286dc 100644
--- a/services/inputflinger/Android.bp
+++ b/services/inputflinger/Android.bp
@@ -148,6 +148,7 @@
     srcs: [":libinputflinger_base_sources"],
     shared_libs: [
         "libbase",
+        "libbinder",
         "libcutils",
         "libinput",
         "liblog",
diff --git a/services/surfaceflinger/CompositionEngine/src/Display.cpp b/services/surfaceflinger/CompositionEngine/src/Display.cpp
index d359424..0ebbcd0 100644
--- a/services/surfaceflinger/CompositionEngine/src/Display.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Display.cpp
@@ -243,7 +243,7 @@
         return false;
     }
 
-    const nsecs_t startTime = systemTime();
+    const TimePoint startTime = TimePoint::now();
 
     // Get any composition changes requested by the HWC device, and apply them.
     std::optional<android::HWComposer::DeviceRequestedChanges> changes;
@@ -261,7 +261,7 @@
     }
 
     if (isPowerHintSessionEnabled()) {
-        mPowerAdvisor->setHwcValidateTiming(mId, startTime, systemTime());
+        mPowerAdvisor->setHwcValidateTiming(mId, startTime, TimePoint::now());
         mPowerAdvisor->setRequiresClientComposition(mId, requiresClientComposition);
     }
 
@@ -365,7 +365,7 @@
 
     auto& hwc = getCompositionEngine().getHwComposer();
 
-    const nsecs_t startTime = systemTime();
+    const TimePoint startTime = TimePoint::now();
 
     if (isPowerHintSessionEnabled()) {
         if (!getCompositionEngine().getHwComposer().getComposer()->isSupported(
@@ -379,7 +379,7 @@
                                    getState().previousPresentFence);
 
     if (isPowerHintSessionEnabled()) {
-        mPowerAdvisor->setHwcPresentTiming(mId, startTime, systemTime());
+        mPowerAdvisor->setHwcPresentTiming(mId, startTime, TimePoint::now());
     }
 
     fences.presentFence = hwc.getPresentFence(*halDisplayIdOpt);
diff --git a/services/surfaceflinger/CompositionEngine/tests/MockPowerAdvisor.h b/services/surfaceflinger/CompositionEngine/tests/MockPowerAdvisor.h
index c8bd5e4..e220541 100644
--- a/services/surfaceflinger/CompositionEngine/tests/MockPowerAdvisor.h
+++ b/services/surfaceflinger/CompositionEngine/tests/MockPowerAdvisor.h
@@ -38,7 +38,7 @@
     MOCK_METHOD(bool, usePowerHintSession, (), (override));
     MOCK_METHOD(bool, supportsPowerHintSession, (), (override));
     MOCK_METHOD(bool, isPowerHintSessionRunning, (), (override));
-    MOCK_METHOD(void, setTargetWorkDuration, (int64_t targetDuration), (override));
+    MOCK_METHOD(void, setTargetWorkDuration, (Duration targetDuration), (override));
     MOCK_METHOD(void, sendActualWorkDuration, (), (override));
     MOCK_METHOD(void, sendPredictedWorkDuration, (), (override));
     MOCK_METHOD(void, enablePowerHint, (bool enabled), (override));
@@ -46,25 +46,24 @@
     MOCK_METHOD(void, setGpuFenceTime,
                 (DisplayId displayId, std::unique_ptr<FenceTime>&& fenceTime), (override));
     MOCK_METHOD(void, setHwcValidateTiming,
-                (DisplayId displayId, nsecs_t valiateStartTime, nsecs_t validateEndTime),
+                (DisplayId displayId, TimePoint validateStartTime, TimePoint validateEndTime),
                 (override));
     MOCK_METHOD(void, setHwcPresentTiming,
-                (DisplayId displayId, nsecs_t presentStartTime, nsecs_t presentEndTime),
+                (DisplayId displayId, TimePoint presentStartTime, TimePoint presentEndTime),
                 (override));
     MOCK_METHOD(void, setSkippedValidate, (DisplayId displayId, bool skipped), (override));
     MOCK_METHOD(void, setRequiresClientComposition,
                 (DisplayId displayId, bool requiresClientComposition), (override));
-    MOCK_METHOD(void, setExpectedPresentTime, (nsecs_t expectedPresentTime), (override));
-    MOCK_METHOD(void, setSfPresentTiming, (nsecs_t presentFenceTime, nsecs_t presentEndTime),
+    MOCK_METHOD(void, setExpectedPresentTime, (TimePoint expectedPresentTime), (override));
+    MOCK_METHOD(void, setSfPresentTiming, (TimePoint presentFenceTime, TimePoint presentEndTime),
                 (override));
     MOCK_METHOD(void, setHwcPresentDelayedTime,
-                (DisplayId displayId,
-                 std::chrono::steady_clock::time_point earliestFrameStartTime));
-    MOCK_METHOD(void, setFrameDelay, (nsecs_t frameDelayDuration), (override));
-    MOCK_METHOD(void, setCommitStart, (nsecs_t commitStartTime), (override));
-    MOCK_METHOD(void, setCompositeEnd, (nsecs_t compositeEndtime), (override));
+                (DisplayId displayId, TimePoint earliestFrameStartTime));
+    MOCK_METHOD(void, setFrameDelay, (Duration frameDelayDuration), (override));
+    MOCK_METHOD(void, setCommitStart, (TimePoint commitStartTime), (override));
+    MOCK_METHOD(void, setCompositeEnd, (TimePoint compositeEndTime), (override));
     MOCK_METHOD(void, setDisplays, (std::vector<DisplayId> & displayIds), (override));
-    MOCK_METHOD(void, setTotalFrameTargetWorkDuration, (int64_t targetDuration), (override));
+    MOCK_METHOD(void, setTotalFrameTargetWorkDuration, (Duration targetDuration), (override));
 };
 
 } // namespace mock
diff --git a/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp b/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp
index 566537b..cb2c8c5 100644
--- a/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp
+++ b/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp
@@ -59,8 +59,6 @@
 using android::hardware::power::Mode;
 using android::hardware::power::WorkDuration;
 
-using scheduler::OneShotTimer;
-
 PowerAdvisor::~PowerAdvisor() = default;
 
 namespace {
@@ -196,7 +194,7 @@
     return mPowerHintSessionRunning;
 }
 
-void PowerAdvisor::setTargetWorkDuration(int64_t targetDuration) {
+void PowerAdvisor::setTargetWorkDuration(Duration targetDuration) {
     if (!usePowerHintSession()) {
         ALOGV("Power hint session target duration cannot be set, skipping");
         return;
@@ -215,13 +213,13 @@
         ALOGV("Actual work duration power hint cannot be sent, skipping");
         return;
     }
-    const std::optional<nsecs_t> actualDuration = estimateWorkDuration(false);
+    const std::optional<Duration> actualDuration = estimateWorkDuration(false);
     if (actualDuration.has_value()) {
         std::lock_guard lock(mPowerHalMutex);
         HalWrapper* const halWrapper = getPowerHal();
         if (halWrapper != nullptr) {
-            halWrapper->sendActualWorkDuration(*actualDuration + kTargetSafetyMargin.count(),
-                                               systemTime());
+            halWrapper->sendActualWorkDuration(*actualDuration + kTargetSafetyMargin,
+                                               TimePoint::now());
         }
     }
 }
@@ -232,14 +230,14 @@
         return;
     }
 
-    const std::optional<nsecs_t> predictedDuration = estimateWorkDuration(true);
+    const std::optional<Duration> predictedDuration = estimateWorkDuration(true);
 
     if (predictedDuration.has_value()) {
         std::lock_guard lock(mPowerHalMutex);
         HalWrapper* const halWrapper = getPowerHal();
         if (halWrapper != nullptr) {
-            halWrapper->sendActualWorkDuration(*predictedDuration + kTargetSafetyMargin.count(),
-                                               systemTime());
+            halWrapper->sendActualWorkDuration(*predictedDuration + kTargetSafetyMargin,
+                                               TimePoint::now());
         }
     }
 }
@@ -281,22 +279,22 @@
                 }
             }
             displayData.lastValidGpuStartTime = displayData.gpuStartTime;
-            displayData.lastValidGpuEndTime = signalTime;
+            displayData.lastValidGpuEndTime = TimePoint::fromNs(signalTime);
         }
     }
     displayData.gpuEndFenceTime = std::move(fenceTime);
-    displayData.gpuStartTime = systemTime();
+    displayData.gpuStartTime = TimePoint::now();
 }
 
-void PowerAdvisor::setHwcValidateTiming(DisplayId displayId, nsecs_t validateStartTime,
-                                        nsecs_t validateEndTime) {
+void PowerAdvisor::setHwcValidateTiming(DisplayId displayId, TimePoint validateStartTime,
+                                        TimePoint validateEndTime) {
     DisplayTimingData& displayData = mDisplayTimingData[displayId];
     displayData.hwcValidateStartTime = validateStartTime;
     displayData.hwcValidateEndTime = validateEndTime;
 }
 
-void PowerAdvisor::setHwcPresentTiming(DisplayId displayId, nsecs_t presentStartTime,
-                                       nsecs_t presentEndTime) {
+void PowerAdvisor::setHwcPresentTiming(DisplayId displayId, TimePoint presentStartTime,
+                                       TimePoint presentEndTime) {
     DisplayTimingData& displayData = mDisplayTimingData[displayId];
     displayData.hwcPresentStartTime = presentStartTime;
     displayData.hwcPresentEndTime = presentEndTime;
@@ -311,43 +309,41 @@
     mDisplayTimingData[displayId].usedClientComposition = requiresClientComposition;
 }
 
-void PowerAdvisor::setExpectedPresentTime(nsecs_t expectedPresentTime) {
+void PowerAdvisor::setExpectedPresentTime(TimePoint expectedPresentTime) {
     mExpectedPresentTimes.append(expectedPresentTime);
 }
 
-void PowerAdvisor::setSfPresentTiming(nsecs_t presentFenceTime, nsecs_t presentEndTime) {
+void PowerAdvisor::setSfPresentTiming(TimePoint presentFenceTime, TimePoint presentEndTime) {
     mLastSfPresentEndTime = presentEndTime;
     mLastPresentFenceTime = presentFenceTime;
 }
 
-void PowerAdvisor::setFrameDelay(nsecs_t frameDelayDuration) {
+void PowerAdvisor::setFrameDelay(Duration frameDelayDuration) {
     mFrameDelayDuration = frameDelayDuration;
 }
 
-void PowerAdvisor::setHwcPresentDelayedTime(
-        DisplayId displayId, std::chrono::steady_clock::time_point earliestFrameStartTime) {
-    mDisplayTimingData[displayId].hwcPresentDelayedTime =
-            (earliestFrameStartTime - std::chrono::steady_clock::now()).count() + systemTime();
+void PowerAdvisor::setHwcPresentDelayedTime(DisplayId displayId, TimePoint earliestFrameStartTime) {
+    mDisplayTimingData[displayId].hwcPresentDelayedTime = earliestFrameStartTime;
 }
 
-void PowerAdvisor::setCommitStart(nsecs_t commitStartTime) {
+void PowerAdvisor::setCommitStart(TimePoint commitStartTime) {
     mCommitStartTimes.append(commitStartTime);
 }
 
-void PowerAdvisor::setCompositeEnd(nsecs_t compositeEnd) {
-    mLastPostcompDuration = compositeEnd - mLastSfPresentEndTime;
+void PowerAdvisor::setCompositeEnd(TimePoint compositeEndTime) {
+    mLastPostcompDuration = compositeEndTime - mLastSfPresentEndTime;
 }
 
 void PowerAdvisor::setDisplays(std::vector<DisplayId>& displayIds) {
     mDisplayIds = displayIds;
 }
 
-void PowerAdvisor::setTotalFrameTargetWorkDuration(nsecs_t targetDuration) {
+void PowerAdvisor::setTotalFrameTargetWorkDuration(Duration targetDuration) {
     mTotalFrameTargetDuration = targetDuration;
 }
 
 std::vector<DisplayId> PowerAdvisor::getOrderedDisplayIds(
-        std::optional<nsecs_t> DisplayTimingData::*sortBy) {
+        std::optional<TimePoint> DisplayTimingData::*sortBy) {
     std::vector<DisplayId> sortedDisplays;
     std::copy_if(mDisplayIds.begin(), mDisplayIds.end(), std::back_inserter(sortedDisplays),
                  [&](DisplayId id) {
@@ -360,33 +356,34 @@
     return sortedDisplays;
 }
 
-std::optional<nsecs_t> PowerAdvisor::estimateWorkDuration(bool earlyHint) {
+std::optional<Duration> PowerAdvisor::estimateWorkDuration(bool earlyHint) {
     if (earlyHint && (!mExpectedPresentTimes.isFull() || !mCommitStartTimes.isFull())) {
         return std::nullopt;
     }
 
     // Tracks when we finish presenting to hwc
-    nsecs_t estimatedEndTime = mCommitStartTimes[0];
+    TimePoint estimatedEndTime = mCommitStartTimes[0];
 
     // How long we spent this frame not doing anything, waiting for fences or vsync
-    nsecs_t idleDuration = 0;
+    Duration idleDuration = 0ns;
 
     // Most recent previous gpu end time in the current frame, probably from a prior display, used
     // as the start time for the next gpu operation if it ran over time since it probably blocked
-    std::optional<nsecs_t> previousValidGpuEndTime;
+    std::optional<TimePoint> previousValidGpuEndTime;
 
     // The currently estimated gpu end time for the frame,
     // used to accumulate gpu time as we iterate over the active displays
-    std::optional<nsecs_t> estimatedGpuEndTime;
+    std::optional<TimePoint> estimatedGpuEndTime;
 
     // If we're predicting at the start of the frame, we use last frame as our reference point
     // If we're predicting at the end of the frame, we use the current frame as a reference point
-    nsecs_t referenceFrameStartTime = (earlyHint ? mCommitStartTimes[-1] : mCommitStartTimes[0]);
+    TimePoint referenceFrameStartTime = (earlyHint ? mCommitStartTimes[-1] : mCommitStartTimes[0]);
 
     // When the prior frame should be presenting to the display
     // If we're predicting at the start of the frame, we use last frame's expected present time
     // If we're predicting at the end of the frame, the present fence time is already known
-    nsecs_t lastFramePresentTime = (earlyHint ? mExpectedPresentTimes[-1] : mLastPresentFenceTime);
+    TimePoint lastFramePresentTime =
+            (earlyHint ? mExpectedPresentTimes[-1] : mLastPresentFenceTime);
 
     // The timing info for the previously calculated display, if there was one
     std::optional<DisplayTimeline> previousDisplayReferenceTiming;
@@ -427,10 +424,10 @@
         // Track how long we spent waiting for the fence, can be excluded from the timing estimate
         idleDuration += estimatedTiming.probablyWaitsForPresentFence
                 ? lastFramePresentTime - estimatedTiming.presentFenceWaitStartTime
-                : 0;
+                : 0ns;
 
         // Track how long we spent waiting to present, can be excluded from the timing estimate
-        idleDuration += earlyHint ? 0 : referenceTiming.hwcPresentDelayDuration;
+        idleDuration += earlyHint ? 0ns : referenceTiming.hwcPresentDelayDuration;
 
         // Estimate the reference frame's gpu timing
         auto gpuTiming = displayData.estimateGpuTiming(previousValidGpuEndTime);
@@ -438,15 +435,15 @@
             previousValidGpuEndTime = gpuTiming->startTime + gpuTiming->duration;
 
             // Estimate the prediction frame's gpu end time from the reference frame
-            estimatedGpuEndTime =
-                    std::max(estimatedTiming.hwcPresentStartTime, estimatedGpuEndTime.value_or(0)) +
+            estimatedGpuEndTime = std::max(estimatedTiming.hwcPresentStartTime,
+                                           estimatedGpuEndTime.value_or(TimePoint{0ns})) +
                     gpuTiming->duration;
         }
         previousDisplayReferenceTiming = referenceTiming;
     }
-    ATRACE_INT64("Idle duration", idleDuration);
+    ATRACE_INT64("Idle duration", idleDuration.ns());
 
-    nsecs_t estimatedFlingerEndTime = earlyHint ? estimatedEndTime : mLastSfPresentEndTime;
+    TimePoint estimatedFlingerEndTime = earlyHint ? estimatedEndTime : mLastSfPresentEndTime;
 
     // Don't count time spent idly waiting in the estimate as we could do more work in that time
     estimatedEndTime -= idleDuration;
@@ -454,21 +451,22 @@
 
     // We finish the frame when both present and the gpu are done, so wait for the later of the two
     // Also add the frame delay duration since the target did not move while we were delayed
-    nsecs_t totalDuration = mFrameDelayDuration +
-            std::max(estimatedEndTime, estimatedGpuEndTime.value_or(0)) - mCommitStartTimes[0];
+    Duration totalDuration = mFrameDelayDuration +
+            std::max(estimatedEndTime, estimatedGpuEndTime.value_or(TimePoint{0ns})) -
+            mCommitStartTimes[0];
 
     // We finish SurfaceFlinger when post-composition finishes, so add that in here
-    nsecs_t flingerDuration =
+    Duration flingerDuration =
             estimatedFlingerEndTime + mLastPostcompDuration - mCommitStartTimes[0];
 
     // Combine the two timings into a single normalized one
-    nsecs_t combinedDuration = combineTimingEstimates(totalDuration, flingerDuration);
+    Duration combinedDuration = combineTimingEstimates(totalDuration, flingerDuration);
 
     return std::make_optional(combinedDuration);
 }
 
-nsecs_t PowerAdvisor::combineTimingEstimates(nsecs_t totalDuration, nsecs_t flingerDuration) {
-    nsecs_t targetDuration;
+Duration PowerAdvisor::combineTimingEstimates(Duration totalDuration, Duration flingerDuration) {
+    Duration targetDuration{0ns};
     {
         std::lock_guard lock(mPowerHalMutex);
         targetDuration = *getPowerHal()->getTargetWorkDuration();
@@ -477,17 +475,18 @@
 
     // Normalize total to the flinger target (vsync period) since that's how often we actually send
     // hints
-    nsecs_t normalizedTotalDuration = (targetDuration * totalDuration) / *mTotalFrameTargetDuration;
+    Duration normalizedTotalDuration = Duration::fromNs((targetDuration.ns() * totalDuration.ns()) /
+                                                        mTotalFrameTargetDuration->ns());
     return std::max(flingerDuration, normalizedTotalDuration);
 }
 
 PowerAdvisor::DisplayTimeline PowerAdvisor::DisplayTimeline::estimateTimelineFromReference(
-        nsecs_t fenceTime, nsecs_t displayStartTime) {
+        TimePoint fenceTime, TimePoint displayStartTime) {
     DisplayTimeline estimated;
     estimated.hwcPresentStartTime = displayStartTime;
 
     // We don't predict waiting for vsync alignment yet
-    estimated.hwcPresentDelayDuration = 0;
+    estimated.hwcPresentDelayDuration = 0ns;
 
     // How long we expect to run before we start waiting for the fence
     // For now just re-use last frame's post-present duration and assume it will not change much
@@ -502,12 +501,11 @@
 }
 
 PowerAdvisor::DisplayTimeline PowerAdvisor::DisplayTimingData::calculateDisplayTimeline(
-        nsecs_t fenceTime) {
+        TimePoint fenceTime) {
     DisplayTimeline timeline;
     // How long between calling hwc present and trying to wait on the fence
-    const nsecs_t fenceWaitStartDelay =
-            (skippedValidate ? kFenceWaitStartDelaySkippedValidate : kFenceWaitStartDelayValidated)
-                    .count();
+    const Duration fenceWaitStartDelay =
+            (skippedValidate ? kFenceWaitStartDelaySkippedValidate : kFenceWaitStartDelayValidated);
 
     // Did our reference frame wait for an appropriate vsync before calling into hwc
     const bool waitedOnHwcPresentTime = hwcPresentDelayedTime.has_value() &&
@@ -522,7 +520,7 @@
 
     // How long hwc present was delayed waiting for the next appropriate vsync
     timeline.hwcPresentDelayDuration =
-            (waitedOnHwcPresentTime ? *hwcPresentDelayedTime - *hwcPresentStartTime : 0);
+            (waitedOnHwcPresentTime ? *hwcPresentDelayedTime - *hwcPresentStartTime : 0ns);
     // When we started waiting for the present fence after calling into hwc present
     timeline.presentFenceWaitStartTime =
             timeline.hwcPresentStartTime + timeline.hwcPresentDelayDuration + fenceWaitStartDelay;
@@ -537,23 +535,26 @@
 }
 
 std::optional<PowerAdvisor::GpuTimeline> PowerAdvisor::DisplayTimingData::estimateGpuTiming(
-        std::optional<nsecs_t> previousEnd) {
+        std::optional<TimePoint> previousEndTime) {
     if (!(usedClientComposition && lastValidGpuStartTime.has_value() && gpuEndFenceTime)) {
         return std::nullopt;
     }
-    const nsecs_t latestGpuStartTime = std::max(previousEnd.value_or(0), *gpuStartTime);
-    const nsecs_t latestGpuEndTime = gpuEndFenceTime->getSignalTime();
-    nsecs_t gpuDuration = 0;
-    if (latestGpuEndTime != Fence::SIGNAL_TIME_INVALID &&
-        latestGpuEndTime != Fence::SIGNAL_TIME_PENDING) {
+    const TimePoint latestGpuStartTime =
+            std::max(previousEndTime.value_or(TimePoint{0ns}), *gpuStartTime);
+    const nsecs_t gpuEndFenceSignal = gpuEndFenceTime->getSignalTime();
+    Duration gpuDuration{0ns};
+    if (gpuEndFenceSignal != Fence::SIGNAL_TIME_INVALID &&
+        gpuEndFenceSignal != Fence::SIGNAL_TIME_PENDING) {
+        const TimePoint latestGpuEndTime = TimePoint::fromNs(gpuEndFenceSignal);
+
         // If we know how long the most recent gpu duration was, use that
         gpuDuration = latestGpuEndTime - latestGpuStartTime;
     } else if (lastValidGpuEndTime.has_value()) {
         // If we don't have the fence data, use the most recent information we do have
         gpuDuration = *lastValidGpuEndTime - *lastValidGpuStartTime;
-        if (latestGpuEndTime == Fence::SIGNAL_TIME_PENDING) {
+        if (gpuEndFenceSignal == Fence::SIGNAL_TIME_PENDING) {
             // If pending but went over the previous duration, use current time as the end
-            gpuDuration = std::max(gpuDuration, systemTime() - latestGpuStartTime);
+            gpuDuration = std::max(gpuDuration, Duration{TimePoint::now() - latestGpuStartTime});
         }
     }
     return GpuTimeline{.duration = gpuDuration, .startTime = latestGpuStartTime};
@@ -614,15 +615,15 @@
 
     bool startPowerHintSession() override { return false; }
 
-    void setTargetWorkDuration(int64_t) override {}
+    void setTargetWorkDuration(Duration) override {}
 
-    void sendActualWorkDuration(int64_t, nsecs_t) override {}
+    void sendActualWorkDuration(Duration, TimePoint) override {}
 
     bool shouldReconnectHAL() override { return false; }
 
     std::vector<int32_t> getPowerHintSessionThreadIds() override { return std::vector<int32_t>{}; }
 
-    std::optional<int64_t> getTargetWorkDuration() override { return std::nullopt; }
+    std::optional<Duration> getTargetWorkDuration() override { return std::nullopt; }
 
 private:
     const sp<V1_3::IPower> mPowerHal = nullptr;
@@ -640,9 +641,6 @@
     }
 
     mSupportsPowerHint = checkPowerHintSessionSupported();
-
-    // Currently set to 0 to disable rate limiter by default
-    mAllowedActualDeviation = base::GetIntProperty<nsecs_t>("debug.sf.allowed_actual_deviation", 0);
 }
 
 AidlPowerHalWrapper::~AidlPowerHalWrapper() {
@@ -730,9 +728,9 @@
         ALOGV("Cannot start power hint session, skipping");
         return false;
     }
-    auto ret =
-            mPowerHal->createHintSession(getpid(), static_cast<int32_t>(getuid()),
-                                         mPowerHintThreadIds, mTargetDuration, &mPowerHintSession);
+    auto ret = mPowerHal->createHintSession(getpid(), static_cast<int32_t>(getuid()),
+                                            mPowerHintThreadIds, mTargetDuration.ns(),
+                                            &mPowerHintSession);
     if (!ret.isOk()) {
         ALOGW("Failed to start power hint session with error: %s",
               ret.exceptionToString(ret.exceptionCode()).c_str());
@@ -742,14 +740,14 @@
     return isPowerHintSessionRunning();
 }
 
-void AidlPowerHalWrapper::setTargetWorkDuration(int64_t targetDuration) {
+void AidlPowerHalWrapper::setTargetWorkDuration(Duration targetDuration) {
     ATRACE_CALL();
     mTargetDuration = targetDuration;
-    if (sTraceHintSessionData) ATRACE_INT64("Time target", targetDuration);
+    if (sTraceHintSessionData) ATRACE_INT64("Time target", targetDuration.ns());
     if (isPowerHintSessionRunning() && (targetDuration != mLastTargetDurationSent)) {
-        ALOGV("Sending target time: %" PRId64 "ns", targetDuration);
+        ALOGV("Sending target time: %" PRId64 "ns", targetDuration.ns());
         mLastTargetDurationSent = targetDuration;
-        auto ret = mPowerHintSession->updateTargetWorkDuration(targetDuration);
+        auto ret = mPowerHintSession->updateTargetWorkDuration(targetDuration.ns());
         if (!ret.isOk()) {
             ALOGW("Failed to set power hint target work duration with error: %s",
                   ret.exceptionMessage().c_str());
@@ -758,65 +756,40 @@
     }
 }
 
-bool AidlPowerHalWrapper::shouldReportActualDurations() {
-    // Report if we have never reported before or will go stale next frame
-    if (!mLastActualDurationSent.has_value() ||
-        (mLastTargetDurationSent + systemTime() - mLastActualReportTimestamp) >
-                kStaleTimeout.count()) {
-        return true;
-    }
-
-    if (!mActualDuration.has_value()) {
-        return false;
-    }
-    // Report if the change in actual duration exceeds the threshold
-    return abs(*mActualDuration - *mLastActualDurationSent) > mAllowedActualDeviation;
-}
-
-void AidlPowerHalWrapper::sendActualWorkDuration(int64_t actualDuration, nsecs_t timestamp) {
+void AidlPowerHalWrapper::sendActualWorkDuration(Duration actualDuration, TimePoint timestamp) {
     ATRACE_CALL();
-
-    if (actualDuration < 0 || !isPowerHintSessionRunning()) {
+    if (actualDuration < 0ns || !isPowerHintSessionRunning()) {
         ALOGV("Failed to send actual work duration, skipping");
         return;
     }
-    const nsecs_t reportedDuration = actualDuration;
-
-    mActualDuration = reportedDuration;
+    mActualDuration = actualDuration;
     WorkDuration duration;
-    duration.durationNanos = reportedDuration;
-    duration.timeStampNanos = timestamp;
+    duration.durationNanos = actualDuration.ns();
+    duration.timeStampNanos = timestamp.ns();
     mPowerHintQueue.push_back(duration);
 
     if (sTraceHintSessionData) {
-        ATRACE_INT64("Measured duration", actualDuration);
-        ATRACE_INT64("Target error term", actualDuration - mTargetDuration);
+        ATRACE_INT64("Measured duration", actualDuration.ns());
+        ATRACE_INT64("Target error term", Duration{actualDuration - mTargetDuration}.ns());
 
-        ATRACE_INT64("Reported duration", reportedDuration);
-        ATRACE_INT64("Reported target", mLastTargetDurationSent);
-        ATRACE_INT64("Reported target error term", reportedDuration - mLastTargetDurationSent);
+        ATRACE_INT64("Reported duration", actualDuration.ns());
+        ATRACE_INT64("Reported target", mLastTargetDurationSent.ns());
+        ATRACE_INT64("Reported target error term",
+                     Duration{actualDuration - mLastTargetDurationSent}.ns());
     }
 
     ALOGV("Sending actual work duration of: %" PRId64 " on reported target: %" PRId64
           " with error: %" PRId64,
-          reportedDuration, mLastTargetDurationSent, reportedDuration - mLastTargetDurationSent);
+          actualDuration.ns(), mLastTargetDurationSent.ns(),
+          Duration{actualDuration - mLastTargetDurationSent}.ns());
 
-    // This rate limiter queues similar duration reports to the powerhal into
-    // batches to avoid excessive binder calls. The criteria to send a given batch
-    // are outlined in shouldReportActualDurationsNow()
-    if (shouldReportActualDurations()) {
-        ALOGV("Sending hint update batch");
-        mLastActualReportTimestamp = systemTime();
-        auto ret = mPowerHintSession->reportActualWorkDuration(mPowerHintQueue);
-        if (!ret.isOk()) {
-            ALOGW("Failed to report actual work durations with error: %s",
-                  ret.exceptionMessage().c_str());
-            mShouldReconnectHal = true;
-        }
-        mPowerHintQueue.clear();
-        // We save the actual duration here for rate limiting
-        mLastActualDurationSent = actualDuration;
+    auto ret = mPowerHintSession->reportActualWorkDuration(mPowerHintQueue);
+    if (!ret.isOk()) {
+        ALOGW("Failed to report actual work durations with error: %s",
+              ret.exceptionMessage().c_str());
+        mShouldReconnectHal = true;
     }
+    mPowerHintQueue.clear();
 }
 
 bool AidlPowerHalWrapper::shouldReconnectHAL() {
@@ -827,14 +800,10 @@
     return mPowerHintThreadIds;
 }
 
-std::optional<int64_t> AidlPowerHalWrapper::getTargetWorkDuration() {
+std::optional<Duration> AidlPowerHalWrapper::getTargetWorkDuration() {
     return mTargetDuration;
 }
 
-void AidlPowerHalWrapper::setAllowedActualDeviation(nsecs_t allowedDeviation) {
-    mAllowedActualDeviation = allowedDeviation;
-}
-
 const bool AidlPowerHalWrapper::sTraceHintSessionData =
         base::GetBoolProperty(std::string("debug.sf.trace_hint_sessions"), false);
 
@@ -845,7 +814,7 @@
 
     // Grab old hint session values before we destroy any existing wrapper
     std::vector<int32_t> oldPowerHintSessionThreadIds;
-    std::optional<int64_t> oldTargetWorkDuration;
+    std::optional<Duration> oldTargetWorkDuration;
 
     if (mHalWrapper != nullptr) {
         oldPowerHintSessionThreadIds = mHalWrapper->getPowerHintSessionThreadIds();
diff --git a/services/surfaceflinger/DisplayHardware/PowerAdvisor.h b/services/surfaceflinger/DisplayHardware/PowerAdvisor.h
index 53db612..1c9d123 100644
--- a/services/surfaceflinger/DisplayHardware/PowerAdvisor.h
+++ b/services/surfaceflinger/DisplayHardware/PowerAdvisor.h
@@ -27,6 +27,7 @@
 
 #include <android/hardware/power/IPower.h>
 #include <compositionengine/impl/OutputCompositionState.h>
+#include <scheduler/Time.h>
 #include <ui/DisplayIdentification.h>
 #include "../Scheduler/OneShotTimer.h"
 
@@ -53,7 +54,7 @@
     virtual bool supportsPowerHintSession() = 0;
     virtual bool isPowerHintSessionRunning() = 0;
     // Sends a power hint that updates to the target work duration for the frame
-    virtual void setTargetWorkDuration(nsecs_t targetDuration) = 0;
+    virtual void setTargetWorkDuration(Duration targetDuration) = 0;
     // Sends a power hint for the actual known work duration at the end of the frame
     virtual void sendActualWorkDuration() = 0;
     // Sends a power hint for the upcoming frame predicted from previous frame timing
@@ -65,33 +66,33 @@
     // Provides PowerAdvisor with a copy of the gpu fence so it can determine the gpu end time
     virtual void setGpuFenceTime(DisplayId displayId, std::unique_ptr<FenceTime>&& fenceTime) = 0;
     // Reports the start and end times of a hwc validate call this frame for a given display
-    virtual void setHwcValidateTiming(DisplayId displayId, nsecs_t validateStartTime,
-                                      nsecs_t validateEndTime) = 0;
+    virtual void setHwcValidateTiming(DisplayId displayId, TimePoint validateStartTime,
+                                      TimePoint validateEndTime) = 0;
     // Reports the start and end times of a hwc present call this frame for a given display
-    virtual void setHwcPresentTiming(DisplayId displayId, nsecs_t presentStartTime,
-                                     nsecs_t presentEndTime) = 0;
+    virtual void setHwcPresentTiming(DisplayId displayId, TimePoint presentStartTime,
+                                     TimePoint presentEndTime) = 0;
     // Reports the expected time that the current frame will present to the display
-    virtual void setExpectedPresentTime(nsecs_t expectedPresentTime) = 0;
+    virtual void setExpectedPresentTime(TimePoint expectedPresentTime) = 0;
     // Reports the most recent present fence time and end time once known
-    virtual void setSfPresentTiming(nsecs_t presentFenceTime, nsecs_t presentEndTime) = 0;
+    virtual void setSfPresentTiming(TimePoint presentFenceTime, TimePoint presentEndTime) = 0;
     // Reports whether a display used client composition this frame
     virtual void setRequiresClientComposition(DisplayId displayId,
                                               bool requiresClientComposition) = 0;
     // Reports whether a given display skipped validation this frame
     virtual void setSkippedValidate(DisplayId displayId, bool skipped) = 0;
     // Reports when a hwc present is delayed, and the time that it will resume
-    virtual void setHwcPresentDelayedTime(
-            DisplayId displayId, std::chrono::steady_clock::time_point earliestFrameStartTime) = 0;
+    virtual void setHwcPresentDelayedTime(DisplayId displayId,
+                                          TimePoint earliestFrameStartTime) = 0;
     // Reports the start delay for SurfaceFlinger this frame
-    virtual void setFrameDelay(nsecs_t frameDelayDuration) = 0;
+    virtual void setFrameDelay(Duration frameDelayDuration) = 0;
     // Reports the SurfaceFlinger commit start time this frame
-    virtual void setCommitStart(nsecs_t commitStartTime) = 0;
+    virtual void setCommitStart(TimePoint commitStartTime) = 0;
     // Reports the SurfaceFlinger composite end time this frame
-    virtual void setCompositeEnd(nsecs_t compositeEndTime) = 0;
+    virtual void setCompositeEnd(TimePoint compositeEndTime) = 0;
     // Reports the list of the currently active displays
     virtual void setDisplays(std::vector<DisplayId>& displayIds) = 0;
     // Sets the target duration for the entire pipeline including the gpu
-    virtual void setTotalFrameTargetWorkDuration(nsecs_t targetDuration) = 0;
+    virtual void setTotalFrameTargetWorkDuration(Duration targetDuration) = 0;
 };
 
 namespace impl {
@@ -111,11 +112,11 @@
         virtual void restartPowerHintSession() = 0;
         virtual void setPowerHintSessionThreadIds(const std::vector<int32_t>& threadIds) = 0;
         virtual bool startPowerHintSession() = 0;
-        virtual void setTargetWorkDuration(nsecs_t targetDuration) = 0;
-        virtual void sendActualWorkDuration(nsecs_t actualDuration, nsecs_t timestamp) = 0;
+        virtual void setTargetWorkDuration(Duration targetDuration) = 0;
+        virtual void sendActualWorkDuration(Duration actualDuration, TimePoint timestamp) = 0;
         virtual bool shouldReconnectHAL() = 0;
         virtual std::vector<int32_t> getPowerHintSessionThreadIds() = 0;
-        virtual std::optional<nsecs_t> getTargetWorkDuration() = 0;
+        virtual std::optional<Duration> getTargetWorkDuration() = 0;
     };
 
     PowerAdvisor(SurfaceFlinger& flinger);
@@ -129,29 +130,27 @@
     bool usePowerHintSession() override;
     bool supportsPowerHintSession() override;
     bool isPowerHintSessionRunning() override;
-    void setTargetWorkDuration(nsecs_t targetDuration) override;
+    void setTargetWorkDuration(Duration targetDuration) override;
     void sendActualWorkDuration() override;
     void sendPredictedWorkDuration() override;
     void enablePowerHint(bool enabled) override;
     bool startPowerHintSession(const std::vector<int32_t>& threadIds) override;
     void setGpuFenceTime(DisplayId displayId, std::unique_ptr<FenceTime>&& fenceTime);
-    void setHwcValidateTiming(DisplayId displayId, nsecs_t valiateStartTime,
-                              nsecs_t validateEndTime) override;
-    void setHwcPresentTiming(DisplayId displayId, nsecs_t presentStartTime,
-                             nsecs_t presentEndTime) override;
+    void setHwcValidateTiming(DisplayId displayId, TimePoint validateStartTime,
+                              TimePoint validateEndTime) override;
+    void setHwcPresentTiming(DisplayId displayId, TimePoint presentStartTime,
+                             TimePoint presentEndTime) override;
     void setSkippedValidate(DisplayId displayId, bool skipped) override;
     void setRequiresClientComposition(DisplayId displayId, bool requiresClientComposition) override;
-    void setExpectedPresentTime(nsecs_t expectedPresentTime) override;
-    void setSfPresentTiming(nsecs_t presentFenceTime, nsecs_t presentEndTime) override;
-    void setHwcPresentDelayedTime(
-            DisplayId displayId,
-            std::chrono::steady_clock::time_point earliestFrameStartTime) override;
+    void setExpectedPresentTime(TimePoint expectedPresentTime) override;
+    void setSfPresentTiming(TimePoint presentFenceTime, TimePoint presentEndTime) override;
+    void setHwcPresentDelayedTime(DisplayId displayId, TimePoint earliestFrameStartTime) override;
 
-    void setFrameDelay(nsecs_t frameDelayDuration) override;
-    void setCommitStart(nsecs_t commitStartTime) override;
-    void setCompositeEnd(nsecs_t compositeEndTime) override;
+    void setFrameDelay(Duration frameDelayDuration) override;
+    void setCommitStart(TimePoint commitStartTime) override;
+    void setCompositeEnd(TimePoint compositeEndTime) override;
     void setDisplays(std::vector<DisplayId>& displayIds) override;
-    void setTotalFrameTargetWorkDuration(nsecs_t targetDuration) override;
+    void setTotalFrameTargetWorkDuration(Duration targetDuration) override;
 
 private:
     friend class PowerAdvisorTest;
@@ -178,44 +177,45 @@
     // Higher-level timing data used for estimation
     struct DisplayTimeline {
         // The start of hwc present, or the start of validate if it happened there instead
-        nsecs_t hwcPresentStartTime = -1;
+        TimePoint hwcPresentStartTime;
         // The end of hwc present or validate, whichever one actually presented
-        nsecs_t hwcPresentEndTime = -1;
+        TimePoint hwcPresentEndTime;
         // How long the actual hwc present was delayed after hwcPresentStartTime
-        nsecs_t hwcPresentDelayDuration = 0;
+        Duration hwcPresentDelayDuration{0ns};
         // When we think we started waiting for the present fence after calling into hwc present and
         // after potentially waiting for the earliest present time
-        nsecs_t presentFenceWaitStartTime = -1;
+        TimePoint presentFenceWaitStartTime;
         // How long we ran after we finished waiting for the fence but before hwc present finished
-        nsecs_t postPresentFenceHwcPresentDuration = 0;
+        Duration postPresentFenceHwcPresentDuration{0ns};
         // Are we likely to have waited for the present fence during composition
         bool probablyWaitsForPresentFence = false;
         // Estimate one frame's timeline from that of a previous frame
-        DisplayTimeline estimateTimelineFromReference(nsecs_t fenceTime, nsecs_t displayStartTime);
+        DisplayTimeline estimateTimelineFromReference(TimePoint fenceTime,
+                                                      TimePoint displayStartTime);
     };
 
     struct GpuTimeline {
-        nsecs_t duration = 0;
-        nsecs_t startTime = -1;
+        Duration duration{0ns};
+        TimePoint startTime;
     };
 
     // Power hint session data recorded from the pipeline
     struct DisplayTimingData {
         std::unique_ptr<FenceTime> gpuEndFenceTime;
-        std::optional<nsecs_t> gpuStartTime;
-        std::optional<nsecs_t> lastValidGpuEndTime;
-        std::optional<nsecs_t> lastValidGpuStartTime;
-        std::optional<nsecs_t> hwcPresentStartTime;
-        std::optional<nsecs_t> hwcPresentEndTime;
-        std::optional<nsecs_t> hwcValidateStartTime;
-        std::optional<nsecs_t> hwcValidateEndTime;
-        std::optional<nsecs_t> hwcPresentDelayedTime;
+        std::optional<TimePoint> gpuStartTime;
+        std::optional<TimePoint> lastValidGpuEndTime;
+        std::optional<TimePoint> lastValidGpuStartTime;
+        std::optional<TimePoint> hwcPresentStartTime;
+        std::optional<TimePoint> hwcPresentEndTime;
+        std::optional<TimePoint> hwcValidateStartTime;
+        std::optional<TimePoint> hwcValidateEndTime;
+        std::optional<TimePoint> hwcPresentDelayedTime;
         bool usedClientComposition = false;
         bool skippedValidate = false;
         // Calculate high-level timing milestones from more granular display timing data
-        DisplayTimeline calculateDisplayTimeline(nsecs_t fenceTime);
+        DisplayTimeline calculateDisplayTimeline(TimePoint fenceTime);
         // Estimate the gpu duration for a given display from previous gpu timing data
-        std::optional<GpuTimeline> estimateGpuTiming(std::optional<nsecs_t> previousEnd);
+        std::optional<GpuTimeline> estimateGpuTiming(std::optional<TimePoint> previousEndTime);
     };
 
     template <class T, size_t N>
@@ -240,30 +240,31 @@
     };
 
     // Filter and sort the display ids by a given property
-    std::vector<DisplayId> getOrderedDisplayIds(std::optional<nsecs_t> DisplayTimingData::*sortBy);
+    std::vector<DisplayId> getOrderedDisplayIds(
+            std::optional<TimePoint> DisplayTimingData::*sortBy);
     // Estimates a frame's total work duration including gpu time.
     // Runs either at the beginning or end of a frame, using the most recent data available
-    std::optional<nsecs_t> estimateWorkDuration(bool earlyHint);
+    std::optional<Duration> estimateWorkDuration(bool earlyHint);
     // There are two different targets and actual work durations we care about,
     // this normalizes them together and takes the max of the two
-    nsecs_t combineTimingEstimates(nsecs_t totalDuration, nsecs_t flingerDuration);
+    Duration combineTimingEstimates(Duration totalDuration, Duration flingerDuration);
 
     std::unordered_map<DisplayId, DisplayTimingData> mDisplayTimingData;
 
     // Current frame's delay
-    nsecs_t mFrameDelayDuration = 0;
+    Duration mFrameDelayDuration{0ns};
     // Last frame's post-composition duration
-    nsecs_t mLastPostcompDuration = 0;
+    Duration mLastPostcompDuration{0ns};
     // Buffer of recent commit start times
-    RingBuffer<nsecs_t, 2> mCommitStartTimes;
+    RingBuffer<TimePoint, 2> mCommitStartTimes;
     // Buffer of recent expected present times
-    RingBuffer<nsecs_t, 2> mExpectedPresentTimes;
+    RingBuffer<TimePoint, 2> mExpectedPresentTimes;
     // Most recent present fence time, provided by SF after composition engine finishes presenting
-    nsecs_t mLastPresentFenceTime = -1;
+    TimePoint mLastPresentFenceTime;
     // Most recent composition engine present end time, returned with the present fence from SF
-    nsecs_t mLastSfPresentEndTime = -1;
+    TimePoint mLastSfPresentEndTime;
     // Target duration for the entire pipeline including gpu
-    std::optional<nsecs_t> mTotalFrameTargetDuration;
+    std::optional<Duration> mTotalFrameTargetDuration;
     // Updated list of display IDs
     std::vector<DisplayId> mDisplayIds;
 
@@ -273,11 +274,11 @@
 
     // An adjustable safety margin which pads the "actual" value sent to PowerHAL,
     // encouraging more aggressive boosting to give SurfaceFlinger a larger margin for error
-    static constexpr const std::chrono::nanoseconds kTargetSafetyMargin = 1ms;
+    static constexpr const Duration kTargetSafetyMargin{1ms};
 
     // How long we expect hwc to run after the present call until it waits for the fence
-    static constexpr const std::chrono::nanoseconds kFenceWaitStartDelayValidated = 150us;
-    static constexpr const std::chrono::nanoseconds kFenceWaitStartDelaySkippedValidate = 250us;
+    static constexpr const Duration kFenceWaitStartDelayValidated{150us};
+    static constexpr const Duration kFenceWaitStartDelaySkippedValidate{250us};
 };
 
 class AidlPowerHalWrapper : public PowerAdvisor::HalWrapper {
@@ -294,21 +295,17 @@
     void restartPowerHintSession() override;
     void setPowerHintSessionThreadIds(const std::vector<int32_t>& threadIds) override;
     bool startPowerHintSession() override;
-    void setTargetWorkDuration(nsecs_t targetDuration) override;
-    void sendActualWorkDuration(nsecs_t actualDuration, nsecs_t timestamp) override;
+    void setTargetWorkDuration(Duration targetDuration) override;
+    void sendActualWorkDuration(Duration actualDuration, TimePoint timestamp) override;
     bool shouldReconnectHAL() override;
     std::vector<int32_t> getPowerHintSessionThreadIds() override;
-    std::optional<nsecs_t> getTargetWorkDuration() override;
+    std::optional<Duration> getTargetWorkDuration() override;
 
 private:
     friend class AidlPowerHalWrapperTest;
 
     bool checkPowerHintSessionSupported();
     void closePowerHintSession();
-    bool shouldReportActualDurations();
-
-    // Used for testing
-    void setAllowedActualDeviation(nsecs_t);
 
     const sp<hardware::power::IPower> mPowerHal = nullptr;
     bool mHasExpensiveRendering = false;
@@ -323,24 +320,15 @@
     // Queue of actual durations saved to report
     std::vector<hardware::power::WorkDuration> mPowerHintQueue;
     // The latest values we have received for target and actual
-    nsecs_t mTargetDuration = kDefaultTarget.count();
-    std::optional<nsecs_t> mActualDuration;
+    Duration mTargetDuration = kDefaultTargetDuration;
+    std::optional<Duration> mActualDuration;
     // The list of thread ids, stored so we can restart the session from this class if needed
     std::vector<int32_t> mPowerHintThreadIds;
     bool mSupportsPowerHint = false;
-    // Keep track of the last messages sent for rate limiter change detection
-    std::optional<nsecs_t> mLastActualDurationSent;
-    // Timestamp of the last report we sent, used to avoid stale sessions
-    nsecs_t mLastActualReportTimestamp = 0;
-    nsecs_t mLastTargetDurationSent = kDefaultTarget.count();
-    // Max amount the error term can vary without causing an actual value report
-    nsecs_t mAllowedActualDeviation = -1;
+    Duration mLastTargetDurationSent = kDefaultTargetDuration;
     // Whether we should emit ATRACE_INT data for hint sessions
     static const bool sTraceHintSessionData;
-    static constexpr const std::chrono::nanoseconds kDefaultTarget = 16ms;
-    // Amount of time after the last message was sent before the session goes stale
-    // actually 100ms but we use 80 here to give some slack
-    static constexpr const std::chrono::nanoseconds kStaleTimeout = 80ms;
+    static constexpr Duration kDefaultTargetDuration{16ms};
 };
 
 } // namespace impl
diff --git a/services/surfaceflinger/Scheduler/VSyncReactor.cpp b/services/surfaceflinger/Scheduler/VSyncReactor.cpp
index 13cd304..e23945d 100644
--- a/services/surfaceflinger/Scheduler/VSyncReactor.cpp
+++ b/services/surfaceflinger/Scheduler/VSyncReactor.cpp
@@ -19,6 +19,7 @@
 #define LOG_TAG "VSyncReactor"
 //#define LOG_NDEBUG 0
 
+#include <assert.h>
 #include <cutils/properties.h>
 #include <log/log.h>
 #include <utils/Trace.h>
diff --git a/services/surfaceflinger/Scheduler/include/scheduler/Time.h b/services/surfaceflinger/Scheduler/include/scheduler/Time.h
index f00d456..2ca55d4 100644
--- a/services/surfaceflinger/Scheduler/include/scheduler/Time.h
+++ b/services/surfaceflinger/Scheduler/include/scheduler/Time.h
@@ -41,6 +41,8 @@
 
     static constexpr TimePoint fromNs(nsecs_t);
 
+    static TimePoint now() { return scheduler::SchedulerClock::now(); };
+
     nsecs_t ns() const;
 };
 
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 57ca859..c4165e7 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1056,7 +1056,7 @@
     }
 
     const auto& schedule = mScheduler->getVsyncSchedule();
-    outStats->vsyncTime = schedule.vsyncDeadlineAfter(scheduler::SchedulerClock::now()).ns();
+    outStats->vsyncTime = schedule.vsyncDeadlineAfter(TimePoint::now()).ns();
     outStats->vsyncPeriod = schedule.period().ns();
     return NO_ERROR;
 }
@@ -1972,7 +1972,7 @@
                                                           : calculateExpectedPresentTime(frameTime);
 
     ATRACE_FORMAT("%s %" PRId64 " vsyncIn %.2fms%s", __func__, vsyncId.value,
-                  ticks<std::milli, float>(mExpectedPresentTime - scheduler::SchedulerClock::now()),
+                  ticks<std::milli, float>(mExpectedPresentTime - TimePoint::now()),
                   mExpectedPresentTime == expectedVsyncTime ? "" : " (adjusted)");
 
     const Period vsyncPeriod = mScheduler->getVsyncSchedule().period();
@@ -2059,16 +2059,16 @@
             activeDisplay->getPowerMode() == hal::PowerMode::ON;
     if (mPowerHintSessionEnabled) {
         const auto& display = FTL_FAKE_GUARD(mStateLock, getDefaultDisplayDeviceLocked()).get();
-        const nsecs_t vsyncPeriod = display->getActiveMode()->getVsyncPeriod();
-        mPowerAdvisor->setCommitStart(frameTime.ns());
-        mPowerAdvisor->setExpectedPresentTime(mExpectedPresentTime.ns());
+        const Period vsyncPeriod = Period::fromNs(display->getActiveMode()->getVsyncPeriod());
+        mPowerAdvisor->setCommitStart(frameTime);
+        mPowerAdvisor->setExpectedPresentTime(mExpectedPresentTime);
 
         // Frame delay is how long we should have minus how long we actually have.
         const Duration idealSfWorkDuration = mVsyncModulator->getVsyncConfig().sfWorkDuration;
         const Duration frameDelay = idealSfWorkDuration - (mExpectedPresentTime - frameTime);
 
-        mPowerAdvisor->setFrameDelay(frameDelay.ns());
-        mPowerAdvisor->setTotalFrameTargetWorkDuration(idealSfWorkDuration.ns());
+        mPowerAdvisor->setFrameDelay(frameDelay);
+        mPowerAdvisor->setTotalFrameTargetWorkDuration(idealSfWorkDuration);
         mPowerAdvisor->setTargetWorkDuration(vsyncPeriod);
 
         // Send early hint here to make sure there's not another frame pending
@@ -2228,8 +2228,9 @@
 
     // Send a power hint hint after presentation is finished
     if (mPowerHintSessionEnabled) {
-        mPowerAdvisor->setSfPresentTiming(mPreviousPresentFences[0].fenceTime->getSignalTime(),
-                                          systemTime());
+        mPowerAdvisor->setSfPresentTiming(TimePoint::fromNs(mPreviousPresentFences[0]
+                                                                    .fenceTime->getSignalTime()),
+                                          TimePoint::now());
         if (mPowerHintSessionMode.late) {
             mPowerAdvisor->sendActualWorkDuration();
         }
@@ -2279,7 +2280,7 @@
     }
 
     if (mPowerHintSessionEnabled) {
-        mPowerAdvisor->setCompositeEnd(systemTime());
+        mPowerAdvisor->setCompositeEnd(TimePoint::now());
     }
 }
 
@@ -2376,7 +2377,7 @@
     auto presentFenceTime = std::make_shared<FenceTime>(presentFence);
     mPreviousPresentFences[0] = {presentFence, presentFenceTime};
 
-    const TimePoint presentTime = scheduler::SchedulerClock::now();
+    const TimePoint presentTime = TimePoint::now();
 
     // Set presentation information before calling Layer::releasePendingBuffer, such that jank
     // information from previous' frame classification is already available when sending jank info
diff --git a/services/surfaceflinger/tests/unittests/AidlPowerHalWrapperTest.cpp b/services/surfaceflinger/tests/unittests/AidlPowerHalWrapperTest.cpp
index 69d30c4..513f779 100644
--- a/services/surfaceflinger/tests/unittests/AidlPowerHalWrapperTest.cpp
+++ b/services/surfaceflinger/tests/unittests/AidlPowerHalWrapperTest.cpp
@@ -50,10 +50,8 @@
     sp<NiceMock<MockIPower>> mMockHal = nullptr;
     sp<NiceMock<MockIPowerHintSession>> mMockSession = nullptr;
     void verifyAndClearExpectations();
-    void sendActualWorkDurationGroup(std::vector<WorkDuration> durations,
-                                     std::chrono::nanoseconds sleepBeforeLastSend);
-    std::chrono::nanoseconds mAllowedDeviation;
-    std::chrono::nanoseconds mStaleTimeout;
+    void sendActualWorkDurationGroup(std::vector<WorkDuration> durations);
+    static constexpr std::chrono::duration kStaleTimeout = 100ms;
 };
 
 void AidlPowerHalWrapperTest::SetUp() {
@@ -61,9 +59,6 @@
     mMockSession = sp<NiceMock<MockIPowerHintSession>>::make();
     ON_CALL(*mMockHal.get(), getHintSessionPreferredRate(_)).WillByDefault(Return(Status::ok()));
     mWrapper = std::make_unique<AidlPowerHalWrapper>(mMockHal);
-    mWrapper->setAllowedActualDeviation(std::chrono::nanoseconds{10ms}.count());
-    mAllowedDeviation = std::chrono::nanoseconds{mWrapper->mAllowedActualDeviation};
-    mStaleTimeout = AidlPowerHalWrapper::kStaleTimeout;
 }
 
 void AidlPowerHalWrapperTest::verifyAndClearExpectations() {
@@ -71,14 +66,11 @@
     Mock::VerifyAndClearExpectations(mMockSession.get());
 }
 
-void AidlPowerHalWrapperTest::sendActualWorkDurationGroup(
-        std::vector<WorkDuration> durations, std::chrono::nanoseconds sleepBeforeLastSend) {
+void AidlPowerHalWrapperTest::sendActualWorkDurationGroup(std::vector<WorkDuration> durations) {
     for (size_t i = 0; i < durations.size(); i++) {
-        if (i == durations.size() - 1) {
-            std::this_thread::sleep_for(sleepBeforeLastSend);
-        }
         auto duration = durations[i];
-        mWrapper->sendActualWorkDuration(duration.durationNanos, duration.timeStampNanos);
+        mWrapper->sendActualWorkDuration(Duration::fromNs(duration.durationNanos),
+                                         TimePoint::fromNs(duration.timeStampNanos));
     }
 }
 
@@ -164,13 +156,13 @@
 
     for (const auto& test : testCases) {
         // reset to 100ms baseline
-        mWrapper->setTargetWorkDuration(1);
-        mWrapper->setTargetWorkDuration(base.count());
+        mWrapper->setTargetWorkDuration(1ns);
+        mWrapper->setTargetWorkDuration(base);
 
-        auto target = test.first;
+        std::chrono::nanoseconds target = test.first;
         EXPECT_CALL(*mMockSession.get(), updateTargetWorkDuration(target.count()))
                 .Times(test.second ? 1 : 0);
-        mWrapper->setTargetWorkDuration(target.count());
+        mWrapper->setTargetWorkDuration(target);
         verifyAndClearExpectations();
     }
 }
@@ -187,7 +179,7 @@
 
     EXPECT_CALL(*mMockSession.get(), updateTargetWorkDuration(1))
             .WillOnce(Return(Status::fromExceptionCode(Status::Exception::EX_ILLEGAL_STATE)));
-    mWrapper->setTargetWorkDuration(1);
+    mWrapper->setTargetWorkDuration(1ns);
     EXPECT_TRUE(mWrapper->shouldReconnectHAL());
 }
 
@@ -206,58 +198,24 @@
     // 100ms
     const std::vector<std::pair<std::vector<std::pair<std::chrono::nanoseconds, nsecs_t>>, bool>>
             testCases = {{{{-1ms, 100}}, false},
-                         {{{100ms - (mAllowedDeviation / 2), 100}}, false},
-                         {{{100ms + (mAllowedDeviation / 2), 100}}, false},
-                         {{{100ms + (mAllowedDeviation + 1ms), 100}}, true},
-                         {{{100ms - (mAllowedDeviation + 1ms), 100}}, true},
+                         {{{50ms, 100}}, true},
                          {{{100ms, 100}, {200ms, 200}}, true},
                          {{{100ms, 500}, {100ms, 600}, {3ms, 600}}, true}};
 
     for (const auto& test : testCases) {
         // reset actual duration
-        sendActualWorkDurationGroup({base}, mStaleTimeout);
+        sendActualWorkDurationGroup({base});
 
         auto raw = test.first;
         std::vector<WorkDuration> durations(raw.size());
         std::transform(raw.begin(), raw.end(), durations.begin(),
                        [](auto d) { return toWorkDuration(d); });
-        EXPECT_CALL(*mMockSession.get(), reportActualWorkDuration(durations))
-                .Times(test.second ? 1 : 0);
-        sendActualWorkDurationGroup(durations, 0ms);
-        verifyAndClearExpectations();
-    }
-}
-
-TEST_F(AidlPowerHalWrapperTest, sendActualWorkDuration_exceedsStaleTime) {
-    ASSERT_TRUE(mWrapper->supportsPowerHintSession());
-
-    std::vector<int32_t> threadIds = {1, 2};
-    mWrapper->setPowerHintSessionThreadIds(threadIds);
-    EXPECT_CALL(*mMockHal.get(), createHintSession(_, _, threadIds, _, _))
-            .WillOnce(DoAll(SetArgPointee<4>(mMockSession), Return(Status::ok())));
-    ASSERT_TRUE(mWrapper->startPowerHintSession());
-    verifyAndClearExpectations();
-
-    auto base = toWorkDuration(100ms, 0);
-    // test cases with actual work durations and whether it should update hint against baseline
-    // 100ms
-    const std::vector<std::tuple<std::vector<std::pair<std::chrono::nanoseconds, nsecs_t>>,
-                                 std::chrono::nanoseconds, bool>>
-            testCases = {{{{100ms, 100}}, mStaleTimeout, true},
-                         {{{100ms + (mAllowedDeviation / 2), 100}}, mStaleTimeout, true},
-                         {{{100ms, 100}}, mStaleTimeout / 2, false}};
-
-    for (const auto& test : testCases) {
-        // reset actual duration
-        sendActualWorkDurationGroup({base}, mStaleTimeout);
-
-        auto raw = std::get<0>(test);
-        std::vector<WorkDuration> durations(raw.size());
-        std::transform(raw.begin(), raw.end(), durations.begin(),
-                       [](auto d) { return toWorkDuration(d); });
-        EXPECT_CALL(*mMockSession.get(), reportActualWorkDuration(durations))
-                .Times(std::get<2>(test) ? 1 : 0);
-        sendActualWorkDurationGroup(durations, std::get<1>(test));
+        for (auto& duration : durations) {
+            EXPECT_CALL(*mMockSession.get(),
+                        reportActualWorkDuration(std::vector<WorkDuration>{duration}))
+                    .Times(test.second ? 1 : 0);
+        }
+        sendActualWorkDurationGroup(durations);
         verifyAndClearExpectations();
     }
 }
@@ -275,7 +233,7 @@
     duration.durationNanos = 1;
     EXPECT_CALL(*mMockSession.get(), reportActualWorkDuration(_))
             .WillOnce(Return(Status::fromExceptionCode(Status::Exception::EX_ILLEGAL_STATE)));
-    sendActualWorkDurationGroup({duration}, 0ms);
+    sendActualWorkDurationGroup({duration});
     EXPECT_TRUE(mWrapper->shouldReconnectHAL());
 }
 
diff --git a/services/surfaceflinger/tests/unittests/PowerAdvisorTest.cpp b/services/surfaceflinger/tests/unittests/PowerAdvisorTest.cpp
index 8711a42..2d66d3c 100644
--- a/services/surfaceflinger/tests/unittests/PowerAdvisorTest.cpp
+++ b/services/surfaceflinger/tests/unittests/PowerAdvisorTest.cpp
@@ -39,15 +39,15 @@
 public:
     void SetUp() override;
     void startPowerHintSession();
-    void fakeBasicFrameTiming(nsecs_t startTime, nsecs_t vsyncPeriod);
-    void setExpectedTiming(nsecs_t startTime, nsecs_t vsyncPeriod);
-    nsecs_t getFenceWaitDelayDuration(bool skipValidate);
+    void fakeBasicFrameTiming(TimePoint startTime, Duration vsyncPeriod);
+    void setExpectedTiming(Duration totalFrameTargetDuration, TimePoint expectedPresentTime);
+    Duration getFenceWaitDelayDuration(bool skipValidate);
 
 protected:
     TestableSurfaceFlinger mFlinger;
     std::unique_ptr<PowerAdvisor> mPowerAdvisor;
     NiceMock<MockAidlPowerHalWrapper>* mMockAidlWrapper;
-    nsecs_t kErrorMargin = std::chrono::nanoseconds(1ms).count();
+    Duration kErrorMargin = 1ms;
 };
 
 void PowerAdvisorTest::SetUp() FTL_FAKE_GUARD(mPowerAdvisor->mPowerHalMutex) {
@@ -67,21 +67,21 @@
     mPowerAdvisor->startPowerHintSession(threadIds);
 }
 
-void PowerAdvisorTest::setExpectedTiming(nsecs_t totalFrameTarget, nsecs_t expectedPresentTime) {
-    mPowerAdvisor->setTotalFrameTargetWorkDuration(totalFrameTarget);
+void PowerAdvisorTest::setExpectedTiming(Duration totalFrameTargetDuration,
+                                         TimePoint expectedPresentTime) {
+    mPowerAdvisor->setTotalFrameTargetWorkDuration(totalFrameTargetDuration);
     mPowerAdvisor->setExpectedPresentTime(expectedPresentTime);
 }
 
-void PowerAdvisorTest::fakeBasicFrameTiming(nsecs_t startTime, nsecs_t vsyncPeriod) {
+void PowerAdvisorTest::fakeBasicFrameTiming(TimePoint startTime, Duration vsyncPeriod) {
     mPowerAdvisor->setCommitStart(startTime);
-    mPowerAdvisor->setFrameDelay(0);
+    mPowerAdvisor->setFrameDelay(0ns);
     mPowerAdvisor->setTargetWorkDuration(vsyncPeriod);
 }
 
-nsecs_t PowerAdvisorTest::getFenceWaitDelayDuration(bool skipValidate) {
+Duration PowerAdvisorTest::getFenceWaitDelayDuration(bool skipValidate) {
     return (skipValidate ? PowerAdvisor::kFenceWaitStartDelaySkippedValidate
-                         : PowerAdvisor::kFenceWaitStartDelayValidated)
-            .count();
+                         : PowerAdvisor::kFenceWaitStartDelayValidated);
 }
 
 namespace {
@@ -93,11 +93,11 @@
     std::vector<DisplayId> displayIds{PhysicalDisplayId::fromPort(42u)};
 
     // 60hz
-    const nsecs_t vsyncPeriod = std::chrono::nanoseconds(1s).count() / 60;
-    const nsecs_t presentDuration = std::chrono::nanoseconds(5ms).count();
-    const nsecs_t postCompDuration = std::chrono::nanoseconds(1ms).count();
+    const Duration vsyncPeriod{std::chrono::nanoseconds(1s) / 60};
+    const Duration presentDuration = 5ms;
+    const Duration postCompDuration = 1ms;
 
-    nsecs_t startTime = 100;
+    TimePoint startTime{100ns};
 
     // advisor only starts on frame 2 so do an initial no-op frame
     fakeBasicFrameTiming(startTime, vsyncPeriod);
@@ -109,14 +109,14 @@
     // increment the frame
     startTime += vsyncPeriod;
 
-    const nsecs_t expectedDuration = kErrorMargin + presentDuration + postCompDuration;
+    const Duration expectedDuration = kErrorMargin + presentDuration + postCompDuration;
     EXPECT_CALL(*mMockAidlWrapper, sendActualWorkDuration(Eq(expectedDuration), _)).Times(1);
 
     fakeBasicFrameTiming(startTime, vsyncPeriod);
     setExpectedTiming(vsyncPeriod, startTime + vsyncPeriod);
     mPowerAdvisor->setDisplays(displayIds);
-    mPowerAdvisor->setHwcValidateTiming(displayIds[0], startTime + 1000000, startTime + 1500000);
-    mPowerAdvisor->setHwcPresentTiming(displayIds[0], startTime + 2000000, startTime + 2500000);
+    mPowerAdvisor->setHwcValidateTiming(displayIds[0], startTime + 1ms, startTime + 1500us);
+    mPowerAdvisor->setHwcPresentTiming(displayIds[0], startTime + 2ms, startTime + 2500us);
     mPowerAdvisor->setSfPresentTiming(startTime, startTime + presentDuration);
     mPowerAdvisor->sendActualWorkDuration();
 }
@@ -128,12 +128,12 @@
     std::vector<DisplayId> displayIds{PhysicalDisplayId::fromPort(42u)};
 
     // 60hz
-    const nsecs_t vsyncPeriod = std::chrono::nanoseconds(1s).count() / 60;
-    const nsecs_t presentDuration = std::chrono::nanoseconds(5ms).count();
-    const nsecs_t postCompDuration = std::chrono::nanoseconds(1ms).count();
-    const nsecs_t hwcBlockedDuration = std::chrono::nanoseconds(500us).count();
+    const Duration vsyncPeriod{std::chrono::nanoseconds(1s) / 60};
+    const Duration presentDuration = 5ms;
+    const Duration postCompDuration = 1ms;
+    const Duration hwcBlockedDuration = 500us;
 
-    nsecs_t startTime = 100;
+    TimePoint startTime{100ns};
 
     // advisor only starts on frame 2 so do an initial no-op frame
     fakeBasicFrameTiming(startTime, vsyncPeriod);
@@ -145,17 +145,17 @@
     // increment the frame
     startTime += vsyncPeriod;
 
-    const nsecs_t expectedDuration = kErrorMargin + presentDuration +
+    const Duration expectedDuration = kErrorMargin + presentDuration +
             getFenceWaitDelayDuration(false) - hwcBlockedDuration + postCompDuration;
     EXPECT_CALL(*mMockAidlWrapper, sendActualWorkDuration(Eq(expectedDuration), _)).Times(1);
 
     fakeBasicFrameTiming(startTime, vsyncPeriod);
     setExpectedTiming(vsyncPeriod, startTime + vsyncPeriod);
     mPowerAdvisor->setDisplays(displayIds);
-    mPowerAdvisor->setHwcValidateTiming(displayIds[0], startTime + 1000000, startTime + 1500000);
-    mPowerAdvisor->setHwcPresentTiming(displayIds[0], startTime + 2000000, startTime + 3000000);
+    mPowerAdvisor->setHwcValidateTiming(displayIds[0], startTime + 1ms, startTime + 1500us);
+    mPowerAdvisor->setHwcPresentTiming(displayIds[0], startTime + 2ms, startTime + 3ms);
     // now report the fence as having fired during the display HWC time
-    mPowerAdvisor->setSfPresentTiming(startTime + 2000000 + hwcBlockedDuration,
+    mPowerAdvisor->setSfPresentTiming(startTime + 2ms + hwcBlockedDuration,
                                       startTime + presentDuration);
     mPowerAdvisor->sendActualWorkDuration();
 }
@@ -168,12 +168,12 @@
                                       GpuVirtualDisplayId(1)};
 
     // 60hz
-    const nsecs_t vsyncPeriod = std::chrono::nanoseconds(1s).count() / 60;
+    const Duration vsyncPeriod{std::chrono::nanoseconds(1s) / 60};
     // make present duration much later than the hwc display by itself will account for
-    const nsecs_t presentDuration = std::chrono::nanoseconds(10ms).count();
-    const nsecs_t postCompDuration = std::chrono::nanoseconds(1ms).count();
+    const Duration presentDuration{10ms};
+    const Duration postCompDuration{1ms};
 
-    nsecs_t startTime = 100;
+    TimePoint startTime{100ns};
 
     // advisor only starts on frame 2 so do an initial no-op frame
     fakeBasicFrameTiming(startTime, vsyncPeriod);
@@ -185,7 +185,7 @@
     // increment the frame
     startTime += vsyncPeriod;
 
-    const nsecs_t expectedDuration = kErrorMargin + presentDuration + postCompDuration;
+    const Duration expectedDuration = kErrorMargin + presentDuration + postCompDuration;
     EXPECT_CALL(*mMockAidlWrapper, sendActualWorkDuration(Eq(expectedDuration), _)).Times(1);
 
     fakeBasicFrameTiming(startTime, vsyncPeriod);
@@ -193,8 +193,8 @@
     mPowerAdvisor->setDisplays(displayIds);
 
     // don't report timing for the gpu displays since they don't use hwc
-    mPowerAdvisor->setHwcValidateTiming(displayIds[0], startTime + 1000000, startTime + 1500000);
-    mPowerAdvisor->setHwcPresentTiming(displayIds[0], startTime + 2000000, startTime + 2500000);
+    mPowerAdvisor->setHwcValidateTiming(displayIds[0], startTime + 1ms, startTime + 1500us);
+    mPowerAdvisor->setHwcPresentTiming(displayIds[0], startTime + 2ms, startTime + 2500us);
     mPowerAdvisor->setSfPresentTiming(startTime, startTime + presentDuration);
     mPowerAdvisor->sendActualWorkDuration();
 }
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockAidlPowerHalWrapper.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockAidlPowerHalWrapper.h
index 657ced3..c2c3d77 100644
--- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockAidlPowerHalWrapper.h
+++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockAidlPowerHalWrapper.h
@@ -17,6 +17,7 @@
 #pragma once
 
 #include <gmock/gmock.h>
+#include <scheduler/Time.h>
 
 #include "DisplayHardware/PowerAdvisor.h"
 
@@ -42,8 +43,8 @@
     MOCK_METHOD(void, setPowerHintSessionThreadIds, (const std::vector<int32_t>& threadIds),
                 (override));
     MOCK_METHOD(bool, startPowerHintSession, (), (override));
-    MOCK_METHOD(void, setTargetWorkDuration, (nsecs_t targetDuration), (override));
-    MOCK_METHOD(void, sendActualWorkDuration, (nsecs_t actualDuration, nsecs_t timestamp),
+    MOCK_METHOD(void, setTargetWorkDuration, (Duration targetDuration), (override));
+    MOCK_METHOD(void, sendActualWorkDuration, (Duration actualDuration, TimePoint timestamp),
                 (override));
     MOCK_METHOD(bool, shouldReconnectHAL, (), (override));
 };
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerAdvisor.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerAdvisor.h
index aede250..fb1b394 100644
--- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerAdvisor.h
+++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerAdvisor.h
@@ -36,7 +36,7 @@
     MOCK_METHOD(bool, usePowerHintSession, (), (override));
     MOCK_METHOD(bool, supportsPowerHintSession, (), (override));
     MOCK_METHOD(bool, isPowerHintSessionRunning, (), (override));
-    MOCK_METHOD(void, setTargetWorkDuration, (int64_t targetDuration), (override));
+    MOCK_METHOD(void, setTargetWorkDuration, (Duration targetDuration), (override));
     MOCK_METHOD(void, sendActualWorkDuration, (), (override));
     MOCK_METHOD(void, sendPredictedWorkDuration, (), (override));
     MOCK_METHOD(void, enablePowerHint, (bool enabled), (override));
@@ -44,25 +44,24 @@
     MOCK_METHOD(void, setGpuFenceTime,
                 (DisplayId displayId, std::unique_ptr<FenceTime>&& fenceTime), (override));
     MOCK_METHOD(void, setHwcValidateTiming,
-                (DisplayId displayId, nsecs_t valiateStartTime, nsecs_t validateEndTime),
+                (DisplayId displayId, TimePoint validateStartTime, TimePoint validateEndTime),
                 (override));
     MOCK_METHOD(void, setHwcPresentTiming,
-                (DisplayId displayId, nsecs_t presentStartTime, nsecs_t presentEndTime),
+                (DisplayId displayId, TimePoint presentStartTime, TimePoint presentEndTime),
                 (override));
     MOCK_METHOD(void, setSkippedValidate, (DisplayId displayId, bool skipped), (override));
     MOCK_METHOD(void, setRequiresClientComposition,
                 (DisplayId displayId, bool requiresClientComposition), (override));
-    MOCK_METHOD(void, setExpectedPresentTime, (nsecs_t expectedPresentTime), (override));
-    MOCK_METHOD(void, setSfPresentTiming, (nsecs_t presentFenceTime, nsecs_t presentEndTime),
+    MOCK_METHOD(void, setExpectedPresentTime, (TimePoint expectedPresentTime), (override));
+    MOCK_METHOD(void, setSfPresentTiming, (TimePoint presentFenceTime, TimePoint presentEndTime),
                 (override));
     MOCK_METHOD(void, setHwcPresentDelayedTime,
-                (DisplayId displayId,
-                 std::chrono::steady_clock::time_point earliestFrameStartTime));
-    MOCK_METHOD(void, setFrameDelay, (nsecs_t frameDelayDuration), (override));
-    MOCK_METHOD(void, setCommitStart, (nsecs_t commitStartTime), (override));
-    MOCK_METHOD(void, setCompositeEnd, (nsecs_t compositeEndtime), (override));
+                (DisplayId displayId, TimePoint earliestFrameStartTime));
+    MOCK_METHOD(void, setFrameDelay, (Duration frameDelayDuration), (override));
+    MOCK_METHOD(void, setCommitStart, (TimePoint commitStartTime), (override));
+    MOCK_METHOD(void, setCompositeEnd, (TimePoint compositeEndTime), (override));
     MOCK_METHOD(void, setDisplays, (std::vector<DisplayId> & displayIds), (override));
-    MOCK_METHOD(void, setTotalFrameTargetWorkDuration, (int64_t targetDuration), (override));
+    MOCK_METHOD(void, setTotalFrameTargetWorkDuration, (Duration targetDuration), (override));
 };
 
 } // namespace android::Hwc2::mock