Add statsd logging to perfetto_cmd

Bug: 133135459
Change-Id: Ie1045d6a26804f650ac580f8ffc2e4a9ff054da6
diff --git a/Android.bp b/Android.bp
index 514776e..e48e2ca 100644
--- a/Android.bp
+++ b/Android.bp
@@ -326,6 +326,7 @@
     ":perfetto_src_base_base",
     ":perfetto_src_base_unix_socket",
     ":perfetto_src_ipc_ipc",
+    ":perfetto_src_perfetto_cmd_perfetto_atoms",
     ":perfetto_src_protozero_protozero",
     ":perfetto_src_traced_probes_android_log_android_log",
     ":perfetto_src_traced_probes_data_source",
@@ -419,6 +420,7 @@
   srcs: [
     ":perfetto_src_android_internal_android_internal",
     ":perfetto_src_android_internal_headers",
+    ":perfetto_src_perfetto_cmd_perfetto_atoms",
   ],
   shared_libs: [
     "android.hardware.atrace@1.0",
@@ -426,14 +428,17 @@
     "android.hardware.power.stats@1.0",
     "libbase",
     "libbinder",
+    "libcutils",
     "libhidlbase",
     "libincident",
     "liblog",
     "libservices",
+    "libstatssocket",
     "libutils",
   ],
   static_libs: [
     "libhealthhalutils",
+    "libstatslog_perfetto",
   ],
   export_include_dirs: [
     "include",
@@ -701,6 +706,7 @@
     ":perfetto_src_base_base",
     ":perfetto_src_base_unix_socket",
     ":perfetto_src_ipc_ipc",
+    ":perfetto_src_perfetto_cmd_perfetto_atoms",
     ":perfetto_src_perfetto_cmd_perfetto_cmd",
     ":perfetto_src_perfetto_cmd_protos_gen",
     ":perfetto_src_perfetto_cmd_trigger_producer",
@@ -968,6 +974,7 @@
     ":perfetto_src_base_test_support",
     ":perfetto_src_base_unix_socket",
     ":perfetto_src_ipc_ipc",
+    ":perfetto_src_perfetto_cmd_perfetto_atoms",
     ":perfetto_src_profiling_memory_client",
     ":perfetto_src_profiling_memory_daemon",
     ":perfetto_src_profiling_memory_end_to_end_tests",
@@ -4043,6 +4050,7 @@
     "src/android_internal/health_hal.cc",
     "src/android_internal/incident_service.cc",
     "src/android_internal/power_stats_hal.cc",
+    "src/android_internal/statsd_logging.cc",
   ],
 }
 
@@ -4203,6 +4211,11 @@
   ],
 }
 
+// GN: //src/perfetto_cmd:perfetto_atoms
+filegroup {
+  name: "perfetto_src_perfetto_cmd_perfetto_atoms",
+}
+
 // GN: //src/perfetto_cmd:perfetto_cmd
 filegroup {
   name: "perfetto_src_perfetto_cmd_perfetto_cmd",
@@ -5408,6 +5421,7 @@
     ":perfetto_src_ipc_ipc",
     ":perfetto_src_ipc_test_messages_gen",
     ":perfetto_src_ipc_unittests",
+    ":perfetto_src_perfetto_cmd_perfetto_atoms",
     ":perfetto_src_perfetto_cmd_perfetto_cmd",
     ":perfetto_src_perfetto_cmd_protos_gen",
     ":perfetto_src_perfetto_cmd_trigger_producer",
@@ -6110,4 +6124,39 @@
   defaults: [
     "perfetto_defaults",
   ],
+}
+
+cc_library_static {
+    name: "libstatslog_perfetto",
+    generated_sources: ["statslog_perfetto.cpp"],
+    generated_headers: ["statslog_perfetto.h"],
+    cflags: [
+        "-Wall",
+        "-Werror",
+    ],
+    export_generated_headers: ["statslog_perfetto.h"],
+    shared_libs: [
+        "libcutils",
+        "liblog",
+        "libstatssocket",
+        "libutils",
+    ],
+}
+
+genrule {
+    name: "statslog_perfetto.h",
+    tools: ["stats-log-api-gen"],
+    cmd: "$(location stats-log-api-gen) --header $(genDir)/statslog_perfetto.h --module perfetto --namespace perfetto,android_internal",
+    out: [
+        "statslog_perfetto.h",
+    ],
+}
+
+genrule {
+    name: "statslog_perfetto.cpp",
+    tools: ["stats-log-api-gen"],
+    cmd: "$(location stats-log-api-gen) --cpp $(genDir)/statslog_perfetto.cpp --module perfetto --namespace perfetto,android_internal --importHeader statslog_perfetto.h",
+    out: [
+        "statslog_perfetto.cpp",
+    ],
 }
\ No newline at end of file
diff --git a/Android.bp.extras b/Android.bp.extras
index ef14e45..6011886 100644
--- a/Android.bp.extras
+++ b/Android.bp.extras
@@ -83,3 +83,38 @@
     "perfetto_defaults",
   ],
 }
+
+cc_library_static {
+    name: "libstatslog_perfetto",
+    generated_sources: ["statslog_perfetto.cpp"],
+    generated_headers: ["statslog_perfetto.h"],
+    cflags: [
+        "-Wall",
+        "-Werror",
+    ],
+    export_generated_headers: ["statslog_perfetto.h"],
+    shared_libs: [
+        "libcutils",
+        "liblog",
+        "libstatssocket",
+        "libutils",
+    ],
+}
+
+genrule {
+    name: "statslog_perfetto.h",
+    tools: ["stats-log-api-gen"],
+    cmd: "$(location stats-log-api-gen) --header $(genDir)/statslog_perfetto.h --module perfetto --namespace perfetto,android_internal",
+    out: [
+        "statslog_perfetto.h",
+    ],
+}
+
+genrule {
+    name: "statslog_perfetto.cpp",
+    tools: ["stats-log-api-gen"],
+    cmd: "$(location stats-log-api-gen) --cpp $(genDir)/statslog_perfetto.cpp --module perfetto --namespace perfetto,android_internal --importHeader statslog_perfetto.h",
+    out: [
+        "statslog_perfetto.cpp",
+    ],
+}
diff --git a/BUILD b/BUILD
index 57831e6..94ba105 100644
--- a/BUILD
+++ b/BUILD
@@ -118,6 +118,7 @@
         ":src_base_base",
         ":src_base_unix_socket",
         ":src_ipc_ipc",
+        ":src_perfetto_cmd_perfetto_atoms",
         ":src_protozero_protozero",
         ":src_traced_probes_android_log_android_log",
         ":src_traced_probes_data_source",
@@ -437,6 +438,7 @@
         "src/android_internal/health_hal.h",
         "src/android_internal/incident_service.h",
         "src/android_internal/power_stats_hal.h",
+        "src/android_internal/statsd_logging.h",
     ],
 )
 
@@ -497,6 +499,14 @@
     ],
 )
 
+# GN target: //src/perfetto_cmd:perfetto_atoms
+filegroup(
+    name = "src_perfetto_cmd_perfetto_atoms",
+    srcs = [
+        "src/perfetto_cmd/perfetto_atoms.h",
+    ],
+)
+
 # GN target: //src/perfetto_cmd:perfetto_cmd
 filegroup(
     name = "src_perfetto_cmd_perfetto_cmd",
@@ -2318,6 +2328,7 @@
         ":src_base_base",
         ":src_base_unix_socket",
         ":src_ipc_ipc",
+        ":src_perfetto_cmd_perfetto_atoms",
         ":src_perfetto_cmd_perfetto_cmd",
         ":src_perfetto_cmd_trigger_producer",
         ":src_protozero_protozero",
diff --git a/include/perfetto/base/time.h b/include/perfetto/base/time.h
index b58c0ed..8c81faa 100644
--- a/include/perfetto/base/time.h
+++ b/include/perfetto/base/time.h
@@ -142,6 +142,10 @@
 
 #endif
 
+inline TimeSeconds GetBootTimeS() {
+  return std::chrono::duration_cast<TimeSeconds>(GetBootTimeNs());
+}
+
 inline TimeMillis GetWallTimeMs() {
   return std::chrono::duration_cast<TimeMillis>(GetWallTimeNs());
 }
diff --git a/src/android_internal/BUILD.gn b/src/android_internal/BUILD.gn
index 819532a..4306b16 100644
--- a/src/android_internal/BUILD.gn
+++ b/src/android_internal/BUILD.gn
@@ -26,6 +26,7 @@
 source_set("headers") {
   deps = [
     "../../gn:default_deps",
+    "../../src/perfetto_cmd:perfetto_atoms",
   ]
   sources = [
     "atrace_hal.h",
@@ -33,6 +34,7 @@
     "health_hal.h",
     "incident_service.h",
     "power_stats_hal.h",
+    "statsd_logging.h",
   ]
 }
 
@@ -66,11 +68,15 @@
       "health_hal.cc",
       "incident_service.cc",
       "power_stats_hal.cc",
+      "statsd_logging.cc",
     ]
     libs = [
       "android.hardware.health@2.0",
       "android.hardware.power.stats@1.0",
       "android.hardware.atrace@1.0",
+      "statslog_perfetto",
+      "statssocket",
+      "cutils",
       "base",
       "binder",
       "log",
diff --git a/src/android_internal/statsd_logging.cc b/src/android_internal/statsd_logging.cc
new file mode 100644
index 0000000..7c57e6b
--- /dev/null
+++ b/src/android_internal/statsd_logging.cc
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "src/android_internal/statsd_logging.h"
+
+#include <string.h>
+
+#include <statslog_perfetto.h>
+
+namespace perfetto {
+namespace android_internal {
+
+void StatsdLogEvent(PerfettoStatsdAtom atom, const char* uuid) {
+  uint64_t uuid_lsb = 0;
+  uint64_t uuid_msb = 0;
+  memcpy(&uuid_lsb, uuid, 8);
+  memcpy(&uuid_msb, uuid + 8, 8);
+  stats_write(PERFETTO_UPLOADED, static_cast<int32_t>(atom), uuid_lsb,
+              uuid_msb);
+}
+
+}  // namespace android_internal
+}  // namespace perfetto
diff --git a/src/android_internal/statsd_logging.h b/src/android_internal/statsd_logging.h
new file mode 100644
index 0000000..9590ab6
--- /dev/null
+++ b/src/android_internal/statsd_logging.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SRC_ANDROID_INTERNAL_STATSD_LOGGING_H_
+#define SRC_ANDROID_INTERNAL_STATSD_LOGGING_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "src/perfetto_cmd/perfetto_atoms.h"
+
+namespace perfetto {
+namespace android_internal {
+
+extern "C" {
+
+void __attribute__((visibility("default")))
+StatsdLogEvent(PerfettoStatsdAtom atom, const char* uuid);
+
+}  // extern "C"
+
+}  // namespace android_internal
+}  // namespace perfetto
+
+#endif  // SRC_ANDROID_INTERNAL_STATSD_LOGGING_H_
diff --git a/src/perfetto_cmd/BUILD.gn b/src/perfetto_cmd/BUILD.gn
index fe6cf12..38a3e53 100644
--- a/src/perfetto_cmd/BUILD.gn
+++ b/src/perfetto_cmd/BUILD.gn
@@ -44,6 +44,12 @@
   ]
 }
 
+source_set("perfetto_atoms") {
+  sources = [
+    "perfetto_atoms.h",
+  ]
+}
+
 # Contains all the implementation but not the main() entry point. This target
 # is shared both by the executable and tests.
 source_set("perfetto_cmd") {
@@ -52,6 +58,7 @@
     "../../include/perfetto/ext/traced",
   ]
   deps = [
+    ":perfetto_atoms",
     ":trigger_producer",
     "../../gn:default_deps",
     "../../gn:zlib",
diff --git a/src/perfetto_cmd/perfetto_atoms.h b/src/perfetto_cmd/perfetto_atoms.h
new file mode 100644
index 0000000..35903ea
--- /dev/null
+++ b/src/perfetto_cmd/perfetto_atoms.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SRC_PERFETTO_CMD_PERFETTO_ATOMS_H_
+#define SRC_PERFETTO_CMD_PERFETTO_ATOMS_H_
+
+namespace perfetto {
+
+// This must match the values of the PerfettoUploadEvent enum in:
+// frameworks/base/cmds/statsd/src/atoms.proto
+enum class PerfettoStatsdAtom {
+  kUndefined = 0,
+
+  kTraceBegin = 1,
+  kBackgroundTraceBegin = 2,
+
+  kOnConnect = 3,
+  kOnTracingDisabled = 4,
+
+  kUploadDropboxBegin = 5,
+  kUploadDropboxSuccess = 6,
+  kUploadDropboxFailure = 7,
+
+  kUploadIncidentBegin = 8,
+  kUploadIncidentSuccess = 9,
+  kUploadIncidentFailure = 10,
+
+  kFinalizeTraceAndExit = 11,
+
+  kTriggerBegin = 12,
+  kTriggerSuccess = 13,
+  kTriggerFailure = 14,
+
+  kHitGuardrails = 15,
+  kOnTimeout = 16,
+  kNotUploadingEmptyTrace = 17,
+};
+
+}  // namespace perfetto
+
+#endif  // SRC_PERFETTO_CMD_PERFETTO_ATOMS_H_
diff --git a/src/perfetto_cmd/perfetto_cmd.cc b/src/perfetto_cmd/perfetto_cmd.cc
index da3850b..3727a7f 100644
--- a/src/perfetto_cmd/perfetto_cmd.cc
+++ b/src/perfetto_cmd/perfetto_cmd.cc
@@ -30,11 +30,13 @@
 #include <iterator>
 #include <sstream>
 
+#include "perfetto/base/compiler.h"
 #include "perfetto/base/logging.h"
 #include "perfetto/base/time.h"
 #include "perfetto/ext/base/file_utils.h"
 #include "perfetto/ext/base/string_view.h"
 #include "perfetto/ext/base/utils.h"
+#include "perfetto/ext/base/uuid.h"
 #include "perfetto/ext/traced/traced.h"
 #include "perfetto/ext/tracing/core/basic_types.h"
 #include "perfetto/ext/tracing/core/trace_packet.h"
@@ -545,6 +547,7 @@
   // connect as a consumer or run the trace. So bail out after processing all
   // the options.
   if (!triggers_to_activate.empty()) {
+    LogUploadEvent(PerfettoStatsdAtom::kTriggerBegin);
     bool finished_with_success = false;
     TriggerProducer producer(
         &task_runner_,
@@ -554,6 +557,11 @@
         },
         &triggers_to_activate);
     task_runner_.Run();
+    if (finished_with_success) {
+      LogUploadEvent(PerfettoStatsdAtom::kTriggerSuccess);
+    } else {
+      LogUploadEvent(PerfettoStatsdAtom::kTriggerFailure);
+    }
     return finished_with_success ? 0 : 1;
   }
 
@@ -601,8 +609,16 @@
     expected_duration_ms_ = timeout_ms + max_stop_delay_ms;
   }
 
-  if (!limiter.ShouldTrace(args))
+  if (trace_config_->trigger_config().trigger_timeout_ms() == 0) {
+    LogUploadEvent(PerfettoStatsdAtom::kTraceBegin);
+  } else {
+    LogUploadEvent(PerfettoStatsdAtom::kBackgroundTraceBegin);
+  }
+
+  if (!limiter.ShouldTrace(args)) {
+    LogUploadEvent(PerfettoStatsdAtom::kHitGuardrails);
     return 1;
+  }
 
   consumer_endpoint_ =
       ConsumerIPCClient::Connect(GetConsumerSocket(), this, &task_runner_);
@@ -614,6 +630,7 @@
 }
 
 void PerfettoCmd::OnConnect() {
+  LogUploadEvent(PerfettoStatsdAtom::kOnConnect);
   if (query_service_) {
     consumer_endpoint_->QueryServiceState(
         [this](bool success, const TracingServiceState& svc_state) {
@@ -666,6 +683,7 @@
 
 void PerfettoCmd::OnTimeout() {
   PERFETTO_ELOG("Timed out while waiting for trace from the service, aborting");
+  LogUploadEvent(PerfettoStatsdAtom::kOnTimeout);
   task_runner_.Quit();
 }
 
@@ -693,6 +711,8 @@
 }
 
 void PerfettoCmd::OnTracingDisabled() {
+  LogUploadEvent(PerfettoStatsdAtom::kOnTracingDisabled);
+
   if (trace_config_->write_into_file()) {
     // If write_into_file == true, at this point the passed file contains
     // already all the packets.
@@ -708,6 +728,7 @@
 }
 
 void PerfettoCmd::FinalizeTraceAndExit() {
+  LogUploadEvent(PerfettoStatsdAtom::kFinalizeTraceAndExit);
   packet_writer_.reset();
 
   if (trace_out_stream_) {
@@ -869,6 +890,14 @@
 void PerfettoCmd::OnObservableEvents(
     const ObservableEvents& /*observable_events*/) {}
 
+void PerfettoCmd::LogUploadEvent(PerfettoStatsdAtom atom) {
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+  LogUploadEventAndroid(atom);
+#else
+  base::ignore_result(atom);
+#endif
+}
+
 int __attribute__((visibility("default")))
 PerfettoCmdMain(int argc, char** argv) {
   g_consumer_cmd = new perfetto::PerfettoCmd();
diff --git a/src/perfetto_cmd/perfetto_cmd.h b/src/perfetto_cmd/perfetto_cmd.h
index ea93a8c..d09a120 100644
--- a/src/perfetto_cmd/perfetto_cmd.h
+++ b/src/perfetto_cmd/perfetto_cmd.h
@@ -28,12 +28,11 @@
 #include "perfetto/ext/base/optional.h"
 #include "perfetto/ext/base/scoped_file.h"
 #include "perfetto/ext/base/unix_task_runner.h"
-#include "perfetto/ext/base/uuid.h"
 #include "perfetto/ext/tracing/core/consumer.h"
 #include "perfetto/ext/tracing/ipc/consumer_ipc_client.h"
-#include "src/perfetto_cmd/rate_limiter.h"
-
+#include "src/perfetto_cmd/perfetto_atoms.h"
 #include "src/perfetto_cmd/perfetto_cmd_state.pb.h"
+#include "src/perfetto_cmd/rate_limiter.h"
 
 namespace perfetto {
 
@@ -82,7 +81,9 @@
   void SaveTraceIntoDropboxAndIncidentOrCrash();
   void SaveOutputToDropboxOrCrash();
   void SaveOutputToIncidentTraceOrCrash();
+  void LogUploadEventAndroid(PerfettoStatsdAtom atom);
 #endif
+  void LogUploadEvent(PerfettoStatsdAtom atom);
 
   base::UnixTaskRunner task_runner_;
 
diff --git a/src/perfetto_cmd/perfetto_cmd_android.cc b/src/perfetto_cmd/perfetto_cmd_android.cc
index ee131d9..46cff98 100644
--- a/src/perfetto_cmd/perfetto_cmd_android.cc
+++ b/src/perfetto_cmd/perfetto_cmd_android.cc
@@ -25,42 +25,50 @@
 #include "src/android_internal/dropbox_service.h"
 #include "src/android_internal/incident_service.h"
 #include "src/android_internal/lazy_library_loader.h"
+#include "src/android_internal/statsd_logging.h"
 
 namespace perfetto {
 
 void PerfettoCmd::SaveTraceIntoDropboxAndIncidentOrCrash() {
   PERFETTO_CHECK(!dropbox_tag_.empty());
 
+  bool use_dropbox = !trace_config_->incident_report_config().skip_dropbox();
+  bool use_incident =
+      !trace_config_->incident_report_config().destination_package().empty();
+
+  if (bytes_written_ == 0) {
+    LogUploadEvent(PerfettoStatsdAtom::kNotUploadingEmptyTrace);
+    if (use_dropbox)
+      PERFETTO_LOG("Skipping write to dropbox. Empty trace.");
+    if (use_incident)
+      PERFETTO_LOG("Skipping write to incident. Empty trace.");
+    return;
+  }
+
   // Otherwise, write to Dropbox unless there's a special override in the
   // incident report config.
-  if (!trace_config_->incident_report_config().skip_dropbox()) {
-    if (bytes_written_ == 0) {
-      PERFETTO_LOG("Skipping write to dropbox. Empty trace.");
-    } else {
-      SaveOutputToDropboxOrCrash();
-    }
+  if (use_dropbox) {
+    SaveOutputToDropboxOrCrash();
   }
 
   // Optionally save the trace as an incident. This is either in addition to, or
   // instead of, the Dropbox write.
-  if (!trace_config_->incident_report_config().destination_package().empty()) {
-    if (bytes_written_ == 0) {
-      PERFETTO_LOG("Skipping incident report. Empty trace.");
-    } else {
-      SaveOutputToIncidentTraceOrCrash();
+  if (use_incident) {
+    SaveOutputToIncidentTraceOrCrash();
 
-      // Ask incidentd to create a report, which will read the file we just
-      // wrote.
-      const auto& cfg = trace_config_->incident_report_config();
-      PERFETTO_LAZY_LOAD(android_internal::StartIncidentReport, incident_fn);
-      PERFETTO_CHECK(incident_fn(cfg.destination_package().c_str(),
-                                 cfg.destination_class().c_str(),
-                                 cfg.privacy_level()));
-    }
+    // Ask incidentd to create a report, which will read the file we just
+    // wrote.
+    const auto& cfg = trace_config_->incident_report_config();
+    PERFETTO_LAZY_LOAD(android_internal::StartIncidentReport, incident_fn);
+    PERFETTO_CHECK(incident_fn(cfg.destination_package().c_str(),
+                               cfg.destination_class().c_str(),
+                               cfg.privacy_level()));
   }
 }
 
 void PerfettoCmd::SaveOutputToDropboxOrCrash() {
+  LogUploadEvent(PerfettoStatsdAtom::kUploadDropboxBegin);
+
   PERFETTO_CHECK(fseek(*trace_out_stream_, 0, SEEK_SET) == 0);
 
   // DropBox takes ownership of the file descriptor, so give it a duplicate.
@@ -73,10 +81,12 @@
 
   PERFETTO_LAZY_LOAD(android_internal::SaveIntoDropbox, dropbox_fn);
   if (dropbox_fn(dropbox_tag_.c_str(), read_only_fd.release())) {
+    LogUploadEvent(PerfettoStatsdAtom::kUploadDropboxSuccess);
     PERFETTO_LOG("Wrote %" PRIu64
                  " bytes (before compression) into DropBox with tag %s",
                  bytes_written_, dropbox_tag_.c_str());
   } else {
+    LogUploadEvent(PerfettoStatsdAtom::kUploadDropboxFailure);
     PERFETTO_FATAL("DropBox upload failed");
   }
 }
@@ -87,6 +97,7 @@
 // unique filenames to avoid creating an unbounded amount of files in case of
 // errors.
 void PerfettoCmd::SaveOutputToIncidentTraceOrCrash() {
+  LogUploadEvent(PerfettoStatsdAtom::kUploadIncidentBegin);
   char kIncidentTracePath[256];
   sprintf(kIncidentTracePath, "%s/incident-trace", kStateDir);
 
@@ -107,6 +118,7 @@
   PERFETTO_CHECK(rename(kTempIncidentTracePath, kIncidentTracePath) == 0);
   // Note: not calling fsync(2), as we're not interested in the file being
   // consistent in case of a crash.
+  LogUploadEvent(PerfettoStatsdAtom::kUploadIncidentSuccess);
 }
 
 // static
@@ -119,4 +131,11 @@
   return fd;
 }
 
+void PerfettoCmd::LogUploadEventAndroid(PerfettoStatsdAtom atom) {
+  if (dropbox_tag_.empty())
+    return;
+  PERFETTO_LAZY_LOAD(android_internal::StatsdLogEvent, log_event_fn);
+  log_event_fn(atom, uuid_.c_str());
+}
+
 }  // namespace perfetto
diff --git a/tools/gen_android_bp b/tools/gen_android_bp
index 2d1203b..77a5947 100755
--- a/tools/gen_android_bp
+++ b/tools/gen_android_bp
@@ -92,22 +92,29 @@
 module_prefix = 'perfetto_'
 
 # Shared libraries which are directly translated to Android system equivalents.
-library_whitelist = [
-    "android.hardware.atrace@1.0",
-    'android.hardware.health@2.0',
-    "android.hardware.power.stats@1.0",
+shared_library_whitelist = [
     'android',
+    'android.hardware.atrace@1.0',
+    'android.hardware.health@2.0',
+    'android.hardware.power.stats@1.0',
     'base',
     'binder',
+    'cutils',
     'hidlbase',
     'hidltransport',
     'hwbinder',
     'incident',
     'log',
     'services',
+    'statssocket',
     'utils',
 ]
 
+# Static libraries which are directly translated to Android system equivalents.
+static_library_whitelist = [
+    'statslog_perfetto',
+]
+
 # Name of the module which settings such as compiler flags for all other
 # modules.
 defaults_module = module_prefix + 'defaults'
@@ -614,8 +621,10 @@
       # Generally library names should be mangled as 'libXXX', unless they
       # are HAL libraries (e.g., android.hardware.health@2.0).
       android_lib = lib if '@' in lib else 'lib' + lib
-      if lib in library_whitelist:
+      if lib in shared_library_whitelist:
         module.shared_libs.add(android_lib)
+      if lib in static_library_whitelist:
+        module.static_libs.add(android_lib)
 
   # If the module is a static library, export all the generated headers.
   if module.type == 'cc_library_static':