Merge "GCC: fix ambiguous call to make_optional"
diff --git a/CHANGELOG b/CHANGELOG
index dabf6bf..0f2befe 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -7,6 +7,7 @@
     * The java heap profiler now rescans all the processes every time for
       continous_dump_config. The scan_pids_only_on_start can be used to restore
       the old behavior.
+    * Added support for building on ARM Macs
   Trace Processor:
     * Changed LIKE comparisions to be case-senstive. This may break existing
       queries but was a necessary from a performance perspective.
diff --git a/gn/standalone/toolchain/BUILD.gn b/gn/standalone/toolchain/BUILD.gn
index 8dba119..408f1f6 100644
--- a/gn/standalone/toolchain/BUILD.gn
+++ b/gn/standalone/toolchain/BUILD.gn
@@ -119,6 +119,8 @@
     _target_triplet = "x86_64-apple-darwin"
   } else if (target_os == "mac" && target_cpu == "x86") {
     _target_triplet = "i686-apple-darwin"
+  } else if (target_os == "mac" && target_cpu == "arm64") {
+    _target_triplet = "aarch64-apple-darwin"
   } else if (target_os == "linux" && target_cpu == "arm64") {
     _target_triplet = "aarch64-linux-gnu"
     _default_target_sysroot =
diff --git a/src/perfetto_cmd/perfetto_cmd.cc b/src/perfetto_cmd/perfetto_cmd.cc
index ef1492d..92c8bfa 100644
--- a/src/perfetto_cmd/perfetto_cmd.cc
+++ b/src/perfetto_cmd/perfetto_cmd.cc
@@ -514,8 +514,9 @@
   trace_config_.reset(new TraceConfig());
 
   bool parsed = false;
-  const bool will_trace = !is_attach() && !query_service_ && !bugreport_;
-  if (!will_trace) {
+  const bool will_trace_or_trigger =
+      !is_attach() && !query_service_ && !bugreport_;
+  if (!will_trace_or_trigger) {
     if ((!trace_config_raw.empty() || has_config_options)) {
       PERFETTO_ELOG("Cannot specify a trace config with this option");
       return 1;
@@ -545,7 +546,7 @@
   if (parsed) {
     *trace_config_->mutable_statsd_metadata() = std::move(statsd_metadata);
     trace_config_raw.clear();
-  } else if (will_trace) {
+  } else if (will_trace_or_trigger) {
     PERFETTO_ELOG("The trace config is invalid, bailing out.");
     return 1;
   }
@@ -573,21 +574,23 @@
     return 1;
   }
 
-  if (trace_config_->activate_triggers().empty() &&
-      trace_config_->incident_report_config().destination_package().empty() &&
+  // Only save to incidentd if:
+  // 1) --upload is set
+  // 2) |skip_incidentd| is absent or false.
+  // 3) we are not simply activating triggers.
+  save_to_incidentd_ =
+      upload_flag_ &&
       !trace_config_->incident_report_config().skip_incidentd() &&
-      upload_flag_) {
+      trace_config_->activate_triggers().empty();
+
+  if (save_to_incidentd_ &&
+      trace_config_->incident_report_config().destination_package().empty()) {
     PERFETTO_ELOG(
         "Missing IncidentReportConfig.destination_package with --dropbox / "
         "--upload.");
     return 1;
   }
 
-  // Only save to incidentd if both --upload is set and |skip_incidentd| is
-  // absent or false.
-  save_to_incidentd_ =
-      upload_flag_ && !trace_config_->incident_report_config().skip_incidentd();
-
   // Respect the wishes of the config with respect to statsd logging or fall
   // back on the presence of the --upload flag if not set.
   switch (trace_config_->statsd_logging()) {
@@ -644,7 +647,7 @@
   }
 
   bool open_out_file = true;
-  if (!will_trace) {
+  if (!will_trace_or_trigger) {
     open_out_file = false;
     if (!trace_out_path_.empty() || upload_flag_) {
       PERFETTO_ELOG("Can't pass an --out file (or --upload) with this option");
diff --git a/test/end_to_end_integrationtest.cc b/test/end_to_end_integrationtest.cc
index 1ec13d3..3d2b65e 100644
--- a/test/end_to_end_integrationtest.cc
+++ b/test/end_to_end_integrationtest.cc
@@ -296,10 +296,30 @@
 #define TEST_PRODUCER_SOCK_NAME ::perfetto::GetProducerSocket()
 #endif
 
+// Defining this macro out-of-line works around C/C++'s macro rules (see
+// https://stackoverflow.com/questions/26284393/nested-operator-in-c-preprocessor).
+#define DisableTest(x) DISABLED_##x
+
 #if PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
 #define TreeHuggerOnly(x) x
 #else
-#define TreeHuggerOnly(x) DISABLED_##x
+#define TreeHuggerOnly(x) DisableTest(x)
+#endif
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+#define AndroidOnly(x) x
+#else
+#define AndroidOnly(x) DisableTest(x)
+#endif
+
+// Disable cmdline tests on sanitizets because they use fork() and that messes
+// up leak / races detections, which has been fixed only recently (see
+// https://github.com/google/sanitizers/issues/836 ).
+#if defined(ADDRESS_SANITIZER) || defined(THREAD_SANITIZER) || \
+    defined(MEMORY_SANITIZER) || defined(LEAK_SANITIZER)
+#define NoSanitizers(X) DisableTest(X)
+#else
+#define NoSanitizers(X) X
 #endif
 
 // TODO(b/73453011): reenable on more platforms (including standalone Android).
@@ -1190,16 +1210,6 @@
                     Property(&protos::gen::TestEvent::str, SizeIs(kMsgSize)))));
 }
 
-// Disable cmdline tests on sanitizets because they use fork() and that messes
-// up leak / races detections, which has been fixed only recently (see
-// https://github.com/google/sanitizers/issues/836 ).
-#if defined(ADDRESS_SANITIZER) || defined(THREAD_SANITIZER) || \
-    defined(MEMORY_SANITIZER) || defined(LEAK_SANITIZER)
-#define NoSanitizers(X) DISABLED_##X
-#else
-#define NoSanitizers(X) X
-#endif
-
 TEST_F(PerfettoCmdlineTest, NoSanitizers(InvalidCases)) {
   std::string cfg("duration_ms: 100");
 
@@ -1518,11 +1528,8 @@
 
 // Dropbox on the commandline client only works on android builds. So disable
 // this test on all other builds.
-#if PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
-TEST_F(PerfettoCmdlineTest, NoSanitizers(NoDataNoFileWithoutTrigger)) {
-#else
-TEST_F(PerfettoCmdlineTest, DISABLED_NoDataNoFileWithoutTrigger) {
-#endif
+TEST_F(PerfettoCmdlineTest,
+       NoSanitizers(TreeHuggerOnly(NoDataNoFileWithoutTrigger))) {
   // See |message_count| and |message_size| in the TraceConfig above.
   constexpr size_t kMessageCount = 11;
   constexpr size_t kMessageSize = 32;
@@ -1746,4 +1753,86 @@
   EXPECT_EQ(0, query_raw.Run(&stderr_)) << stderr_;
 }
 
+TEST_F(PerfettoCmdlineTest,
+       NoSanitizers(AndroidOnly(CmdTriggerWithUploadFlag))) {
+  // See |message_count| and |message_size| in the TraceConfig above.
+  constexpr size_t kMessageCount = 2;
+  constexpr size_t kMessageSize = 2;
+  protos::gen::TraceConfig trace_config;
+  trace_config.add_buffers()->set_size_kb(1024);
+  auto* ds_config = trace_config.add_data_sources()->mutable_config();
+  ds_config->set_name("android.perfetto.FakeProducer");
+  ds_config->mutable_for_testing()->set_message_count(kMessageCount);
+  ds_config->mutable_for_testing()->set_message_size(kMessageSize);
+  auto* trigger_cfg = trace_config.mutable_trigger_config();
+  trigger_cfg->set_trigger_mode(
+      protos::gen::TraceConfig::TriggerConfig::STOP_TRACING);
+  trigger_cfg->set_trigger_timeout_ms(15000);
+  auto* trigger = trigger_cfg->add_triggers();
+  trigger->set_name("trigger_name");
+  // |stop_delay_ms| must be long enough that we can write the packets in
+  // before the trace finishes. This has to be long enough for the slowest
+  // emulator. But as short as possible to prevent the test running a long
+  // time.
+  trigger->set_stop_delay_ms(500);
+
+  // We have to construct all the processes we want to fork before we start the
+  // service with |StartServiceIfRequired()|. this is because it is unsafe
+  // (could deadlock) to fork after we've spawned some threads which might
+  // printf (and thus hold locks).
+  const std::string path = RandomTraceFileName();
+  auto perfetto_proc = ExecPerfetto(
+      {
+          "-o",
+          path,
+          "-c",
+          "-",
+      },
+      trace_config.SerializeAsString());
+
+  std::string triggers = R"(
+    activate_triggers: "trigger_name"
+  )";
+  auto perfetto_proc_2 = ExecPerfetto(
+      {
+          "--upload",
+          "-c",
+          "-",
+          "--txt",
+      },
+      triggers);
+
+  // Start the service and connect a simple fake producer.
+  StartServiceIfRequiredNoNewExecsAfterThis();
+  auto* fake_producer = ConnectFakeProducer();
+  EXPECT_TRUE(fake_producer);
+
+  std::thread background_trace([&perfetto_proc]() {
+    std::string stderr_str;
+    EXPECT_EQ(0, perfetto_proc.Run(&stderr_str)) << stderr_str;
+  });
+
+  WaitForProducerEnabled();
+  // Wait for the producer to start, and then write out 11 packets, before the
+  // trace actually starts (the trigger is seen).
+  auto on_data_written = task_runner_.CreateCheckpoint("data_written_1");
+  fake_producer->ProduceEventBatch(WrapTask(on_data_written));
+  task_runner_.RunUntilCheckpoint("data_written_1");
+
+  EXPECT_EQ(0, perfetto_proc_2.Run(&stderr_)) << "stderr: " << stderr_;
+
+  background_trace.join();
+
+  std::string trace_str;
+  base::ReadFile(path, &trace_str);
+  protos::gen::Trace trace;
+  ASSERT_TRUE(trace.ParseFromString(trace_str));
+  EXPECT_LT(static_cast<int>(kMessageCount), trace.packet_size());
+  for (const auto& packet : trace.packet()) {
+    if (packet.has_trigger()) {
+      EXPECT_EQ("trigger_name", packet.trigger().trigger_name());
+    }
+  }
+}
+
 }  // namespace perfetto
diff --git a/tools/build_all_configs.py b/tools/build_all_configs.py
index 95fe044..0c0ec5d 100755
--- a/tools/build_all_configs.py
+++ b/tools/build_all_configs.py
@@ -100,6 +100,11 @@
   else:
     assert False, 'Unsupported system %r' % system
 
+  machine = platform.machine()
+  if machine == 'arm64':
+    for name, config in configs.items():
+      configs[name] = config + ('host_cpu="arm64"',)
+
   if args.ccache:
     for config_name, gn_args in iteritems(configs):
       configs[config_name] = gn_args + ('cc_wrapper="ccache"',)