Merge changes If3d6ea21,Iab8360f2

* changes:
  WindowInfo: Remove unused field portalToDisplayId
  InputDispatcher: Allow spy window to receive entire gesture after pilfer
diff --git a/cmds/dumpstate/DumpstateService.cpp b/cmds/dumpstate/DumpstateService.cpp
index 77915d5..e42ee05 100644
--- a/cmds/dumpstate/DumpstateService.cpp
+++ b/cmds/dumpstate/DumpstateService.cpp
@@ -202,7 +202,6 @@
     dprintf(fd, "base_name: %s\n", ds_->base_name_.c_str());
     dprintf(fd, "name: %s\n", ds_->name_.c_str());
     dprintf(fd, "now: %ld\n", ds_->now_);
-    dprintf(fd, "is_zipping: %s\n", ds_->IsZipping() ? "true" : "false");
     dprintf(fd, "notification title: %s\n", ds_->options_->notification_title.c_str());
     dprintf(fd, "notification description: %s\n", ds_->options_->notification_description.c_str());
 
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index e97949e..a951c4f 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -371,14 +371,10 @@
 /*
  * Returns a vector of dump fds under |dir_path| with a given |file_prefix|.
  * The returned vector is sorted by the mtimes of the dumps with descending
- * order. If |limit_by_mtime| is set, the vector only contains files that
- * were written in the last 30 minutes.
+ * order.
  */
 static std::vector<DumpData> GetDumpFds(const std::string& dir_path,
-                                        const std::string& file_prefix,
-                                        bool limit_by_mtime) {
-    const time_t thirty_minutes_ago = ds.now_ - 60 * 30;
-
+                                        const std::string& file_prefix) {
     std::unique_ptr<DIR, decltype(&closedir)> dump_dir(opendir(dir_path.c_str()), closedir);
 
     if (dump_dir == nullptr) {
@@ -412,11 +408,6 @@
             continue;
         }
 
-        if (limit_by_mtime && st.st_mtime < thirty_minutes_ago) {
-            MYLOGI("Excluding stale dump file: %s\n", abs_path.c_str());
-            continue;
-        }
-
         dump_data.emplace_back(DumpData{abs_path, std::move(fd), st.st_mtime});
     }
     if (!dump_data.empty()) {
@@ -447,7 +438,7 @@
                    strerror(errno));
         }
 
-        if (ds.IsZipping() && add_to_zip) {
+        if (add_to_zip) {
             if (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + name, fd, /* timeout = */ 0ms) != OK) {
                 MYLOGE("Unable to add %s to zip file, addZipEntryFromFd failed\n", name.c_str());
             }
@@ -486,7 +477,6 @@
 }
 
 void add_mountinfo() {
-    if (!ds.IsZipping()) return;
     std::string title = "MOUNT INFO";
     mount_points.clear();
     DurationReporter duration_reporter(title, true);
@@ -823,11 +813,6 @@
 
 status_t Dumpstate::AddZipEntryFromFd(const std::string& entry_name, int fd,
                                       std::chrono::milliseconds timeout = 0ms) {
-    if (!IsZipping()) {
-        MYLOGD("Not adding zip entry %s from fd because it's not a zipped bugreport\n",
-               entry_name.c_str());
-        return INVALID_OPERATION;
-    }
     std::string valid_name = entry_name;
 
     // Rename extension if necessary.
@@ -928,21 +913,12 @@
 }
 
 void Dumpstate::AddDir(const std::string& dir, bool recursive) {
-    if (!IsZipping()) {
-        MYLOGD("Not adding dir %s because it's not a zipped bugreport\n", dir.c_str());
-        return;
-    }
     MYLOGD("Adding dir %s (recursive: %d)\n", dir.c_str(), recursive);
     DurationReporter duration_reporter(dir, true);
     dump_files("", dir.c_str(), recursive ? skip_none : is_dir, _add_file_from_fd);
 }
 
 bool Dumpstate::AddTextZipEntry(const std::string& entry_name, const std::string& content) {
-    if (!IsZipping()) {
-        MYLOGD("Not adding text zip entry %s because it's not a zipped bugreport\n",
-               entry_name.c_str());
-        return false;
-    }
     MYLOGD("Adding zip text entry %s\n", entry_name.c_str());
     int32_t err = zip_writer_->StartEntryWithTime(entry_name.c_str(), ZipWriter::kCompress, ds.now_);
     if (err != 0) {
@@ -1035,10 +1011,6 @@
 }
 
 static void DumpIncidentReport() {
-    if (!ds.IsZipping()) {
-        MYLOGD("Not dumping incident report because it's not a zipped bugreport\n");
-        return;
-    }
     const std::string path = ds.bugreport_internal_dir_ + "/tmp_incident_report";
     auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
                 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
@@ -1064,10 +1036,6 @@
     // This function copies into the .zip the system trace that was snapshotted
     // by the early call to MaybeSnapshotSystemTrace(), if any background
     // tracing was happening.
-    if (!ds.IsZipping()) {
-        MYLOGD("Not dumping system trace because it's not a zipped bugreport\n");
-        return;
-    }
     if (!ds.has_system_trace_) {
         // No background trace was happening at the time dumpstate was invoked.
         return;
@@ -1079,10 +1047,6 @@
 }
 
 static void DumpVisibleWindowViews() {
-    if (!ds.IsZipping()) {
-        MYLOGD("Not dumping visible views because it's not a zipped bugreport\n");
-        return;
-    }
     DurationReporter duration_reporter("VISIBLE WINDOW VIEWS");
     const std::string path = ds.bugreport_internal_dir_ + "/tmp_visible_window_views";
     auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
@@ -1163,7 +1127,7 @@
 }
 
 static void AddAnrTraceFiles() {
-    const bool add_to_zip = ds.IsZipping() && ds.version_ == VERSION_SPLIT_ANR;
+    const bool add_to_zip = ds.version_ == VERSION_SPLIT_ANR;
 
     std::string anr_traces_dir = "/data/anr";
 
@@ -1303,10 +1267,6 @@
 static Dumpstate::RunStatus RunDumpsysProto(const std::string& title, int priority,
                                             std::chrono::milliseconds timeout,
                                             std::chrono::milliseconds service_timeout) {
-    if (!ds.IsZipping()) {
-        MYLOGD("Not dumping %s because it's not a zipped bugreport\n", title.c_str());
-        return Dumpstate::RunStatus::OK;
-    }
     sp<android::IServiceManager> sm = defaultServiceManager();
     Dumpsys dumpsys(sm.get());
     Vector<String16> args;
@@ -1386,12 +1346,6 @@
  * if it's not running in the parallel task.
  */
 static void DumpHals(int out_fd = STDOUT_FILENO) {
-    if (!ds.IsZipping()) {
-        RunCommand("HARDWARE HALS", {"lshal", "--all", "--types=all", "--debug"},
-                   CommandOptions::WithTimeout(60).AsRootIfAvailable().Build(),
-                   false, out_fd);
-        return;
-    }
     RunCommand("HARDWARE HALS", {"lshal", "--all", "--types=all"},
                CommandOptions::WithTimeout(10).AsRootIfAvailable().Build(),
                false, out_fd);
@@ -1846,8 +1800,8 @@
 
     /* Run some operations that require root. */
     if (!PropertiesHelper::IsDryRun()) {
-        ds.tombstone_data_ = GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX, !ds.IsZipping());
-        ds.anr_data_ = GetDumpFds(ANR_DIR, ANR_FILE_PREFIX, !ds.IsZipping());
+        ds.tombstone_data_ = GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX);
+        ds.anr_data_ = GetDumpFds(ANR_DIR, ANR_FILE_PREFIX);
     }
 
     ds.AddDir(RECOVERY_DIR, true);
@@ -2394,11 +2348,6 @@
     dprintf(out_fd, "== Board\n");
     dprintf(out_fd, "========================================================\n");
 
-    if (!IsZipping()) {
-        MYLOGD("Not dumping board info because it's not a zipped bugreport\n");
-        return;
-    }
-
     /*
      * mount debugfs for non-user builds with ro.product.debugfs_restrictions.enabled
      * set to true and unmount it after invoking dumpstateBoard_* methods.
@@ -3567,10 +3516,6 @@
     dprintf(fd, "%saverage_max: %d\n", pr, average_max_);
 }
 
-bool Dumpstate::IsZipping() const {
-    return zip_writer_ != nullptr;
-}
-
 std::string Dumpstate::GetPath(const std::string& suffix) const {
     return GetPath(bugreport_internal_dir_, suffix);
 }
@@ -4216,10 +4161,6 @@
 }
 
 void dump_frozen_cgroupfs() {
-    if (!ds.IsZipping()) {
-        MYLOGD("Not adding cgroupfs because it's not a zipped bugreport\n");
-        return;
-    }
     MYLOGD("Adding frozen processes from %s\n", CGROUPFS_DIR);
     DurationReporter duration_reporter("FROZEN CGROUPFS");
     if (PropertiesHelper::IsDryRun()) return;
diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h
index 852b9a8..d0acb31 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -214,9 +214,6 @@
 
     static Dumpstate& GetInstance();
 
-    /* Checkes whether dumpstate is generating a zipped bugreport. */
-    bool IsZipping() const;
-
     /* Initialize dumpstate fields before starting bugreport generation */
     void Initialize();
 
diff --git a/data/etc/android.hardware.telephony.radio.xml b/data/etc/android.hardware.sensor.heading.xml
similarity index 71%
copy from data/etc/android.hardware.telephony.radio.xml
copy to data/etc/android.hardware.sensor.heading.xml
index 4377705..8b81823 100644
--- a/data/etc/android.hardware.telephony.radio.xml
+++ b/data/etc/android.hardware.sensor.heading.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2021 The Android Open Source Project
+<!-- 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.
@@ -14,8 +14,7 @@
      limitations under the License.
 -->
 
-<!-- This is the standard set of features for devices to support Telephony Radio Access API. -->
+<!-- Feature for devices with a heading sensor. -->
 <permissions>
-  <feature name="android.hardware.telephony" />
-  <feature name="android.hardware.telephony.radio" />
+    <feature name="android.hardware.sensor.heading" />
 </permissions>
diff --git a/data/etc/android.hardware.telephony.calling.xml b/data/etc/android.hardware.telephony.calling.xml
index 3e92a66..ab245fc 100644
--- a/data/etc/android.hardware.telephony.calling.xml
+++ b/data/etc/android.hardware.telephony.calling.xml
@@ -18,7 +18,7 @@
 <permissions>
     <feature name="android.hardware.telephony" />
     <feature name="android.software.telecom" />
-    <feature name="android.hardware.telephony.radio" />
+    <feature name="android.hardware.telephony.radio.access" />
     <feature name="android.hardware.telephony.subscription" />
     <feature name="android.hardware.telephony.calling" />
 </permissions>
diff --git a/data/etc/android.hardware.telephony.cdma.xml b/data/etc/android.hardware.telephony.cdma.xml
index c81cf06..0a8cfc4 100644
--- a/data/etc/android.hardware.telephony.cdma.xml
+++ b/data/etc/android.hardware.telephony.cdma.xml
@@ -18,7 +18,7 @@
 <permissions>
     <feature name="android.hardware.telephony" />
     <feature name="android.software.telecom" />
-    <feature name="android.hardware.telephony.radio" />
+    <feature name="android.hardware.telephony.radio.access" />
     <feature name="android.hardware.telephony.subscription" />
     <feature name="android.hardware.telephony.cdma" />
     <feature name="android.hardware.telephony.calling" />
diff --git a/data/etc/android.hardware.telephony.data.xml b/data/etc/android.hardware.telephony.data.xml
index 2716152..a9bb36e 100644
--- a/data/etc/android.hardware.telephony.data.xml
+++ b/data/etc/android.hardware.telephony.data.xml
@@ -17,7 +17,7 @@
 <!-- This is the standard set of features for devices to support Telephony Data API. -->
 <permissions>
     <feature name="android.hardware.telephony" />
-    <feature name="android.hardware.telephony.radio" />
+    <feature name="android.hardware.telephony.radio.access" />
     <feature name="android.hardware.telephony.subscription" />
     <feature name="android.hardware.telephony.data" />
 </permissions>
diff --git a/data/etc/android.hardware.telephony.gsm.xml b/data/etc/android.hardware.telephony.gsm.xml
index e368a06..e3952bf 100644
--- a/data/etc/android.hardware.telephony.gsm.xml
+++ b/data/etc/android.hardware.telephony.gsm.xml
@@ -18,7 +18,7 @@
 <permissions>
     <feature name="android.hardware.telephony" />
     <feature name="android.software.telecom" />
-    <feature name="android.hardware.telephony.radio" />
+    <feature name="android.hardware.telephony.radio.access" />
     <feature name="android.hardware.telephony.subscription" />
     <feature name="android.hardware.telephony.gsm" />
     <feature name="android.hardware.telephony.calling" />
diff --git a/data/etc/android.hardware.telephony.radio.xml b/data/etc/android.hardware.telephony.radio.access.xml
similarity index 92%
rename from data/etc/android.hardware.telephony.radio.xml
rename to data/etc/android.hardware.telephony.radio.access.xml
index 4377705..c98267c 100644
--- a/data/etc/android.hardware.telephony.radio.xml
+++ b/data/etc/android.hardware.telephony.radio.access.xml
@@ -17,5 +17,5 @@
 <!-- This is the standard set of features for devices to support Telephony Radio Access API. -->
 <permissions>
   <feature name="android.hardware.telephony" />
-  <feature name="android.hardware.telephony.radio" />
+  <feature name="android.hardware.telephony.radio.access" />
 </permissions>
diff --git a/include/android/sensor.h b/include/android/sensor.h
index 7e86d3f..cf1ca02 100644
--- a/include/android/sensor.h
+++ b/include/android/sensor.h
@@ -301,6 +301,14 @@
      * supported and a value of 0 means not supported.
      */
     ASENSOR_TYPE_GYROSCOPE_LIMITED_AXES_UNCALIBRATED = 41,
+    /**
+     * {@link ASENSOR_TYPE_HEADING}
+     * reporting-mode: continuous
+     *
+     * A heading sensor measures the direction in which the device is pointing
+     * relative to true north in degrees.
+     */
+    ASENSOR_TYPE_HEADING = 42,
 };
 
 /**
@@ -563,6 +571,23 @@
     };
 } ALimitedAxesImuUncalibratedEvent;
 
+typedef struct AHeadingEvent {
+    /**
+     * The direction in which the device is pointing relative to true north in
+     * degrees. The value must be between 0.0 (inclusive) and 360.0 (exclusive),
+     * with 0 indicating north, 90 east, 180 south, and 270 west.
+     */
+    float heading;
+    /**
+     * Accuracy is defined at 68% confidence. In the case where the underlying
+     * distribution is assumed Gaussian normal, this would be considered one
+     * standard deviation. For example, if the heading returns 60 degrees, and
+     * accuracy returns 10 degrees, then there is a 68 percent probability of
+     * the true heading being between 50 degrees and 70 degrees.
+     */
+    float accuracy;
+} AHeadingEvent;
+
 /**
  * Information that describes a sensor event, refer to
  * <a href="/reference/android/hardware/SensorEvent">SensorEvent</a> for additional
@@ -602,6 +627,7 @@
             AHeadTrackerEvent head_tracker;
             ALimitedAxesImuEvent limited_axes_imu;
             ALimitedAxesImuUncalibratedEvent limited_axes_imu_uncalibrated;
+            AHeadingEvent heading;
         };
         union {
             uint64_t        data[8];
diff --git a/libs/binder/Status.cpp b/libs/binder/Status.cpp
index a44c578..83b97d0 100644
--- a/libs/binder/Status.cpp
+++ b/libs/binder/Status.cpp
@@ -211,6 +211,12 @@
     return status;
 }
 
+status_t Status::writeOverParcel(Parcel* parcel) const {
+    parcel->setDataSize(0);
+    parcel->setDataPosition(0);
+    return writeToParcel(parcel);
+}
+
 void Status::setException(int32_t ex, const String8& message) {
     mException = ex;
     mErrorCode = ex == EX_TRANSACTION_FAILED ? FAILED_TRANSACTION : NO_ERROR;
diff --git a/libs/binder/include/binder/Status.h b/libs/binder/include/binder/Status.h
index aaafa36..af34695 100644
--- a/libs/binder/include/binder/Status.h
+++ b/libs/binder/include/binder/Status.h
@@ -117,6 +117,10 @@
     status_t readFromParcel(const Parcel& parcel);
     status_t writeToParcel(Parcel* parcel) const;
 
+    // Convenience API to replace a Parcel with a status value, w/o requiring
+    // calling multiple APIs (makes generated code smaller).
+    status_t writeOverParcel(Parcel* parcel) const;
+
     // Set one of the pre-defined exception types defined above.
     void setException(int32_t ex, const String8& message);
     // Set a service specific exception with error code.
diff --git a/libs/binder/ndk/Android.bp b/libs/binder/ndk/Android.bp
index 77493b3..79c8c8f 100644
--- a/libs/binder/ndk/Android.bp
+++ b/libs/binder/ndk/Android.bp
@@ -32,16 +32,6 @@
     ],
 }
 
-// TODO(b/211908498): remove this
-cc_defaults {
-    name: "libbinder_ndk_host_user",
-    target: {
-        darwin: {
-            enabled: false,
-        },
-    },
-}
-
 cc_library {
     name: "libbinder_ndk",
 
diff --git a/libs/binder/tests/Android.bp b/libs/binder/tests/Android.bp
index 86da588..ff55d6e 100644
--- a/libs/binder/tests/Android.bp
+++ b/libs/binder/tests/Android.bp
@@ -37,7 +37,11 @@
     srcs: ["binderDriverInterfaceTest.cpp"],
     header_libs: ["libbinder_headers"],
     compile_multilib: "32",
-    multilib: { lib32: { suffix: "" } },
+    multilib: {
+        lib32: {
+            suffix: "",
+        },
+    },
     cflags: ["-DBINDER_IPC_32BIT=1"],
     test_suites: ["vts"],
 }
@@ -52,7 +56,10 @@
     },
     header_libs: ["libbinder_headers"],
     srcs: ["binderDriverInterfaceTest.cpp"],
-    test_suites: ["device-tests", "vts"],
+    test_suites: [
+        "device-tests",
+        "vts",
+    ],
 }
 
 cc_test {
@@ -69,7 +76,11 @@
         "libgmock",
     ],
     compile_multilib: "32",
-    multilib: { lib32: { suffix: "" } },
+    multilib: {
+        lib32: {
+            suffix: "",
+        },
+    },
     cflags: ["-DBINDER_IPC_32BIT=1"],
     test_suites: ["vts"],
     require_root: true,
@@ -84,7 +95,11 @@
             enabled: false,
         },
     },
-    srcs: ["binderParcelUnitTest.cpp", "binderBinderUnitTest.cpp"],
+    srcs: [
+        "binderParcelUnitTest.cpp",
+        "binderBinderUnitTest.cpp",
+        "binderStatusUnitTest.cpp",
+    ],
     shared_libs: [
         "libbinder",
         "libcutils",
@@ -112,7 +127,10 @@
     static_libs: [
         "libgmock",
     ],
-    test_suites: ["device-tests", "vts"],
+    test_suites: [
+        "device-tests",
+        "vts",
+    ],
     require_root: true,
 }
 
@@ -179,7 +197,6 @@
     },
     defaults: [
         "binder_test_defaults",
-        "libbinder_ndk_host_user",
         "libbinder_tls_shared_deps",
     ],
 
@@ -232,7 +249,10 @@
         "libbinder_tls_test_utils",
         "libbinder_tls_static",
     ],
-    test_suites: ["general-tests", "device-tests"],
+    test_suites: [
+        "general-tests",
+        "device-tests",
+    ],
 }
 
 cc_benchmark {
@@ -348,7 +368,10 @@
         "liblog",
         "libutils",
     ],
-    test_suites: ["device-tests", "vts"],
+    test_suites: [
+        "device-tests",
+        "vts",
+    ],
     require_root: true,
 }
 
@@ -402,7 +425,10 @@
         "binderStabilityTestIface-ndk",
     ],
 
-    test_suites: ["device-tests", "vts"],
+    test_suites: [
+        "device-tests",
+        "vts",
+    ],
     require_root: true,
 }
 
diff --git a/libs/binder/tests/binderStatusUnitTest.cpp b/libs/binder/tests/binderStatusUnitTest.cpp
new file mode 100644
index 0000000..a32ec5c
--- /dev/null
+++ b/libs/binder/tests/binderStatusUnitTest.cpp
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2020 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/Parcel.h>
+#include <binder/Status.h>
+#include <gtest/gtest.h>
+
+using android::Parcel;
+using android::binder::Status;
+
+TEST(Status, WriteOverParcel) {
+    Status status = Status::fromExceptionCode(Status::EX_NULL_POINTER);
+
+    Parcel indirect;
+    indirect.writeInt32(64);
+    status.writeOverParcel(&indirect);
+
+    Parcel direct;
+    status.writeToParcel(&direct);
+
+    EXPECT_EQ(0, indirect.compareData(direct));
+}
diff --git a/libs/gralloc/types/Android.bp b/libs/gralloc/types/Android.bp
index 6afd172..bd21fba 100644
--- a/libs/gralloc/types/Android.bp
+++ b/libs/gralloc/types/Android.bp
@@ -23,7 +23,6 @@
 
 cc_library {
     name: "libgralloctypes",
-    defaults: ["libbinder_ndk_host_user"],
     cflags: [
         "-Wall",
         "-Werror",
diff --git a/libs/gralloc/types/fuzzer/Android.bp b/libs/gralloc/types/fuzzer/Android.bp
index 6689771..3c3b6af 100644
--- a/libs/gralloc/types/fuzzer/Android.bp
+++ b/libs/gralloc/types/fuzzer/Android.bp
@@ -9,12 +9,11 @@
 
 cc_fuzz {
     name: "libgralloctypes_fuzzer",
-    defaults: ["libbinder_ndk_host_user"],
     host_supported: true,
     target: {
         darwin: {
             enabled: false,
-        }
+        },
     },
 
     fuzz_config: {
diff --git a/libs/gui/LayerDebugInfo.cpp b/libs/gui/LayerDebugInfo.cpp
index 0827bbe..ea5fb29 100644
--- a/libs/gui/LayerDebugInfo.cpp
+++ b/libs/gui/LayerDebugInfo.cpp
@@ -58,7 +58,6 @@
     RETURN_ON_ERROR(parcel->writeInt32(mActiveBufferStride));
     RETURN_ON_ERROR(parcel->writeInt32(mActiveBufferFormat));
     RETURN_ON_ERROR(parcel->writeInt32(mNumQueuedFrames));
-    RETURN_ON_ERROR(parcel->writeBool(mRefreshPending));
     RETURN_ON_ERROR(parcel->writeBool(mIsOpaque));
     RETURN_ON_ERROR(parcel->writeBool(mContentDirty));
     RETURN_ON_ERROR(parcel->write(mStretchEffect));
@@ -103,7 +102,6 @@
     RETURN_ON_ERROR(parcel->readInt32(&mActiveBufferStride));
     RETURN_ON_ERROR(parcel->readInt32(&mActiveBufferFormat));
     RETURN_ON_ERROR(parcel->readInt32(&mNumQueuedFrames));
-    RETURN_ON_ERROR(parcel->readBool(&mRefreshPending));
     RETURN_ON_ERROR(parcel->readBool(&mIsOpaque));
     RETURN_ON_ERROR(parcel->readBool(&mContentDirty));
     RETURN_ON_ERROR(parcel->read(mStretchEffect));
@@ -146,8 +144,7 @@
     StringAppendF(&result, "      activeBuffer=[%4ux%4u:%4u,%s],", info.mActiveBufferWidth,
                   info.mActiveBufferHeight, info.mActiveBufferStride,
                   decodePixelFormat(info.mActiveBufferFormat).c_str());
-    StringAppendF(&result, " queued-frames=%d, mRefreshPending=%d", info.mNumQueuedFrames,
-                  info.mRefreshPending);
+    StringAppendF(&result, " queued-frames=%d", info.mNumQueuedFrames);
     result.append("\n");
     return result;
 }
diff --git a/libs/gui/include/gui/LayerDebugInfo.h b/libs/gui/include/gui/LayerDebugInfo.h
index 8b7d32c..af834d7 100644
--- a/libs/gui/include/gui/LayerDebugInfo.h
+++ b/libs/gui/include/gui/LayerDebugInfo.h
@@ -64,7 +64,6 @@
     int32_t mActiveBufferStride = 0;
     PixelFormat mActiveBufferFormat = PIXEL_FORMAT_NONE;
     int32_t mNumQueuedFrames = -1;
-    bool mRefreshPending = false;
     bool mIsOpaque = false;
     bool mContentDirty = false;
     StretchEffect mStretchEffect = {};
diff --git a/libs/sensor/Sensor.cpp b/libs/sensor/Sensor.cpp
index 5b4631a..ec0ced8 100644
--- a/libs/sensor/Sensor.cpp
+++ b/libs/sensor/Sensor.cpp
@@ -296,6 +296,10 @@
         mStringType = SENSOR_STRING_TYPE_GYROSCOPE_LIMITED_AXES_UNCALIBRATED;
         mFlags |= SENSOR_FLAG_CONTINUOUS_MODE;
         break;
+    case SENSOR_TYPE_HEADING:
+        mStringType = SENSOR_STRING_TYPE_HEADING;
+        mFlags |= SENSOR_FLAG_CONTINUOUS_MODE;
+        break;
     default:
         // Only pipe the stringType, requiredPermission and flags for custom sensors.
         if (halVersion > SENSORS_DEVICE_API_VERSION_1_0 && hwSensor.stringType) {
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index dc46f30..6c321bc 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -137,7 +137,7 @@
 // Number of recent events to keep for debugging purposes.
 constexpr size_t RECENT_QUEUE_MAX_SIZE = 10;
 
-// Event log tags. See EventLogTags.logtags for reference
+// Event log tags. See EventLogTags.logtags for reference.
 constexpr int LOGTAG_INPUT_INTERACTION = 62000;
 constexpr int LOGTAG_INPUT_FOCUS = 62001;
 constexpr int LOGTAG_INPUT_CANCEL = 62003;
@@ -4903,23 +4903,42 @@
     mLooper->wake();
 }
 
-void InputDispatcher::setInTouchMode(bool inTouchMode) {
+bool InputDispatcher::setInTouchMode(bool inTouchMode, int32_t pid, int32_t uid,
+                                     bool hasPermission) {
     bool needWake = false;
     {
         std::scoped_lock lock(mLock);
         if (mInTouchMode == inTouchMode) {
-            return;
+            return false;
         }
         if (DEBUG_TOUCH_MODE) {
-            ALOGD("Request to change touch mode from %s to %s", toString(mInTouchMode),
-                  toString(inTouchMode));
-            // TODO(b/198487159): Also print the current last interacted apps.
+            ALOGD("Request to change touch mode from %s to %s (calling pid=%d, uid=%d, "
+                  "hasPermission=%s)",
+                  toString(mInTouchMode), toString(inTouchMode), pid, uid, toString(hasPermission));
+        }
+        if (!hasPermission) {
+            const sp<IBinder> focusedToken =
+                    mFocusResolver.getFocusedWindowToken(mFocusedDisplayId);
+
+            //  TODO(b/198487159): if no window is currently focused, then we need to check the last
+            //      interacted window (within 1 second timeout). We should allow touch mode change
+            //      if the last interacted window owner's pid/uid match the calling ones.
+            if (focusedToken == nullptr) {
+                return false;
+            }
+            const sp<WindowInfoHandle> windowHandle = getWindowHandleLocked(focusedToken);
+            if (windowHandle == nullptr) {
+                return false;
+            }
+            const WindowInfo* windowInfo = windowHandle->getInfo();
+            if (pid != windowInfo->ownerPid || uid != windowInfo->ownerUid) {
+                return false;
+            }
         }
 
         // TODO(b/198499018): Store touch mode per display.
         mInTouchMode = inTouchMode;
 
-        // TODO(b/198487159): Enforce that only last interacted apps can change touch mode.
         auto entry = std::make_unique<TouchModeEntry>(mIdGenerator.nextId(), now(), inTouchMode);
         needWake = enqueueInboundEventLocked(std::move(entry));
     } // release lock
@@ -4927,6 +4946,7 @@
     if (needWake) {
         mLooper->wake();
     }
+    return true;
 }
 
 void InputDispatcher::setMaximumObscuringOpacityForTouch(float opacity) {
diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h
index 0a70385..e162c78 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.h
+++ b/services/inputflinger/dispatcher/InputDispatcher.h
@@ -117,7 +117,7 @@
     void setFocusedDisplay(int32_t displayId) override;
     void setInputDispatchMode(bool enabled, bool frozen) override;
     void setInputFilterEnabled(bool enabled) override;
-    void setInTouchMode(bool inTouchMode) override;
+    bool setInTouchMode(bool inTouchMode, int32_t pid, int32_t uid, bool hasPermission) override;
     void setMaximumObscuringOpacityForTouch(float opacity) override;
     void setBlockUntrustedTouchesMode(android::os::BlockUntrustedTouchesMode mode) override;
 
diff --git a/services/inputflinger/dispatcher/include/InputDispatcherInterface.h b/services/inputflinger/dispatcher/include/InputDispatcherInterface.h
index 44ce8ec..67e1b6f 100644
--- a/services/inputflinger/dispatcher/include/InputDispatcherInterface.h
+++ b/services/inputflinger/dispatcher/include/InputDispatcherInterface.h
@@ -123,8 +123,10 @@
      * Touch mode is a global state that apps may enter / exit based on specific
      * user interactions with input devices.
      * If true, the device is in touch mode.
+     *
+     * Returns true when changing touch mode state.
      */
-    virtual void setInTouchMode(bool inTouchMode) = 0;
+    virtual bool setInTouchMode(bool inTouchMode, int32_t pid, int32_t uid, bool hasPermission) = 0;
 
     /**
      * Sets the maximum allowed obscuring opacity by UID to propagate touches.
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index ef1ee26..872882e 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -2997,6 +2997,7 @@
     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
     sp<FakeWindowHandle> window =
             new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
+    const WindowInfo& windowInfo = *window->getInfo();
 
     // Set focused application.
     mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
@@ -3013,7 +3014,8 @@
     window->consumeFocusEvent(false /*hasFocus*/, true /*inTouchMode*/);
 
     SCOPED_TRACE("Disable touch mode");
-    mDispatcher->setInTouchMode(false);
+    mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
+                                /* hasPermission */ true);
     window->consumeTouchModeEvent(false);
     window->setFocusable(true);
     mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
@@ -3026,7 +3028,8 @@
     window->consumeFocusEvent(false /*hasFocus*/, false /*inTouchMode*/);
 
     SCOPED_TRACE("Enable touch mode again");
-    mDispatcher->setInTouchMode(true);
+    mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
+                                /* hasPermission */ true);
     window->consumeTouchModeEvent(true);
     window->setFocusable(true);
     mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
@@ -6231,19 +6234,23 @@
         mWindow->consumeFocusEvent(true);
     }
 
-    void changeAndVerifyTouchMode(bool inTouchMode) {
-        mDispatcher->setInTouchMode(inTouchMode);
+    void changeAndVerifyTouchMode(bool inTouchMode, int32_t pid, int32_t uid, bool hasPermission) {
+        mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission);
         mWindow->consumeTouchModeEvent(inTouchMode);
         mSecondWindow->consumeTouchModeEvent(inTouchMode);
     }
 };
 
 TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchModeOnFocusedWindow) {
-    changeAndVerifyTouchMode(!InputDispatcher::kDefaultInTouchMode);
+    const WindowInfo& windowInfo = *mWindow->getInfo();
+    changeAndVerifyTouchMode(!InputDispatcher::kDefaultInTouchMode, windowInfo.ownerPid,
+                             windowInfo.ownerUid, /* hasPermission */ false);
 }
 
 TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
-    mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode);
+    const WindowInfo& windowInfo = *mWindow->getInfo();
+    mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, windowInfo.ownerPid,
+                                windowInfo.ownerUid, /* hasPermission */ true);
     mWindow->assertNoEvents();
     mSecondWindow->assertNoEvents();
 }
@@ -6813,4 +6820,7 @@
     window->assertNoEvents();
 }
 
+// TODO(b/198487159): Add permission tests for touch mode switch once the validation is put in
+//     place.
+
 } // namespace android::inputdispatcher
diff --git a/services/sensorservice/AidlSensorHalWrapper.cpp b/services/sensorservice/AidlSensorHalWrapper.cpp
index 09aed46..86c8b0d 100644
--- a/services/sensorservice/AidlSensorHalWrapper.cpp
+++ b/services/sensorservice/AidlSensorHalWrapper.cpp
@@ -285,6 +285,11 @@
                     src.payload.get<Event::EventPayload::limitedAxesImuUncal>().zSupported;
             break;
 
+        case SensorType::HEADING:
+            dst->heading.heading = src.payload.get<Event::EventPayload::heading>().heading;
+            dst->heading.accuracy = src.payload.get<Event::EventPayload::heading>().accuracy;
+            break;
+
         default: {
             CHECK_GE((int32_t)src.sensorType, (int32_t)SensorType::DEVICE_PRIVATE_BASE);
 
@@ -473,6 +478,14 @@
             break;
         }
 
+        case SensorType::HEADING: {
+            Event::EventPayload::Heading heading;
+            heading.heading = src.heading.heading;
+            heading.accuracy = src.heading.accuracy;
+            dst->payload.set<Event::EventPayload::heading>(heading);
+            break;
+        }
+
         default: {
             CHECK_GE((int32_t)dst->sensorType, (int32_t)SensorType::DEVICE_PRIVATE_BASE);
 
diff --git a/services/sensorservice/SensorServiceUtils.cpp b/services/sensorservice/SensorServiceUtils.cpp
index c304381..7dd2331 100644
--- a/services/sensorservice/SensorServiceUtils.cpp
+++ b/services/sensorservice/SensorServiceUtils.cpp
@@ -67,6 +67,9 @@
         case SENSOR_TYPE_HEAD_TRACKER:
             return 7;
 
+        case SENSOR_TYPE_HEADING:
+            return 2;
+
         default:
             return 3;
     }
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index b7e2ff3..18a6bae 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -319,7 +319,6 @@
         Mutex::Autolock lock(mFrameEventHistoryMutex);
         mFrameEventHistory.addPreComposition(mCurrentFrameNumber, refreshStartTime);
     }
-    mRefreshPending = false;
     return hasReadyFrame();
 }
 namespace {
@@ -474,19 +473,6 @@
         return refreshRequired;
     }
 
-    if (!hasReadyFrame()) {
-        return false;
-    }
-
-    // if we've already called updateTexImage() without going through
-    // a composition step, we have to skip this layer at this point
-    // because we cannot call updateTeximage() without a corresponding
-    // compositionComplete() call.
-    // we'll trigger an update in onPreComposition().
-    if (mRefreshPending) {
-        return false;
-    }
-
     // If the head buffer's acquire fence hasn't signaled yet, return and
     // try again later
     if (!fenceHasSignaled()) {
@@ -518,7 +504,6 @@
 
     gatherBufferInfo();
 
-    mRefreshPending = true;
     if (oldBufferInfo.mBuffer == nullptr) {
         // the first time we receive a buffer, we need to trigger a
         // geometry invalidation.
@@ -689,7 +674,6 @@
 }
 
 void BufferLayer::latchAndReleaseBuffer() {
-    mRefreshPending = false;
     if (hasReadyFrame()) {
         bool ignored = false;
         latchBuffer(ignored, systemTime(), 0 /* expectedPresentTime */);
diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h
index 99267be..3e70493 100644
--- a/services/surfaceflinger/BufferLayer.h
+++ b/services/surfaceflinger/BufferLayer.h
@@ -88,9 +88,6 @@
     // to figure out if the content or size of a surface has changed.
     bool latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime,
                      nsecs_t expectedPresentTime) override;
-
-    bool isBufferLatched() const override { return mRefreshPending; }
-
     bool hasReadyFrame() const override;
 
     // Returns the current scaling mode
@@ -158,9 +155,6 @@
 
     // from graphics API
     const uint32_t mTextureName;
-
-    bool mRefreshPending{false};
-
     ui::Dataspace translateDataspace(ui::Dataspace dataspace);
     void setInitialValuesForClone(const sp<Layer>& clonedFrom);
     void updateCloneBufferInfo() override;
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 645d4d1..a039250 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -1398,7 +1398,6 @@
         }
     }
     info.mNumQueuedFrames = getQueuedFrameCount();
-    info.mRefreshPending = isBufferLatched();
     info.mIsOpaque = isOpaque(ds);
     info.mContentDirty = contentDirty;
     info.mStretchEffect = getStretchEffect();
@@ -2029,7 +2028,6 @@
     layerInfo->set_is_protected(isProtected());
     layerInfo->set_dataspace(dataspaceDetails(static_cast<android_dataspace>(getDataSpace())));
     layerInfo->set_queued_frames(getQueuedFrameCount());
-    layerInfo->set_refresh_pending(isBufferLatched());
     layerInfo->set_curr_frame(mCurrentFrameNumber);
     layerInfo->set_effective_scaling_mode(getEffectiveScalingMode());
 
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 605a27e..ddcd641 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -549,8 +549,6 @@
         return false;
     }
 
-    virtual bool isBufferLatched() const { return false; }
-
     virtual void latchAndReleaseBuffer() {}
 
     /*
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 3459a8f..b3c3a41 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -3563,11 +3563,9 @@
         for (const auto& layer : mLayersWithQueuedFrames) {
             if (layer->latchBuffer(visibleRegions, latchTime, expectedPresentTime)) {
                 mLayersPendingRefresh.push_back(layer);
-            }
-            layer->useSurfaceDamage();
-            if (layer->isBufferLatched()) {
                 newDataLatched = true;
             }
+            layer->useSurfaceDamage();
         }
     }
 
@@ -3915,7 +3913,8 @@
     // been applied by SF
     if (state.flags & eAnimation) {
         while (itr != mPendingTransactionQueues.end()) {
-            status_t err = mTransactionQueueCV.waitRelative(mQueueLock, s2ns(5));
+            status_t err =
+                    mTransactionQueueCV.waitRelative(mQueueLock, mAnimationTransactionTimeout);
             if (CC_UNLIKELY(err != NO_ERROR)) {
                 ALOGW_IF(err == TIMED_OUT,
                          "setTransactionState timed out "
@@ -3951,7 +3950,8 @@
     // applyTransactionState is called on the main SF thread.  While a given process may wish
     // to wait on synchronous transactions, the main SF thread should apply the transaction and
     // set the value to notify this after committed.
-    if (!transactionCommittedSignal.wait_until(std::chrono::seconds(5))) {
+    if (!transactionCommittedSignal.wait_until(
+                std::chrono::nanoseconds(mAnimationTransactionTimeout))) {
         ALOGE("setTransactionState timed out!");
     }
 }
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index c6a4d85..77193a6 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -1372,6 +1372,8 @@
         nsecs_t compositeStart;
         nsecs_t presentEnd;
     } mPowerHintSessionData GUARDED_BY(SF_MAIN_THREAD);
+
+    nsecs_t mAnimationTransactionTimeout = s2ns(5);
 };
 
 } // namespace android
diff --git a/services/surfaceflinger/TransactionState.h b/services/surfaceflinger/TransactionState.h
index fe3f3fc..04ca347 100644
--- a/services/surfaceflinger/TransactionState.h
+++ b/services/surfaceflinger/TransactionState.h
@@ -93,7 +93,7 @@
     }
 
     // Return true if triggered.
-    bool wait_until(const std::chrono::seconds& timeout) const {
+    bool wait_until(const std::chrono::nanoseconds& timeout) const {
         std::unique_lock<std::mutex> lock(mMutex);
         const auto untilTime = std::chrono::system_clock::now() + timeout;
         while (mFlags != 0) {
diff --git a/services/surfaceflinger/fuzzer/Android.bp b/services/surfaceflinger/fuzzer/Android.bp
index 0ead163..b0d216e 100644
--- a/services/surfaceflinger/fuzzer/Android.bp
+++ b/services/surfaceflinger/fuzzer/Android.bp
@@ -92,3 +92,13 @@
         "android.hardware.graphics.composer@2.4-hal",
     ],
 }
+
+cc_fuzz {
+    name: "surfaceflinger_scheduler_fuzzer",
+    defaults: [
+        "surfaceflinger_fuzz_defaults",
+    ],
+    srcs: [
+        "surfaceflinger_scheduler_fuzzer.cpp",
+    ],
+}
diff --git a/services/surfaceflinger/fuzzer/README.md b/services/surfaceflinger/fuzzer/README.md
index 4ecf770..6231ca5 100644
--- a/services/surfaceflinger/fuzzer/README.md
+++ b/services/surfaceflinger/fuzzer/README.md
@@ -2,6 +2,7 @@
 ## Table of contents
 + [SurfaceFlinger](#SurfaceFlinger)
 + [DisplayHardware](#DisplayHardware)
++ [Scheduler](#Scheduler)
 
 # <a name="SurfaceFlinger"></a> Fuzzer for SurfaceFlinger
 
@@ -51,3 +52,21 @@
   $ adb sync data
   $ adb shell /data/fuzz/arm64/surfaceflinger_displayhardware_fuzzer/surfaceflinger_displayhardware_fuzzer
 ```
+
+# <a name="Scheduler"></a> Fuzzer for Scheduler
+
+Scheduler supports the following parameters:
+1. VSync Periods (parameter name: `lowFpsPeriod`)
+
+You can find the possible values in the fuzzer's source code.
+
+#### Steps to run
+1. Build the fuzzer
+```
+  $ mm -j$(nproc) surfaceflinger_scheduler_fuzzer
+```
+2. To run on device
+```
+  $ adb sync data
+  $ adb shell /data/fuzz/arm64/surfaceflinger_scheduler_fuzzer/surfaceflinger_scheduler_fuzzer
+```
diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.cpp b/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.cpp
new file mode 100644
index 0000000..51a5081
--- /dev/null
+++ b/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.cpp
@@ -0,0 +1,392 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include "surfaceflinger_scheduler_fuzzer.h"
+#include <fuzzer/FuzzedDataProvider.h>
+#include <processgroup/sched_policy.h>
+#include "Scheduler/DispSyncSource.h"
+#include "Scheduler/OneShotTimer.h"
+#include "Scheduler/VSyncDispatchTimerQueue.h"
+#include "Scheduler/VSyncPredictor.h"
+#include "Scheduler/VSyncReactor.h"
+#include "surfaceflinger_fuzzers_utils.h"
+
+namespace android::fuzz {
+
+using hardware::graphics::composer::hal::PowerMode;
+
+static constexpr PowerMode kPowerModes[] = {PowerMode::ON, PowerMode::DOZE, PowerMode::OFF,
+                                            PowerMode::DOZE_SUSPEND, PowerMode::ON_SUSPEND};
+
+constexpr uint16_t kRandomStringLength = 256;
+constexpr std::chrono::duration kSyncPeriod(16ms);
+
+template <typename T>
+void dump(T* component, FuzzedDataProvider* fdp) {
+    std::string res = fdp->ConsumeRandomLengthString(kRandomStringLength);
+    component->dump(res);
+}
+
+class SchedulerFuzzer : private VSyncSource::Callback {
+public:
+    SchedulerFuzzer(const uint8_t* data, size_t size) : mFdp(data, size){};
+    void process();
+
+private:
+    void fuzzRefreshRateSelection();
+    void fuzzRefreshRateConfigs();
+    void fuzzVSyncModulator();
+    void fuzzVSyncPredictor();
+    void fuzzVSyncReactor();
+    void fuzzLayerHistory();
+    void fuzzDispSyncSource();
+    void fuzzCallbackToken(scheduler::VSyncDispatchTimerQueue* dispatch);
+    void fuzzVSyncDispatchTimerQueue();
+    void fuzzOneShotTimer();
+    void fuzzEventThread();
+    PhysicalDisplayId getPhysicalDisplayId();
+
+    FuzzedDataProvider mFdp;
+
+protected:
+    void onVSyncEvent(nsecs_t /* when */, nsecs_t /* expectedVSyncTimestamp */,
+                      nsecs_t /* deadlineTimestamp */) {}
+};
+
+PhysicalDisplayId SchedulerFuzzer::getPhysicalDisplayId() {
+    PhysicalDisplayId internalDispId = PhysicalDisplayId::fromPort(111u);
+    PhysicalDisplayId externalDispId = PhysicalDisplayId::fromPort(222u);
+    PhysicalDisplayId randomDispId = PhysicalDisplayId::fromPort(mFdp.ConsumeIntegral<uint16_t>());
+    PhysicalDisplayId dispId64Bit = PhysicalDisplayId::fromEdid(0xffu, 0xffffu, 0xffff'ffffu);
+    PhysicalDisplayId displayId = mFdp.PickValueInArray<PhysicalDisplayId>(
+            {internalDispId, externalDispId, dispId64Bit, randomDispId});
+    return displayId;
+}
+
+void SchedulerFuzzer::fuzzEventThread() {
+    const auto getVsyncPeriod = [](uid_t /* uid */) { return kSyncPeriod.count(); };
+    std::unique_ptr<android::impl::EventThread> thread = std::make_unique<
+            android::impl::EventThread>(std::move(std::make_unique<FuzzImplVSyncSource>()), nullptr,
+                                        nullptr, nullptr, getVsyncPeriod);
+
+    thread->onHotplugReceived(getPhysicalDisplayId(), mFdp.ConsumeBool());
+    sp<EventThreadConnection> connection =
+            new EventThreadConnection(thread.get(), mFdp.ConsumeIntegral<uint16_t>(), nullptr,
+                                      {} /*eventRegistration*/);
+    thread->requestNextVsync(connection);
+    thread->setVsyncRate(mFdp.ConsumeIntegral<uint32_t>() /*rate*/, connection);
+
+    thread->setDuration((std::chrono::nanoseconds)mFdp.ConsumeIntegral<uint64_t>(),
+                        (std::chrono::nanoseconds)mFdp.ConsumeIntegral<uint64_t>());
+    thread->registerDisplayEventConnection(connection);
+    thread->onScreenAcquired();
+    thread->onScreenReleased();
+    dump<android::impl::EventThread>(thread.get(), &mFdp);
+}
+
+void SchedulerFuzzer::fuzzDispSyncSource() {
+    std::unique_ptr<FuzzImplVSyncDispatch> vSyncDispatch =
+            std::make_unique<FuzzImplVSyncDispatch>();
+    std::unique_ptr<scheduler::DispSyncSource> dispSyncSource = std::make_unique<
+            scheduler::DispSyncSource>(*vSyncDispatch,
+                                       (std::chrono::nanoseconds)
+                                               mFdp.ConsumeIntegral<uint64_t>() /*workDuration*/,
+                                       (std::chrono::nanoseconds)mFdp.ConsumeIntegral<uint64_t>()
+                                       /*readyDuration*/,
+                                       mFdp.ConsumeBool(),
+                                       mFdp.ConsumeRandomLengthString(kRandomStringLength).c_str());
+    dispSyncSource->setVSyncEnabled(true);
+    dispSyncSource->setCallback(this);
+    dispSyncSource->setDuration((std::chrono::nanoseconds)mFdp.ConsumeIntegral<uint64_t>(), 0ns);
+    dump<scheduler::DispSyncSource>(dispSyncSource.get(), &mFdp);
+}
+
+void SchedulerFuzzer::fuzzCallbackToken(scheduler::VSyncDispatchTimerQueue* dispatch) {
+    scheduler::VSyncDispatch::CallbackToken tmp = dispatch->registerCallback(
+            [&](auto, auto, auto) {
+                dispatch->schedule(tmp,
+                                   {.workDuration = mFdp.ConsumeIntegral<nsecs_t>(),
+                                    .readyDuration = mFdp.ConsumeIntegral<nsecs_t>(),
+                                    .earliestVsync = mFdp.ConsumeIntegral<nsecs_t>()});
+            },
+            "o.o");
+    dispatch->schedule(tmp,
+                       {.workDuration = mFdp.ConsumeIntegral<nsecs_t>(),
+                        .readyDuration = mFdp.ConsumeIntegral<nsecs_t>(),
+                        .earliestVsync = mFdp.ConsumeIntegral<nsecs_t>()});
+    dispatch->unregisterCallback(tmp);
+    dispatch->cancel(tmp);
+}
+
+void SchedulerFuzzer::fuzzVSyncDispatchTimerQueue() {
+    FuzzImplVSyncTracker stubTracker{mFdp.ConsumeIntegral<nsecs_t>()};
+    scheduler::VSyncDispatchTimerQueue
+            mDispatch{std::make_unique<scheduler::ControllableClock>(), stubTracker,
+                      mFdp.ConsumeIntegral<nsecs_t>() /*dispatchGroupThreshold*/,
+                      mFdp.ConsumeIntegral<nsecs_t>() /*vSyncMoveThreshold*/};
+
+    fuzzCallbackToken(&mDispatch);
+
+    dump<scheduler::VSyncDispatchTimerQueue>(&mDispatch, &mFdp);
+
+    scheduler::VSyncDispatchTimerQueueEntry entry(
+            "fuzz", [](auto, auto, auto) {},
+            mFdp.ConsumeIntegral<nsecs_t>() /*vSyncMoveThreshold*/);
+    entry.update(stubTracker, 0);
+    entry.schedule({.workDuration = mFdp.ConsumeIntegral<nsecs_t>(),
+                    .readyDuration = mFdp.ConsumeIntegral<nsecs_t>(),
+                    .earliestVsync = mFdp.ConsumeIntegral<nsecs_t>()},
+                   stubTracker, 0);
+    entry.disarm();
+    entry.ensureNotRunning();
+    entry.schedule({.workDuration = mFdp.ConsumeIntegral<nsecs_t>(),
+                    .readyDuration = mFdp.ConsumeIntegral<nsecs_t>(),
+                    .earliestVsync = mFdp.ConsumeIntegral<nsecs_t>()},
+                   stubTracker, 0);
+    auto const wakeup = entry.wakeupTime();
+    auto const ready = entry.readyTime();
+    entry.callback(entry.executing(), *wakeup, *ready);
+    entry.addPendingWorkloadUpdate({.workDuration = mFdp.ConsumeIntegral<nsecs_t>(),
+                                    .readyDuration = mFdp.ConsumeIntegral<nsecs_t>(),
+                                    .earliestVsync = mFdp.ConsumeIntegral<nsecs_t>()});
+    dump<scheduler::VSyncDispatchTimerQueueEntry>(&entry, &mFdp);
+}
+
+void SchedulerFuzzer::fuzzVSyncPredictor() {
+    uint16_t now = mFdp.ConsumeIntegral<uint16_t>();
+    uint16_t historySize = mFdp.ConsumeIntegralInRange<uint16_t>(1, UINT16_MAX);
+    uint16_t minimumSamplesForPrediction = mFdp.ConsumeIntegralInRange<uint16_t>(1, UINT16_MAX);
+    scheduler::VSyncPredictor tracker{mFdp.ConsumeIntegral<uint16_t>() /*period*/, historySize,
+                                      minimumSamplesForPrediction,
+                                      mFdp.ConsumeIntegral<uint32_t>() /*outlierTolerancePercent*/};
+    uint16_t period = mFdp.ConsumeIntegral<uint16_t>();
+    tracker.setPeriod(period);
+    for (uint16_t i = 0; i < minimumSamplesForPrediction; ++i) {
+        if (!tracker.needsMoreSamples()) {
+            break;
+        }
+        tracker.addVsyncTimestamp(now += period);
+    }
+    tracker.nextAnticipatedVSyncTimeFrom(now);
+    tracker.resetModel();
+}
+
+void SchedulerFuzzer::fuzzOneShotTimer() {
+    FakeClock* clock = new FakeClock();
+    std::unique_ptr<scheduler::OneShotTimer> idleTimer = std::make_unique<scheduler::OneShotTimer>(
+            mFdp.ConsumeRandomLengthString(kRandomStringLength) /*name*/,
+            (std::chrono::milliseconds)mFdp.ConsumeIntegral<uint8_t>() /*val*/,
+            [] {} /*resetCallback*/, [] {} /*timeoutCallback*/, std::unique_ptr<FakeClock>(clock));
+    idleTimer->start();
+    idleTimer->reset();
+    idleTimer->stop();
+}
+
+void SchedulerFuzzer::fuzzLayerHistory() {
+    TestableSurfaceFlinger flinger;
+    flinger.setupScheduler(std::make_unique<android::mock::VsyncController>(),
+                           std::make_unique<android::mock::VSyncTracker>(),
+                           std::make_unique<android::mock::EventThread>(),
+                           std::make_unique<android::mock::EventThread>());
+    flinger.setupTimeStats(std::make_unique<android::mock::TimeStats>());
+    std::unique_ptr<android::renderengine::RenderEngine> renderEngine =
+            std::make_unique<android::renderengine::mock::RenderEngine>();
+    flinger.setupRenderEngine(std::move(renderEngine));
+    flinger.setupComposer(std::make_unique<android::Hwc2::mock::Composer>());
+
+    scheduler::TestableScheduler* scheduler = flinger.scheduler();
+
+    scheduler::LayerHistory& historyV1 = scheduler->mutableLayerHistory();
+    nsecs_t time1 = systemTime();
+    nsecs_t time2 = time1;
+    uint8_t historySize = mFdp.ConsumeIntegral<uint8_t>();
+
+    sp<FuzzImplLayer> layer1 = new FuzzImplLayer(flinger.flinger());
+    sp<FuzzImplLayer> layer2 = new FuzzImplLayer(flinger.flinger());
+
+    for (int i = 0; i < historySize; ++i) {
+        historyV1.record(layer1.get(), time1, time1,
+                         scheduler::LayerHistory::LayerUpdateType::Buffer);
+        historyV1.record(layer2.get(), time2, time2,
+                         scheduler::LayerHistory::LayerUpdateType::Buffer);
+        time1 += mFdp.PickValueInArray(kVsyncPeriods);
+        time2 += mFdp.PickValueInArray(kVsyncPeriods);
+    }
+    historyV1.summarize(*scheduler->refreshRateConfigs(), time1);
+    historyV1.summarize(*scheduler->refreshRateConfigs(), time2);
+
+    scheduler->createConnection(std::make_unique<android::mock::EventThread>());
+
+    scheduler::ConnectionHandle handle;
+    scheduler->createDisplayEventConnection(handle);
+    scheduler->setDuration(handle, (std::chrono::nanoseconds)mFdp.ConsumeIntegral<uint64_t>(),
+                           (std::chrono::nanoseconds)mFdp.ConsumeIntegral<uint64_t>());
+
+    dump<scheduler::TestableScheduler>(scheduler, &mFdp);
+}
+
+void SchedulerFuzzer::fuzzVSyncReactor() {
+    std::shared_ptr<FuzzImplVSyncTracker> vSyncTracker = std::make_shared<FuzzImplVSyncTracker>();
+    scheduler::VSyncReactor reactor(std::make_unique<ClockWrapper>(
+                                            std::make_shared<FuzzImplClock>()),
+                                    *vSyncTracker, mFdp.ConsumeIntegral<uint8_t>() /*pendingLimit*/,
+                                    false);
+
+    reactor.startPeriodTransition(mFdp.ConsumeIntegral<nsecs_t>());
+    bool periodFlushed = mFdp.ConsumeBool();
+    reactor.addHwVsyncTimestamp(0, std::nullopt, &periodFlushed);
+    reactor.addHwVsyncTimestamp(mFdp.ConsumeIntegral<nsecs_t>() /*newPeriod*/, std::nullopt,
+                                &periodFlushed);
+    sp<Fence> fence = new Fence(memfd_create("fd", MFD_ALLOW_SEALING));
+    std::shared_ptr<FenceTime> ft = std::make_shared<FenceTime>(fence);
+    vSyncTracker->addVsyncTimestamp(mFdp.ConsumeIntegral<nsecs_t>());
+    FenceTime::Snapshot snap(mFdp.ConsumeIntegral<nsecs_t>());
+    ft->applyTrustedSnapshot(snap);
+    reactor.setIgnorePresentFences(mFdp.ConsumeBool());
+    reactor.addPresentFence(ft);
+    dump<scheduler::VSyncReactor>(&reactor, &mFdp);
+}
+
+void SchedulerFuzzer::fuzzVSyncModulator() {
+    enum {
+        SF_OFFSET_LATE,
+        APP_OFFSET_LATE,
+        SF_DURATION_LATE,
+        APP_DURATION_LATE,
+        SF_OFFSET_EARLY,
+        APP_OFFSET_EARLY,
+        SF_DURATION_EARLY,
+        APP_DURATION_EARLY,
+        SF_OFFSET_EARLY_GPU,
+        APP_OFFSET_EARLY_GPU,
+        SF_DURATION_EARLY_GPU,
+        APP_DURATION_EARLY_GPU,
+        HWC_MIN_WORK_DURATION,
+    };
+    using Schedule = scheduler::TransactionSchedule;
+    using nanos = std::chrono::nanoseconds;
+    using VsyncModulator = scheduler::VsyncModulator;
+    using FuzzImplVsyncModulator = scheduler::FuzzImplVsyncModulator;
+    const VsyncModulator::VsyncConfig early{SF_OFFSET_EARLY, APP_OFFSET_EARLY,
+                                            nanos(SF_DURATION_LATE), nanos(APP_DURATION_LATE)};
+    const VsyncModulator::VsyncConfig earlyGpu{SF_OFFSET_EARLY_GPU, APP_OFFSET_EARLY_GPU,
+                                               nanos(SF_DURATION_EARLY), nanos(APP_DURATION_EARLY)};
+    const VsyncModulator::VsyncConfig late{SF_OFFSET_LATE, APP_OFFSET_LATE,
+                                           nanos(SF_DURATION_EARLY_GPU),
+                                           nanos(APP_DURATION_EARLY_GPU)};
+    const VsyncModulator::VsyncConfigSet offsets = {early, earlyGpu, late,
+                                                    nanos(HWC_MIN_WORK_DURATION)};
+    sp<FuzzImplVsyncModulator> vSyncModulator =
+            sp<FuzzImplVsyncModulator>::make(offsets, scheduler::Now);
+    (void)vSyncModulator->setVsyncConfigSet(offsets);
+    (void)vSyncModulator->setTransactionSchedule(Schedule::Late);
+    const auto token = sp<BBinder>::make();
+    (void)vSyncModulator->setTransactionSchedule(Schedule::EarlyStart, token);
+    vSyncModulator->binderDied(token);
+}
+
+void SchedulerFuzzer::fuzzRefreshRateSelection() {
+    TestableSurfaceFlinger flinger;
+    flinger.setupScheduler(std::make_unique<android::mock::VsyncController>(),
+                           std::make_unique<android::mock::VSyncTracker>(),
+                           std::make_unique<android::mock::EventThread>(),
+                           std::make_unique<android::mock::EventThread>());
+
+    sp<Client> client;
+    LayerCreationArgs args(flinger.flinger(), client,
+                           mFdp.ConsumeRandomLengthString(kRandomStringLength) /*name*/,
+                           mFdp.ConsumeIntegral<uint16_t>() /*layerFlags*/, LayerMetadata());
+    sp<Layer> layer = new BufferQueueLayer(args);
+
+    layer->setFrameRateSelectionPriority(mFdp.ConsumeIntegral<int16_t>());
+}
+
+void SchedulerFuzzer::fuzzRefreshRateConfigs() {
+    using RefreshRateConfigs = scheduler::RefreshRateConfigs;
+    using LayerRequirement = RefreshRateConfigs::LayerRequirement;
+    using RefreshRateStats = scheduler::RefreshRateStats;
+    uint16_t minRefreshRate = mFdp.ConsumeIntegralInRange<uint16_t>(1, UINT16_MAX >> 1);
+    uint16_t maxRefreshRate = mFdp.ConsumeIntegralInRange<uint16_t>(minRefreshRate + 1, UINT16_MAX);
+
+    DisplayModeId hwcConfigIndexType = DisplayModeId(mFdp.ConsumeIntegralInRange<uint8_t>(0, 10));
+
+    DisplayModes displayModes;
+    for (uint16_t fps = minRefreshRate; fps < maxRefreshRate; ++fps) {
+        constexpr int32_t kGroup = 0;
+        const auto refreshRate = Fps::fromValue(static_cast<float>(fps));
+        displayModes.push_back(scheduler::createDisplayMode(hwcConfigIndexType, kGroup,
+                                                            refreshRate.getPeriodNsecs()));
+    }
+    auto refreshRateConfigs =
+            std::make_unique<RefreshRateConfigs>(displayModes, hwcConfigIndexType);
+    const RefreshRateConfigs::GlobalSignals globalSignals = {.touch = false, .idle = false};
+    auto layers = std::vector<LayerRequirement>{
+            LayerRequirement{.weight = mFdp.ConsumeFloatingPoint<float>()}};
+    refreshRateConfigs->getBestRefreshRate(layers, globalSignals);
+    layers[0].name = mFdp.ConsumeRandomLengthString(kRandomStringLength);
+    layers[0].ownerUid = mFdp.ConsumeIntegral<uint16_t>();
+    layers[0].desiredRefreshRate = Fps::fromValue(mFdp.ConsumeFloatingPoint<float>());
+    layers[0].vote = mFdp.PickValueInArray(kLayerVoteTypes);
+    auto frameRateOverrides =
+            refreshRateConfigs->getFrameRateOverrides(layers,
+                                                      Fps::fromValue(
+                                                              mFdp.ConsumeFloatingPoint<float>()),
+                                                      globalSignals);
+
+    refreshRateConfigs->setDisplayManagerPolicy(
+            {hwcConfigIndexType,
+             {Fps::fromValue(mFdp.ConsumeFloatingPoint<float>()),
+              Fps::fromValue(mFdp.ConsumeFloatingPoint<float>())}});
+    refreshRateConfigs->setCurrentModeId(hwcConfigIndexType);
+
+    RefreshRateConfigs::isFractionalPairOrMultiple(Fps::fromValue(
+                                                           mFdp.ConsumeFloatingPoint<float>()),
+                                                   Fps::fromValue(
+                                                           mFdp.ConsumeFloatingPoint<float>()));
+    RefreshRateConfigs::getFrameRateDivider(Fps::fromValue(mFdp.ConsumeFloatingPoint<float>()),
+                                            Fps::fromValue(mFdp.ConsumeFloatingPoint<float>()));
+
+    android::mock::TimeStats timeStats;
+    std::unique_ptr<RefreshRateStats> refreshRateStats =
+            std::make_unique<RefreshRateStats>(timeStats,
+                                               Fps::fromValue(mFdp.ConsumeFloatingPoint<float>()),
+                                               PowerMode::OFF);
+    refreshRateStats->setRefreshRate(
+            refreshRateConfigs->getRefreshRateFromModeId(hwcConfigIndexType).getFps());
+    refreshRateStats->setPowerMode(mFdp.PickValueInArray(kPowerModes));
+}
+
+void SchedulerFuzzer::process() {
+    fuzzRefreshRateSelection();
+    fuzzRefreshRateConfigs();
+    fuzzVSyncModulator();
+    fuzzVSyncPredictor();
+    fuzzVSyncReactor();
+    fuzzLayerHistory();
+    fuzzDispSyncSource();
+    fuzzEventThread();
+    fuzzVSyncDispatchTimerQueue();
+    fuzzOneShotTimer();
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+    SchedulerFuzzer schedulerFuzzer(data, size);
+    schedulerFuzzer.process();
+    return 0;
+}
+
+} // namespace android::fuzz
diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.h b/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.h
new file mode 100644
index 0000000..89cf819
--- /dev/null
+++ b/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.h
@@ -0,0 +1,229 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/*
+    Reference for some of the classes and functions has been taken from unittests
+    present in frameworks/native/services/surfaceflinger/tests/unittests
+*/
+
+#pragma once
+
+#include "Clock.h"
+#include "Layer.h"
+#include "Scheduler/EventThread.h"
+#include "Scheduler/RefreshRateConfigs.h"
+#include "Scheduler/Scheduler.h"
+#include "Scheduler/VSyncTracker.h"
+#include "Scheduler/VsyncModulator.h"
+#include "scheduler/TimeKeeper.h"
+
+namespace android::fuzz {
+
+constexpr int64_t kVsyncPeriods[] = {static_cast<int64_t>(1e9f / 30),
+                                     static_cast<int64_t>(1e9f / 60),
+                                     static_cast<int64_t>(1e9f / 72),
+                                     static_cast<int64_t>(1e9f / 90),
+                                     static_cast<int64_t>(1e9f / 120)};
+
+android::scheduler::RefreshRateConfigs::LayerVoteType kLayerVoteTypes[] =
+        {android::scheduler::RefreshRateConfigs::LayerVoteType::NoVote,
+         android::scheduler::RefreshRateConfigs::LayerVoteType::Min,
+         android::scheduler::RefreshRateConfigs::LayerVoteType::Max,
+         android::scheduler::RefreshRateConfigs::LayerVoteType::Heuristic,
+         android::scheduler::RefreshRateConfigs::LayerVoteType::ExplicitDefault,
+         android::scheduler::RefreshRateConfigs::LayerVoteType::ExplicitExactOrMultiple};
+
+class FuzzImplClock : public android::scheduler::Clock {
+public:
+    nsecs_t now() const { return 1; }
+};
+
+class ClockWrapper : public android::scheduler::Clock {
+public:
+    ClockWrapper(std::shared_ptr<android::scheduler::Clock> const& clock) : mClock(clock) {}
+
+    nsecs_t now() const { return mClock->now(); }
+
+private:
+    std::shared_ptr<android::scheduler::Clock> const mClock;
+};
+
+} // namespace android::fuzz
+
+namespace android {
+
+using namespace std::chrono_literals;
+
+class FakeClock : public Clock {
+public:
+    virtual ~FakeClock() = default;
+    std::chrono::steady_clock::time_point now() const override { return mNow; }
+
+    void advanceTime(std::chrono::nanoseconds delta) { mNow += delta; }
+
+private:
+    std::chrono::steady_clock::time_point mNow;
+};
+
+class FuzzImplLayer : public Layer {
+public:
+    FuzzImplLayer(SurfaceFlinger* flinger, std::string name)
+          : Layer(LayerCreationArgs(flinger, nullptr, std::move(name), 0, {})) {}
+    explicit FuzzImplLayer(SurfaceFlinger* flinger) : FuzzImplLayer(flinger, "FuzzLayer") {}
+
+    const char* getType() const override { return ""; }
+
+    bool isVisible() const override { return true; }
+
+    sp<Layer> createClone() override { return nullptr; }
+};
+
+class FuzzImplVSyncSource : public VSyncSource {
+public:
+    const char* getName() const override { return "fuzz"; }
+
+    void setVSyncEnabled(bool /* enable */) override {}
+
+    void setCallback(Callback* /* callback */) override {}
+
+    void setDuration(std::chrono::nanoseconds /* workDuration */,
+                     std::chrono::nanoseconds /* readyDuration */) override {}
+
+    void dump(std::string& /* result */) const override {}
+};
+
+class FuzzImplVSyncTracker : public scheduler::VSyncTracker {
+public:
+    FuzzImplVSyncTracker(nsecs_t period) { mPeriod = period; }
+
+    FuzzImplVSyncTracker() = default;
+
+    bool addVsyncTimestamp(nsecs_t /* timestamp */) override { return true; }
+
+    nsecs_t nextAnticipatedVSyncTimeFrom(nsecs_t /* timePoint */) const override { return 1; }
+
+    nsecs_t currentPeriod() const override { return 1; }
+
+    void setPeriod(nsecs_t /* period */) override {}
+
+    void resetModel() override {}
+
+    bool needsMoreSamples() const override { return true; }
+
+    bool isVSyncInPhase(nsecs_t /* timePoint */, Fps /* frameRate */) const override {
+        return true;
+    }
+
+    nsecs_t nextVSyncTime(nsecs_t timePoint) const {
+        if (timePoint % mPeriod == 0) {
+            return timePoint;
+        }
+        return (timePoint - (timePoint % mPeriod) + mPeriod);
+    }
+
+    void dump(std::string& /* result */) const override {}
+
+protected:
+    nsecs_t mPeriod;
+};
+
+class FuzzImplVSyncDispatch : public scheduler::VSyncDispatch {
+public:
+    CallbackToken registerCallback(Callback /* callbackFn */,
+                                   std::string /* callbackName */) override {
+        return CallbackToken{};
+    }
+
+    void unregisterCallback(CallbackToken /* token */) override {}
+
+    scheduler::ScheduleResult schedule(CallbackToken /* token */,
+                                       ScheduleTiming /* scheduleTiming */) override {
+        return (scheduler::ScheduleResult)0;
+    }
+
+    scheduler::CancelResult cancel(CallbackToken /* token */) override {
+        return (scheduler::CancelResult)0;
+    }
+
+    void dump(std::string& /* result */) const override {}
+};
+
+} // namespace android
+
+namespace android::scheduler {
+
+DisplayModePtr createDisplayMode(DisplayModeId modeId, int32_t group, int64_t vsyncPeriod,
+                                 ui::Size resolution = ui::Size()) {
+    return DisplayMode::Builder(hal::HWConfigId(modeId.value()))
+            .setId(modeId)
+            .setPhysicalDisplayId(PhysicalDisplayId::fromPort(0))
+            .setVsyncPeriod(int32_t(vsyncPeriod))
+            .setGroup(group)
+            .setHeight(resolution.height)
+            .setWidth(resolution.width)
+            .build();
+}
+
+class ControllableClock : public TimeKeeper {
+public:
+    nsecs_t now() const { return 1; };
+    void alarmAt(std::function<void()> /* callback */, nsecs_t /* time */) override {}
+    void alarmCancel() override {}
+    void dump(std::string& /* result */) const override {}
+
+    void alarmAtDefaultBehavior(std::function<void()> const& callback, nsecs_t time) {
+        mCallback = callback;
+        mNextCallbackTime = time;
+    }
+
+    nsecs_t fakeTime() const { return mCurrentTime; }
+
+    void advanceToNextCallback() {
+        mCurrentTime = mNextCallbackTime;
+        if (mCallback) {
+            mCallback();
+        }
+    }
+
+    void advanceBy(nsecs_t advancement) {
+        mCurrentTime += advancement;
+        if (mCurrentTime >= (mNextCallbackTime + mLag) && mCallback) {
+            mCallback();
+        }
+    };
+
+    void setLag(nsecs_t lag) { mLag = lag; }
+
+private:
+    std::function<void()> mCallback;
+    nsecs_t mNextCallbackTime = 0;
+    nsecs_t mCurrentTime = 0;
+    nsecs_t mLag = 0;
+};
+
+static VsyncModulator::TimePoint Now() {
+    static VsyncModulator::TimePoint now;
+    return now += VsyncModulator::MIN_EARLY_TRANSACTION_TIME;
+}
+
+class FuzzImplVsyncModulator : public VsyncModulator {
+public:
+    FuzzImplVsyncModulator(const VsyncConfigSet& config, Now now) : VsyncModulator(config, now) {}
+
+    void binderDied(const wp<IBinder>& token) { VsyncModulator::binderDied(token); }
+};
+} // namespace android::scheduler
diff --git a/services/surfaceflinger/layerproto/LayerProtoParser.cpp b/services/surfaceflinger/layerproto/LayerProtoParser.cpp
index 2841f7c..854084e 100644
--- a/services/surfaceflinger/layerproto/LayerProtoParser.cpp
+++ b/services/surfaceflinger/layerproto/LayerProtoParser.cpp
@@ -305,7 +305,7 @@
                   zOrderRelativeOf == nullptr ? "none" : zOrderRelativeOf->name.c_str());
     StringAppendF(&result, "      activeBuffer=%s,", activeBuffer.to_string().c_str());
     StringAppendF(&result, " tr=%s", bufferTransform.to_string().c_str());
-    StringAppendF(&result, " queued-frames=%d, mRefreshPending=%d,", queuedFrames, refreshPending);
+    StringAppendF(&result, " queued-frames=%d", queuedFrames);
     StringAppendF(&result, " metadata={");
     bool first = true;
     for (const auto& entry : metadata.mMap) {
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index d292e08..4fe1e98 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -177,6 +177,11 @@
 public:
     using HotplugEvent = SurfaceFlinger::HotplugEvent;
 
+    TestableSurfaceFlinger()
+          : mFlinger(sp<SurfaceFlinger>::make(mFactory, SurfaceFlinger::SkipInitialization)) {
+        mFlinger->mAnimationTransactionTimeout = ms2ns(10);
+    }
+
     SurfaceFlinger* flinger() { return mFlinger.get(); }
     scheduler::TestableScheduler* scheduler() { return mScheduler; }
 
@@ -466,6 +471,10 @@
         return static_cast<mock::FrameTracer*>(mFlinger->mFrameTracer.get());
     }
 
+    nsecs_t getAnimationTransactionTimeout() const {
+        return mFlinger->mAnimationTransactionTimeout;
+    }
+
     /* ------------------------------------------------------------------------
      * Read-write access to private data to set up preconditions and assert
      * post-conditions.
diff --git a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
index 1ce0309..ed23176 100644
--- a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
@@ -89,10 +89,10 @@
 
     mock::VsyncController* mVsyncController = new mock::VsyncController();
     mock::VSyncTracker* mVSyncTracker = new mock::VSyncTracker();
-    mock::MockFence* mFenceUnsignaled = new mock::MockFence();
-    mock::MockFence* mFenceSignaled = new mock::MockFence();
-    mock::MockFence* mFenceUnsignaled2 = new mock::MockFence();
-    mock::MockFence* mFenceSignaled2 = new mock::MockFence();
+    sp<mock::MockFence> mFenceUnsignaled = sp<mock::MockFence>::make();
+    sp<mock::MockFence> mFenceSignaled = sp<mock::MockFence>::make();
+    sp<mock::MockFence> mFenceUnsignaled2 = sp<mock::MockFence>::make();
+    sp<mock::MockFence> mFenceSignaled2 = sp<mock::MockFence>::make();
 
     struct TransactionInfo {
         Vector<ComposerState> states;
@@ -159,9 +159,9 @@
         // completed.  If this is animation, it should not time out waiting.
         nsecs_t returnedTime = systemTime();
         if (flags & ISurfaceComposer::eSynchronous || syncInputWindows) {
-            EXPECT_GE(returnedTime, applicationTime + s2ns(5));
+            EXPECT_GE(returnedTime, applicationTime + mFlinger.getAnimationTransactionTimeout());
         } else {
-            EXPECT_LE(returnedTime, applicationTime + s2ns(5));
+            EXPECT_LE(returnedTime, applicationTime + mFlinger.getAnimationTransactionTimeout());
         }
         // Each transaction should have been placed on the transaction queue
         auto transactionQueue = mFlinger.getTransactionQueue();
@@ -188,9 +188,11 @@
 
         nsecs_t returnedTime = systemTime();
         if ((flags & ISurfaceComposer::eSynchronous) || syncInputWindows) {
-            EXPECT_GE(systemTime(), applicationSentTime + s2ns(5));
+            EXPECT_GE(systemTime(),
+                      applicationSentTime + mFlinger.getAnimationTransactionTimeout());
         } else {
-            EXPECT_LE(returnedTime, applicationSentTime + s2ns(5));
+            EXPECT_LE(returnedTime,
+                      applicationSentTime + mFlinger.getAnimationTransactionTimeout());
         }
         // This transaction should have been placed on the transaction queue
         auto transactionQueue = mFlinger.getTransactionQueue();
@@ -228,7 +230,7 @@
         // This thread should not have been blocked by the above transaction
         // (5s is the timeout period that applyTransactionState waits for SF to
         // commit the transaction)
-        EXPECT_LE(systemTime(), applicationSentTime + s2ns(5));
+        EXPECT_LE(systemTime(), applicationSentTime + mFlinger.getAnimationTransactionTimeout());
         // transaction that would goes to pending transaciton queue.
         mFlinger.flushTransactionQueues();
 
@@ -246,9 +248,11 @@
         // the transaction should be placed on the pending queue
         if (flags & (ISurfaceComposer::eAnimation | ISurfaceComposer::eSynchronous) ||
             syncInputWindows) {
-            EXPECT_GE(systemTime(), applicationSentTime + s2ns(5));
+            EXPECT_GE(systemTime(),
+                      applicationSentTime + mFlinger.getAnimationTransactionTimeout());
         } else {
-            EXPECT_LE(systemTime(), applicationSentTime + s2ns(5));
+            EXPECT_LE(systemTime(),
+                      applicationSentTime + mFlinger.getAnimationTransactionTimeout());
         }
 
         // transaction that would goes to pending transaciton queue.