SF: Store transaction traces as a serialized blob

Reduce memory usage for transaction traces by storing
the data after serialization since this will pack the
messages tightly.

Test: presubmit
Test: awk '/Private_Dirty:/{ sum += $2 } END { print sum }' /proc/`pidof surfaceflinger`/smaps
Bug: 200284593
Fixes: 210078963
Change-Id: I6d6324264b112a08225bb4335b27fd19dd832d08
diff --git a/services/surfaceflinger/Tracing/RingBuffer.h b/services/surfaceflinger/Tracing/RingBuffer.h
index 281cd19..3b2626d 100644
--- a/services/surfaceflinger/Tracing/RingBuffer.h
+++ b/services/surfaceflinger/Tracing/RingBuffer.h
@@ -37,22 +37,21 @@
     size_t used() const { return mUsedInBytes; }
     size_t frameCount() const { return mStorage.size(); }
     void setSize(size_t newSize) { mSizeInBytes = newSize; }
-    EntryProto& front() { return mStorage.front(); }
-    const EntryProto& front() const { return mStorage.front(); }
-    const EntryProto& back() const { return mStorage.back(); }
+    const std::string& front() const { return mStorage.front(); }
+    const std::string& back() const { return mStorage.back(); }
 
     void reset() {
         // use the swap trick to make sure memory is released
-        std::deque<EntryProto>().swap(mStorage);
+        std::deque<std::string>().swap(mStorage);
         mUsedInBytes = 0U;
     }
 
     void writeToProto(FileProto& fileProto) {
         fileProto.mutable_entry()->Reserve(static_cast<int>(mStorage.size()) +
                                            fileProto.entry().size());
-        for (const EntryProto& entry : mStorage) {
+        for (const std::string& entry : mStorage) {
             EntryProto* entryProto = fileProto.add_entry();
-            *entryProto = entry;
+            entryProto->ParseFromString(entry);
         }
     }
 
@@ -74,28 +73,35 @@
         return NO_ERROR;
     }
 
-    std::vector<EntryProto> emplace(EntryProto&& proto) {
-        std::vector<EntryProto> replacedEntries;
-        size_t protoSize = static_cast<size_t>(proto.ByteSize());
+    std::vector<std::string> emplace(std::string&& serializedProto) {
+        std::vector<std::string> replacedEntries;
+        size_t protoSize = static_cast<size_t>(serializedProto.size());
         while (mUsedInBytes + protoSize > mSizeInBytes) {
             if (mStorage.empty()) {
                 return {};
             }
-            mUsedInBytes -= static_cast<size_t>(mStorage.front().ByteSize());
+            mUsedInBytes -= static_cast<size_t>(mStorage.front().size());
             replacedEntries.emplace_back(mStorage.front());
             mStorage.pop_front();
         }
         mUsedInBytes += protoSize;
-        mStorage.emplace_back();
-        mStorage.back().Swap(&proto);
+        mStorage.emplace_back(serializedProto);
         return replacedEntries;
     }
 
+    std::vector<std::string> emplace(EntryProto&& proto) {
+        std::string serializedProto;
+        proto.SerializeToString(&serializedProto);
+        return emplace(std::move(serializedProto));
+    }
+
     void dump(std::string& result) const {
         std::chrono::milliseconds duration(0);
         if (frameCount() > 0) {
+            EntryProto entry;
+            entry.ParseFromString(mStorage.front());
             duration = std::chrono::duration_cast<std::chrono::milliseconds>(
-                    std::chrono::nanoseconds(systemTime() - front().elapsed_realtime_nanos()));
+                    std::chrono::nanoseconds(systemTime() - entry.elapsed_realtime_nanos()));
         }
         const int64_t durationCount = duration.count();
         base::StringAppendF(&result,
@@ -107,7 +113,7 @@
 private:
     size_t mUsedInBytes = 0U;
     size_t mSizeInBytes = 0U;
-    std::deque<EntryProto> mStorage;
+    std::deque<std::string> mStorage;
 };
 
 } // namespace android
diff --git a/services/surfaceflinger/Tracing/TransactionTracing.cpp b/services/surfaceflinger/Tracing/TransactionTracing.cpp
index c1b3d2e..b5966d5 100644
--- a/services/surfaceflinger/Tracing/TransactionTracing.cpp
+++ b/services/surfaceflinger/Tracing/TransactionTracing.cpp
@@ -177,9 +177,9 @@
                                   const std::vector<int32_t>& removedLayers) {
     ATRACE_CALL();
     std::scoped_lock lock(mTraceLock);
-    std::vector<proto::TransactionTraceEntry> removedEntries;
+    std::vector<std::string> removedEntries;
+    proto::TransactionTraceEntry entryProto;
     for (const CommittedTransactions& entry : committedTransactions) {
-        proto::TransactionTraceEntry entryProto;
         entryProto.set_elapsed_realtime_nanos(entry.timestamp);
         entryProto.set_vsync_id(entry.vsyncId);
         entryProto.mutable_added_layers()->Reserve(static_cast<int32_t>(mCreatedLayers.size()));
@@ -202,13 +202,21 @@
                 ALOGW("Could not find transaction id %" PRIu64, id);
             }
         }
-        std::vector<proto::TransactionTraceEntry> entries = mBuffer->emplace(std::move(entryProto));
+
+        std::string serializedProto;
+        entryProto.SerializeToString(&serializedProto);
+        entryProto.Clear();
+        std::vector<std::string> entries = mBuffer->emplace(std::move(serializedProto));
+        removedEntries.reserve(removedEntries.size() + entries.size());
         removedEntries.insert(removedEntries.end(), std::make_move_iterator(entries.begin()),
                               std::make_move_iterator(entries.end()));
     }
 
-    for (const proto::TransactionTraceEntry& removedEntry : removedEntries) {
-        updateStartingStateLocked(removedEntry);
+    proto::TransactionTraceEntry removedEntryProto;
+    for (const std::string& removedEntry : removedEntries) {
+        removedEntryProto.ParseFromString(removedEntry);
+        updateStartingStateLocked(removedEntryProto);
+        removedEntryProto.Clear();
     }
     mTransactionsAddedToBufferCv.notify_one();
 }
@@ -220,7 +228,11 @@
     std::unique_lock<std::mutex> lock(mTraceLock);
     base::ScopedLockAssertion assumeLocked(mTraceLock);
     mTransactionsAddedToBufferCv.wait(lock, [&]() REQUIRES(mTraceLock) {
-        return mBuffer->used() > 0 && mBuffer->back().vsync_id() >= vsyncId;
+        proto::TransactionTraceEntry entry;
+        if (mBuffer->used() > 0) {
+            entry.ParseFromString(mBuffer->back());
+        }
+        return mBuffer->used() > 0 && entry.vsync_id() >= vsyncId;
     });
 }
 
diff --git a/services/surfaceflinger/tests/unittests/TransactionTracingTest.cpp b/services/surfaceflinger/tests/unittests/TransactionTracingTest.cpp
index 71c7bd9..43b09fd 100644
--- a/services/surfaceflinger/tests/unittests/TransactionTracingTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TransactionTracingTest.cpp
@@ -56,7 +56,9 @@
 
     auto bufferFront() {
         std::scoped_lock<std::mutex> lock(mTracing->mTraceLock);
-        return mTracing->mBuffer->front();
+        proto::TransactionTraceEntry entry;
+        entry.ParseFromString(mTracing->mBuffer->front());
+        return entry;
     }
 
     bool threadIsJoinable() {