Add synchronous SurfaceFlinger tracing

We want to collect traces without impacting composition so by default
we collect traces in another thread while holding a tracing lock when
current state is copied over to drawing state. But this has some
issues. If the tracing thread is not scheduled before the next frame
is composed, we may miss a state. If we need to collect composition
state then we may access states that are currently being modified by
the drawing thread.

To counter this the caller can pass in a TRACE_SYNC flag which will
force the trace to be collected in the drawing thread after
composition. This can be used by tests which don't care about the perf
impact caused by the sync tracing.

This change also fixes threading bugs highlighted in b/154155922

Finally we add a flag TRACE_BUFFERS to capture buffer latches as
well. This is used for Blast buffer tests.

Bug: 169849887, 153739621
Fixes: 154155922
Test: enable tracing with flags, on hwasan builds
Change-Id: I58512cdc98745398b460fa8e7798eb809bd2b0ae
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 7b045af..576f0fd 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1850,16 +1850,18 @@
 
     bool refreshNeeded;
     {
-        ConditionalLockGuard<std::mutex> lock(mTracingLock, mTracingEnabled);
+        mTracePostComposition = mTracing.flagIsSet(SurfaceTracing::TRACE_COMPOSITION) ||
+                mTracing.flagIsSet(SurfaceTracing::TRACE_SYNC) ||
+                mTracing.flagIsSet(SurfaceTracing::TRACE_BUFFERS);
+        const bool tracePreComposition = mTracingEnabled && !mTracePostComposition;
+        ConditionalLockGuard<std::mutex> lock(mTracingLock, tracePreComposition);
 
         mFrameTimeline->setSfWakeUp(vsyncId, frameStart);
 
         refreshNeeded = handleMessageTransaction();
         refreshNeeded |= handleMessageInvalidate();
-        if (mTracingEnabled) {
-            mAddCompositionStateToTrace =
-                    mTracing.flagIsSetLocked(SurfaceTracing::TRACE_COMPOSITION);
-            if (mVisibleRegionsDirty && !mAddCompositionStateToTrace) {
+        if (tracePreComposition) {
+            if (mVisibleRegionsDirty) {
                 mTracing.notifyLocked("visibleRegionsDirty");
             }
         }
@@ -2009,12 +2011,15 @@
     modulateVsync(&VsyncModulator::onDisplayRefresh, usedGpuComposition);
 
     mLayersWithQueuedFrames.clear();
-    if (mVisibleRegionsDirty) {
-        mVisibleRegionsDirty = false;
-        if (mTracingEnabled && mAddCompositionStateToTrace) {
+    if (mTracingEnabled && mTracePostComposition) {
+        // This may block if SurfaceTracing is running in sync mode.
+        if (mVisibleRegionsDirty) {
             mTracing.notify("visibleRegionsDirty");
+        } else if (mTracing.flagIsSet(SurfaceTracing::TRACE_BUFFERS)) {
+            mTracing.notify("bufferLatched");
         }
     }
+    mVisibleRegionsDirty = false;
 
     if (mCompositionEngine->needsAnotherUpdate()) {
         signalLayerUpdate();
@@ -4279,7 +4284,7 @@
 
 status_t SurfaceFlinger::dumpCritical(int fd, const DumpArgs&, bool asProto) {
     if (asProto && mTracing.isEnabled()) {
-        mTracing.writeToFileAsync();
+        mTracing.writeToFile();
     }
 
     return doDump(fd, DumpArgs(), asProto);
@@ -5103,19 +5108,19 @@
             }
             case 1025: { // Set layer tracing
                 n = data.readInt32();
+                bool tracingEnabledChanged;
                 if (n) {
                     ALOGD("LayerTracing enabled");
-                    mTracingEnabledChanged = mTracing.enable();
-                    reply->writeInt32(NO_ERROR);
+                    tracingEnabledChanged = mTracing.enable();
+                    if (tracingEnabledChanged) {
+                        schedule([&]() MAIN_THREAD { mTracing.notify("start"); }).wait();
+                    }
                 } else {
                     ALOGD("LayerTracing disabled");
-                    mTracingEnabledChanged = mTracing.disable();
-                    if (mTracingEnabledChanged) {
-                        reply->writeInt32(mTracing.writeToFile());
-                    } else {
-                        reply->writeInt32(NO_ERROR);
-                    }
+                    tracingEnabledChanged = mTracing.disable();
                 }
+                mTracingEnabledChanged = tracingEnabledChanged;
+                reply->writeInt32(NO_ERROR);
                 return NO_ERROR;
             }
             case 1026: { // Get layer tracing status
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 5bb5a0d..9db09f0 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -1134,7 +1134,7 @@
     SurfaceTracing mTracing{*this};
     std::mutex mTracingLock;
     bool mTracingEnabled = false;
-    bool mAddCompositionStateToTrace = false;
+    bool mTracePostComposition = false;
     std::atomic<bool> mTracingEnabledChanged = false;
 
     const std::shared_ptr<TimeStats> mTimeStats;
diff --git a/services/surfaceflinger/SurfaceTracing.cpp b/services/surfaceflinger/SurfaceTracing.cpp
index d84ce69..1d1f0c5 100644
--- a/services/surfaceflinger/SurfaceTracing.cpp
+++ b/services/surfaceflinger/SurfaceTracing.cpp
@@ -14,9 +14,6 @@
  * limitations under the License.
  */
 
-// TODO(b/129481165): remove the #pragma below and fix conversion issues
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wconversion"
 #undef LOG_TAG
 #define LOG_TAG "SurfaceTracing"
 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
@@ -32,65 +29,65 @@
 
 namespace android {
 
-SurfaceTracing::SurfaceTracing(SurfaceFlinger& flinger)
-      : mFlinger(flinger), mSfLock(flinger.mTracingLock) {}
+SurfaceTracing::SurfaceTracing(SurfaceFlinger& flinger) : mFlinger(flinger) {}
 
-void SurfaceTracing::mainLoop() {
-    bool enabled = addFirstEntry();
-    while (enabled) {
-        LayersTraceProto entry = traceWhenNotified();
-        enabled = addTraceToBuffer(entry);
-    }
-}
-
-bool SurfaceTracing::addFirstEntry() {
-    LayersTraceProto entry;
-    {
-        std::scoped_lock lock(mSfLock);
-        entry = traceLayersLocked("tracing.enable");
-    }
-    return addTraceToBuffer(entry);
-}
-
-LayersTraceProto SurfaceTracing::traceWhenNotified() {
-    std::unique_lock<std::mutex> lock(mSfLock);
-    mCanStartTrace.wait(lock);
-    android::base::ScopedLockAssertion assumeLock(mSfLock);
-    LayersTraceProto entry = traceLayersLocked(mWhere);
-    mTracingInProgress = false;
-    mMissedTraceEntries = 0;
-    lock.unlock();
-    return entry;
-}
-
-bool SurfaceTracing::addTraceToBuffer(LayersTraceProto& entry) {
+bool SurfaceTracing::enable() {
     std::scoped_lock lock(mTraceLock);
-    mBuffer.emplace(std::move(entry));
-    if (mWriteToFile) {
-        writeProtoFileLocked();
-        mWriteToFile = false;
+    if (mEnabled) {
+        return false;
     }
+
+    if (flagIsSet(TRACE_SYNC)) {
+        runner = std::make_unique<SurfaceTracing::Runner>(mFlinger, mConfig);
+    } else {
+        runner = std::make_unique<SurfaceTracing::AsyncRunner>(mFlinger, mConfig,
+                                                               mFlinger.mTracingLock);
+    }
+    mEnabled = true;
+    return true;
+}
+
+bool SurfaceTracing::disable() {
+    std::scoped_lock lock(mTraceLock);
+    if (!mEnabled) {
+        return false;
+    }
+    mEnabled = false;
+    runner->stop();
+    return true;
+}
+
+bool SurfaceTracing::isEnabled() const {
+    std::scoped_lock lock(mTraceLock);
     return mEnabled;
 }
 
+status_t SurfaceTracing::writeToFile() {
+    std::scoped_lock lock(mTraceLock);
+    if (!mEnabled) {
+        return STATUS_OK;
+    }
+    return runner->writeToFile();
+}
+
 void SurfaceTracing::notify(const char* where) {
-    std::scoped_lock lock(mSfLock);
-    notifyLocked(where);
+    if (mEnabled) {
+        runner->notify(where);
+    }
 }
 
 void SurfaceTracing::notifyLocked(const char* where) {
-    mWhere = where;
-    if (mTracingInProgress) {
-        mMissedTraceEntries++;
+    if (mEnabled) {
+        runner->notifyLocked(where);
     }
-    mTracingInProgress = true;
-    mCanStartTrace.notify_one();
 }
 
-void SurfaceTracing::writeToFileAsync() {
+void SurfaceTracing::dump(std::string& result) const {
     std::scoped_lock lock(mTraceLock);
-    mWriteToFile = true;
-    mCanStartTrace.notify_one();
+    base::StringAppendF(&result, "Tracing state: %s\n", mEnabled ? "enabled" : "disabled");
+    if (mEnabled) {
+        runner->dump(result);
+    }
 }
 
 void SurfaceTracing::LayersTraceBuffer::reset(size_t newSize) {
@@ -101,12 +98,12 @@
 }
 
 void SurfaceTracing::LayersTraceBuffer::emplace(LayersTraceProto&& proto) {
-    auto protoSize = proto.ByteSize();
+    size_t protoSize = static_cast<size_t>(proto.ByteSize());
     while (mUsedInBytes + protoSize > mSizeInBytes) {
         if (mStorage.empty()) {
             return;
         }
-        mUsedInBytes -= mStorage.front().ByteSize();
+        mUsedInBytes -= static_cast<size_t>(mStorage.front().ByteSize());
         mStorage.pop();
     }
     mUsedInBytes += protoSize;
@@ -115,7 +112,7 @@
 }
 
 void SurfaceTracing::LayersTraceBuffer::flush(LayersTraceFileProto* fileProto) {
-    fileProto->mutable_entry()->Reserve(mStorage.size());
+    fileProto->mutable_entry()->Reserve(static_cast<int>(mStorage.size()));
 
     while (!mStorage.empty()) {
         auto entry = fileProto->add_entry();
@@ -124,85 +121,21 @@
     }
 }
 
-bool SurfaceTracing::enable() {
-    std::scoped_lock lock(mTraceLock);
-
-    if (mEnabled) {
-        return false;
-    }
-
-    mBuffer.reset(mBufferSize);
-    mEnabled = true;
-    mThread = std::thread(&SurfaceTracing::mainLoop, this);
-    return true;
+SurfaceTracing::Runner::Runner(SurfaceFlinger& flinger, SurfaceTracing::Config& config)
+      : mFlinger(flinger), mConfig(config) {
+    mBuffer.setSize(mConfig.bufferSize);
 }
 
-status_t SurfaceTracing::writeToFile() {
-    std::thread thread;
-    {
-        std::scoped_lock lock(mTraceLock);
-        thread = std::move(mThread);
-    }
-    thread.join();
-    return mLastErr;
+void SurfaceTracing::Runner::notify(const char* where) {
+    LayersTraceProto entry = traceLayers(where);
+    mBuffer.emplace(std::move(entry));
 }
 
-bool SurfaceTracing::disable() {
-    std::scoped_lock lock(mTraceLock);
-
-    if (!mEnabled) {
-        return false;
-    }
-
-    mEnabled = false;
-    mWriteToFile = true;
-    mCanStartTrace.notify_all();
-    return true;
+status_t SurfaceTracing::Runner::stop() {
+    return writeToFile();
 }
 
-bool SurfaceTracing::isEnabled() const {
-    std::scoped_lock lock(mTraceLock);
-    return mEnabled;
-}
-
-void SurfaceTracing::setBufferSize(size_t bufferSizeInByte) {
-    std::scoped_lock lock(mTraceLock);
-    mBufferSize = bufferSizeInByte;
-    mBuffer.setSize(bufferSizeInByte);
-}
-
-void SurfaceTracing::setTraceFlags(uint32_t flags) {
-    std::scoped_lock lock(mSfLock);
-    mTraceFlags = flags;
-}
-
-LayersTraceProto SurfaceTracing::traceLayersLocked(const char* where) {
-    ATRACE_CALL();
-
-    LayersTraceProto entry;
-    entry.set_elapsed_realtime_nanos(elapsedRealtimeNano());
-    entry.set_where(where);
-    LayersProto layers(mFlinger.dumpDrawingStateProto(mTraceFlags));
-
-    if (flagIsSetLocked(SurfaceTracing::TRACE_EXTRA)) {
-        mFlinger.dumpOffscreenLayersProto(layers);
-    }
-    entry.mutable_layers()->Swap(&layers);
-
-    if (mTraceFlags & SurfaceTracing::TRACE_HWC) {
-        std::string hwcDump;
-        mFlinger.dumpHwc(hwcDump);
-        entry.set_hwc_blob(hwcDump);
-    }
-    if (!flagIsSetLocked(SurfaceTracing::TRACE_COMPOSITION)) {
-        entry.set_excludes_composition_state(true);
-    }
-    entry.set_missed_entries(mMissedTraceEntries);
-
-    return entry;
-}
-
-void SurfaceTracing::writeProtoFileLocked() {
+status_t SurfaceTracing::Runner::writeToFile() {
     ATRACE_CALL();
 
     LayersTraceFileProto fileProto;
@@ -211,33 +144,114 @@
     fileProto.set_magic_number(uint64_t(LayersTraceFileProto_MagicNumber_MAGIC_NUMBER_H) << 32 |
                                LayersTraceFileProto_MagicNumber_MAGIC_NUMBER_L);
     mBuffer.flush(&fileProto);
-    mBuffer.reset(mBufferSize);
+    mBuffer.reset(mConfig.bufferSize);
 
     if (!fileProto.SerializeToString(&output)) {
         ALOGE("Could not save the proto file! Permission denied");
-        mLastErr = PERMISSION_DENIED;
+        return PERMISSION_DENIED;
     }
 
     // -rw-r--r--
     const mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
-    if (!android::base::WriteStringToFile(output, kDefaultFileName, mode, getuid(), getgid(),
+    if (!android::base::WriteStringToFile(output, DEFAULT_FILE_NAME, mode, getuid(), getgid(),
                                           true)) {
         ALOGE("Could not save the proto file! There are missing fields");
-        mLastErr = PERMISSION_DENIED;
+        return PERMISSION_DENIED;
     }
 
-    mLastErr = NO_ERROR;
+    return NO_ERROR;
 }
 
-void SurfaceTracing::dump(std::string& result) const {
-    std::scoped_lock lock(mTraceLock);
-    base::StringAppendF(&result, "Tracing state: %s\n", mEnabled ? "enabled" : "disabled");
+LayersTraceProto SurfaceTracing::Runner::traceLayers(const char* where) {
+    ATRACE_CALL();
+
+    LayersTraceProto entry;
+    entry.set_elapsed_realtime_nanos(elapsedRealtimeNano());
+    entry.set_where(where);
+    LayersProto layers(mFlinger.dumpDrawingStateProto(mConfig.flags));
+
+    if (flagIsSet(SurfaceTracing::TRACE_EXTRA)) {
+        mFlinger.dumpOffscreenLayersProto(layers);
+    }
+    entry.mutable_layers()->Swap(&layers);
+
+    if (flagIsSet(SurfaceTracing::TRACE_HWC)) {
+        std::string hwcDump;
+        mFlinger.dumpHwc(hwcDump);
+        entry.set_hwc_blob(hwcDump);
+    }
+    if (!flagIsSet(SurfaceTracing::TRACE_COMPOSITION)) {
+        entry.set_excludes_composition_state(true);
+    }
+    entry.set_missed_entries(mMissedTraceEntries);
+
+    return entry;
+}
+
+void SurfaceTracing::Runner::dump(std::string& result) const {
     base::StringAppendF(&result, "  number of entries: %zu (%.2fMB / %.2fMB)\n",
                         mBuffer.frameCount(), float(mBuffer.used()) / float(1_MB),
                         float(mBuffer.size()) / float(1_MB));
 }
 
-} // namespace android
+SurfaceTracing::AsyncRunner::AsyncRunner(SurfaceFlinger& flinger, SurfaceTracing::Config& config,
+                                         std::mutex& sfLock)
+      : SurfaceTracing::Runner(flinger, config), mSfLock(sfLock) {
+    mEnabled = true;
+    mThread = std::thread(&AsyncRunner::loop, this);
+}
 
-// TODO(b/129481165): remove the #pragma below and fix conversion issues
-#pragma clang diagnostic pop // ignored "-Wconversion"
+void SurfaceTracing::AsyncRunner::loop() {
+    while (mEnabled) {
+        LayersTraceProto entry;
+        bool entryAdded = traceWhenNotified(&entry);
+        if (entryAdded) {
+            mBuffer.emplace(std::move(entry));
+        }
+        if (mWriteToFile) {
+            Runner::writeToFile();
+            mWriteToFile = false;
+        }
+    }
+}
+
+bool SurfaceTracing::AsyncRunner::traceWhenNotified(LayersTraceProto* outProto) {
+    std::unique_lock<std::mutex> lock(mSfLock);
+    mCanStartTrace.wait(lock);
+    if (!mAddEntry) {
+        return false;
+    }
+    *outProto = traceLayers(mWhere);
+    mAddEntry = false;
+    mMissedTraceEntries = 0;
+    return true;
+}
+
+void SurfaceTracing::AsyncRunner::notify(const char* where) {
+    std::scoped_lock lock(mSfLock);
+    notifyLocked(where);
+}
+
+void SurfaceTracing::AsyncRunner::notifyLocked(const char* where) {
+    mWhere = where;
+    if (mAddEntry) {
+        mMissedTraceEntries++;
+    }
+    mAddEntry = true;
+    mCanStartTrace.notify_one();
+}
+
+status_t SurfaceTracing::AsyncRunner::writeToFile() {
+    mWriteToFile = true;
+    mCanStartTrace.notify_one();
+    return STATUS_OK;
+}
+
+status_t SurfaceTracing::AsyncRunner::stop() {
+    mEnabled = false;
+    mCanStartTrace.notify_one();
+    mThread.join();
+    return Runner::writeToFile();
+}
+
+} // namespace android
diff --git a/services/surfaceflinger/SurfaceTracing.h b/services/surfaceflinger/SurfaceTracing.h
index f208eb8..576bba7 100644
--- a/services/surfaceflinger/SurfaceTracing.h
+++ b/services/surfaceflinger/SurfaceTracing.h
@@ -32,25 +32,31 @@
 namespace android {
 
 class SurfaceFlinger;
-
 constexpr auto operator""_MB(unsigned long long const num) {
     return num * 1024 * 1024;
 }
 /*
- * SurfaceTracing records layer states during surface flinging.
+ * SurfaceTracing records layer states during surface flinging. Manages tracing state and
+ * configuration.
  */
 class SurfaceTracing {
 public:
-    explicit SurfaceTracing(SurfaceFlinger& flinger);
+    SurfaceTracing(SurfaceFlinger& flinger);
     bool enable();
     bool disable();
     status_t writeToFile();
     bool isEnabled() const;
+    /*
+     * Adds a trace entry, must be called from the drawing thread or while holding the
+     * SurfaceFlinger tracing lock.
+     */
     void notify(const char* where);
-    void notifyLocked(const char* where) NO_THREAD_SAFETY_ANALYSIS /* REQUIRES(mSfLock) */;
+    /*
+     * Adds a trace entry, called while holding the SurfaceFlinger tracing lock.
+     */
+    void notifyLocked(const char* where) /* REQUIRES(mSfLock) */;
 
-    void setBufferSize(size_t bufferSizeInByte);
-    void writeToFileAsync();
+    void setBufferSize(size_t bufferSizeInBytes) { mConfig.bufferSize = bufferSizeInBytes; }
     void dump(std::string& result) const;
 
     enum : uint32_t {
@@ -59,18 +65,34 @@
         TRACE_COMPOSITION = 1 << 2,
         TRACE_EXTRA = 1 << 3,
         TRACE_HWC = 1 << 4,
-        TRACE_ALL = 0xffffffff
+        // Add non-geometry composition changes to the trace.
+        TRACE_BUFFERS = 1 << 5,
+        // Add entries from the drawing thread post composition.
+        TRACE_SYNC = 1 << 6,
+        TRACE_ALL = TRACE_CRITICAL | TRACE_INPUT | TRACE_COMPOSITION | TRACE_EXTRA,
     };
-    void setTraceFlags(uint32_t flags);
-    bool flagIsSetLocked(uint32_t flags) NO_THREAD_SAFETY_ANALYSIS /* REQUIRES(mSfLock) */ {
-        return (mTraceFlags & flags) == flags;
-    }
+    void setTraceFlags(uint32_t flags) { mConfig.flags = flags; }
+    bool flagIsSet(uint32_t flags) { return (mConfig.flags & flags) == flags; }
 
 private:
-    static constexpr auto kDefaultBufferCapInByte = 5_MB;
-    static constexpr auto kDefaultFileName = "/data/misc/wmtrace/layers_trace.pb";
+    class Runner;
+    static constexpr auto DEFAULT_BUFFER_SIZE = 5_MB;
+    static constexpr auto DEFAULT_FILE_NAME = "/data/misc/wmtrace/layers_trace.pb";
 
-    class LayersTraceBuffer { // ring buffer
+    SurfaceFlinger& mFlinger;
+    mutable std::mutex mTraceLock;
+    bool mEnabled = false;
+    std::unique_ptr<Runner> runner;
+
+    struct Config {
+        uint32_t flags = TRACE_CRITICAL | TRACE_INPUT;
+        size_t bufferSize = DEFAULT_BUFFER_SIZE;
+    } mConfig;
+
+    /*
+     * ring buffer.
+     */
+    class LayersTraceBuffer {
     public:
         size_t size() const { return mSizeInBytes; }
         size_t used() const { return mUsedInBytes; }
@@ -83,35 +105,59 @@
 
     private:
         size_t mUsedInBytes = 0U;
-        size_t mSizeInBytes = 0U;
+        size_t mSizeInBytes = DEFAULT_BUFFER_SIZE;
         std::queue<LayersTraceProto> mStorage;
     };
 
-    void mainLoop();
-    bool addFirstEntry();
-    LayersTraceProto traceWhenNotified();
-    LayersTraceProto traceLayersLocked(const char* where) REQUIRES(mSfLock);
+    /*
+     * Implements a synchronous way of adding trace entries. This must be called
+     * from the drawing thread.
+     */
+    class Runner {
+    public:
+        Runner(SurfaceFlinger& flinger, SurfaceTracing::Config& config);
+        virtual ~Runner() = default;
+        virtual status_t stop();
+        virtual status_t writeToFile();
+        virtual void notify(const char* where);
+        /* Cannot be called with a synchronous runner. */
+        virtual void notifyLocked(const char* /* where */) {}
+        void dump(std::string& result) const;
 
-    // Returns true if trace is enabled.
-    bool addTraceToBuffer(LayersTraceProto& entry);
-    void writeProtoFileLocked() REQUIRES(mTraceLock);
+    protected:
+        bool flagIsSet(uint32_t flags) { return (mConfig.flags & flags) == flags; }
+        SurfaceFlinger& mFlinger;
+        SurfaceTracing::Config mConfig;
+        SurfaceTracing::LayersTraceBuffer mBuffer;
+        uint32_t mMissedTraceEntries = 0;
+        LayersTraceProto traceLayers(const char* where);
+    };
 
-    SurfaceFlinger& mFlinger;
-    status_t mLastErr = NO_ERROR;
-    std::thread mThread;
-    std::condition_variable mCanStartTrace;
+    /*
+     * Implements asynchronous way to add trace entries called from a separate thread while holding
+     * the SurfaceFlinger tracing lock. Trace entries may be missed if the tracing thread is not
+     * scheduled in time.
+     */
+    class AsyncRunner : public Runner {
+    public:
+        AsyncRunner(SurfaceFlinger& flinger, SurfaceTracing::Config& config, std::mutex& sfLock);
+        virtual ~AsyncRunner() = default;
+        status_t stop() override;
+        status_t writeToFile() override;
+        void notify(const char* where) override;
+        void notifyLocked(const char* where);
 
-    std::mutex& mSfLock;
-    uint32_t mTraceFlags GUARDED_BY(mSfLock) = TRACE_CRITICAL | TRACE_INPUT;
-    const char* mWhere GUARDED_BY(mSfLock) = "";
-    uint32_t mMissedTraceEntries GUARDED_BY(mSfLock) = 0;
-    bool mTracingInProgress GUARDED_BY(mSfLock) = false;
-
-    mutable std::mutex mTraceLock;
-    LayersTraceBuffer mBuffer GUARDED_BY(mTraceLock);
-    size_t mBufferSize GUARDED_BY(mTraceLock) = kDefaultBufferCapInByte;
-    bool mEnabled GUARDED_BY(mTraceLock) = false;
-    bool mWriteToFile GUARDED_BY(mTraceLock) = false;
+    private:
+        std::mutex& mSfLock;
+        std::condition_variable mCanStartTrace;
+        std::thread mThread;
+        const char* mWhere = "";
+        bool mWriteToFile = false;
+        bool mEnabled = false;
+        bool mAddEntry = false;
+        void loop();
+        bool traceWhenNotified(LayersTraceProto* outProto);
+    };
 };
 
 } // namespace android
diff --git a/services/surfaceflinger/layerproto/layerstrace.proto b/services/surfaceflinger/layerproto/layerstrace.proto
index acf621e..990f3cf 100644
--- a/services/surfaceflinger/layerproto/layerstrace.proto
+++ b/services/surfaceflinger/layerproto/layerstrace.proto
@@ -42,7 +42,7 @@
 /* one window manager trace entry. */
 message LayersTraceProto {
     /* required: elapsed realtime in nanos since boot of when this entry was logged */
-    optional fixed64 elapsed_realtime_nanos = 1;
+    optional sfixed64 elapsed_realtime_nanos = 1;
 
     /* where the trace originated */
     optional string where = 2;
@@ -56,5 +56,5 @@
     optional bool excludes_composition_state = 5;
 
     /* Number of missed entries since the last entry was recorded. */
-    optional int32 missed_entries = 6;
+    optional uint32 missed_entries = 6;
 }