Merge "SF: Move/Refactor doComposition and doDisplayComposition to CompositionEngine"
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index 438f8f3..51bf78a 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -139,6 +139,7 @@
         "DisplayHardware/VirtualDisplaySurface.cpp",
         "Effects/Daltonizer.cpp",
         "EventLog/EventLog.cpp",
+        "FrameTracer/FrameTracer.cpp",
         "FrameTracker.cpp",
         "Layer.cpp",
         "LayerProtoHelper.cpp",
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index a8bdb79..90a02b3 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -51,6 +51,7 @@
 
 #include "Colorizer.h"
 #include "DisplayDevice.h"
+#include "FrameTracer/FrameTracer.h"
 #include "LayerRejecter.h"
 #include "TimeStats/TimeStats.h"
 
@@ -71,7 +72,9 @@
 
 BufferLayer::~BufferLayer() {
     mFlinger->deleteTextureAsync(mTextureName);
-    mFlinger->mTimeStats->onDestroy(getSequence());
+    const int32_t layerID = getSequence();
+    mFlinger->mTimeStats->onDestroy(layerID);
+    mFlinger->mFrameTracer->onDestroy(layerID);
 }
 
 void BufferLayer::useSurfaceDamage() {
@@ -314,17 +317,17 @@
 
     if (presentFence->isValid()) {
         mFlinger->mTimeStats->setPresentFence(layerID, mCurrentFrameNumber, presentFence);
-        mFlinger->mTimeStats->traceFence(layerID, getCurrentBufferId(), mCurrentFrameNumber,
-                                         presentFence, TimeStats::FrameEvent::PRESENT_FENCE);
+        mFlinger->mFrameTracer->traceFence(layerID, getCurrentBufferId(), mCurrentFrameNumber,
+                                           presentFence, FrameTracer::FrameEvent::PRESENT_FENCE);
         mFrameTracker.setActualPresentFence(std::shared_ptr<FenceTime>(presentFence));
     } else if (displayId && mFlinger->getHwComposer().isConnected(*displayId)) {
         // The HWC doesn't support present fences, so use the refresh
         // timestamp instead.
         const nsecs_t actualPresentTime = mFlinger->getHwComposer().getRefreshTimestamp(*displayId);
         mFlinger->mTimeStats->setPresentTime(layerID, mCurrentFrameNumber, actualPresentTime);
-        mFlinger->mTimeStats->traceTimestamp(layerID, getCurrentBufferId(), mCurrentFrameNumber,
-                                             actualPresentTime,
-                                             TimeStats::FrameEvent::PRESENT_FENCE);
+        mFlinger->mFrameTracer->traceTimestamp(layerID, getCurrentBufferId(), mCurrentFrameNumber,
+                                               actualPresentTime,
+                                               FrameTracer::FrameEvent::PRESENT_FENCE);
         mFrameTracker.setActualPresentTime(actualPresentTime);
     }
 
diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp
index 6cad3c7..4da39e4 100644
--- a/services/surfaceflinger/BufferQueueLayer.cpp
+++ b/services/surfaceflinger/BufferQueueLayer.cpp
@@ -29,6 +29,7 @@
 #include "LayerRejecter.h"
 #include "SurfaceInterceptor.h"
 
+#include "FrameTracer/FrameTracer.h"
 #include "TimeStats/TimeStats.h"
 
 namespace android {
@@ -48,9 +49,9 @@
 
     // Prevent tracing the same release multiple times.
     if (mPreviousFrameNumber != mPreviousReleasedFrameNumber) {
-        mFlinger->mTimeStats->traceFence(getSequence(), mPreviousBufferId, mPreviousFrameNumber,
-                                         std::make_shared<FenceTime>(releaseFence),
-                                         TimeStats::FrameEvent::RELEASE_FENCE);
+        mFlinger->mFrameTracer->traceFence(getSequence(), mPreviousBufferId, mPreviousFrameNumber,
+                                           std::make_shared<FenceTime>(releaseFence),
+                                           FrameTracer::FrameEvent::RELEASE_FENCE);
         mPreviousReleasedFrameNumber = mPreviousFrameNumber;
     }
 }
@@ -337,6 +338,7 @@
             mQueueItems.clear();
             mQueuedFrames = 0;
             mFlinger->mTimeStats->onDestroy(layerID);
+            mFlinger->mFrameTracer->onDestroy(layerID);
         }
 
         // Once we have hit this state, the shadow queue may no longer
@@ -366,12 +368,12 @@
         uint64_t bufferID = mQueueItems[0].mGraphicBuffer->getId();
         mFlinger->mTimeStats->setAcquireFence(layerID, currentFrameNumber,
                                               mQueueItems[0].mFenceTime);
-        mFlinger->mTimeStats->traceFence(layerID, bufferID, currentFrameNumber,
-                                         mQueueItems[0].mFenceTime,
-                                         TimeStats::FrameEvent::ACQUIRE_FENCE);
+        mFlinger->mFrameTracer->traceFence(layerID, bufferID, currentFrameNumber,
+                                           mQueueItems[0].mFenceTime,
+                                           FrameTracer::FrameEvent::ACQUIRE_FENCE);
         mFlinger->mTimeStats->setLatchTime(layerID, currentFrameNumber, latchTime);
-        mFlinger->mTimeStats->traceTimestamp(layerID, bufferID, currentFrameNumber, latchTime,
-                                             TimeStats::FrameEvent::LATCH);
+        mFlinger->mFrameTracer->traceTimestamp(layerID, bufferID, currentFrameNumber, latchTime,
+                                               FrameTracer::FrameEvent::LATCH);
 
         mQueueItems.removeAt(0);
     }
@@ -429,9 +431,9 @@
 
 void BufferQueueLayer::onFrameAvailable(const BufferItem& item) {
     const int32_t layerID = getSequence();
-    mFlinger->mTimeStats->traceNewLayer(layerID, getName().c_str());
-    mFlinger->mTimeStats->traceTimestamp(layerID, item.mGraphicBuffer->getId(), item.mFrameNumber,
-                                         systemTime(), TimeStats::FrameEvent::POST);
+    mFlinger->mFrameTracer->traceNewLayer(layerID, getName().c_str());
+    mFlinger->mFrameTracer->traceTimestamp(layerID, item.mGraphicBuffer->getId(), item.mFrameNumber,
+                                           systemTime(), FrameTracer::FrameEvent::POST);
 
     ATRACE_CALL();
     // Add this buffer from our internal queue tracker
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index 4a8261d..e7d1b63 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -32,6 +32,7 @@
 
 #include "BufferStateLayer.h"
 #include "ColorLayer.h"
+#include "FrameTracer/FrameTracer.h"
 #include "TimeStats/TimeStats.h"
 
 namespace android {
@@ -90,9 +91,9 @@
 
     // Prevent tracing the same release multiple times.
     if (mPreviousFrameNumber != mPreviousReleasedFrameNumber) {
-        mFlinger->mTimeStats->traceFence(getSequence(), mPreviousBufferId, mPreviousFrameNumber,
-                                         std::make_shared<FenceTime>(releaseFence),
-                                         TimeStats::FrameEvent::RELEASE_FENCE);
+        mFlinger->mFrameTracer->traceFence(getSequence(), mPreviousBufferId, mPreviousFrameNumber,
+                                           std::make_shared<FenceTime>(releaseFence),
+                                           FrameTracer::FrameEvent::RELEASE_FENCE);
         mPreviousReleasedFrameNumber = mPreviousFrameNumber;
     }
 }
@@ -236,9 +237,9 @@
 
     const int32_t layerID = getSequence();
     mFlinger->mTimeStats->setPostTime(layerID, mFrameNumber, getName().c_str(), postTime);
-    mFlinger->mTimeStats->traceNewLayer(layerID, getName().c_str());
-    mFlinger->mTimeStats->traceTimestamp(layerID, buffer->getId(), mFrameNumber, postTime,
-                                         TimeStats::FrameEvent::POST);
+    mFlinger->mFrameTracer->traceNewLayer(layerID, getName().c_str());
+    mFlinger->mFrameTracer->traceTimestamp(layerID, buffer->getId(), mFrameNumber, postTime,
+                                           FrameTracer::FrameEvent::POST);
     mCurrentState.desiredPresentTime = desiredPresentTime;
 
     if (mFlinger->mUseSmart90ForVideo) {
@@ -569,17 +570,18 @@
         status_t err = bindTextureImage();
         if (err != NO_ERROR) {
             mFlinger->mTimeStats->onDestroy(layerID);
+            mFlinger->mFrameTracer->onDestroy(layerID);
             return BAD_VALUE;
         }
     }
 
     const uint64_t bufferID = getCurrentBufferId();
     mFlinger->mTimeStats->setAcquireFence(layerID, mFrameNumber, getCurrentFenceTime());
-    mFlinger->mTimeStats->traceFence(layerID, bufferID, mFrameNumber, getCurrentFenceTime(),
-                                     TimeStats::FrameEvent::ACQUIRE_FENCE);
+    mFlinger->mFrameTracer->traceFence(layerID, bufferID, mFrameNumber, getCurrentFenceTime(),
+                                       FrameTracer::FrameEvent::ACQUIRE_FENCE);
     mFlinger->mTimeStats->setLatchTime(layerID, mFrameNumber, latchTime);
-    mFlinger->mTimeStats->traceTimestamp(layerID, bufferID, mFrameNumber, latchTime,
-                                         TimeStats::FrameEvent::LATCH);
+    mFlinger->mFrameTracer->traceTimestamp(layerID, bufferID, mFrameNumber, latchTime,
+                                           FrameTracer::FrameEvent::LATCH);
 
     mCurrentStateModified = false;
 
diff --git a/services/surfaceflinger/FrameTracer/FrameTracer.cpp b/services/surfaceflinger/FrameTracer/FrameTracer.cpp
new file mode 100644
index 0000000..7cbb8d8
--- /dev/null
+++ b/services/surfaceflinger/FrameTracer/FrameTracer.cpp
@@ -0,0 +1,173 @@
+/*
+ * Copyright 2019 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 "FrameTracer"
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+
+#include "FrameTracer.h"
+
+#include <android-base/stringprintf.h>
+
+#include <algorithm>
+
+PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(android::FrameTracer::FrameTracerDataSource);
+
+namespace android {
+
+void FrameTracer::initialize() {
+    perfetto::TracingInitArgs args;
+    args.backends = perfetto::kSystemBackend;
+    perfetto::Tracing::Initialize(args);
+    registerDataSource();
+}
+
+void FrameTracer::registerDataSource() {
+    perfetto::DataSourceDescriptor dsd;
+    dsd.set_name(kFrameTracerDataSource);
+    FrameTracerDataSource::Register(dsd);
+}
+
+void FrameTracer::traceNewLayer(int32_t layerID, const std::string& layerName) {
+    FrameTracerDataSource::Trace([this, layerID, &layerName](FrameTracerDataSource::TraceContext) {
+        if (mTraceTracker.find(layerID) == mTraceTracker.end()) {
+            std::lock_guard<std::mutex> lock(mTraceMutex);
+            mTraceTracker[layerID].layerName = layerName;
+        }
+    });
+}
+
+void FrameTracer::traceTimestamp(int32_t layerID, uint64_t bufferID, uint64_t frameNumber,
+                                 nsecs_t timestamp, FrameEvent::BufferEventType type,
+                                 nsecs_t duration) {
+    FrameTracerDataSource::Trace([this, layerID, bufferID, frameNumber, timestamp, type,
+                                  duration](FrameTracerDataSource::TraceContext ctx) {
+        std::lock_guard<std::mutex> lock(mTraceMutex);
+        if (mTraceTracker.find(layerID) == mTraceTracker.end()) {
+            return;
+        }
+
+        // Handle any pending fences for this buffer.
+        tracePendingFencesLocked(ctx, layerID, bufferID);
+
+        // Complete current trace.
+        traceLocked(ctx, layerID, bufferID, frameNumber, timestamp, type, duration);
+    });
+}
+
+void FrameTracer::traceFence(int32_t layerID, uint64_t bufferID, uint64_t frameNumber,
+                             const std::shared_ptr<FenceTime>& fence,
+                             FrameEvent::BufferEventType type, nsecs_t startTime) {
+    FrameTracerDataSource::Trace([this, layerID, bufferID, frameNumber, &fence, type,
+                                  startTime](FrameTracerDataSource::TraceContext ctx) {
+        const nsecs_t signalTime = fence->getSignalTime();
+        if (signalTime != Fence::SIGNAL_TIME_INVALID) {
+            std::lock_guard<std::mutex> lock(mTraceMutex);
+            if (mTraceTracker.find(layerID) == mTraceTracker.end()) {
+                return;
+            }
+
+            // Handle any pending fences for this buffer.
+            tracePendingFencesLocked(ctx, layerID, bufferID);
+
+            if (signalTime != Fence::SIGNAL_TIME_PENDING) {
+                traceSpanLocked(ctx, layerID, bufferID, frameNumber, type, startTime, signalTime);
+            } else {
+                mTraceTracker[layerID].pendingFences[bufferID].push_back(
+                        {.frameNumber = frameNumber,
+                         .type = type,
+                         .fence = fence,
+                         .startTime = startTime});
+            }
+        }
+    });
+}
+
+void FrameTracer::tracePendingFencesLocked(FrameTracerDataSource::TraceContext& ctx,
+                                           int32_t layerID, uint64_t bufferID) {
+    if (mTraceTracker[layerID].pendingFences.count(bufferID)) {
+        auto& pendingFences = mTraceTracker[layerID].pendingFences[bufferID];
+        for (size_t i = 0; i < pendingFences.size(); ++i) {
+            auto& pendingFence = pendingFences[i];
+
+            nsecs_t signalTime = Fence::SIGNAL_TIME_INVALID;
+            if (pendingFence.fence && pendingFence.fence->isValid()) {
+                signalTime = pendingFence.fence->getSignalTime();
+                if (signalTime == Fence::SIGNAL_TIME_PENDING) {
+                    continue;
+                }
+            }
+
+            if (signalTime != Fence::SIGNAL_TIME_INVALID &&
+                systemTime() - signalTime < kFenceSignallingDeadline) {
+                traceSpanLocked(ctx, layerID, bufferID, pendingFence.frameNumber, pendingFence.type,
+                                pendingFence.startTime, signalTime);
+            }
+
+            pendingFences.erase(pendingFences.begin() + i);
+            --i;
+        }
+    }
+}
+
+void FrameTracer::traceLocked(FrameTracerDataSource::TraceContext& ctx, int32_t layerID,
+                              uint64_t bufferID, uint64_t frameNumber, nsecs_t timestamp,
+                              FrameEvent::BufferEventType type, nsecs_t duration) {
+    auto packet = ctx.NewTracePacket();
+    packet->set_timestamp(timestamp);
+    auto* event = packet->set_graphics_frame_event()->set_buffer_event();
+    event->set_buffer_id(static_cast<uint32_t>(bufferID));
+    event->set_frame_number(frameNumber);
+    event->set_type(type);
+
+    if (mTraceTracker.find(layerID) != mTraceTracker.end() &&
+        !mTraceTracker[layerID].layerName.empty()) {
+        const std::string& layerName = mTraceTracker[layerID].layerName;
+        event->set_layer_name(layerName.c_str(), layerName.size());
+    }
+
+    if (duration > 0) {
+        event->set_duration_ns(duration);
+    }
+}
+
+void FrameTracer::traceSpanLocked(FrameTracerDataSource::TraceContext& ctx, int32_t layerID,
+                                  uint64_t bufferID, uint64_t frameNumber,
+                                  FrameEvent::BufferEventType type, nsecs_t startTime,
+                                  nsecs_t endTime) {
+    nsecs_t timestamp = endTime;
+    nsecs_t duration = 0;
+    if (startTime > 0 && startTime < endTime) {
+        timestamp = startTime;
+        duration = endTime - startTime;
+    }
+    traceLocked(ctx, layerID, bufferID, frameNumber, timestamp, type, duration);
+}
+
+void FrameTracer::onDestroy(int32_t layerID) {
+    std::lock_guard<std::mutex> traceLock(mTraceMutex);
+    mTraceTracker.erase(layerID);
+}
+
+std::string FrameTracer::miniDump() {
+    std::string result = "FrameTracer miniDump:\n";
+    std::lock_guard<std::mutex> lock(mTraceMutex);
+    android::base::StringAppendF(&result, "Number of layers currently being traced is %zu\n",
+                                 mTraceTracker.size());
+    return result;
+}
+
+} // namespace android
diff --git a/services/surfaceflinger/FrameTracer/FrameTracer.h b/services/surfaceflinger/FrameTracer/FrameTracer.h
new file mode 100644
index 0000000..d34ad81
--- /dev/null
+++ b/services/surfaceflinger/FrameTracer/FrameTracer.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2019 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.
+ */
+
+#pragma once
+
+#include <perfetto/trace/android/graphics_frame_event.pbzero.h>
+#include <perfetto/tracing.h>
+#include <ui/FenceTime.h>
+
+#include <mutex>
+#include <unordered_map>
+
+namespace android {
+
+class FrameTracer {
+public:
+    class FrameTracerDataSource : public perfetto::DataSource<FrameTracerDataSource> {
+        virtual void OnSetup(const SetupArgs&) override{};
+        virtual void OnStart(const StartArgs&) override{};
+        virtual void OnStop(const StopArgs&) override{};
+    };
+
+    using FrameEvent = perfetto::protos::pbzero::GraphicsFrameEvent;
+
+    ~FrameTracer() = default;
+
+    // Sets up the perfetto tracing backend and data source.
+    void initialize();
+    // Registers the data source with the perfetto backend. Called as part of initialize()
+    // and should not be called manually outside of tests. Public to allow for substituting a
+    // perfetto::kInProcessBackend in tests.
+    void registerDataSource();
+    // Starts tracking a new layer for tracing. Needs to be called once before traceTimestamp() or
+    // traceFence() for each layer.
+    void traceNewLayer(int32_t layerID, const std::string& layerName);
+    // Creates a trace point at the timestamp provided.
+    void traceTimestamp(int32_t layerID, uint64_t bufferID, uint64_t frameNumber, nsecs_t timestamp,
+                        FrameEvent::BufferEventType type, nsecs_t duration = 0);
+    // Creates a trace point after the provided fence has been signalled. If a startTime is provided
+    // the trace will have be timestamped from startTime until fence signalling time. If no
+    // startTime is provided, a durationless trace point will be created timestamped at fence
+    // signalling time. If the fence hasn't signalled yet, the trace point will be created the next
+    // time after signalling a trace call for this buffer occurs.
+    void traceFence(int32_t layerID, uint64_t bufferID, uint64_t frameNumber,
+                    const std::shared_ptr<FenceTime>& fence, FrameEvent::BufferEventType type,
+                    nsecs_t startTime = 0);
+
+    // Takes care of cleanup when a layer is destroyed.
+    void onDestroy(int32_t layerID);
+
+    std::string miniDump();
+
+    static constexpr char kFrameTracerDataSource[] = "android.surfaceflinger.frame";
+
+    // The maximum amount of time a fence has to signal before it is discarded.
+    // Used to avoid fences from previous traces generating new trace points in later ones.
+    // Public for testing.
+    static constexpr nsecs_t kFenceSignallingDeadline = 60'000'000'000; // 60 seconds
+
+private:
+    struct PendingFence {
+        uint64_t frameNumber;
+        FrameEvent::BufferEventType type;
+        std::shared_ptr<FenceTime> fence;
+        nsecs_t startTime;
+    };
+
+    struct TraceRecord {
+        std::string layerName;
+        using BufferID = uint64_t;
+        std::unordered_map<BufferID, std::vector<PendingFence>> pendingFences;
+    };
+
+    // Checks if any pending fences for a layer and buffer have signalled and, if they have, creates
+    // trace points for them.
+    void tracePendingFencesLocked(FrameTracerDataSource::TraceContext& ctx, int32_t layerID,
+                                  uint64_t bufferID);
+    // Creates a trace point by translating a start time and an end time to a timestamp and
+    // duration. If startTime is later than end time it sets end time as the timestamp and the
+    // duration to 0. Used by traceFence().
+    void traceSpanLocked(FrameTracerDataSource::TraceContext& ctx, int32_t layerID,
+                         uint64_t bufferID, uint64_t frameNumber, FrameEvent::BufferEventType type,
+                         nsecs_t startTime, nsecs_t endTime);
+    void traceLocked(FrameTracerDataSource::TraceContext& ctx, int32_t layerID, uint64_t bufferID,
+                     uint64_t frameNumber, nsecs_t timestamp, FrameEvent::BufferEventType type,
+                     nsecs_t duration = 0);
+
+    std::mutex mTraceMutex;
+    std::unordered_map<int32_t, TraceRecord> mTraceTracker;
+};
+
+} // namespace android
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 5121835..106d505 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -57,6 +57,7 @@
 #include "Colorizer.h"
 #include "DisplayDevice.h"
 #include "DisplayHardware/HWComposer.h"
+#include "FrameTracer/FrameTracer.h"
 #include "LayerProtoHelper.h"
 #include "LayerRejecter.h"
 #include "MonitoredProducer.h"
@@ -1343,7 +1344,9 @@
 void Layer::onDisconnect() {
     Mutex::Autolock lock(mFrameEventHistoryMutex);
     mFrameEventHistory.onDisconnect();
-    mFlinger->mTimeStats->onDestroy(getSequence());
+    const int32_t layerID = getSequence();
+    mFlinger->mTimeStats->onDestroy(layerID);
+    mFlinger->mFrameTracer->onDestroy(layerID);
 }
 
 void Layer::addAndGetFrameTimestamps(const NewFrameEventsEntry* newTimestamps,
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 1875151..0eac1a7 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -98,6 +98,7 @@
 #include "DisplayHardware/HWComposer.h"
 #include "DisplayHardware/VirtualDisplaySurface.h"
 #include "Effects/Daltonizer.h"
+#include "FrameTracer/FrameTracer.h"
 #include "RegionSamplingThread.h"
 #include "Scheduler/DispSync.h"
 #include "Scheduler/DispSyncSource.h"
@@ -257,6 +258,7 @@
       : mFactory(factory),
         mInterceptor(mFactory.createSurfaceInterceptor(this)),
         mTimeStats(mFactory.createTimeStats()),
+        mFrameTracer(std::make_unique<FrameTracer>()),
         mEventQueue(mFactory.createMessageQueue()),
         mCompositionEngine(mFactory.createCompositionEngine()),
         mPhaseOffsets(mFactory.createPhaseOffsets()) {}
@@ -513,7 +515,7 @@
     const nsecs_t duration = now - mBootTime;
     ALOGI("Boot is finished (%ld ms)", long(ns2ms(duration)) );
 
-    mTimeStats->initializeTracing();
+    mFrameTracer->initialize();
 
     // wait patiently for the window manager death
     const String16 name("window");
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 9acd975..3c1fc82 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -94,6 +94,7 @@
 class RefreshRateOverlay;
 class RegionSamplingThread;
 class TimeStats;
+class FrameTracer;
 
 namespace compositionengine {
 class DisplaySurface;
@@ -993,6 +994,7 @@
     bool mTracingEnabled = false;
     bool mTracingEnabledChanged GUARDED_BY(mStateLock) = false;
     const std::shared_ptr<TimeStats> mTimeStats;
+    const std::unique_ptr<FrameTracer> mFrameTracer;
     bool mUseHwcVirtualDisplays = false;
     std::atomic<uint32_t> mFrameMissedCount = 0;
     std::atomic<uint32_t> mHwcFrameMissedCount = 0;
diff --git a/services/surfaceflinger/TimeStats/Android.bp b/services/surfaceflinger/TimeStats/Android.bp
index 9e1d503..2080a38 100644
--- a/services/surfaceflinger/TimeStats/Android.bp
+++ b/services/surfaceflinger/TimeStats/Android.bp
@@ -2,12 +2,9 @@
     name: "libtimestats",
     defaults: ["surfaceflinger_defaults"],
     srcs: [
-      "TimeStats.cpp"
+      "TimeStats.cpp",
     ],
     export_include_dirs: ["."],
-    static_libs: [
-      "libperfetto_client_experimental",
-    ],
     shared_libs: [
       "libtimestats_proto",
       "libui",
diff --git a/services/surfaceflinger/TimeStats/TimeStats.cpp b/services/surfaceflinger/TimeStats/TimeStats.cpp
index b66e4cf..b01fa81 100644
--- a/services/surfaceflinger/TimeStats/TimeStats.cpp
+++ b/services/surfaceflinger/TimeStats/TimeStats.cpp
@@ -30,141 +30,10 @@
 #include <algorithm>
 #include <regex>
 
-PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(android::impl::TimeStats::TimeStatsDataSource);
-
 namespace android {
 
 namespace impl {
 
-void TimeStats::initializeTracing() {
-    perfetto::TracingInitArgs args;
-    args.backends = perfetto::kSystemBackend;
-    perfetto::Tracing::Initialize(args);
-    registerTracingDataSource();
-}
-
-void TimeStats::registerTracingDataSource() {
-    perfetto::DataSourceDescriptor dsd;
-    dsd.set_name(kTimeStatsDataSource);
-    TimeStatsDataSource::Register(dsd);
-}
-
-void TimeStats::traceNewLayer(int32_t layerID, const std::string& layerName) {
-    TimeStatsDataSource::Trace([this, layerID, &layerName](TimeStatsDataSource::TraceContext) {
-        if (mTraceTracker.find(layerID) == mTraceTracker.end()) {
-            std::lock_guard<std::mutex> lock(mTraceMutex);
-            mTraceTracker[layerID].layerName = layerName;
-        }
-    });
-}
-
-void TimeStats::traceTimestamp(int32_t layerID, uint64_t bufferID, uint64_t frameNumber,
-                               nsecs_t timestamp, FrameEvent::BufferEventType type,
-                               nsecs_t duration) {
-    TimeStatsDataSource::Trace([this, layerID, bufferID, frameNumber, timestamp, type,
-                                duration](TimeStatsDataSource::TraceContext ctx) {
-        std::lock_guard<std::mutex> lock(mTraceMutex);
-        if (mTraceTracker.find(layerID) == mTraceTracker.end()) {
-            return;
-        }
-
-        // Handle any pending fences for this buffer.
-        tracePendingFencesLocked(ctx, layerID, bufferID);
-
-        // Complete current trace.
-        traceLocked(ctx, layerID, bufferID, frameNumber, timestamp, type, duration);
-    });
-}
-
-void TimeStats::traceFence(int32_t layerID, uint64_t bufferID, uint64_t frameNumber,
-                           const std::shared_ptr<FenceTime>& fence,
-                           FrameEvent::BufferEventType type, nsecs_t startTime) {
-    TimeStatsDataSource::Trace([this, layerID, bufferID, frameNumber, &fence, type,
-                                startTime](TimeStatsDataSource::TraceContext ctx) {
-        const nsecs_t signalTime = fence->getSignalTime();
-        if (signalTime != Fence::SIGNAL_TIME_INVALID) {
-            std::lock_guard<std::mutex> lock(mTraceMutex);
-            if (mTraceTracker.find(layerID) == mTraceTracker.end()) {
-                return;
-            }
-
-            // Handle any pending fences for this buffer.
-            tracePendingFencesLocked(ctx, layerID, bufferID);
-
-            if (signalTime != Fence::SIGNAL_TIME_PENDING) {
-                traceSpanLocked(ctx, layerID, bufferID, frameNumber, type, startTime, signalTime);
-            } else {
-                mTraceTracker[layerID].pendingFences[bufferID].push_back(
-                        {.frameNumber = frameNumber,
-                         .type = type,
-                         .fence = fence,
-                         .startTime = startTime});
-            }
-        }
-    });
-}
-
-void TimeStats::tracePendingFencesLocked(TimeStatsDataSource::TraceContext& ctx, int32_t layerID,
-                                         uint64_t bufferID) {
-    if (mTraceTracker[layerID].pendingFences.count(bufferID)) {
-        auto& pendingFences = mTraceTracker[layerID].pendingFences[bufferID];
-        for (size_t i = 0; i < pendingFences.size(); ++i) {
-            auto& pendingFence = pendingFences[i];
-
-            nsecs_t signalTime = Fence::SIGNAL_TIME_INVALID;
-            if (pendingFence.fence && pendingFence.fence->isValid()) {
-                signalTime = pendingFence.fence->getSignalTime();
-                if (signalTime == Fence::SIGNAL_TIME_PENDING) {
-                    continue;
-                }
-            }
-
-            if (signalTime != Fence::SIGNAL_TIME_INVALID &&
-                systemTime() - signalTime < kFenceSignallingDeadline) {
-                traceSpanLocked(ctx, layerID, bufferID, pendingFence.frameNumber, pendingFence.type,
-                                pendingFence.startTime, signalTime);
-            }
-
-            pendingFences.erase(pendingFences.begin() + i);
-            --i;
-        }
-    }
-}
-
-void TimeStats::traceLocked(TimeStatsDataSource::TraceContext& ctx, int32_t layerID,
-                            uint64_t bufferID, uint64_t frameNumber, nsecs_t timestamp,
-                            FrameEvent::BufferEventType type, nsecs_t duration) {
-    auto packet = ctx.NewTracePacket();
-    packet->set_timestamp(timestamp);
-    auto* event = packet->set_graphics_frame_event()->set_buffer_event();
-    event->set_buffer_id(static_cast<uint32_t>(bufferID));
-    event->set_frame_number(frameNumber);
-    event->set_type(type);
-
-    if (mTraceTracker.find(layerID) != mTraceTracker.end() &&
-        !mTraceTracker[layerID].layerName.empty()) {
-        const std::string& layerName = mTraceTracker[layerID].layerName;
-        event->set_layer_name(layerName.c_str(), layerName.size());
-    }
-
-    if (duration > 0) {
-        event->set_duration_ns(duration);
-    }
-}
-
-void TimeStats::traceSpanLocked(TimeStatsDataSource::TraceContext& ctx, int32_t layerID,
-                                uint64_t bufferID, uint64_t frameNumber,
-                                FrameEvent::BufferEventType type, nsecs_t startTime,
-                                nsecs_t endTime) {
-    nsecs_t timestamp = endTime;
-    nsecs_t duration = 0;
-    if (startTime > 0 && startTime < endTime) {
-        timestamp = startTime;
-        duration = endTime - startTime;
-    }
-    traceLocked(ctx, layerID, bufferID, frameNumber, timestamp, type, duration);
-}
-
 void TimeStats::parseArgs(bool asProto, const Vector<String16>& args, std::string& result) {
     ATRACE_CALL();
 
@@ -207,8 +76,6 @@
                                  mTimeStatsTracker.size());
     android::base::StringAppendF(&result, "Number of layers in the stats pool is %zu\n",
                                  mTimeStats.stats.size());
-    android::base::StringAppendF(&result, "Number of layers currently being traced is %zu\n",
-                                 mTraceTracker.size());
     return result;
 }
 
@@ -542,15 +409,8 @@
 void TimeStats::onDestroy(int32_t layerID) {
     ATRACE_CALL();
     ALOGV("[%d]-onDestroy", layerID);
-    {
-        std::lock_guard<std::mutex> lock(mMutex);
-        mTimeStatsTracker.erase(layerID);
-    }
-
-    {
-        std::lock_guard<std::mutex> traceLock(mTraceMutex);
-        mTraceTracker.erase(layerID);
-    }
+    std::lock_guard<std::mutex> lock(mMutex);
+    mTimeStatsTracker.erase(layerID);
 }
 
 void TimeStats::removeTimeRecord(int32_t layerID, uint64_t frameNumber) {
diff --git a/services/surfaceflinger/TimeStats/TimeStats.h b/services/surfaceflinger/TimeStats/TimeStats.h
index 470137a..9ebc1ad 100644
--- a/services/surfaceflinger/TimeStats/TimeStats.h
+++ b/services/surfaceflinger/TimeStats/TimeStats.h
@@ -17,8 +17,6 @@
 #pragma once
 
 #include <hardware/hwcomposer_defs.h>
-#include <perfetto/trace/android/graphics_frame_event.pbzero.h>
-#include <perfetto/tracing.h>
 #include <timestatsproto/TimeStatsHelper.h>
 #include <timestatsproto/TimeStatsProtoHeader.h>
 #include <ui/FenceTime.h>
@@ -36,32 +34,8 @@
 
 class TimeStats {
 public:
-    using FrameEvent = perfetto::protos::pbzero::GraphicsFrameEvent;
-
     virtual ~TimeStats() = default;
 
-    // Sets up the perfetto tracing backend and data source.
-    virtual void initializeTracing() = 0;
-    // Registers the data source with the perfetto backend. Called as part of initializeTracing()
-    // and should not be called manually outside of tests. Public to allow for substituting a
-    // perfetto::kInProcessBackend in tests.
-    virtual void registerTracingDataSource() = 0;
-    // Starts tracking a new layer for tracing. Needs to be called once before traceTimestamp() or
-    // traceFence() for each layer.
-    virtual void traceNewLayer(int32_t layerID, const std::string& layerName) = 0;
-    // Creates a trace point at the timestamp provided.
-    virtual void traceTimestamp(int32_t layerID, uint64_t bufferID, uint64_t frameNumber,
-                                nsecs_t timestamp, FrameEvent::BufferEventType type,
-                                nsecs_t duration = 0) = 0;
-    // Creates a trace point after the provided fence has been signalled. If a startTime is provided
-    // the trace will have be timestamped from startTime until fence signalling time. If no
-    // startTime is provided, a durationless trace point will be created timestamped at fence
-    // signalling time. If the fence hasn't signalled yet, the trace point will be created the next
-    // time after signalling a trace call for this buffer occurs.
-    virtual void traceFence(int32_t layerID, uint64_t bufferID, uint64_t frameNumber,
-                            const std::shared_ptr<FenceTime>& fence,
-                            FrameEvent::BufferEventType type, nsecs_t startTime = 0) = 0;
-
     virtual void parseArgs(bool asProto, const Vector<String16>& args, std::string& result) = 0;
     virtual bool isEnabled() = 0;
     virtual std::string miniDump() = 0;
@@ -89,13 +63,6 @@
     // Source of truth is RefrehRateStats.
     virtual void recordRefreshRate(uint32_t fps, nsecs_t duration) = 0;
     virtual void setPresentFenceGlobal(const std::shared_ptr<FenceTime>& presentFence) = 0;
-
-    static constexpr char kTimeStatsDataSource[] = "android.surfaceflinger.timestats";
-
-    // The maximum amount of time a fence has to signal before it is discarded.
-    // Used to avoid fence's from previous traces generating new trace points in later ones.
-    // Public for testing.
-    static constexpr nsecs_t kFenceSignallingDeadline = 60'000'000'000; // 60 seconds
 };
 
 namespace impl {
@@ -117,13 +84,6 @@
         std::shared_ptr<FenceTime> presentFence;
     };
 
-    struct PendingFence {
-        uint64_t frameNumber;
-        FrameEvent::BufferEventType type;
-        std::shared_ptr<FenceTime> fence;
-        nsecs_t startTime;
-    };
-
     struct LayerRecord {
         std::string layerName;
         // This is the index in timeRecords, at which the timestamps for that
@@ -135,12 +95,6 @@
         std::deque<TimeRecord> timeRecords;
     };
 
-    struct TraceRecord {
-        std::string layerName;
-        using BufferID = uint64_t;
-        std::unordered_map<BufferID, std::vector<PendingFence>> pendingFences;
-    };
-
     struct PowerTime {
         int32_t powerMode = HWC_POWER_MODE_OFF;
         nsecs_t prevTime = 0;
@@ -152,23 +106,8 @@
     };
 
 public:
-    class TimeStatsDataSource : public perfetto::DataSource<TimeStatsDataSource> {
-        virtual void OnSetup(const SetupArgs&) override{};
-        virtual void OnStart(const StartArgs&) override { ALOGV("TimeStats trace started"); };
-        virtual void OnStop(const StopArgs&) override { ALOGV("TimeStats trace stopped"); };
-    };
-
     TimeStats() = default;
 
-    void initializeTracing() override;
-    void registerTracingDataSource() override;
-    void traceNewLayer(int32_t layerID, const std::string& layerName) override;
-    void traceTimestamp(int32_t layerID, uint64_t bufferID, uint64_t frameNumber, nsecs_t timestamp,
-                        FrameEvent::BufferEventType type, nsecs_t duration = 0) override;
-    void traceFence(int32_t layerID, uint64_t bufferID, uint64_t frameNumber,
-                    const std::shared_ptr<FenceTime>& fence, FrameEvent::BufferEventType type,
-                    nsecs_t startTime = 0) override;
-
     void parseArgs(bool asProto, const Vector<String16>& args, std::string& result) override;
     bool isEnabled() override;
     std::string miniDump() override;
@@ -200,20 +139,6 @@
     static const size_t MAX_NUM_TIME_RECORDS = 64;
 
 private:
-    // Checks if any pending fences for a layer and buffer have signalled and, if they have, creates
-    // trace points for them.
-    void tracePendingFencesLocked(TimeStatsDataSource::TraceContext& ctx, int32_t layerID,
-                                  uint64_t bufferID);
-    // Creates a trace point by translating a start time and an end time to a timestamp and
-    // duration. If startTime is later than end time it sets end time as the timestamp and the
-    // duration to 0. Used by traceFence().
-    void traceSpanLocked(TimeStatsDataSource::TraceContext& ctx, int32_t layerID, uint64_t bufferID,
-                         uint64_t frameNumber, FrameEvent::BufferEventType type, nsecs_t startTime,
-                         nsecs_t endTime);
-    void traceLocked(TimeStatsDataSource::TraceContext& ctx, int32_t layerID, uint64_t bufferID,
-                     uint64_t frameNumber, nsecs_t timestamp, FrameEvent::BufferEventType type,
-                     nsecs_t duration = 0);
-
     bool recordReadyLocked(int32_t layerID, TimeRecord* timeRecord);
     void flushAvailableRecordsToStatsLocked(int32_t layerID);
     void flushPowerTimeLocked();
@@ -232,9 +157,6 @@
     PowerTime mPowerTime;
     GlobalRecord mGlobalRecord;
 
-    std::mutex mTraceMutex;
-    std::unordered_map<int32_t, TraceRecord> mTraceTracker;
-
     static const size_t MAX_NUM_LAYER_RECORDS = 200;
     static const size_t MAX_NUM_LAYER_STATS = 200;
 };
diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp
index 0eedf9b..8d98af6 100644
--- a/services/surfaceflinger/tests/unittests/Android.bp
+++ b/services/surfaceflinger/tests/unittests/Android.bp
@@ -51,6 +51,7 @@
         "RefreshRateStatsTest.cpp",
         "RegionSamplingTest.cpp",
         "TimeStatsTest.cpp",
+        "FrameTracerTest.cpp",
         "mock/DisplayHardware/MockComposer.cpp",
         "mock/DisplayHardware/MockDisplay.cpp",
         "mock/DisplayHardware/MockPowerAdvisor.cpp",
@@ -63,6 +64,7 @@
         "mock/MockNativeWindowSurface.cpp",
         "mock/MockSurfaceInterceptor.cpp",
         "mock/MockTimeStats.cpp",
+        "mock/MockFrameTracer.cpp",
         "mock/system/window/MockNativeWindow.cpp",
     ],
     static_libs: [
diff --git a/services/surfaceflinger/tests/unittests/FrameTracerTest.cpp b/services/surfaceflinger/tests/unittests/FrameTracerTest.cpp
new file mode 100644
index 0000000..b5af591
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/FrameTracerTest.cpp
@@ -0,0 +1,396 @@
+/*
+ * Copyright 2019 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 "LibSurfaceFlingerUnittests"
+
+#include <FrameTracer/FrameTracer.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <log/log.h>
+#include <perfetto/trace/trace.pb.h>
+
+#include "libsurfaceflinger_unittest_main.h"
+
+using namespace google::protobuf;
+
+namespace android {
+namespace {
+
+class FrameTracerTest : public testing::Test {
+public:
+    FrameTracerTest() {
+        const ::testing::TestInfo* const test_info =
+                ::testing::UnitTest::GetInstance()->current_test_info();
+        ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name());
+
+        // Need to initialize tracing in process for testing, and only once per test suite.
+        static bool wasInitialized = false;
+        if (!wasInitialized) {
+            perfetto::TracingInitArgs args;
+            args.backends = perfetto::kInProcessBackend;
+            perfetto::Tracing::Initialize(args);
+            wasInitialized = true;
+        }
+    }
+
+    ~FrameTracerTest() {
+        const ::testing::TestInfo* const test_info =
+                ::testing::UnitTest::GetInstance()->current_test_info();
+        ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name());
+    }
+
+    void SetUp() override {
+        mFrameTracer = std::make_unique<FrameTracer>();
+        mFrameTracer->registerDataSource();
+    }
+
+    void TearDown() override { mFrameTracer.reset(); }
+
+    // Each tracing session can be used for a single block of Start -> Stop.
+    static std::unique_ptr<perfetto::TracingSession> getTracingSessionForTest() {
+        perfetto::TraceConfig cfg;
+        cfg.set_duration_ms(500);
+        cfg.add_buffers()->set_size_kb(1024);
+        auto* ds_cfg = cfg.add_data_sources()->mutable_config();
+        ds_cfg->set_name(FrameTracer::kFrameTracerDataSource);
+
+        auto tracingSession = perfetto::Tracing::NewTrace(perfetto::kInProcessBackend);
+        tracingSession->Setup(cfg);
+        return tracingSession;
+    }
+
+    std::unique_ptr<FrameTracer> mFrameTracer;
+    FenceToFenceTimeMap fenceFactory;
+};
+
+TEST_F(FrameTracerTest, traceNewLayerStartsTrackingLayerWhenTracing) {
+    EXPECT_EQ(mFrameTracer->miniDump(),
+              "FrameTracer miniDump:\nNumber of layers currently being traced is 0\n");
+
+    const std::string layerName = "co.layername#0";
+    const int32_t layerID = 5;
+    mFrameTracer->traceNewLayer(layerID, layerName);
+
+    EXPECT_EQ(mFrameTracer->miniDump(),
+              "FrameTracer miniDump:\nNumber of layers currently being traced is 0\n");
+
+    auto tracingSession = getTracingSessionForTest();
+    tracingSession->StartBlocking();
+    EXPECT_EQ(mFrameTracer->miniDump(),
+              "FrameTracer miniDump:\nNumber of layers currently being traced is 0\n");
+    mFrameTracer->traceNewLayer(layerID, layerName);
+    EXPECT_EQ(mFrameTracer->miniDump(),
+              "FrameTracer miniDump:\nNumber of layers currently being traced is 1\n");
+    tracingSession->StopBlocking();
+}
+
+TEST_F(FrameTracerTest, onDestroyRemovesTheTrackedLayer) {
+    EXPECT_EQ(mFrameTracer->miniDump(),
+              "FrameTracer miniDump:\nNumber of layers currently being traced is 0\n");
+
+    const std::string layerName = "co.layername#0";
+    const int32_t layerID = 5;
+    const int32_t secondLayerID = 6;
+
+    auto tracingSession = getTracingSessionForTest();
+    tracingSession->StartBlocking();
+    mFrameTracer->traceNewLayer(layerID, layerName);
+    mFrameTracer->traceNewLayer(secondLayerID, layerName);
+    EXPECT_EQ(mFrameTracer->miniDump(),
+              "FrameTracer miniDump:\nNumber of layers currently being traced is 2\n");
+    tracingSession->StopBlocking();
+
+    mFrameTracer->onDestroy(layerID);
+    EXPECT_EQ(mFrameTracer->miniDump(),
+              "FrameTracer miniDump:\nNumber of layers currently being traced is 1\n");
+    mFrameTracer->onDestroy(layerID);
+    EXPECT_EQ(mFrameTracer->miniDump(),
+              "FrameTracer miniDump:\nNumber of layers currently being traced is 1\n");
+    mFrameTracer->onDestroy(secondLayerID);
+    EXPECT_EQ(mFrameTracer->miniDump(),
+              "FrameTracer miniDump:\nNumber of layers currently being traced is 0\n");
+}
+
+TEST_F(FrameTracerTest, canTraceAfterAddingLayer) {
+    const std::string layerName = "co.layername#0";
+    const int32_t layerID = 1;
+    const uint32_t bufferID = 2;
+    const uint64_t frameNumber = 3;
+    const nsecs_t timestamp = 4;
+    const nsecs_t duration = 5;
+    const auto type = FrameTracer::FrameEvent::POST;
+
+    {
+        auto tracingSession = getTracingSessionForTest();
+
+        tracingSession->StartBlocking();
+        // Clean up irrelevant traces.
+        tracingSession->ReadTraceBlocking();
+
+        mFrameTracer->traceTimestamp(layerID, bufferID, frameNumber, timestamp, type, duration);
+        // Create second trace packet to finalize the previous one.
+        mFrameTracer->traceTimestamp(layerID, 0, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED);
+        tracingSession->StopBlocking();
+
+        std::vector<char> raw_trace = tracingSession->ReadTraceBlocking();
+        EXPECT_EQ(raw_trace.size(), 0);
+    }
+
+    {
+        auto tracingSession = getTracingSessionForTest();
+
+        tracingSession->StartBlocking();
+        // Clean up irrelevant traces.
+        tracingSession->ReadTraceBlocking();
+
+        mFrameTracer->traceNewLayer(layerID, layerName);
+        mFrameTracer->traceTimestamp(layerID, bufferID, frameNumber, timestamp, type, duration);
+        // Create second trace packet to finalize the previous one.
+        mFrameTracer->traceTimestamp(layerID, 0, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED);
+        tracingSession->StopBlocking();
+
+        std::vector<char> raw_trace = tracingSession->ReadTraceBlocking();
+        ASSERT_GT(raw_trace.size(), 0);
+
+        perfetto::protos::Trace trace;
+        ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), int(raw_trace.size())));
+        ASSERT_FALSE(trace.packet().empty());
+        EXPECT_EQ(trace.packet().size(), 1);
+
+        const auto& packet = trace.packet().Get(0);
+        ASSERT_TRUE(packet.has_timestamp());
+        EXPECT_EQ(packet.timestamp(), timestamp);
+        ASSERT_TRUE(packet.has_graphics_frame_event());
+        const auto& frame_event = packet.graphics_frame_event();
+        ASSERT_TRUE(frame_event.has_buffer_event());
+        const auto& buffer_event = frame_event.buffer_event();
+        ASSERT_TRUE(buffer_event.has_buffer_id());
+        EXPECT_EQ(buffer_event.buffer_id(), bufferID);
+        ASSERT_TRUE(buffer_event.has_frame_number());
+        EXPECT_EQ(buffer_event.frame_number(), frameNumber);
+        ASSERT_TRUE(buffer_event.has_type());
+        EXPECT_EQ(buffer_event.type(), perfetto::protos::GraphicsFrameEvent_BufferEventType(type));
+        ASSERT_TRUE(buffer_event.has_duration_ns());
+        EXPECT_EQ(buffer_event.duration_ns(), duration);
+    }
+}
+
+TEST_F(FrameTracerTest, traceFenceTriggersOnNextTraceAfterFenceFired) {
+    const std::string layerName = "co.layername#0";
+    const int32_t layerID = 5;
+    const uint32_t bufferID = 4;
+    const uint64_t frameNumber = 3;
+    const auto type = FrameTracer::FrameEvent::ACQUIRE_FENCE;
+
+    {
+        auto fenceTime = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
+        fenceFactory.signalAllForTest(Fence::NO_FENCE, Fence::SIGNAL_TIME_PENDING);
+        auto tracingSession = getTracingSessionForTest();
+        tracingSession->StartBlocking();
+        // Clean up irrelevant traces.
+        tracingSession->ReadTraceBlocking();
+        // Trace.
+        mFrameTracer->traceNewLayer(layerID, layerName);
+        mFrameTracer->traceFence(layerID, bufferID, frameNumber, fenceTime, type);
+        // Create extra trace packet to (hopefully not) trigger and finalize the fence packet.
+        mFrameTracer->traceTimestamp(layerID, bufferID, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED);
+        tracingSession->StopBlocking();
+        std::vector<char> raw_trace = tracingSession->ReadTraceBlocking();
+        EXPECT_EQ(raw_trace.size(), 0);
+    }
+
+    {
+        auto fenceTime = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
+        auto tracingSession = getTracingSessionForTest();
+        tracingSession->StartBlocking();
+        // Clean up irrelevant traces.
+        tracingSession->ReadTraceBlocking();
+        mFrameTracer->traceNewLayer(layerID, layerName);
+        mFrameTracer->traceFence(layerID, bufferID, frameNumber, fenceTime, type);
+        const nsecs_t timestamp = systemTime();
+        fenceFactory.signalAllForTest(Fence::NO_FENCE, timestamp);
+        // Create extra trace packet to trigger and finalize fence trace packets.
+        mFrameTracer->traceTimestamp(layerID, bufferID, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED);
+        tracingSession->StopBlocking();
+
+        std::vector<char> raw_trace = tracingSession->ReadTraceBlocking();
+        ASSERT_GT(raw_trace.size(), 0);
+
+        perfetto::protos::Trace trace;
+        ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), int(raw_trace.size())));
+        ASSERT_FALSE(trace.packet().empty());
+        EXPECT_EQ(trace.packet().size(), 2); // Two packets because of the extra trace made above.
+
+        const auto& packet = trace.packet().Get(1);
+        ASSERT_TRUE(packet.has_timestamp());
+        EXPECT_EQ(packet.timestamp(), timestamp);
+        ASSERT_TRUE(packet.has_graphics_frame_event());
+        const auto& frame_event = packet.graphics_frame_event();
+        ASSERT_TRUE(frame_event.has_buffer_event());
+        const auto& buffer_event = frame_event.buffer_event();
+        ASSERT_TRUE(buffer_event.has_buffer_id());
+        EXPECT_EQ(buffer_event.buffer_id(), bufferID);
+        ASSERT_TRUE(buffer_event.has_frame_number());
+        EXPECT_EQ(buffer_event.frame_number(), frameNumber);
+        ASSERT_TRUE(buffer_event.has_type());
+        EXPECT_EQ(buffer_event.type(), perfetto::protos::GraphicsFrameEvent_BufferEventType(type));
+        EXPECT_FALSE(buffer_event.has_duration_ns());
+    }
+}
+
+TEST_F(FrameTracerTest, traceFenceWithStartTimeAfterSignalTime_ShouldHaveNoDuration) {
+    const std::string layerName = "co.layername#0";
+    const int32_t layerID = 5;
+    const uint32_t bufferID = 4;
+    const uint64_t frameNumber = 3;
+    const auto type = FrameTracer::FrameEvent::ACQUIRE_FENCE;
+
+    auto tracingSession = getTracingSessionForTest();
+
+    tracingSession->StartBlocking();
+    // Clean up irrelevant traces.
+    tracingSession->ReadTraceBlocking();
+    mFrameTracer->traceNewLayer(layerID, layerName);
+
+    // traceFence called after fence signalled.
+    const nsecs_t signalTime1 = systemTime();
+    const nsecs_t startTime1 = signalTime1 + 100000;
+    auto fence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
+    fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime1);
+    mFrameTracer->traceFence(layerID, bufferID, frameNumber, fence1, type, startTime1);
+
+    // traceFence called before fence signalled.
+    const nsecs_t signalTime2 = systemTime();
+    const nsecs_t startTime2 = signalTime2 + 100000;
+    auto fence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
+    mFrameTracer->traceFence(layerID, bufferID, frameNumber, fence2, type, startTime2);
+    fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime2);
+
+    // Create extra trace packet to trigger and finalize fence trace packets.
+    mFrameTracer->traceTimestamp(layerID, bufferID, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED);
+    tracingSession->StopBlocking();
+
+    std::vector<char> raw_trace = tracingSession->ReadTraceBlocking();
+    ASSERT_GT(raw_trace.size(), 0);
+
+    perfetto::protos::Trace trace;
+    ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), int(raw_trace.size())));
+    ASSERT_FALSE(trace.packet().empty());
+    EXPECT_EQ(trace.packet().size(), 2);
+
+    const auto& packet1 = trace.packet().Get(0);
+    ASSERT_TRUE(packet1.has_timestamp());
+    EXPECT_EQ(packet1.timestamp(), signalTime1);
+    ASSERT_TRUE(packet1.has_graphics_frame_event());
+    ASSERT_TRUE(packet1.graphics_frame_event().has_buffer_event());
+    ASSERT_FALSE(packet1.graphics_frame_event().buffer_event().has_duration_ns());
+
+    const auto& packet2 = trace.packet().Get(1);
+    ASSERT_TRUE(packet2.has_timestamp());
+    EXPECT_EQ(packet2.timestamp(), signalTime2);
+    ASSERT_TRUE(packet2.has_graphics_frame_event());
+    ASSERT_TRUE(packet2.graphics_frame_event().has_buffer_event());
+    ASSERT_FALSE(packet2.graphics_frame_event().buffer_event().has_duration_ns());
+}
+
+TEST_F(FrameTracerTest, traceFenceOlderThanDeadline_ShouldBeIgnored) {
+    const std::string layerName = "co.layername#0";
+    const int32_t layerID = 5;
+    const uint32_t bufferID = 4;
+    const uint64_t frameNumber = 3;
+    const auto type = FrameTracer::FrameEvent::ACQUIRE_FENCE;
+    const nsecs_t signalTime = systemTime() - FrameTracer::kFenceSignallingDeadline;
+
+    auto tracingSession = getTracingSessionForTest();
+    auto fence = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
+
+    tracingSession->StartBlocking();
+    // Clean up irrelevant traces.
+    tracingSession->ReadTraceBlocking();
+    mFrameTracer->traceNewLayer(layerID, layerName);
+    mFrameTracer->traceFence(layerID, bufferID, frameNumber, fence, type);
+    fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime);
+    // Create extra trace packet to trigger and finalize any previous fence packets.
+    mFrameTracer->traceTimestamp(layerID, bufferID, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED);
+    tracingSession->StopBlocking();
+
+    std::vector<char> raw_trace = tracingSession->ReadTraceBlocking();
+    EXPECT_EQ(raw_trace.size(), 0);
+}
+
+TEST_F(FrameTracerTest, traceFenceWithValidStartTime_ShouldHaveCorrectDuration) {
+    const std::string layerName = "co.layername#0";
+    const int32_t layerID = 5;
+    const uint32_t bufferID = 4;
+    const uint64_t frameNumber = 3;
+    const auto type = FrameTracer::FrameEvent::ACQUIRE_FENCE;
+    const nsecs_t duration = 1234;
+
+    auto tracingSession = getTracingSessionForTest();
+
+    tracingSession->StartBlocking();
+    // Clean up irrelevant traces.
+    tracingSession->ReadTraceBlocking();
+    mFrameTracer->traceNewLayer(layerID, layerName);
+
+    // traceFence called after fence signalled.
+    const nsecs_t signalTime1 = systemTime();
+    const nsecs_t startTime1 = signalTime1 - duration;
+    auto fence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
+    fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime1);
+    mFrameTracer->traceFence(layerID, bufferID, frameNumber, fence1, type, startTime1);
+
+    // traceFence called before fence signalled.
+    const nsecs_t signalTime2 = systemTime();
+    const nsecs_t startTime2 = signalTime2 - duration;
+    auto fence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
+    mFrameTracer->traceFence(layerID, bufferID, frameNumber, fence2, type, startTime2);
+    fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime2);
+
+    // Create extra trace packet to trigger and finalize fence trace packets.
+    mFrameTracer->traceTimestamp(layerID, bufferID, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED);
+    tracingSession->StopBlocking();
+
+    std::vector<char> raw_trace = tracingSession->ReadTraceBlocking();
+    ASSERT_GT(raw_trace.size(), 0);
+
+    perfetto::protos::Trace trace;
+    ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), int(raw_trace.size())));
+    ASSERT_FALSE(trace.packet().empty());
+    EXPECT_EQ(trace.packet().size(), 2);
+
+    const auto& packet1 = trace.packet().Get(0);
+    ASSERT_TRUE(packet1.has_timestamp());
+    EXPECT_EQ(packet1.timestamp(), startTime1);
+    ASSERT_TRUE(packet1.has_graphics_frame_event());
+    ASSERT_TRUE(packet1.graphics_frame_event().has_buffer_event());
+    ASSERT_TRUE(packet1.graphics_frame_event().buffer_event().has_duration_ns());
+    const auto& buffer_event1 = packet1.graphics_frame_event().buffer_event();
+    EXPECT_EQ(buffer_event1.duration_ns(), duration);
+
+    const auto& packet2 = trace.packet().Get(1);
+    ASSERT_TRUE(packet2.has_timestamp());
+    EXPECT_EQ(packet2.timestamp(), startTime2);
+    ASSERT_TRUE(packet2.has_graphics_frame_event());
+    ASSERT_TRUE(packet2.graphics_frame_event().has_buffer_event());
+    ASSERT_TRUE(packet2.graphics_frame_event().buffer_event().has_duration_ns());
+    const auto& buffer_event2 = packet2.graphics_frame_event().buffer_event();
+    EXPECT_EQ(buffer_event2.duration_ns(), duration);
+}
+
+} // namespace
+} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp b/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp
index f01e603..ffacbfe 100644
--- a/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp
@@ -20,8 +20,8 @@
 #include <TimeStats/TimeStats.h>
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
+
 #include <log/log.h>
-#include <perfetto/trace/trace.pb.h>
 #include <utils/String16.h>
 #include <utils/Vector.h>
 
@@ -109,15 +109,6 @@
         const ::testing::TestInfo* const test_info =
                 ::testing::UnitTest::GetInstance()->current_test_info();
         ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name());
-
-        // Need to initialize tracing in process for testing, and only once per test suite.
-        static bool wasInitialized = false;
-        if (!wasInitialized) {
-            perfetto::TracingInitArgs args;
-            args.backends = perfetto::kInProcessBackend;
-            perfetto::Tracing::Initialize(args);
-            wasInitialized = true;
-        }
     }
 
     ~TimeStatsTest() {
@@ -126,13 +117,6 @@
         ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name());
     }
 
-    void SetUp() override {
-        mTimeStats = std::make_unique<impl::TimeStats>();
-        mTimeStats->registerTracingDataSource();
-    }
-
-    void TearDown() override { mTimeStats.reset(); }
-
     std::string inputCommand(InputCommand cmd, bool useProto);
 
     void setTimeStamp(TimeStamp type, int32_t id, uint64_t frameNumber, nsecs_t ts);
@@ -147,22 +131,8 @@
         }
     }
 
-    // Each tracing session can be used for a single block of Start -> Stop.
-    static std::unique_ptr<perfetto::TracingSession> getTracingSessionForTest() {
-        perfetto::TraceConfig cfg;
-        cfg.set_duration_ms(500);
-        cfg.add_buffers()->set_size_kb(1024);
-        auto* ds_cfg = cfg.add_data_sources()->mutable_config();
-        ds_cfg->set_name(TimeStats::kTimeStatsDataSource);
-
-        auto tracingSession = perfetto::Tracing::NewTrace(perfetto::kInProcessBackend);
-        tracingSession->Setup(cfg);
-        return tracingSession;
-    }
-
     std::mt19937 mRandomEngine = std::mt19937(std::random_device()());
-    std::unique_ptr<TimeStats> mTimeStats;
-    FenceToFenceTimeMap fenceFactory;
+    std::unique_ptr<TimeStats> mTimeStats = std::make_unique<impl::TimeStats>();
 };
 
 std::string TimeStatsTest::inputCommand(InputCommand cmd, bool useProto) {
@@ -239,330 +209,6 @@
     return distr(mRandomEngine);
 }
 
-TEST_F(TimeStatsTest, traceNewLayerStartsTrackingLayerWhenTracing) {
-    EXPECT_EQ(mTimeStats->miniDump(),
-              "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of "
-              "layers in the stats pool is 0\nNumber of layers currently being traced is 0\n");
-
-    const std::string layerName = "co.layername#0";
-    const int32_t layerID = 5;
-    mTimeStats->traceNewLayer(layerID, layerName);
-
-    EXPECT_EQ(mTimeStats->miniDump(),
-              "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of "
-              "layers in the stats pool is 0\nNumber of layers currently being traced is 0\n");
-
-    auto tracingSession = getTracingSessionForTest();
-    tracingSession->StartBlocking();
-    EXPECT_EQ(mTimeStats->miniDump(),
-              "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of "
-              "layers in the stats pool is 0\nNumber of layers currently being traced is 0\n");
-    mTimeStats->traceNewLayer(layerID, layerName);
-    EXPECT_EQ(mTimeStats->miniDump(),
-              "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of "
-              "layers in the stats pool is 0\nNumber of layers currently being traced is 1\n");
-    tracingSession->StopBlocking();
-}
-
-TEST_F(TimeStatsTest, onDestroyRemovesTheTrackedLayer) {
-    EXPECT_EQ(mTimeStats->miniDump(),
-              "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of "
-              "layers in the stats pool is 0\nNumber of layers currently being traced is 0\n");
-
-    const std::string layerName = "co.layername#0";
-    const int32_t layerID = 5;
-    const int32_t secondLayerID = 6;
-
-    auto tracingSession = getTracingSessionForTest();
-    tracingSession->StartBlocking();
-    mTimeStats->traceNewLayer(layerID, layerName);
-    mTimeStats->traceNewLayer(secondLayerID, layerName);
-    EXPECT_EQ(mTimeStats->miniDump(),
-              "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of "
-              "layers in the stats pool is 0\nNumber of layers currently being traced is 2\n");
-    tracingSession->StopBlocking();
-
-    mTimeStats->onDestroy(layerID);
-    EXPECT_EQ(mTimeStats->miniDump(),
-              "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of "
-              "layers in the stats pool is 0\nNumber of layers currently being traced is 1\n");
-    mTimeStats->onDestroy(layerID);
-    EXPECT_EQ(mTimeStats->miniDump(),
-              "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of "
-              "layers in the stats pool is 0\nNumber of layers currently being traced is 1\n");
-    mTimeStats->onDestroy(secondLayerID);
-    EXPECT_EQ(mTimeStats->miniDump(),
-              "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of "
-              "layers in the stats pool is 0\nNumber of layers currently being traced is 0\n");
-}
-
-TEST_F(TimeStatsTest, canTraceAfterAddingLayer) {
-    const std::string layerName = "co.layername#0";
-    const int32_t layerID = 1;
-    const uint32_t bufferID = 2;
-    const uint64_t frameNumber = 3;
-    const nsecs_t timestamp = 4;
-    const nsecs_t duration = 5;
-    const auto type = TimeStats::FrameEvent::POST;
-
-    {
-        auto tracingSession = getTracingSessionForTest();
-
-        tracingSession->StartBlocking();
-        // Clean up irrelevant traces.
-        tracingSession->ReadTraceBlocking();
-
-        mTimeStats->traceTimestamp(layerID, bufferID, frameNumber, timestamp, type, duration);
-        // Create second trace packet to finalize the previous one.
-        mTimeStats->traceTimestamp(layerID, 0, 0, 0, TimeStats::FrameEvent::UNSPECIFIED);
-        tracingSession->StopBlocking();
-
-        std::vector<char> raw_trace = tracingSession->ReadTraceBlocking();
-        EXPECT_EQ(raw_trace.size(), 0);
-    }
-
-    {
-        auto tracingSession = getTracingSessionForTest();
-
-        tracingSession->StartBlocking();
-        // Clean up irrelevant traces.
-        tracingSession->ReadTraceBlocking();
-
-        mTimeStats->traceNewLayer(layerID, layerName);
-        mTimeStats->traceTimestamp(layerID, bufferID, frameNumber, timestamp, type, duration);
-        // Create second trace packet to finalize the previous one.
-        mTimeStats->traceTimestamp(layerID, 0, 0, 0, TimeStats::FrameEvent::UNSPECIFIED);
-        tracingSession->StopBlocking();
-
-        std::vector<char> raw_trace = tracingSession->ReadTraceBlocking();
-        ASSERT_GT(raw_trace.size(), 0);
-
-        perfetto::protos::Trace trace;
-        ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), int(raw_trace.size())));
-        ASSERT_FALSE(trace.packet().empty());
-        EXPECT_EQ(trace.packet().size(), 1);
-
-        const auto& packet = trace.packet().Get(0);
-        ASSERT_TRUE(packet.has_timestamp());
-        EXPECT_EQ(packet.timestamp(), timestamp);
-        ASSERT_TRUE(packet.has_graphics_frame_event());
-        const auto& frame_event = packet.graphics_frame_event();
-        ASSERT_TRUE(frame_event.has_buffer_event());
-        const auto& buffer_event = frame_event.buffer_event();
-        ASSERT_TRUE(buffer_event.has_buffer_id());
-        EXPECT_EQ(buffer_event.buffer_id(), bufferID);
-        ASSERT_TRUE(buffer_event.has_frame_number());
-        EXPECT_EQ(buffer_event.frame_number(), frameNumber);
-        ASSERT_TRUE(buffer_event.has_type());
-        EXPECT_EQ(buffer_event.type(), perfetto::protos::GraphicsFrameEvent_BufferEventType(type));
-        ASSERT_TRUE(buffer_event.has_duration_ns());
-        EXPECT_EQ(buffer_event.duration_ns(), duration);
-    }
-}
-
-TEST_F(TimeStatsTest, traceFenceTriggersOnNextTraceAfterFenceFired) {
-    const std::string layerName = "co.layername#0";
-    const int32_t layerID = 5;
-    const uint32_t bufferID = 4;
-    const uint64_t frameNumber = 3;
-    const auto type = TimeStats::FrameEvent::ACQUIRE_FENCE;
-
-    {
-        auto fenceTime = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
-        fenceFactory.signalAllForTest(Fence::NO_FENCE, Fence::SIGNAL_TIME_PENDING);
-        auto tracingSession = getTracingSessionForTest();
-        tracingSession->StartBlocking();
-        // Clean up irrelevant traces.
-        tracingSession->ReadTraceBlocking();
-        // Trace.
-        mTimeStats->traceNewLayer(layerID, layerName);
-        mTimeStats->traceFence(layerID, bufferID, frameNumber, fenceTime, type);
-        // Create extra trace packet to (hopefully not) trigger and finalize the fence packet.
-        mTimeStats->traceTimestamp(layerID, bufferID, 0, 0, TimeStats::FrameEvent::UNSPECIFIED);
-        tracingSession->StopBlocking();
-        std::vector<char> raw_trace = tracingSession->ReadTraceBlocking();
-        EXPECT_EQ(raw_trace.size(), 0);
-    }
-
-    {
-        auto fenceTime = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
-        auto tracingSession = getTracingSessionForTest();
-        tracingSession->StartBlocking();
-        // Clean up irrelevant traces.
-        tracingSession->ReadTraceBlocking();
-        mTimeStats->traceNewLayer(layerID, layerName);
-        mTimeStats->traceFence(layerID, bufferID, frameNumber, fenceTime, type);
-        const nsecs_t timestamp = systemTime();
-        fenceFactory.signalAllForTest(Fence::NO_FENCE, timestamp);
-        // Create extra trace packet to trigger and finalize fence trace packets.
-        mTimeStats->traceTimestamp(layerID, bufferID, 0, 0, TimeStats::FrameEvent::UNSPECIFIED);
-        tracingSession->StopBlocking();
-
-        std::vector<char> raw_trace = tracingSession->ReadTraceBlocking();
-        ASSERT_GT(raw_trace.size(), 0);
-
-        perfetto::protos::Trace trace;
-        ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), int(raw_trace.size())));
-        ASSERT_FALSE(trace.packet().empty());
-        EXPECT_EQ(trace.packet().size(), 2); // Two packets because of the extra trace made above.
-
-        const auto& packet = trace.packet().Get(1);
-        ASSERT_TRUE(packet.has_timestamp());
-        EXPECT_EQ(packet.timestamp(), timestamp);
-        ASSERT_TRUE(packet.has_graphics_frame_event());
-        const auto& frame_event = packet.graphics_frame_event();
-        ASSERT_TRUE(frame_event.has_buffer_event());
-        const auto& buffer_event = frame_event.buffer_event();
-        ASSERT_TRUE(buffer_event.has_buffer_id());
-        EXPECT_EQ(buffer_event.buffer_id(), bufferID);
-        ASSERT_TRUE(buffer_event.has_frame_number());
-        EXPECT_EQ(buffer_event.frame_number(), frameNumber);
-        ASSERT_TRUE(buffer_event.has_type());
-        EXPECT_EQ(buffer_event.type(), perfetto::protos::GraphicsFrameEvent_BufferEventType(type));
-        EXPECT_FALSE(buffer_event.has_duration_ns());
-    }
-}
-
-TEST_F(TimeStatsTest, traceFenceWithStartTimeAfterSignalTime_ShouldHaveNoDuration) {
-    const std::string layerName = "co.layername#0";
-    const int32_t layerID = 5;
-    const uint32_t bufferID = 4;
-    const uint64_t frameNumber = 3;
-    const auto type = TimeStats::FrameEvent::ACQUIRE_FENCE;
-
-    auto tracingSession = getTracingSessionForTest();
-
-    tracingSession->StartBlocking();
-    // Clean up irrelevant traces.
-    tracingSession->ReadTraceBlocking();
-    mTimeStats->traceNewLayer(layerID, layerName);
-
-    // traceFence called after fence signalled.
-    const nsecs_t signalTime1 = systemTime();
-    const nsecs_t startTime1 = signalTime1 + 100000;
-    auto fence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
-    fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime1);
-    mTimeStats->traceFence(layerID, bufferID, frameNumber, fence1, type, startTime1);
-
-    // traceFence called before fence signalled.
-    const nsecs_t signalTime2 = systemTime();
-    const nsecs_t startTime2 = signalTime2 + 100000;
-    auto fence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
-    mTimeStats->traceFence(layerID, bufferID, frameNumber, fence2, type, startTime2);
-    fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime2);
-
-    // Create extra trace packet to trigger and finalize fence trace packets.
-    mTimeStats->traceTimestamp(layerID, bufferID, 0, 0, TimeStats::FrameEvent::UNSPECIFIED);
-    tracingSession->StopBlocking();
-
-    std::vector<char> raw_trace = tracingSession->ReadTraceBlocking();
-    ASSERT_GT(raw_trace.size(), 0);
-
-    perfetto::protos::Trace trace;
-    ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), int(raw_trace.size())));
-    ASSERT_FALSE(trace.packet().empty());
-    EXPECT_EQ(trace.packet().size(), 2);
-
-    const auto& packet1 = trace.packet().Get(0);
-    ASSERT_TRUE(packet1.has_timestamp());
-    EXPECT_EQ(packet1.timestamp(), signalTime1);
-    ASSERT_TRUE(packet1.has_graphics_frame_event());
-    ASSERT_TRUE(packet1.graphics_frame_event().has_buffer_event());
-    ASSERT_FALSE(packet1.graphics_frame_event().buffer_event().has_duration_ns());
-
-    const auto& packet2 = trace.packet().Get(1);
-    ASSERT_TRUE(packet2.has_timestamp());
-    EXPECT_EQ(packet2.timestamp(), signalTime2);
-    ASSERT_TRUE(packet2.has_graphics_frame_event());
-    ASSERT_TRUE(packet2.graphics_frame_event().has_buffer_event());
-    ASSERT_FALSE(packet2.graphics_frame_event().buffer_event().has_duration_ns());
-}
-
-TEST_F(TimeStatsTest, traceFenceOlderThanDeadline_ShouldBeIgnored) {
-    const std::string layerName = "co.layername#0";
-    const int32_t layerID = 5;
-    const uint32_t bufferID = 4;
-    const uint64_t frameNumber = 3;
-    const auto type = TimeStats::FrameEvent::ACQUIRE_FENCE;
-    const nsecs_t signalTime = systemTime() - TimeStats::kFenceSignallingDeadline;
-
-    auto tracingSession = getTracingSessionForTest();
-    auto fence = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
-
-    tracingSession->StartBlocking();
-    // Clean up irrelevant traces.
-    tracingSession->ReadTraceBlocking();
-    mTimeStats->traceNewLayer(layerID, layerName);
-    mTimeStats->traceFence(layerID, bufferID, frameNumber, fence, type);
-    fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime);
-    // Create extra trace packet to trigger and finalize any previous fence packets.
-    mTimeStats->traceTimestamp(layerID, bufferID, 0, 0, TimeStats::FrameEvent::UNSPECIFIED);
-    tracingSession->StopBlocking();
-
-    std::vector<char> raw_trace = tracingSession->ReadTraceBlocking();
-    EXPECT_EQ(raw_trace.size(), 0);
-}
-
-TEST_F(TimeStatsTest, traceFenceWithValidStartTime_ShouldHaveCorrectDuration) {
-    const std::string layerName = "co.layername#0";
-    const int32_t layerID = 5;
-    const uint32_t bufferID = 4;
-    const uint64_t frameNumber = 3;
-    const auto type = TimeStats::FrameEvent::ACQUIRE_FENCE;
-    const nsecs_t duration = 1234;
-
-    auto tracingSession = getTracingSessionForTest();
-
-    tracingSession->StartBlocking();
-    // Clean up irrelevant traces.
-    tracingSession->ReadTraceBlocking();
-    mTimeStats->traceNewLayer(layerID, layerName);
-
-    // traceFence called after fence signalled.
-    const nsecs_t signalTime1 = systemTime();
-    const nsecs_t startTime1 = signalTime1 - duration;
-    auto fence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
-    fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime1);
-    mTimeStats->traceFence(layerID, bufferID, frameNumber, fence1, type, startTime1);
-
-    // traceFence called before fence signalled.
-    const nsecs_t signalTime2 = systemTime();
-    const nsecs_t startTime2 = signalTime2 - duration;
-    auto fence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
-    mTimeStats->traceFence(layerID, bufferID, frameNumber, fence2, type, startTime2);
-    fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime2);
-
-    // Create extra trace packet to trigger and finalize fence trace packets.
-    mTimeStats->traceTimestamp(layerID, bufferID, 0, 0, TimeStats::FrameEvent::UNSPECIFIED);
-    tracingSession->StopBlocking();
-
-    std::vector<char> raw_trace = tracingSession->ReadTraceBlocking();
-    ASSERT_GT(raw_trace.size(), 0);
-
-    perfetto::protos::Trace trace;
-    ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), int(raw_trace.size())));
-    ASSERT_FALSE(trace.packet().empty());
-    EXPECT_EQ(trace.packet().size(), 2);
-
-    const auto& packet1 = trace.packet().Get(0);
-    ASSERT_TRUE(packet1.has_timestamp());
-    EXPECT_EQ(packet1.timestamp(), startTime1);
-    ASSERT_TRUE(packet1.has_graphics_frame_event());
-    ASSERT_TRUE(packet1.graphics_frame_event().has_buffer_event());
-    ASSERT_TRUE(packet1.graphics_frame_event().buffer_event().has_duration_ns());
-    const auto& buffer_event1 = packet1.graphics_frame_event().buffer_event();
-    EXPECT_EQ(buffer_event1.duration_ns(), duration);
-
-    const auto& packet2 = trace.packet().Get(1);
-    ASSERT_TRUE(packet2.has_timestamp());
-    EXPECT_EQ(packet2.timestamp(), startTime2);
-    ASSERT_TRUE(packet2.has_graphics_frame_event());
-    ASSERT_TRUE(packet2.graphics_frame_event().has_buffer_event());
-    ASSERT_TRUE(packet2.graphics_frame_event().buffer_event().has_duration_ns());
-    const auto& buffer_event2 = packet2.graphics_frame_event().buffer_event();
-    EXPECT_EQ(buffer_event2.duration_ns(), duration);
-}
-
 TEST_F(TimeStatsTest, canEnableAndDisableTimeStats) {
     EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
     ASSERT_TRUE(mTimeStats->isEnabled());
diff --git a/services/surfaceflinger/tests/unittests/mock/MockFrameTracer.cpp b/services/surfaceflinger/tests/unittests/mock/MockFrameTracer.cpp
new file mode 100644
index 0000000..358dfdb
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/mock/MockFrameTracer.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2019 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.
+ */
+
+#include "mock/MockFrameTracer.h"
+
+namespace android {
+namespace mock {
+
+// Explicit default instantiation is recommended.
+FrameTracer::FrameTracer() = default;
+FrameTracer::~FrameTracer() = default;
+
+} // namespace mock
+} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/mock/MockFrameTracer.h b/services/surfaceflinger/tests/unittests/mock/MockFrameTracer.h
new file mode 100644
index 0000000..f768b81
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/mock/MockFrameTracer.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2019 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.
+ */
+
+#pragma once
+
+#include <gmock/gmock.h>
+
+#include "FrameTracer/FrameTracer.h"
+
+namespace android {
+namespace mock {
+
+class FrameTracer : public android::FrameTracer {
+public:
+    FrameTracer();
+    ~FrameTracer();
+
+    MOCK_METHOD0(initialize, void());
+    MOCK_METHOD0(registerDataSource, void());
+    MOCK_METHOD2(traceNewLayer, void(int32_t, const std::string&));
+    MOCK_METHOD6(traceTimestamp,
+                 void(int32_t, uint64_t, uint64_t, nsecs_t, FrameEvent::BufferEventType, nsecs_t));
+    MOCK_METHOD6(traceFence,
+                 void(int32_t, uint64_t, uint64_t, const std::shared_ptr<FenceTime>&,
+                      FrameEvent::BufferEventType, nsecs_t));
+    MOCK_METHOD0(miniDump, std::string());
+};
+
+} // namespace mock
+} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/mock/MockTimeStats.h b/services/surfaceflinger/tests/unittests/mock/MockTimeStats.h
index 542c70a..b1634a8 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockTimeStats.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockTimeStats.h
@@ -28,14 +28,6 @@
     TimeStats();
     ~TimeStats() override;
 
-    MOCK_METHOD0(initializeTracing, void());
-    MOCK_METHOD0(registerTracingDataSource, void());
-    MOCK_METHOD2(traceNewLayer, void(int32_t, const std::string&));
-    MOCK_METHOD6(traceTimestamp,
-                 void(int32_t, uint64_t, uint64_t, nsecs_t, FrameEvent::BufferEventType, nsecs_t));
-    MOCK_METHOD6(traceFence,
-                 void(int32_t, uint64_t, uint64_t, const std::shared_ptr<FenceTime>&,
-                      FrameEvent::BufferEventType, nsecs_t));
     MOCK_METHOD3(parseArgs, void(bool, const Vector<String16>&, std::string&));
     MOCK_METHOD0(isEnabled, bool());
     MOCK_METHOD0(miniDump, std::string());