Create shared timeline data structure and unit test cases

This change adds the necessary classes for the graphics shared timeline.

Bug: 162889810
Test: libsurfaceflinger_unittest --gtest_filter='FrameTimelineTest*'
Change-Id: I7310a8e0793b2d640d873814bb5a9ba83c76a196
diff --git a/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp b/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp
new file mode 100644
index 0000000..c95440a
--- /dev/null
+++ b/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp
@@ -0,0 +1,226 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#undef LOG_TAG
+#define LOG_TAG "FrameTimeline"
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+
+#include "FrameTimeline.h"
+#include <android-base/stringprintf.h>
+#include <cinttypes>
+
+namespace android::frametimeline::impl {
+
+using base::StringAppendF;
+
+int64_t TokenManager::generateTokenForPredictions(TimelineItem&& predictions) {
+    std::lock_guard<std::mutex> lock(mMutex);
+    const int64_t assignedToken = mCurrentToken++;
+    mPredictions[assignedToken] = predictions;
+    mTokens.emplace_back(std::make_pair(assignedToken, systemTime()));
+    flushTokens(systemTime());
+    return assignedToken;
+}
+
+std::optional<TimelineItem> TokenManager::getPredictionsForToken(int64_t token) {
+    std::lock_guard<std::mutex> lock(mMutex);
+    flushTokens(systemTime());
+    auto predictionsIterator = mPredictions.find(token);
+    if (predictionsIterator != mPredictions.end()) {
+        return predictionsIterator->second;
+    }
+    return {};
+}
+
+void TokenManager::flushTokens(nsecs_t flushTime) {
+    for (size_t i = 0; i < mTokens.size(); i++) {
+        if (flushTime - mTokens[i].second >= kMaxRetentionTime) {
+            mPredictions.erase(mTokens[i].first);
+            mTokens.erase(mTokens.begin() + static_cast<int>(i));
+            --i;
+        } else {
+            // Tokens are ordered by time. If i'th token is within the retention time, then the
+            // i+1'th token will also be within retention time.
+            break;
+        }
+    }
+}
+
+SurfaceFrame::SurfaceFrame(const std::string& layerName, PredictionState predictionState,
+                           frametimeline::TimelineItem&& predictions)
+      : mLayerName(layerName),
+        mPresentState(PresentState::Unknown),
+        mPredictionState(predictionState),
+        mPredictions(predictions),
+        mActuals({0, 0, 0}),
+        mActualQueueTime(0) {}
+
+void SurfaceFrame::setPresentState(PresentState state) {
+    std::lock_guard<std::mutex> lock(mMutex);
+    mPresentState = state;
+}
+
+PredictionState SurfaceFrame::getPredictionState() {
+    std::lock_guard<std::mutex> lock(mMutex);
+    return mPredictionState;
+}
+
+SurfaceFrame::PresentState SurfaceFrame::getPresentState() {
+    std::lock_guard<std::mutex> lock(mMutex);
+    return mPresentState;
+}
+
+TimelineItem SurfaceFrame::getActuals() {
+    std::lock_guard<std::mutex> lock(mMutex);
+    return mActuals;
+}
+
+void SurfaceFrame::setActuals(frametimeline::TimelineItem&& actuals) {
+    std::lock_guard<std::mutex> lock(mMutex);
+    mActuals = actuals;
+}
+
+void SurfaceFrame::setPresentTime(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, "Predicted Start Time : %" PRId64 "\n", mPredictions.startTime);
+    StringAppendF(&result, "Actual Start Time : %" PRId64 "\n", mActuals.startTime);
+    StringAppendF(&result, "Actual Queue Time : %" PRId64 "\n", mActualQueueTime);
+    StringAppendF(&result, "Predicted Render Complete Time : %" PRId64 "\n", mPredictions.endTime);
+    StringAppendF(&result, "Actual Render Complete Time : %" PRId64 "\n", mActuals.endTime);
+    StringAppendF(&result, "Predicted Present Time : %" PRId64 "\n", mPredictions.presentTime);
+    StringAppendF(&result, "Actual Present Time : %" PRId64 "\n", mActuals.presentTime);
+}
+
+FrameTimeline::FrameTimeline() : mCurrentDisplayFrame(std::make_shared<DisplayFrame>()) {}
+
+FrameTimeline::DisplayFrame::DisplayFrame()
+      : surfaceFlingerPredictions(TimelineItem()),
+        surfaceFlingerActuals(TimelineItem()),
+        predictionState(PredictionState::None) {
+    this->surfaceFrames.reserve(kNumSurfaceFramesInitial);
+}
+
+std::unique_ptr<android::frametimeline::SurfaceFrame> FrameTimeline::createSurfaceFrameForToken(
+        const std::string& layerName, std::optional<int64_t> token) {
+    if (!token) {
+        return std::make_unique<impl::SurfaceFrame>(layerName, PredictionState::None,
+                                                    TimelineItem());
+    }
+    std::optional<TimelineItem> predictions = mTokenManager.getPredictionsForToken(*token);
+    if (predictions) {
+        return std::make_unique<impl::SurfaceFrame>(layerName, PredictionState::Valid,
+                                                    std::move(*predictions));
+    }
+    return std::make_unique<impl::SurfaceFrame>(layerName, PredictionState::Expired,
+                                                TimelineItem());
+}
+
+void FrameTimeline::addSurfaceFrame(
+        std::unique_ptr<android::frametimeline::SurfaceFrame> surfaceFrame,
+        SurfaceFrame::PresentState state) {
+    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));
+}
+
+void FrameTimeline::setSfWakeUp(int64_t token, nsecs_t wakeUpTime) {
+    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->surfaceFlingerActuals.startTime = wakeUpTime;
+}
+
+void FrameTimeline::setSfPresent(nsecs_t sfPresentTime,
+                                 const std::shared_ptr<FenceTime>& presentFence) {
+    std::lock_guard<std::mutex> lock(mMutex);
+    mCurrentDisplayFrame->surfaceFlingerActuals.endTime = sfPresentTime;
+    mPendingPresentFences.emplace_back(std::make_pair(presentFence, mCurrentDisplayFrame));
+    flushPendingPresentFences();
+    finalizeCurrentDisplayFrame();
+}
+
+void FrameTimeline::flushPendingPresentFences() {
+    for (size_t i = 0; i < mPendingPresentFences.size(); i++) {
+        const auto& pendingPresentFence = mPendingPresentFences[i];
+        nsecs_t signalTime = Fence::SIGNAL_TIME_INVALID;
+        if (pendingPresentFence.first && pendingPresentFence.first->isValid()) {
+            signalTime = pendingPresentFence.first->getSignalTime();
+            if (signalTime == Fence::SIGNAL_TIME_PENDING) {
+                continue;
+            }
+        }
+        if (signalTime != Fence::SIGNAL_TIME_INVALID) {
+            auto& displayFrame = pendingPresentFence.second;
+            displayFrame->surfaceFlingerActuals.presentTime = signalTime;
+            for (auto& surfaceFrame : displayFrame->surfaceFrames) {
+                if (surfaceFrame->getPresentState() == SurfaceFrame::PresentState::Presented) {
+                    // Only presented SurfaceFrames need to be updated
+                    surfaceFrame->setPresentTime(signalTime);
+                }
+            }
+        }
+
+        mPendingPresentFences.erase(mPendingPresentFences.begin() + static_cast<int>(i));
+        --i;
+    }
+}
+
+void FrameTimeline::finalizeCurrentDisplayFrame() {
+    while (mDisplayFrames.size() >= kMaxDisplayFrames) {
+        // We maintain only a fixed number of frames' data. Pop older frames
+        mDisplayFrames.pop_front();
+    }
+    mDisplayFrames.push_back(mCurrentDisplayFrame);
+    mCurrentDisplayFrame.reset();
+    mCurrentDisplayFrame = std::make_shared<DisplayFrame>();
+}
+
+void FrameTimeline::dump(std::string& result) {
+    std::lock_guard<std::mutex> lock(mMutex);
+    StringAppendF(&result, "Number of display frames : %d\n", (int)mDisplayFrames.size());
+    for (const auto& displayFrame : mDisplayFrames) {
+        StringAppendF(&result, "---Display Frame---\n");
+        StringAppendF(&result, "Predicted SF wake time : %" PRId64 "\n",
+                      displayFrame->surfaceFlingerPredictions.startTime);
+        StringAppendF(&result, "Actual SF wake time : %" PRId64 "\n",
+                      displayFrame->surfaceFlingerActuals.startTime);
+        StringAppendF(&result, "Predicted SF Complete time : %" PRId64 "\n",
+                      displayFrame->surfaceFlingerPredictions.endTime);
+        StringAppendF(&result, "Actual SF Complete time : %" PRId64 "\n",
+                      displayFrame->surfaceFlingerActuals.endTime);
+        StringAppendF(&result, "Predicted Present time : %" PRId64 "\n",
+                      displayFrame->surfaceFlingerPredictions.presentTime);
+        StringAppendF(&result, "Actual Present time : %" PRId64 "\n",
+                      displayFrame->surfaceFlingerActuals.presentTime);
+        for (size_t i = 0; i < displayFrame->surfaceFrames.size(); i++) {
+            StringAppendF(&result, "Surface frame - %" PRId32 "\n", (int)i);
+            displayFrame->surfaceFrames[i]->dump(result);
+        }
+    }
+}
+
+} // namespace android::frametimeline::impl