Enable SurfaceFlinger to use FrameTimeline
This change adds the necessary plumbing from SurfaceFlinger to use
FrameTimeline for the BufferQueueLayers.
Bug: 162890590
Test: libsurfaceflinger_unittest
Change-Id: Ibac00ccb6584e9eb8d06eb9682747400b3e92845
diff --git a/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp b/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp
index c95440a..a12f4c7 100644
--- a/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp
+++ b/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp
@@ -20,6 +20,7 @@
#include "FrameTimeline.h"
#include <android-base/stringprintf.h>
+#include <utils/Trace.h>
#include <cinttypes>
namespace android::frametimeline::impl {
@@ -27,6 +28,7 @@
using base::StringAppendF;
int64_t TokenManager::generateTokenForPredictions(TimelineItem&& predictions) {
+ ATRACE_CALL();
std::lock_guard<std::mutex> lock(mMutex);
const int64_t assignedToken = mCurrentToken++;
mPredictions[assignedToken] = predictions;
@@ -88,18 +90,34 @@
return mActuals;
}
-void SurfaceFrame::setActuals(frametimeline::TimelineItem&& actuals) {
+nsecs_t SurfaceFrame::getActualQueueTime() {
std::lock_guard<std::mutex> lock(mMutex);
- mActuals = actuals;
+ return mActualQueueTime;
}
-void SurfaceFrame::setPresentTime(nsecs_t presentTime) {
+void SurfaceFrame::setActualStartTime(nsecs_t actualStartTime) {
+ std::lock_guard<std::mutex> lock(mMutex);
+ mActuals.startTime = actualStartTime;
+}
+
+void SurfaceFrame::setActualQueueTime(nsecs_t actualQueueTime) {
+ std::lock_guard<std::mutex> lock(mMutex);
+ mActualQueueTime = actualQueueTime;
+}
+void SurfaceFrame::setActualEndTime(nsecs_t actualEndTime) {
+ std::lock_guard<std::mutex> lock(mMutex);
+ mActuals.endTime = actualEndTime;
+}
+
+void SurfaceFrame::setActualPresentTime(nsecs_t presentTime) {
std::lock_guard<std::mutex> lock(mMutex);
mActuals.presentTime = presentTime;
}
void SurfaceFrame::dump(std::string& result) {
std::lock_guard<std::mutex> lock(mMutex);
+ StringAppendF(&result, "Present State : %d\n", static_cast<int>(mPresentState));
+ StringAppendF(&result, "Prediction State : %d\n", static_cast<int>(mPredictionState));
StringAppendF(&result, "Predicted Start Time : %" PRId64 "\n", mPredictions.startTime);
StringAppendF(&result, "Actual Start Time : %" PRId64 "\n", mActuals.startTime);
StringAppendF(&result, "Actual Queue Time : %" PRId64 "\n", mActualQueueTime);
@@ -120,6 +138,7 @@
std::unique_ptr<android::frametimeline::SurfaceFrame> FrameTimeline::createSurfaceFrameForToken(
const std::string& layerName, std::optional<int64_t> token) {
+ ATRACE_CALL();
if (!token) {
return std::make_unique<impl::SurfaceFrame>(layerName, PredictionState::None,
TimelineItem());
@@ -136,6 +155,7 @@
void FrameTimeline::addSurfaceFrame(
std::unique_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()));
@@ -144,18 +164,21 @@
}
void FrameTimeline::setSfWakeUp(int64_t token, nsecs_t wakeUpTime) {
+ ATRACE_CALL();
const std::optional<TimelineItem> prediction = mTokenManager.getPredictionsForToken(token);
std::lock_guard<std::mutex> lock(mMutex);
if (!prediction) {
mCurrentDisplayFrame->predictionState = PredictionState::Expired;
} else {
mCurrentDisplayFrame->surfaceFlingerPredictions = *prediction;
+ mCurrentDisplayFrame->predictionState = PredictionState::Valid;
}
mCurrentDisplayFrame->surfaceFlingerActuals.startTime = wakeUpTime;
}
void FrameTimeline::setSfPresent(nsecs_t sfPresentTime,
const std::shared_ptr<FenceTime>& presentFence) {
+ ATRACE_CALL();
std::lock_guard<std::mutex> lock(mMutex);
mCurrentDisplayFrame->surfaceFlingerActuals.endTime = sfPresentTime;
mPendingPresentFences.emplace_back(std::make_pair(presentFence, mCurrentDisplayFrame));
@@ -179,7 +202,7 @@
for (auto& surfaceFrame : displayFrame->surfaceFrames) {
if (surfaceFrame->getPresentState() == SurfaceFrame::PresentState::Presented) {
// Only presented SurfaceFrames need to be updated
- surfaceFrame->setPresentTime(signalTime);
+ surfaceFrame->setActualPresentTime(signalTime);
}
}
}
@@ -204,6 +227,8 @@
StringAppendF(&result, "Number of display frames : %d\n", (int)mDisplayFrames.size());
for (const auto& displayFrame : mDisplayFrames) {
StringAppendF(&result, "---Display Frame---\n");
+ StringAppendF(&result, "Prediction State : %d\n",
+ static_cast<int>(displayFrame->predictionState));
StringAppendF(&result, "Predicted SF wake time : %" PRId64 "\n",
displayFrame->surfaceFlingerPredictions.startTime);
StringAppendF(&result, "Actual SF wake time : %" PRId64 "\n",
diff --git a/services/surfaceflinger/FrameTimeline/FrameTimeline.h b/services/surfaceflinger/FrameTimeline/FrameTimeline.h
index 291e30e..a42c32c 100644
--- a/services/surfaceflinger/FrameTimeline/FrameTimeline.h
+++ b/services/surfaceflinger/FrameTimeline/FrameTimeline.h
@@ -51,7 +51,7 @@
// Generates a token for the given set of predictions. Stores the predictions for 120ms and
// destroys it later.
- virtual int64_t generateTokenForPredictions(TimelineItem&& prediction);
+ virtual int64_t generateTokenForPredictions(TimelineItem&& prediction) = 0;
};
enum class PredictionState {
@@ -76,15 +76,18 @@
virtual TimelineItem getPredictions() = 0;
virtual TimelineItem getActuals() = 0;
+ virtual nsecs_t getActualQueueTime() = 0;
virtual PresentState getPresentState() = 0;
virtual PredictionState getPredictionState() = 0;
virtual void setPresentState(PresentState state) = 0;
- virtual void setActuals(TimelineItem&& actuals) = 0;
- // There is no prediction for Queue time and it is not a part of TimelineItem. Set it
- // separately.
+ // Actual timestamps of the app are set individually at different functions.
+ // Start time (if the app provides) and Queue time are accessible after queueing the frame,
+ // whereas End time is available only during latch.
+ virtual void setActualStartTime(nsecs_t actualStartTime) = 0;
virtual void setActualQueueTime(nsecs_t actualQueueTime) = 0;
+ virtual void setActualEndTime(nsecs_t actualEndTime) = 0;
};
/*
@@ -94,7 +97,7 @@
class FrameTimeline {
public:
virtual ~FrameTimeline() = default;
- virtual TokenManager& getTokenManager() = 0;
+ virtual TokenManager* getTokenManager() = 0;
// Create a new surface frame, set the predictions based on a token and return it to the caller.
// Sets the PredictionState of SurfaceFrame.
@@ -115,6 +118,8 @@
// that vsync.
virtual void setSfPresent(nsecs_t sfPresentTime,
const std::shared_ptr<FenceTime>& presentFence) = 0;
+
+ virtual void dump(std::string& result) = 0;
};
namespace impl {
@@ -151,14 +156,15 @@
TimelineItem getPredictions() override { return mPredictions; };
TimelineItem getActuals() override;
+ nsecs_t getActualQueueTime() override;
PresentState getPresentState() override;
PredictionState getPredictionState() override;
- void setActuals(TimelineItem&& actuals) override;
- void setActualQueueTime(nsecs_t actualQueueTime) override {
- mActualQueueTime = actualQueueTime;
- };
+
+ void setActualStartTime(nsecs_t actualStartTime) override;
+ void setActualQueueTime(nsecs_t actualQueueTime) override;
+ void setActualEndTime(nsecs_t actualEndTime) override;
void setPresentState(PresentState state) override;
- void setPresentTime(nsecs_t presentTime);
+ void setActualPresentTime(nsecs_t presentTime);
void dump(std::string& result);
private:
@@ -176,7 +182,7 @@
FrameTimeline();
~FrameTimeline() = default;
- frametimeline::TokenManager& getTokenManager() override { return mTokenManager; }
+ frametimeline::TokenManager* getTokenManager() override { return &mTokenManager; }
std::unique_ptr<frametimeline::SurfaceFrame> createSurfaceFrameForToken(
const std::string& layerName, std::optional<int64_t> token) override;
void addSurfaceFrame(std::unique_ptr<frametimeline::SurfaceFrame> surfaceFrame,
@@ -184,7 +190,7 @@
void setSfWakeUp(int64_t token, nsecs_t wakeupTime) override;
void setSfPresent(nsecs_t sfPresentTime,
const std::shared_ptr<FenceTime>& presentFence) override;
- void dump(std::string& result);
+ void dump(std::string& result) override;
private:
// Friend class for testing