Merge "TransactionTraceWriter - always overwrite old files" into main
diff --git a/cmds/installd/Android.bp b/cmds/installd/Android.bp
index ac101ec..334bae4 100644
--- a/cmds/installd/Android.bp
+++ b/cmds/installd/Android.bp
@@ -34,7 +34,6 @@
         "unique_file.cpp",
         "utils.cpp",
         "utils_default.cpp",
-        "view_compiler.cpp",
         ":installd_aidl",
     ],
     shared_libs: [
@@ -254,7 +253,6 @@
         "unique_file.cpp",
         "utils.cpp",
         "utils_default.cpp",
-        "view_compiler.cpp",
     ],
 
     static_libs: [
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index 073d0c4..d7c9b40 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -69,7 +69,6 @@
 #include "installd_deps.h"
 #include "otapreopt_utils.h"
 #include "utils.h"
-#include "view_compiler.h"
 
 #include "CacheTracker.h"
 #include "CrateManager.h"
@@ -3258,17 +3257,6 @@
     return ok();
 }
 
-binder::Status InstalldNativeService::compileLayouts(const std::string& apkPath,
-                                                     const std::string& packageName,
-                                                     const std ::string& outDexFile, int uid,
-                                                     bool* _aidl_return) {
-    const char* apk_path = apkPath.c_str();
-    const char* package_name = packageName.c_str();
-    const char* out_dex_file = outDexFile.c_str();
-    *_aidl_return = android::installd::view_compiler(apk_path, package_name, out_dex_file, uid);
-    return *_aidl_return ? ok() : error("viewcompiler failed");
-}
-
 binder::Status InstalldNativeService::linkNativeLibraryDirectory(
         const std::optional<std::string>& uuid, const std::string& packageName,
         const std::string& nativeLibPath32, int32_t userId) {
diff --git a/cmds/installd/InstalldNativeService.h b/cmds/installd/InstalldNativeService.h
index 1ec092d..1b56144 100644
--- a/cmds/installd/InstalldNativeService.h
+++ b/cmds/installd/InstalldNativeService.h
@@ -146,9 +146,6 @@
 
     binder::Status controlDexOptBlocking(bool block);
 
-    binder::Status compileLayouts(const std::string& apkPath, const std::string& packageName,
-                                  const std::string& outDexFile, int uid, bool* _aidl_return);
-
     binder::Status rmdex(const std::string& codePath, const std::string& instructionSet);
 
     binder::Status mergeProfiles(int32_t uid, const std::string& packageName,
diff --git a/cmds/installd/binder/android/os/IInstalld.aidl b/cmds/installd/binder/android/os/IInstalld.aidl
index 8893e38..f5a7709 100644
--- a/cmds/installd/binder/android/os/IInstalld.aidl
+++ b/cmds/installd/binder/android/os/IInstalld.aidl
@@ -70,8 +70,6 @@
     // Blocks (when block is true) or unblock (when block is false) dexopt.
     // Blocking also invloves cancelling the currently running dexopt.
     void controlDexOptBlocking(boolean block);
-    boolean compileLayouts(@utf8InCpp String apkPath, @utf8InCpp String packageName,
-            @utf8InCpp String outDexFile, int uid);
 
     void rmdex(@utf8InCpp String codePath, @utf8InCpp String instructionSet);
 
diff --git a/cmds/installd/view_compiler.cpp b/cmds/installd/view_compiler.cpp
deleted file mode 100644
index 8c000a1..0000000
--- a/cmds/installd/view_compiler.cpp
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright (C) 2019 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 "view_compiler.h"
-
-#include <string>
-
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <unistd.h>
-
-#include "utils.h"
-
-#include "android-base/logging.h"
-#include "android-base/stringprintf.h"
-#include "android-base/unique_fd.h"
-
-namespace android {
-namespace installd {
-
-namespace {
-
-using ::android::base::unique_fd;
-
-constexpr int kTimeoutMs = 300000;
-
-} // namespace
-
-bool view_compiler(const char* apk_path, const char* package_name, const char* out_dex_file,
-                   int uid) {
-    CHECK(apk_path != nullptr);
-    CHECK(package_name != nullptr);
-    CHECK(out_dex_file != nullptr);
-
-    // viewcompiler won't have permission to open anything, so we have to open the files first
-    // and pass file descriptors.
-
-    // Open input file
-    unique_fd infd{open(apk_path, O_RDONLY)}; // NOLINT(android-cloexec-open)
-    if (infd.get() < 0) {
-        PLOG(ERROR) << "Could not open input file: " << apk_path;
-        return false;
-    }
-
-    // Set up output file. viewcompiler can't open outputs by fd, but it can write to stdout, so
-    // we close stdout and open it towards the right output.
-    unique_fd outfd{open(out_dex_file, O_CREAT | O_TRUNC | O_WRONLY | O_CLOEXEC, 0644)};
-    if (outfd.get() < 0) {
-        PLOG(ERROR) << "Could not open output file: " << out_dex_file;
-        return false;
-    }
-    if (fchmod(outfd, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) != 0) {
-        PLOG(ERROR) << "Could not change output file permissions";
-        return false;
-    }
-    if (dup2(outfd, STDOUT_FILENO) < 0) {
-        PLOG(ERROR) << "Could not duplicate output file descriptor";
-        return false;
-    }
-
-    // Prepare command line arguments for viewcompiler
-    std::string args[] = {"/system/bin/viewcompiler",
-                          "--apk",
-                          "--infd",
-                          android::base::StringPrintf("%d", infd.get()),
-                          "--dex",
-                          "--package",
-                          package_name};
-    char* const argv[] = {const_cast<char*>(args[0].c_str()), const_cast<char*>(args[1].c_str()),
-                          const_cast<char*>(args[2].c_str()), const_cast<char*>(args[3].c_str()),
-                          const_cast<char*>(args[4].c_str()), const_cast<char*>(args[5].c_str()),
-                          const_cast<char*>(args[6].c_str()), nullptr};
-
-    pid_t pid = fork();
-    if (pid == 0) {
-        // Now that we've opened the files we need, drop privileges.
-        drop_capabilities(uid);
-        execv("/system/bin/viewcompiler", argv);
-        _exit(1);
-    }
-
-    int return_code = wait_child_with_timeout(pid, kTimeoutMs);
-    if (!WIFEXITED(return_code)) {
-        LOG(WARNING) << "viewcompiler failed for " << package_name << ":" << apk_path;
-        if (WTERMSIG(return_code) == SIGKILL) {
-            // If the subprocess is killed while it's writing to the file, the file is likely
-            // corrupted, so we should remove it.
-            remove_file_at_fd(outfd.get());
-        }
-        return false;
-    }
-    return WEXITSTATUS(return_code) == 0;
-}
-
-} // namespace installd
-} // namespace android
diff --git a/cmds/installd/view_compiler.h b/cmds/installd/view_compiler.h
deleted file mode 100644
index aa141ca..0000000
--- a/cmds/installd/view_compiler.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-
-#ifndef VIEW_COMPILER_H_
-#define VIEW_COMPILER_H_
-
-namespace android {
-namespace installd {
-
-bool view_compiler(const char* apk_path, const char* package_name, const char* out_dex_file,
-                   int uid);
-
-} // namespace installd
-} // namespace android
-
-#endif // VIEW_COMPILER_H_
diff --git a/data/etc/Android.bp b/data/etc/Android.bp
index e286a84..550b374 100644
--- a/data/etc/Android.bp
+++ b/data/etc/Android.bp
@@ -131,6 +131,24 @@
 }
 
 prebuilt_etc {
+    name: "android.hardware.se.omapi.ese.prebuilt.xml",
+    src: "android.hardware.se.omapi.ese.xml",
+    defaults: ["frameworks_native_data_etc_defaults"],
+}
+
+prebuilt_etc {
+    name: "android.hardware.se.omapi.sd.prebuilt.xml",
+    src: "android.hardware.se.omapi.sd.xml",
+    defaults: ["frameworks_native_data_etc_defaults"],
+}
+
+prebuilt_etc {
+    name: "android.hardware.se.omapi.uicc.prebuilt.xml",
+    src: "android.hardware.se.omapi.uicc.xml",
+    defaults: ["frameworks_native_data_etc_defaults"],
+}
+
+prebuilt_etc {
     name: "android.hardware.sensor.accelerometer_limited_axes_uncalibrated.prebuilt.xml",
     src: "android.hardware.sensor.accelerometer_limited_axes_uncalibrated.xml",
     defaults: ["frameworks_native_data_etc_defaults"],
diff --git a/include/input/KeyCharacterMap.h b/include/input/KeyCharacterMap.h
index b2e8baa..dfcf766 100644
--- a/include/input/KeyCharacterMap.h
+++ b/include/input/KeyCharacterMap.h
@@ -146,7 +146,7 @@
 
 #ifdef __linux__
     /* Reads a key map from a parcel. */
-    static std::shared_ptr<KeyCharacterMap> readFromParcel(Parcel* parcel);
+    static std::unique_ptr<KeyCharacterMap> readFromParcel(Parcel* parcel);
 
     /* Writes a key map to a parcel. */
     void writeToParcel(Parcel* parcel) const;
diff --git a/libs/binder/ndk/include_platform/android/binder_manager.h b/libs/binder/ndk/include_platform/android/binder_manager.h
index 89fd7a3..316a79c 100644
--- a/libs/binder/ndk/include_platform/android/binder_manager.h
+++ b/libs/binder/ndk/include_platform/android/binder_manager.h
@@ -120,7 +120,7 @@
 
 /**
  * Gets a binder object with this specific instance name. Efficiently waits for the service.
- * If the service is not declared, it will wait indefinitely. Requires the threadpool
+ * If the service is not ever registered, it will wait indefinitely. Requires the threadpool
  * to be started in the service.
  * This also implicitly calls AIBinder_incStrong (so the caller of this function is responsible
  * for calling AIBinder_decStrong).
diff --git a/libs/binder/ndk/stability.cpp b/libs/binder/ndk/stability.cpp
index 7eafb9c..73eb863 100644
--- a/libs/binder/ndk/stability.cpp
+++ b/libs/binder/ndk/stability.cpp
@@ -27,6 +27,10 @@
 #error libbinder_ndk should only be built in a system context
 #endif
 
+#ifdef __ANDROID_VENDOR__
+#error libbinder_ndk should only be built in a system context
+#endif
+
 #ifdef __ANDROID_NDK__
 #error libbinder_ndk should only be built in a system context
 #endif
diff --git a/libs/binder/rust/src/parcel.rs b/libs/binder/rust/src/parcel.rs
index 3c615ed..f9f135d 100644
--- a/libs/binder/rust/src/parcel.rs
+++ b/libs/binder/rust/src/parcel.rs
@@ -54,6 +54,10 @@
 
 /// Safety: This type guarantees that it owns the AParcel and that all access to
 /// the AParcel happens through the Parcel, so it is ok to send across threads.
+///
+/// It would not be okay to implement Sync, because that would allow you to call
+/// the reading methods from several threads in parallel, which would be a data
+/// race on the cursor position inside the AParcel.
 unsafe impl Send for Parcel {}
 
 /// Container for a message (data and object references) that can be sent
diff --git a/libs/binder/tests/parcel_fuzzer/random_parcel.cpp b/libs/binder/tests/parcel_fuzzer/random_parcel.cpp
index f0beed2..f367b41 100644
--- a/libs/binder/tests/parcel_fuzzer/random_parcel.cpp
+++ b/libs/binder/tests/parcel_fuzzer/random_parcel.cpp
@@ -66,6 +66,11 @@
                 },
                 // write FD
                 [&]() {
+                    // b/296516864 - Limit number of objects written to a parcel.
+                    if (p->objectsCount() > 100) {
+                        return;
+                    }
+
                     if (options->extraFds.size() > 0 && provider.ConsumeBool()) {
                         const base::unique_fd& fd = options->extraFds.at(
                                 provider.ConsumeIntegralInRange<size_t>(0,
@@ -82,7 +87,6 @@
                         CHECK(OK ==
                               p->writeFileDescriptor(fds.begin()->release(),
                                                      true /*takeOwnership*/));
-
                         options->extraFds.insert(options->extraFds.end(),
                                                  std::make_move_iterator(fds.begin() + 1),
                                                  std::make_move_iterator(fds.end()));
@@ -90,6 +94,11 @@
                 },
                 // write binder
                 [&]() {
+                    // b/296516864 - Limit number of objects written to a parcel.
+                    if (p->objectsCount() > 100) {
+                        return;
+                    }
+
                     sp<IBinder> binder;
                     if (options->extraBinders.size() > 0 && provider.ConsumeBool()) {
                         binder = options->extraBinders.at(
diff --git a/libs/graphicsenv/include/graphicsenv/GpuStatsInfo.h b/libs/graphicsenv/include/graphicsenv/GpuStatsInfo.h
index 47607a0..9ebaf16 100644
--- a/libs/graphicsenv/include/graphicsenv/GpuStatsInfo.h
+++ b/libs/graphicsenv/include/graphicsenv/GpuStatsInfo.h
@@ -104,7 +104,7 @@
         GL_UPDATED = 2,
         VULKAN = 3,
         VULKAN_UPDATED = 4,
-        ANGLE = 5,
+        ANGLE = 5, // cover both system ANGLE and ANGLE APK
     };
 
     enum Stats {
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 05e2ddf..a351811 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -2604,7 +2604,7 @@
         outMode.resolution.height = mode.resolution.height;
         outMode.xDpi = mode.xDpi;
         outMode.yDpi = mode.yDpi;
-        outMode.refreshRate = mode.refreshRate;
+        outMode.peakRefreshRate = mode.peakRefreshRate;
         outMode.vsyncRate = mode.vsyncRate;
         outMode.appVsyncOffset = mode.appVsyncOffset;
         outMode.sfVsyncOffset = mode.sfVsyncOffset;
diff --git a/libs/gui/aidl/android/gui/DisplayMode.aidl b/libs/gui/aidl/android/gui/DisplayMode.aidl
index b057653..f605177 100644
--- a/libs/gui/aidl/android/gui/DisplayMode.aidl
+++ b/libs/gui/aidl/android/gui/DisplayMode.aidl
@@ -30,7 +30,7 @@
     int[] supportedHdrTypes;
 
     // Some modes have peak refresh rate lower than the panel vsync rate.
-    float refreshRate = 0.0f;
+    float peakRefreshRate = 0.0f;
     float vsyncRate = 0.0f;
     long appVsyncOffset = 0;
     long sfVsyncOffset = 0;
diff --git a/libs/gui/tests/EndToEndNativeInputTest.cpp b/libs/gui/tests/EndToEndNativeInputTest.cpp
index 662e9fe..d4b8dbe 100644
--- a/libs/gui/tests/EndToEndNativeInputTest.cpp
+++ b/libs/gui/tests/EndToEndNativeInputTest.cpp
@@ -394,7 +394,7 @@
         // After a new buffer is queued, SurfaceFlinger is notified and will
         // latch the new buffer on next vsync.  Let's heuristically wait for 3
         // vsyncs.
-        mBufferPostDelay = static_cast<int32_t>(1e6 / mode.refreshRate) * 3;
+        mBufferPostDelay = static_cast<int32_t>(1e6 / mode.peakRefreshRate) * 3;
     }
 
     void TearDown() {
diff --git a/libs/input/KeyCharacterMap.cpp b/libs/input/KeyCharacterMap.cpp
index a4cd239..e2feabc 100644
--- a/libs/input/KeyCharacterMap.cpp
+++ b/libs/input/KeyCharacterMap.cpp
@@ -613,14 +613,14 @@
 }
 
 #ifdef __linux__
-std::shared_ptr<KeyCharacterMap> KeyCharacterMap::readFromParcel(Parcel* parcel) {
+std::unique_ptr<KeyCharacterMap> KeyCharacterMap::readFromParcel(Parcel* parcel) {
     if (parcel == nullptr) {
         ALOGE("%s: Null parcel", __func__);
         return nullptr;
     }
     std::string loadFileName = parcel->readCString();
-    std::shared_ptr<KeyCharacterMap> map =
-            std::shared_ptr<KeyCharacterMap>(new KeyCharacterMap(loadFileName));
+    std::unique_ptr<KeyCharacterMap> map =
+            std::make_unique<KeyCharacterMap>(KeyCharacterMap(loadFileName));
     map->mType = static_cast<KeyCharacterMap::KeyboardType>(parcel->readInt32());
     map->mLayoutOverlayApplied = parcel->readBool();
     size_t numKeys = parcel->readInt32();
diff --git a/libs/nativedisplay/ADisplay.cpp b/libs/nativedisplay/ADisplay.cpp
index bf0805b..e3be3bc 100644
--- a/libs/nativedisplay/ADisplay.cpp
+++ b/libs/nativedisplay/ADisplay.cpp
@@ -155,7 +155,7 @@
             const ui::DisplayMode& mode = modes[j];
             modesPerDisplay[i].emplace_back(
                     DisplayConfigImpl{static_cast<size_t>(mode.id), mode.resolution.getWidth(),
-                                      mode.resolution.getHeight(), mode.refreshRate,
+                                      mode.resolution.getHeight(), mode.peakRefreshRate,
                                       mode.sfVsyncOffset, mode.appVsyncOffset});
         }
     }
diff --git a/libs/nativewindow/include/android/native_window_aidl.h b/libs/nativewindow/include/android/native_window_aidl.h
index a252245..0d5727d 100644
--- a/libs/nativewindow/include/android/native_window_aidl.h
+++ b/libs/nativewindow/include/android/native_window_aidl.h
@@ -34,6 +34,12 @@
 #include <android/native_window.h>
 #include <sys/cdefs.h>
 
+// Only required by the AIDL glue helper
+#ifdef __cplusplus
+#include <sstream>
+#include <string>
+#endif // __cplusplus
+
 __BEGIN_DECLS
 
 /**
@@ -80,7 +86,7 @@
  * Takes ownership of the ANativeWindow* given to it in reset() and will automatically
  * destroy it in the destructor, similar to a smart pointer container
  */
-class NativeWindow {
+class NativeWindow final {
 public:
     NativeWindow() noexcept {}
     explicit NativeWindow(ANativeWindow* _Nullable window) {
@@ -123,15 +129,29 @@
         }
         mWindow = window;
     }
-    inline ANativeWindow* _Nullable operator-> () const { return mWindow;  }
+
     inline ANativeWindow* _Nullable get() const { return mWindow; }
-    inline explicit operator bool () const { return mWindow != nullptr; }
 
     NativeWindow& operator=(NativeWindow&& other) noexcept {
         mWindow = other.release(); // steal ownership from r-value
         return *this;
     }
 
+    inline ANativeWindow* _Nullable operator->() const { return mWindow; }
+    inline explicit operator bool() const { return mWindow != nullptr; }
+    inline bool operator==(const NativeWindow& rhs) const { return mWindow == rhs.mWindow; }
+    inline bool operator!=(const NativeWindow& rhs) const { return !(*this == rhs); }
+    inline bool operator<(const NativeWindow& rhs) const { return mWindow < rhs.mWindow; }
+    inline bool operator>(const NativeWindow& rhs) const { return rhs < *this; }
+    inline bool operator>=(const NativeWindow& rhs) const { return !(*this < rhs); }
+    inline bool operator<=(const NativeWindow& rhs) const { return !(*this > rhs); }
+
+    std::string toString() const {
+        std::ostringstream ss;
+        ss << "NativeWindow: " << mWindow;
+        return ss.str();
+    }
+
     /**
      * Stops managing any contained ANativeWindow*, returning it to the caller. Ownership
      * is released.
diff --git a/libs/ui/include/ui/DisplayMode.h b/libs/ui/include/ui/DisplayMode.h
index a469c78..ddb9bbd 100644
--- a/libs/ui/include/ui/DisplayMode.h
+++ b/libs/ui/include/ui/DisplayMode.h
@@ -38,7 +38,7 @@
     std::vector<ui::Hdr> supportedHdrTypes;
 
     // Some modes have peak refresh rate lower than the panel vsync rate.
-    float refreshRate = 0.f;
+    float peakRefreshRate = 0.f;
     float vsyncRate = 0.f;
     nsecs_t appVsyncOffset = 0;
     nsecs_t sfVsyncOffset = 0;
diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp
index 04e2fff..7b2f39c 100644
--- a/opengl/libs/EGL/Loader.cpp
+++ b/opengl/libs/EGL/Loader.cpp
@@ -567,6 +567,7 @@
         return nullptr;
     }
 
+    // use ANGLE APK driver
     android::GraphicsEnv::getInstance().setDriverToLoad(android::GpuStatsInfo::Driver::ANGLE);
     driver_t* hnd = nullptr;
 
@@ -635,7 +636,13 @@
 Loader::driver_t* Loader::attempt_to_load_system_driver(egl_connection_t* cnx, const char* suffix,
                                                         const bool exact) {
     ATRACE_CALL();
-    android::GraphicsEnv::getInstance().setDriverToLoad(android::GpuStatsInfo::Driver::GL);
+    if (strcmp(suffix, "angle") == 0) {
+        // use system ANGLE driver
+        android::GraphicsEnv::getInstance().setDriverToLoad(android::GpuStatsInfo::Driver::ANGLE);
+    } else {
+        android::GraphicsEnv::getInstance().setDriverToLoad(android::GpuStatsInfo::Driver::GL);
+    }
+
     driver_t* hnd = nullptr;
     void* dso = load_system_driver("GLES", suffix, exact);
     if (dso) {
diff --git a/services/gpuservice/gpustats/GpuStats.cpp b/services/gpuservice/gpustats/GpuStats.cpp
index f06a045..d447d1e 100644
--- a/services/gpuservice/gpustats/GpuStats.cpp
+++ b/services/gpuservice/gpustats/GpuStats.cpp
@@ -163,11 +163,11 @@
         addLoadingTime(driver, driverLoadingTime, &appInfo);
         appInfo.appPackageName = appPackageName;
         appInfo.driverVersionCode = driverVersionCode;
-        appInfo.angleInUse = driverPackageName == "angle";
+        appInfo.angleInUse = driver == GpuStatsInfo::Driver::ANGLE;
         appInfo.lastAccessTime = std::chrono::system_clock::now();
         mAppStats.insert({appStatsKey, appInfo});
     } else {
-        mAppStats[appStatsKey].angleInUse = driverPackageName == "angle";
+        mAppStats[appStatsKey].angleInUse = driver == GpuStatsInfo::Driver::ANGLE;
         addLoadingTime(driver, driverLoadingTime, &mAppStats[appStatsKey]);
         mAppStats[appStatsKey].lastAccessTime = std::chrono::system_clock::now();
     }
diff --git a/services/inputflinger/InputListener.cpp b/services/inputflinger/InputListener.cpp
index 1f17c16..016ae04 100644
--- a/services/inputflinger/InputListener.cpp
+++ b/services/inputflinger/InputListener.cpp
@@ -39,7 +39,7 @@
 
 // Helper to std::visit with lambdas.
 template <typename... V>
-struct Visitor : V... {};
+struct Visitor : V... { using V::operator()...; };
 // explicit deduction guide (not needed as of C++20)
 template <typename... V>
 Visitor(V...) -> Visitor<V...>;
diff --git a/services/inputflinger/NotifyArgs.cpp b/services/inputflinger/NotifyArgs.cpp
index c34cd53..de836e9 100644
--- a/services/inputflinger/NotifyArgs.cpp
+++ b/services/inputflinger/NotifyArgs.cpp
@@ -190,7 +190,7 @@
 
 // Helper to std::visit with lambdas.
 template <typename... V>
-struct Visitor : V... {};
+struct Visitor : V... { using V::operator()...; };
 // explicit deduction guide (not needed as of C++20)
 template <typename... V>
 Visitor(V...) -> Visitor<V...>;
diff --git a/services/inputflinger/reader/mapper/gestures/PropertyProvider.cpp b/services/inputflinger/reader/mapper/gestures/PropertyProvider.cpp
index be2bfed..69264f8 100644
--- a/services/inputflinger/reader/mapper/gestures/PropertyProvider.cpp
+++ b/services/inputflinger/reader/mapper/gestures/PropertyProvider.cpp
@@ -239,7 +239,7 @@
 
 // Helper to std::visit with lambdas.
 template <typename... V>
-struct Visitor : V... {};
+struct Visitor : V... { using V::operator()...; };
 // explicit deduction guide (not needed as of C++20)
 template <typename... V>
 Visitor(V...) -> Visitor<V...>;
diff --git a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
index 892bb8f..6807c8e 100644
--- a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
+++ b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
@@ -147,6 +147,8 @@
     MOCK_METHOD(const aidl::android::hardware::graphics::composer3::OverlayProperties&,
                 getOverlaySupport, (), (const, override));
     MOCK_METHOD(status_t, setRefreshRateChangedCallbackDebugEnabled, (PhysicalDisplayId, bool));
+    MOCK_METHOD(status_t, notifyExpectedPresentIfRequired,
+                (PhysicalDisplayId, nsecs_t, int32_t, int32_t));
 };
 
 } // namespace mock
diff --git a/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp b/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp
index 1f409c6..1643ad0 100644
--- a/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp
@@ -1450,6 +1450,20 @@
     return Error::NONE;
 }
 
+Error AidlComposer::notifyExpectedPresent(Display displayId, nsecs_t expectedPresentTime,
+                                          int32_t frameIntervalNs) {
+    const auto status =
+            mAidlComposerClient->notifyExpectedPresent(translate<int64_t>(displayId),
+                                                       ClockMonotonicTimestamp{expectedPresentTime},
+                                                       frameIntervalNs);
+
+    if (!status.isOk()) {
+        ALOGE("notifyExpectedPresent failed %s", status.getDescription().c_str());
+        return static_cast<Error>(status.getServiceSpecificError());
+    }
+    return Error::NONE;
+}
+
 Error AidlComposer::getClientTargetProperty(
         Display display, ClientTargetPropertyWithBrightness* outClientTargetProperty) {
     Error error = Error::NONE;
diff --git a/services/surfaceflinger/DisplayHardware/AidlComposerHal.h b/services/surfaceflinger/DisplayHardware/AidlComposerHal.h
index b1b57a4..7693a80 100644
--- a/services/surfaceflinger/DisplayHardware/AidlComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/AidlComposerHal.h
@@ -240,6 +240,8 @@
     Error getHdrConversionCapabilities(std::vector<HdrConversionCapability>*) override;
     Error setHdrConversionStrategy(HdrConversionStrategy, Hdr*) override;
     Error setRefreshRateChangedCallbackDebugEnabled(Display, bool) override;
+    Error notifyExpectedPresent(Display, nsecs_t expectedPresentTime,
+                                int32_t frameIntervalNs) override;
 
 private:
     // Many public functions above simply write a command into the command
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.h b/services/surfaceflinger/DisplayHardware/ComposerHal.h
index e942587..6704d88 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.h
@@ -298,6 +298,8 @@
     virtual Error setHdrConversionStrategy(
             ::aidl::android::hardware::graphics::common::HdrConversionStrategy, Hdr*) = 0;
     virtual Error setRefreshRateChangedCallbackDebugEnabled(Display, bool) = 0;
+    virtual Error notifyExpectedPresent(Display, nsecs_t expectedPresentTime,
+                                        int32_t frameIntervalNs) = 0;
 };
 
 } // namespace Hwc2
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 812621f..fb6089d 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -31,6 +31,7 @@
 #include <compositionengine/OutputLayer.h>
 #include <compositionengine/impl/OutputLayerCompositionState.h>
 #include <ftl/concat.h>
+#include <gui/TraceUtils.h>
 #include <log/log.h>
 #include <ui/DebugUtils.h>
 #include <ui/GraphicBuffer.h>
@@ -484,6 +485,7 @@
     }();
 
     displayData.validateWasSkipped = false;
+    displayData.lastExpectedPresentTimestamp = expectedPresentTime;
     if (canSkipValidate) {
         sp<Fence> outPresentFence;
         uint32_t state = UINT32_MAX;
@@ -876,6 +878,30 @@
     return NO_ERROR;
 }
 
+status_t HWComposer::notifyExpectedPresentIfRequired(PhysicalDisplayId displayId,
+                                                     nsecs_t expectedPresentTime,
+                                                     int32_t frameIntervalNs, int32_t timeoutNs) {
+    RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
+
+    auto& displayData = mDisplayData[displayId];
+    if (expectedPresentTime >= displayData.lastExpectedPresentTimestamp &&
+        expectedPresentTime < displayData.lastExpectedPresentTimestamp + timeoutNs) {
+        return NO_ERROR;
+    }
+
+    displayData.lastExpectedPresentTimestamp = expectedPresentTime;
+    ATRACE_FORMAT("%s ExpectedPresentTime %" PRId64 " frameIntervalNs %d", __func__,
+                  expectedPresentTime, frameIntervalNs);
+    const auto error = mComposer->notifyExpectedPresent(displayData.hwcDisplay->getId(),
+                                                        expectedPresentTime, frameIntervalNs);
+
+    if (error != hal::Error::NONE) {
+        ALOGE("Error in notifyExpectedPresent call %s", to_string(error).c_str());
+        return INVALID_OPERATION;
+    }
+    return NO_ERROR;
+}
+
 status_t HWComposer::getDisplayDecorationSupport(
         PhysicalDisplayId displayId,
         std::optional<aidl::android::hardware::graphics::common::DisplayDecorationSupport>*
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index b4d3d28..726a8ea 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -60,6 +60,7 @@
 struct DisplayedFrameStats;
 class GraphicBuffer;
 class TestableSurfaceFlinger;
+struct HWComposerTest;
 struct CompositionInfo;
 
 namespace Hwc2 {
@@ -300,6 +301,9 @@
             aidl::android::hardware::graphics::common::HdrConversionStrategy,
             aidl::android::hardware::graphics::common::Hdr*) = 0;
     virtual status_t setRefreshRateChangedCallbackDebugEnabled(PhysicalDisplayId, bool enabled) = 0;
+    virtual status_t notifyExpectedPresentIfRequired(PhysicalDisplayId, nsecs_t expectedPresentTime,
+                                                     int32_t frameIntervalNs,
+                                                     int32_t timeoutNs) = 0;
 };
 
 static inline bool operator==(const android::HWComposer::DeviceRequestedChanges& lhs,
@@ -458,6 +462,8 @@
             aidl::android::hardware::graphics::common::HdrConversionStrategy,
             aidl::android::hardware::graphics::common::Hdr*) override;
     status_t setRefreshRateChangedCallbackDebugEnabled(PhysicalDisplayId, bool enabled) override;
+    status_t notifyExpectedPresentIfRequired(PhysicalDisplayId, nsecs_t expectedPresentTime,
+                                             int32_t frameIntervalNs, int32_t timeoutNs) override;
 
     // for debugging ----------------------------------------------------------
     void dump(std::string& out) const override;
@@ -483,6 +489,7 @@
 private:
     // For unit tests
     friend TestableSurfaceFlinger;
+    friend HWComposerTest;
 
     struct DisplayData {
         std::unique_ptr<HWC2::Display> hwcDisplay;
@@ -490,6 +497,8 @@
         sp<Fence> lastPresentFence = Fence::NO_FENCE; // signals when the last set op retires
         nsecs_t lastPresentTimestamp = 0;
 
+        nsecs_t lastExpectedPresentTimestamp = 0;
+
         std::unordered_map<HWC2::Layer*, sp<Fence>> releaseFences;
 
         bool validateWasSkipped;
diff --git a/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp b/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp
index 70d48de..c13e568 100644
--- a/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp
@@ -1378,6 +1378,10 @@
     return Error::UNSUPPORTED;
 }
 
+Error HidlComposer::notifyExpectedPresent(Display, nsecs_t, int32_t) {
+    return Error::UNSUPPORTED;
+}
+
 Error HidlComposer::getClientTargetProperty(
         Display display, ClientTargetPropertyWithBrightness* outClientTargetProperty) {
     IComposerClient::ClientTargetProperty property;
diff --git a/services/surfaceflinger/DisplayHardware/HidlComposerHal.h b/services/surfaceflinger/DisplayHardware/HidlComposerHal.h
index 26d2222..1004ddd 100644
--- a/services/surfaceflinger/DisplayHardware/HidlComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/HidlComposerHal.h
@@ -348,6 +348,7 @@
     Error setHdrConversionStrategy(aidl::android::hardware::graphics::common::HdrConversionStrategy,
                                    Hdr*) override;
     Error setRefreshRateChangedCallbackDebugEnabled(Display, bool) override;
+    Error notifyExpectedPresent(Display, nsecs_t, int32_t) override;
 
 private:
     class CommandWriter : public CommandWriterBase {
diff --git a/services/surfaceflinger/Scheduler/LayerHistory.cpp b/services/surfaceflinger/Scheduler/LayerHistory.cpp
index 069d89b..ff82914 100644
--- a/services/surfaceflinger/Scheduler/LayerHistory.cpp
+++ b/services/surfaceflinger/Scheduler/LayerHistory.cpp
@@ -21,6 +21,7 @@
 #include "LayerHistory.h"
 
 #include <android-base/stringprintf.h>
+#include <com_android_graphics_surfaceflinger_flags.h>
 #include <cutils/properties.h>
 #include <gui/TraceUtils.h>
 #include <utils/Log.h>
@@ -39,8 +40,14 @@
 
 namespace {
 
+using namespace com::android::graphics::surfaceflinger;
+
 bool isLayerActive(const LayerInfo& info, nsecs_t threshold) {
-    // Layers with an explicit frame rate or frame rate category are always kept active,
+    if (flags::misc1() && !info.isVisible()) {
+        return false;
+    }
+
+    // Layers with an explicit frame rate or frame rate category are kept active,
     // but ignore NoVote.
     if (info.getSetFrameRateVote().isValid() && !info.getSetFrameRateVote().isNoVote()) {
         return true;
diff --git a/services/surfaceflinger/Scheduler/LayerInfo.cpp b/services/surfaceflinger/Scheduler/LayerInfo.cpp
index 36f2475..54e9022 100644
--- a/services/surfaceflinger/Scheduler/LayerInfo.cpp
+++ b/services/surfaceflinger/Scheduler/LayerInfo.cpp
@@ -304,19 +304,22 @@
 
     if (mLayerVote.type != LayerHistory::LayerVoteType::Heuristic) {
         if (mLayerVote.category != FrameRateCategory::Default) {
-            ATRACE_FORMAT_INSTANT("ExplicitCategory (%s)",
+            const auto voteType = mLayerVote.type == LayerHistory::LayerVoteType::NoVote
+                    ? LayerHistory::LayerVoteType::NoVote
+                    : LayerHistory::LayerVoteType::ExplicitCategory;
+            ATRACE_FORMAT_INSTANT("Vote %s (category=%s)", ftl::enum_string(voteType).c_str(),
                                   ftl::enum_string(mLayerVote.category).c_str());
-            ALOGV("%s uses frame rate category: %d", mName.c_str(),
-                  static_cast<int>(mLayerVote.category));
-            votes.push_back({LayerHistory::LayerVoteType::ExplicitCategory, Fps(),
-                             Seamlessness::Default, mLayerVote.category,
+            ALOGV("%s voted %s with category: %s", mName.c_str(),
+                  ftl::enum_string(voteType).c_str(),
+                  ftl::enum_string(mLayerVote.category).c_str());
+            votes.push_back({voteType, Fps(), Seamlessness::Default, mLayerVote.category,
                              mLayerVote.categorySmoothSwitchOnly});
         }
 
         if (mLayerVote.fps.isValid() ||
             mLayerVote.type != LayerHistory::LayerVoteType::ExplicitDefault) {
             ATRACE_FORMAT_INSTANT("Vote %s", ftl::enum_string(mLayerVote.type).c_str());
-            ALOGV("%s voted %d ", mName.c_str(), static_cast<int>(mLayerVote.type));
+            ALOGV("%s voted %d", mName.c_str(), static_cast<int>(mLayerVote.type));
             votes.push_back(mLayerVote);
         }
 
diff --git a/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp b/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp
index 1d23fb5..eb69d0b 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp
+++ b/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp
@@ -401,7 +401,6 @@
 
 float RefreshRateSelector::calculateLayerScoreLocked(const LayerRequirement& layer, Fps refreshRate,
                                                      bool isSeamlessSwitch) const {
-    ATRACE_CALL();
     // Slightly prefer seamless switches.
     constexpr float kSeamedSwitchPenalty = 0.95f;
     const float seamlessness = isSeamlessSwitch ? 1.0f : kSeamedSwitchPenalty;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index dc19cbd..48be33c 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -267,7 +267,7 @@
 
 bool isAbove4k30(const ui::DisplayMode& outMode) {
     using fps_approx_ops::operator>;
-    Fps refreshRate = Fps::fromValue(outMode.refreshRate);
+    Fps refreshRate = Fps::fromValue(outMode.peakRefreshRate);
     return outMode.resolution.getWidth() >= FOUR_K_WIDTH &&
             outMode.resolution.getHeight() >= FOUR_K_HEIGHT && refreshRate > 30_Hz;
 }
@@ -1060,11 +1060,11 @@
         outMode.yDpi = yDpi;
 
         const auto peakFps = mode->getPeakFps();
-        outMode.refreshRate = peakFps.getValue();
+        outMode.peakRefreshRate = peakFps.getValue();
         outMode.vsyncRate = mode->getVsyncRate().getValue();
 
-        const auto vsyncConfigSet =
-                mVsyncConfiguration->getConfigsForRefreshRate(Fps::fromValue(outMode.refreshRate));
+        const auto vsyncConfigSet = mVsyncConfiguration->getConfigsForRefreshRate(
+                Fps::fromValue(outMode.peakRefreshRate));
         outMode.appVsyncOffset = vsyncConfigSet.late.appOffset;
         outMode.sfVsyncOffset = vsyncConfigSet.late.sfOffset;
         outMode.group = mode->getGroup();
@@ -9235,7 +9235,7 @@
         outMode.resolution.height = mode.resolution.height;
         outMode.xDpi = mode.xDpi;
         outMode.yDpi = mode.yDpi;
-        outMode.refreshRate = mode.refreshRate;
+        outMode.peakRefreshRate = mode.peakRefreshRate;
         outMode.vsyncRate = mode.vsyncRate;
         outMode.appVsyncOffset = mode.appVsyncOffset;
         outMode.sfVsyncOffset = mode.sfVsyncOffset;
diff --git a/services/surfaceflinger/SurfaceFlingerProperties.cpp b/services/surfaceflinger/SurfaceFlingerProperties.cpp
index 66c8f33..a765078 100644
--- a/services/surfaceflinger/SurfaceFlingerProperties.cpp
+++ b/services/surfaceflinger/SurfaceFlingerProperties.cpp
@@ -371,5 +371,9 @@
     return SurfaceFlingerProperties::clear_slots_with_set_layer_buffer().value_or(defaultValue);
 }
 
+int32_t game_default_frame_rate_override(int32_t defaultValue) {
+    return SurfaceFlingerProperties::game_default_frame_rate_override().value_or(defaultValue);
+}
+
 } // namespace sysprop
 } // namespace android
diff --git a/services/surfaceflinger/SurfaceFlingerProperties.h b/services/surfaceflinger/SurfaceFlingerProperties.h
index a080420..65ebe2a 100644
--- a/services/surfaceflinger/SurfaceFlingerProperties.h
+++ b/services/surfaceflinger/SurfaceFlingerProperties.h
@@ -101,6 +101,8 @@
 
 bool clear_slots_with_set_layer_buffer(bool defaultValue);
 
+int32_t game_default_frame_rate_override(int32_t defaultValue);
+
 } // namespace sysprop
 } // namespace android
 #endif // SURFACEFLINGERPROPERTIES_H_
diff --git a/services/surfaceflinger/TEST_MAPPING b/services/surfaceflinger/TEST_MAPPING
index f339d22..3b2bbb0 100644
--- a/services/surfaceflinger/TEST_MAPPING
+++ b/services/surfaceflinger/TEST_MAPPING
@@ -31,6 +31,9 @@
     },
     {
       "name": "CtsSurfaceControlTests"
+    },
+    {
+      "name": "CtsSurfaceControlTestsStaging"
     }
   ],
   "hwasan-presubmit": [
@@ -40,10 +43,5 @@
     {
       "name": "libsurfaceflinger_unittest"
     }
-  ],
-  "postsubmit": [
-    {
-      "name": "CtsSurfaceControlTestsStaging"
-    }
   ]
 }
diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_frametracer_fuzzer.cpp b/services/surfaceflinger/fuzzer/surfaceflinger_frametracer_fuzzer.cpp
index a22a778..8978971 100644
--- a/services/surfaceflinger/fuzzer/surfaceflinger_frametracer_fuzzer.cpp
+++ b/services/surfaceflinger/fuzzer/surfaceflinger_frametracer_fuzzer.cpp
@@ -23,12 +23,19 @@
 
 using namespace google::protobuf;
 
-constexpr size_t kMaxStringSize = 100;
+constexpr size_t kMaxStringSize = 256;
 constexpr size_t kMinLayerIds = 1;
 constexpr size_t kMaxLayerIds = 10;
+constexpr int32_t kMinRange = 0;
 constexpr int32_t kConfigDuration = 500;
 constexpr int32_t kBufferSize = 1024;
 constexpr int32_t kTimeOffset = 100000;
+constexpr perfetto::BackendType backendTypes[] = {
+        perfetto::kUnspecifiedBackend,
+        perfetto::kInProcessBackend,
+        perfetto::kSystemBackend,
+        perfetto::kCustomBackend,
+};
 
 class FrameTracerFuzzer {
 public:
@@ -47,24 +54,25 @@
     void process();
 
 private:
-    std::unique_ptr<perfetto::TracingSession> getTracingSessionForTest();
     void traceTimestamp();
-    std::vector<int32_t> generateLayerIds(size_t numLayerIds);
     void traceTimestamp(std::vector<int32_t> layerIds, size_t numLayerIds);
     void traceFence(std::vector<int32_t> layerIds, size_t numLayerIds);
+    std::unique_ptr<perfetto::TracingSession> getTracingSessionForTest();
     std::unique_ptr<android::FrameTracer> mFrameTracer = nullptr;
-    FuzzedDataProvider mFdp;
+    std::vector<int32_t> generateLayerIds(size_t numLayerIds);
     android::FenceToFenceTimeMap mFenceFactory;
+    FuzzedDataProvider mFdp;
 };
 
 std::unique_ptr<perfetto::TracingSession> FrameTracerFuzzer::getTracingSessionForTest() {
     perfetto::TraceConfig cfg;
-    cfg.set_duration_ms(kConfigDuration);
-    cfg.add_buffers()->set_size_kb(kBufferSize);
+    cfg.set_duration_ms(mFdp.ConsumeIntegralInRange<int32_t>(kMinRange, kConfigDuration));
+    cfg.add_buffers()->set_size_kb(mFdp.ConsumeIntegralInRange<int32_t>(kMinRange, kBufferSize));
     auto* dsCfg = cfg.add_data_sources()->mutable_config();
     dsCfg->set_name(android::FrameTracer::kFrameTracerDataSource);
 
-    auto tracingSession = perfetto::Tracing::NewTrace(perfetto::kInProcessBackend);
+    auto tracingSession =
+            perfetto::Tracing::NewTrace(mFdp.PickValueInArray<perfetto::BackendType>(backendTypes));
     tracingSession->Setup(cfg);
     return tracingSession;
 }
@@ -78,17 +86,23 @@
 }
 
 void FrameTracerFuzzer::traceTimestamp(std::vector<int32_t> layerIds, size_t numLayerIds) {
-    int32_t layerId = layerIds.at(mFdp.ConsumeIntegralInRange<size_t>(0, numLayerIds - 1));
+    uint32_t layerId = layerIds.at(mFdp.ConsumeIntegralInRange<size_t>(0, numLayerIds - 1));
+    android::FrameTracer::FrameEvent::BufferEventType type = static_cast<
+            android::FrameTracer::FrameEvent::BufferEventType>(
+            mFdp.ConsumeIntegralInRange<uint32_t>(android::FrameTracer::FrameEvent::UNSPECIFIED,
+                                                  android::FrameTracer::FrameEvent::CANCEL));
     mFrameTracer->traceTimestamp(layerId, mFdp.ConsumeIntegral<uint64_t>() /*bufferID*/,
                                  mFdp.ConsumeIntegral<uint64_t>() /*frameNumber*/,
-                                 mFdp.ConsumeIntegral<nsecs_t>() /*timestamp*/,
-                                 android::FrameTracer::FrameEvent::UNSPECIFIED,
+                                 mFdp.ConsumeIntegral<nsecs_t>() /*timestamp*/, type,
                                  mFdp.ConsumeIntegral<nsecs_t>() /*duration*/);
 }
 
 void FrameTracerFuzzer::traceFence(std::vector<int32_t> layerIds, size_t numLayerIds) {
-    const nsecs_t signalTime = systemTime();
-    const nsecs_t startTime = signalTime + kTimeOffset;
+    const nsecs_t signalTime =
+            mFdp.ConsumeBool() ? android::Fence::SIGNAL_TIME_PENDING : systemTime();
+    const nsecs_t startTime = (signalTime == android::Fence::SIGNAL_TIME_PENDING)
+            ? signalTime - kTimeOffset
+            : signalTime + kTimeOffset;
     auto fence = mFenceFactory.createFenceTimeForTest(android::Fence::NO_FENCE);
     mFenceFactory.signalAllForTest(android::Fence::NO_FENCE, signalTime);
     int32_t layerId = layerIds.at(mFdp.ConsumeIntegralInRange<size_t>(0, numLayerIds - 1));
@@ -98,26 +112,30 @@
 }
 
 void FrameTracerFuzzer::process() {
-    mFrameTracer->registerDataSource();
+    std::vector<int32_t> layerIds =
+            generateLayerIds(mFdp.ConsumeIntegralInRange<size_t>(kMinLayerIds, kMaxLayerIds));
 
-    auto tracingSession = getTracingSessionForTest();
-    tracingSession->StartBlocking();
-
-    size_t numLayerIds = mFdp.ConsumeIntegralInRange<size_t>(kMinLayerIds, kMaxLayerIds);
-    std::vector<int32_t> layerIds = generateLayerIds(numLayerIds);
-
-    for (auto it = layerIds.begin(); it != layerIds.end(); ++it) {
-        mFrameTracer->traceNewLayer(*it /*layerId*/,
-                                    mFdp.ConsumeRandomLengthString(kMaxStringSize) /*layerName*/);
+    while (mFdp.remaining_bytes()) {
+        auto invokeFrametracerAPI = mFdp.PickValueInArray<const std::function<void()>>({
+                [&]() { mFrameTracer->registerDataSource(); },
+                [&]() {
+                    auto tracingSession = getTracingSessionForTest();
+                    tracingSession->StartBlocking();
+                },
+                [&]() { traceTimestamp(layerIds, layerIds.size()); },
+                [&]() { traceFence(layerIds, layerIds.size()); },
+                [&]() {
+                    for (auto it = layerIds.begin(); it != layerIds.end(); ++it) {
+                        mFrameTracer->traceNewLayer(*it /*layerId*/,
+                                                    mFdp.ConsumeRandomLengthString(
+                                                            kMaxStringSize) /*layerName*/);
+                    }
+                },
+                [&]() { mFenceFactory.signalAllForTest(android::Fence::NO_FENCE, systemTime()); },
+        });
+        invokeFrametracerAPI();
     }
 
-    traceTimestamp(layerIds, numLayerIds);
-    traceFence(layerIds, numLayerIds);
-
-    mFenceFactory.signalAllForTest(android::Fence::NO_FENCE, systemTime());
-
-    tracingSession->StopBlocking();
-
     for (auto it = layerIds.begin(); it != layerIds.end(); ++it) {
         mFrameTracer->onDestroy(*it);
     }
diff --git a/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop b/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop
index be29be4..0ad5ac9 100644
--- a/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop
+++ b/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop
@@ -495,3 +495,15 @@
     access: Readonly
     prop_name: "ro.surface_flinger.clear_slots_with_set_layer_buffer"
 }
+
+# Controls the default frame rate override of game applications. Ideally, game applications set
+# desired frame rate via setFrameRate() API. However, to cover the scenario when the game didn't
+# have a set frame rate, we introduce the default frame rate. The priority of this override is the
+# lowest among setFrameRate() and game intervention override.
+prop {
+    api_name: "game_default_frame_rate_override"
+    type: Integer
+    scope: Public
+    access: Readonly
+    prop_name: "ro.surface_flinger.game_default_frame_rate_override"
+}
diff --git a/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt b/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt
index ba88acc..0017300 100644
--- a/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt
+++ b/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt
@@ -65,6 +65,11 @@
     prop_name: "ro.surface_flinger.force_hwc_copy_for_virtual_displays"
   }
   prop {
+    api_name: "game_default_frame_rate_override"
+    type: Integer
+    prop_name: "ro.surface_flinger.game_default_frame_rate_override"
+  }
+  prop {
     api_name: "has_HDR_display"
     prop_name: "ro.surface_flinger.has_HDR_display"
   }
diff --git a/services/surfaceflinger/tests/DisplayConfigs_test.cpp b/services/surfaceflinger/tests/DisplayConfigs_test.cpp
index 4be961b..0a951d4 100644
--- a/services/surfaceflinger/tests/DisplayConfigs_test.cpp
+++ b/services/surfaceflinger/tests/DisplayConfigs_test.cpp
@@ -75,8 +75,8 @@
     setSpecs.allowGroupSwitching = false;
     for (size_t i = 0; i < modes.size(); i++) {
         setSpecs.defaultMode = modes[i].id;
-        setSpecs.primaryRanges.physical.min = modes[i].refreshRate;
-        setSpecs.primaryRanges.physical.max = modes[i].refreshRate;
+        setSpecs.primaryRanges.physical.min = modes[i].peakRefreshRate;
+        setSpecs.primaryRanges.physical.max = modes[i].peakRefreshRate;
         setSpecs.primaryRanges.render = setSpecs.primaryRanges.physical;
         setSpecs.appRequestRanges = setSpecs.primaryRanges;
         res = SurfaceComposerClient::setDesiredDisplayModeSpecs(mDisplayToken, setSpecs);
diff --git a/services/surfaceflinger/tests/LayerTransactionTest.h b/services/surfaceflinger/tests/LayerTransactionTest.h
index 2bdb8a4..9269e7c 100644
--- a/services/surfaceflinger/tests/LayerTransactionTest.h
+++ b/services/surfaceflinger/tests/LayerTransactionTest.h
@@ -299,7 +299,7 @@
         // After a new buffer is queued, SurfaceFlinger is notified and will
         // latch the new buffer on next vsync.  Let's heuristically wait for 3
         // vsyncs.
-        mBufferPostDelay = static_cast<int32_t>(1e6 / mode.refreshRate) * 3;
+        mBufferPostDelay = static_cast<int32_t>(1e6 / mode.peakRefreshRate) * 3;
 
         mBlackBgSurface =
                 createSurface(mClient, "BaseSurface", 0 /* buffer width */, 0 /* buffer height */,
diff --git a/services/surfaceflinger/tests/unittests/HWComposerTest.cpp b/services/surfaceflinger/tests/unittests/HWComposerTest.cpp
index 8a45f17..4f545a9 100644
--- a/services/surfaceflinger/tests/unittests/HWComposerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/HWComposerTest.cpp
@@ -32,6 +32,7 @@
 
 #include <gui/LayerMetadata.h>
 #include <log/log.h>
+#include <chrono>
 
 #include "DisplayHardware/DisplayMode.h"
 #include "DisplayHardware/HWComposer.h"
@@ -44,11 +45,11 @@
 #pragma clang diagnostic pop // ignored "-Wconversion"
 
 namespace android {
-namespace {
 
 namespace V2_1 = hardware::graphics::composer::V2_1;
 namespace V2_4 = hardware::graphics::composer::V2_4;
 namespace aidl = aidl::android::hardware::graphics::composer3;
+using namespace std::chrono_literals;
 
 using Hwc2::Config;
 
@@ -77,6 +78,12 @@
         EXPECT_CALL(*mHal, setVsyncEnabled(hwcDisplayId, Hwc2::IComposerClient::Vsync::DISABLE));
         EXPECT_CALL(*mHal, onHotplugConnect(hwcDisplayId));
     }
+
+    void setDisplayData(HalDisplayId displayId, nsecs_t lastExpectedPresentTimestamp) {
+        ASSERT_TRUE(mHwc.mDisplayData.find(displayId) != mHwc.mDisplayData.end());
+        auto& displayData = mHwc.mDisplayData.at(displayId);
+        displayData.lastExpectedPresentTimestamp = lastExpectedPresentTimestamp;
+    }
 };
 
 TEST_F(HWComposerTest, isHeadless) {
@@ -227,12 +234,19 @@
         constexpr int32_t kHeight = 720;
         constexpr int32_t kConfigGroup = 1;
         constexpr int32_t kVsyncPeriod = 16666667;
-        hal::DisplayConfiguration displayConfiguration;
-        displayConfiguration.configId = kConfigId;
-        displayConfiguration.configGroup = kConfigGroup;
-        displayConfiguration.height = kHeight;
-        displayConfiguration.width = kWidth;
-        displayConfiguration.vsyncPeriod = kVsyncPeriod;
+        const hal::VrrConfig vrrConfig =
+                hal::VrrConfig{.minFrameIntervalNs = static_cast<Fps>(120_Hz).getPeriodNsecs(),
+                               .notifyExpectedPresentConfig = hal::VrrConfig::
+                                       NotifyExpectedPresentConfig{.notifyExpectedPresentHeadsUpNs =
+                                                                           ms2ns(30),
+                                                                   .notifyExpectedPresentTimeoutNs =
+                                                                           ms2ns(30)}};
+        hal::DisplayConfiguration displayConfiguration{.configId = kConfigId,
+                                                       .width = kWidth,
+                                                       .height = kHeight,
+                                                       .configGroup = kConfigGroup,
+                                                       .vsyncPeriod = kVsyncPeriod,
+                                                       .vrrConfig = vrrConfig};
 
         EXPECT_CALL(*mHal, getDisplayConfigurations(kHwcDisplayId, _, _))
                 .WillOnce(DoAll(SetArgPointee<2>(std::vector<hal::DisplayConfiguration>{
@@ -247,6 +261,7 @@
         EXPECT_EQ(modes.front().height, kHeight);
         EXPECT_EQ(modes.front().configGroup, kConfigGroup);
         EXPECT_EQ(modes.front().vsyncPeriod, kVsyncPeriod);
+        EXPECT_EQ(modes.front().vrrConfig, vrrConfig);
         EXPECT_EQ(modes.front().dpiX, -1);
         EXPECT_EQ(modes.front().dpiY, -1);
 
@@ -266,6 +281,7 @@
         EXPECT_EQ(modes.front().height, kHeight);
         EXPECT_EQ(modes.front().configGroup, kConfigGroup);
         EXPECT_EQ(modes.front().vsyncPeriod, kVsyncPeriod);
+        EXPECT_EQ(modes.front().vrrConfig, vrrConfig);
         EXPECT_EQ(modes.front().dpiX, kDpi);
         EXPECT_EQ(modes.front().dpiY, kDpi);
     }
@@ -299,6 +315,55 @@
     EXPECT_FALSE(displayIdOpt);
 }
 
+TEST_F(HWComposerTest, notifyExpectedPresentTimeout) {
+    constexpr hal::HWDisplayId kHwcDisplayId = 2;
+    expectHotplugConnect(kHwcDisplayId);
+    const auto info = mHwc.onHotplug(kHwcDisplayId, hal::Connection::CONNECTED);
+    ASSERT_TRUE(info);
+
+    auto expectedPresentTime = systemTime() + ms2ns(10);
+    const int32_t frameIntervalNs = static_cast<Fps>(60_Hz).getPeriodNsecs();
+    static constexpr nsecs_t kTimeoutNs = ms2ns(30);
+
+    ASSERT_NO_FATAL_FAILURE(setDisplayData(info->id, /* lastExpectedPresentTimestamp= */ 0));
+
+    {
+        // Very first ExpectedPresent after idle, no previous timestamp
+        EXPECT_CALL(*mHal,
+                    notifyExpectedPresent(kHwcDisplayId, expectedPresentTime, frameIntervalNs))
+                .WillOnce(Return(HalError::NONE));
+        mHwc.notifyExpectedPresentIfRequired(info->id, expectedPresentTime, frameIntervalNs,
+                                             kTimeoutNs);
+    }
+    {
+        // ExpectedPresent is after the timeoutNs
+        expectedPresentTime += ms2ns(50);
+        EXPECT_CALL(*mHal,
+                    notifyExpectedPresent(kHwcDisplayId, expectedPresentTime, frameIntervalNs))
+                .WillOnce(Return(HalError::NONE));
+        mHwc.notifyExpectedPresentIfRequired(info->id, expectedPresentTime, frameIntervalNs,
+                                             kTimeoutNs);
+    }
+    {
+        // ExpectedPresent is after the last reported ExpectedPresent.
+        expectedPresentTime += ms2ns(10);
+        EXPECT_CALL(*mHal, notifyExpectedPresent(kHwcDisplayId, _, _)).Times(0);
+        mHwc.notifyExpectedPresentIfRequired(info->id, expectedPresentTime, frameIntervalNs,
+                                             kTimeoutNs);
+    }
+    {
+        // ExpectedPresent is before the last reported ExpectedPresent but after the timeoutNs,
+        // representing we changed our decision and want to present earlier than previously
+        // reported.
+        expectedPresentTime -= ms2ns(20);
+        EXPECT_CALL(*mHal,
+                    notifyExpectedPresent(kHwcDisplayId, expectedPresentTime, frameIntervalNs))
+                .WillOnce(Return(HalError::NONE));
+        mHwc.notifyExpectedPresentIfRequired(info->id, expectedPresentTime, frameIntervalNs,
+                                             kTimeoutNs);
+    }
+}
+
 struct MockHWC2ComposerCallback final : StrictMock<HWC2::ComposerCallback> {
     MOCK_METHOD2(onComposerHalHotplug, void(hal::HWDisplayId, hal::Connection));
     MOCK_METHOD1(onComposerHalRefresh, void(hal::HWDisplayId));
@@ -423,5 +488,4 @@
     EXPECT_EQ(hal::Error::UNSUPPORTED, result);
 }
 
-} // namespace
 } // namespace android
diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryIntegrationTest.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryIntegrationTest.cpp
index 631adf1..2f6058f 100644
--- a/services/surfaceflinger/tests/unittests/LayerHistoryIntegrationTest.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerHistoryIntegrationTest.cpp
@@ -18,12 +18,14 @@
 #define LOG_TAG "LayerHistoryIntegrationTest"
 
 #include <Layer.h>
+#include <com_android_graphics_surfaceflinger_flags.h>
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
 #include <log/log.h>
 
 #include <renderengine/mock/FakeExternalTexture.h>
 
+#include "FlagUtils.h"
 #include "FpsOps.h"
 #include "LayerHierarchyTest.h"
 #include "Scheduler/LayerHistory.h"
@@ -36,6 +38,7 @@
 namespace android::scheduler {
 
 using android::mock::createDisplayMode;
+using namespace com::android::graphics::surfaceflinger;
 
 class LayerHistoryIntegrationTest : public surfaceflinger::frontend::LayerSnapshotTestBase {
 protected:
@@ -492,7 +495,9 @@
     EXPECT_EQ(1, frequentLayerCount(time));
 }
 
-TEST_F(LayerHistoryIntegrationTest, invisibleExplicitLayer) {
+TEST_F(LayerHistoryIntegrationTest, invisibleExplicitLayerIsActive) {
+    SET_FLAG_FOR_TEST(flags::misc1, false);
+
     auto explicitVisiblelayer = createLegacyAndFrontedEndLayer(1);
     auto explicitInvisiblelayer = createLegacyAndFrontedEndLayer(2);
     hideLayer(2);
@@ -515,6 +520,31 @@
     EXPECT_EQ(2, frequentLayerCount(time));
 }
 
+TEST_F(LayerHistoryIntegrationTest, invisibleExplicitLayerIsNotActive) {
+    SET_FLAG_FOR_TEST(flags::misc1, true);
+
+    auto explicitVisiblelayer = createLegacyAndFrontedEndLayer(1);
+    auto explicitInvisiblelayer = createLegacyAndFrontedEndLayer(2);
+    hideLayer(2);
+    setFrameRate(1, 60.0f, ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_FIXED_SOURCE,
+                 ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS);
+    setFrameRate(2, 90.0f, ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_FIXED_SOURCE,
+                 ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS);
+    nsecs_t time = systemTime();
+
+    // Post a buffer to the layers to make them active
+    setBufferWithPresentTime(explicitVisiblelayer, time);
+    setBufferWithPresentTime(explicitInvisiblelayer, time);
+
+    EXPECT_EQ(2u, layerCount());
+    ASSERT_EQ(1u, summarizeLayerHistory(time).size());
+    EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitExactOrMultiple,
+              summarizeLayerHistory(time)[0].vote);
+    EXPECT_EQ(60_Hz, summarizeLayerHistory(time)[0].desiredRefreshRate);
+    EXPECT_EQ(1u, activeLayerCount());
+    EXPECT_EQ(1, frequentLayerCount(time));
+}
+
 TEST_F(LayerHistoryIntegrationTest, infrequentAnimatingLayer) {
     auto layer = createLegacyAndFrontedEndLayer(1);
 
diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp
index 33c1d86..e8831ab 100644
--- a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp
@@ -22,10 +22,12 @@
 #define LOG_TAG "LayerHistoryTest"
 
 #include <Layer.h>
+#include <com_android_graphics_surfaceflinger_flags.h>
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
 #include <log/log.h>
 
+#include "FlagUtils.h"
 #include "FpsOps.h"
 #include "Scheduler/LayerHistory.h"
 #include "Scheduler/LayerInfo.h"
@@ -149,6 +151,8 @@
 
 namespace {
 
+using namespace com::android::graphics::surfaceflinger;
+
 TEST_F(LayerHistoryTest, singleLayerNoVoteDefaultCompatibility) {
     const auto layer = createLayer();
     EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true));
@@ -555,6 +559,33 @@
     EXPECT_EQ(FrameRateCategory::High, summarizeLayerHistory(time)[0].frameRateCategory);
 }
 
+TEST_F(LayerHistoryTest, oneLayerExplicitVoteWithCategoryNotVisibleDoesNotVote) {
+    SET_FLAG_FOR_TEST(flags::misc1, true);
+
+    auto layer = createLayer();
+    EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(false));
+    EXPECT_CALL(*layer, getFrameRateForLayerTree())
+            .WillRepeatedly(
+                    Return(Layer::FrameRate(12.34_Hz, Layer::FrameRateCompatibility::Default,
+                                            Seamlessness::OnlySeamless, FrameRateCategory::High)));
+
+    EXPECT_EQ(1, layerCount());
+    EXPECT_EQ(0, activeLayerCount());
+
+    nsecs_t time = systemTime();
+    for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) {
+        history().record(layer->getSequence(), layer->getLayerProps(), time, time,
+                         LayerHistory::LayerUpdateType::Buffer);
+        time += HI_FPS_PERIOD;
+    }
+
+    // Layer is not visible, so the layer is moved to inactive, infrequent, and it will not have
+    // votes to consider for refresh rate selection.
+    ASSERT_EQ(0, summarizeLayerHistory(time).size());
+    EXPECT_EQ(0, activeLayerCount());
+    EXPECT_EQ(0, frequentLayerCount(time));
+}
+
 TEST_F(LayerHistoryTest, multipleLayers) {
     auto layer1 = createLayer("A");
     auto layer2 = createLayer("B");
@@ -780,6 +811,8 @@
 }
 
 TEST_F(LayerHistoryTest, invisibleExplicitLayer) {
+    SET_FLAG_FOR_TEST(flags::misc1, false);
+
     auto explicitVisiblelayer = createLayer();
     auto explicitInvisiblelayer = createLayer();
 
@@ -810,6 +843,39 @@
     EXPECT_EQ(2, frequentLayerCount(time));
 }
 
+TEST_F(LayerHistoryTest, invisibleExplicitLayerDoesNotVote) {
+    SET_FLAG_FOR_TEST(flags::misc1, true);
+
+    auto explicitVisiblelayer = createLayer();
+    auto explicitInvisiblelayer = createLayer();
+
+    EXPECT_CALL(*explicitVisiblelayer, isVisible()).WillRepeatedly(Return(true));
+    EXPECT_CALL(*explicitVisiblelayer, getFrameRateForLayerTree())
+            .WillRepeatedly(Return(
+                    Layer::FrameRate(60_Hz, Layer::FrameRateCompatibility::ExactOrMultiple)));
+
+    EXPECT_CALL(*explicitInvisiblelayer, isVisible()).WillRepeatedly(Return(false));
+    EXPECT_CALL(*explicitInvisiblelayer, getFrameRateForLayerTree())
+            .WillRepeatedly(Return(
+                    Layer::FrameRate(90_Hz, Layer::FrameRateCompatibility::ExactOrMultiple)));
+
+    nsecs_t time = systemTime();
+
+    // Post a buffer to the layers to make them active
+    history().record(explicitVisiblelayer->getSequence(), explicitVisiblelayer->getLayerProps(),
+                     time, time, LayerHistory::LayerUpdateType::Buffer);
+    history().record(explicitInvisiblelayer->getSequence(), explicitInvisiblelayer->getLayerProps(),
+                     time, time, LayerHistory::LayerUpdateType::Buffer);
+
+    EXPECT_EQ(2, layerCount());
+    ASSERT_EQ(1, summarizeLayerHistory(time).size());
+    EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitExactOrMultiple,
+              summarizeLayerHistory(time)[0].vote);
+    EXPECT_EQ(60_Hz, summarizeLayerHistory(time)[0].desiredRefreshRate);
+    EXPECT_EQ(1, activeLayerCount());
+    EXPECT_EQ(1, frequentLayerCount(time));
+}
+
 TEST_F(LayerHistoryTest, infrequentAnimatingLayer) {
     auto layer = createLayer();
 
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index 8f1982d..03af56c 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -271,7 +271,7 @@
         resetScheduler(mScheduler);
     }
 
-    void setupMockScheduler(test::MockSchedulerOptions options = {}) {
+    void setupMockScheduler(surfaceflinger::test::MockSchedulerOptions options = {}) {
         using testing::_;
         using testing::Return;
 
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
index 95004a4..0b07745 100644
--- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
+++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
@@ -178,6 +178,7 @@
     MOCK_METHOD1(onHotplugConnect, void(Display));
     MOCK_METHOD1(onHotplugDisconnect, void(Display));
     MOCK_METHOD(Error, setRefreshRateChangedCallbackDebugEnabled, (Display, bool));
+    MOCK_METHOD(Error, notifyExpectedPresent, (Display, nsecs_t, int32_t));
 };
 
 } // namespace Hwc2::mock