Merge "Snap for 4787638 from 5552beb813d2a5ae60c4eef9a4a5646b7ab430d7 to oreo-mr1-cts-release" into oreo-mr1-cts-release
diff --git a/simpleperf/cmd_kmem.cpp b/simpleperf/cmd_kmem.cpp
index 51f9a58..59ec2c3 100644
--- a/simpleperf/cmd_kmem.cpp
+++ b/simpleperf/cmd_kmem.cpp
@@ -612,7 +612,8 @@
       slab_sample_tree_builder_->ProcessSampleRecord(
           *static_cast<const SampleRecord*>(record.get()));
     }
-  } else if (record->type() == PERF_RECORD_TRACING_DATA) {
+  } else if (record->type() == PERF_RECORD_TRACING_DATA ||
+             record->type() == SIMPLE_PERF_RECORD_TRACING_DATA) {
     const auto& r = *static_cast<TracingDataRecord*>(record.get());
     ProcessTracingData(std::vector<char>(r.data, r.data + r.data_size));
   }
diff --git a/simpleperf/cmd_record_test.cpp b/simpleperf/cmd_record_test.cpp
index c3f9cb4..e942332 100644
--- a/simpleperf/cmd_record_test.cpp
+++ b/simpleperf/cmd_record_test.cpp
@@ -391,12 +391,21 @@
 
 TEST(record_cmd, handle_SIGHUP) {
   TemporaryFile tmpfile;
-  std::thread thread([]() {
-    sleep(1);
+  int pipefd[2];
+  ASSERT_EQ(0, pipe(pipefd));
+  int read_fd = pipefd[0];
+  int write_fd = pipefd[1];
+  char data[8] = {};
+  std::thread thread([&]() {
+    android::base::ReadFully(read_fd, data, 7);
     kill(getpid(), SIGHUP);
   });
-  thread.detach();
-  ASSERT_TRUE(RecordCmd()->Run({"-o", tmpfile.path, "sleep", "1000000"}));
+  ASSERT_TRUE(RecordCmd()->Run({"-o", tmpfile.path, "--start_profiling_fd",
+                                std::to_string(write_fd), "sleep", "1000000"}));
+  thread.join();
+  close(write_fd);
+  close(read_fd);
+  ASSERT_STREQ(data, "STARTED");
 }
 
 TEST(record_cmd, stop_when_no_more_targets) {
diff --git a/simpleperf/cmd_report.cpp b/simpleperf/cmd_report.cpp
index 29cf743..f026d32 100644
--- a/simpleperf/cmd_report.cpp
+++ b/simpleperf/cmd_report.cpp
@@ -777,7 +777,8 @@
     size_t attr_id = record_file_reader_->GetAttrIndexOfRecord(record.get());
     sample_tree_builder_[attr_id]->ProcessSampleRecord(
         *static_cast<const SampleRecord*>(record.get()));
-  } else if (record->type() == PERF_RECORD_TRACING_DATA) {
+  } else if (record->type() == PERF_RECORD_TRACING_DATA ||
+             record->type() == SIMPLE_PERF_RECORD_TRACING_DATA) {
     const auto& r = *static_cast<TracingDataRecord*>(record.get());
     if (!ProcessTracingData(std::vector<char>(r.data, r.data + r.data_size))) {
       return false;
diff --git a/simpleperf/cmd_report_test.cpp b/simpleperf/cmd_report_test.cpp
index e146876..2790c27 100644
--- a/simpleperf/cmd_report_test.cpp
+++ b/simpleperf/cmd_report_test.cpp
@@ -471,6 +471,11 @@
   ASSERT_EQ(content.find("skipped in brief callgraph mode"), std::string::npos);
 }
 
+TEST_F(ReportCommandTest, report_big_trace_data) {
+  Report(PERF_DATA_WITH_BIG_TRACE_DATA);
+  ASSERT_TRUE(success);
+}
+
 #if defined(__linux__)
 #include "event_selection_set.h"
 
diff --git a/simpleperf/cmd_stat_test.cpp b/simpleperf/cmd_stat_test.cpp
index 3cdb4eb..3876b42 100644
--- a/simpleperf/cmd_stat_test.cpp
+++ b/simpleperf/cmd_stat_test.cpp
@@ -157,6 +157,11 @@
 }
 
 TEST(stat_cmd, handle_SIGHUP) {
+  if (!GetDefaultAppPackageName().empty()) {
+    // See http://b/79495636.
+    GTEST_LOG_(INFO) << "Omit this test in app's context.";
+    return;
+  }
   std::thread thread([]() {
     sleep(1);
     kill(getpid(), SIGHUP);
diff --git a/simpleperf/get_test_data.h b/simpleperf/get_test_data.h
index 963fe00..625b3de 100644
--- a/simpleperf/get_test_data.h
+++ b/simpleperf/get_test_data.h
@@ -108,4 +108,6 @@
 // generated by recording an app.
 static const std::string PERF_DATA_WITH_WRONG_IP_IN_CALLCHAIN = "wrong_ip_callchain_perf.data";
 
+static const std::string PERF_DATA_WITH_BIG_TRACE_DATA = "perf_with_big_trace_data.data";
+
 #endif  // SIMPLE_PERF_GET_TEST_DATA_H_
diff --git a/simpleperf/record.cpp b/simpleperf/record.cpp
index 65e98ea..697434b 100644
--- a/simpleperf/record.cpp
+++ b/simpleperf/record.cpp
@@ -46,6 +46,9 @@
       {SIMPLE_PERF_RECORD_DSO, "dso"},
       {SIMPLE_PERF_RECORD_SYMBOL, "symbol"},
       {SIMPLE_PERF_RECORD_EVENT_ID, "event_id"},
+      {SIMPLE_PERF_RECORD_CALLCHAIN, "callchain"},
+      {SIMPLE_PERF_RECORD_UNWINDING_RESULT, "unwinding_result"},
+      {SIMPLE_PERF_RECORD_TRACING_DATA, "tracing_data"},
   };
 
   auto it = record_type_names.find(record_type);
@@ -821,7 +824,7 @@
 }
 
 TracingDataRecord::TracingDataRecord(const std::vector<char>& tracing_data) {
-  SetTypeAndMisc(PERF_RECORD_TRACING_DATA, 0);
+  SetTypeAndMisc(SIMPLE_PERF_RECORD_TRACING_DATA, 0);
   data_size = tracing_data.size();
   SetSize(header_size() + sizeof(uint32_t) + Align(tracing_data.size(), 64));
   char* new_binary = new char[size()];
@@ -904,6 +907,8 @@
       return std::unique_ptr<Record>(new SymbolRecord(p));
     case SIMPLE_PERF_RECORD_EVENT_ID:
       return std::unique_ptr<Record>(new EventIdRecord(p));
+    case SIMPLE_PERF_RECORD_TRACING_DATA:
+      return std::unique_ptr<Record>(new TracingDataRecord(p));
     default:
       return std::unique_ptr<Record>(new UnknownRecord(p));
   }
diff --git a/simpleperf/record.h b/simpleperf/record.h
index d6ee2ce..cfe3191 100644
--- a/simpleperf/record.h
+++ b/simpleperf/record.h
@@ -46,6 +46,9 @@
   SIMPLE_PERF_RECORD_SPLIT,
   SIMPLE_PERF_RECORD_SPLIT_END,
   SIMPLE_PERF_RECORD_EVENT_ID,
+  SIMPLE_PERF_RECORD_CALLCHAIN,
+  SIMPLE_PERF_RECORD_UNWINDING_RESULT,
+  SIMPLE_PERF_RECORD_TRACING_DATA,
 };
 
 // perf_event_header uses u16 to store record size. However, that is not
diff --git a/simpleperf/testdata/perf_with_big_trace_data.data b/simpleperf/testdata/perf_with_big_trace_data.data
new file mode 100644
index 0000000..5134ec5
--- /dev/null
+++ b/simpleperf/testdata/perf_with_big_trace_data.data
Binary files differ
diff --git a/simpleperf/tracing.cpp b/simpleperf/tracing.cpp
index 884a883..df86d59 100644
--- a/simpleperf/tracing.cpp
+++ b/simpleperf/tracing.cpp
@@ -24,6 +24,7 @@
 
 #include <android-base/file.h>
 #include <android-base/logging.h>
+#include <android-base/parseint.h>
 #include <android-base/stringprintf.h>
 #include <android-base/strings.h>
 
@@ -295,14 +296,23 @@
     } else if (s[i] == ';') {
       value = s.substr(start, i - start);
       if (name == "field") {
-        size_t pos = value.find_first_of('[');
-        if (pos == std::string::npos) {
+        // Parse value with brackets like "comm[16]", or just a field name.
+        size_t left_bracket_pos = value.find('[');
+        if (left_bracket_pos == std::string::npos) {
           field.name = value;
           field.elem_count = 1;
         } else {
-          field.name = value.substr(0, pos);
-          field.elem_count =
-              static_cast<size_t>(strtoull(&value[pos + 1], nullptr, 10));
+          field.name = value.substr(0, left_bracket_pos);
+          field.elem_count = 1;
+          size_t right_bracket_pos = value.find(']', left_bracket_pos);
+          if (right_bracket_pos != std::string::npos) {
+            size_t len = right_bracket_pos - left_bracket_pos - 1;
+            size_t elem_count;
+            // Array size may not be a number, like field:u32 rates[IEEE80211_NUM_BANDS].
+            if (android::base::ParseUint(value.substr(left_bracket_pos + 1, len), &elem_count)) {
+              field.elem_count = elem_count;
+            }
+          }
         }
       } else if (name == "offset") {
         field.offset =