Added support to read multiple fields from cmdline.

Bug:73058765
Change-Id: I855d50393048ea9700d7ea050b95df1fc405e6d7
diff --git a/src/process_stats/process_info.h b/src/process_stats/process_info.h
index 1c8a5d9..2739644 100644
--- a/src/process_stats/process_info.h
+++ b/src/process_stats/process_info.h
@@ -6,6 +6,7 @@
 #define SRC_PROCESS_STATS_PROCESS_INFO_H_
 
 #include <map>
+#include <vector>
 
 struct ThreadInfo {
   int tid;
@@ -18,7 +19,7 @@
   bool in_kernel;
   bool is_app;
   char exe[256];
-  char cmdline[256];
+  std::vector<std::string> cmdline;
   std::map<int, ThreadInfo> threads;
 };
 
diff --git a/src/process_stats/procfs_utils.cc b/src/process_stats/procfs_utils.cc
index 1c2d2e6..4aa9744 100644
--- a/src/process_stats/procfs_utils.cc
+++ b/src/process_stats/procfs_utils.cc
@@ -50,7 +50,17 @@
     return -1;
   const char* line = strstr(buf, status_string);
   PERFETTO_DCHECK(line);
-  return atoi(line + sizeof(status_string) - 1);
+  return atoi(line + strlen(status_string));
+}
+
+inline std::vector<std::string> SplitOnNull(const char* input) {
+  std::vector<std::string> output;
+  do {
+    // This works because it will only push the string up to a null character.
+    output.push_back(std::string(input));
+    input += output.back().size() + 1;
+  } while (input[0] != 0);
+  return output;
 }
 
 }  // namespace
@@ -66,14 +76,19 @@
 std::unique_ptr<ProcessInfo> ReadProcessInfo(int pid) {
   ProcessInfo* process = new ProcessInfo();
   process->pid = pid;
-  // TODO(taylori) Parse full cmdline into a vector.
-  ReadProcString(pid, "cmdline", process->cmdline, sizeof(process->cmdline));
-  if (process->cmdline[0] == 0) {
-    ReadProcString(pid, "comm", process->cmdline, sizeof(process->cmdline));
+  char cmdline_buf[256];
+  process->cmdline = SplitOnNull("\0");
+  ReadProcString(pid, "cmdline", cmdline_buf, sizeof(cmdline_buf));
+  if (cmdline_buf[0] == 0) {
+    // Nothing in cmdline_buf so read name from /comm instead.
+    char name[256];
+    ReadProcString(pid, "comm", name, sizeof(name));
+    process->cmdline.push_back(name);
     process->in_kernel = true;
   } else {
+    process->cmdline = SplitOnNull(cmdline_buf);
     ReadExePath(pid, process->exe, sizeof(process->exe));
-    process->is_app = IsApp(process->cmdline, process->exe);
+    process->is_app = IsApp(process->cmdline[0].c_str(), process->exe);
   }
   process->ppid = ReadPpid(pid);
   return std::unique_ptr<ProcessInfo>(process);
diff --git a/src/traced/probes/probes_producer.cc b/src/traced/probes/probes_producer.cc
index 7c81c1d..5ac726c 100644
--- a/src/traced/probes/probes_producer.cc
+++ b/src/traced/probes/probes_producer.cc
@@ -156,8 +156,8 @@
         auto* process_writer = process_tree->add_processes();
         process_writer->set_pid(process->pid);
         process_writer->set_ppid(process->ppid);
-        process_writer->add_cmdline(process->cmdline);
-
+        for (const auto& field : process->cmdline)
+          process_writer->add_cmdline(field.c_str());
         for (auto& thread : process->threads) {
           auto* thread_writer = process_writer->add_threads();
           thread_writer->set_tid(thread.second.tid);
diff --git a/tools/trace_to_text/main.cc b/tools/trace_to_text/main.cc
index 7c9c92d..7fe7c63 100644
--- a/tools/trace_to_text/main.cc
+++ b/tools/trace_to_text/main.cc
@@ -845,9 +845,15 @@
 // TODO(taylori): Confirm correct format for this.
 std::string FormatProcess(const Process& process) {
   char line[2048];
-  sprintf(line, "process: pid=%d ppid=%d cmdline=%s\\n", process.pid(),
-          process.ppid(), process.cmdline(0).c_str());
+  sprintf(line, "process: pid=%d ppid=%d cmdline=", process.pid(),
+          process.ppid());
   std::string output = std::string(line);
+  for (auto field : process.cmdline()) {
+    char cmd[2048];
+    sprintf(cmd, "%s ", field.c_str());
+    output += std::string(cmd);
+  }
+  output += "\\n";
   for (auto thread : process.threads()) {
     char thread_line[2048];
     sprintf(thread_line, "thread: tid=%d name=%s\\n", thread.tid(),