Snap for 8819924 from 613884e78e5284bab871e0468341a813f8955217 to mainline-wifi-release

Change-Id: Ie0b26682b9ffbd345e360a69226112fa3a15dd6c
diff --git a/src/profiling/common/producer_support.cc b/src/profiling/common/producer_support.cc
index 544d3c5..8ab0b42 100644
--- a/src/profiling/common/producer_support.cc
+++ b/src/profiling/common/producer_support.cc
@@ -98,25 +98,18 @@
                        const std::string& packages_list_path) {
   // These constants are replicated from libcutils android_filesystem_config.h,
   // to allow for building and testing the profilers outside the android tree.
-  constexpr auto kAidSystem = 1000;           // AID_SYSTEM
-  constexpr auto kAidUserOffset = 100000;     // AID_USER_OFFSET
-  constexpr auto kAidAppStart = 10000;        // AID_APP_START
-  constexpr auto kAidAppEnd = 19999;          // AID_APP_END
-  constexpr auto kAidSdkSandboxStart = 20000; // AID_SDK_SANDBOX_PROCESS_START
-  constexpr auto kAidSdkSandboxEnd = 29999;   // AID_SDK_SANDBOX_PROCESS_END
-  constexpr auto kAidIsolatedStart = 90000;   // AID_ISOLATED_START
-  constexpr auto kAidIsolatedEnd = 99999;     // AID_ISOLATED_END
+  constexpr auto kAidUserOffset = 100000;      // AID_USER_OFFSET
+  constexpr auto kAidAppStart = 10000;         // AID_APP_START
+  constexpr auto kAidAppEnd = 19999;           // AID_APP_END
+  constexpr auto kAidSdkSandboxStart = 20000;  // AID_SDK_SANDBOX_PROCESS_START
+  constexpr auto kAidSdkSandboxEnd = 29999;    // AID_SDK_SANDBOX_PROCESS_END
+  constexpr auto kAidIsolatedStart = 90000;    // AID_ISOLATED_START
+  constexpr auto kAidIsolatedEnd = 99999;      // AID_ISOLATED_END
 
   if (!build_type.empty() && build_type != "user") {
     return true;
   }
 
-  // TODO(b/217368496): remove this.
-  if (uid == kAidSystem) {
-    return ds_config.session_initiator() ==
-      DataSourceConfig::SESSION_INITIATOR_TRUSTED_SYSTEM;
-  }
-
   uint64_t uid_without_profile = uid % kAidUserOffset;
   uint64_t uid_for_lookup = 0;
   if (uid_without_profile >= kAidAppStart &&
diff --git a/src/traced/probes/ftrace/ftrace_config_muxer.cc b/src/traced/probes/ftrace/ftrace_config_muxer.cc
index 6d3a546..69c4176 100644
--- a/src/traced/probes/ftrace/ftrace_config_muxer.cc
+++ b/src/traced/probes/ftrace/ftrace_config_muxer.cc
@@ -95,12 +95,6 @@
   *out = std::move(v);
 }
 
-bool SupportsRssStatThrottled(const FtraceProcfs& ftrace_procfs) {
-  const auto trigger_info = ftrace_procfs.ReadEventTrigger("kmem", "rss_stat");
-
-  return trigger_info.find("rss_stat_throttled") != std::string::npos;
-}
-
 // This is just to reduce binary size and stack frame size of the insertions.
 // It effectively undoes STL's set::insert inlining.
 void PERFETTO_NO_INLINE InsertEvent(const char* group,
@@ -416,7 +410,7 @@
 
       if (category == "memory") {
         // Use rss_stat_throttled if supported
-        if (SupportsRssStatThrottled(*ftrace_)) {
+        if (ftrace_->SupportsRssStatThrottled()) {
           InsertEvent("synthetic", "rss_stat_throttled", &events);
         } else {
           InsertEvent("kmem", "rss_stat", &events);
@@ -440,7 +434,7 @@
   }
 
   // If throttle_rss_stat: true, use the rss_stat_throttled event if supported
-  if (request.throttle_rss_stat() && SupportsRssStatThrottled(*ftrace_)) {
+  if (request.throttle_rss_stat() && ftrace_->SupportsRssStatThrottled()) {
     auto it = std::find_if(
         events.begin(), events.end(), [](const GroupAndName& event) {
           return event.group() == "kmem" && event.name() == "rss_stat";
diff --git a/src/traced/probes/ftrace/ftrace_procfs.cc b/src/traced/probes/ftrace/ftrace_procfs.cc
index e393648..55b81b4 100644
--- a/src/traced/probes/ftrace/ftrace_procfs.cc
+++ b/src/traced/probes/ftrace/ftrace_procfs.cc
@@ -45,6 +45,12 @@
 
 namespace {
 
+namespace {
+constexpr char kRssStatThrottledTrigger[] =
+    "hist:keys=mm_id,member:bucket=size/0x80000"
+    ":onchange($bucket).rss_stat_throttled(mm_id,curr,member,size)";
+}
+
 void KernelLogWrite(const char* s) {
   PERFETTO_DCHECK(*s && s[strlen(s) - 1] == '\n');
   if (FtraceProcfs::g_kmesg_fd != -1)
@@ -104,6 +110,11 @@
 bool FtraceProcfs::EnableEvent(const std::string& group,
                                const std::string& name) {
   std::string path = root_ + "events/" + group + "/" + name + "/enable";
+
+  // Create any required triggers for the ftrace event being enabled.
+  // Some ftrace events (synthetic events) need to set up an event trigger
+  MaybeSetUpEventTriggers(group, name);
+
   if (WriteToFile(path, "1"))
     return true;
   path = root_ + "set_event";
@@ -113,10 +124,17 @@
 bool FtraceProcfs::DisableEvent(const std::string& group,
                                 const std::string& name) {
   std::string path = root_ + "events/" + group + "/" + name + "/enable";
-  if (WriteToFile(path, "0"))
-    return true;
-  path = root_ + "set_event";
-  return AppendToFile(path, "!" + group + ":" + name);
+
+  bool ret = WriteToFile(path, "0");
+  if (!ret) {
+    path = root_ + "set_event";
+    ret = AppendToFile(path, "!" + group + ":" + name);
+  }
+
+  // Remove any associated event triggers after disabling the event
+  MaybeTearDownEventTriggers(group, name);
+
+  return ret;
 }
 
 bool FtraceProcfs::DisableAllEvents() {
@@ -130,10 +148,110 @@
   return ReadFileIntoString(path);
 }
 
-std::string FtraceProcfs::ReadEventTrigger(const std::string& group,
-                                           const std::string& name) const {
+std::vector<std::string> FtraceProcfs::ReadEventTriggers(
+    const std::string& group,
+    const std::string& name) const {
   std::string path = root_ + "events/" + group + "/" + name + "/trigger";
-  return ReadFileIntoString(path);
+  std::string s = ReadFileIntoString(path);
+  std::vector<std::string> triggers;
+
+  for (base::StringSplitter ss(s, '\n'); ss.Next();) {
+    std::string trigger = ss.cur_token();
+    if (trigger.empty() || trigger[0] == '#')
+      continue;
+
+    base::StringSplitter ts(trigger, ' ');
+    PERFETTO_CHECK(ts.Next());
+    triggers.push_back(ts.cur_token());
+  }
+
+  return triggers;
+}
+
+bool FtraceProcfs::CreateEventTrigger(const std::string& group,
+                                      const std::string& name,
+                                      const std::string& trigger) {
+  std::string path = root_ + "events/" + group + "/" + name + "/trigger";
+  return WriteToFile(path, trigger);
+}
+
+bool FtraceProcfs::RemoveEventTrigger(const std::string& group,
+                                      const std::string& name,
+                                      const std::string& trigger) {
+  std::string path = root_ + "events/" + group + "/" + name + "/trigger";
+  return WriteToFile(path, "!" + trigger);
+}
+
+bool FtraceProcfs::RemoveAllEventTriggers(const std::string& group,
+                                          const std::string& name) {
+  std::vector<std::string> triggers = ReadEventTriggers(group, name);
+
+  // Remove the triggers in reverse order since a trigger can depend
+  // on another trigger created earlier.
+  for (auto it = triggers.rbegin(); it != triggers.rend(); ++it)
+    if (!RemoveEventTrigger(group, name, *it))
+      return false;
+  return true;
+}
+
+bool FtraceProcfs::MaybeSetUpEventTriggers(const std::string& group,
+                                           const std::string& name) {
+  bool ret = true;
+
+  if (group == "synthetic" && name == "rss_stat_throttled") {
+    ret = RemoveAllEventTriggers("kmem", "rss_stat") &&
+          CreateEventTrigger("kmem", "rss_stat", kRssStatThrottledTrigger);
+  }
+
+  if (!ret) {
+    PERFETTO_PLOG("Failed to setup event triggers for %s:%s", group.c_str(),
+                  name.c_str());
+  }
+
+  return ret;
+}
+
+bool FtraceProcfs::MaybeTearDownEventTriggers(const std::string& group,
+                                              const std::string& name) {
+  bool ret = true;
+
+  if (group == "synthetic" && name == "rss_stat_throttled")
+    ret = RemoveAllEventTriggers("kmem", "rss_stat");
+
+  if (!ret) {
+    PERFETTO_PLOG("Failed to tear down event triggers for: %s:%s",
+                  group.c_str(), name.c_str());
+  }
+
+  return ret;
+}
+
+bool FtraceProcfs::SupportsRssStatThrottled() {
+  std::string group = "synthetic";
+  std::string name = "rss_stat_throttled";
+
+  // Check if the trigger already exists. Don't try recreating
+  // or removing the trigger if it is already in use.
+  auto triggers = ReadEventTriggers("kmem", "rss_stat");
+  for (const auto& trigger : triggers) {
+    // The kernel shows all the default values of a trigger
+    // when read from and trace event 'trigger' file.
+    //
+    // Trying to match the complete trigger string is prone
+    // to fail if, in the future, the kernel changes default
+    // fields or values for event triggers.
+    //
+    // Do a partial match on the generated event name
+    // (rss_stat_throttled) to detect if the trigger
+    // is already created.
+    if (trigger.find(name) != std::string::npos)
+      return true;
+  }
+
+  // Attempt to create rss_stat_throttled hist trigger */
+  bool ret = MaybeSetUpEventTriggers(group, name);
+
+  return ret && MaybeTearDownEventTriggers(group, name);
 }
 
 std::string FtraceProcfs::ReadPrintkFormats() const {
diff --git a/src/traced/probes/ftrace/ftrace_procfs.h b/src/traced/probes/ftrace/ftrace_procfs.h
index 6e0791b..b7ddf99 100644
--- a/src/traced/probes/ftrace/ftrace_procfs.h
+++ b/src/traced/probes/ftrace/ftrace_procfs.h
@@ -58,9 +58,34 @@
 
   virtual std::string ReadPageHeaderFormat() const;
 
-  // Read the triggers for event with the given |group| and |name|.
-  std::string ReadEventTrigger(const std::string& group,
-                               const std::string& name) const;
+  // Get all triggers for event with the given |group| and |name|.
+  std::vector<std::string> ReadEventTriggers(const std::string& group,
+                                             const std::string& name) const;
+
+  // Create an event trigger for the given |group| and |name|.
+  bool CreateEventTrigger(const std::string& group,
+                          const std::string& name,
+                          const std::string& trigger);
+
+  // Remove an event trigger for the given |group| and |name|.
+  bool RemoveEventTrigger(const std::string& group,
+                          const std::string& name,
+                          const std::string& trigger);
+
+  // Remove all event trigger for the given |group| and |name|.
+  bool RemoveAllEventTriggers(const std::string& group,
+                              const std::string& name);
+
+  // Sets up any associated event trigger before enabling the event
+  bool MaybeSetUpEventTriggers(const std::string& group,
+                               const std::string& name);
+
+  // Tears down any associated event trigger after disabling the event
+  bool MaybeTearDownEventTriggers(const std::string& group,
+                                  const std::string& name);
+
+  // Returns true if rss_stat_throttled synthetic event is supported
+  bool SupportsRssStatThrottled();
 
   // Read the printk formats file.
   std::string ReadPrintkFormats() const;
diff --git a/test/configs/rss_stat.cfg b/test/configs/rss_stat.cfg
new file mode 100644
index 0000000..010aa97
--- /dev/null
+++ b/test/configs/rss_stat.cfg
@@ -0,0 +1,17 @@
+buffers: {
+  size_kb: 512
+  fill_policy: DISCARD
+}
+
+data_sources: {
+  config {
+    name: "linux.ftrace"
+    ftrace_config {
+      ftrace_events: "sched_switch"
+      ftrace_events: "kmem/rss_stat"
+      throttle_rss_stat: true
+    }
+  }
+}
+
+duration_ms: 10000