SurfaceFlinger: check transaction timings even if it doesn't have a buffer
Bufferless transactions should also not be applied if they are considered
early.
Bug: 181978893
Test: launch an app and observe systraces
Test: adb shell /data/nativetest64/SurfaceFlinger_test/SurfaceFlinger_test
Change-Id: Ie6cff82f8316c1a299d4c9f151eaf637cb60e154
diff --git a/services/surfaceflinger/tests/LayerCallback_test.cpp b/services/surfaceflinger/tests/LayerCallback_test.cpp
index 6d28e62..aa1cce2 100644
--- a/services/surfaceflinger/tests/LayerCallback_test.cpp
+++ b/services/surfaceflinger/tests/LayerCallback_test.cpp
@@ -18,6 +18,10 @@
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wconversion"
+#include <sys/epoll.h>
+
+#include <gui/DisplayEventReceiver.h>
+
#include "LayerTransactionTest.h"
#include "utils/CallbackUtils.h"
@@ -30,6 +34,24 @@
class LayerCallbackTest : public LayerTransactionTest {
public:
+ void SetUp() override {
+ LayerTransactionTest::SetUp();
+
+ 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);
+ LayerTransactionTest::TearDown();
+ }
+
virtual sp<SurfaceControl> createBufferStateLayer() {
return createLayer(mClient, "test", 0, 0, ISurfaceComposerClient::eFXSurfaceBufferState);
}
@@ -82,6 +104,35 @@
ASSERT_NO_FATAL_FAILURE(helper.verifyFinalState());
}
}
+
+ DisplayEventReceiver mDisplayEventReceiver;
+ int mEpollFd;
+
+ struct Vsync {
+ int64_t vsyncId = FrameTimelineInfo::INVALID_VSYNC_ID;
+ nsecs_t expectedPresentTime = std::numeric_limits<nsecs_t>::max();
+ };
+
+ Vsync waitForNextVsync() {
+ mDisplayEventReceiver.requestNextVsync();
+ epoll_event epollEvent;
+ Vsync vsync;
+ EXPECT_EQ(1, epoll_wait(mEpollFd, &epollEvent, 1, 1000))
+ << "Timeout waiting for vsync event";
+ DisplayEventReceiver::Event event;
+ while (mDisplayEventReceiver.getEvents(&event, 1) > 0) {
+ if (event.header.type != DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
+ continue;
+ }
+
+ vsync = {event.vsync.vsyncId, event.vsync.expectedVSyncTimestamp};
+ }
+
+ EXPECT_GE(vsync.vsyncId, 1);
+ EXPECT_GT(event.vsync.expectedVSyncTimestamp, systemTime());
+
+ return vsync;
+ }
};
TEST_F(LayerCallbackTest, BufferColor) {
@@ -873,6 +924,29 @@
expected.addExpectedPresentTime(systemTime());
EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true));
}
+
+TEST_F(LayerCallbackTest, ExpectedPresentTime) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer());
+
+ Transaction transaction;
+ CallbackHelper callback;
+ int err = fillTransaction(transaction, &callback, layer);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
+
+ const Vsync vsync = waitForNextVsync();
+ transaction.setFrameTimelineInfo({vsync.vsyncId, 0});
+ transaction.apply();
+
+ ExpectedResult expected;
+ expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer);
+ expected.addExpectedPresentTimeForVsyncId(vsync.expectedPresentTime);
+ EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true));
+}
+
} // namespace android
// TODO(b/129481165): remove the #pragma below and fix conversion issues
diff --git a/services/surfaceflinger/tests/utils/CallbackUtils.h b/services/surfaceflinger/tests/utils/CallbackUtils.h
index 1318deb..459b35c 100644
--- a/services/surfaceflinger/tests/utils/CallbackUtils.h
+++ b/services/surfaceflinger/tests/utils/CallbackUtils.h
@@ -81,6 +81,10 @@
mExpectedPresentTime = expectedPresentTime;
}
+ void addExpectedPresentTimeForVsyncId(nsecs_t expectedPresentTime) {
+ mExpectedPresentTimeForVsyncId = expectedPresentTime;
+ }
+
void verifyCallbackData(const CallbackData& callbackData) const {
const auto& [latchTime, presentFence, surfaceControlStats] = callbackData;
if (mTransactionResult == ExpectedResult::Transaction::PRESENTED) {
@@ -93,6 +97,11 @@
// misses vsync and we have to wait another 33.3ms
ASSERT_LE(presentFence->getSignalTime(),
mExpectedPresentTime + nsecs_t(66.666666 * 1e6));
+ } else if (mExpectedPresentTimeForVsyncId >= 0) {
+ ASSERT_EQ(presentFence->wait(3000), NO_ERROR);
+ // We give 4ms for prediction error
+ ASSERT_GE(presentFence->getSignalTime(),
+ mExpectedPresentTimeForVsyncId - 4'000'000);
}
} else {
ASSERT_EQ(presentFence, nullptr) << "transaction shouldn't have been presented";
@@ -151,6 +160,7 @@
};
ExpectedResult::Transaction mTransactionResult = ExpectedResult::Transaction::NOT_PRESENTED;
nsecs_t mExpectedPresentTime = -1;
+ nsecs_t mExpectedPresentTimeForVsyncId = -1;
std::unordered_map<sp<SurfaceControl>, ExpectedSurfaceResult, SCHash> mExpectedSurfaceResults;
};