Perfprofd: Convert proto to be flat

Use extensions instead of nesting, to improve upload situation.

Bug: 86953235
Test: mmma system/extras/perfprofd
Change-Id: I681350a56839674906f200c87e6afe22ca89017d
diff --git a/perfprofd/perf_data_converter.cc b/perfprofd/perf_data_converter.cc
index f94cc86..6d7ebbd 100644
--- a/perfprofd/perf_data_converter.cc
+++ b/perfprofd/perf_data_converter.cc
@@ -33,13 +33,13 @@
                    ::quipper::PerfParser& perf_parser,
                    ::perfprofd::Symbolizer* symbolizer) {
   std::unordered_set<std::string> filenames_w_build_id;
-  for (auto& perf_build_id : record->perf_data().build_ids()) {
+  for (auto& perf_build_id : record->build_ids()) {
     filenames_w_build_id.insert(perf_build_id.filename());
   }
 
   std::unordered_set<std::string> files_wo_build_id;
   {
-    quipper::MmapEventIterator it(record->perf_data());
+    quipper::MmapEventIterator it(*record);
     for (; it != it.end(); ++it) {
       const ::quipper::PerfDataProto_MMapEvent* mmap_event = &it->mmap_event();
       if (!mmap_event->has_filename() || !mmap_event->has_start() || !mmap_event->has_len()) {
@@ -63,8 +63,8 @@
   };
   std::unordered_map<std::string, Dso> files;
 
-  auto it = record->perf_data().events().begin();
-  auto end = record->perf_data().events().end();
+  auto it = record->events().begin();
+  auto end = record->events().end();
   auto parsed_it = perf_parser.parsed_events().begin();
   auto parsed_end = perf_parser.parsed_events().end();
   for (; it != end; ++it, ++parsed_it) {
@@ -132,6 +132,7 @@
 
   if (!files.empty()) {
     // We have extra symbol info, create proto messages now.
+    size_t symbol_info_index = 0;
     for (auto& file_data : files) {
       const std::string& filename = file_data.first;
       const Dso& dso = file_data.second;
@@ -139,17 +140,19 @@
         continue;
       }
 
-      PerfprofdRecord_SymbolInfo* symbol_info = record->add_symbol_info();
+      auto* symbol_info = record->AddExtension(::quipper::symbol_info);
       symbol_info->set_filename(filename);
       symbol_info->set_filename_md5_prefix(::quipper::Md5Prefix(filename));
       symbol_info->set_min_vaddr(dso.min_vaddr);
       for (auto& aggr_sym : dso.symbols) {
-        PerfprofdRecord_SymbolInfo_Symbol* symbol = symbol_info->add_symbols();
+        auto* symbol = symbol_info->add_symbols();
         symbol->set_addr(*aggr_sym.second.offsets.begin());
         symbol->set_size(*aggr_sym.second.offsets.rbegin() - *aggr_sym.second.offsets.begin() + 1);
         symbol->set_name(aggr_sym.second.symbol);
         symbol->set_name_md5_prefix(::quipper::Md5Prefix(aggr_sym.second.symbol));
       }
+
+      ++symbol_info_index;
     }
   }
 }
@@ -160,25 +163,23 @@
 RawPerfDataToAndroidPerfProfile(const string &perf_file,
                                 ::perfprofd::Symbolizer* symbolizer) {
   std::unique_ptr<PerfprofdRecord> ret(new PerfprofdRecord());
-  ret->set_id(0);  // TODO.
+  ret->SetExtension(::quipper::id, 0);  // TODO.
 
   ::quipper::PerfParserOptions options = {};
   options.do_remap = true;
   options.discard_unused_events = true;
   options.read_missing_buildids = true;
 
-  ::quipper::PerfDataProto* perf_data = ret->mutable_perf_data();
-
   ::quipper::PerfReader reader;
   if (!reader.ReadFile(perf_file)) return nullptr;
 
   ::quipper::PerfParser parser(&reader, options);
   if (!parser.ParseRawEvents()) return nullptr;
 
-  if (!reader.Serialize(perf_data)) return nullptr;
+  if (!reader.Serialize(ret.get())) return nullptr;
 
   // Append parser stats to protobuf.
-  ::quipper::PerfSerializer::SerializeParserStats(parser.stats(), perf_data);
+  ::quipper::PerfSerializer::SerializeParserStats(parser.stats(), ret.get());
 
   // TODO: Symbolization.
   if (symbolizer != nullptr) {
diff --git a/perfprofd/perfprofd_record-fwd.h b/perfprofd/perfprofd_record-fwd.h
index 000ccec..6972582 100644
--- a/perfprofd/perfprofd_record-fwd.h
+++ b/perfprofd/perfprofd_record-fwd.h
@@ -18,9 +18,13 @@
 #ifndef SYSTEM_EXTRAS_PERFPROFD_PERFPROFD_RECORD_FWD_H_
 #define SYSTEM_EXTRAS_PERFPROFD_PERFPROFD_RECORD_FWD_H_
 
+namespace quipper {
+class PerfDataProto;
+}  // namespace quipper
+
 namespace android {
 namespace perfprofd {
-class PerfprofdRecord;
+using PerfprofdRecord = ::quipper::PerfDataProto;
 }  // namespace perfprofd
 }  // namespace android
 
diff --git a/perfprofd/perfprofd_record.proto b/perfprofd/perfprofd_record.proto
index 08b5fa2..1660d5f 100644
--- a/perfprofd/perfprofd_record.proto
+++ b/perfprofd/perfprofd_record.proto
@@ -5,55 +5,54 @@
 
 option java_package = "com.google.android.perfprofd";
 
-package android.perfprofd;
+package quipper;
 
-message PerfprofdRecord {
-  // Symbol info for a shared library without build id.
-  message SymbolInfo {
-    // A symbol, stretching the given range of the library.
-    message Symbol {
-      optional string name = 1;
-      optional uint64 name_md5_prefix = 2;
+// Symbol info for a shared library without build id.
+message SymbolInfo {
+  // A symbol, stretching the given range of the library.
+  message Symbol {
+    optional string name = 1;
+    optional uint64 name_md5_prefix = 2;
 
-      optional uint64 addr = 3;
-      optional uint64 size = 4;
-    };
-
-    optional string filename = 1;
-    optional uint64 filename_md5_prefix = 2;
-
-    optional uint64 min_vaddr = 3;
-
-    repeated Symbol symbols = 4;
+    optional uint64 addr = 3;
+    optional uint64 size = 4;
   };
 
-  optional int64 id = 1;
-  optional quipper.PerfDataProto perf_data = 2;
+  optional string filename = 1;
+  optional uint64 filename_md5_prefix = 2;
+
+  optional uint64 min_vaddr = 3;
+
+  repeated Symbol symbols = 4;
+};
+
+extend PerfDataProto {
+  optional int64 id = 32;
 
   // Extra symbol info.
-  repeated SymbolInfo symbol_info = 3;
+  repeated SymbolInfo symbol_info = 33;
 
   // Stats inherited from old perf_profile.proto.
 
   // is device screen on at point when profile is collected?
-  optional bool display_on = 5;
+  optional bool display_on = 34;
 
   // system load at point when profile is collected; corresponds
   // to first value from /proc/loadavg multiplied by 100 then
   // converted to int32
-  optional int32 sys_load_average = 6;
+  optional int32 sys_load_average = 35;
 
   // At the point when the profile was collected, was a camera active?
-  optional bool camera_active = 7;
+  optional bool camera_active = 36;
 
   // At the point when the profile was collected, was the device still booting?
-  optional bool booting = 8;
+  optional bool booting = 37;
 
   // At the point when the profile was collected, was the device plugged into
   // a charger?
-  optional bool on_charger = 9;
+  optional bool on_charger = 38;
 
   // CPU utilization measured prior to profile collection (expressed as
   // 100 minus the idle percentage).
-  optional int32 cpu_utilization = 10;
+  optional int32 cpu_utilization = 39;
 };
diff --git a/perfprofd/perfprofdcore.cc b/perfprofd/perfprofdcore.cc
index a86c5ef..a152111 100644
--- a/perfprofd/perfprofdcore.cc
+++ b/perfprofd/perfprofdcore.cc
@@ -362,7 +362,7 @@
   // Incorporate cpu utilization (collected prior to perf run)
   //
   if (config.collect_cpu_utilization) {
-    profile->set_cpu_utilization(cpu_utilization);
+    profile->SetExtension(quipper::cpu_utilization, cpu_utilization);
   }
 
   //
@@ -373,7 +373,7 @@
   if (android::base::ReadFileToString("/proc/loadavg", &load) &&
       sscanf(load.c_str(), "%lf", &fload) == 1) {
     int iload = static_cast<int>(fload * 100.0);
-    profile->set_sys_load_average(iload);
+    profile->SetExtension(quipper::sys_load_average, iload);
   } else {
     PLOG(ERROR) << "Failed to read or scan /proc/loadavg";
   }
@@ -383,13 +383,13 @@
   //
   bool is_booting = get_booting();
   if (config.collect_booting) {
-    profile->set_booting(is_booting);
+    profile->SetExtension(quipper::booting, is_booting);
   }
   if (config.collect_camera_active) {
-    profile->set_camera_active(is_booting ? false : get_camera_active());
+    profile->SetExtension(quipper::camera_active, is_booting ? false : get_camera_active());
   }
   if (config.collect_charging_state) {
-    profile->set_on_charger(get_charging());
+    profile->SetExtension(quipper::on_charger, get_charging());
   }
 
   //
@@ -400,7 +400,7 @@
   std::string disp;
   if (android::base::ReadFileToString("/sys/power/wake_unlock", &disp)) {
     bool ison = (strstr(disp.c_str(), "PowerManagerService.Display") == 0);
-    profile->set_display_on(ison);
+    profile->SetExtension(quipper::display_on, ison);
   } else {
     PLOG(ERROR) << "Failed to read /sys/power/wake_unlock";
   }
@@ -440,7 +440,7 @@
   //
   // Issue error if no samples
   //
-  if (encodedProfile == nullptr || encodedProfile->perf_data().events_size() == 0) {
+  if (encodedProfile == nullptr || encodedProfile->events_size() == 0) {
     return ERR_PERF_ENCODE_FAILED;
   }
 
diff --git a/perfprofd/scripts/perf_proto_stack.py b/perfprofd/scripts/perf_proto_stack.py
index eb93eb6..9287b87 100644
--- a/perfprofd/scripts/perf_proto_stack.py
+++ b/perfprofd/scripts/perf_proto_stack.py
@@ -43,6 +43,7 @@
 #      --python_out=system/extras/perfprofd/scripts \
 #      system/extras/perfprofd/perfprofd_record.proto
 import perfprofd_record_pb2
+import perf_data_pb2
 
 # Make sure that symbol is on the PYTHONPATH, e.g., run as
 # PYTHONPATH=$PYTHONPATH:$ANDROID_BUILD_TOP/development/scripts python ...
@@ -120,7 +121,8 @@
 
 def create_symbol_maps(profile):
     symbol_maps = {}
-    for si in profile.symbol_info:
+#    if profile.HasExtension(perfprofd_record_pb2.symbol_info):
+    for si in profile.Extensions[perfprofd_record_pb2.symbol_info]:
         map = SymbolMap(si.min_vaddr)
         symbol_maps[si.filename] = map
         for sym in si.symbols:
@@ -484,10 +486,11 @@
     data = file.read()
     file.close()
 
-    profile = perfprofd_record_pb2.PerfprofdRecord()
+    profile = perf_data_pb2.PerfDataProto()
+    # PerfprofdRecord()
     profile.ParseFromString(data)
 
-    perf_data = profile.perf_data
+    perf_data = profile
 
     print "Stats: ", perf_data.stats
 
diff --git a/perfprofd/tests/perfprofd_test.cc b/perfprofd/tests/perfprofd_test.cc
index f17d1a6..8712f0c 100644
--- a/perfprofd/tests/perfprofd_test.cc
+++ b/perfprofd/tests/perfprofd_test.cc
@@ -714,8 +714,7 @@
 
 struct BasicRunWithCannedPerf : PerfProfdTest {
   void VerifyBasicCannedProfile(const android::perfprofd::PerfprofdRecord& encodedProfile) {
-    ASSERT_TRUE(encodedProfile.has_perf_data()) << test_logger.JoinTestLog(" ");
-    const quipper::PerfDataProto& perf_data = encodedProfile.perf_data();
+    const quipper::PerfDataProto& perf_data = encodedProfile;
 
     // Expect 21108 events.
     EXPECT_EQ(21108, perf_data.events_size()) << CreateStats(perf_data);
@@ -948,9 +947,10 @@
 
   VerifyBasicCannedProfile(encodedProfile);
 
-  auto find_symbol = [&](const std::string& filename)
-      -> const android::perfprofd::PerfprofdRecord_SymbolInfo* {
-    for (auto& symbol_info : encodedProfile.symbol_info()) {
+  auto find_symbol = [&](const std::string& filename) -> const quipper::SymbolInfo* {
+    const size_t size = encodedProfile.ExtensionSize(quipper::symbol_info);
+    for (size_t i = 0; i != size; ++i) {
+      auto& symbol_info = encodedProfile.GetExtension(quipper::symbol_info, i);
       if (symbol_info.filename() == filename) {
         return &symbol_info;
       }
@@ -959,7 +959,9 @@
   };
   auto all_filenames = [&]() {
     std::ostringstream oss;
-    for (auto& symbol_info : encodedProfile.symbol_info()) {
+    const size_t size = encodedProfile.ExtensionSize(quipper::symbol_info);
+    for (size_t i = 0; i != size; ++i) {
+      auto& symbol_info = encodedProfile.GetExtension(quipper::symbol_info, i);
       oss << " " << symbol_info.filename();
     }
     return oss.str();
@@ -1005,9 +1007,7 @@
   android::perfprofd::PerfprofdRecord encodedProfile;
   readEncodedProfile(dest_dir, false, encodedProfile);
 
-
-  ASSERT_TRUE(encodedProfile.has_perf_data());
-  const quipper::PerfDataProto& perf_data = encodedProfile.perf_data();
+  const quipper::PerfDataProto& perf_data = encodedProfile;
 
   // Expect 21108 events.
   EXPECT_EQ(2224, perf_data.events_size()) << CreateStats(perf_data);
@@ -1094,7 +1094,7 @@
 
   // Examine what we get back. Since it's a live profile, we can't
   // really do much in terms of verifying the contents.
-  EXPECT_LT(0, encodedProfile.perf_data().events_size());
+  EXPECT_LT(0, encodedProfile.events_size());
 
   // Verify log contents
   const std::string expected = std::string(
@@ -1152,7 +1152,7 @@
 
   // Examine what we get back. Since it's a live profile, we can't
   // really do much in terms of verifying the contents.
-  EXPECT_LT(0, encodedProfile.perf_data().events_size());
+  EXPECT_LT(0, encodedProfile.events_size());
 
   // Examine that encoded.1 file is removed while encoded.{0|2} exists.
   EXPECT_EQ(0, access(encoded_file_path(dest_dir, 0).c_str(), F_OK));
@@ -1224,7 +1224,7 @@
 
   // Examine what we get back. Since it's a live profile, we can't
   // really do much in terms of verifying the contents.
-  EXPECT_LT(0, encodedProfile.perf_data().events_size());
+  EXPECT_LT(0, encodedProfile.events_size());
 
   // Verify log contents
   const std::string expected = std::string(
@@ -1243,12 +1243,12 @@
   CompareLogMessages(expandVars(expected), "CallChainRunWithLivePerf", true);
 
   // Check that we have at least one SampleEvent with a callchain.
-  SampleEventIterator samples(encodedProfile.perf_data());
+  SampleEventIterator samples(encodedProfile);
   bool found_callchain = false;
   while (!found_callchain && samples != samples.end()) {
     found_callchain = samples->sample_event().callchain_size() > 0;
   }
-  EXPECT_TRUE(found_callchain) << CreateStats(encodedProfile.perf_data());
+  EXPECT_TRUE(found_callchain) << CreateStats(encodedProfile);
 }
 
 #endif