Add Shared timeline jank classification listener (1/2)
Adds the ability to register a listener that gets informed about
SF' jank classifications via the TransactionCompleted interface
Bug: 17475548
Test: FrameTimelineTest
Test: Register listener, ensure data flows back
Change-Id: Ie42c508da605c03569eadab6ab18b7315b35d247
diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp
index dc99986..325ecfe 100644
--- a/services/surfaceflinger/BufferQueueLayer.cpp
+++ b/services/surfaceflinger/BufferQueueLayer.cpp
@@ -440,7 +440,7 @@
mName, mFrameTimelineVsyncId);
surfaceFrame->setActualQueueTime(systemTime());
- mQueueItems.push_back({item, std::move(surfaceFrame)});
+ mQueueItems.push_back({item, surfaceFrame});
mQueuedFrames++;
// Wake up any pending callbacks
diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h
index b45900e..5a6b9bc 100644
--- a/services/surfaceflinger/BufferQueueLayer.h
+++ b/services/surfaceflinger/BufferQueueLayer.h
@@ -129,10 +129,10 @@
Condition mQueueItemCondition;
struct BufferData {
- BufferData(BufferItem item, std::unique_ptr<frametimeline::SurfaceFrame> surfaceFrame)
- : item(item), surfaceFrame(std::move(surfaceFrame)) {}
+ BufferData(BufferItem item, std::shared_ptr<frametimeline::SurfaceFrame> surfaceFrame)
+ : item(item), surfaceFrame(surfaceFrame) {}
BufferItem item;
- std::unique_ptr<frametimeline::SurfaceFrame> surfaceFrame;
+ std::shared_ptr<frametimeline::SurfaceFrame> surfaceFrame;
};
std::vector<BufferData> mQueueItems;
std::atomic<uint64_t> mLastFrameNumberReceived{0};
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index 963e541..4efff75 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -100,14 +100,30 @@
}
}
+void BufferStateLayer::onSurfaceFrameCreated(
+ const std::shared_ptr<frametimeline::SurfaceFrame>& surfaceFrame) {
+ mPendingJankClassifications.emplace_back(surfaceFrame);
+}
+
void BufferStateLayer::releasePendingBuffer(nsecs_t dequeueReadyTime) {
for (const auto& handle : mDrawingState.callbackHandles) {
handle->transformHint = mTransformHint;
handle->dequeueReadyTime = dequeueReadyTime;
}
+ std::vector<JankData> jankData;
+ jankData.reserve(mPendingJankClassifications.size());
+ while (!mPendingJankClassifications.empty()
+ && mPendingJankClassifications.front()->getJankType()) {
+ std::shared_ptr<frametimeline::SurfaceFrame> surfaceFrame =
+ mPendingJankClassifications.front();
+ mPendingJankClassifications.pop_front();
+ jankData.emplace_back(
+ JankData(surfaceFrame->getToken(), surfaceFrame->getJankType().value()));
+ }
+
mFlinger->getTransactionCompletedThread().finalizePendingCallbackHandles(
- mDrawingState.callbackHandles);
+ mDrawingState.callbackHandles, jankData);
mDrawingState.callbackHandles = {};
@@ -382,7 +398,7 @@
void BufferStateLayer::forceSendCallbacks() {
mFlinger->getTransactionCompletedThread().finalizePendingCallbackHandles(
- mCurrentState.callbackHandles);
+ mCurrentState.callbackHandles, std::vector<JankData>());
}
bool BufferStateLayer::setTransparentRegionHint(const Region& transparent) {
diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h
index 42be62a..0f0b48a 100644
--- a/services/surfaceflinger/BufferStateLayer.h
+++ b/services/surfaceflinger/BufferStateLayer.h
@@ -115,6 +115,7 @@
protected:
void gatherBufferInfo() override;
uint64_t getHeadFrameNumber(nsecs_t expectedPresentTime) const;
+ void onSurfaceFrameCreated(const std::shared_ptr<frametimeline::SurfaceFrame>& surfaceFrame);
private:
friend class SlotGenerationTest;
@@ -158,6 +159,8 @@
bool mReleasePreviousBuffer = false;
nsecs_t mCallbackHandleAcquireTime = -1;
+ std::deque<std::shared_ptr<android::frametimeline::SurfaceFrame>> mPendingJankClassifications;
+
// TODO(marissaw): support sticky transform for LEGACY camera mode
class HwcSlotGenerator : public ClientCache::ErasedRecipient {
diff --git a/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp b/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp
index b45c213..b09f07a 100644
--- a/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp
+++ b/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp
@@ -265,8 +265,11 @@
mJankMetadata = jankMetadata;
}
-JankType SurfaceFrame::getJankType() const {
+std::optional<JankType> SurfaceFrame::getJankType() const {
std::lock_guard<std::mutex> lock(mMutex);
+ if (mActuals.presentTime == 0) {
+ return std::nullopt;
+ }
return mJankType;
}
@@ -386,37 +389,36 @@
this->surfaceFrames.reserve(kNumSurfaceFramesInitial);
}
-std::unique_ptr<android::frametimeline::SurfaceFrame> FrameTimeline::createSurfaceFrameForToken(
+std::shared_ptr<android::frametimeline::SurfaceFrame> FrameTimeline::createSurfaceFrameForToken(
pid_t ownerPid, uid_t ownerUid, std::string layerName, std::string debugName,
std::optional<int64_t> token) {
ATRACE_CALL();
if (!token) {
- return std::make_unique<impl::SurfaceFrame>(ISurfaceComposer::INVALID_VSYNC_ID, ownerPid,
+ return std::make_shared<impl::SurfaceFrame>(ISurfaceComposer::INVALID_VSYNC_ID,ownerPid,
ownerUid, std::move(layerName),
std::move(debugName), PredictionState::None,
TimelineItem());
}
std::optional<TimelineItem> predictions = mTokenManager.getPredictionsForToken(*token);
if (predictions) {
- return std::make_unique<impl::SurfaceFrame>(*token, ownerPid, ownerUid,
+ return std::make_shared<impl::SurfaceFrame>(*token, ownerPid, ownerUid,
std::move(layerName), std::move(debugName),
PredictionState::Valid,
std::move(*predictions));
}
- return std::make_unique<impl::SurfaceFrame>(*token, ownerPid, ownerUid, std::move(layerName),
+ return std::make_shared<impl::SurfaceFrame>(*token, ownerPid, ownerUid, std::move(layerName),
std::move(debugName), PredictionState::Expired,
TimelineItem());
}
void FrameTimeline::addSurfaceFrame(
- std::unique_ptr<android::frametimeline::SurfaceFrame> surfaceFrame,
+ std::shared_ptr<android::frametimeline::SurfaceFrame> surfaceFrame,
SurfaceFrame::PresentState state) {
ATRACE_CALL();
surfaceFrame->setPresentState(state);
- std::unique_ptr<impl::SurfaceFrame> implSurfaceFrame(
- static_cast<impl::SurfaceFrame*>(surfaceFrame.release()));
std::lock_guard<std::mutex> lock(mMutex);
- mCurrentDisplayFrame->surfaceFrames.push_back(std::move(implSurfaceFrame));
+ mCurrentDisplayFrame->surfaceFrames.push_back(
+ std::static_pointer_cast<impl::SurfaceFrame>(surfaceFrame));
}
void FrameTimeline::setSfWakeUp(int64_t token, nsecs_t wakeUpTime) {
diff --git a/services/surfaceflinger/FrameTimeline/FrameTimeline.h b/services/surfaceflinger/FrameTimeline/FrameTimeline.h
index fe83ebf..084935b 100644
--- a/services/surfaceflinger/FrameTimeline/FrameTimeline.h
+++ b/services/surfaceflinger/FrameTimeline/FrameTimeline.h
@@ -120,6 +120,12 @@
virtual void setActualStartTime(nsecs_t actualStartTime) = 0;
virtual void setActualQueueTime(nsecs_t actualQueueTime) = 0;
virtual void setAcquireFenceTime(nsecs_t acquireFenceTime) = 0;
+
+ // Retrieves jank classification, if it's already been classified.
+ virtual std::optional<JankType> getJankType() const = 0;
+
+ // Token identifying the frame.
+ virtual int64_t getToken() const = 0;
};
/*
@@ -138,13 +144,13 @@
// Create a new surface frame, set the predictions based on a token and return it to the caller.
// Sets the PredictionState of SurfaceFrame.
// Debug name is the human-readable debugging string for dumpsys.
- virtual std::unique_ptr<SurfaceFrame> createSurfaceFrameForToken(
+ virtual std::shared_ptr<SurfaceFrame> createSurfaceFrameForToken(
pid_t ownerPid, uid_t ownerUid, std::string layerName, std::string debugName,
std::optional<int64_t> token) = 0;
// Adds a new SurfaceFrame to the current DisplayFrame. Frames from multiple layers can be
// composited into one display frame.
- virtual void addSurfaceFrame(std::unique_ptr<SurfaceFrame> surfaceFrame,
+ virtual void addSurfaceFrame(std::shared_ptr<SurfaceFrame> surfaceFrame,
SurfaceFrame::PresentState state) = 0;
// The first function called by SF for the current DisplayFrame. Fetches SF predictions based on
@@ -209,8 +215,8 @@
PresentState getPresentState() const override;
PredictionState getPredictionState() const override { return mPredictionState; };
pid_t getOwnerPid() const override { return mOwnerPid; };
- JankType getJankType() const;
- int64_t getToken() const { return mToken; };
+ std::optional<JankType> getJankType() const override;
+ int64_t getToken() const override { return mToken; };
nsecs_t getBaseTime() const;
uid_t getOwnerUid() const { return mOwnerUid; };
const std::string& getName() const { return mLayerName; };
@@ -258,10 +264,10 @@
~FrameTimeline() = default;
frametimeline::TokenManager* getTokenManager() override { return &mTokenManager; }
- std::unique_ptr<frametimeline::SurfaceFrame> createSurfaceFrameForToken(
+ std::shared_ptr<frametimeline::SurfaceFrame> createSurfaceFrameForToken(
pid_t ownerPid, uid_t ownerUid, std::string layerName, std::string debugName,
std::optional<int64_t> token) override;
- void addSurfaceFrame(std::unique_ptr<frametimeline::SurfaceFrame> surfaceFrame,
+ void addSurfaceFrame(std::shared_ptr<frametimeline::SurfaceFrame> surfaceFrame,
SurfaceFrame::PresentState state) override;
void setSfWakeUp(int64_t token, nsecs_t wakeupTime) override;
void setSfPresent(nsecs_t sfPresentTime,
@@ -299,7 +305,7 @@
TimelineItem surfaceFlingerActuals;
// Collection of predictions and actual values sent over by Layers
- std::vector<std::unique_ptr<SurfaceFrame>> surfaceFrames;
+ std::vector<std::shared_ptr<SurfaceFrame>> surfaceFrames;
PredictionState predictionState = PredictionState::None;
JankType jankType = JankType::None; // Enum for the type of jank
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index ab0d3df..cfaa59d 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -901,17 +901,17 @@
? std::nullopt
: std::make_optional(stateToCommit->frameTimelineVsyncId);
- auto surfaceFrame =
+ mSurfaceFrame =
mFlinger->mFrameTimeline->createSurfaceFrameForToken(getOwnerPid(), getOwnerUid(),
mName, mTransactionName,
vsyncId);
- surfaceFrame->setActualQueueTime(stateToCommit->postTime);
+ mSurfaceFrame->setActualQueueTime(stateToCommit->postTime);
// For transactions we set the acquire fence time to the post time as we
// don't have a buffer. For BufferStateLayer it is overridden in
// BufferStateLayer::applyPendingStates
- surfaceFrame->setAcquireFenceTime(stateToCommit->postTime);
+ mSurfaceFrame->setAcquireFenceTime(stateToCommit->postTime);
- mSurfaceFrame = std::move(surfaceFrame);
+ onSurfaceFrameCreated(mSurfaceFrame);
}
mCurrentState.modified = false;
@@ -1057,7 +1057,7 @@
void Layer::commitTransaction(const State& stateToCommit) {
mDrawingState = stateToCommit;
- mFlinger->mFrameTimeline->addSurfaceFrame(std::move(mSurfaceFrame), PresentState::Presented);
+ mFlinger->mFrameTimeline->addSurfaceFrame(mSurfaceFrame, PresentState::Presented);
}
uint32_t Layer::getTransactionFlags(uint32_t flags) {
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 75d68a1..b30793a 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -942,6 +942,7 @@
virtual void commitTransaction(const State& stateToCommit);
virtual bool applyPendingStates(State* stateToCommit);
virtual uint32_t doTransactionResize(uint32_t flags, Layer::State* stateToCommit);
+ virtual void onSurfaceFrameCreated(const std::shared_ptr<frametimeline::SurfaceFrame>&) {}
// Returns mCurrentScaling mode (originating from the
// Client) or mOverrideScalingMode mode (originating from
@@ -1066,7 +1067,7 @@
const InputWindowInfo::Type mWindowType;
// Can only be accessed with the SF state lock held.
- std::unique_ptr<frametimeline::SurfaceFrame> mSurfaceFrame;
+ std::shared_ptr<frametimeline::SurfaceFrame> mSurfaceFrame;
// The owner of the layer. If created from a non system process, it will be the calling uid.
// If created from a system process, the value can be passed in.
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 773b3ab..cb56ecc 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1986,12 +1986,14 @@
mScheduler->onDisplayRefreshed(presentTime);
- postFrame();
- postComposition();
-
+ // Set presentation information before calling postComposition, such that jank information from
+ // this' frame classification is already available when sending jank info to clients.
mFrameTimeline->setSfPresent(systemTime(),
std::make_shared<FenceTime>(mPreviousPresentFences[0]));
+ postFrame();
+ postComposition();
+
const bool prevFrameHadClientComposition = mHadClientComposition;
mHadClientComposition = std::any_of(displays.cbegin(), displays.cend(), [](const auto& pair) {
diff --git a/services/surfaceflinger/TransactionCompletedThread.cpp b/services/surfaceflinger/TransactionCompletedThread.cpp
index ca24493..1797af4 100644
--- a/services/surfaceflinger/TransactionCompletedThread.cpp
+++ b/services/surfaceflinger/TransactionCompletedThread.cpp
@@ -153,7 +153,7 @@
}
status_t TransactionCompletedThread::finalizePendingCallbackHandles(
- const std::deque<sp<CallbackHandle>>& handles) {
+ const std::deque<sp<CallbackHandle>>& handles, const std::vector<JankData>& jankData) {
if (handles.empty()) {
return NO_ERROR;
}
@@ -186,7 +186,7 @@
ALOGW("cannot find listener in mPendingTransactions");
}
- status_t err = addCallbackHandle(handle);
+ status_t err = addCallbackHandle(handle, jankData);
if (err != NO_ERROR) {
ALOGE("could not add callback handle");
return err;
@@ -204,7 +204,7 @@
return BAD_VALUE;
}
- return addCallbackHandle(handle);
+ return addCallbackHandle(handle, std::vector<JankData>());
}
status_t TransactionCompletedThread::findTransactionStats(
@@ -225,7 +225,8 @@
return BAD_VALUE;
}
-status_t TransactionCompletedThread::addCallbackHandle(const sp<CallbackHandle>& handle) {
+status_t TransactionCompletedThread::addCallbackHandle(const sp<CallbackHandle>& handle,
+ const std::vector<JankData>& jankData) {
// If we can't find the transaction stats something has gone wrong. The client should call
// startRegistration before trying to add a callback handle.
TransactionStats* transactionStats;
@@ -246,7 +247,7 @@
handle->dequeueReadyTime);
transactionStats->surfaceStats.emplace_back(surfaceControl, handle->acquireTime,
handle->previousReleaseFence,
- handle->transformHint, eventStats);
+ handle->transformHint, eventStats, jankData);
}
return NO_ERROR;
}
diff --git a/services/surfaceflinger/TransactionCompletedThread.h b/services/surfaceflinger/TransactionCompletedThread.h
index f50147a..c4ba7e4 100644
--- a/services/surfaceflinger/TransactionCompletedThread.h
+++ b/services/surfaceflinger/TransactionCompletedThread.h
@@ -73,7 +73,8 @@
// presented.
status_t registerPendingCallbackHandle(const sp<CallbackHandle>& handle);
// Notifies the TransactionCompletedThread that a pending CallbackHandle has been presented.
- status_t finalizePendingCallbackHandles(const std::deque<sp<CallbackHandle>>& handles);
+ status_t finalizePendingCallbackHandles(const std::deque<sp<CallbackHandle>>& handles,
+ const std::vector<JankData>& jankData);
// Adds the Transaction CallbackHandle from a layer that does not need to be relatched and
// presented this frame.
@@ -93,7 +94,8 @@
const std::vector<CallbackId>& callbackIds,
TransactionStats** outTransactionStats) REQUIRES(mMutex);
- status_t addCallbackHandle(const sp<CallbackHandle>& handle) REQUIRES(mMutex);
+ status_t addCallbackHandle(const sp<CallbackHandle>& handle,
+ const std::vector<JankData>& jankData) REQUIRES(mMutex);
class ThreadDeathRecipient : public IBinder::DeathRecipient {
public:
diff --git a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp
index 31a5126..538b10d 100644
--- a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp
+++ b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp
@@ -69,6 +69,7 @@
using Transaction = SurfaceComposerClient::Transaction;
using Attribute = V2_4::IComposerClient::Attribute;
+using Display = V2_1::Display;
///////////////////////////////////////////////
diff --git a/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp b/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp
index 411e780..43b5afe 100644
--- a/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp
+++ b/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp
@@ -205,7 +205,7 @@
// Set up the display frame
mFrameTimeline->setSfWakeUp(token1, 20);
- mFrameTimeline->addSurfaceFrame(std::move(surfaceFrame1), SurfaceFrame::PresentState::Dropped);
+ mFrameTimeline->addSurfaceFrame(surfaceFrame1, SurfaceFrame::PresentState::Dropped);
mFrameTimeline->setSfPresent(25, presentFence1);
presentFence1->signalForTest(30);
@@ -229,11 +229,11 @@
sLayerNameOne, surfaceFrameToken1);
auto surfaceFrame2 =
mFrameTimeline->createSurfaceFrameForToken(sPidOne, sUidOne, sLayerNameTwo,
- sLayerNameTwo, surfaceFrameToken1);
+ sLayerNameTwo, surfaceFrameToken2);
mFrameTimeline->setSfWakeUp(sfToken1, 22);
- mFrameTimeline->addSurfaceFrame(std::move(surfaceFrame1),
+ mFrameTimeline->addSurfaceFrame(surfaceFrame1,
SurfaceFrame::PresentState::Presented);
- mFrameTimeline->addSurfaceFrame(std::move(surfaceFrame2),
+ mFrameTimeline->addSurfaceFrame(surfaceFrame2,
SurfaceFrame::PresentState::Presented);
mFrameTimeline->setSfPresent(26, presentFence1);
auto displayFrame = getDisplayFrame(0);
@@ -246,13 +246,16 @@
EXPECT_EQ(presentedSurfaceFrame1.getActuals().presentTime, 0);
EXPECT_EQ(presentedSurfaceFrame2.getActuals().presentTime, 0);
+ EXPECT_EQ(surfaceFrame1->getToken(), surfaceFrameToken1);
+ EXPECT_EQ(surfaceFrame2->getToken(), surfaceFrameToken2);
+
// Trigger a flush by finalizing the next DisplayFrame
auto presentFence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
auto surfaceFrame3 =
mFrameTimeline->createSurfaceFrameForToken(sPidOne, sUidOne, sLayerNameOne,
sLayerNameOne, surfaceFrameToken2);
mFrameTimeline->setSfWakeUp(sfToken2, 52);
- mFrameTimeline->addSurfaceFrame(std::move(surfaceFrame3), SurfaceFrame::PresentState::Dropped);
+ mFrameTimeline->addSurfaceFrame(surfaceFrame3, SurfaceFrame::PresentState::Dropped);
mFrameTimeline->setSfPresent(56, presentFence2);
displayFrame = getDisplayFrame(0);
@@ -260,6 +263,8 @@
EXPECT_EQ(displayFrame->surfaceFlingerActuals.presentTime, 42);
EXPECT_EQ(presentedSurfaceFrame1.getActuals().presentTime, 42);
EXPECT_EQ(presentedSurfaceFrame2.getActuals().presentTime, 42);
+ EXPECT_NE(surfaceFrame1->getJankType(), std::nullopt);
+ EXPECT_NE(surfaceFrame2->getJankType(), std::nullopt);
}
TEST_F(FrameTimelineTest, displayFramesSlidingWindowMovesAfterLimit) {
@@ -275,7 +280,7 @@
mFrameTimeline->createSurfaceFrameForToken(sPidOne, sUidOne, sLayerNameOne,
sLayerNameOne, surfaceFrameToken);
mFrameTimeline->setSfWakeUp(sfToken, 22 + frameTimeFactor);
- mFrameTimeline->addSurfaceFrame(std::move(surfaceFrame),
+ mFrameTimeline->addSurfaceFrame(surfaceFrame,
SurfaceFrame::PresentState::Presented);
mFrameTimeline->setSfPresent(27 + frameTimeFactor, presentFence);
presentFence->signalForTest(32 + frameTimeFactor);
@@ -297,7 +302,7 @@
mFrameTimeline->createSurfaceFrameForToken(sPidOne, sUidOne, sLayerNameOne,
sLayerNameOne, surfaceFrameToken);
mFrameTimeline->setSfWakeUp(sfToken, 22 + frameTimeFactor);
- mFrameTimeline->addSurfaceFrame(std::move(surfaceFrame), SurfaceFrame::PresentState::Presented);
+ mFrameTimeline->addSurfaceFrame(surfaceFrame, SurfaceFrame::PresentState::Presented);
mFrameTimeline->setSfPresent(27 + frameTimeFactor, presentFence);
presentFence->signalForTest(32 + frameTimeFactor);
displayFrame0 = getDisplayFrame(0);
@@ -337,7 +342,7 @@
sLayerNameOne, std::nullopt);
int64_t sfToken = mTokenManager->generateTokenForPredictions({22, 26, 30});
mFrameTimeline->setSfWakeUp(sfToken, 22);
- mFrameTimeline->addSurfaceFrame(std::move(surfaceFrame),
+ mFrameTimeline->addSurfaceFrame(surfaceFrame,
SurfaceFrame::PresentState::Presented);
mFrameTimeline->setSfPresent(27, presentFence);
}
@@ -353,7 +358,7 @@
sLayerNameOne, std::nullopt);
int64_t sfToken = mTokenManager->generateTokenForPredictions({22, 26, 30});
mFrameTimeline->setSfWakeUp(sfToken, 22);
- mFrameTimeline->addSurfaceFrame(std::move(surfaceFrame),
+ mFrameTimeline->addSurfaceFrame(surfaceFrame,
SurfaceFrame::PresentState::Presented);
mFrameTimeline->setSfPresent(27, presentFence);
}
@@ -369,7 +374,7 @@
sLayerNameOne, std::nullopt);
int64_t sfToken = mTokenManager->generateTokenForPredictions({22, 26, 30});
mFrameTimeline->setSfWakeUp(sfToken, 22);
- mFrameTimeline->addSurfaceFrame(std::move(surfaceFrame),
+ mFrameTimeline->addSurfaceFrame(surfaceFrame,
SurfaceFrame::PresentState::Presented);
mFrameTimeline->setSfPresent(27, presentFence);
}
@@ -396,10 +401,10 @@
sLayerNameOne, surfaceFrameToken1);
mFrameTimeline->setSfWakeUp(sfToken1,
std::chrono::duration_cast<std::chrono::nanoseconds>(52ms).count());
- mFrameTimeline->addSurfaceFrame(std::move(surfaceFrame1),
+ mFrameTimeline->addSurfaceFrame(surfaceFrame1,
SurfaceFrame::PresentState::Presented);
presentFence1->signalForTest(
- std::chrono::duration_cast<std::chrono::nanoseconds>(90ms).count());
+ std::chrono::duration_cast<std::chrono::nanoseconds>(70ms).count());
mFrameTimeline->setSfPresent(std::chrono::duration_cast<std::chrono::nanoseconds>(59ms).count(),
presentFence1);
@@ -423,12 +428,14 @@
sLayerNameOne, surfaceFrameToken1);
mFrameTimeline->setSfWakeUp(sfToken1,
std::chrono::duration_cast<std::chrono::nanoseconds>(52ms).count());
- mFrameTimeline->addSurfaceFrame(std::move(surfaceFrame1),
+ mFrameTimeline->addSurfaceFrame(surfaceFrame1,
SurfaceFrame::PresentState::Presented);
presentFence1->signalForTest(
std::chrono::duration_cast<std::chrono::nanoseconds>(90ms).count());
mFrameTimeline->setSfPresent(std::chrono::duration_cast<std::chrono::nanoseconds>(59ms).count(),
presentFence1);
+ EXPECT_NE(surfaceFrame1->getJankType(), std::nullopt);
+ EXPECT_TRUE((surfaceFrame1->getJankType().value() & JankType::Display) != 0);
}
TEST_F(FrameTimelineTest, presentFenceSignaled_reportsAppMiss) {
@@ -453,12 +460,15 @@
mFrameTimeline->setSfWakeUp(sfToken1,
std::chrono::duration_cast<std::chrono::nanoseconds>(52ms).count());
- mFrameTimeline->addSurfaceFrame(std::move(surfaceFrame1),
+ mFrameTimeline->addSurfaceFrame(surfaceFrame1,
SurfaceFrame::PresentState::Presented);
presentFence1->signalForTest(
std::chrono::duration_cast<std::chrono::nanoseconds>(90ms).count());
mFrameTimeline->setSfPresent(std::chrono::duration_cast<std::chrono::nanoseconds>(56ms).count(),
presentFence1);
+
+ EXPECT_NE(surfaceFrame1->getJankType(), std::nullopt);
+ EXPECT_TRUE((surfaceFrame1->getJankType().value() & JankType::AppDeadlineMissed) != 0);
}
/*
diff --git a/services/surfaceflinger/tests/unittests/mock/MockFrameTimeline.h b/services/surfaceflinger/tests/unittests/mock/MockFrameTimeline.h
index 81c32fe..6b12536 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockFrameTimeline.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockFrameTimeline.h
@@ -31,7 +31,7 @@
MOCK_METHOD0(onBootFinished, void());
MOCK_METHOD2(addSurfaceFrame,
- void(std::unique_ptr<frametimeline::SurfaceFrame>,
+ void(std::shared_ptr<frametimeline::SurfaceFrame>,
frametimeline::SurfaceFrame::PresentState));
MOCK_METHOD2(setSfWakeUp, void(int64_t, nsecs_t));
MOCK_METHOD2(setSfPresent, void(nsecs_t, const std::shared_ptr<FenceTime>&));