SF TimeStats: move dumpStats into TimeStatsHelper

Move dumpStats into TimeStatsHelper to make the TimeStatsHelper class
more modularized.

Test: dumpsys SurfaceFlinger --timestats <see go/sf-timestats for args>
Bug: b/70388650
Change-Id: Ie828d9b4c47aae54df5851e0febb8f48d34b78c8
diff --git a/services/surfaceflinger/TimeStats/TimeStats.cpp b/services/surfaceflinger/TimeStats/TimeStats.cpp
index a6833a5..cd64da0 100644
--- a/services/surfaceflinger/TimeStats/TimeStats.cpp
+++ b/services/surfaceflinger/TimeStats/TimeStats.cpp
@@ -59,14 +59,15 @@
     }
 
     if (argsMap.count("-dump")) {
-        int64_t maxLayers = 0;
+        std::optional<uint32_t> maxLayers = std::nullopt;
         auto iter = argsMap.find("-maxlayers");
         if (iter != argsMap.end() && iter->second + 1 < static_cast<int32_t>(args.size())) {
-            maxLayers = strtol(String8(args[iter->second + 1]).c_str(), nullptr, 10);
-            maxLayers = std::clamp(maxLayers, int64_t(0), int64_t(UINT32_MAX));
+            int64_t value = strtol(String8(args[iter->second + 1]).c_str(), nullptr, 10);
+            value = std::clamp(value, int64_t(0), int64_t(UINT32_MAX));
+            maxLayers = static_cast<uint32_t>(value);
         }
 
-        dump(asProto, static_cast<uint32_t>(maxLayers), result);
+        dump(asProto, maxLayers, result);
     }
 
     if (argsMap.count("-clear")) {
@@ -147,6 +148,21 @@
     return static_cast<int32_t>(delta);
 }
 
+static std::string getPackageName(const std::string& layerName) {
+    // This regular expression captures the following for instance:
+    // StatusBar in StatusBar#0
+    // com.appname in com.appname/com.appname.activity#0
+    // com.appname in SurfaceView - com.appname/com.appname.activity#0
+    const std::regex re("(?:SurfaceView[-\\s\\t]+)?([^/]+).*#\\d+");
+    std::smatch match;
+    if (std::regex_match(layerName.begin(), layerName.end(), match, re)) {
+        // There must be a match for group 1 otherwise the whole string is not
+        // matched and the above will return false
+        return match[1];
+    }
+    return "";
+}
+
 void TimeStats::flushAvailableRecordsToStatsLocked(const std::string& layerName) {
     ATRACE_CALL();
 
@@ -161,6 +177,7 @@
         if (prevTimeRecord.ready) {
             if (!timeStats.stats.count(layerName)) {
                 timeStats.stats[layerName].layerName = layerName;
+                timeStats.stats[layerName].packageName = getPackageName(layerName);
                 timeStats.stats[layerName].statsStart = static_cast<int64_t>(std::time(0));
             }
             TimeStatsHelper::TimeStatsLayer& timeStatsLayer = timeStats.stats[layerName];
@@ -434,7 +451,6 @@
 
     std::lock_guard<std::mutex> lock(mMutex);
     ALOGD("Cleared");
-    timeStats.dumpStats.clear();
     timeStats.stats.clear();
     timeStats.statsStart = (mEnabled.load() ? static_cast<int64_t>(std::time(0)) : 0);
     timeStats.statsEnd = 0;
@@ -447,7 +463,7 @@
     return mEnabled.load();
 }
 
-void TimeStats::dump(bool asProto, uint32_t maxLayers, String8& result) {
+void TimeStats::dump(bool asProto, std::optional<uint32_t> maxLayers, String8& result) {
     ATRACE_CALL();
 
     std::lock_guard<std::mutex> lock(mMutex);
@@ -457,39 +473,15 @@
 
     timeStats.statsEnd = static_cast<int64_t>(std::time(0));
 
-    // TODO(zzyiwei): refactor dumpStats into TimeStatsHelper
-    timeStats.dumpStats.clear();
-    for (auto& ele : timeStats.stats) {
-        timeStats.dumpStats.push_back(&ele.second);
-    }
-
-    std::sort(timeStats.dumpStats.begin(), timeStats.dumpStats.end(),
-              [](TimeStatsHelper::TimeStatsLayer* const& l,
-                 TimeStatsHelper::TimeStatsLayer* const& r) {
-                  return l->totalFrames > r->totalFrames;
-              });
-
-    if (maxLayers != 0 && maxLayers < timeStats.dumpStats.size()) {
-        timeStats.dumpStats.resize(maxLayers);
-    }
-
     if (asProto) {
-        dumpAsProtoLocked(result);
+        ALOGD("Dumping TimeStats as proto");
+        SFTimeStatsGlobalProto timeStatsProto = timeStats.toProto(maxLayers);
+        result.append(timeStatsProto.SerializeAsString().c_str(), timeStatsProto.ByteSize());
     } else {
-        dumpAsTextLocked(result);
+        ALOGD("Dumping TimeStats as text");
+        result.append(timeStats.toString(maxLayers).c_str());
+        result.append("\n");
     }
 }
 
-void TimeStats::dumpAsTextLocked(String8& result) {
-    ALOGD("Dumping TimeStats as text");
-    result.append(timeStats.toString().c_str());
-    result.append("\n");
-}
-
-void TimeStats::dumpAsProtoLocked(String8& result) {
-    ALOGD("Dumping TimeStats as proto");
-    SFTimeStatsGlobalProto timeStatsProto = timeStats.toProto();
-    result.append(timeStatsProto.SerializeAsString().c_str(), timeStatsProto.ByteSize());
-}
-
 } // namespace android