Automatically generate section_list.cpp file from incident.proto
with the SectionFlags field annotations

Bug: 64728679
Test: tested manually on device
Change-Id: I5b067b09cd6ccc3528f0845d7290cc9e2bc63a07
diff --git a/tools/incident_section_gen/main.cpp b/tools/incident_section_gen/main.cpp
index 15f622c..8e5c4f9 100644
--- a/tools/incident_section_gen/main.cpp
+++ b/tools/incident_section_gen/main.cpp
@@ -17,26 +17,30 @@
 
 #include <frameworks/base/core/proto/android/os/incident.pb.h>
 
-
 #include <map>
+#include <string>
 
+using namespace android;
 using namespace android::os;
 using namespace google::protobuf;
 using namespace google::protobuf::io;
 using namespace google::protobuf::internal;
 using namespace std;
 
-int
-main(int, const char**)
-{
-    map<string,FieldDescriptor const*> sections;
-    int N;
-
+static void generateHead(const char* header) {
     printf("// Auto generated file. Do not modify\n");
     printf("\n");
-    printf("#include \"incident_sections.h\"\n");
+    printf("#include \"%s.h\"\n", header);
     printf("\n");
+}
 
+// ================================================================================
+static bool generateIncidentSectionsCpp()
+{
+    generateHead("incident_sections");
+
+    map<string,FieldDescriptor const*> sections;
+    int N;
     Descriptor const* descriptor = IncidentProto::descriptor();
     N = descriptor->field_count();
     for (int i=0; i<N; i++) {
@@ -63,5 +67,72 @@
 
     printf("const int INCIDENT_SECTION_COUNT = %d;\n", N);
 
-    return 0;
+    return true;
+}
+
+// ================================================================================
+static void splitAndPrint(const string& args) {
+    size_t base = 0;
+    size_t found;
+    while (true) {
+        found = args.find_first_of(" ", base);
+        if (found != base) {
+            string arg = args.substr(base, found - base);
+            printf(" \"%s\",", arg.c_str());
+        }
+        if (found == args.npos) break;
+        base = found + 1;
+    }
+}
+
+static bool generateSectionListCpp() {
+    generateHead("section_list");
+
+    printf("const Section* SECTION_LIST[] = {\n");
+    Descriptor const* descriptor = IncidentProto::descriptor();
+    for (int i=0; i<descriptor->field_count(); i++) {
+        const FieldDescriptor* field = descriptor->field(i);
+
+        if (field->type() != FieldDescriptor::TYPE_MESSAGE) {
+            continue;
+        }
+        const SectionFlags s = field->options().GetExtension(section);
+        switch (s.type()) {
+            case SECTION_NONE:
+                continue;
+            case SECTION_FILE:
+                printf("    new FileSection(%d, \"%s\"),\n", field->number(), s.args().c_str());
+                break;
+            case SECTION_COMMAND:
+                printf("    new CommandSection(%d,", field->number());
+                splitAndPrint(s.args());
+                printf(" NULL),\n");
+                break;
+            case SECTION_DUMPSYS:
+                printf("    new DumpsysSection(%d,", field->number());
+                splitAndPrint(s.args());
+                printf(" NULL),\n");
+                break;
+        }
+    }
+    printf("    NULL\n");
+    printf("};\n");
+    return true;
+}
+
+// ================================================================================
+int main(int argc, char const *argv[])
+{
+    if (argc != 2) return 1;
+    const char* module = argv[1];
+
+    if (strcmp(module, "incident") == 0) {
+        return !generateIncidentSectionsCpp();
+    }
+    if (strcmp(module, "incidentd") == 0 ) {
+        return !generateSectionListCpp();
+    }
+
+    // return failure if not called by the whitelisted modules
+    return 1;
 }