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/timestatsproto/TimeStatsHelper.cpp b/services/surfaceflinger/TimeStats/timestatsproto/TimeStatsHelper.cpp
index 3e5007c..21f3ef3 100644
--- a/services/surfaceflinger/TimeStats/timestatsproto/TimeStatsHelper.cpp
+++ b/services/surfaceflinger/TimeStats/timestatsproto/TimeStatsHelper.cpp
@@ -17,7 +17,6 @@
 #include <timestatsproto/TimeStatsHelper.h>
 
 #include <array>
-#include <regex>
 
 #define HISTOGRAM_SIZE 85
 
@@ -47,55 +46,39 @@
     hist[*iter]++;
 }
 
-float TimeStatsHelper::Histogram::averageTime() {
+float TimeStatsHelper::Histogram::averageTime() const {
     int64_t ret = 0;
     int64_t count = 0;
-    for (auto ele : hist) {
+    for (auto& ele : hist) {
         count += ele.second;
         ret += ele.first * ele.second;
     }
     return static_cast<float>(ret) / count;
 }
 
-std::string TimeStatsHelper::Histogram::toString() {
+std::string TimeStatsHelper::Histogram::toString() const {
     std::string result;
     for (int32_t i = 0; i < HISTOGRAM_SIZE; ++i) {
         int32_t bucket = histogramConfig[i];
-        int32_t count = (hist.count(bucket) == 0) ? 0 : hist[bucket];
+        int32_t count = (hist.count(bucket) == 0) ? 0 : hist.at(bucket);
         StringAppendF(&result, "%dms=%d ", bucket, count);
     }
     result.back() = '\n';
     return result;
 }
 
-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 "";
-}
-
-std::string TimeStatsHelper::TimeStatsLayer::toString() {
+std::string TimeStatsHelper::TimeStatsLayer::toString() const {
     std::string result = "";
     StringAppendF(&result, "layerName = %s\n", layerName.c_str());
-    packageName = getPackageName(layerName);
     StringAppendF(&result, "packageName = %s\n", packageName.c_str());
     StringAppendF(&result, "statsStart = %lld\n", static_cast<long long int>(statsStart));
     StringAppendF(&result, "statsEnd = %lld\n", static_cast<long long int>(statsEnd));
     StringAppendF(&result, "totalFrames= %d\n", totalFrames);
-    if (deltas.find("present2present") != deltas.end()) {
-        StringAppendF(&result, "averageFPS = %.3f\n",
-                      1000.0 / deltas["present2present"].averageTime());
+    auto iter = deltas.find("present2present");
+    if (iter != deltas.end()) {
+        StringAppendF(&result, "averageFPS = %.3f\n", 1000.0 / iter->second.averageTime());
     }
-    for (auto ele : deltas) {
+    for (auto& ele : deltas) {
         StringAppendF(&result, "%s histogram is as below:\n", ele.first.c_str());
         StringAppendF(&result, "%s", ele.second.toString().c_str());
     }
@@ -103,7 +86,7 @@
     return result;
 }
 
-std::string TimeStatsHelper::TimeStatsGlobal::toString() {
+std::string TimeStatsHelper::TimeStatsGlobal::toString(std::optional<uint32_t> maxLayers) const {
     std::string result = "SurfaceFlinger TimeStats:\n";
     StringAppendF(&result, "statsStart = %lld\n", static_cast<long long int>(statsStart));
     StringAppendF(&result, "statsEnd = %lld\n", static_cast<long long int>(statsEnd));
@@ -111,25 +94,25 @@
     StringAppendF(&result, "missedFrames= %d\n", missedFrames);
     StringAppendF(&result, "clientCompositionFrames= %d\n", clientCompositionFrames);
     StringAppendF(&result, "TimeStats for each layer is as below:\n");
-    for (auto ele : dumpStats) {
+    const auto dumpStats = generateDumpStats(maxLayers);
+    for (auto& ele : dumpStats) {
         StringAppendF(&result, "%s", ele->toString().c_str());
     }
 
     return result;
 }
 
-SFTimeStatsLayerProto TimeStatsHelper::TimeStatsLayer::toProto() {
+SFTimeStatsLayerProto TimeStatsHelper::TimeStatsLayer::toProto() const {
     SFTimeStatsLayerProto layerProto;
     layerProto.set_layer_name(layerName);
-    packageName = getPackageName(layerName);
     layerProto.set_package_name(packageName);
     layerProto.set_stats_start(statsStart);
     layerProto.set_stats_end(statsEnd);
     layerProto.set_total_frames(totalFrames);
-    for (auto ele : deltas) {
+    for (auto& ele : deltas) {
         SFTimeStatsDeltaProto* deltaProto = layerProto.add_deltas();
         deltaProto->set_delta_name(ele.first);
-        for (auto histEle : ele.second.hist) {
+        for (auto& histEle : ele.second.hist) {
             SFTimeStatsHistogramBucketProto* histProto = deltaProto->add_histograms();
             histProto->set_render_millis(histEle.first);
             histProto->set_frame_count(histEle.second);
@@ -138,19 +121,40 @@
     return layerProto;
 }
 
-SFTimeStatsGlobalProto TimeStatsHelper::TimeStatsGlobal::toProto() {
+SFTimeStatsGlobalProto TimeStatsHelper::TimeStatsGlobal::toProto(
+        std::optional<uint32_t> maxLayers) const {
     SFTimeStatsGlobalProto globalProto;
     globalProto.set_stats_start(statsStart);
     globalProto.set_stats_end(statsEnd);
     globalProto.set_total_frames(totalFrames);
     globalProto.set_missed_frames(missedFrames);
     globalProto.set_client_composition_frames(clientCompositionFrames);
-    for (auto ele : dumpStats) {
+    const auto dumpStats = generateDumpStats(maxLayers);
+    for (auto& ele : dumpStats) {
         SFTimeStatsLayerProto* layerProto = globalProto.add_stats();
         layerProto->CopyFrom(ele->toProto());
     }
     return globalProto;
 }
 
+std::vector<TimeStatsHelper::TimeStatsLayer const*>
+TimeStatsHelper::TimeStatsGlobal::generateDumpStats(std::optional<uint32_t> maxLayers) const {
+    std::vector<TimeStatsLayer const*> dumpStats;
+    for (auto& ele : stats) {
+        dumpStats.push_back(&ele.second);
+    }
+
+    std::sort(dumpStats.begin(), dumpStats.end(),
+              [](TimeStatsHelper::TimeStatsLayer const* l,
+                 TimeStatsHelper::TimeStatsLayer const* r) {
+                  return l->totalFrames > r->totalFrames;
+              });
+
+    if (maxLayers && (*maxLayers < dumpStats.size())) {
+        dumpStats.resize(*maxLayers);
+    }
+    return dumpStats;
+}
+
 } // namespace surfaceflinger
 } // namespace android