Frame Timeline Perfetto producer

This change adds a Perfetto Producer inside FrameTimeline that emits
DisplayFrame and SurfaceFrame as TracePackets as per the proto defined
in frame_timeline_event.proto
This change also adds a MockFrameTimeline to be used in unittests as a
part of TestableSurfaceFlinger. Due to perfetto capability, running
production FrameTimeline in TestableSurfaceFlinger has caused issues and
its best to isolate them.

Bug: 170914689
Test: libsurfaceflinger_unittest (whole test suite without filter)

Change-Id: Iabd5521629d16ded6ba3f165229caa74b1cb8eb7
diff --git a/services/surfaceflinger/FrameTimeline/Android.bp b/services/surfaceflinger/FrameTimeline/Android.bp
index e075d3e..1e6d21e 100644
--- a/services/surfaceflinger/FrameTimeline/Android.bp
+++ b/services/surfaceflinger/FrameTimeline/Android.bp
@@ -14,5 +14,8 @@
         "libui",
         "libutils",
     ],
+    static_libs: [
+        "libperfetto_client_experimental",
+    ],
     export_include_dirs: ["."],
 }
diff --git a/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp b/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp
index bd87482..ef5f5ad 100644
--- a/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp
+++ b/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp
@@ -29,6 +29,7 @@
 namespace android::frametimeline::impl {
 
 using base::StringAppendF;
+using FrameTimelineEvent = perfetto::protos::pbzero::FrameTimelineEvent;
 
 void dumpTable(std::string& result, TimelineItem predictions, TimelineItem actuals,
                const std::string& indent, PredictionState predictionState, nsecs_t baseTime) {
@@ -143,6 +144,32 @@
                            });
 }
 
+FrameTimelineEvent::PresentType presentTypeToProto(int32_t jankMetadata) {
+    if (jankMetadata & EarlyPresent) {
+        return FrameTimelineEvent::PRESENT_EARLY;
+    }
+    if (jankMetadata & LatePresent) {
+        return FrameTimelineEvent::PRESENT_LATE;
+    }
+    return FrameTimelineEvent::PRESENT_ON_TIME;
+}
+
+FrameTimelineEvent::JankType JankTypeToProto(TimeStats::JankType jankType) {
+    switch (jankType) {
+        case TimeStats::None:
+            return FrameTimelineEvent::JANK_NONE;
+        case TimeStats::Display:
+            return FrameTimelineEvent::JANK_DISPLAY_HAL;
+        case TimeStats::SurfaceFlingerDeadlineMissed:
+            return FrameTimelineEvent::JANK_SF_DEADLINE_MISSED;
+        case TimeStats::AppDeadlineMissed:
+        case TimeStats::PredictionExpired:
+            return FrameTimelineEvent::JANK_APP_DEADLINE_MISSED;
+        default:
+            return FrameTimelineEvent::JANK_UNKNOWN;
+    }
+}
+
 int64_t TokenManager::generateTokenForPredictions(TimelineItem&& predictions) {
     ATRACE_CALL();
     std::lock_guard<std::mutex> lock(mMutex);
@@ -177,10 +204,11 @@
     }
 }
 
-SurfaceFrame::SurfaceFrame(pid_t ownerPid, uid_t ownerUid, std::string layerName,
+SurfaceFrame::SurfaceFrame(int64_t token, pid_t ownerPid, uid_t ownerUid, std::string layerName,
                            std::string debugName, PredictionState predictionState,
                            frametimeline::TimelineItem&& predictions)
-      : mOwnerPid(ownerPid),
+      : mToken(token),
+        mOwnerPid(ownerPid),
         mOwnerUid(ownerUid),
         mLayerName(std::move(layerName)),
         mDebugName(std::move(debugName)),
@@ -291,17 +319,70 @@
     dumpTable(result, mPredictions, mActuals, indent, mPredictionState, baseTime);
 }
 
+void SurfaceFrame::traceSurfaceFrame(int64_t displayFrameToken) {
+    using FrameTimelineDataSource = FrameTimeline::FrameTimelineDataSource;
+    FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
+        std::lock_guard<std::mutex> lock(mMutex);
+        if (mToken == ISurfaceComposer::INVALID_VSYNC_ID) {
+            ALOGD("Cannot trace SurfaceFrame - %s with invalid token", mLayerName.c_str());
+            return;
+        } else if (displayFrameToken == ISurfaceComposer::INVALID_VSYNC_ID) {
+            ALOGD("Cannot trace SurfaceFrame  - %s with invalid displayFrameToken",
+                  mLayerName.c_str());
+            return;
+        }
+        auto packet = ctx.NewTracePacket();
+        packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC);
+        packet->set_timestamp(static_cast<uint64_t>(systemTime()));
+
+        auto* event = packet->set_frame_timeline_event();
+        auto* surfaceFrameEvent = event->set_surface_frame();
+
+        surfaceFrameEvent->set_token(mToken);
+        surfaceFrameEvent->set_display_frame_token(displayFrameToken);
+
+        if (mPresentState == PresentState::Dropped) {
+            surfaceFrameEvent->set_present_type(FrameTimelineEvent::PRESENT_DROPPED);
+        } else if (mPresentState == PresentState::Unknown) {
+            surfaceFrameEvent->set_present_type(FrameTimelineEvent::PRESENT_UNSPECIFIED);
+        } else {
+            surfaceFrameEvent->set_present_type(presentTypeToProto(mJankMetadata));
+        }
+        surfaceFrameEvent->set_on_time_finish(!(mJankMetadata & LateFinish));
+        surfaceFrameEvent->set_gpu_composition(mJankMetadata & GpuComposition);
+        surfaceFrameEvent->set_jank_type(JankTypeToProto(mJankType));
+
+        surfaceFrameEvent->set_expected_start_ns(mPredictions.startTime);
+        surfaceFrameEvent->set_expected_end_ns(mPredictions.endTime);
+
+        surfaceFrameEvent->set_actual_start_ns(mActuals.startTime);
+        surfaceFrameEvent->set_actual_end_ns(mActuals.endTime);
+
+        surfaceFrameEvent->set_layer_name(mDebugName);
+        surfaceFrameEvent->set_pid(mOwnerPid);
+    });
+}
+
 FrameTimeline::FrameTimeline(std::shared_ptr<TimeStats> timeStats)
       : mCurrentDisplayFrame(std::make_shared<DisplayFrame>()),
         mMaxDisplayFrames(kDefaultMaxDisplayFrames),
         mTimeStats(std::move(timeStats)) {}
 
+void FrameTimeline::onBootFinished() {
+    perfetto::TracingInitArgs args;
+    args.backends = perfetto::kSystemBackend;
+    perfetto::Tracing::Initialize(args);
+    registerDataSource();
+}
+
+void FrameTimeline::registerDataSource() {
+    perfetto::DataSourceDescriptor dsd;
+    dsd.set_name(kFrameTimelineDataSource);
+    FrameTimelineDataSource::Register(dsd);
+}
+
 FrameTimeline::DisplayFrame::DisplayFrame()
-      : surfaceFlingerPredictions(TimelineItem()),
-        surfaceFlingerActuals(TimelineItem()),
-        predictionState(PredictionState::None),
-        jankType(TimeStats::JankType::None),
-        jankMetadata(0) {
+      : surfaceFlingerPredictions(TimelineItem()), surfaceFlingerActuals(TimelineItem()) {
     this->surfaceFrames.reserve(kNumSurfaceFramesInitial);
 }
 
@@ -310,17 +391,19 @@
         std::optional<int64_t> token) {
     ATRACE_CALL();
     if (!token) {
-        return std::make_unique<impl::SurfaceFrame>(ownerPid, ownerUid, std::move(layerName),
+        return std::make_unique<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>(ownerPid, ownerUid, std::move(layerName),
-                                                    std::move(debugName), PredictionState::Valid,
+        return std::make_unique<impl::SurfaceFrame>(*token, ownerPid, ownerUid,
+                                                    std::move(layerName), std::move(debugName),
+                                                    PredictionState::Valid,
                                                     std::move(*predictions));
     }
-    return std::make_unique<impl::SurfaceFrame>(ownerPid, ownerUid, std::move(layerName),
+    return std::make_unique<impl::SurfaceFrame>(*token, ownerPid, ownerUid, std::move(layerName),
                                                 std::move(debugName), PredictionState::Expired,
                                                 TimelineItem());
 }
@@ -340,6 +423,7 @@
     ATRACE_CALL();
     const std::optional<TimelineItem> prediction = mTokenManager.getPredictionsForToken(token);
     std::lock_guard<std::mutex> lock(mMutex);
+    mCurrentDisplayFrame->token = token;
     if (!prediction) {
         mCurrentDisplayFrame->predictionState = PredictionState::Expired;
     } else {
@@ -408,6 +492,7 @@
             }
 
             totalJankReasons |= displayFrame->jankType;
+            traceDisplayFrame(*displayFrame);
 
             for (auto& surfaceFrame : displayFrame->surfaceFrames) {
                 if (surfaceFrame->getPresentState() == SurfaceFrame::PresentState::Presented) {
@@ -419,7 +504,6 @@
                     if (predictionState == PredictionState::Expired) {
                         // Jank analysis cannot be done on apps that don't use predictions
                         surfaceFrame->setJankInfo(TimeStats::JankType::PredictionExpired, 0);
-                        continue;
                     } else if (predictionState == PredictionState::Valid) {
                         const auto& actuals = surfaceFrame->getActuals();
                         const auto& predictions = surfaceFrame->getPredictions();
@@ -453,6 +537,7 @@
                         surfaceFrame->setJankInfo(jankType, jankMetadata);
                     }
                 }
+                surfaceFrame->traceSurfaceFrame(displayFrame->token);
             }
 
             mTimeStats->incrementJankyFrames(totalJankReasons);
@@ -569,4 +654,31 @@
     setMaxDisplayFrames(kDefaultMaxDisplayFrames);
 }
 
+void FrameTimeline::traceDisplayFrame(const DisplayFrame& displayFrame) {
+    FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
+        if (displayFrame.token == ISurfaceComposer::INVALID_VSYNC_ID) {
+            ALOGD("Cannot trace DisplayFrame with invalid token");
+            return;
+        }
+        auto packet = ctx.NewTracePacket();
+        packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC);
+        packet->set_timestamp(static_cast<uint64_t>(systemTime()));
+
+        auto* event = packet->set_frame_timeline_event();
+        auto* displayFrameEvent = event->set_display_frame();
+
+        displayFrameEvent->set_token(displayFrame.token);
+        displayFrameEvent->set_present_type(presentTypeToProto(displayFrame.jankMetadata));
+        displayFrameEvent->set_on_time_finish(!(displayFrame.jankMetadata & LateFinish));
+        displayFrameEvent->set_gpu_composition(displayFrame.jankMetadata & GpuComposition);
+        displayFrameEvent->set_jank_type(JankTypeToProto(displayFrame.jankType));
+
+        displayFrameEvent->set_expected_start_ns(displayFrame.surfaceFlingerPredictions.startTime);
+        displayFrameEvent->set_expected_end_ns(displayFrame.surfaceFlingerPredictions.endTime);
+
+        displayFrameEvent->set_actual_start_ns(displayFrame.surfaceFlingerActuals.startTime);
+        displayFrameEvent->set_actual_end_ns(displayFrame.surfaceFlingerActuals.endTime);
+    });
+}
+
 } // namespace android::frametimeline::impl
diff --git a/services/surfaceflinger/FrameTimeline/FrameTimeline.h b/services/surfaceflinger/FrameTimeline/FrameTimeline.h
index e61567e..9a74d50 100644
--- a/services/surfaceflinger/FrameTimeline/FrameTimeline.h
+++ b/services/surfaceflinger/FrameTimeline/FrameTimeline.h
@@ -18,6 +18,8 @@
 
 #include <../TimeStats/TimeStats.h>
 #include <gui/ISurfaceComposer.h>
+#include <perfetto/trace/android/frame_timeline_event.pbzero.h>
+#include <perfetto/tracing.h>
 #include <ui/FenceTime.h>
 #include <utils/RefBase.h>
 #include <utils/String16.h>
@@ -128,6 +130,10 @@
     virtual ~FrameTimeline() = default;
     virtual TokenManager* getTokenManager() = 0;
 
+    // Initializes the Perfetto DataSource that emits DisplayFrame and SurfaceFrame events. Test
+    // classes can avoid double registration by mocking this function.
+    virtual void onBootFinished() = 0;
+
     // 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.
@@ -191,8 +197,9 @@
 
 class SurfaceFrame : public android::frametimeline::SurfaceFrame {
 public:
-    SurfaceFrame(pid_t ownerPid, uid_t ownerUid, std::string layerName, std::string debugName,
-                 PredictionState predictionState, TimelineItem&& predictions);
+    SurfaceFrame(int64_t token, pid_t ownerPid, uid_t ownerUid, std::string layerName,
+                 std::string debugName, PredictionState predictionState,
+                 TimelineItem&& predictions);
     ~SurfaceFrame() = default;
 
     TimelineItem getPredictions() const override { return mPredictions; };
@@ -202,6 +209,7 @@
     PredictionState getPredictionState() const override { return mPredictionState; };
     pid_t getOwnerPid() const override { return mOwnerPid; };
     TimeStats::JankType getJankType() const;
+    int64_t getToken() const { return mToken; };
     nsecs_t getBaseTime() const;
     uid_t getOwnerUid() const { return mOwnerUid; };
     const std::string& getName() const { return mLayerName; };
@@ -216,7 +224,13 @@
     // All the timestamps are dumped relative to the baseTime
     void dump(std::string& result, const std::string& indent, nsecs_t baseTime);
 
+    // Emits a packet for perfetto tracing. The function body will be executed only if tracing is
+    // enabled. The displayFrameToken is needed to link the SurfaceFrame to the corresponding
+    // DisplayFrame at the trace processor side.
+    void traceSurfaceFrame(int64_t displayFrameToken);
+
 private:
+    const int64_t mToken;
     const pid_t mOwnerPid;
     const uid_t mOwnerUid;
     const std::string mLayerName;
@@ -233,6 +247,12 @@
 
 class FrameTimeline : public android::frametimeline::FrameTimeline {
 public:
+    class FrameTimelineDataSource : public perfetto::DataSource<FrameTimelineDataSource> {
+        void OnSetup(const SetupArgs&) override{};
+        void OnStart(const StartArgs&) override{};
+        void OnStop(const StopArgs&) override{};
+    };
+
     FrameTimeline(std::shared_ptr<TimeStats> timeStats);
     ~FrameTimeline() = default;
 
@@ -249,6 +269,14 @@
     void setMaxDisplayFrames(uint32_t size) override;
     void reset() override;
 
+    // Sets up the perfetto tracing backend and data source.
+    void onBootFinished() override;
+    // Registers the data source with the perfetto backend. Called as part of onBootFinished()
+    // and should not be called manually outside of tests.
+    void registerDataSource();
+
+    static constexpr char kFrameTimelineDataSource[] = "android.surfaceflinger.frametimeline";
+
 private:
     // Friend class for testing
     friend class android::frametimeline::FrameTimelineTest;
@@ -259,6 +287,8 @@
     struct DisplayFrame {
         DisplayFrame();
 
+        int64_t token = ISurfaceComposer::INVALID_VSYNC_ID;
+
         /* Usage of TimelineItem w.r.t SurfaceFlinger
          * startTime    Time when SurfaceFlinger wakes up to handle transactions and buffer updates
          * endTime      Time when SurfaceFlinger sends a composited frame to Display
@@ -270,9 +300,9 @@
         // Collection of predictions and actual values sent over by Layers
         std::vector<std::unique_ptr<SurfaceFrame>> surfaceFrames;
 
-        PredictionState predictionState;
+        PredictionState predictionState = PredictionState::None;
         TimeStats::JankType jankType = TimeStats::JankType::None; // Enum for the type of jank
-        int32_t jankMetadata = 0x0;         // Additional details about the jank
+        int32_t jankMetadata = 0x0; // Additional details about the jank
     };
 
     void flushPendingPresentFences() REQUIRES(mMutex);
@@ -285,6 +315,10 @@
     void dumpAll(std::string& result);
     void dumpJank(std::string& result);
 
+    // Emits a packet for perfetto tracing. The function body will be executed only if tracing is
+    // enabled.
+    void traceDisplayFrame(const DisplayFrame& displayFrame) REQUIRES(mMutex);
+
     // Sliding window of display frames. TODO(b/168072834): compare perf with fixed size array
     std::deque<std::shared_ptr<DisplayFrame>> mDisplayFrames GUARDED_BY(mMutex);
     std::vector<std::pair<std::shared_ptr<FenceTime>, std::shared_ptr<DisplayFrame>>>
@@ -295,10 +329,10 @@
     uint32_t mMaxDisplayFrames;
     std::shared_ptr<TimeStats> mTimeStats;
     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 display
-    // frame, this is a good starting size for the vector so that we can avoid the internal vector
-    // resizing that happens with push_back.
+    // 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
+    // display frame, this is a good starting size for the vector so that we can avoid the
+    // internal vector resizing that happens with push_back.
     static constexpr uint32_t kNumSurfaceFramesInitial = 10;
     // The various thresholds for App and SF. If the actual timestamp falls within the threshold
     // compared to prediction, we don't treat it as a jank.