Merge "SurfaceFlinger: Remove unnecessary state copy"
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/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/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/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/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/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 c5dba63..5ccb5eb 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -5507,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) {
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());