[sf] fix overflow in snapshot generator

Fixes a couple of issues that caused the snapshot
builder to crash from a stack overflow:
- mirror layers were temporarily rooted to the display
with the default layer stack
- there was no check to prevent a layer from mirroring
itself (causing a cycle in the hierarchy)

Also modifies the layer trace generator to easily generate
test data for the transaction trace test suite.

Test: atest transactiontrace_testsuite
Fixes: 282110579
Change-Id: I2954f838e333b857b4b755e11666c2580d97c2b6
diff --git a/services/surfaceflinger/tests/tracing/TransactionTraceTestSuite.cpp b/services/surfaceflinger/tests/tracing/TransactionTraceTestSuite.cpp
index 2b29530..b8a5e79 100644
--- a/services/surfaceflinger/tests/tracing/TransactionTraceTestSuite.cpp
+++ b/services/surfaceflinger/tests/tracing/TransactionTraceTestSuite.cpp
@@ -59,8 +59,8 @@
         std::string actualLayersTracePath =
                 std::string(temp_dir.path) + "/" + expectedLayersFilename + "_actual";
 
-        EXPECT_TRUE(
-                LayerTraceGenerator().generate(mTransactionTrace, actualLayersTracePath.c_str()))
+        EXPECT_TRUE(LayerTraceGenerator().generate(mTransactionTrace, actualLayersTracePath.c_str(),
+                                                   /*onlyLastEntry=*/true))
                 << "Failed to generate layers trace from " << transactionTracePath;
         EXPECT_TRUE(std::filesystem::exists(std::filesystem::path(actualLayersTracePath)));
         parseLayersTraceFromFile(actualLayersTracePath.c_str(), mActualLayersTraceProto);
@@ -86,9 +86,9 @@
 std::vector<std::filesystem::path> TransactionTraceTestSuite::sTransactionTraces{};
 
 struct LayerInfo {
-    int32_t id;
+    uint64_t id;
     std::string name;
-    int32_t parent;
+    uint64_t parent;
     int z;
     uint64_t curr_frame;
     float x;
@@ -119,8 +119,8 @@
 }
 
 struct find_id : std::unary_function<LayerInfo, bool> {
-    int id;
-    find_id(int id) : id(id) {}
+    uint64_t id;
+    find_id(uint64_t id) : id(id) {}
     bool operator()(LayerInfo const& m) const { return m.id == id; }
 };
 
@@ -136,9 +136,9 @@
         touchableRegionBounds = touchableRegion.bounds();
     }
 
-    return {proto.id(),
+    return {static_cast<uint64_t>(proto.id()),
             proto.name(),
-            proto.parent(),
+            static_cast<uint64_t>(proto.parent()),
             proto.z(),
             proto.curr_frame(),
             proto.has_position() ? proto.position().x() : -1,
@@ -150,7 +150,7 @@
 
 static std::vector<LayerInfo> getLayerInfosFromProto(
         android::surfaceflinger::LayersTraceProto& entry) {
-    std::unordered_map<int32_t /* snapshotId*/, int32_t /*layerId*/> snapshotIdToLayerId;
+    std::unordered_map<uint64_t /* snapshotId*/, uint64_t /*layerId*/> snapshotIdToLayerId;
     std::vector<LayerInfo> layers;
     layers.reserve(static_cast<size_t>(entry.layers().layers_size()));
     bool mapSnapshotIdToLayerId = false;
@@ -158,7 +158,12 @@
         auto layer = entry.layers().layers(i);
         LayerInfo layerInfo = getLayerInfoFromProto(layer);
 
-        snapshotIdToLayerId[layerInfo.id] = static_cast<int32_t>(layer.original_id());
+        uint64_t layerId = layerInfo.name.find("(Mirror)") == std::string::npos
+                ? static_cast<uint64_t>(layer.original_id())
+                : static_cast<uint64_t>(layer.original_id()) | 1ull << 63;
+
+        snapshotIdToLayerId[layerInfo.id] = layerId;
+
         if (layer.original_id() != 0) {
             mapSnapshotIdToLayerId = true;
         }
@@ -172,7 +177,7 @@
     for (auto& layer : layers) {
         layer.id = snapshotIdToLayerId[layer.id];
         auto it = snapshotIdToLayerId.find(layer.parent);
-        layer.parent = it == snapshotIdToLayerId.end() ? -1 : it->second;
+        layer.parent = it == snapshotIdToLayerId.end() ? static_cast<uint64_t>(-1) : it->second;
     }
     return layers;
 }
@@ -189,7 +194,6 @@
 
     std::vector<LayerInfo> expectedLayers = getLayerInfosFromProto(expectedLastEntry);
     std::vector<LayerInfo> actualLayers = getLayerInfosFromProto(actualLastEntry);
-    ;
 
     size_t i = 0;
     for (; i < actualLayers.size() && i < expectedLayers.size(); i++) {
@@ -197,9 +201,9 @@
                                find_id(expectedLayers[i].id));
         EXPECT_NE(it, actualLayers.end());
         EXPECT_EQ(expectedLayers[i], *it);
-        ALOGV("Validating %s[%d] parent=%d z=%d frame=%" PRIu64, expectedLayers[i].name.c_str(),
-              expectedLayers[i].id, expectedLayers[i].parent, expectedLayers[i].z,
-              expectedLayers[i].curr_frame);
+        ALOGV("Validating %s[%" PRIu64 "] parent=%" PRIu64 " z=%d frame=%" PRIu64,
+              expectedLayers[i].name.c_str(), expectedLayers[i].id, expectedLayers[i].parent,
+              expectedLayers[i].z, expectedLayers[i].curr_frame);
     }
 
     EXPECT_EQ(expectedLayers.size(), actualLayers.size());
@@ -208,9 +212,9 @@
         for (size_t j = 0; j < actualLayers.size(); j++) {
             if (std::find_if(expectedLayers.begin(), expectedLayers.end(),
                              find_id(actualLayers[j].id)) == expectedLayers.end()) {
-                ALOGD("actualLayers [%d]:%s parent=%d z=%d frame=%" PRIu64, actualLayers[j].id,
-                      actualLayers[j].name.c_str(), actualLayers[j].parent, actualLayers[j].z,
-                      actualLayers[j].curr_frame);
+                ALOGD("actualLayers [%" PRIu64 "]:%s parent=%" PRIu64 " z=%d frame=%" PRIu64,
+                      actualLayers[j].id, actualLayers[j].name.c_str(), actualLayers[j].parent,
+                      actualLayers[j].z, actualLayers[j].curr_frame);
             }
         }
         FAIL();
@@ -220,9 +224,9 @@
         for (size_t j = 0; j < expectedLayers.size(); j++) {
             if (std::find_if(actualLayers.begin(), actualLayers.end(),
                              find_id(expectedLayers[j].id)) == actualLayers.end()) {
-                ALOGD("expectedLayers [%d]:%s parent=%d z=%d frame=%" PRIu64, expectedLayers[j].id,
-                      expectedLayers[j].name.c_str(), expectedLayers[j].parent, expectedLayers[j].z,
-                      expectedLayers[j].curr_frame);
+                ALOGD("expectedLayers [%" PRIu64 "]:%s parent=%" PRIu64 " z=%d frame=%" PRIu64,
+                      expectedLayers[j].id, expectedLayers[j].name.c_str(),
+                      expectedLayers[j].parent, expectedLayers[j].z, expectedLayers[j].curr_frame);
             }
         }
         FAIL();