Merge changes I7bae2f9d,I0e8f0b15,I09cbb0cb into sc-dev

* changes:
  Consider GPU comp info for jank classification
  Remove hwcDuration from FrameTimeline
  Report deltas as 0 instead of -1 for prediction expired display frames
diff --git a/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp b/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp
index 6485265..7468ac3 100644
--- a/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp
+++ b/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp
@@ -752,14 +752,13 @@
 }
 
 FrameTimeline::FrameTimeline(std::shared_ptr<TimeStats> timeStats, pid_t surfaceFlingerPid,
-                             JankClassificationThresholds thresholds, nsecs_t hwcDuration)
+                             JankClassificationThresholds thresholds)
       : mMaxDisplayFrames(kDefaultMaxDisplayFrames),
         mTimeStats(std::move(timeStats)),
         mSurfaceFlingerPid(surfaceFlingerPid),
-        mJankClassificationThresholds(thresholds),
-        mHwcDuration(hwcDuration) {
-    mCurrentDisplayFrame = std::make_shared<DisplayFrame>(mTimeStats, thresholds, hwcDuration,
-                                                          &mTraceCookieCounter);
+        mJankClassificationThresholds(thresholds) {
+    mCurrentDisplayFrame =
+            std::make_shared<DisplayFrame>(mTimeStats, thresholds, &mTraceCookieCounter);
 }
 
 void FrameTimeline::onBootFinished() {
@@ -804,13 +803,11 @@
 
 FrameTimeline::DisplayFrame::DisplayFrame(std::shared_ptr<TimeStats> timeStats,
                                           JankClassificationThresholds thresholds,
-                                          nsecs_t hwcDuration,
                                           TraceCookieCounter* traceCookieCounter)
       : mSurfaceFlingerPredictions(TimelineItem()),
         mSurfaceFlingerActuals(TimelineItem()),
         mTimeStats(timeStats),
         mJankClassificationThresholds(thresholds),
-        mHwcDuration(hwcDuration),
         mTraceCookieCounter(*traceCookieCounter) {
     mSurfaceFrames.reserve(kNumSurfaceFramesInitial);
 }
@@ -830,13 +827,11 @@
 
 void FrameTimeline::setSfPresent(nsecs_t sfPresentTime,
                                  const std::shared_ptr<FenceTime>& presentFence,
-                                 bool gpuComposition) {
+                                 const std::shared_ptr<FenceTime>& gpuFence) {
     ATRACE_CALL();
     std::scoped_lock lock(mMutex);
     mCurrentDisplayFrame->setActualEndTime(sfPresentTime);
-    if (gpuComposition) {
-        mCurrentDisplayFrame->setGpuComposition();
-    }
+    mCurrentDisplayFrame->setGpuFence(gpuFence);
     mPendingPresentFences.emplace_back(std::make_pair(presentFence, mCurrentDisplayFrame));
     flushPendingPresentFences();
     finalizeCurrentDisplayFrame();
@@ -874,25 +869,32 @@
     mSurfaceFlingerActuals.endTime = actualEndTime;
 }
 
-void FrameTimeline::DisplayFrame::setGpuComposition() {
-    mGpuComposition = true;
+void FrameTimeline::DisplayFrame::setGpuFence(const std::shared_ptr<FenceTime>& gpuFence) {
+    mGpuFence = gpuFence;
 }
 
 void FrameTimeline::DisplayFrame::classifyJank(nsecs_t& deadlineDelta, nsecs_t& deltaToVsync) {
     if (mPredictionState == PredictionState::Expired ||
         mSurfaceFlingerActuals.presentTime == Fence::SIGNAL_TIME_INVALID) {
-        // Cannot do jank classification with expired predictions or invalid signal times.
+        // Cannot do jank classification with expired predictions or invalid signal times. Set the
+        // deltas to 0 as both negative and positive deltas are used as real values.
         mJankType = JankType::Unknown;
-        deadlineDelta = -1;
-        deltaToVsync = -1;
+        deadlineDelta = 0;
+        deltaToVsync = 0;
         return;
     }
 
     // Delta between the expected present and the actual present
     const nsecs_t presentDelta =
             mSurfaceFlingerActuals.presentTime - mSurfaceFlingerPredictions.presentTime;
-    deadlineDelta =
-            mSurfaceFlingerActuals.endTime - (mSurfaceFlingerPredictions.endTime - mHwcDuration);
+    // Sf actual end time represents the CPU end time. In case of HWC, SF's end time would have
+    // included the time for composition. However, for GPU composition, the final end time is max(sf
+    // end time, gpu fence time).
+    nsecs_t combinedEndTime = mSurfaceFlingerActuals.endTime;
+    if (mGpuFence != FenceTime::NO_FENCE) {
+        combinedEndTime = std::max(combinedEndTime, mGpuFence->getSignalTime());
+    }
+    deadlineDelta = combinedEndTime - mSurfaceFlingerPredictions.endTime;
 
     // How far off was the presentDelta when compared to the vsyncPeriod. Used in checking if there
     // was a prediction error or not.
@@ -907,9 +909,7 @@
         mFramePresentMetadata = FramePresentMetadata::OnTimePresent;
     }
 
-    if (mSurfaceFlingerActuals.endTime > mSurfaceFlingerPredictions.endTime - mHwcDuration) {
-        // SF needs to have finished at least mHwcDuration ahead of the deadline for it to be
-        // on time.
+    if (combinedEndTime > mSurfaceFlingerPredictions.endTime) {
         mFrameReadyMetadata = FrameReadyMetadata::LateFinish;
     } else {
         mFrameReadyMetadata = FrameReadyMetadata::OnTimeFinish;
@@ -966,7 +966,15 @@
                     mJankType = JankType::SurfaceFlingerScheduling;
                 } else {
                     // OnTime start, Finish late, Present late
-                    mJankType = JankType::SurfaceFlingerCpuDeadlineMissed;
+                    if (mGpuFence != FenceTime::NO_FENCE &&
+                        mSurfaceFlingerActuals.endTime - mSurfaceFlingerActuals.startTime <
+                                mRefreshRate.getPeriodNsecs()) {
+                        // If SF was in GPU composition and the CPU work finished before the vsync
+                        // period, classify it as GPU deadline missed.
+                        mJankType = JankType::SurfaceFlingerGpuDeadlineMissed;
+                    } else {
+                        mJankType = JankType::SurfaceFlingerCpuDeadlineMissed;
+                    }
                 }
             } else {
                 // Finish time unknown
@@ -1041,7 +1049,7 @@
         actualDisplayFrameStartEvent->set_present_type(toProto(mFramePresentMetadata));
         actualDisplayFrameStartEvent->set_on_time_finish(mFrameReadyMetadata ==
                                                          FrameReadyMetadata::OnTimeFinish);
-        actualDisplayFrameStartEvent->set_gpu_composition(mGpuComposition);
+        actualDisplayFrameStartEvent->set_gpu_composition(mGpuFence != FenceTime::NO_FENCE);
         actualDisplayFrameStartEvent->set_jank_type(jankTypeBitmaskToProto(mJankType));
         actualDisplayFrameStartEvent->set_prediction_type(toProto(mPredictionState));
     });
@@ -1164,7 +1172,7 @@
     mDisplayFrames.push_back(mCurrentDisplayFrame);
     mCurrentDisplayFrame.reset();
     mCurrentDisplayFrame = std::make_shared<DisplayFrame>(mTimeStats, mJankClassificationThresholds,
-                                                          mHwcDuration, &mTraceCookieCounter);
+                                                          &mTraceCookieCounter);
 }
 
 nsecs_t FrameTimeline::DisplayFrame::getBaseTime() const {
diff --git a/services/surfaceflinger/FrameTimeline/FrameTimeline.h b/services/surfaceflinger/FrameTimeline/FrameTimeline.h
index 3f04592..41f4978 100644
--- a/services/surfaceflinger/FrameTimeline/FrameTimeline.h
+++ b/services/surfaceflinger/FrameTimeline/FrameTimeline.h
@@ -293,11 +293,12 @@
     // the token and sets the actualSfWakeTime for the current DisplayFrame.
     virtual void setSfWakeUp(int64_t token, nsecs_t wakeupTime, Fps refreshRate) = 0;
 
-    // Sets the sfPresentTime, gpuComposition and finalizes the current DisplayFrame. Tracks the
+    // Sets the sfPresentTime and finalizes the current DisplayFrame. Tracks the
     // given present fence until it's signaled, and updates the present timestamps of all presented
-    // SurfaceFrames in that vsync.
+    // SurfaceFrames in that vsync. If a gpuFence was also provided, its tracked in the
+    // corresponding DisplayFrame.
     virtual void setSfPresent(nsecs_t sfPresentTime, const std::shared_ptr<FenceTime>& presentFence,
-                              bool gpuComposition) = 0;
+                              const std::shared_ptr<FenceTime>& gpuFence) = 0;
 
     // Args:
     // -jank : Dumps only the Display Frames that are either janky themselves
@@ -355,7 +356,7 @@
     class DisplayFrame {
     public:
         DisplayFrame(std::shared_ptr<TimeStats> timeStats, JankClassificationThresholds thresholds,
-                     nsecs_t hwcDuration, TraceCookieCounter* traceCookieCounter);
+                     TraceCookieCounter* traceCookieCounter);
         virtual ~DisplayFrame() = default;
         // Dumpsys interface - dumps only if the DisplayFrame itself is janky or is at least one
         // SurfaceFrame is janky.
@@ -376,7 +377,7 @@
         void setPredictions(PredictionState predictionState, TimelineItem predictions);
         void setActualStartTime(nsecs_t actualStartTime);
         void setActualEndTime(nsecs_t actualEndTime);
-        void setGpuComposition();
+        void setGpuFence(const std::shared_ptr<FenceTime>& gpuFence);
 
         // BaseTime is the smallest timestamp in a DisplayFrame.
         // Used for dumping all timestamps relative to the oldest, making it easy to read.
@@ -410,7 +411,6 @@
         TimelineItem mSurfaceFlingerActuals;
         std::shared_ptr<TimeStats> mTimeStats;
         const JankClassificationThresholds mJankClassificationThresholds;
-        const nsecs_t mHwcDuration;
 
         // Collection of predictions and actual values sent over by Layers
         std::vector<std::shared_ptr<SurfaceFrame>> mSurfaceFrames;
@@ -418,8 +418,8 @@
         PredictionState mPredictionState = PredictionState::None;
         // Bitmask for the type of jank
         int32_t mJankType = JankType::None;
-        // Indicates if this frame was composited by the GPU or not
-        bool mGpuComposition = false;
+        // A valid gpu fence indicates that the DisplayFrame was composited by the GPU
+        std::shared_ptr<FenceTime> mGpuFence = FenceTime::NO_FENCE;
         // Enum for the type of present
         FramePresentMetadata mFramePresentMetadata = FramePresentMetadata::UnknownPresent;
         // Enum for the type of finish
@@ -436,8 +436,7 @@
     };
 
     FrameTimeline(std::shared_ptr<TimeStats> timeStats, pid_t surfaceFlingerPid,
-                  JankClassificationThresholds thresholds = {},
-                  nsecs_t hwcDuration = kDefaultHwcDuration);
+                  JankClassificationThresholds thresholds = {});
     ~FrameTimeline() = default;
 
     frametimeline::TokenManager* getTokenManager() override { return &mTokenManager; }
@@ -447,7 +446,7 @@
     void addSurfaceFrame(std::shared_ptr<frametimeline::SurfaceFrame> surfaceFrame) override;
     void setSfWakeUp(int64_t token, nsecs_t wakeupTime, Fps refreshRate) override;
     void setSfPresent(nsecs_t sfPresentTime, const std::shared_ptr<FenceTime>& presentFence,
-                      bool gpuComposition = false) override;
+                      const std::shared_ptr<FenceTime>& gpuFence = FenceTime::NO_FENCE) override;
     void parseArgs(const Vector<String16>& args, std::string& result) override;
     void setMaxDisplayFrames(uint32_t size) override;
     float computeFps(const std::unordered_set<int32_t>& layerIds) override;
@@ -482,11 +481,6 @@
     std::shared_ptr<TimeStats> mTimeStats;
     const pid_t mSurfaceFlingerPid;
     const JankClassificationThresholds mJankClassificationThresholds;
-    // In SF Predictions, both end & present are the same. The predictions consider the time used by
-    // composer as well, but we have no way to estimate how much time the composer needs. We are
-    // assuming an arbitrary time for the composer work.
-    const nsecs_t mHwcDuration;
-    static constexpr nsecs_t kDefaultHwcDuration = std::chrono::nanoseconds(3ms).count();
     static constexpr uint32_t kDefaultMaxDisplayFrames = 64;
     // The initial container size for the vector<SurfaceFrames> inside display frame. Although
     // this number doesn't represent any bounds on the number of surface frames that can go in a
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 047b2f5..89ce9d2 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -2141,7 +2141,7 @@
     // information from previous' frame classification is already available when sending jank info
     // to clients, so they get jank classification as early as possible.
     mFrameTimeline->setSfPresent(systemTime(), mPreviousPresentFences[0].fenceTime,
-                                 glCompositionDoneFenceTime != FenceTime::NO_FENCE);
+                                 glCompositionDoneFenceTime);
 
     nsecs_t dequeueReadyTime = systemTime();
     for (const auto& layer : mLayersWithQueuedFrames) {
diff --git a/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp b/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp
index 982252f..7727052 100644
--- a/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp
+++ b/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp
@@ -68,7 +68,7 @@
     void SetUp() override {
         mTimeStats = std::make_shared<mock::TimeStats>();
         mFrameTimeline = std::make_unique<impl::FrameTimeline>(mTimeStats, kSurfaceFlingerPid,
-                                                               kTestThresholds, kHwcDuration);
+                                                               kTestThresholds);
         mFrameTimeline->registerDataSource();
         mTokenManager = &mFrameTimeline->mTokenManager;
         mTraceCookieCounter = &mFrameTimeline->mTraceCookieCounter;
@@ -163,7 +163,6 @@
     static constexpr JankClassificationThresholds kTestThresholds{kPresentThreshold,
                                                                   kDeadlineThreshold,
                                                                   kStartThreshold};
-    static constexpr nsecs_t kHwcDuration = std::chrono::nanoseconds(3ns).count();
 };
 
 static const std::string sLayerNameOne = "layer1";
@@ -483,7 +482,6 @@
 
 TEST_F(FrameTimelineTest, presentFenceSignaled_reportsLongSfCpu) {
     Fps refreshRate = Fps::fromPeriodNsecs(11);
-    // Deadline delta is 2ms because, sf's adjusted deadline is 60 - composerTime(3) = 57ms.
     EXPECT_CALL(*mTimeStats,
                 incrementJankyFrames(
                         TimeStats::JankyFramesInfo{refreshRate, std::nullopt, sUidOne,
@@ -504,7 +502,34 @@
     mFrameTimeline->addSurfaceFrame(surfaceFrame1);
     presentFence1->signalForTest(70);
 
-    mFrameTimeline->setSfPresent(59, presentFence1);
+    mFrameTimeline->setSfPresent(62, presentFence1);
+}
+
+TEST_F(FrameTimelineTest, presentFenceSignaled_reportsLongSfGpu) {
+    Fps refreshRate = Fps::fromPeriodNsecs(11);
+    EXPECT_CALL(*mTimeStats,
+                incrementJankyFrames(
+                        TimeStats::JankyFramesInfo{refreshRate, std::nullopt, sUidOne,
+                                                   sLayerNameOne,
+                                                   JankType::SurfaceFlingerGpuDeadlineMissed, 4, 10,
+                                                   0}));
+    auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
+    auto gpuFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
+    int64_t surfaceFrameToken1 = mTokenManager->generateTokenForPredictions({10, 20, 60});
+    int64_t sfToken1 = mTokenManager->generateTokenForPredictions({52, 60, 60});
+
+    auto surfaceFrame1 =
+            mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne,
+                                                       sUidOne, sLayerIdOne, sLayerNameOne,
+                                                       sLayerNameOne, /*isBuffer*/ true);
+    mFrameTimeline->setSfWakeUp(sfToken1, 52, refreshRate);
+    surfaceFrame1->setAcquireFenceTime(20);
+    surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented);
+    mFrameTimeline->addSurfaceFrame(surfaceFrame1);
+    gpuFence1->signalForTest(64);
+    presentFence1->signalForTest(70);
+
+    mFrameTimeline->setSfPresent(59, presentFence1, gpuFence1);
 }
 
 TEST_F(FrameTimelineTest, presentFenceSignaled_reportsDisplayMiss) {
@@ -512,7 +537,7 @@
     EXPECT_CALL(*mTimeStats,
                 incrementJankyFrames(TimeStats::JankyFramesInfo{refreshRate, std::nullopt, sUidOne,
                                                                 sLayerNameOne, JankType::DisplayHAL,
-                                                                -1, 0, 0}));
+                                                                -4, 0, 0}));
 
     auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
     int64_t surfaceFrameToken1 = mTokenManager->generateTokenForPredictions({10, 20, 60});
@@ -536,7 +561,7 @@
     EXPECT_CALL(*mTimeStats,
                 incrementJankyFrames(TimeStats::JankyFramesInfo{refreshRate, std::nullopt, sUidOne,
                                                                 sLayerNameOne,
-                                                                JankType::AppDeadlineMissed, -1, 0,
+                                                                JankType::AppDeadlineMissed, -4, 0,
                                                                 25}));
     auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
     int64_t surfaceFrameToken1 = mTokenManager->generateTokenForPredictions({10, 20, 60});
@@ -563,7 +588,7 @@
                 incrementJankyFrames(TimeStats::JankyFramesInfo{refreshRate, std::nullopt, sUidOne,
                                                                 sLayerNameOne,
                                                                 JankType::SurfaceFlingerScheduling,
-                                                                -1, 0, -10}));
+                                                                -4, 0, -10}));
     auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
     int64_t surfaceFrameToken1 = mTokenManager->generateTokenForPredictions({40, 60, 92});
     int64_t sfToken1 = mTokenManager->generateTokenForPredictions({52, 60, 60});
@@ -588,7 +613,7 @@
     EXPECT_CALL(*mTimeStats,
                 incrementJankyFrames(TimeStats::JankyFramesInfo{refreshRate, std::nullopt, sUidOne,
                                                                 sLayerNameOne,
-                                                                JankType::PredictionError, -1, 5,
+                                                                JankType::PredictionError, -4, 5,
                                                                 0}));
     auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
     int64_t surfaceFrameToken1 = mTokenManager->generateTokenForPredictions({30, 40, 60});
@@ -614,7 +639,7 @@
     EXPECT_CALL(*mTimeStats,
                 incrementJankyFrames(TimeStats::JankyFramesInfo{refreshRate, std::nullopt, sUidOne,
                                                                 sLayerNameOne,
-                                                                JankType::BufferStuffing, -1, 0,
+                                                                JankType::BufferStuffing, -4, 0,
                                                                 0}));
     auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
     int64_t surfaceFrameToken1 = mTokenManager->generateTokenForPredictions({30, 40, 58});
@@ -642,7 +667,7 @@
     EXPECT_CALL(*mTimeStats,
                 incrementJankyFrames(
                         TimeStats::JankyFramesInfo{refreshRate, renderRate, sUidOne, sLayerNameOne,
-                                                   JankType::AppDeadlineMissed, -1, 0, 25}));
+                                                   JankType::AppDeadlineMissed, -4, 0, 25}));
     auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
     int64_t surfaceFrameToken1 = mTokenManager->generateTokenForPredictions({10, 20, 60});
     int64_t sfToken1 = mTokenManager->generateTokenForPredictions({82, 90, 90});
@@ -671,7 +696,7 @@
                 incrementJankyFrames(
                         TimeStats::JankyFramesInfo{refreshRate, renderRate, sUidOne, sLayerNameOne,
                                                    JankType::Unknown | JankType::AppDeadlineMissed,
-                                                   -1, -1, 25}));
+                                                   0, 0, 25}));
     auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
     int64_t surfaceFrameToken1 = mTokenManager->generateTokenForPredictions({10, 20, 60});
     int64_t sfToken1 = mTokenManager->generateTokenForPredictions({82, 90, 90});
@@ -1458,24 +1483,47 @@
 }
 
 TEST_F(FrameTimelineTest, jankClassification_displayFrameLateFinishLatePresent) {
+    /*
+     * Case 1 - cpu time > vsync period but combined time > deadline > deadline -> cpudeadlinemissed
+     * Case 2 - cpu time < vsync period but combined time > deadline -> gpudeadlinemissed
+     */
     auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
+    auto presentFence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
+    auto gpuFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
+    auto gpuFence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
     int64_t sfToken1 = mTokenManager->generateTokenForPredictions({22, 26, 40});
+    int64_t sfToken2 = mTokenManager->generateTokenForPredictions({52, 60, 60});
+    // case 1 - cpu time = 33 - 12 = 21, vsync period = 11
     mFrameTimeline->setSfWakeUp(sfToken1, 12, Fps::fromPeriodNsecs(11));
-    mFrameTimeline->setSfPresent(36, presentFence1);
-    auto displayFrame = getDisplayFrame(0);
+    mFrameTimeline->setSfPresent(33, presentFence1, gpuFence1);
+    auto displayFrame0 = getDisplayFrame(0);
+    gpuFence1->signalForTest(36);
     presentFence1->signalForTest(52);
 
     // Fences haven't been flushed yet, so it should be 0
-    EXPECT_EQ(displayFrame->getActuals().presentTime, 0);
+    EXPECT_EQ(displayFrame0->getActuals().presentTime, 0);
+
+    // case 2 - cpu time = 56 - 52 = 4, vsync period = 11
+    mFrameTimeline->setSfWakeUp(sfToken2, 52, Fps::fromPeriodNsecs(11));
+    mFrameTimeline->setSfPresent(56, presentFence2, gpuFence2);
+    auto displayFrame1 = getDisplayFrame(1);
+    gpuFence2->signalForTest(66);
+    presentFence2->signalForTest(71);
+
+    EXPECT_EQ(displayFrame1->getActuals().presentTime, 0);
+    // Fences have flushed for first displayFrame, so the present timestamps should be updated
+    EXPECT_EQ(displayFrame0->getActuals().presentTime, 52);
+    EXPECT_EQ(displayFrame0->getFramePresentMetadata(), FramePresentMetadata::LatePresent);
+    EXPECT_EQ(displayFrame0->getFrameReadyMetadata(), FrameReadyMetadata::LateFinish);
+    EXPECT_EQ(displayFrame0->getJankType(), JankType::SurfaceFlingerCpuDeadlineMissed);
 
     addEmptyDisplayFrame();
-    displayFrame = getDisplayFrame(0);
 
-    // Fences have flushed, so the present timestamps should be updated
-    EXPECT_EQ(displayFrame->getActuals().presentTime, 52);
-    EXPECT_EQ(displayFrame->getFramePresentMetadata(), FramePresentMetadata::LatePresent);
-    EXPECT_EQ(displayFrame->getFrameReadyMetadata(), FrameReadyMetadata::LateFinish);
-    EXPECT_EQ(displayFrame->getJankType(), JankType::SurfaceFlingerCpuDeadlineMissed);
+    // Fences have flushed for second displayFrame, so the present timestamps should be updated
+    EXPECT_EQ(displayFrame1->getActuals().presentTime, 71);
+    EXPECT_EQ(displayFrame1->getFramePresentMetadata(), FramePresentMetadata::LatePresent);
+    EXPECT_EQ(displayFrame1->getFrameReadyMetadata(), FrameReadyMetadata::LateFinish);
+    EXPECT_EQ(displayFrame1->getJankType(), JankType::SurfaceFlingerGpuDeadlineMissed);
 }
 
 TEST_F(FrameTimelineTest, jankClassification_displayFrameLateStartLateFinishLatePresent) {
@@ -1562,7 +1610,7 @@
     EXPECT_CALL(*mTimeStats,
                 incrementJankyFrames(
                         TimeStats::JankyFramesInfo{Fps::fromPeriodNsecs(11), std::nullopt, sUidOne,
-                                                   sLayerNameOne, JankType::PredictionError, 0, 5,
+                                                   sLayerNameOne, JankType::PredictionError, -3, 5,
                                                    0}));
 
     addEmptyDisplayFrame();
@@ -1642,7 +1690,7 @@
     EXPECT_CALL(*mTimeStats,
                 incrementJankyFrames(
                         TimeStats::JankyFramesInfo{Fps::fromPeriodNsecs(11), std::nullopt, sUidOne,
-                                                   sLayerNameOne, JankType::PredictionError, 0, 5,
+                                                   sLayerNameOne, JankType::PredictionError, -3, 5,
                                                    0}));
 
     addEmptyDisplayFrame();
diff --git a/services/surfaceflinger/tests/unittests/mock/MockFrameTimeline.h b/services/surfaceflinger/tests/unittests/mock/MockFrameTimeline.h
index 5707978..5dc48c3 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockFrameTimeline.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockFrameTimeline.h
@@ -32,7 +32,9 @@
     MOCK_METHOD0(onBootFinished, void());
     MOCK_METHOD1(addSurfaceFrame, void(std::shared_ptr<frametimeline::SurfaceFrame>));
     MOCK_METHOD3(setSfWakeUp, void(int64_t, nsecs_t, Fps));
-    MOCK_METHOD3(setSfPresent, void(nsecs_t, const std::shared_ptr<FenceTime>&, bool));
+    MOCK_METHOD3(setSfPresent,
+                 void(nsecs_t, const std::shared_ptr<FenceTime>&,
+                      const std::shared_ptr<FenceTime>&));
     MOCK_METHOD1(computeFps, float(const std::unordered_set<int32_t>&));
 };