Merge "Update TODO bug in setInTouchMode"
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index a951c4f..8ccd940 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -1087,7 +1087,7 @@
     RunCommand("DEVICE-MAPPER", {"gsid", "dump-device-mapper"});
 }
 
-static void AddAnrTraceDir(const bool add_to_zip, const std::string& anr_traces_dir) {
+static void AddAnrTraceDir(const std::string& anr_traces_dir) {
     MYLOGD("AddAnrTraceDir(): dump_traces_file=%s, anr_traces_dir=%s\n", dump_traces_path,
            anr_traces_dir.c_str());
 
@@ -1095,13 +1095,9 @@
     // (created with mkostemp or similar) that contains dumps taken earlier
     // on in the process.
     if (dump_traces_path != nullptr) {
-        if (add_to_zip) {
-            ds.AddZipEntry(ZIP_ROOT_DIR + anr_traces_dir + "/traces-just-now.txt", dump_traces_path);
-        } else {
-            MYLOGD("Dumping current ANR traces (%s) to the main bugreport entry\n",
-                   dump_traces_path);
-            ds.DumpFile("VM TRACES JUST NOW", dump_traces_path);
-        }
+        MYLOGD("Dumping current ANR traces (%s) to the main bugreport entry\n",
+                dump_traces_path);
+        ds.DumpFile("VM TRACES JUST NOW", dump_traces_path);
 
         const int ret = unlink(dump_traces_path);
         if (ret == -1) {
@@ -1112,14 +1108,12 @@
 
     // Add a specific message for the first ANR Dump.
     if (ds.anr_data_.size() > 0) {
+        // The "last" ANR will always be present in the body of the main entry.
         AddDumps(ds.anr_data_.begin(), ds.anr_data_.begin() + 1,
-                 "VM TRACES AT LAST ANR", add_to_zip);
+                 "VM TRACES AT LAST ANR", false /* add_to_zip */);
 
-        // The "last" ANR will always be included as separate entry in the zip file. In addition,
-        // it will be present in the body of the main entry if |add_to_zip| == false.
-        //
         // Historical ANRs are always included as separate entries in the bugreport zip file.
-        AddDumps(ds.anr_data_.begin() + ((add_to_zip) ? 1 : 0), ds.anr_data_.end(),
+        AddDumps(ds.anr_data_.begin(), ds.anr_data_.end(),
                  "HISTORICAL ANR", true /* add_to_zip */);
     } else {
         printf("*** NO ANRs to dump in %s\n\n", ANR_DIR.c_str());
@@ -1127,11 +1121,9 @@
 }
 
 static void AddAnrTraceFiles() {
-    const bool add_to_zip = ds.version_ == VERSION_SPLIT_ANR;
-
     std::string anr_traces_dir = "/data/anr";
 
-    AddAnrTraceDir(add_to_zip, anr_traces_dir);
+    AddAnrTraceDir(anr_traces_dir);
 
     RunCommand("ANR FILES", {"ls", "-lt", ANR_DIR});
 
@@ -2906,10 +2898,9 @@
         version_ = VERSION_CURRENT;
     }
 
-    if (version_ != VERSION_CURRENT && version_ != VERSION_SPLIT_ANR) {
-        MYLOGE("invalid version requested ('%s'); suppported values are: ('%s', '%s', '%s')\n",
-               version_.c_str(), VERSION_DEFAULT.c_str(), VERSION_CURRENT.c_str(),
-               VERSION_SPLIT_ANR.c_str());
+    if (version_ != VERSION_CURRENT) {
+        MYLOGE("invalid version requested ('%s'); supported values are: ('%s', '%s')\n",
+               version_.c_str(), VERSION_DEFAULT.c_str(), VERSION_CURRENT.c_str());
         return RunStatus::INVALID_INPUT;
     }
 
diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h
index d0acb31..4a99cd8 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -157,12 +157,6 @@
 static std::string VERSION_CURRENT = "2.0";
 
 /*
- * Temporary version that adds a anr-traces.txt entry. Once tools support it, the current version
- * will be bumped to 3.0.
- */
-static std::string VERSION_SPLIT_ANR = "3.0-dev-split-anr";
-
-/*
  * "Alias" for the current version.
  */
 static std::string VERSION_DEFAULT = "default";
diff --git a/libs/cputimeinstate/Android.bp b/libs/cputimeinstate/Android.bp
index 4f63194..79cc15f 100644
--- a/libs/cputimeinstate/Android.bp
+++ b/libs/cputimeinstate/Android.bp
@@ -13,12 +13,13 @@
     shared_libs: [
         "libbase",
         "libbpf_bcc",
-        "libbpf_android",
         "libbpf_minimal",
         "liblog",
-        "libnetdutils"
     ],
-    header_libs: ["bpf_prog_headers"],
+    header_libs: [
+        "bpf_prog_headers",
+        "bpf_headers",
+    ],
     cflags: [
         "-Werror",
         "-Wall",
@@ -33,12 +34,13 @@
     shared_libs: [
         "libbase",
         "libbpf_bcc",
-        "libbpf_android",
         "libbpf_minimal",
         "libtimeinstate",
-        "libnetdutils",
     ],
-    header_libs: ["bpf_prog_headers"],
+    header_libs: [
+        "bpf_prog_headers",
+        "bpf_headers",
+    ],
     cflags: [
         "-Werror",
         "-Wall",
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index ec3587b..e17b2c8 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -198,6 +198,7 @@
         "SurfaceComposerClient.cpp",
         "SyncFeatures.cpp",
         "TransactionTracing.cpp",
+        "VsyncEventData.cpp",
         "view/Surface.cpp",
         "WindowInfosListenerReporter.cpp",
         "bufferqueue/1.0/B2HProducerListener.cpp",
diff --git a/libs/gui/DisplayEventDispatcher.cpp b/libs/gui/DisplayEventDispatcher.cpp
index ee80082..26db59b 100644
--- a/libs/gui/DisplayEventDispatcher.cpp
+++ b/libs/gui/DisplayEventDispatcher.cpp
@@ -148,14 +148,13 @@
 
 void DisplayEventDispatcher::populateFrameTimelines(const DisplayEventReceiver::Event& event,
                                                     VsyncEventData* outVsyncEventData) const {
-    for (size_t i = 0; i < DisplayEventReceiver::kFrameTimelinesLength; i++) {
+    for (size_t i = 0; i < VsyncEventData::kFrameTimelinesLength; i++) {
         DisplayEventReceiver::Event::VSync::FrameTimeline receiverTimeline =
                 event.vsync.frameTimelines[i];
-        outVsyncEventData->frameTimelines[i] = {.id = receiverTimeline.vsyncId,
-                                                .deadlineTimestamp =
-                                                        receiverTimeline.deadlineTimestamp,
-                                                .expectedPresentTime =
-                                                        receiverTimeline.expectedVSyncTimestamp};
+        outVsyncEventData->frameTimelines[i] =
+                VsyncEventData::FrameTimeline(receiverTimeline.vsyncId,
+                                              receiverTimeline.deadlineTimestamp,
+                                              receiverTimeline.expectedVSyncTimestamp);
     }
 }
 
diff --git a/libs/gui/VsyncEventData.cpp b/libs/gui/VsyncEventData.cpp
new file mode 100644
index 0000000..aad81d0
--- /dev/null
+++ b/libs/gui/VsyncEventData.cpp
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "gui/VsyncEventData.h"
+#include <gui/DisplayEventReceiver.h>
+#include <private/gui/ParcelUtils.h>
+#include <utils/Log.h>
+#include <utils/Looper.h>
+#include <cstdint>
+
+namespace android::gui {
+
+status_t VsyncEventData::readFromParcel(const Parcel* parcel) {
+    if (parcel == nullptr) {
+        ALOGE("%s: Null parcel", __func__);
+        return BAD_VALUE;
+    }
+
+    SAFE_PARCEL(parcel->readInt64, &id)
+    SAFE_PARCEL(parcel->readInt64, &deadlineTimestamp);
+    SAFE_PARCEL(parcel->readInt64, &frameInterval);
+
+    uint64_t uintPreferredFrameTimelineIndex;
+    SAFE_PARCEL(parcel->readUint64, &uintPreferredFrameTimelineIndex);
+    preferredFrameTimelineIndex = static_cast<size_t>(uintPreferredFrameTimelineIndex);
+
+    std::vector<FrameTimeline> timelines;
+    SAFE_PARCEL(parcel->readParcelableVector, &timelines);
+    std::copy_n(timelines.begin(), timelines.size(), frameTimelines.begin());
+
+    return OK;
+}
+status_t VsyncEventData::writeToParcel(Parcel* parcel) const {
+    SAFE_PARCEL(parcel->writeInt64, id)
+    SAFE_PARCEL(parcel->writeInt64, deadlineTimestamp);
+    SAFE_PARCEL(parcel->writeInt64, frameInterval);
+    SAFE_PARCEL(parcel->writeUint64, preferredFrameTimelineIndex);
+    SAFE_PARCEL(parcel->writeParcelableVector,
+                std::vector(frameTimelines.begin(), frameTimelines.end()));
+
+    return OK;
+}
+status_t VsyncEventData::FrameTimeline::readFromParcel(const Parcel* parcel) {
+    if (parcel == nullptr) {
+        ALOGE("%s: Null parcel", __func__);
+        return BAD_VALUE;
+    }
+
+    SAFE_PARCEL(parcel->readInt64, &id)
+    SAFE_PARCEL(parcel->readInt64, &deadlineTimestamp);
+    SAFE_PARCEL(parcel->readInt64, &expectedPresentTime);
+
+    return OK;
+}
+status_t VsyncEventData::FrameTimeline::writeToParcel(Parcel* parcel) const {
+    SAFE_PARCEL(parcel->writeInt64, id);
+    SAFE_PARCEL(parcel->writeInt64, deadlineTimestamp);
+    SAFE_PARCEL(parcel->writeInt64, expectedPresentTime);
+
+    return OK;
+}
+
+}; // namespace android::gui
diff --git a/libs/gui/WindowInfosListenerReporter.cpp b/libs/gui/WindowInfosListenerReporter.cpp
index c32b9ab..4112f74 100644
--- a/libs/gui/WindowInfosListenerReporter.cpp
+++ b/libs/gui/WindowInfosListenerReporter.cpp
@@ -68,8 +68,7 @@
 binder::Status WindowInfosListenerReporter::onWindowInfosChanged(
         const std::vector<WindowInfo>& windowInfos, const std::vector<DisplayInfo>& displayInfos,
         const sp<IWindowInfosReportedListener>& windowInfosReportedListener) {
-    std::unordered_set<sp<WindowInfosListener>, ISurfaceComposer::SpHash<WindowInfosListener>>
-            windowInfosListeners;
+    std::unordered_set<sp<WindowInfosListener>, SpHash<WindowInfosListener>> windowInfosListeners;
 
     {
         std::scoped_lock lock(mListenersMutex);
@@ -96,4 +95,4 @@
     }
 }
 
-} // namespace android
\ No newline at end of file
+} // namespace android
diff --git a/libs/gui/include/gui/DisplayEventDispatcher.h b/libs/gui/include/gui/DisplayEventDispatcher.h
index 40621dd..71968fa 100644
--- a/libs/gui/include/gui/DisplayEventDispatcher.h
+++ b/libs/gui/include/gui/DisplayEventDispatcher.h
@@ -17,45 +17,10 @@
 #include <gui/DisplayEventReceiver.h>
 #include <utils/Log.h>
 #include <utils/Looper.h>
-#include <array>
 
 namespace android {
 using FrameRateOverride = DisplayEventReceiver::Event::FrameRateOverride;
 
-struct VsyncEventData {
-    // The Vsync Id corresponsing to this vsync event. This will be used to
-    // populate ISurfaceComposer::setFrameTimelineVsync and
-    // SurfaceComposerClient::setFrameTimelineVsync
-    int64_t id = FrameTimelineInfo::INVALID_VSYNC_ID;
-
-    // The deadline in CLOCK_MONOTONIC that the app needs to complete its
-    // frame by (both on the CPU and the GPU)
-    int64_t deadlineTimestamp = std::numeric_limits<int64_t>::max();
-
-    // The current frame interval in ns when this frame was scheduled.
-    int64_t frameInterval = 0;
-
-    struct FrameTimeline {
-        // The Vsync Id corresponsing to this vsync event. This will be used to
-        // populate ISurfaceComposer::setFrameTimelineVsync and
-        // SurfaceComposerClient::setFrameTimelineVsync
-        int64_t id = FrameTimelineInfo::INVALID_VSYNC_ID;
-
-        // The deadline in CLOCK_MONOTONIC that the app needs to complete its
-        // frame by (both on the CPU and the GPU)
-        int64_t deadlineTimestamp = std::numeric_limits<int64_t>::max();
-
-        // The anticipated Vsync present time.
-        int64_t expectedPresentTime = 0;
-    };
-
-    // Sorted possible frame timelines.
-    std::array<FrameTimeline, DisplayEventReceiver::kFrameTimelinesLength> frameTimelines;
-
-    // Index into the frameTimelines that represents the platform's preferred frame timeline.
-    size_t preferredFrameTimelineIndex = std::numeric_limits<size_t>::max();
-};
-
 class DisplayEventDispatcher : public LooperCallback {
 public:
     explicit DisplayEventDispatcher(
diff --git a/libs/gui/include/gui/DisplayEventReceiver.h b/libs/gui/include/gui/DisplayEventReceiver.h
index 456bbfb..db41c32 100644
--- a/libs/gui/include/gui/DisplayEventReceiver.h
+++ b/libs/gui/include/gui/DisplayEventReceiver.h
@@ -26,6 +26,7 @@
 
 #include <binder/IInterface.h>
 #include <gui/ISurfaceComposer.h>
+#include <gui/VsyncEventData.h>
 
 // ----------------------------------------------------------------------------
 
@@ -34,6 +35,7 @@
 // ----------------------------------------------------------------------------
 
 using gui::IDisplayEventConnection;
+using gui::VsyncEventData;
 
 namespace gui {
 class BitTube;
@@ -49,8 +51,6 @@
 // ----------------------------------------------------------------------------
 class DisplayEventReceiver {
 public:
-    // Max amount of frame timelines is arbitrarily set to be reasonable.
-    static constexpr int64_t kFrameTimelinesLength = 7;
 
     enum {
         DISPLAY_EVENT_VSYNC = fourcc('v', 's', 'y', 'n'),
@@ -85,7 +85,7 @@
                 nsecs_t expectedVSyncTimestamp __attribute__((aligned(8)));
                 nsecs_t deadlineTimestamp __attribute__((aligned(8)));
                 int64_t vsyncId;
-            } frameTimelines[kFrameTimelinesLength];
+            } frameTimelines[VsyncEventData::kFrameTimelinesLength];
         };
 
         struct Hotplug {
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index 4b5cee2..90b2a0e 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -30,6 +30,7 @@
 #include <ftl/Flags.h>
 #include <gui/FrameTimelineInfo.h>
 #include <gui/ITransactionCompletedListener.h>
+#include <gui/SpHash.h>
 #include <math/vec4.h>
 #include <stdint.h>
 #include <sys/types.h>
@@ -70,6 +71,7 @@
 using gui::IDisplayEventConnection;
 using gui::IRegionSamplingListener;
 using gui::IScreenCaptureListener;
+using gui::SpHash;
 
 namespace ui {
 
@@ -118,11 +120,6 @@
 
     using EventRegistrationFlags = Flags<EventRegistration>;
 
-    template <typename T>
-    struct SpHash {
-        size_t operator()(const sp<T>& k) const { return std::hash<T*>()(k.get()); }
-    };
-
     /*
      * Create a connection with SurfaceFlinger.
      */
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index cd6afd2..f720619 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -31,6 +31,7 @@
 
 #include <gui/ISurfaceComposer.h>
 #include <gui/LayerMetadata.h>
+#include <gui/SpHash.h>
 #include <gui/SurfaceControl.h>
 #include <gui/WindowInfo.h>
 #include <math/vec3.h>
@@ -412,7 +413,7 @@
 
 struct LayerCaptureArgs : CaptureArgs {
     sp<IBinder> layerHandle;
-    std::unordered_set<sp<IBinder>, ISurfaceComposer::SpHash<IBinder>> excludeHandles;
+    std::unordered_set<sp<IBinder>, SpHash<IBinder>> excludeHandles;
     bool childrenOnly{false};
 
     status_t write(Parcel& output) const override;
diff --git a/libs/gui/include/gui/SpHash.h b/libs/gui/include/gui/SpHash.h
new file mode 100644
index 0000000..5162f01
--- /dev/null
+++ b/libs/gui/include/gui/SpHash.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <functional>
+
+namespace android::gui {
+
+template <typename T>
+struct SpHash {
+    size_t operator()(const sp<T>& k) const { return std::hash<T*>()(k.get()); }
+};
+
+}; // namespace android::gui
diff --git a/libs/gui/include/gui/VsyncEventData.h b/libs/gui/include/gui/VsyncEventData.h
new file mode 100644
index 0000000..abac61c
--- /dev/null
+++ b/libs/gui/include/gui/VsyncEventData.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <gui/FrameTimelineInfo.h>
+
+#include <array>
+
+namespace android::gui {
+struct VsyncEventData : public Parcelable {
+    // Max amount of frame timelines is arbitrarily set to be reasonable.
+    static constexpr int64_t kFrameTimelinesLength = 7;
+
+    // The Vsync Id corresponsing to this vsync event. This will be used to
+    // populate ISurfaceComposer::setFrameTimelineVsync and
+    // SurfaceComposerClient::setFrameTimelineVsync
+    // TODO(b/198191703): Remove when JNI DisplayEventReceiver uses frameTimelines array.
+    int64_t id = FrameTimelineInfo::INVALID_VSYNC_ID;
+
+    // The deadline in CLOCK_MONOTONIC that the app needs to complete its
+    // frame by (both on the CPU and the GPU)
+    // TODO(b/198191703): Remove when JNI DisplayEventReceiver uses frameTimelines array.
+    int64_t deadlineTimestamp = std::numeric_limits<int64_t>::max();
+
+    // The current frame interval in ns when this frame was scheduled.
+    int64_t frameInterval = 0;
+
+    struct FrameTimeline : public Parcelable {
+        FrameTimeline() = default;
+        FrameTimeline(int64_t id, int64_t deadlineTimestamp, int64_t expectedPresentTime)
+              : id(id),
+                deadlineTimestamp(deadlineTimestamp),
+                expectedPresentTime(expectedPresentTime) {}
+
+        // The Vsync Id corresponsing to this vsync event. This will be used to
+        // populate ISurfaceComposer::setFrameTimelineVsync and
+        // SurfaceComposerClient::setFrameTimelineVsync
+        int64_t id = FrameTimelineInfo::INVALID_VSYNC_ID;
+
+        // The deadline in CLOCK_MONOTONIC that the app needs to complete its
+        // frame by (both on the CPU and the GPU)
+        int64_t deadlineTimestamp = std::numeric_limits<int64_t>::max();
+
+        // The anticipated Vsync present time.
+        int64_t expectedPresentTime = 0;
+
+        status_t readFromParcel(const Parcel*) override;
+        status_t writeToParcel(Parcel*) const override;
+    };
+
+    // Sorted possible frame timelines.
+    std::array<FrameTimeline, kFrameTimelinesLength> frameTimelines;
+
+    // Index into the frameTimelines that represents the platform's preferred frame timeline.
+    size_t preferredFrameTimelineIndex = std::numeric_limits<size_t>::max();
+
+    status_t readFromParcel(const Parcel*) override;
+    status_t writeToParcel(Parcel*) const override;
+};
+} // namespace android::gui
diff --git a/libs/gui/include/gui/WindowInfosListenerReporter.h b/libs/gui/include/gui/WindowInfosListenerReporter.h
index 157a804..96bd0b1 100644
--- a/libs/gui/include/gui/WindowInfosListenerReporter.h
+++ b/libs/gui/include/gui/WindowInfosListenerReporter.h
@@ -20,6 +20,7 @@
 #include <android/gui/IWindowInfosReportedListener.h>
 #include <binder/IBinder.h>
 #include <gui/ISurfaceComposer.h>
+#include <gui/SpHash.h>
 #include <gui/WindowInfosListener.h>
 #include <unordered_set>
 
@@ -41,8 +42,7 @@
 
 private:
     std::mutex mListenersMutex;
-    std::unordered_set<sp<gui::WindowInfosListener>,
-                       ISurfaceComposer::SpHash<gui::WindowInfosListener>>
+    std::unordered_set<sp<gui::WindowInfosListener>, SpHash<gui::WindowInfosListener>>
             mWindowInfosListeners GUARDED_BY(mListenersMutex);
 };
-} // namespace android
\ No newline at end of file
+} // namespace android
diff --git a/libs/gui/tests/Android.bp b/libs/gui/tests/Android.bp
index 6dd1073..e58543a 100644
--- a/libs/gui/tests/Android.bp
+++ b/libs/gui/tests/Android.bp
@@ -44,6 +44,7 @@
         "SurfaceTextureMultiContextGL_test.cpp",
         "Surface_test.cpp",
         "TextureRenderer.cpp",
+        "VsyncEventData_test.cpp",
         "WindowInfo_test.cpp",
     ],
 
diff --git a/libs/gui/tests/VsyncEventData_test.cpp b/libs/gui/tests/VsyncEventData_test.cpp
new file mode 100644
index 0000000..a670d42
--- /dev/null
+++ b/libs/gui/tests/VsyncEventData_test.cpp
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include <binder/Parcel.h>
+
+#include <gui/VsyncEventData.h>
+
+namespace android {
+
+using gui::VsyncEventData;
+using FrameTimeline = gui::VsyncEventData::FrameTimeline;
+
+namespace test {
+
+TEST(VsyncEventData, Parcelling) {
+    VsyncEventData data;
+    data.id = 123;
+    data.deadlineTimestamp = 456;
+    data.frameInterval = 789;
+    data.preferredFrameTimelineIndex = 1;
+    FrameTimeline timeline0 = FrameTimeline(1, 2, 3);
+    FrameTimeline timeline1 = FrameTimeline(4, 5, 6);
+    data.frameTimelines[0] = timeline0;
+    data.frameTimelines[1] = timeline1;
+
+    Parcel p;
+    data.writeToParcel(&p);
+    p.setDataPosition(0);
+
+    VsyncEventData data2;
+    data2.readFromParcel(&p);
+    ASSERT_EQ(data.id, data2.id);
+    ASSERT_EQ(data.deadlineTimestamp, data2.deadlineTimestamp);
+    ASSERT_EQ(data.frameInterval, data2.frameInterval);
+    ASSERT_EQ(data.preferredFrameTimelineIndex, data2.preferredFrameTimelineIndex);
+    for (int i = 0; i < data.frameTimelines.size(); i++) {
+        ASSERT_EQ(data.frameTimelines[i].id, data2.frameTimelines[i].id);
+        ASSERT_EQ(data.frameTimelines[i].deadlineTimestamp,
+                  data2.frameTimelines[i].deadlineTimestamp);
+        ASSERT_EQ(data.frameTimelines[i].expectedPresentTime,
+                  data2.frameTimelines[i].expectedPresentTime);
+    }
+}
+
+TEST(FrameTimeline, Parcelling) {
+    FrameTimeline timeline = FrameTimeline(1, 2, 3);
+
+    Parcel p;
+    timeline.writeToParcel(&p);
+    p.setDataPosition(0);
+
+    FrameTimeline timeline2;
+    timeline2.readFromParcel(&p);
+    ASSERT_EQ(timeline.id, timeline2.id);
+    ASSERT_EQ(timeline.deadlineTimestamp, timeline2.deadlineTimestamp);
+    ASSERT_EQ(timeline.expectedPresentTime, timeline2.expectedPresentTime);
+}
+
+} // namespace test
+} // namespace android
diff --git a/libs/nativedisplay/AChoreographer.cpp b/libs/nativedisplay/AChoreographer.cpp
index d90ee57..b182a4a 100644
--- a/libs/nativedisplay/AChoreographer.cpp
+++ b/libs/nativedisplay/AChoreographer.cpp
@@ -73,6 +73,7 @@
 } // namespace
 
 namespace android {
+using gui::VsyncEventData;
 
 struct FrameCallback {
     AChoreographer_frameCallback callback;
@@ -102,8 +103,7 @@
 struct ChoreographerFrameCallbackDataImpl {
     int64_t frameTimeNanos{0};
 
-    std::array<VsyncEventData::FrameTimeline, DisplayEventReceiver::kFrameTimelinesLength>
-            frameTimelines;
+    std::array<VsyncEventData::FrameTimeline, VsyncEventData::kFrameTimelinesLength> frameTimelines;
 
     size_t preferredFrameTimelineIndex;
 
diff --git a/libs/renderengine/skia/filters/BlurFilter.cpp b/libs/renderengine/skia/filters/BlurFilter.cpp
index 6746e47..63cc02b 100644
--- a/libs/renderengine/skia/filters/BlurFilter.cpp
+++ b/libs/renderengine/skia/filters/BlurFilter.cpp
@@ -38,7 +38,7 @@
         uniform float mixFactor;
 
         half4 main(float2 xy) {
-            return half4(mix(originalInput.eval(xy), blurredInput.eval(xy), mixFactor));
+            return half4(mix(originalInput.eval(xy), blurredInput.eval(xy), mixFactor)).rgb1;
         }
     )");
 
@@ -103,7 +103,7 @@
                                   inputMatrix);
         blurBuilder.uniform("mixFactor") = blurRadius / mMaxCrossFadeRadius;
 
-        paint.setShader(blurBuilder.makeShader(nullptr, true));
+        paint.setShader(blurBuilder.makeShader());
     } else {
         paint.setShader(blurShader);
     }
diff --git a/libs/renderengine/skia/filters/LinearEffect.cpp b/libs/renderengine/skia/filters/LinearEffect.cpp
index 6077c2e..a46329d 100644
--- a/libs/renderengine/skia/filters/LinearEffect.cpp
+++ b/libs/renderengine/skia/filters/LinearEffect.cpp
@@ -58,7 +58,7 @@
         effectBuilder.uniform(uniform.name.c_str()).set(uniform.value.data(), uniform.value.size());
     }
 
-    return effectBuilder.makeShader(nullptr, false);
+    return effectBuilder.makeShader();
 }
 
 } // namespace skia
diff --git a/libs/renderengine/skia/filters/StretchShaderFactory.cpp b/libs/renderengine/skia/filters/StretchShaderFactory.cpp
index c262e35..beec3ec 100644
--- a/libs/renderengine/skia/filters/StretchShaderFactory.cpp
+++ b/libs/renderengine/skia/filters/StretchShaderFactory.cpp
@@ -238,7 +238,7 @@
     mBuilder->uniform("viewportWidth").set(&viewportWidth, 1);
     mBuilder->uniform("viewportHeight").set(&viewportHeight, 1);
 
-    return mBuilder->makeShader(nullptr, false);
+    return mBuilder->makeShader();
 }
 
 } // namespace skia
diff --git a/services/gpuservice/bpfprogs/Android.bp b/services/gpuservice/bpfprogs/Android.bp
index 9842ed7..076affd 100644
--- a/services/gpuservice/bpfprogs/Android.bp
+++ b/services/gpuservice/bpfprogs/Android.bp
@@ -24,6 +24,7 @@
 bpf {
     name: "gpu_mem.o",
     srcs: ["gpu_mem.c"],
+    btf: true,
     cflags: [
         "-Wall",
         "-Werror",
diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp
index ff30348..e29e6ab 100644
--- a/services/surfaceflinger/RegionSamplingThread.cpp
+++ b/services/surfaceflinger/RegionSamplingThread.cpp
@@ -30,6 +30,7 @@
 #include <compositionengine/impl/OutputCompositionState.h>
 #include <cutils/properties.h>
 #include <ftl/future.h>
+#include <gui/SpHash.h>
 #include <gui/SyncScreenCaptureListener.h>
 #include <renderengine/impl/ExternalTexture.h>
 #include <ui/DisplayStatInfo.h>
@@ -46,10 +47,7 @@
 namespace android {
 using namespace std::chrono_literals;
 
-template <typename T>
-struct SpHash {
-    size_t operator()(const sp<T>& p) const { return std::hash<T*>()(p.get()); }
-};
+using gui::SpHash;
 
 constexpr auto lumaSamplingStepTag = "LumaSamplingStep";
 enum class samplingStep {
diff --git a/services/surfaceflinger/Scheduler/DispSyncSource.cpp b/services/surfaceflinger/Scheduler/DispSyncSource.cpp
index 50b38c9..c593340 100644
--- a/services/surfaceflinger/Scheduler/DispSyncSource.cpp
+++ b/services/surfaceflinger/Scheduler/DispSyncSource.cpp
@@ -180,7 +180,7 @@
     }
 
     if (callback != nullptr) {
-        callback->onVSyncEvent(targetWakeupTime, vsyncTime, readyTime);
+        callback->onVSyncEvent(targetWakeupTime, {vsyncTime, readyTime});
     }
 }
 
diff --git a/services/surfaceflinger/Scheduler/EventThread.cpp b/services/surfaceflinger/Scheduler/EventThread.cpp
index 627c49a..adc1009 100644
--- a/services/surfaceflinger/Scheduler/EventThread.cpp
+++ b/services/surfaceflinger/Scheduler/EventThread.cpp
@@ -108,13 +108,12 @@
 
 DisplayEventReceiver::Event makeVSync(PhysicalDisplayId displayId, nsecs_t timestamp,
                                       uint32_t count, nsecs_t expectedVSyncTimestamp,
-                                      nsecs_t deadlineTimestamp, int64_t vsyncId) {
+                                      nsecs_t deadlineTimestamp) {
     DisplayEventReceiver::Event event;
     event.header = {DisplayEventReceiver::DISPLAY_EVENT_VSYNC, displayId, timestamp};
     event.vsync.count = count;
     event.vsync.expectedVSyncTimestamp = expectedVSyncTimestamp;
     event.vsync.deadlineTimestamp = deadlineTimestamp;
-    event.vsync.vsyncId = vsyncId;
     return event;
 }
 
@@ -351,14 +350,13 @@
     mCondition.notify_all();
 }
 
-void EventThread::onVSyncEvent(nsecs_t timestamp, nsecs_t expectedVSyncTimestamp,
-                               nsecs_t deadlineTimestamp) {
+void EventThread::onVSyncEvent(nsecs_t timestamp, VSyncSource::VSyncData vsyncData) {
     std::lock_guard<std::mutex> lock(mMutex);
 
     LOG_FATAL_IF(!mVSyncState);
-    const int64_t vsyncId = generateToken(timestamp, deadlineTimestamp, expectedVSyncTimestamp);
     mPendingEvents.push_back(makeVSync(mVSyncState->displayId, timestamp, ++mVSyncState->count,
-                                       expectedVSyncTimestamp, deadlineTimestamp, vsyncId));
+                                       vsyncData.expectedVSyncTimestamp,
+                                       vsyncData.deadlineTimestamp));
     mCondition.notify_all();
 }
 
@@ -493,16 +491,9 @@
                 const auto now = systemTime(SYSTEM_TIME_MONOTONIC);
                 const auto deadlineTimestamp = now + timeout.count();
                 const auto expectedVSyncTime = deadlineTimestamp + timeout.count();
-                const int64_t vsyncId = [&] {
-                    if (mTokenManager != nullptr) {
-                        return mTokenManager->generateTokenForPredictions(
-                                {now, deadlineTimestamp, expectedVSyncTime});
-                    }
-                    return FrameTimelineInfo::INVALID_VSYNC_ID;
-                }();
                 mPendingEvents.push_back(makeVSync(mVSyncState->displayId, now,
                                                    ++mVSyncState->count, expectedVSyncTime,
-                                                   deadlineTimestamp, vsyncId));
+                                                   deadlineTimestamp));
             }
         }
     }
@@ -572,25 +563,20 @@
 
 void EventThread::generateFrameTimeline(DisplayEventReceiver::Event& event) const {
     // Add 1 to ensure the preferredFrameTimelineIndex entry (when multiplier == 0) is included.
-    for (int multiplier = -DisplayEventReceiver::kFrameTimelinesLength + 1, currentIndex = 0;
-         currentIndex < DisplayEventReceiver::kFrameTimelinesLength; multiplier++) {
+    for (int multiplier = -VsyncEventData::kFrameTimelinesLength + 1, currentIndex = 0;
+         currentIndex < VsyncEventData::kFrameTimelinesLength; multiplier++) {
         nsecs_t deadline = event.vsync.deadlineTimestamp + multiplier * event.vsync.frameInterval;
         // Valid possible frame timelines must have future values.
         if (deadline > event.header.timestamp) {
             if (multiplier == 0) {
                 event.vsync.preferredFrameTimelineIndex = currentIndex;
-                event.vsync.frameTimelines[currentIndex] =
-                        {.vsyncId = event.vsync.vsyncId,
-                         .deadlineTimestamp = event.vsync.deadlineTimestamp,
-                         .expectedVSyncTimestamp = event.vsync.expectedVSyncTimestamp};
-            } else {
-                nsecs_t expectedVSync =
-                        event.vsync.expectedVSyncTimestamp + multiplier * event.vsync.frameInterval;
-                event.vsync.frameTimelines[currentIndex] =
-                        {.vsyncId = generateToken(event.header.timestamp, deadline, expectedVSync),
-                         .deadlineTimestamp = deadline,
-                         .expectedVSyncTimestamp = expectedVSync};
             }
+            nsecs_t expectedVSync =
+                    event.vsync.expectedVSyncTimestamp + multiplier * event.vsync.frameInterval;
+            event.vsync.frameTimelines[currentIndex] =
+                    {.vsyncId = generateToken(event.header.timestamp, deadline, expectedVSync),
+                     .deadlineTimestamp = deadline,
+                     .expectedVSyncTimestamp = expectedVSync};
             currentIndex++;
         }
     }
diff --git a/services/surfaceflinger/Scheduler/EventThread.h b/services/surfaceflinger/Scheduler/EventThread.h
index fa9af09..c3b9129 100644
--- a/services/surfaceflinger/Scheduler/EventThread.h
+++ b/services/surfaceflinger/Scheduler/EventThread.h
@@ -62,11 +62,16 @@
 
 class VSyncSource {
 public:
+    class VSyncData {
+    public:
+        nsecs_t expectedVSyncTimestamp;
+        nsecs_t deadlineTimestamp;
+    };
+
     class Callback {
     public:
         virtual ~Callback() {}
-        virtual void onVSyncEvent(nsecs_t when, nsecs_t expectedVSyncTimestamp,
-                                  nsecs_t deadlineTimestamp) = 0;
+        virtual void onVSyncEvent(nsecs_t when, VSyncData vsyncData) = 0;
     };
 
     virtual ~VSyncSource() {}
@@ -201,8 +206,7 @@
             REQUIRES(mMutex);
 
     // Implements VSyncSource::Callback
-    void onVSyncEvent(nsecs_t timestamp, nsecs_t expectedVSyncTimestamp,
-                      nsecs_t deadlineTimestamp) override;
+    void onVSyncEvent(nsecs_t timestamp, VSyncSource::VSyncData vsyncData) override;
 
     int64_t generateToken(nsecs_t timestamp, nsecs_t deadlineTimestamp,
                           nsecs_t expectedVSyncTimestamp) const;
diff --git a/services/surfaceflinger/Scheduler/InjectVSyncSource.h b/services/surfaceflinger/Scheduler/InjectVSyncSource.h
index 016b076..7b93f1e 100644
--- a/services/surfaceflinger/Scheduler/InjectVSyncSource.h
+++ b/services/surfaceflinger/Scheduler/InjectVSyncSource.h
@@ -39,7 +39,7 @@
                            nsecs_t deadlineTimestamp) {
         std::lock_guard<std::mutex> lock(mCallbackMutex);
         if (mCallback) {
-            mCallback->onVSyncEvent(when, expectedVSyncTimestamp, deadlineTimestamp);
+            mCallback->onVSyncEvent(when, {expectedVSyncTimestamp, deadlineTimestamp});
         }
     }
 
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index b3c3a41..5ccb5eb 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -3645,7 +3645,7 @@
     // states) around outside the scope of the lock
     std::vector<TransactionState> transactions;
     // Layer handles that have transactions with buffers that are ready to be applied.
-    std::unordered_set<sp<IBinder>, ISurfaceComposer::SpHash<IBinder>> bufferLayersReadyToPresent;
+    std::unordered_set<sp<IBinder>, SpHash<IBinder>> bufferLayersReadyToPresent;
     {
         Mutex::Autolock _l(mStateLock);
         {
@@ -3734,7 +3734,7 @@
                                        int64_t vsyncId) {
     bool needsTraversal = false;
     // Now apply all transactions.
-    for (const auto& transaction : transactions) {
+    for (auto& transaction : transactions) {
         needsTraversal |=
                 applyTransactionState(transaction.frameTimelineInfo, transaction.states,
                                       transaction.displays, transaction.flags,
@@ -3842,8 +3842,7 @@
 bool SurfaceFlinger::transactionIsReadyToBeApplied(
         const FrameTimelineInfo& info, bool isAutoTimestamp, int64_t desiredPresentTime,
         uid_t originUid, const Vector<ComposerState>& states,
-        const std::unordered_set<sp<IBinder>, ISurfaceComposer::SpHash<IBinder>>&
-                bufferLayersReadyToPresent,
+        const std::unordered_set<sp<IBinder>, SpHash<IBinder>>& bufferLayersReadyToPresent,
         bool allowLatchUnsignaled) const {
     ATRACE_FORMAT("transactionIsReadyToBeApplied vsyncId: %" PRId64, info.vsyncId);
     const nsecs_t expectedPresentTime = mExpectedPresentTime.load();
@@ -4028,7 +4027,7 @@
 }
 
 bool SurfaceFlinger::applyTransactionState(const FrameTimelineInfo& frameTimelineInfo,
-                                           const Vector<ComposerState>& states,
+                                           Vector<ComposerState>& states,
                                            const Vector<DisplayState>& displays, uint32_t flags,
                                            const InputWindowCommands& inputWindowCommands,
                                            const int64_t desiredPresentTime, bool isAutoTimestamp,
@@ -4050,9 +4049,9 @@
     }
 
     uint32_t clientStateFlags = 0;
-    for (const ComposerState& state : states) {
-        ComposerState stateCopy = state;
-        clientStateFlags |= setClientStateLocked(frameTimelineInfo, stateCopy, desiredPresentTime,
+    for (int i = 0; i < states.size(); i++) {
+        ComposerState& state = states.editItemAt(i);
+        clientStateFlags |= setClientStateLocked(frameTimelineInfo, state, desiredPresentTime,
                                                  isAutoTimestamp, postTime, permissions);
         if ((flags & eAnimation) && state.state.surface) {
             if (const auto layer = fromHandle(state.state.surface).promote()) {
@@ -5508,7 +5507,13 @@
             }
             return PERMISSION_DENIED;
         }
-        case SET_OVERRIDE_FRAME_RATE:
+        case SET_OVERRIDE_FRAME_RATE: {
+            const int uid = IPCThreadState::self()->getCallingUid();
+            if (uid == AID_ROOT || uid == AID_SYSTEM) {
+                return OK;
+            }
+            return PERMISSION_DENIED;
+        }
         case ON_PULL_ATOM: {
             const int uid = IPCThreadState::self()->getCallingUid();
             if (uid == AID_SYSTEM) {
@@ -6291,7 +6296,7 @@
     ui::Size reqSize;
     sp<Layer> parent;
     Rect crop(args.sourceCrop);
-    std::unordered_set<sp<Layer>, ISurfaceComposer::SpHash<Layer>> excludeLayers;
+    std::unordered_set<sp<Layer>, SpHash<Layer>> excludeLayers;
     ui::Dataspace dataspace;
 
     // Call this before holding mStateLock to avoid any deadlocking.
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 77193a6..b95cd91 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -714,7 +714,7 @@
     /*
      * Transactions
      */
-    bool applyTransactionState(const FrameTimelineInfo& info, const Vector<ComposerState>& state,
+    bool applyTransactionState(const FrameTimelineInfo& info, Vector<ComposerState>& state,
                                const Vector<DisplayState>& displays, uint32_t flags,
                                const InputWindowCommands& inputWindowCommands,
                                const int64_t desiredPresentTime, bool isAutoTimestamp,
@@ -752,8 +752,7 @@
     bool transactionIsReadyToBeApplied(
             const FrameTimelineInfo& info, bool isAutoTimestamp, int64_t desiredPresentTime,
             uid_t originUid, const Vector<ComposerState>& states,
-            const std::unordered_set<sp<IBinder>, ISurfaceComposer::SpHash<IBinder>>&
-                    bufferLayersReadyToPresent,
+            const std::unordered_set<sp<IBinder>, SpHash<IBinder>>& bufferLayersReadyToPresent,
             bool allowLatchUnsignaled) const REQUIRES(mStateLock);
     static LatchUnsignaledConfig getLatchUnsignaledConfig();
     bool latchUnsignaledIsAllowed(std::vector<TransactionState>& transactions) REQUIRES(mStateLock);
@@ -1155,7 +1154,7 @@
 
     // Tracks layers that have pending frames which are candidates for being
     // latched.
-    std::unordered_set<sp<Layer>, ISurfaceComposer::SpHash<Layer>> mLayersWithQueuedFrames;
+    std::unordered_set<sp<Layer>, SpHash<Layer>> mLayersWithQueuedFrames;
     // Tracks layers that need to update a display's dirty region.
     std::vector<sp<Layer>> mLayersPendingRefresh;
     std::array<FenceWithFenceTime, 2> mPreviousPresentFences;
diff --git a/services/surfaceflinger/WindowInfosListenerInvoker.cpp b/services/surfaceflinger/WindowInfosListenerInvoker.cpp
index 72434e9..23cd993 100644
--- a/services/surfaceflinger/WindowInfosListenerInvoker.cpp
+++ b/services/surfaceflinger/WindowInfosListenerInvoker.cpp
@@ -67,8 +67,7 @@
 void WindowInfosListenerInvoker::windowInfosChanged(const std::vector<WindowInfo>& windowInfos,
                                                     const std::vector<DisplayInfo>& displayInfos,
                                                     bool shouldSync) {
-    std::unordered_set<sp<IWindowInfosListener>, ISurfaceComposer::SpHash<IWindowInfosListener>>
-            windowInfosListeners;
+    std::unordered_set<sp<IWindowInfosListener>, SpHash<IWindowInfosListener>> windowInfosListeners;
 
     {
         std::scoped_lock lock(mListenersMutex);
diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.cpp b/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.cpp
index 51a5081..06bbfd2 100644
--- a/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.cpp
+++ b/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.cpp
@@ -63,8 +63,7 @@
     FuzzedDataProvider mFdp;
 
 protected:
-    void onVSyncEvent(nsecs_t /* when */, nsecs_t /* expectedVSyncTimestamp */,
-                      nsecs_t /* deadlineTimestamp */) {}
+    void onVSyncEvent(nsecs_t /* when */, VSyncSource::VSyncData) {}
 };
 
 PhysicalDisplayId SchedulerFuzzer::getPhysicalDisplayId() {
diff --git a/services/surfaceflinger/tests/Android.bp b/services/surfaceflinger/tests/Android.bp
index 7b86229..c5c0c3f 100644
--- a/services/surfaceflinger/tests/Android.bp
+++ b/services/surfaceflinger/tests/Android.bp
@@ -47,6 +47,7 @@
         "ReleaseBufferCallback_test.cpp",
         "ScreenCapture_test.cpp",
         "SetFrameRate_test.cpp",
+        "SetFrameRateOverride_test.cpp",
         "SetGeometry_test.cpp",
         "Stress_test.cpp",
         "SurfaceInterceptor_test.cpp",
diff --git a/services/surfaceflinger/tests/SetFrameRateOverride_test.cpp b/services/surfaceflinger/tests/SetFrameRateOverride_test.cpp
new file mode 100644
index 0000000..4efec77
--- /dev/null
+++ b/services/surfaceflinger/tests/SetFrameRateOverride_test.cpp
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+#include <gui/DisplayEventReceiver.h>
+#include <gui/ISurfaceComposer.h>
+#include <gui/SurfaceComposerClient.h>
+#include <sys/epoll.h>
+#include <algorithm>
+
+namespace android {
+namespace {
+using FrameRateOverride = DisplayEventReceiver::Event::FrameRateOverride;
+
+class SetFrameRateOverrideTest : public ::testing::Test {
+protected:
+    void SetUp() override {
+        const ISurfaceComposer::VsyncSource vsyncSource = ISurfaceComposer::eVsyncSourceApp;
+        const ISurfaceComposer::EventRegistrationFlags eventRegistration = {
+                ISurfaceComposer::EventRegistration::frameRateOverride};
+
+        mDisplayEventReceiver =
+                std::make_unique<DisplayEventReceiver>(vsyncSource, eventRegistration);
+        EXPECT_EQ(NO_ERROR, mDisplayEventReceiver->initCheck());
+
+        mEpollFd = epoll_create1(EPOLL_CLOEXEC);
+        EXPECT_GT(mEpollFd, 1);
+
+        epoll_event event;
+        event.events = EPOLLIN;
+        EXPECT_EQ(0, epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mDisplayEventReceiver->getFd(), &event));
+    }
+
+    void TearDown() override { close(mEpollFd); }
+
+    void setFrameRateAndListenEvents(uid_t uid, float frameRate) {
+        status_t ret = SurfaceComposerClient::setOverrideFrameRate(uid, frameRate);
+        ASSERT_EQ(NO_ERROR, ret);
+
+        DisplayEventReceiver::Event event;
+        bool isOverrideFlushReceived = false;
+        mFrameRateOverrides.clear();
+
+        epoll_event epollEvent;
+        while (epoll_wait(mEpollFd, &epollEvent, 1, 1000) > 0) {
+            while (mDisplayEventReceiver->getEvents(&event, 1) > 0) {
+                if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE) {
+                    mFrameRateOverrides.emplace_back(event.frameRateOverride);
+                }
+                if (event.header.type ==
+                    DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE_FLUSH) {
+                    isOverrideFlushReceived = true;
+                }
+            }
+
+            if (isOverrideFlushReceived) break;
+        }
+    }
+
+    std::unique_ptr<DisplayEventReceiver> mDisplayEventReceiver;
+    std::vector<FrameRateOverride> mFrameRateOverrides;
+
+    int mEpollFd;
+};
+
+TEST_F(SetFrameRateOverrideTest, SetFrameRateOverrideCall) {
+    uid_t uid = getuid();
+    float frameRate = 30.0f;
+    setFrameRateAndListenEvents(uid, frameRate);
+    // check if the frame rate override we set exists
+    ASSERT_TRUE(std::find_if(mFrameRateOverrides.begin(), mFrameRateOverrides.end(),
+                             [uid = uid, frameRate = frameRate](auto i) {
+                                 return uid == i.uid && frameRate == i.frameRateHz;
+                             }) != mFrameRateOverrides.end());
+
+    // test removing frame rate override
+    frameRate = 0.0f;
+    setFrameRateAndListenEvents(uid, frameRate);
+    ASSERT_TRUE(std::find_if(mFrameRateOverrides.begin(), mFrameRateOverrides.end(),
+                             [uid = uid, frameRate = frameRate](auto i) {
+                                 return uid == i.uid && frameRate == i.frameRateHz;
+                             }) == mFrameRateOverrides.end());
+}
+} // namespace
+} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/DispSyncSourceTest.cpp b/services/surfaceflinger/tests/unittests/DispSyncSourceTest.cpp
index f613e43..5a0ea35 100644
--- a/services/surfaceflinger/tests/unittests/DispSyncSourceTest.cpp
+++ b/services/surfaceflinger/tests/unittests/DispSyncSourceTest.cpp
@@ -128,13 +128,12 @@
     void createDispSync();
     void createDispSyncSource();
 
-    void onVSyncEvent(nsecs_t when, nsecs_t expectedVSyncTimestamp,
-                      nsecs_t deadlineTimestamp) override;
+    void onVSyncEvent(nsecs_t when, VSyncSource::VSyncData) override;
 
     std::unique_ptr<MockVSyncDispatch> mVSyncDispatch;
     std::unique_ptr<scheduler::DispSyncSource> mDispSyncSource;
 
-    AsyncCallRecorder<void (*)(nsecs_t, nsecs_t, nsecs_t)> mVSyncEventCallRecorder;
+    AsyncCallRecorder<void (*)(nsecs_t, VSyncSource::VSyncData)> mVSyncEventCallRecorder;
 
     static constexpr std::chrono::nanoseconds mWorkDuration = 20ms;
     static constexpr std::chrono::nanoseconds mReadyDuration = 10ms;
@@ -155,11 +154,10 @@
     ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name());
 }
 
-void DispSyncSourceTest::onVSyncEvent(nsecs_t when, nsecs_t expectedVSyncTimestamp,
-                                      nsecs_t deadlineTimestamp) {
+void DispSyncSourceTest::onVSyncEvent(nsecs_t when, VSyncSource::VSyncData vsyncData) {
     ALOGD("onVSyncEvent: %" PRId64, when);
 
-    mVSyncEventCallRecorder.recordCall(when, expectedVSyncTimestamp, deadlineTimestamp);
+    mVSyncEventCallRecorder.recordCall(when, vsyncData);
 }
 
 void DispSyncSourceTest::createDispSync() {
@@ -233,8 +231,10 @@
         mVSyncDispatch->triggerCallbacks();
         const auto callbackData = mVSyncEventCallRecorder.waitForCall();
         ASSERT_TRUE(callbackData.has_value());
-        const auto [when, expectedVSyncTimestamp, deadlineTimestamp] = callbackData.value();
-        EXPECT_EQ(when, expectedVSyncTimestamp - mWorkDuration.count() - mReadyDuration.count());
+        const auto [when, vsyncData] = callbackData.value();
+        EXPECT_EQ(when,
+                  vsyncData.expectedVSyncTimestamp - mWorkDuration.count() -
+                          mReadyDuration.count());
     }
 }
 
@@ -265,8 +265,10 @@
         mVSyncDispatch->triggerCallbacks();
         const auto callbackData = mVSyncEventCallRecorder.waitForCall();
         ASSERT_TRUE(callbackData.has_value());
-        const auto [when, expectedVSyncTimestamp, deadlineTimestamp] = callbackData.value();
-        EXPECT_EQ(when, expectedVSyncTimestamp - mWorkDuration.count() - mReadyDuration.count());
+        const auto [when, vsyncData] = callbackData.value();
+        EXPECT_EQ(when,
+                  vsyncData.expectedVSyncTimestamp - mWorkDuration.count() -
+                          mReadyDuration.count());
     }
 
     const auto newDuration = mWorkDuration / 2;
@@ -286,8 +288,8 @@
         mVSyncDispatch->triggerCallbacks();
         const auto callbackData = mVSyncEventCallRecorder.waitForCall();
         ASSERT_TRUE(callbackData.has_value());
-        const auto [when, expectedVSyncTimestamp, deadlineTimestamp] = callbackData.value();
-        EXPECT_EQ(when, expectedVSyncTimestamp - newDuration.count());
+        const auto [when, vsyncData] = callbackData.value();
+        EXPECT_EQ(when, vsyncData.expectedVSyncTimestamp - newDuration.count());
     }
 
     EXPECT_CALL(*mVSyncDispatch, cancel(_)).Times(1);
diff --git a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
index 67a0d7e..e5f7b03 100644
--- a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
+++ b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
@@ -257,7 +257,7 @@
     ASSERT_TRUE(args.has_value()) << " did not receive an event for timestamp "
                                   << expectedTimestamp;
     const auto& event = std::get<0>(args.value());
-    for (int i = 0; i < DisplayEventReceiver::kFrameTimelinesLength; i++) {
+    for (int i = 0; i < gui::VsyncEventData::kFrameTimelinesLength; i++) {
         auto prediction =
                 mTokenManager->getPredictionsForToken(event.vsync.frameTimelines[i].vsyncId);
         EXPECT_TRUE(prediction.has_value());
@@ -275,17 +275,16 @@
                       event.vsync.frameTimelines[i - 1].expectedVSyncTimestamp)
                     << "Expected vsync timestamp out of order for frame timeline " << i;
         }
-        if (event.vsync.frameTimelines[i].deadlineTimestamp == preferredDeadline) {
-            EXPECT_EQ(i, event.vsync.preferredFrameTimelineIndex)
-                    << "Preferred frame timeline index should be " << i;
-            // For the platform-preferred frame timeline, the vsync ID is 0 because the first frame
-            // timeline is made before the rest.
-            EXPECT_EQ(0, event.vsync.frameTimelines[i].vsyncId)
-                    << "Vsync ID incorrect for frame timeline " << i;
-        } else {
-            // Vsync ID 0 is used for the preferred frame timeline.
-            EXPECT_EQ(i + 1, event.vsync.frameTimelines[i].vsyncId)
-                    << "Vsync ID incorrect for frame timeline " << i;
+
+        // Vsync ID order lines up with registration into test token manager.
+        EXPECT_EQ(i, event.vsync.frameTimelines[i].vsyncId)
+                << "Vsync ID incorrect for frame timeline " << i;
+        if (i == event.vsync.preferredFrameTimelineIndex) {
+            EXPECT_EQ(event.vsync.frameTimelines[i].deadlineTimestamp, preferredDeadline)
+                    << "Preferred deadline timestamp incorrect" << i;
+            EXPECT_EQ(event.vsync.frameTimelines[i].expectedVSyncTimestamp,
+                      event.vsync.expectedVSyncTimestamp)
+                    << "Preferred expected vsync timestamp incorrect" << i;
         }
     }
 }
@@ -369,7 +368,7 @@
 
     // Use the received callback to signal a first vsync event.
     // The interceptor should receive the event, as well as the connection.
-    mCallback->onVSyncEvent(123, 456, 789);
+    mCallback->onVSyncEvent(123, {456, 789});
     expectInterceptCallReceived(123);
     expectThrottleVsyncReceived(456, mConnectionUid);
     expectVsyncEventReceivedByConnection(123, 1u);
@@ -377,7 +376,7 @@
     // Use the received callback to signal a second vsync event.
     // The interceptor should receive the event, but the connection should
     // not as it was only interested in the first.
-    mCallback->onVSyncEvent(456, 123, 0);
+    mCallback->onVSyncEvent(456, {123, 0});
     expectInterceptCallReceived(456);
     EXPECT_FALSE(mThrottleVsyncCallRecorder.waitForUnexpectedCall().has_value());
     EXPECT_FALSE(mConnectionEventCallRecorder.waitForUnexpectedCall().has_value());
@@ -395,7 +394,7 @@
 
     // Use the received callback to signal a vsync event.
     // The interceptor should receive the event, as well as the connection.
-    mCallback->onVSyncEvent(123, 456, 789);
+    mCallback->onVSyncEvent(123, {456, 789});
     expectInterceptCallReceived(123);
     expectVsyncEventFrameTimelinesCorrect(123, 789);
 }
@@ -422,7 +421,7 @@
     // Send a vsync event. EventThread should then make a call to the
     // interceptor, and the second connection. The first connection should not
     // get the event.
-    mCallback->onVSyncEvent(123, 456, 0);
+    mCallback->onVSyncEvent(123, {456, 0});
     expectInterceptCallReceived(123);
     EXPECT_FALSE(firstConnectionEventRecorder.waitForUnexpectedCall().has_value());
     expectVsyncEventReceivedByConnection("secondConnection", secondConnectionEventRecorder, 123,
@@ -437,19 +436,19 @@
 
     // Send a vsync event. EventThread should then make a call to the
     // interceptor, and the connection.
-    mCallback->onVSyncEvent(123, 456, 789);
+    mCallback->onVSyncEvent(123, {456, 789});
     expectInterceptCallReceived(123);
     expectThrottleVsyncReceived(456, mConnectionUid);
     expectVsyncEventReceivedByConnection(123, 1u);
 
     // A second event should go to the same places.
-    mCallback->onVSyncEvent(456, 123, 0);
+    mCallback->onVSyncEvent(456, {123, 0});
     expectInterceptCallReceived(456);
     expectThrottleVsyncReceived(123, mConnectionUid);
     expectVsyncEventReceivedByConnection(456, 2u);
 
     // A third event should go to the same places.
-    mCallback->onVSyncEvent(789, 777, 111);
+    mCallback->onVSyncEvent(789, {777, 111});
     expectInterceptCallReceived(789);
     expectThrottleVsyncReceived(777, mConnectionUid);
     expectVsyncEventReceivedByConnection(789, 3u);
@@ -462,25 +461,25 @@
     expectVSyncSetEnabledCallReceived(true);
 
     // The first event will be seen by the interceptor, and not the connection.
-    mCallback->onVSyncEvent(123, 456, 789);
+    mCallback->onVSyncEvent(123, {456, 789});
     expectInterceptCallReceived(123);
     EXPECT_FALSE(mConnectionEventCallRecorder.waitForUnexpectedCall().has_value());
     EXPECT_FALSE(mThrottleVsyncCallRecorder.waitForUnexpectedCall().has_value());
 
     // The second event will be seen by the interceptor and the connection.
-    mCallback->onVSyncEvent(456, 123, 0);
+    mCallback->onVSyncEvent(456, {123, 0});
     expectInterceptCallReceived(456);
     expectVsyncEventReceivedByConnection(456, 2u);
     EXPECT_FALSE(mThrottleVsyncCallRecorder.waitForUnexpectedCall().has_value());
 
     // The third event will be seen by the interceptor, and not the connection.
-    mCallback->onVSyncEvent(789, 777, 744);
+    mCallback->onVSyncEvent(789, {777, 744});
     expectInterceptCallReceived(789);
     EXPECT_FALSE(mConnectionEventCallRecorder.waitForUnexpectedCall().has_value());
     EXPECT_FALSE(mThrottleVsyncCallRecorder.waitForUnexpectedCall().has_value());
 
     // The fourth event will be seen by the interceptor and the connection.
-    mCallback->onVSyncEvent(101112, 7847, 86);
+    mCallback->onVSyncEvent(101112, {7847, 86});
     expectInterceptCallReceived(101112);
     expectVsyncEventReceivedByConnection(101112, 4u);
 }
@@ -495,7 +494,7 @@
     mConnection = nullptr;
 
     // The first event will be seen by the interceptor, and not the connection.
-    mCallback->onVSyncEvent(123, 456, 789);
+    mCallback->onVSyncEvent(123, {456, 789});
     expectInterceptCallReceived(123);
     EXPECT_FALSE(mConnectionEventCallRecorder.waitForUnexpectedCall().has_value());
 
@@ -513,13 +512,13 @@
 
     // The first event will be seen by the interceptor, and by the connection,
     // which then returns an error.
-    mCallback->onVSyncEvent(123, 456, 789);
+    mCallback->onVSyncEvent(123, {456, 789});
     expectInterceptCallReceived(123);
     expectVsyncEventReceivedByConnection("errorConnection", errorConnectionEventRecorder, 123, 1u);
 
     // A subsequent event will be seen by the interceptor and not by the
     // connection.
-    mCallback->onVSyncEvent(456, 123, 0);
+    mCallback->onVSyncEvent(456, {123, 0});
     expectInterceptCallReceived(456);
     EXPECT_FALSE(errorConnectionEventRecorder.waitForUnexpectedCall().has_value());
 
@@ -544,7 +543,7 @@
 
     // The first event will be seen by the interceptor, and by the connection,
     // which then returns an error.
-    mCallback->onVSyncEvent(123, 456, 789);
+    mCallback->onVSyncEvent(123, {456, 789});
     expectInterceptCallReceived(123);
     expectVsyncEventReceivedByConnection("errorConnection", errorConnectionEventRecorder, 123, 1u);
     expectVsyncEventReceivedByConnection("successConnection", secondConnectionEventRecorder, 123,
@@ -562,13 +561,13 @@
 
     // The first event will be seen by the interceptor, and by the connection,
     // which then returns an non-fatal error.
-    mCallback->onVSyncEvent(123, 456, 789);
+    mCallback->onVSyncEvent(123, {456, 789});
     expectInterceptCallReceived(123);
     expectVsyncEventReceivedByConnection("errorConnection", errorConnectionEventRecorder, 123, 1u);
 
     // A subsequent event will be seen by the interceptor, and by the connection,
     // which still then returns an non-fatal error.
-    mCallback->onVSyncEvent(456, 123, 0);
+    mCallback->onVSyncEvent(456, {123, 0});
     expectInterceptCallReceived(456);
     expectVsyncEventReceivedByConnection("errorConnection", errorConnectionEventRecorder, 456, 2u);
 
@@ -692,7 +691,7 @@
 
     // Use the received callback to signal a first vsync event.
     // The interceptor should receive the event, but not the connection.
-    mCallback->onVSyncEvent(123, 456, 789);
+    mCallback->onVSyncEvent(123, {456, 789});
     expectInterceptCallReceived(123);
     expectThrottleVsyncReceived(456, mThrottledConnectionUid);
     mThrottledConnectionEventCallRecorder.waitForUnexpectedCall();
@@ -700,7 +699,7 @@
     // Use the received callback to signal a second vsync event.
     // The interceptor should receive the event, but the connection should
     // not as it was only interested in the first.
-    mCallback->onVSyncEvent(456, 123, 0);
+    mCallback->onVSyncEvent(456, {123, 0});
     expectInterceptCallReceived(456);
     expectThrottleVsyncReceived(123, mThrottledConnectionUid);
     EXPECT_FALSE(mConnectionEventCallRecorder.waitForUnexpectedCall().has_value());