LayerTraceGenerator: Fix duplicate layer ids

Layers can be created from API calls on the binder thread or
by surfaceflinger on the main thread for mirroring and
BSL background layers. Transaction traces keep track of
layer creation API calls to recreate layers when generating
the layer trace.

However, there was a possibility that new layers would be
recorded with a set of transactions that were applied with
an earlier vsync. This is harmless except we could end up
creating layers with duplicate layer ids since layers created
via binder would get an injected sequence id while main
thread created layers would use the global counter.

Test: atest transactiontrace_testsuite
Bug: 235376060
Change-Id: Ia11839d1880bc131ab5314779281c93393d6742f
diff --git a/services/surfaceflinger/Tracing/TransactionProtoParser.cpp b/services/surfaceflinger/Tracing/TransactionProtoParser.cpp
index 8ec6c99..65918f6 100644
--- a/services/surfaceflinger/Tracing/TransactionProtoParser.cpp
+++ b/services/surfaceflinger/Tracing/TransactionProtoParser.cpp
@@ -498,8 +498,13 @@
         inputInfo.replaceTouchableRegionWithCrop =
                 windowInfoProto.replace_touchable_region_with_crop();
         int64_t layerId = windowInfoProto.crop_layer_id();
-        inputInfo.touchableRegionCropHandle =
-                mMapper->getLayerHandle(static_cast<int32_t>(layerId));
+        if (layerId != -1) {
+            inputInfo.touchableRegionCropHandle =
+                    mMapper->getLayerHandle(static_cast<int32_t>(layerId));
+        } else {
+            inputInfo.touchableRegionCropHandle = nullptr;
+        }
+
         layer.windowInfoHandle = sp<gui::WindowInfoHandle>::make(inputInfo);
     }
     if (proto.what() & layer_state_t::eBackgroundColorChanged) {
diff --git a/services/surfaceflinger/Tracing/TransactionTracing.cpp b/services/surfaceflinger/Tracing/TransactionTracing.cpp
index 6381758..e53feca 100644
--- a/services/surfaceflinger/Tracing/TransactionTracing.cpp
+++ b/services/surfaceflinger/Tracing/TransactionTracing.cpp
@@ -152,17 +152,33 @@
     mTransactionQueue.push(state);
 }
 
-void TransactionTracing::addCommittedTransactions(std::vector<TransactionState>& transactions,
-                                                  int64_t vsyncId) {
+TransactionTracing::CommittedTransactions&
+TransactionTracing::findOrCreateCommittedTransactionRecord(int64_t vsyncId) {
+    for (auto& pendingTransaction : mPendingTransactions) {
+        if (pendingTransaction.vsyncId == vsyncId) {
+            return pendingTransaction;
+        }
+    }
+
     CommittedTransactions committedTransactions;
     committedTransactions.vsyncId = vsyncId;
     committedTransactions.timestamp = systemTime();
+    mPendingTransactions.emplace_back(committedTransactions);
+    return mPendingTransactions.back();
+}
+
+void TransactionTracing::onLayerAddedToDrawingState(int layerId, int64_t vsyncId) {
+    CommittedTransactions& committedTransactions = findOrCreateCommittedTransactionRecord(vsyncId);
+    committedTransactions.createdLayerIds.emplace_back(layerId);
+}
+
+void TransactionTracing::addCommittedTransactions(std::vector<TransactionState>& transactions,
+                                                  int64_t vsyncId) {
+    CommittedTransactions& committedTransactions = findOrCreateCommittedTransactionRecord(vsyncId);
     committedTransactions.transactionIds.reserve(transactions.size());
     for (const auto& transaction : transactions) {
         committedTransactions.transactionIds.emplace_back(transaction.id);
     }
-
-    mPendingTransactions.emplace_back(committedTransactions);
     tryPushToTracingThread();
 }
 
@@ -235,15 +251,24 @@
     for (const CommittedTransactions& entry : committedTransactions) {
         entryProto.set_elapsed_realtime_nanos(entry.timestamp);
         entryProto.set_vsync_id(entry.vsyncId);
-        entryProto.mutable_added_layers()->Reserve(static_cast<int32_t>(mCreatedLayers.size()));
-        for (auto& newLayer : mCreatedLayers) {
-            entryProto.mutable_added_layers()->Add(std::move(newLayer));
+        entryProto.mutable_added_layers()->Reserve(
+                static_cast<int32_t>(entry.createdLayerIds.size()));
+
+        for (const int32_t& id : entry.createdLayerIds) {
+            auto it = mCreatedLayers.find(id);
+            if (it != mCreatedLayers.end()) {
+                entryProto.mutable_added_layers()->Add(std::move(it->second));
+                mCreatedLayers.erase(it);
+            } else {
+                ALOGW("Could not created layer with id %d", id);
+            }
         }
+
         entryProto.mutable_removed_layers()->Reserve(static_cast<int32_t>(removedLayers.size()));
         for (auto& removedLayer : removedLayers) {
             entryProto.mutable_removed_layers()->Add(removedLayer);
+            mCreatedLayers.erase(removedLayer);
         }
-        mCreatedLayers.clear();
         entryProto.mutable_transactions()->Reserve(
                 static_cast<int32_t>(entry.transactionIds.size()));
         for (const uint64_t& id : entry.transactionIds) {
@@ -304,7 +329,7 @@
         ALOGW("Duplicate handles found. %p", layerHandle);
     }
     mLayerHandles[layerHandle] = layerId;
-    mCreatedLayers.push_back(mProtoParser.toProto(args));
+    mCreatedLayers[layerId] = mProtoParser.toProto(args);
 }
 
 void TransactionTracing::onMirrorLayerAdded(BBinder* layerHandle, int layerId,
@@ -315,7 +340,7 @@
         ALOGW("Duplicate handles found. %p", layerHandle);
     }
     mLayerHandles[layerHandle] = layerId;
-    mCreatedLayers.emplace_back(mProtoParser.toProto(args));
+    mCreatedLayers[layerId] = mProtoParser.toProto(args);
 }
 
 void TransactionTracing::onLayerRemoved(int32_t layerId) {
diff --git a/services/surfaceflinger/Tracing/TransactionTracing.h b/services/surfaceflinger/Tracing/TransactionTracing.h
index 4c291f9..2f5ee87 100644
--- a/services/surfaceflinger/Tracing/TransactionTracing.h
+++ b/services/surfaceflinger/Tracing/TransactionTracing.h
@@ -64,6 +64,7 @@
                             int mirrorFromId);
     void onLayerRemoved(int layerId);
     void onHandleRemoved(BBinder* layerHandle);
+    void onLayerAddedToDrawingState(int layerId, int64_t vsyncId);
     void dump(std::string&) const;
     static constexpr auto CONTINUOUS_TRACING_BUFFER_SIZE = 512 * 1024;
     static constexpr auto ACTIVE_TRACING_BUFFER_SIZE = 100 * 1024 * 1024;
@@ -81,7 +82,7 @@
             GUARDED_BY(mTraceLock);
     LocklessStack<proto::TransactionState> mTransactionQueue;
     nsecs_t mStartingTimestamp GUARDED_BY(mTraceLock);
-    std::vector<proto::LayerCreationArgs> mCreatedLayers GUARDED_BY(mTraceLock);
+    std::unordered_map<int, proto::LayerCreationArgs> mCreatedLayers GUARDED_BY(mTraceLock);
     std::unordered_map<BBinder* /* layerHandle */, int32_t /* layerId */> mLayerHandles
             GUARDED_BY(mTraceLock);
     std::vector<int32_t /* layerId */> mRemovedLayerHandles GUARDED_BY(mTraceLock);
@@ -100,6 +101,7 @@
     std::condition_variable mTransactionsAddedToBufferCv;
     struct CommittedTransactions {
         std::vector<uint64_t> transactionIds;
+        std::vector<int32_t> createdLayerIds;
         int64_t vsyncId;
         int64_t timestamp;
     };
@@ -117,7 +119,7 @@
     void tryPushToTracingThread() EXCLUDES(mMainThreadLock);
     void addStartingStateToProtoLocked(proto::TransactionTraceFile& proto) REQUIRES(mTraceLock);
     void updateStartingStateLocked(const proto::TransactionTraceEntry& entry) REQUIRES(mTraceLock);
-
+    CommittedTransactions& findOrCreateCommittedTransactionRecord(int64_t vsyncId);
     // TEST
     // Wait until all the committed transactions for the specified vsync id are added to the buffer.
     void flush(int64_t vsyncId) EXCLUDES(mMainThreadLock);
diff --git a/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.cpp b/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.cpp
index 5bb9d2f..ea33eb5 100644
--- a/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.cpp
+++ b/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.cpp
@@ -248,7 +248,7 @@
                     (dataMapper->mLayerHandles.find(tracingArgs.parentId) ==
                      dataMapper->mLayerHandles.end())) {
                     args.addToRoot = false;
-                } else {
+                } else if (tracingArgs.parentId != -1) {
                     parentHandle = dataMapper->getLayerHandle(tracingArgs.parentId);
                 }
                 mFlinger.createLayer(args, &outHandle, parentHandle, &outLayerId,