Add clock ftrace APIs

Add methods to ftrace_procfs to read/write the trace_clock file.

Bug: 72932275
Change-Id: Iee69906c453f6c4860025fbc9ad75c39c4f0a3c8
diff --git a/src/ftrace_reader/ftrace_procfs.cc b/src/ftrace_reader/ftrace_procfs.cc
index db5975a..f4998bd 100644
--- a/src/ftrace_reader/ftrace_procfs.cc
+++ b/src/ftrace_reader/ftrace_procfs.cc
@@ -147,6 +147,48 @@
   return ReadOneCharFromFile(path) == '1';
 }
 
+bool FtraceProcfs::SetClock(const std::string& clock_name) {
+  std::string path = root_ + "trace_clock";
+  return WriteToFile(path, clock_name);
+}
+
+std::string FtraceProcfs::GetClock() {
+  std::string path = root_ + "trace_clock";
+  std::string s = ReadFileIntoString(path);
+
+  size_t start = s.find("[");
+  if (start == std::string::npos)
+    return "";
+
+  size_t end = s.find("]", start);
+  if (end == std::string::npos)
+    return "";
+
+  return s.substr(start + 1, end - start - 1);
+}
+
+std::set<std::string> FtraceProcfs::AvailableClocks() {
+  std::string path = root_ + "trace_clock";
+  std::string s = ReadFileIntoString(path);
+  std::set<std::string> names;
+
+  size_t start = 0;
+  size_t end = 0;
+
+  while ((end = s.find(" ", start)) != std::string::npos) {
+    std::string name = s.substr(start, end - start);
+
+    if (name[0] == '[')
+      name = name.substr(1, name.size() - 2);
+
+    names.insert(name);
+
+    start = end + 1;
+  }
+
+  return names;
+}
+
 bool FtraceProcfs::WriteNumberToFile(const std::string& path, size_t value) {
   // 2^65 requires 20 digits to write.
   char buf[21];
diff --git a/src/ftrace_reader/ftrace_procfs.h b/src/ftrace_reader/ftrace_procfs.h
index a964551..b4fe27b 100644
--- a/src/ftrace_reader/ftrace_procfs.h
+++ b/src/ftrace_reader/ftrace_procfs.h
@@ -18,6 +18,7 @@
 #define SRC_FTRACE_READER_FTRACE_PROCFS_H_
 
 #include <memory>
+#include <set>
 #include <string>
 
 #include "perfetto/base/scoped_file.h"
@@ -74,6 +75,16 @@
   // point.
   bool IsTracingEnabled();
 
+  // Set the clock. |clock_name| should be one of the names returned by
+  // AvailableClocks. Setting the clock clears the buffer.
+  bool SetClock(const std::string& clock_name);
+
+  // Get the currently set clock.
+  std::string GetClock();
+
+  // Get all the avaiable clocks.
+  std::set<std::string> AvailableClocks();
+
   // Open the raw pipe for |cpu|.
   virtual base::ScopedFile OpenPipeForCpu(size_t cpu);
 
diff --git a/src/ftrace_reader/ftrace_procfs_integrationtest.cc b/src/ftrace_reader/ftrace_procfs_integrationtest.cc
index 19690d8..620cd87 100644
--- a/src/ftrace_reader/ftrace_procfs_integrationtest.cc
+++ b/src/ftrace_reader/ftrace_procfs_integrationtest.cc
@@ -15,7 +15,9 @@
  */
 
 #include <fstream>
+#include <set>
 #include <sstream>
+#include <string>
 
 #include "ftrace_procfs.h"
 #include "gmock/gmock.h"
@@ -23,6 +25,7 @@
 
 using testing::HasSubstr;
 using testing::Not;
+using testing::Contains;
 
 namespace perfetto {
 namespace {
@@ -128,6 +131,18 @@
   EXPECT_TRUE(ftrace.OpenPipeForCpu(0));
 }
 
+TEST(FtraceProcfsIntegrationTest, DISABLED_Clock) {
+  FtraceProcfs ftrace(kTracingPath);
+  std::set<std::string> clocks = ftrace.AvailableClocks();
+  EXPECT_THAT(clocks, Contains("local"));
+  EXPECT_THAT(clocks, Contains("global"));
+
+  EXPECT_TRUE(ftrace.SetClock("global"));
+  EXPECT_EQ(ftrace.GetClock(), "global");
+  EXPECT_TRUE(ftrace.SetClock("local"));
+  EXPECT_EQ(ftrace.GetClock(), "local");
+}
+
 TEST(FtraceProcfsIntegrationTest, DISABLED_CanSetBufferSize) {
   FtraceProcfs ftrace(kTracingPath);
   EXPECT_TRUE(ftrace.SetCpuBufferSizeInPages(4ul));
diff --git a/src/ftrace_reader/test/explorer.html b/src/ftrace_reader/test/explorer.html
index 4d15600..a567b10 100755
--- a/src/ftrace_reader/test/explorer.html
+++ b/src/ftrace_reader/test/explorer.html
@@ -246,7 +246,7 @@
       value: filterText,
     }),
     m('ul',
-      Array.from(namesToRecords.entries()).filter(e => e[1].length > 1)
+      Array.from(namesToRecords.entries())
           .filter(e => matcher(e[0])).map(e => m('li[tabindex=0]', {
         onfocus: () => { gDisplayedRecords = e[1]; gDisplayedName = e[0];
       },