Split atrace, atrace-helper CMakeLists.txt 93/244593/5
authorSeungha Son <seungha.son@samsung.com>
Tue, 22 Sep 2020 06:55:37 +0000 (15:55 +0900)
committerSeungha Son <seungha.son@samsung.com>
Thu, 24 Sep 2020 02:39:03 +0000 (11:39 +0900)
Change-Id: Iaebd60a6feb8687f608cf1781974e9dacb2fe2e3
Signed-off-by: Seungha Son <seungha.son@samsung.com>
39 files changed:
CMakeLists.txt
atrace-helper/CMakeLists.txt [new file with mode: 0644]
atrace-helper/LICENSE [new file with mode: 0644]
atrace-helper/atrace_process_dump.cc [new file with mode: 0644]
atrace-helper/atrace_process_dump.h [new file with mode: 0644]
atrace-helper/file_utils.cc [new file with mode: 0644]
atrace-helper/file_utils.h [new file with mode: 0644]
atrace-helper/logging.h [new file with mode: 0644]
atrace-helper/main.cc [new file with mode: 0644]
atrace-helper/process_info.h [new file with mode: 0644]
atrace-helper/process_memory_stats.cc [new file with mode: 0644]
atrace-helper/process_memory_stats.h [new file with mode: 0644]
atrace-helper/procfs_utils.cc [new file with mode: 0644]
atrace-helper/procfs_utils.h [new file with mode: 0644]
atrace-helper/time_utils.cc [new file with mode: 0644]
atrace-helper/time_utils.h [new file with mode: 0644]
atrace.pc.in [deleted file]
atrace/CMakeLists.txt [new file with mode: 0644]
atrace/MODULE_LICENSE_APACHE2 [new file with mode: 0644]
atrace/NOTICE [new file with mode: 0644]
atrace/atrace.cpp [new file with mode: 0755]
packaging/ttrace.spec
src/atrace/MODULE_LICENSE_APACHE2 [deleted file]
src/atrace/NOTICE [deleted file]
src/atrace/atrace.cpp [deleted file]
src/atrace_helper/LICENSE [deleted file]
src/atrace_helper/atrace_process_dump.cc [deleted file]
src/atrace_helper/atrace_process_dump.h [deleted file]
src/atrace_helper/file_utils.cc [deleted file]
src/atrace_helper/file_utils.h [deleted file]
src/atrace_helper/logging.h [deleted file]
src/atrace_helper/main.cc [deleted file]
src/atrace_helper/process_info.h [deleted file]
src/atrace_helper/process_memory_stats.cc [deleted file]
src/atrace_helper/process_memory_stats.h [deleted file]
src/atrace_helper/procfs_utils.cc [deleted file]
src/atrace_helper/procfs_utils.h [deleted file]
src/atrace_helper/time_utils.cc [deleted file]
src/atrace_helper/time_utils.h [deleted file]

index 0d639684911717a23b8743e4bb71fd6338e200f5..8141fc7f0a90d698c76abf778299aacc9f8fe57f 100755 (executable)
@@ -80,50 +80,9 @@ TARGET_LINK_LIBRARIES(${TTRACE_STATIC} ${pkg_ttrace_LDFLAGS} "-ldl")
 FOREACH(hfile ${HEADERS_ttrace})
        INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/include/${hfile} DESTINATION ${INCLUDEDIR})
 ENDFOREACH(hfile)
+
 #################################################################
-# Build atrace Library (KK)
+# Build atrace / atrace-helper
 # ------------------------------
-SET(ATRACE "atrace")
-SET(SRCS_atrace src/atrace/atrace.cpp)
-SET(HEADERS_atrace src/ttrace/ttrace.h)
-
-INCLUDE(FindPkgConfig)
-pkg_check_modules(pkg_atrace REQUIRED zlib libsmack)
-FOREACH(flag ${pkg_atrace_CXXFLAGS})
-       SET(EXTRA_CXXFLAGS_common "${EXTRA_CXXFLAGS_common} ${flag}")
-ENDFOREACH(flag)
-SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CXXFLAGS} ${EXTRA_CXXFLAGS_common} -std=c++11")
-MESSAGE("CMAKE_CXX_FLAGS: ${CMAKE_CXX_FLAGS}")
-
-# Build atrace-helper
-SET(ATRACE_HELPER "atrace-helper")
-SET(ATRACE_HELPER_PATH src/atrace_helper)
-SET(SRCS_atrace_helper
-        ${ATRACE_HELPER_PATH}/atrace_process_dump.cc
-        ${ATRACE_HELPER_PATH}/file_utils.cc
-        ${ATRACE_HELPER_PATH}/main.cc
-        ${ATRACE_HELPER_PATH}/process_memory_stats.cc
-        ${ATRACE_HELPER_PATH}/procfs_utils.cc
-        ${ATRACE_HELPER_PATH}/time_utils.cc
-    )
-SET(HEADER_atrace_helper
-        ${ATRACE_HELPER_PATH}/atrace_process_dump.h
-        ${ATRACE_HELPER_PATH}/file_utils.h
-        ${ATRACE_HELPER_PATH}/logging.h
-        ${ATRACE_HELPER_PATH}/process_info.h
-        ${ATRACE_HELPER_PATH}/process_memory_stats.h
-        ${ATRACE_HELPER_PATH}/procfs_utils.h
-        ${ATRACE_HELPER_PATH}/tile_utils.h
-    )
-
-ADD_EXECUTABLE(${ATRACE} ${SRCS_atrace})
-#SET_TARGET_PROPERTIES(${ATRACE} PROPERTIES COMPILE_FLAGS ${EXTRA_CFLAGS_common})
-TARGET_LINK_LIBRARIES(${ATRACE} ${pkg_atrace_LDFLAGS} "-ldl")
-
-ADD_EXECUTABLE(${ATRACE_HELPER} ${SRCS_atrace_helper})
-
-CONFIGURE_FILE(${ATRACE}.pc.in ${ATRACE}.pc @ONLY)
-
-INSTALL(TARGETS ${ATRACE} DESTINATION bin)
-INSTALL(TARGETS ${ATRACE_HELPER} DESTINATION bin)
-INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${ATRACE}.pc DESTINATION ${LIBDIR}/pkgconfig)
+ADD_SUBDIRECTORY(atrace)
+ADD_SUBDIRECTORY(atrace-helper)
diff --git a/atrace-helper/CMakeLists.txt b/atrace-helper/CMakeLists.txt
new file mode 100644 (file)
index 0000000..b4ee937
--- /dev/null
@@ -0,0 +1,22 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+PROJECT(atrace-helper CXX)
+
+SET(PREFIX ${CMAKE_INSTALL_PREFIX})
+SET(EXEC_PREFIX "\${prefix}")
+
+SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CFLAGS} -std=c++11")
+SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g")
+SET(CMAKE_CXX_FLAGS_RELEASE "-O2")
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} SOURCES)
+
+SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CFLAGS} -std=c++11")
+SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g")
+SET(CMAKE_CXX_FLAGS_RELEASE "-O2")
+
+ADD_EXECUTABLE(${PROJECT_NAME} ${SOURCES})
+
+SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES VERSION ${ATRACE_HELPER_VERSION})
+
+INSTALL(TARGETS ${PROJECT_NAME} DESTINATION bin)
diff --git a/atrace-helper/LICENSE b/atrace-helper/LICENSE
new file mode 100644 (file)
index 0000000..8dc3504
--- /dev/null
@@ -0,0 +1,27 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//    * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//    * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//    * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/atrace-helper/atrace_process_dump.cc b/atrace-helper/atrace_process_dump.cc
new file mode 100644 (file)
index 0000000..bf28553
--- /dev/null
@@ -0,0 +1,248 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "atrace_process_dump.h"
+
+#include <inttypes.h>
+#include <stdint.h>
+
+#include <limits>
+
+#include "file_utils.h"
+#include "logging.h"
+#include "procfs_utils.h"
+
+namespace {
+
+const int kMemInfoIntervalMs = 100;  // 100ms-ish.
+
+}  // namespace
+
+AtraceProcessDump::AtraceProcessDump() {
+  self_pid_ = static_cast<int>(getpid());
+  dump_count_ = 0;
+  out_ = nullptr;
+  snapshot_timestamp_ = 0;
+  dump_interval_in_timer_ticks_ = 0;
+}
+
+AtraceProcessDump::~AtraceProcessDump() {
+}
+
+void AtraceProcessDump::SetDumpInterval(int interval_ms) {
+  CHECK(interval_ms >= kMemInfoIntervalMs);
+  dump_interval_in_timer_ticks_ = interval_ms / kMemInfoIntervalMs;
+  // Approximately equals to kMemInfoIntervalMs.
+  int tick_interval_ms = interval_ms / dump_interval_in_timer_ticks_;
+  snapshot_timer_ = std::unique_ptr<time_utils::PeriodicTimer>(
+      new time_utils::PeriodicTimer(tick_interval_ms));
+}
+
+void AtraceProcessDump::RunAndPrintJson(FILE* stream) {
+  out_ = stream;
+
+  fprintf(out_, "{\"start_ts\": \"%" PRIu64 "\", \"snapshots\":[\n",
+      time_utils::GetTimestamp());
+
+  CHECK(snapshot_timer_);
+  snapshot_timer_->Start();
+
+  int tick_count = std::numeric_limits<int>::max();
+  if (dump_count_ > 0)
+    tick_count = dump_count_ * dump_interval_in_timer_ticks_;
+
+  for (int tick = 0; tick < tick_count; tick++) {
+    if (tick > 0) {
+      if (!snapshot_timer_->Wait())
+        break;  // Interrupted by signal.
+      fprintf(out_, ",\n");
+    }
+    TakeAndSerializeMemInfo();
+    if (!(tick % dump_interval_in_timer_ticks_)) {
+      fprintf(out_, ",\n");
+      TakeGlobalSnapshot();
+      SerializeSnapshot();
+    }
+    fflush(out_);
+  }
+
+  fprintf(out_, "],\n");
+  SerializePersistentProcessInfo();
+  fprintf(out_, "}\n");
+  fflush(out_);
+  Cleanup();
+}
+
+void AtraceProcessDump::Stop() {
+  CHECK(snapshot_timer_);
+  snapshot_timer_->Stop();
+}
+
+void AtraceProcessDump::TakeGlobalSnapshot() {
+  snapshot_.clear();
+  snapshot_timestamp_ = time_utils::GetTimestamp();
+
+  file_utils::ForEachPidInProcPath("/proc", [this](int pid) {
+    // Skip if not regognized as a process.
+    if (!UpdatePersistentProcessInfo(pid))
+      return;
+    const ProcessInfo* process = processes_[pid].get();
+    // Snapshot can't be obtained for kernel workers.
+    if (process->in_kernel)
+      return;
+
+    ProcessSnapshot* process_snapshot = new ProcessSnapshot();
+    snapshot_[pid] = std::unique_ptr<ProcessSnapshot>(process_snapshot);
+
+    process_snapshot->pid = pid;
+    procfs_utils::ReadOomStats(process_snapshot);
+    procfs_utils::ReadPageFaultsAndCpuTimeStats(process_snapshot);
+
+    if (ShouldTakeFullDump(process)) {
+      process_snapshot->memory.ReadFullStats(pid);
+    } else {
+      process_snapshot->memory.ReadLightStats(pid);
+    }
+  });
+}
+
+bool AtraceProcessDump::UpdatePersistentProcessInfo(int pid) {
+  if (!processes_.count(pid)) {
+    if (procfs_utils::ReadTgid(pid) != pid)
+      return false;
+    processes_[pid] = procfs_utils::ReadProcessInfo(pid);
+  }
+  ProcessInfo* process = processes_[pid].get();
+  procfs_utils::ReadProcessThreads(process);
+
+  if (full_dump_mode_ == FullDumpMode::kOnlyWhitelisted &&
+      full_dump_whitelist_.count(process->name)) {
+    full_dump_whitelisted_pids_.insert(pid);
+  }
+  return true;
+}
+
+bool AtraceProcessDump::ShouldTakeFullDump(const ProcessInfo* process) {
+  if (full_dump_mode_ == FullDumpMode::kAllProcesses)
+    return !process->in_kernel && (process->pid != self_pid_);
+  if (full_dump_mode_ == FullDumpMode::kAllJavaApps)
+    return process->is_app;
+  if (full_dump_mode_ == FullDumpMode::kDisabled)
+    return false;
+  return full_dump_whitelisted_pids_.count(process->pid) > 0;
+}
+
+void AtraceProcessDump::SerializeSnapshot() {
+  fprintf(out_, "{\"ts\":\"%" PRIu64 "\",\"memdump\":{\n",
+          snapshot_timestamp_);
+  for (auto it = snapshot_.begin(); it != snapshot_.end();) {
+    const ProcessSnapshot* process = it->second.get();
+    const ProcessMemoryStats* mem = &process->memory;
+    fprintf(out_, "\"%d\":{", process->pid);
+
+    fprintf(out_, "\"vm\":%" PRIu64 ",\"rss\":%" PRIu64,
+            mem->virt_kb(), mem->rss_kb());
+
+    fprintf(out_, ",\"oom_sc\":%d,\"oom_sc_adj\":%d"
+                  ",\"min_flt\":%lu,\"maj_flt\":%lu"
+                  ",\"utime\":%lu,\"stime\":%lu",
+            process->oom_score, process->oom_score_adj,
+            process->minor_faults, process->major_faults,
+            process->utime, process->stime);
+
+    if (mem->full_stats_available()) {
+      fprintf(out_, ",\"pss\":%" PRIu64 ",\"swp\":%" PRIu64
+                    ",\"pc\":%" PRIu64 ",\"pd\":%" PRIu64
+                    ",\"sc\":%" PRIu64 ",\"sd\":%" PRIu64,
+              mem->pss_kb(), mem->swapped_kb(),
+              mem->private_clean_kb(), mem->private_dirty_kb(),
+              mem->shared_clean_kb(), mem->shared_dirty_kb());
+    }
+
+    // Memory maps are too heavy to serialize. Enable only in whitelisting mode.
+    if (print_smaps_ &&
+        full_dump_mode_ == FullDumpMode::kOnlyWhitelisted &&
+        mem->full_stats_available() &&
+        full_dump_whitelisted_pids_.count(process->pid)) {
+
+      fprintf(out_, ", \"mmaps\":[");
+      size_t n_mmaps = mem->mmaps_count();
+      for (size_t k = 0; k < n_mmaps; ++k) {
+        const ProcessMemoryStats::MmapInfo* mm = mem->mmap(k);
+        fprintf(out_,
+                "{\"vm\":\"%" PRIx64 "-%" PRIx64 "\","
+                "\"file\":\"%s\",\"flags\":\"%s\","
+                "\"pss\":%" PRIu64 ",\"rss\":%" PRIu64 ",\"swp\":%" PRIu64 ","
+                "\"pc\":%" PRIu64 ",\"pd\":%" PRIu64 ","
+                "\"sc\":%" PRIu64 ",\"sd\":%" PRIu64 "}",
+                mm->start_addr, mm->end_addr,
+                mm->mapped_file, mm->prot_flags,
+                mm->pss_kb, mm->rss_kb, mm->swapped_kb,
+                mm->private_clean_kb, mm->private_dirty_kb,
+                mm->shared_clean_kb, mm->shared_dirty_kb);
+        if (k < n_mmaps - 1)
+          fprintf(out_, ", ");
+      }
+      fprintf(out_, "]");
+    }
+
+    if (++it != snapshot_.end())
+      fprintf(out_, "},\n");
+    else
+      fprintf(out_, "}}\n");
+  }
+  fprintf(out_, "}");
+}
+
+void AtraceProcessDump::SerializePersistentProcessInfo() {
+  fprintf(out_, "\"processes\":{");
+  for (auto it = processes_.begin(); it != processes_.end();) {
+    const ProcessInfo* process = it->second.get();
+    fprintf(out_, "\"%d\":{", process->pid);
+    fprintf(out_, "\"name\":\"%s\"", process->name);
+
+    if (!process->in_kernel) {
+      fprintf(out_, ",\"exe\":\"%s\",", process->exe);
+      fprintf(out_, "\"threads\":{\n");
+      const auto threads = &process->threads;
+      for (auto thread_it = threads->begin(); thread_it != threads->end();) {
+        const ThreadInfo* thread = &(thread_it->second);
+        fprintf(out_, "\"%d\":{", thread->tid);
+        fprintf(out_, "\"name\":\"%s\"", thread->name);
+
+        if (++thread_it != threads->end())
+          fprintf(out_, "},\n");
+        else
+          fprintf(out_, "}\n");
+      }
+      fprintf(out_, "}");
+    }
+
+    if (++it != processes_.end())
+      fprintf(out_, "},\n");
+    else
+      fprintf(out_, "}\n");
+  }
+  fprintf(out_, "}");
+}
+
+void AtraceProcessDump::TakeAndSerializeMemInfo() {
+  std::map<std::string, uint64_t> mem_info;
+  CHECK(procfs_utils::ReadMemInfoStats(&mem_info));
+  fprintf(out_, "{\"ts\":\"%" PRIu64 "\",\"meminfo\":{\n",
+          time_utils::GetTimestamp());
+  for (auto it = mem_info.begin(); it != mem_info.end(); ++it) {
+    if (it != mem_info.begin())
+      fprintf(out_, ",");
+    fprintf(out_, "\"%s\":%" PRIu64, it->first.c_str(), it->second);
+  }
+  fprintf(out_, "}}");
+}
+
+void AtraceProcessDump::Cleanup() {
+  processes_.clear();
+  snapshot_.clear();
+  full_dump_whitelisted_pids_.clear();
+  snapshot_timer_ = nullptr;
+}
diff --git a/atrace-helper/atrace_process_dump.h b/atrace-helper/atrace_process_dump.h
new file mode 100644 (file)
index 0000000..280a18a
--- /dev/null
@@ -0,0 +1,81 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ATRACE_PROCESS_DUMP_H_
+#define ATRACE_PROCESS_DUMP_H_
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <memory>
+#include <set>
+#include <string>
+
+#include "logging.h"
+#include "process_info.h"
+#include "time_utils.h"
+
+// Program that collects processes, thread names, per-process memory stats and
+// other minor metrics from /proc filesystem. It's aimed to extend systrace
+// with more actionable number to hit performance issues.
+class AtraceProcessDump {
+ public:
+  enum FullDumpMode {
+    kDisabled,
+    kAllProcesses,
+    kAllJavaApps,
+    kOnlyWhitelisted,
+  };
+
+  AtraceProcessDump();
+  ~AtraceProcessDump();
+
+  void RunAndPrintJson(FILE* stream);
+  void Stop();
+
+  void SetDumpInterval(int interval_ms);
+
+  // Negative number or zero means unlimited number of dumps.
+  void set_dump_count(int count) { dump_count_ = count; }
+
+  void set_full_dump_mode(FullDumpMode mode) { full_dump_mode_ = mode; }
+  void set_full_dump_whitelist(const std::set<std::string> &whitelist) {
+    CHECK(full_dump_mode_ == FullDumpMode::kOnlyWhitelisted);
+    full_dump_whitelist_ = whitelist;
+  }
+  void enable_print_smaps() { print_smaps_ = true; }
+
+ private:
+  AtraceProcessDump(const AtraceProcessDump&) = delete;
+  void operator=(const AtraceProcessDump&) = delete;
+
+  using ProcessMap = std::map<int, std::unique_ptr<ProcessInfo>>;
+  using ProcessSnapshotMap = std::map<int, std::unique_ptr<ProcessSnapshot>>;
+
+  void TakeGlobalSnapshot();
+  void TakeAndSerializeMemInfo();
+  bool UpdatePersistentProcessInfo(int pid);
+  bool ShouldTakeFullDump(const ProcessInfo* process);
+  void SerializeSnapshot();
+  void SerializePersistentProcessInfo();
+  void Cleanup();
+
+  int self_pid_;
+  int dump_count_;
+  bool graphics_stats_ = false;
+  bool print_smaps_ = false;
+  FullDumpMode full_dump_mode_ = FullDumpMode::kDisabled;
+  std::set<std::string> full_dump_whitelist_;
+
+  FILE* out_;
+  ProcessMap processes_;
+  ProcessSnapshotMap snapshot_;
+  uint64_t snapshot_timestamp_;
+  std::set<int> full_dump_whitelisted_pids_;
+  std::unique_ptr<time_utils::PeriodicTimer> snapshot_timer_;
+  int dump_interval_in_timer_ticks_;
+};
+
+#endif  // ATRACE_PROCESS_DUMP_H_
diff --git a/atrace-helper/file_utils.cc b/atrace-helper/file_utils.cc
new file mode 100644 (file)
index 0000000..7d122d6
--- /dev/null
@@ -0,0 +1,117 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "file_utils.h"
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+namespace {
+
+bool IsNumeric(const char* str) {
+  if (!str[0])
+    return false;
+  for (const char* c = str; *c; c++) {
+    if (!isdigit(*c))
+      return false;
+  }
+  return true;
+}
+
+}  // namespace
+
+namespace file_utils {
+
+void ForEachPidInProcPath(const char* proc_path,
+                          std::function<void(int)> predicate) {
+  DIR* root_dir = opendir(proc_path);
+  ScopedDir autoclose(root_dir);
+  struct dirent* child_dir;
+  while ((child_dir = readdir(root_dir))) {
+    if (child_dir->d_type != DT_DIR || !IsNumeric(child_dir->d_name))
+      continue;
+    predicate(atoi(child_dir->d_name));
+  }
+}
+
+ssize_t ReadFile(const char* path, char* buf, size_t length) {
+  buf[0] = '\0';
+  int fd = open(path, O_RDONLY);
+  if (fd < 0 && errno == ENOENT)
+    return -1;
+  ScopedFD autoclose(fd);
+  size_t tot_read = 0;
+  do {
+    ssize_t rsize = read(fd, buf + tot_read, length - tot_read);
+    if (rsize == 0)
+      break;
+    if (rsize == -1 && errno == EINTR)
+      continue;
+    else if (rsize < 0)
+      return -1;
+    tot_read += static_cast<size_t>(rsize);
+  } while (tot_read < length);
+  buf[tot_read < length ? tot_read : length - 1] = '\0';
+  return tot_read;
+}
+
+bool ReadFileTrimmed(const char* path, char* buf, size_t length) {
+  ssize_t rsize = ReadFile(path, buf, length);
+  if (rsize < 0)
+    return false;
+  for (ssize_t i = 0; i < rsize; i++) {
+    const char c = buf[i];
+    if (c == '\0' || c == '\r' || c == '\n') {
+      buf[i] = '\0';
+      break;
+    }
+    buf[i] = isprint(c) ? c : '?';
+  }
+  return true;
+}
+
+ssize_t ReadProcFile(int pid, const char* proc_file, char* buf, size_t length) {
+  char proc_path[128];
+  snprintf(proc_path, sizeof(proc_path), "/proc/%d/%s", pid, proc_file);
+  return ReadFile(proc_path, buf, length);
+}
+
+// Reads a single-line proc file, stripping out any \0, \r, \n and replacing
+// non-printable charcters with '?'.
+bool ReadProcFileTrimmed(int pid,
+                         const char* proc_file,
+                         char* buf,
+                         size_t length) {
+  char proc_path[128];
+  snprintf(proc_path, sizeof(proc_path), "/proc/%d/%s", pid, proc_file);
+  return ReadFileTrimmed(proc_path, buf, length);
+}
+
+LineReader::LineReader(char* buf, size_t size)
+    : ptr_(buf), end_(buf + size) {
+}
+
+LineReader::~LineReader() {
+}
+
+const char* LineReader::NextLine() {
+  if (ptr_ >= end_)
+    return nullptr;
+  const char* cur = ptr_;
+  char* next = strchr(ptr_, '\n');
+  if (next) {
+    *next = '\0';
+    ptr_ = next + 1;
+  } else {
+    ptr_ = end_;
+  }
+  return cur;
+}
+
+}  // namespace file_utils
diff --git a/atrace-helper/file_utils.h b/atrace-helper/file_utils.h
new file mode 100644 (file)
index 0000000..2b2556b
--- /dev/null
@@ -0,0 +1,67 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef FILE_UTILS_H_
+#define FILE_UTILS_H_
+
+#include <dirent.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <functional>
+#include <map>
+#include <memory>
+
+#include "logging.h"
+
+namespace file_utils {
+
+// RAII classes for auto-releasing fd/dirs.
+template <typename RESOURCE_TYPE, int (*CLOSE_FN)(RESOURCE_TYPE)>
+struct ScopedResource {
+  explicit ScopedResource(RESOURCE_TYPE r) : r_(r) { CHECK(r); }
+  ~ScopedResource() { CLOSE_FN(r_); }
+  RESOURCE_TYPE r_;
+};
+
+using ScopedFD = ScopedResource<int, close>;
+using ScopedDir = ScopedResource<DIR*, closedir>;
+
+// Invokes predicate(pid) for each folder in |proc_path|/[0-9]+ which has
+// a numeric name (typically pids and tids).
+void ForEachPidInProcPath(const char* proc_path,
+                          std::function<void(int)> predicate);
+
+// Reads the contents of |path| fully into |buf| up to |length| chars.
+// |buf| is guaranteed to be null terminated.
+ssize_t ReadFile(const char* path, char* buf, size_t length);
+
+// Reads a single-line file, stripping out any \0, \r, \n and replacing
+// non-printable charcters with '?'. |buf| is guaranteed to be null terminated.
+bool ReadFileTrimmed(const char* path, char* buf, size_t length);
+
+// Convenience wrappers for /proc/|pid|/|proc_file| paths.
+ssize_t ReadProcFile(int pid, const char* proc_file, char* buf, size_t length);
+bool ReadProcFileTrimmed(int pid,
+                         const char* proc_file,
+                         char* buf,
+                         size_t length);
+
+// Takes a C string buffer and chunks it into lines without creating any
+// copies. It modifies the original buffer, by replacing \n with \0.
+class LineReader {
+ public:
+  LineReader(char* buf, size_t size);
+  ~LineReader();
+
+  const char* NextLine();
+
+ private:
+  char* ptr_;
+  char* end_;
+};
+
+}  // namespace file_utils
+
+#endif  // FILE_UTILS_H_
diff --git a/atrace-helper/logging.h b/atrace-helper/logging.h
new file mode 100644 (file)
index 0000000..ecbb56b
--- /dev/null
@@ -0,0 +1,32 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef LOGGING_H_
+#define LOGGING_H_
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define CHECK_ARGS(COND, ERR)                                          \
+  "FAILED CHECK(%s) @ %s:%d (errno: %s)\n", #COND, __FILE__, __LINE__, \
+      strerror(ERR)
+
+#define CHECK(x)                                              \
+  do {                                                        \
+    if (!(x)) {                                               \
+      const int e = errno;                                    \
+      fprintf(stderr, "\n" CHECK_ARGS(x, e));                 \
+      fflush(stderr);                                         \
+      abort();                                                \
+    }                                                         \
+  } while (0)
+
+inline void LogError(const char* message) {
+  fprintf(stderr, "\n%s\n", message);
+  fflush(stderr);
+}
+
+#endif  // LOGGING_H_
diff --git a/atrace-helper/main.cc b/atrace-helper/main.cc
new file mode 100644 (file)
index 0000000..6079c00
--- /dev/null
@@ -0,0 +1,134 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <inttypes.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <memory>
+#include <set>
+#include <string>
+#include <sstream>
+
+#include "atrace_process_dump.h"
+#include "logging.h"
+
+#define PATH_MAX 256
+
+namespace {
+
+std::unique_ptr<AtraceProcessDump> g_prog;
+
+void ParseFullDumpConfig(const std::string& config, AtraceProcessDump* prog) {
+  using FullDumpMode = AtraceProcessDump::FullDumpMode;
+  if (config == "all") {
+    prog->set_full_dump_mode(FullDumpMode::kAllProcesses);
+  } else if (config == "apps") {
+    prog->set_full_dump_mode(FullDumpMode::kAllJavaApps);
+  } else {
+    std::set<std::string> whitelist;
+    std::istringstream ss(config);
+    std::string entry;
+    while (std::getline(ss, entry, ',')) {
+      whitelist.insert(entry);
+    }
+    if (whitelist.empty())
+      return;
+    prog->set_full_dump_mode(FullDumpMode::kOnlyWhitelisted);
+    prog->set_full_dump_whitelist(whitelist);
+  }
+}
+
+}  // namespace
+
+int main(int argc, char** argv) {
+  if (argc == 2 && !strcmp(argv[1], "--echo-ts")) {
+    // Used by clock sync marker to correct the difference between
+    // Linux monotonic clocks on the device and host.
+    printf("%" PRIu64 "\n", time_utils::GetTimestamp());
+    return 0;
+  }
+
+  bool background = false;
+  int dump_interval_ms = 5000;
+  char out_file[PATH_MAX] = {};
+  bool dump_to_file = false;
+  int count = -1;
+
+  AtraceProcessDump* prog = new AtraceProcessDump();
+  g_prog = std::unique_ptr<AtraceProcessDump>(prog);
+
+  if (geteuid()) {
+    fprintf(stderr, "Must run as root\n");
+    exit(EXIT_FAILURE);
+  }
+
+  int opt;
+  while ((opt = getopt(argc, argv, "bm:st:o:c:")) != -1) {
+    switch (opt) {
+      case 'b':
+        background = true;
+        break;
+      case 'm':
+        ParseFullDumpConfig(optarg, prog);
+        break;
+      case 's':
+        prog->enable_print_smaps();
+        break;
+      case 't':
+        dump_interval_ms = atoi(optarg);
+        CHECK(dump_interval_ms > 0);
+        break;
+      case 'c':
+        count = atoi(optarg);
+        CHECK(count > 0);
+        break;
+      case 'o':
+        strncpy(out_file, optarg, sizeof(out_file));
+        out_file[PATH_MAX - 1] = '\0';
+        dump_to_file = true;
+        break;
+      default:
+        fprintf(stderr,
+                "Usage: %s [-b] [-m full_dump_filter] [-s] "
+                "[-t dump_interval_ms] "
+                "[-c dumps_count] [-o out.json]\n",
+                argv[0]);
+        exit(EXIT_FAILURE);
+    }
+  }
+
+  prog->set_dump_count(count);
+  prog->SetDumpInterval(dump_interval_ms);
+
+  FILE* out_stream = stdout;
+  char tmp_file[PATH_MAX + 4];
+  if (dump_to_file) {
+    unlink(out_file);
+    snprintf(tmp_file, PATH_MAX + 4, "%s.tmp", out_file);
+    out_stream = fopen(tmp_file, "w");
+    CHECK(out_stream);
+  }
+
+  if (background) {
+    if (!dump_to_file) {
+      fprintf(stderr, "-b requires -o for output dump path.\n");
+      exit(EXIT_FAILURE);
+    }
+    printf("Continuing in background. kill -TERM to terminate the daemon.\n");
+    CHECK(daemon(0 /* nochdir */, 0 /* noclose */) == 0);
+  }
+
+  auto on_exit = [](int) { g_prog->Stop(); };
+  signal(SIGINT, on_exit);
+  signal(SIGTERM, on_exit);
+
+  prog->RunAndPrintJson(out_stream);
+  fclose(out_stream);
+
+  if (dump_to_file)
+    rename(tmp_file, out_file);
+}
diff --git a/atrace-helper/process_info.h b/atrace-helper/process_info.h
new file mode 100644 (file)
index 0000000..089e77e
--- /dev/null
@@ -0,0 +1,40 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PROCESS_INFO_H_
+#define PROCESS_INFO_H_
+
+#include <map>
+
+#include "process_memory_stats.h"
+
+struct ThreadInfo {
+  int tid;
+  char name[16];
+};
+
+struct ProcessInfo {
+  int pid;
+  bool in_kernel;
+  bool is_app;
+  char name[256];
+  char exe[256];
+  std::map<int, ThreadInfo> threads;
+};
+
+struct ProcessSnapshot {
+  int pid;
+  ProcessMemoryStats memory;
+  // OOM badness and tolerance (oom_adj is deprecated).
+  int oom_score;
+  int oom_score_adj;
+  // Page faults.
+  unsigned long minor_faults;
+  unsigned long major_faults;
+  // Time spent in userspace and in the kernel.
+  unsigned long utime;
+  unsigned long stime;
+};
+
+#endif  // PROCESS_INFO_H_
diff --git a/atrace-helper/process_memory_stats.cc b/atrace-helper/process_memory_stats.cc
new file mode 100644 (file)
index 0000000..bcc0678
--- /dev/null
@@ -0,0 +1,124 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "process_memory_stats.h"
+
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <memory>
+
+#include "file_utils.h"
+#include "logging.h"
+
+namespace {
+
+const int kKbPerPage = 4;
+
+const char kRss[] = "Rss";
+const char kPss[] = "Pss";
+const char kSwap[] = "Swap";
+const char kSharedClean[] = "Shared_Clean";
+const char kSharedDirty[] = "Shared_Dirty";
+const char kPrivateClean[] = "Private_Clean";
+const char kPrivateDirty[] = "Private_Dirty";
+
+bool ReadSmapsMetric(
+    const char* line, const char* metric, int metric_size, uint64_t* res) {
+  if (strncmp(line, metric, metric_size - 1))
+    return false;
+  if (line[metric_size - 1] != ':')
+    return false;
+  *res = strtoull(line + metric_size, nullptr, 10);
+  return true;
+}
+
+}  // namespace
+
+bool ProcessMemoryStats::ReadLightStats(int pid) {
+  char buf[64];
+  if (file_utils::ReadProcFile(pid, "statm", buf, sizeof(buf)) <= 0)
+    return false;
+  uint32_t vm_size_pages;
+  uint32_t rss_pages;
+  int res = sscanf(buf, "%u %u", &vm_size_pages, &rss_pages);
+  CHECK(res == 2);
+  rss_kb_ = (uint64_t)rss_pages * kKbPerPage;
+  virt_kb_ = (uint64_t)vm_size_pages * kKbPerPage;
+  return true;
+}
+
+bool ProcessMemoryStats::ReadFullStats(int pid) {
+  const size_t kBufSize = 8u * 1024 * 1024;
+  std::unique_ptr<char[]> buf(new char[kBufSize]);
+  ssize_t rsize = file_utils::ReadProcFile(pid, "smaps", &buf[0], kBufSize);
+  if (rsize <= 0)
+    return false;
+  MmapInfo* last_mmap_entry = nullptr;
+  std::unique_ptr<MmapInfo> new_mmap(new MmapInfo());
+  CHECK(mmaps_.empty());
+  CHECK(rss_kb_ == 0);
+
+  // Iterate over all lines in /proc/PID/smaps.
+  file_utils::LineReader rd(&buf[0], rsize);
+  for (const char* line = rd.NextLine(); line; line = rd.NextLine()) {
+    if (!line[0])
+      continue;
+    // Performance optimization (hack).
+    // Any header line starts with lowercase hex digit but subsequent lines
+    // start with uppercase letter.
+    if (line[0] < 'A' || line[0] > 'Z') {
+      // Note that the mapped file name ([stack]) is optional and won't be
+      // present on anonymous memory maps (hence res >= 3 below).
+      int res = sscanf(line,
+          "%" PRIx64 "-%" PRIx64 " %4s %*x %*[:0-9a-f] "
+          "%*[0-9a-f]%*[ \t]%127[^\n]",
+          &new_mmap->start_addr, &new_mmap->end_addr, new_mmap->prot_flags,
+          new_mmap->mapped_file);
+      last_mmap_entry = new_mmap.get();
+      CHECK(new_mmap->end_addr >= new_mmap->start_addr);
+      new_mmap->virt_kb =
+          (new_mmap->end_addr - new_mmap->start_addr) / 1024;
+      if (res == 3)
+        new_mmap->mapped_file[0] = '\0';
+      virt_kb_ += new_mmap->virt_kb;
+      mmaps_.push_back(std::move(new_mmap));
+      new_mmap.reset(new MmapInfo());
+    } else {
+      // The current line is a metrics line within a mmap entry, e.g.:
+      // Size:   4 kB
+      uint64_t size = 0;
+      CHECK(last_mmap_entry);
+      if (ReadSmapsMetric(line, kRss, sizeof(kRss), &size)) {
+        last_mmap_entry->rss_kb = size;
+        rss_kb_ += size;
+      } else if (ReadSmapsMetric(line, kPss, sizeof(kPss), &size)) {
+        last_mmap_entry->pss_kb = size;
+        pss_kb_ += size;
+      } else if (ReadSmapsMetric(line, kSwap, sizeof(kSwap), &size)) {
+        last_mmap_entry->swapped_kb = size;
+        swapped_kb_ += size;
+      } else if (ReadSmapsMetric(
+                     line, kSharedClean, sizeof(kSharedClean), &size)) {
+        last_mmap_entry->shared_clean_kb = size;
+        shared_clean_kb_ += size;
+      } else if (ReadSmapsMetric(
+                     line, kSharedDirty, sizeof(kSharedDirty), &size)) {
+        last_mmap_entry->shared_dirty_kb = size;
+        shared_dirty_kb_ += size;
+      } else if (ReadSmapsMetric(
+                     line, kPrivateClean, sizeof(kPrivateClean), &size)) {
+        last_mmap_entry->private_clean_kb = size;
+        private_clean_kb_ += size;
+      } else if (ReadSmapsMetric(
+                     line, kPrivateDirty, sizeof(kPrivateDirty), &size)) {
+        last_mmap_entry->private_dirty_kb = size;
+        private_dirty_kb_ += size;
+      }
+    }
+  }
+  full_stats_ = true;
+  return true;
+}
diff --git a/atrace-helper/process_memory_stats.h b/atrace-helper/process_memory_stats.h
new file mode 100644 (file)
index 0000000..cb72c9c
--- /dev/null
@@ -0,0 +1,72 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PROCESS_MEMORY_STATS_H_
+#define PROCESS_MEMORY_STATS_H_
+
+#include <stdint.h>
+
+#include <memory>
+#include <vector>
+
+// Reads process memory stats from /proc/pid/{statm,smaps}.
+class ProcessMemoryStats {
+ public:
+  struct MmapInfo {
+    char mapped_file[128] = {};
+    char prot_flags[5] = {};
+    uint64_t start_addr = 0;
+    uint64_t end_addr = 0;
+    uint64_t virt_kb = 0;
+    uint64_t pss_kb = 0;  // Proportional Set Size.
+    uint64_t rss_kb = 0;  // Resident Set Size.
+    uint64_t private_clean_kb = 0;
+    uint64_t private_dirty_kb = 0;
+    uint64_t shared_clean_kb = 0;
+    uint64_t shared_dirty_kb = 0;
+    uint64_t swapped_kb = 0;
+  };
+
+  ProcessMemoryStats() {}
+
+  bool ReadLightStats(int pid);
+  bool ReadFullStats(int pid);
+
+  // Available after ReadLightStats().
+  uint64_t virt_kb() const { return virt_kb_; }
+  uint64_t rss_kb() const { return rss_kb_; }
+
+  // Available after ReadFullStats().
+  bool full_stats_available() const { return full_stats_; }
+  uint64_t pss_kb() const { return pss_kb_; }
+  uint64_t private_clean_kb() const { return private_clean_kb_; }
+  uint64_t private_dirty_kb() const { return private_dirty_kb_; }
+  uint64_t shared_clean_kb() const { return shared_clean_kb_; }
+  uint64_t shared_dirty_kb() const { return shared_dirty_kb_; }
+  uint64_t swapped_kb() const { return swapped_kb_; }
+
+  size_t mmaps_count() const { return mmaps_.size(); }
+  const MmapInfo* mmap(size_t index) const { return mmaps_[index].get(); }
+
+ private:
+  ProcessMemoryStats(const ProcessMemoryStats&) = delete;
+  void operator=(const ProcessMemoryStats&) = delete;
+
+  // Light stats.
+  uint64_t virt_kb_ = 0;
+  uint64_t rss_kb_ = 0;
+
+  // Full stats.
+  bool full_stats_ = false;
+  uint64_t pss_kb_ = 0;
+  uint64_t private_clean_kb_ = 0;
+  uint64_t private_dirty_kb_ = 0;
+  uint64_t shared_clean_kb_ = 0;
+  uint64_t shared_dirty_kb_ = 0;
+  uint64_t swapped_kb_ = 0;
+
+  std::vector<std::unique_ptr<const MmapInfo>> mmaps_;
+};
+
+#endif  // PROCESS_MEMORY_STATS_H_
diff --git a/atrace-helper/procfs_utils.cc b/atrace-helper/procfs_utils.cc
new file mode 100644 (file)
index 0000000..5726a24
--- /dev/null
@@ -0,0 +1,137 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "procfs_utils.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#include "file_utils.h"
+#include "logging.h"
+
+using file_utils::ForEachPidInProcPath;
+using file_utils::ReadProcFile;
+using file_utils::ReadProcFileTrimmed;
+
+namespace procfs_utils {
+
+namespace {
+
+const char kJavaAppPrefix[] = "/system/bin/app_process";
+const char kZygotePrefix[] = "zygote";
+
+inline void ReadProcString(int pid, const char* path, char* buf, size_t size) {
+  if (!file_utils::ReadProcFileTrimmed(pid, path, buf, size))
+    buf[0] = '\0';
+}
+
+inline void ReadExePath(int pid, char* buf, size_t size) {
+  char exe_path[64];
+  snprintf(exe_path, sizeof(exe_path), "/proc/%d/exe", pid);
+  ssize_t res = readlink(exe_path, buf, size - 1);
+  if (res >= 0)
+    buf[res] = '\0';
+  else
+    buf[0] = '\0';
+}
+
+inline bool IsApp(const char* name, const char* exe) {
+  return strncmp(exe, kJavaAppPrefix, sizeof(kJavaAppPrefix) - 1) == 0 &&
+         strncmp(name, kZygotePrefix, sizeof(kZygotePrefix) - 1) != 0;
+}
+
+}  // namespace
+
+int ReadTgid(int pid) {
+  static const char kTgid[] = "\nTgid:";
+  char buf[512];
+  ssize_t rsize = ReadProcFile(pid, "status", buf, sizeof(buf));
+  if (rsize <= 0)
+    return -1;
+  const char* tgid_line = strstr(buf, kTgid);
+  CHECK(tgid_line);
+  return atoi(tgid_line + sizeof(kTgid) - 1);
+}
+
+std::unique_ptr<ProcessInfo> ReadProcessInfo(int pid) {
+  ProcessInfo* process = new ProcessInfo();
+  process->pid = pid;
+  ReadProcString(pid, "cmdline", process->name, sizeof(process->name));
+  if (process->name[0] != 0) {
+    ReadExePath(pid, process->exe, sizeof(process->exe));
+    process->is_app = IsApp(process->name, process->exe);
+  } else {
+    ReadProcString(pid, "comm", process->name, sizeof(process->name));
+    CHECK(process->name[0]);
+    process->in_kernel = true;
+  }
+  return std::unique_ptr<ProcessInfo>(process);
+}
+
+void ReadProcessThreads(ProcessInfo* process) {
+  if (process->in_kernel)
+    return;
+
+  char tasks_path[64];
+  snprintf(tasks_path, sizeof(tasks_path), "/proc/%d/task", process->pid);
+  ForEachPidInProcPath(tasks_path, [process](int tid) {
+    if (process->threads.count(tid))
+      return;
+    ThreadInfo thread = { tid, "" };
+    char task_comm[64];
+    snprintf(task_comm, sizeof(task_comm), "task/%d/comm", tid);
+    ReadProcString(process->pid, task_comm, thread.name, sizeof(thread.name));
+    if (thread.name[0] == '\0' && process->is_app)
+      strcpy(thread.name, "UI Thread");
+    process->threads[tid] = thread;
+  });
+}
+
+bool ReadOomStats(ProcessSnapshot* snapshot) {
+  char buf[64];
+  if (ReadProcFileTrimmed(snapshot->pid, "oom_score", buf, sizeof(buf)))
+    snapshot->oom_score = atoi(buf);
+  else
+    return false;
+  if (ReadProcFileTrimmed(snapshot->pid, "oom_score_adj", buf, sizeof(buf)))
+    snapshot->oom_score_adj = atoi(buf);
+  else
+    return false;
+  return true;
+}
+
+bool ReadPageFaultsAndCpuTimeStats(ProcessSnapshot* snapshot) {
+  char buf[512];
+  if (!ReadProcFileTrimmed(snapshot->pid, "stat", buf, sizeof(buf)))
+    return false;
+  int ret = sscanf(buf,
+      "%*d %*s %*c %*d %*d %*d %*d %*d %*u %lu %*u %lu %*u %lu %lu",
+      &snapshot->minor_faults, &snapshot->major_faults,
+      &snapshot->utime, &snapshot->stime);
+  printf("ret is %d[%s]\n", ret, buf);
+  CHECK(ret == 4);
+  return true;
+}
+
+bool ReadMemInfoStats(std::map<std::string, uint64_t>* mem_info) {
+  char buf[1024];
+  ssize_t rsize = file_utils::ReadFile("/proc/meminfo", buf, sizeof(buf));
+  if (rsize <= 0)
+    return false;
+
+  file_utils::LineReader reader(buf, rsize);
+  for (const char* line = reader.NextLine();
+       line && line[0];
+       line = reader.NextLine()) {
+
+    const char* pos_colon = strstr(line, ":");
+    if (pos_colon == nullptr)
+      continue;  // Should not happen.
+    std::string name(line, pos_colon - line);
+    (*mem_info)[name] = strtoull(&pos_colon[1], nullptr, 10);
+  }
+  return true;
+}
+
+}  // namespace procfs_utils
diff --git a/atrace-helper/procfs_utils.h b/atrace-helper/procfs_utils.h
new file mode 100644 (file)
index 0000000..e5ce704
--- /dev/null
@@ -0,0 +1,30 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PROCFS_UTILS_H_
+#define PROCFS_UTILS_H_
+
+#include <map>
+#include <memory>
+#include <string>
+
+#include "process_info.h"
+
+namespace procfs_utils {
+
+// ProcFS doesn't necessarly distinguish PID vs. TID, but all threads of a
+// process have the same Thread Group ID which is equal to Process ID.
+int ReadTgid(int pid);
+
+std::unique_ptr<ProcessInfo> ReadProcessInfo(int pid);
+void ReadProcessThreads(ProcessInfo* process);
+
+bool ReadOomStats(ProcessSnapshot* snapshot);
+bool ReadPageFaultsAndCpuTimeStats(ProcessSnapshot* snapshot);
+
+bool ReadMemInfoStats(std::map<std::string, uint64_t>* mem_info);
+
+}  // namespace procfs_utils
+
+#endif  // PROCFS_UTILS_H_
diff --git a/atrace-helper/time_utils.cc b/atrace-helper/time_utils.cc
new file mode 100644 (file)
index 0000000..afcc2fc
--- /dev/null
@@ -0,0 +1,62 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "time_utils.h"
+
+#include <sys/time.h>
+#include <sys/timerfd.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "logging.h"
+
+namespace time_utils {
+
+uint64_t GetTimestamp() {
+  struct timespec ts = {};
+  CHECK(clock_gettime(CLOCK_MONOTONIC_COARSE, &ts) == 0);
+  return ((uint64_t)ts.tv_sec * 1000) + ((uint64_t)ts.tv_nsec / 1000000ul);
+}
+
+PeriodicTimer::PeriodicTimer(int interval_ms) : interval_ms_(interval_ms) {
+  timer_fd_ = -1;
+}
+
+PeriodicTimer::~PeriodicTimer() {
+  Stop();
+}
+
+void PeriodicTimer::Start() {
+  Stop();
+  timer_fd_ = timerfd_create(CLOCK_MONOTONIC, 0);
+  CHECK(timer_fd_ >= 0);
+  int sec = interval_ms_ / 1000;
+  int nsec = (interval_ms_ % 1000) * 1000000;
+  struct itimerspec ts = {};
+  ts.it_value.tv_nsec = nsec;
+  ts.it_value.tv_sec = sec;
+  ts.it_interval.tv_nsec = nsec;
+  ts.it_interval.tv_sec = sec;
+  CHECK(timerfd_settime(timer_fd_, 0, &ts, nullptr) == 0);
+}
+
+void PeriodicTimer::Stop() {
+  if (timer_fd_ < 0)
+    return;
+  close(timer_fd_);
+  timer_fd_ = -1;
+}
+
+bool PeriodicTimer::Wait() {
+  if (timer_fd_ < 0)
+    return false;  // Not started yet.
+  uint64_t stub = 0;
+  int res = read(timer_fd_, &stub, sizeof(stub));
+  if (res < 0 && errno == EBADF)
+    return false;  // Interrupted by Stop().
+  CHECK(res > 0);
+  return true;
+}
+
+}  // namespace time_utils
diff --git a/atrace-helper/time_utils.h b/atrace-helper/time_utils.h
new file mode 100644 (file)
index 0000000..2319601
--- /dev/null
@@ -0,0 +1,34 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TIME_UTILS_H_
+#define TIME_UTILS_H_
+
+#include <stdint.h>
+
+namespace time_utils {
+
+uint64_t GetTimestamp();
+
+class PeriodicTimer {
+ public:
+  PeriodicTimer(int interval_ms);
+  ~PeriodicTimer();
+
+  void Start();
+  void Stop();
+  // Wait for next tick. Returns false if interrupted by Stop() or not started.
+  bool Wait();
+
+ private:
+  PeriodicTimer(const PeriodicTimer&) = delete;
+  void operator=(const PeriodicTimer&) = delete;
+
+  const int interval_ms_;
+  int timer_fd_;
+};
+
+}  // namespace time_utils
+
+#endif  // TIME_UTILS_
diff --git a/atrace.pc.in b/atrace.pc.in
deleted file mode 100644 (file)
index 1ece274..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-# Package Information for pkg-config
-
-prefix=@PREFIX@
-exec_prefix=@EXEC_PREFIX@
-libdir=@LIB_INSTALL_DIR@
-includedir=@INCLUDEDIR@
-
-Name: atrace
-Description: atrace for tizen
-Version: @VERSION@
-Requires: zlib
-Libs: -L${libdir}
-Cflags: -I${includedir}
diff --git a/atrace/CMakeLists.txt b/atrace/CMakeLists.txt
new file mode 100644 (file)
index 0000000..378aa08
--- /dev/null
@@ -0,0 +1,24 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+PROJECT(atrace C)
+
+SET(PREFIX ${CMAKE_INSTALL_PREFIX})
+SET(EXEC_PREFIX "\${prefix}")
+
+SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CFLAGS} -std=c++11")
+SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g")
+SET(CMAKE_CXX_FLAGS_RELEASE "-O2")
+
+AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} SOURCES)
+
+INCLUDE(FindPkgConfig)
+pkg_check_modules(pkg_atrace REQUIRED zlib libsmack)
+FOREACH(flag ${pkg_atrace_CXXFLAGS})
+       SET(EXTRA_CXXFLAGS "${EXTRA_CXXFLAGS} ${flag}")
+ENDFOREACH(flag)
+
+ADD_EXECUTABLE(${PROJECT_NAME} ${SOURCES})
+TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${pkg_atrace_LDFLAGS} "-ldl")
+
+SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES VERSION ${ATRACE_VERSION})
+
+INSTALL(TARGETS ${PROJECT_NAME} DESTINATION bin)
diff --git a/atrace/MODULE_LICENSE_APACHE2 b/atrace/MODULE_LICENSE_APACHE2
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/atrace/NOTICE b/atrace/NOTICE
new file mode 100644 (file)
index 0000000..c77f135
--- /dev/null
@@ -0,0 +1,190 @@
+
+   Copyright (c) 2012, 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.
+
+   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.
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
diff --git a/atrace/atrace.cpp b/atrace/atrace.cpp
new file mode 100755 (executable)
index 0000000..bb2edf2
--- /dev/null
@@ -0,0 +1,1095 @@
+/*
+ * Copyright (C) 2012 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 <errno.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/sendfile.h>
+#include <time.h>
+#include <zlib.h>
+#include <stdint.h>
+#include <strings.h>
+#include <string.h>
+#include <grp.h>
+#include <sys/mman.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/smack.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <inttypes.h>
+
+#include <memory>
+#include <fstream>
+
+#include "ttrace.h"
+
+using std::string;
+
+#define TTRACE_TAG_NONE     9999
+#define TAG_NONE_IDX        0
+
+#define BACKUP_TRACE        "/tmp/trace.backup"
+#define BOOTUP_TRACE        "/etc/ttrace.conf"
+#define DEF_GR_SIZE         1024
+#define NELEM(x)            ((int) (sizeof(x) / sizeof((x)[0])))
+
+enum { MAX_SYS_FILES = 11 };
+
+const char* k_traceTagsProperty = "debug.atrace.tags.enableflags";
+const char* k_traceAppCmdlineProperty = "debug.atrace.app_cmdlines";
+
+typedef enum { OPT, REQ } requiredness  ;
+
+char str_error[256] = "";
+
+struct TracingCategory {
+    // The name identifying the category.
+    const char* name;
+
+    // A longer description of the category.
+    const char* longname;
+
+    // The userland tracing tags that the category enables.
+    uint64_t tags;
+
+    // The fname==nullptr terminated list of /sys/ files that the category
+    // enables.
+    struct {
+        // Whether the file must be writable in order to enable the tracing
+        // category.
+        requiredness required;
+
+        // The path to the enable file.
+        const char* path;
+    } sysfiles[MAX_SYS_FILES];
+};
+
+/* Tracing categories */
+static const TracingCategory k_categories[] = {
+    { "none",        "None",                TTRACE_TAG_NONE, { } }, //do not change "none" option's index
+    { "gfx",         "Graphics",            TTRACE_TAG_GRAPHICS, { } },
+    { "input",       "Input",               TTRACE_TAG_INPUT, { } },
+    { "view",        "View System",         TTRACE_TAG_VIEW, { } },
+    { "web",         "Web",                 TTRACE_TAG_WEB, { } },
+    { "wm",          "Window Manager",      TTRACE_TAG_WINDOW_MANAGER, { } },
+    { "am",          "Application Manager", TTRACE_TAG_APPLICATION_MANAGER, { } },
+    { "image",       "Image",               TTRACE_TAG_IMAGE, { } },
+    { "audio",       "Audio",               TTRACE_TAG_AUDIO, { } },
+    { "video",       "Video",               TTRACE_TAG_VIDEO, { } },
+    { "camera",      "Camera",              TTRACE_TAG_CAMERA, { } },
+    { "hal",         "Hardware Modules",    TTRACE_TAG_HAL, { } },
+    { "mc",          "Multimedia content",  TTRACE_TAG_MEDIA_CONTENT, { } },
+    { "mdb",         "Multimedia database", TTRACE_TAG_MEDIA_DB, { } },
+    { "scmirroring", "Screen mirroring",    TTRACE_TAG_SCREEN_MIRRORING, { } },
+    { "efl",         "EFL",                 TTRACE_TAG_EFL, { } },
+    { "app",         "Application",         TTRACE_TAG_APP, { } },
+    { "sched",      "CPU Scheduling",   0, {
+        { REQ,      "/sys/kernel/debug/tracing/events/sched/sched_switch/enable" },
+        { REQ,      "/sys/kernel/debug/tracing/events/sched/sched_wakeup/enable" },
+        { OPT,      "/sys/kernel/debug/tracing/events/sched/sched_waking/enable" },
+        { OPT,      "/sys/kernel/debug/tracing/events/sched/sched_pi_setprio/enable" },
+        { OPT,      "/sys/kernel/debug/tracing/events/sched/sched_process_exit/enable" },
+        { OPT,      "/sys/kernel/debug/tracing/events/cgroup/enable" },
+        { OPT,      "/sys/kernel/debug/tracing/events/oom/oom_score_adj_update/enable" },
+        { OPT,      "/sys/kernel/debug/tracing/events/task/task_rename/enable" },
+        { OPT,      "/sys/kernel/debug/tracing/events/task/task_newtask/enable" },
+    } },
+    { "irq",        "IRQ Events",   0, {
+        { REQ,      "/sys/kernel/debug/tracing/events/irq/enable" },
+        { OPT,      "/sys/kernel/debug/tracing/events/ipi/enable" },
+    } },
+    { "irqoff",     "IRQ-disabled code section tracing", 0, {
+        { REQ,      "/sys/kernel/debug/tracing/events/preemptirq/irq_enable/enable" },
+        { REQ,      "/sys/kernel/debug/tracing/events/preemptirq/irq_disable/enable" },
+    } },
+    { "i2c",        "I2C Events",   0, {
+        { REQ,      "/sys/kernel/debug/tracing/events/i2c/enable" },
+        { REQ,      "/sys/kernel/debug/tracing/events/i2c/i2c_read/enable" },
+        { REQ,      "/sys/kernel/debug/tracing/events/i2c/i2c_write/enable" },
+        { REQ,      "/sys/kernel/debug/tracing/events/i2c/i2c_result/enable" },
+        { REQ,      "/sys/kernel/debug/tracing/events/i2c/i2c_reply/enable" },
+    } },
+    { "freq",       "CPU Frequency",    0, {
+        { REQ,      "/sys/kernel/debug/tracing/events/power/cpu_frequency/enable" },
+        { OPT,      "/sys/kernel/debug/tracing/events/power/clock_set_rate/enable" },
+        { OPT,      "/sys/kernel/debug/tracing/events/power/clock_set_rate/enable" },
+        { OPT,      "/sys/kernel/debug/tracing/events/power/clock_disable/enable" },
+        { OPT,      "/sys/kernel/debug/tracing/events/power/clock_enable/enable" },
+        { OPT,      "/sys/kernel/debug/tracing/events/clk/clk_set_rate/enable" },
+        { OPT,      "/sys/kernel/debug/tracing/events/clk/clk_disable/enable" },
+        { OPT,      "/sys/kernel/debug/tracing/events/clk/clk_enable/enable" },
+        { OPT,      "/sys/kernel/debug/tracing/events/power/cpu_frequency_limits/enable" },
+        { OPT,      "/sys/kernel/debug/tracing/events/power/suspend_resume/enable" },
+    } },
+    { "membus",     "Memory Bus Utilization", 0, {
+        { REQ,      "/sys/kernel/debug/tracing/events/memory_bus/enable" },
+    } },
+    { "idle",       "CPU Idle",         0, {
+        { REQ,      "/sys/kernel/debug/tracing/events/power/cpu_idle/enable" },
+    } },
+    { "disk",       "Disk I/O",         0, {
+        { REQ,      "/sys/kernel/debug/tracing/events/ext4/ext4_sync_file_enter/enable" },
+        { REQ,      "/sys/kernel/debug/tracing/events/ext4/ext4_sync_file_exit/enable" },
+        { REQ,      "/sys/kernel/debug/tracing/events/block/block_rq_issue/enable" },
+        { REQ,      "/sys/kernel/debug/tracing/events/block/block_rq_complete/enable" },
+        { OPT,      "/sys/kernel/debug/tracing/events/ext4/ext4_da_write_begin/enable" },
+        { OPT,      "/sys/kernel/debug/tracing/events/ext4/ext4_da_write_end/enable" },
+    } },
+    { "mmc",        "eMMC commands",    0, {
+        { REQ,      "/sys/kernel/debug/tracing/events/mmc/enable" },
+    } },
+    { "load",       "CPU Load",         0, {
+        { REQ,      "/sys/kernel/debug/tracing/events/cpufreq_interactive/enable" },
+    } },
+    { "sync",       "Synchronization",  0, {
+        // linux kernel < 4.9
+        { OPT,      "/sys/kernel/debug/tracing/events/sync/enable" },
+        // linux kernel == 4.9.x
+        { OPT,      "/sys/kernel/debug/tracing/events/fence/enable" },
+        // linux kernel > 4.9
+        { OPT,      "/sys/kernel/debug/tracing/events/dma_fence/enable" },
+    } },
+    { "workq",      "Kernel Workqueues", 0, {
+        { REQ,      "/sys/kernel/debug/tracing/events/workqueue/enable" },
+    } },
+    { "regulators",  "Voltage and Current Regulators", 0, {
+        { REQ,      "/sys/kernel/debug/tracing/events/regulator/enable" },
+    } },
+    { "pagecache",  "Page cache", 0, {
+        { REQ,      "/sys/kernel/debug/tracing/events/filemap/enable" },
+    } },
+#ifdef TTRACE_PROFILE_MOBILE
+#elif defined TTRACE_PROFILE_TV
+    { "system",       "System",                 TTRACE_TAG_SYSTEM, { } },
+    { "perftest",     "For Performance test",   TTRACE_TAG_PERFTEST, { } },
+#elif defined TTRACE_PROFILE_WEARABLE
+#endif
+};
+
+/* Command line options */
+static int g_traceDurationSeconds = 5;
+static bool g_traceOverwrite = false;
+static int g_traceBufferSizeKB = 2048;
+static bool g_compress = false;
+static bool g_nohup = false;
+static int g_initialSleepSecs = 0;
+static const char* g_kernelTraceFuncs = nullptr;
+static const char* g_debugAppCmdLine = "";
+
+/* Global state */
+static bool g_traceAborted = false;
+static bool g_categoryEnables[NELEM(k_categories)] = {};
+static bool g_append_trace = false;
+static bool g_backup_trace = false;
+
+/* Save excluded tags list */
+uint64_t excludedTags;
+
+static bool setCategoryEnable(const char* name, bool enable);
+
+/* Sys file paths */
+static const char* k_traceClockPath =
+    "/sys/kernel/debug/tracing/trace_clock";
+
+static const char* k_traceBufferSizePath =
+    "/sys/kernel/debug/tracing/buffer_size_kb";
+
+static const char* k_tracingOverwriteEnablePath =
+    "/sys/kernel/debug/tracing/options/overwrite";
+
+static const char* k_currentTracerPath =
+    "/sys/kernel/debug/tracing/current_tracer";
+
+static const char* k_printTgidPath =
+    "/sys/kernel/debug/tracing/options/print-tgid";
+
+static const char* k_funcgraphAbsTimePath =
+    "/sys/kernel/debug/tracing/options/funcgraph-abstime";
+
+static const char* k_funcgraphCpuPath =
+    "/sys/kernel/debug/tracing/options/funcgraph-cpu";
+
+static const char* k_funcgraphProcPath =
+    "/sys/kernel/debug/tracing/options/funcgraph-proc";
+
+static const char* k_funcgraphFlatPath =
+    "/sys/kernel/debug/tracing/options/funcgraph-flat";
+
+static const char* k_funcgraphDurationPath =
+    "/sys/kernel/debug/tracing/options/funcgraph-duration";
+
+static const char* k_ftraceFilterPath =
+    "/sys/kernel/debug/tracing/set_ftrace_filter";
+
+static const char* k_tracingOnPath =
+    "/sys/kernel/debug/tracing/tracing_on";
+
+static const char* k_tracePath =
+    "/sys/kernel/debug/tracing/trace";
+
+// Check whether a file exists.
+static bool fileExists(const char* filename) {
+    return access(filename, F_OK) != -1;
+}
+
+// Check whether a file is writable.
+static bool fileIsWritable(const char* filename) {
+    return access(filename, W_OK) != -1;
+}
+
+// Truncate a file.
+static bool truncateFile(const char* path)
+{
+    // This uses creat rather than truncate because some of the debug kernel
+    // device nodes (e.g. k_ftraceFilterPath) currently aren't changed by
+    // calls to truncate, but they are cleared by calls to creat.
+    int traceFD = creat(path, 0);
+    if (traceFD == -1) {
+        fprintf(stderr, "error truncating %s: %s (%d)\n", path,
+            strerror_r(errno, str_error, sizeof(str_error)), errno);
+        return false;
+    }
+
+    close(traceFD);
+
+    return true;
+}
+
+static bool _writeStr(const char* filename, const char* str, int flags)
+{
+    int fd = open(filename, flags);
+    if (fd == -1) {
+        fprintf(stderr, "error opening %s: %s (%d)\n", filename,
+                strerror_r(errno, str_error, sizeof(str_error)), errno);
+        return false;
+    }
+
+    bool ok = true;
+    ssize_t len = strlen(str);
+    if (write(fd, str, len) != len) {
+        fprintf(stderr, "error writing to %s: %s (%d)\n", filename,
+                strerror_r(errno, str_error, sizeof(str_error)), errno);
+        ok = false;
+    }
+
+    close(fd);
+
+    return ok;
+}
+
+// Write a string to a file, returning true if the write was successful.
+static bool writeStr(const char* filename, const char* str)
+{
+    return _writeStr(filename, str, O_WRONLY);
+}
+
+// Append a string to a file, returning true if the write was successful.
+static bool appendStr(const char* filename, const char* str)
+{
+    return _writeStr(filename, str, O_APPEND|O_WRONLY);
+}
+
+// Enable or disable a kernel option by writing a "1" or a "0" into a /sys
+// file.
+static bool setKernelOptionEnable(const char* filename, bool enable)
+{
+    return writeStr(filename, enable ? "1" : "0");
+}
+
+// Check whether the category is supported on the device with the current
+// rootness.  A category is supported only if all its required /sys/ files are
+// writable and if enabling the category will enable one or more tracing tags
+// or /sys/ files.
+static bool isCategorySupported(const TracingCategory& category)
+{
+    bool ok = category.tags != 0;
+    for (int i = 0; i < MAX_SYS_FILES; i++) {
+        const char* path = category.sysfiles[i].path;
+        bool req = category.sysfiles[i].required == REQ;
+        if (path != nullptr) {
+            if (req) {
+                if (!fileIsWritable(path)) {
+                    return false;
+                } else {
+                    ok = true;
+                }
+            } else {
+                ok |= fileIsWritable(path);
+            }
+        }
+    }
+    return ok;
+}
+
+// Check whether the category would be supported on the device if the user
+// were root.  This function assumes that root is able to write to any file
+// that exists.  It performs the same logic as isCategorySupported, but it
+// uses file existance rather than writability in the /sys/ file checks.
+static bool isCategorySupportedForRoot(const TracingCategory& category)
+{
+    bool ok = category.tags != 0;
+    for (int i = 0; i < MAX_SYS_FILES; i++) {
+        const char* path = category.sysfiles[i].path;
+        bool req = category.sysfiles[i].required == REQ;
+        if (path != nullptr) {
+            if (req) {
+                if (!fileExists(path)) {
+                    return false;
+                } else {
+                    ok = true;
+                }
+            } else {
+                ok |= fileExists(path);
+            }
+        }
+    }
+    return ok;
+}
+
+// Enable or disable overwriting of the kernel trace buffers.  Disabling this
+// will cause tracing to stop once the trace buffers have filled up.
+static bool setTraceOverwriteEnable(bool enable)
+{
+    return setKernelOptionEnable(k_tracingOverwriteEnablePath, enable);
+}
+
+// Enable or disable kernel tracing.
+static bool setTracingEnabled(bool enable)
+{
+    return setKernelOptionEnable(k_tracingOnPath, enable);
+}
+
+// Clear the contents of the kernel trace.
+static bool clearKernelTrace()
+{
+    return truncateFile(k_tracePath);
+}
+
+// Set the size of the kernel's trace buffer in kilobytes.
+static bool setTraceBufferSizeKB(int size)
+{
+    char str[32] = "1";
+    if (size < 1) {
+        size = 1;
+    }
+    snprintf(str, 32, "%d", size);
+    return writeStr(k_traceBufferSizePath, str);
+}
+
+// Set the clock to the best available option while tracing. Use 'boot' if it's
+// available; otherwise, use 'mono'. If neither are available use 'global'.
+// Any write to the trace_clock sysfs file will reset the buffer, so only
+// update it if the requested value is not the current value.
+static bool setBestClock(bool enable)
+{
+    std::ifstream clockFile(k_traceClockPath, std::ios::in);
+    std::string clockStr((std::istreambuf_iterator<char>(clockFile)),
+        std::istreambuf_iterator<char>());
+    std::string newClock;
+
+    if (enable == false)
+        return writeStr(k_traceClockPath, "local");
+
+    if (clockStr.find("boot") != std::string::npos)
+        newClock = "boot";
+    else if (clockStr.find("mono") != std::string::npos)
+        newClock = "mono";
+    else
+        newClock = "global";
+
+    size_t begin = clockStr.find('[') + 1;
+    size_t end = clockStr.find(']');
+    if (newClock.compare(0, std::string::npos, clockStr, begin, end-begin) == 0)
+        return true;
+
+    return writeStr(k_traceClockPath, newClock.c_str());
+}
+
+static bool setPrintTgidEnableIfPresent(bool enable)
+{
+    if (fileExists(k_printTgidPath)) {
+        return setKernelOptionEnable(k_printTgidPath, enable);
+    }
+    return true;
+}
+
+static bool getBootupTagStr(char* bootupTagStr, int strSize)
+{
+    if(fileExists(BOOTUP_TRACE)) {
+        FILE *bootupTagFile = nullptr;
+
+        bootupTagFile = fopen(BOOTUP_TRACE, "r");
+        if (bootupTagFile == nullptr) {
+            return false;
+        }
+        if (fgets(bootupTagStr, strSize, bootupTagFile) == NULL) {
+            fclose(bootupTagFile);
+            return false;
+        }
+        fclose(bootupTagFile);
+        fprintf(stderr, "[Info] Loaded tags: %s, bufsize: %d\n",\
+                bootupTagStr, strSize);
+        return true;
+    }
+    return false;
+}
+
+static void setBootupTags(char* bootupTagStr)
+{
+    char* tagPtr;
+    char* nextTagPtr;
+    tagPtr = strtok_r(bootupTagStr, " \n", &nextTagPtr);
+    while (tagPtr != nullptr) {
+        setCategoryEnable(tagPtr, true);
+        fprintf(stderr, "[Info] Tag %s enabled\n", tagPtr);
+        tagPtr = strtok_r(nullptr, " \n", &nextTagPtr);
+    }
+    return;
+}
+
+static bool initEnabledTagFile()
+{
+    uint64_t *sm_for_enabled_tag = nullptr;
+    int fd = -1;
+
+    if(fileExists(ENABLED_TAG_FILE)) {
+        fprintf(stderr, "[Info] T-trace has been already initailized\n");
+        return true; //atrace has been already initailized.
+    }
+
+    fd = open("/tmp/tmp_tag", O_CREAT | O_RDWR | O_CLOEXEC, 0600);
+    if(fd < 0){
+        fprintf(stderr, "Fail to open enabled_tag file: %s(%d)\n", strerror_r(errno, str_error, sizeof(str_error)), errno);
+        return false;
+    }
+
+    if (ftruncate(fd, sizeof(uint64_t)) < 0) {
+        fprintf(stderr, "ftruncate() failed(%s)\n", strerror_r(errno, str_error, sizeof(str_error)));
+        close(fd);
+        return false;
+    }
+    sm_for_enabled_tag = (uint64_t*)mmap(nullptr, sizeof(uint64_t), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+
+    if(sm_for_enabled_tag == MAP_FAILED) {
+        fprintf(stderr, "mmap() failed(%s)\n", strerror_r(errno, str_error, sizeof(str_error)));
+        close(fd);
+        return false;
+    }
+
+    memset(sm_for_enabled_tag, 0, sizeof(uint64_t));
+    if(-1 == rename("/tmp/tmp_tag", ENABLED_TAG_FILE)) {
+        fprintf(stderr, "Fail to rename enabled_tag file: %s(%d)\n", strerror_r(errno, str_error, sizeof(str_error)), errno);
+    }
+
+    munmap(sm_for_enabled_tag, sizeof(uint64_t));
+    close(fd);
+    return true;
+}
+
+// Set the trace tags that userland tracing uses, and poke the running
+// processes to pick up the new value.
+static bool setTagsProperty(uint64_t tags)
+{
+    uint64_t *sm_for_enabled_tag = nullptr;
+    int fd = -1;
+
+    // atrace normal mode
+    fd = open(ENABLED_TAG_FILE, O_RDWR | O_CLOEXEC, 0600);
+    if(fd < 0){
+        fprintf(stderr, "Fail to open enabled_tag file: %s(%d)\n", strerror_r(errno, str_error, sizeof(str_error)), errno);
+        return false;
+    }
+    sm_for_enabled_tag = (uint64_t*)mmap(nullptr, sizeof(uint64_t), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+    if(sm_for_enabled_tag == MAP_FAILED) {
+        fprintf(stderr, "mmap() failed(%s)\n", strerror_r(errno, str_error, sizeof(str_error)));
+        close(fd);
+        return false;
+    }
+    *sm_for_enabled_tag = tags;
+
+    // For debug
+    // fprintf(stderr, "Enabled TAGs: %u\n", (uint32_t)*sm_for_enabled_tag);
+    //
+    munmap(sm_for_enabled_tag, sizeof(uint64_t));
+    close(fd);
+    return true;
+}
+
+// Disable all /sys/ enable files.
+static bool disableKernelTraceEvents() {
+    bool ok = true;
+    for (int i = 0; i < NELEM(k_categories); i++) {
+        const TracingCategory &c = k_categories[i];
+        for (int j = 0; j < MAX_SYS_FILES; j++) {
+            const char* path = c.sysfiles[j].path;
+            if (path != nullptr && fileIsWritable(path)) {
+                ok &= setKernelOptionEnable(path, false);
+            }
+        }
+    }
+    return ok;
+}
+
+// Set the comma separated list of functions that the kernel is to trace.
+static bool setKernelTraceFuncs(const char* funcs)
+{
+    bool ok = true;
+    char *ptr[2];
+
+    if (funcs == nullptr || funcs[0] == '\0') {
+        // Disable kernel function tracing.
+        if (fileIsWritable(k_currentTracerPath)) {
+            ok &= writeStr(k_currentTracerPath, "nop");
+        }
+        if (fileIsWritable(k_ftraceFilterPath)) {
+            ok &= truncateFile(k_ftraceFilterPath);
+        }
+    } else {
+        // Enable kernel function tracing.
+        ok &= writeStr(k_currentTracerPath, "function_graph");
+        ok &= setKernelOptionEnable(k_funcgraphAbsTimePath, true);
+        ok &= setKernelOptionEnable(k_funcgraphCpuPath, true);
+        ok &= setKernelOptionEnable(k_funcgraphProcPath, true);
+        ok &= setKernelOptionEnable(k_funcgraphFlatPath, true);
+        ok &= setKernelOptionEnable(k_funcgraphDurationPath, true);
+
+        // Set the requested filter functions.
+        ok &= truncateFile(k_ftraceFilterPath);
+        char* myFuncs = strdup(funcs);
+        char* func = strtok_r(myFuncs, ",", &ptr[0]);
+        while (func) {
+            ok &= appendStr(k_ftraceFilterPath, func);
+            func = strtok_r(NULL, ",", &ptr[1]);
+        }
+        free(myFuncs);
+    }
+
+    return ok;
+}
+
+// Enable tracing in the kernel.
+static bool startTrace()
+{
+    return setTracingEnabled(true);
+}
+
+// Set all the kernel tracing settings to the desired state for this trace
+// capture.
+static bool setUpTrace()
+{
+    bool ok = true;
+
+    // Set up the tracing options.
+    ok &= setTraceOverwriteEnable(g_traceOverwrite);
+    if(!g_append_trace) {
+        ok &= setTraceBufferSizeKB(g_traceBufferSizeKB);
+        ok &= setBestClock(true);
+        ok &= setKernelTraceFuncs(g_kernelTraceFuncs);
+    }
+    ok &= setPrintTgidEnableIfPresent(true);
+
+    // Set up the tags property.
+    uint64_t tags = 0;
+    if (g_categoryEnables[TAG_NONE_IDX]) tags = TTRACE_TAG_NEVER;
+    else {
+        for (int i = 0; i < NELEM(k_categories); i++) {
+            if (g_categoryEnables[i]) {
+                const TracingCategory &c = k_categories[i];
+                if ((c.tags & excludedTags) == 0)
+                    tags |= c.tags;
+            }
+        }
+        if (tags == 0 && excludedTags == 0) {
+            tags |= TTRACE_TAG_ALWAYS;
+        }
+        else if (tags == 0 && excludedTags != 0) {
+            excludedTags |= TTRACE_TAG_ALWAYS;
+            tags |= ~excludedTags;
+        }
+        else {
+            excludedTags |= TTRACE_TAG_ALWAYS;
+            tags &= ~excludedTags;
+        }
+        printf("Tags: 0x%" PRIx64 " excludedTags: 0x%" PRIx64 "\n", tags, excludedTags);
+    }
+
+    ok &= startTrace();
+    if(!g_append_trace) {
+        // Clear Kernel Trace
+        ok &= clearKernelTrace();
+
+        // Disable all the sysfs enables.  This is done as a separate loop from
+        // the enables to allow the same enable to exist in multiple categories.
+        ok &= disableKernelTraceEvents();
+    }
+    ok &= setTagsProperty(tags);
+
+    // Enable all the sysfs enables that are in an enabled category.
+    for (int i = 0; i < NELEM(k_categories); i++) {
+        if (g_categoryEnables[i]) {
+            const TracingCategory &c = k_categories[i];
+            for (int j = 0; j < MAX_SYS_FILES; j++) {
+                const char* path = c.sysfiles[j].path;
+                bool required = c.sysfiles[j].required == REQ;
+                if (path != nullptr) {
+                    if (fileIsWritable(path)) {
+                        ok &= setKernelOptionEnable(path, true);
+                    } else if (required) {
+                        fprintf(stderr, "error writing file %s\n", path);
+                        ok = false;
+                    }
+                }
+            }
+        }
+    }
+
+    return ok;
+}
+
+// Reset all the kernel tracing settings to their default state.
+static void cleanUpTrace()
+{
+    // Disable all tracing that we're able to.
+    disableKernelTraceEvents();
+
+    // Set the options back to their defaults.
+    setTraceOverwriteEnable(true);
+    setTraceBufferSizeKB(1);
+    setBestClock(false);
+    setPrintTgidEnableIfPresent(false);
+    setKernelTraceFuncs(nullptr);
+}
+
+// Disable tracing in the kernel.
+static void stopTrace()
+{
+    setTagsProperty(0);
+    setTracingEnabled(false);
+}
+
+// Read the current kernel trace and write it to stdout.
+static void dumpTrace(bool startup)
+{
+    int backup_fd = -1;
+    int traceFD = -1;
+
+    traceFD = open(k_tracePath, O_RDWR);
+    if (traceFD == -1) {
+        fprintf(stderr, "error opening %s: %s (%d)\n", k_tracePath,
+                strerror_r(errno, str_error, sizeof(str_error)), errno);
+        return;
+    }
+
+    if(startup) {
+        backup_fd = open(BACKUP_TRACE, O_CREAT|O_RDWR|O_TRUNC, 0600);
+        if (backup_fd == -1) {
+            fprintf(stderr, "error opening %s: %s (%d)\n", BACKUP_TRACE,
+                    strerror_r(errno, str_error, sizeof(str_error)), errno);
+            close(traceFD);
+            return;
+        }
+    }
+
+    if (g_compress) {
+        z_stream zs;
+        int result, flush;
+
+        bzero(&zs, sizeof(zs));
+        result = deflateInit(&zs, Z_DEFAULT_COMPRESSION);
+        if (result != Z_OK) {
+            fprintf(stderr, "error initializing zlib: %d\n", result);
+            close(traceFD);
+            if (backup_fd > -1)
+                close(backup_fd);
+            return;
+        }
+
+        const size_t bufSize = 64*1024;
+        std::unique_ptr<uint8_t[]> in(new uint8_t[bufSize]);
+        std::unique_ptr<uint8_t[]> out(new uint8_t[bufSize]);
+        if ((in == nullptr) || (out == nullptr)) {
+            fprintf(stderr, "Could not allocate memory");
+            close(traceFD);
+            if (backup_fd > -1)
+                close(backup_fd);
+            return;
+        }
+        flush = Z_NO_FLUSH;
+
+        zs.next_out = reinterpret_cast<Bytef*>(out.get());
+        zs.avail_out = bufSize;
+
+        do {
+
+            if (zs.avail_in == 0) {
+                // More input is needed.
+                result = read(traceFD, in.get(), bufSize);
+                if (result < 0) {
+                    fprintf(stderr, "error reading trace: %s (%d)\n",
+                            strerror_r(errno, str_error, sizeof(str_error)), errno);
+                    result = Z_STREAM_END;
+                    break;
+                } else if (result == 0) {
+                    flush = Z_FINISH;
+                } else {
+                    zs.next_in = reinterpret_cast<Bytef*>(in.get());
+                    zs.avail_in = result;
+                }
+            }
+
+            if (zs.avail_out == 0) {
+                // Need to write the output.
+                if(startup)
+                    result = write(backup_fd, out.get(), bufSize);
+                else
+                    result = write(STDOUT_FILENO, out.get(), bufSize);
+
+                if ((size_t)result < bufSize) {
+                    fprintf(stderr, "error writing deflated trace: %s (%d)\n",
+                            strerror_r(errno, str_error, sizeof(str_error)), errno);
+                    result = Z_STREAM_END; // skip deflate error message
+                    zs.avail_out = bufSize; // skip the final write
+                    break;
+                }
+                zs.next_out = reinterpret_cast<Bytef*>(out.get());
+                zs.avail_out = bufSize;
+            }
+
+        } while ((result = deflate(&zs, flush)) == Z_OK);
+
+        if (result != Z_STREAM_END) {
+            fprintf(stderr, "error deflating trace: %s\n", zs.msg);
+        }
+
+        if (zs.avail_out < bufSize) {
+            size_t bytes = bufSize - zs.avail_out;
+            if(startup)
+                result = write(backup_fd, out.get(), bytes);
+            else
+                result = write(STDOUT_FILENO, out.get(), bytes);
+
+            if ((size_t)result < bytes) {
+                fprintf(stderr, "error writing deflated trace: %s (%d)\n",
+                        strerror_r(errno, str_error, sizeof(str_error)), errno);
+            }
+        }
+
+        result = deflateEnd(&zs);
+        if (result != Z_OK) {
+            fprintf(stderr, "error cleaning up zlib: %d\n", result);
+        }
+    } else {
+        ssize_t sent = 0;
+        if (startup)
+            while ((sent = sendfile(backup_fd, traceFD, nullptr, 64*1024*1024)) > 0);
+        else
+            while ((sent = sendfile(STDOUT_FILENO, traceFD, nullptr, 64*1024*1024)) > 0);
+
+        if (sent == -1) {
+            fprintf(stderr, "error dumping trace: %s (%d)\n", strerror_r(errno, str_error, sizeof(str_error)),
+                    errno);
+        }
+    }
+
+    if (backup_fd > -1)
+        close(backup_fd);
+    close(traceFD);
+}
+
+static void handleSignal(int signo)
+{
+    if (!g_nohup) {
+        g_traceAborted = true;
+    }
+}
+
+static void registerSigHandler()
+{
+    struct sigaction sa;
+    sigemptyset(&sa.sa_mask);
+    sa.sa_flags = 0;
+    sa.sa_handler = handleSignal;
+    sigaction(SIGHUP, &sa, nullptr);
+    sigaction(SIGINT, &sa, nullptr);
+    sigaction(SIGQUIT, &sa, nullptr);
+    sigaction(SIGTERM, &sa, nullptr);
+}
+
+static bool setCategoryEnable(const char* name, bool enable)
+{
+    for (int i = 0; i < NELEM(k_categories); i++) {
+        const TracingCategory& c = k_categories[i];
+        if (strcmp(name, c.name) == 0) {
+            if (isCategorySupported(c)) {
+                g_categoryEnables[i] = enable;
+                return true;
+            } else {
+                if (isCategorySupportedForRoot(c)) {
+                    fprintf(stderr, "error: category \"%s\" requires root "
+                            "privileges.\n", name);
+                } else {
+                    fprintf(stderr, "error: category \"%s\" is not supported "
+                            "on this device.\n", name);
+                }
+                return false;
+            }
+        }
+    }
+    fprintf(stderr, "error: unknown tracing category \"%s\"\n", name);
+    return false;
+}
+
+static void listSupportedCategories()
+{
+    for (int i = 0; i < NELEM(k_categories); i++) {
+        if(i==TAG_NONE_IDX) continue;
+        const TracingCategory& c = k_categories[i];
+        if (isCategorySupported(c)) {
+            printf("  %10s - %s\n", c.name, c.longname);
+        }
+    }
+}
+
+// Print the command usage help to stderr.
+static void showHelp(const char *cmd)
+{
+    fprintf(stderr, "usage: %s [options] [categories...]\n", cmd);
+    fprintf(stderr, "options include:\n"
+            "  -b N            use a trace buffer size of N KB\n"
+            "  -c              trace into a circular buffer\n"
+            "  -e category     specify a category to exclude [default None]\n"
+            "                   example, $ atrace -e wm -e am -e gfx\n"
+            "  -k fname,...    trace the listed kernel functions\n"
+            "  -n              ignore signals\n"
+            "  -s N            sleep for N seconds before tracing [default 0]\n"
+            "  -t N            trace for N seconds [defualt 5]\n"
+            "  -z              compress the trace dump\n"
+            "  --async_start   start circular trace and return immediatly\n"
+            "  --async_dump    dump the current contents of circular trace buffer\n"
+            "  --async_stop    stop tracing and dump the current contents of circular\n"
+            "                  trace buffer\n"
+            "  --append        append traces to the existing traces. do not clear the trace buffer \n"
+            "                  and kernel trace events set\n"
+            "  --backup        back up the existing traces to /tmp/trace.backup and then clear the trace buffer\n"
+            "  --list_categories\n"
+            "                  list the available tracing categories\n"
+           );
+}
+
+int main(int argc, char **argv)
+{
+    bool async = false;
+    bool traceStart = true;
+    bool traceStop = true;
+    bool traceDump = true;
+
+    char strBuf[128];
+
+    // Global Variable Initialization
+    excludedTags = 0ULL;
+
+    if (argc == 2 && 0 == strcmp(argv[1], "--help")) {
+        showHelp(argv[0]);
+        exit(0);
+    }
+
+    for (;;) {
+        int ret;
+        int option_index = 0;
+        static struct option long_options[] = {
+            {"async_start",     no_argument, nullptr,  0 },
+            {"async_stop",      no_argument, nullptr,  0 },
+            {"async_dump",      no_argument, nullptr,  0 },
+            {"list_categories", no_argument, nullptr,  0 },
+            {"init_exec",       no_argument, nullptr,  0 },
+            {"append",          no_argument, nullptr,  0 },
+            {"backup",          no_argument, nullptr,  0 },
+            {0,                 0,           nullptr,  0 }
+        };
+        ret = getopt_long(argc, argv, "b:ck:e:ns:t:z",
+                long_options, &option_index);
+        if (ret < 0) {
+            for (int i = optind; i < argc; i++) {
+                if (!setCategoryEnable(argv[i], true)) {
+                    fprintf(stderr, "error enabling tracing category \"%s\"\n", argv[i]);
+                    exit(1);
+                }
+            }
+            break;
+        }
+
+        switch(ret) {
+            case 'a':
+                g_debugAppCmdLine = optarg;
+                break;
+
+            case 'b':
+                g_traceBufferSizeKB = atoi(optarg);
+                break;
+
+            case 'c':
+                g_traceOverwrite = true;
+                break;
+
+            case 'e':
+                setCategoryEnable(optarg, true);
+                for (int i = 0; i < NELEM(k_categories); i++) {
+                    const TracingCategory &c = k_categories[i];
+                    if (!strcmp(c.name, optarg)) {
+                        excludedTags |= c.tags;
+                    }
+                }
+                break;
+
+            case 'k':
+                g_kernelTraceFuncs = optarg;
+                break;
+
+            case 'n':
+                g_nohup = true;
+                break;
+
+            case 's':
+                g_initialSleepSecs = atoi(optarg);
+                break;
+
+            case 't':
+                g_traceDurationSeconds = atoi(optarg);
+                break;
+
+            case 'z':
+                g_compress = true;
+                break;
+
+            case 0:
+                if (!strcmp(long_options[option_index].name, "list_categories")) {
+                    listSupportedCategories();
+                    exit(0);
+                }
+                if (!strcmp(long_options[option_index].name, "async_start")) {
+                    async = true;
+                    traceStop = false;
+                    traceDump = false;
+                    g_traceOverwrite = true;
+                } else if (!strcmp(long_options[option_index].name, "async_stop")) {
+                    async = true;
+                    traceStart = false;
+                    traceStop = true;
+                } else if (!strcmp(long_options[option_index].name, "async_dump")) {
+                    async = true;
+                    traceStart = false;
+                    traceStop = false;
+                } else if (!strcmp(long_options[option_index].name, "list_categories")) {
+                    listSupportedCategories();
+                    exit(0);
+                } else if (!strcmp(long_options[option_index].name, "init_exec")) {
+                    fprintf(stderr, "[Info] Initailize T-trace\n");
+                    if(!initEnabledTagFile()) {
+                        exit(-1);
+                    }
+                    if (getBootupTagStr(strBuf, sizeof(strBuf))) {
+                        async = true;
+                        traceStop = false;
+                        traceDump = false;
+                        g_traceOverwrite = true;
+                        setBootupTags(strBuf);
+                    }
+                    else {
+                        exit(0);
+                    }
+                } else if (!strcmp(long_options[option_index].name, "append")) {
+                    g_append_trace = true;
+                } else if (!strcmp(long_options[option_index].name, "backup")) {
+                    g_backup_trace = true;
+                }
+                break;
+
+            default:
+                fprintf(stderr, "\n");
+                showHelp(argv[0]);
+                exit(0);
+                break;
+        }
+    }
+
+    registerSigHandler();
+
+    if (g_initialSleepSecs > 0) {
+        sleep(g_initialSleepSecs);
+    }
+
+    bool ok = true;
+    if(traceStart && g_backup_trace) {
+        //before start tracing by atrace, backup existig traces
+        stopTrace();
+        dumpTrace(true);
+    }
+    if (!(async && !g_traceOverwrite)) {
+        ok &= setUpTrace();
+    }
+    if (ok && traceStart) {
+        // For debug
+        // printf("capturing trace...");
+        //
+        fflush(stdout);
+
+        // We clear the trace after starting it because tracing gets enabled for
+        // each CPU individually in the kernel. Having the beginning of the trace
+        // contain entries from only one CPU can cause "begin" entries without a
+        // matching "end" entry to show up if a task gets migrated from one CPU to
+        // another.
+        if (ok && !async) {
+            // Sleep to allow the trace to be captured.
+            struct timespec timeLeft;
+            timeLeft.tv_sec = g_traceDurationSeconds;
+            timeLeft.tv_nsec = 0;
+            do {
+                if (g_traceAborted) {
+                    break;
+                }
+            } while (nanosleep(&timeLeft, &timeLeft) == -1 && errno == EINTR);
+        }
+    }
+
+    // Stop the trace and restore the default settings.
+    if (traceStop)
+        stopTrace();
+
+    if (ok && traceDump) {
+        if (!g_traceAborted) {
+            printf(" done\nTRACE:\n");
+            fflush(stdout);
+            dumpTrace(false);
+        } else {
+            printf("\ntrace aborted.\n");
+            fflush(stdout);
+        }
+        clearKernelTrace();
+    } else if (!ok) {
+        fprintf(stderr, "unable to start tracing\n");
+    }
+
+    // Reset the trace buffer size to 1.
+    if (traceStop)
+        cleanUpTrace();
+
+    return g_traceAborted ? 1 : 0;
+}
index 947807fe381fbe9b2b46b3baedb4ffe7566e5d44..33a315d40193fee8f5d9c69a11622cb51735e3c3 100644 (file)
@@ -37,6 +37,9 @@ BuildRequires: cmake
 %define TTRACE_TIZEN_VERSION_MAJOR 3
 %endif
 
+%define ATRACE_VERSION 1.1
+%define ATRACE_HELPER_VERSION 1.0
+
 %description
 T-trace library
 
@@ -73,7 +76,8 @@ export CXXFLAGS="$CXXFLAGS -std=c++0x -fPIE -pie -fno-exceptions"
 MAJORVER=`echo %{version} | awk 'BEGIN {FS="."}{print $1}'`
 %cmake . -DCMAKE_INSTALL_PREFIX=%{_prefix} -DLIBDIR=%{_libdir} -DINCLUDEDIR=%{_includedir} \
       -DTTRACE_PROFILE=%{TTRACE_PROFILE} -DTTRACE_TIZEN_VERSION_MAJOR=%{TTRACE_TIZEN_VERSION_MAJOR} \
-      -DMAJORVER=${MAJORVER} -DFULLVER=%{version}
+      -DMAJORVER=${MAJORVER} -DFULLVER=%{version} \
+      -DATRACE_VERSION=%{ATRACE_VERSION} -DATRACE_HELPER_VERSION=%{ATRACE_HELPER_VERSION}
 make %{?jobs:-j%jobs}
 
 %if 0%{?gcov:1}
@@ -110,7 +114,9 @@ install -m 0644 gcov-obj/* %{buildroot}%{_datadir}/gcov/obj
 %{_unitdir}/ttrace-marker.service
 %{_unitdir}/sys-kernel-debug-tracing.mount
 %attr(755,root,users) %{_bindir}/atrace
+%attr(755,root,users) %{_bindir}/atrace-%{ATRACE_VERSION}
 %attr(755,root,users) %{_bindir}/atrace-helper
+%attr(755,root,users) %{_bindir}/atrace-helper-%{ATRACE_HELPER_VERSION}
 %{_unitdir}/sysinit.target.wants/ttrace-marker.service
 %{_unitdir}/sysinit.target.wants/sys-kernel-debug-tracing.mount
 %attr(755,root,root) %{_bindir}/atrace-bootup.sh
diff --git a/src/atrace/MODULE_LICENSE_APACHE2 b/src/atrace/MODULE_LICENSE_APACHE2
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/src/atrace/NOTICE b/src/atrace/NOTICE
deleted file mode 100644 (file)
index c77f135..0000000
+++ /dev/null
@@ -1,190 +0,0 @@
-
-   Copyright (c) 2012, 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.
-
-   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.
-
-
-                                 Apache License
-                           Version 2.0, January 2004
-                        http://www.apache.org/licenses/
-
-   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-   1. Definitions.
-
-      "License" shall mean the terms and conditions for use, reproduction,
-      and distribution as defined by Sections 1 through 9 of this document.
-
-      "Licensor" shall mean the copyright owner or entity authorized by
-      the copyright owner that is granting the License.
-
-      "Legal Entity" shall mean the union of the acting entity and all
-      other entities that control, are controlled by, or are under common
-      control with that entity. For the purposes of this definition,
-      "control" means (i) the power, direct or indirect, to cause the
-      direction or management of such entity, whether by contract or
-      otherwise, or (ii) ownership of fifty percent (50%) or more of the
-      outstanding shares, or (iii) beneficial ownership of such entity.
-
-      "You" (or "Your") shall mean an individual or Legal Entity
-      exercising permissions granted by this License.
-
-      "Source" form shall mean the preferred form for making modifications,
-      including but not limited to software source code, documentation
-      source, and configuration files.
-
-      "Object" form shall mean any form resulting from mechanical
-      transformation or translation of a Source form, including but
-      not limited to compiled object code, generated documentation,
-      and conversions to other media types.
-
-      "Work" shall mean the work of authorship, whether in Source or
-      Object form, made available under the License, as indicated by a
-      copyright notice that is included in or attached to the work
-      (an example is provided in the Appendix below).
-
-      "Derivative Works" shall mean any work, whether in Source or Object
-      form, that is based on (or derived from) the Work and for which the
-      editorial revisions, annotations, elaborations, or other modifications
-      represent, as a whole, an original work of authorship. For the purposes
-      of this License, Derivative Works shall not include works that remain
-      separable from, or merely link (or bind by name) to the interfaces of,
-      the Work and Derivative Works thereof.
-
-      "Contribution" shall mean any work of authorship, including
-      the original version of the Work and any modifications or additions
-      to that Work or Derivative Works thereof, that is intentionally
-      submitted to Licensor for inclusion in the Work by the copyright owner
-      or by an individual or Legal Entity authorized to submit on behalf of
-      the copyright owner. For the purposes of this definition, "submitted"
-      means any form of electronic, verbal, or written communication sent
-      to the Licensor or its representatives, including but not limited to
-      communication on electronic mailing lists, source code control systems,
-      and issue tracking systems that are managed by, or on behalf of, the
-      Licensor for the purpose of discussing and improving the Work, but
-      excluding communication that is conspicuously marked or otherwise
-      designated in writing by the copyright owner as "Not a Contribution."
-
-      "Contributor" shall mean Licensor and any individual or Legal Entity
-      on behalf of whom a Contribution has been received by Licensor and
-      subsequently incorporated within the Work.
-
-   2. Grant of Copyright License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      copyright license to reproduce, prepare Derivative Works of,
-      publicly display, publicly perform, sublicense, and distribute the
-      Work and such Derivative Works in Source or Object form.
-
-   3. Grant of Patent License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      (except as stated in this section) patent license to make, have made,
-      use, offer to sell, sell, import, and otherwise transfer the Work,
-      where such license applies only to those patent claims licensable
-      by such Contributor that are necessarily infringed by their
-      Contribution(s) alone or by combination of their Contribution(s)
-      with the Work to which such Contribution(s) was submitted. If You
-      institute patent litigation against any entity (including a
-      cross-claim or counterclaim in a lawsuit) alleging that the Work
-      or a Contribution incorporated within the Work constitutes direct
-      or contributory patent infringement, then any patent licenses
-      granted to You under this License for that Work shall terminate
-      as of the date such litigation is filed.
-
-   4. Redistribution. You may reproduce and distribute copies of the
-      Work or Derivative Works thereof in any medium, with or without
-      modifications, and in Source or Object form, provided that You
-      meet the following conditions:
-
-      (a) You must give any other recipients of the Work or
-          Derivative Works a copy of this License; and
-
-      (b) You must cause any modified files to carry prominent notices
-          stating that You changed the files; and
-
-      (c) You must retain, in the Source form of any Derivative Works
-          that You distribute, all copyright, patent, trademark, and
-          attribution notices from the Source form of the Work,
-          excluding those notices that do not pertain to any part of
-          the Derivative Works; and
-
-      (d) If the Work includes a "NOTICE" text file as part of its
-          distribution, then any Derivative Works that You distribute must
-          include a readable copy of the attribution notices contained
-          within such NOTICE file, excluding those notices that do not
-          pertain to any part of the Derivative Works, in at least one
-          of the following places: within a NOTICE text file distributed
-          as part of the Derivative Works; within the Source form or
-          documentation, if provided along with the Derivative Works; or,
-          within a display generated by the Derivative Works, if and
-          wherever such third-party notices normally appear. The contents
-          of the NOTICE file are for informational purposes only and
-          do not modify the License. You may add Your own attribution
-          notices within Derivative Works that You distribute, alongside
-          or as an addendum to the NOTICE text from the Work, provided
-          that such additional attribution notices cannot be construed
-          as modifying the License.
-
-      You may add Your own copyright statement to Your modifications and
-      may provide additional or different license terms and conditions
-      for use, reproduction, or distribution of Your modifications, or
-      for any such Derivative Works as a whole, provided Your use,
-      reproduction, and distribution of the Work otherwise complies with
-      the conditions stated in this License.
-
-   5. Submission of Contributions. Unless You explicitly state otherwise,
-      any Contribution intentionally submitted for inclusion in the Work
-      by You to the Licensor shall be under the terms and conditions of
-      this License, without any additional terms or conditions.
-      Notwithstanding the above, nothing herein shall supersede or modify
-      the terms of any separate license agreement you may have executed
-      with Licensor regarding such Contributions.
-
-   6. Trademarks. This License does not grant permission to use the trade
-      names, trademarks, service marks, or product names of the Licensor,
-      except as required for reasonable and customary use in describing the
-      origin of the Work and reproducing the content of the NOTICE file.
-
-   7. Disclaimer of Warranty. Unless required by applicable law or
-      agreed to in writing, Licensor provides the Work (and each
-      Contributor provides its Contributions) on an "AS IS" BASIS,
-      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-      implied, including, without limitation, any warranties or conditions
-      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-      PARTICULAR PURPOSE. You are solely responsible for determining the
-      appropriateness of using or redistributing the Work and assume any
-      risks associated with Your exercise of permissions under this License.
-
-   8. Limitation of Liability. In no event and under no legal theory,
-      whether in tort (including negligence), contract, or otherwise,
-      unless required by applicable law (such as deliberate and grossly
-      negligent acts) or agreed to in writing, shall any Contributor be
-      liable to You for damages, including any direct, indirect, special,
-      incidental, or consequential damages of any character arising as a
-      result of this License or out of the use or inability to use the
-      Work (including but not limited to damages for loss of goodwill,
-      work stoppage, computer failure or malfunction, or any and all
-      other commercial damages or losses), even if such Contributor
-      has been advised of the possibility of such damages.
-
-   9. Accepting Warranty or Additional Liability. While redistributing
-      the Work or Derivative Works thereof, You may choose to offer,
-      and charge a fee for, acceptance of support, warranty, indemnity,
-      or other liability obligations and/or rights consistent with this
-      License. However, in accepting such obligations, You may act only
-      on Your own behalf and on Your sole responsibility, not on behalf
-      of any other Contributor, and only if You agree to indemnify,
-      defend, and hold each Contributor harmless for any liability
-      incurred by, or claims asserted against, such Contributor by reason
-      of your accepting any such warranty or additional liability.
-
-   END OF TERMS AND CONDITIONS
-
diff --git a/src/atrace/atrace.cpp b/src/atrace/atrace.cpp
deleted file mode 100755 (executable)
index bb2edf2..0000000
+++ /dev/null
@@ -1,1095 +0,0 @@
-/*
- * Copyright (C) 2012 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 <errno.h>
-#include <fcntl.h>
-#include <getopt.h>
-#include <signal.h>
-#include <stdarg.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/sendfile.h>
-#include <time.h>
-#include <zlib.h>
-#include <stdint.h>
-#include <strings.h>
-#include <string.h>
-#include <grp.h>
-#include <sys/mman.h>
-#include <sys/file.h>
-#include <sys/stat.h>
-#include <sys/smack.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <inttypes.h>
-
-#include <memory>
-#include <fstream>
-
-#include "ttrace.h"
-
-using std::string;
-
-#define TTRACE_TAG_NONE     9999
-#define TAG_NONE_IDX        0
-
-#define BACKUP_TRACE        "/tmp/trace.backup"
-#define BOOTUP_TRACE        "/etc/ttrace.conf"
-#define DEF_GR_SIZE         1024
-#define NELEM(x)            ((int) (sizeof(x) / sizeof((x)[0])))
-
-enum { MAX_SYS_FILES = 11 };
-
-const char* k_traceTagsProperty = "debug.atrace.tags.enableflags";
-const char* k_traceAppCmdlineProperty = "debug.atrace.app_cmdlines";
-
-typedef enum { OPT, REQ } requiredness  ;
-
-char str_error[256] = "";
-
-struct TracingCategory {
-    // The name identifying the category.
-    const char* name;
-
-    // A longer description of the category.
-    const char* longname;
-
-    // The userland tracing tags that the category enables.
-    uint64_t tags;
-
-    // The fname==nullptr terminated list of /sys/ files that the category
-    // enables.
-    struct {
-        // Whether the file must be writable in order to enable the tracing
-        // category.
-        requiredness required;
-
-        // The path to the enable file.
-        const char* path;
-    } sysfiles[MAX_SYS_FILES];
-};
-
-/* Tracing categories */
-static const TracingCategory k_categories[] = {
-    { "none",        "None",                TTRACE_TAG_NONE, { } }, //do not change "none" option's index
-    { "gfx",         "Graphics",            TTRACE_TAG_GRAPHICS, { } },
-    { "input",       "Input",               TTRACE_TAG_INPUT, { } },
-    { "view",        "View System",         TTRACE_TAG_VIEW, { } },
-    { "web",         "Web",                 TTRACE_TAG_WEB, { } },
-    { "wm",          "Window Manager",      TTRACE_TAG_WINDOW_MANAGER, { } },
-    { "am",          "Application Manager", TTRACE_TAG_APPLICATION_MANAGER, { } },
-    { "image",       "Image",               TTRACE_TAG_IMAGE, { } },
-    { "audio",       "Audio",               TTRACE_TAG_AUDIO, { } },
-    { "video",       "Video",               TTRACE_TAG_VIDEO, { } },
-    { "camera",      "Camera",              TTRACE_TAG_CAMERA, { } },
-    { "hal",         "Hardware Modules",    TTRACE_TAG_HAL, { } },
-    { "mc",          "Multimedia content",  TTRACE_TAG_MEDIA_CONTENT, { } },
-    { "mdb",         "Multimedia database", TTRACE_TAG_MEDIA_DB, { } },
-    { "scmirroring", "Screen mirroring",    TTRACE_TAG_SCREEN_MIRRORING, { } },
-    { "efl",         "EFL",                 TTRACE_TAG_EFL, { } },
-    { "app",         "Application",         TTRACE_TAG_APP, { } },
-    { "sched",      "CPU Scheduling",   0, {
-        { REQ,      "/sys/kernel/debug/tracing/events/sched/sched_switch/enable" },
-        { REQ,      "/sys/kernel/debug/tracing/events/sched/sched_wakeup/enable" },
-        { OPT,      "/sys/kernel/debug/tracing/events/sched/sched_waking/enable" },
-        { OPT,      "/sys/kernel/debug/tracing/events/sched/sched_pi_setprio/enable" },
-        { OPT,      "/sys/kernel/debug/tracing/events/sched/sched_process_exit/enable" },
-        { OPT,      "/sys/kernel/debug/tracing/events/cgroup/enable" },
-        { OPT,      "/sys/kernel/debug/tracing/events/oom/oom_score_adj_update/enable" },
-        { OPT,      "/sys/kernel/debug/tracing/events/task/task_rename/enable" },
-        { OPT,      "/sys/kernel/debug/tracing/events/task/task_newtask/enable" },
-    } },
-    { "irq",        "IRQ Events",   0, {
-        { REQ,      "/sys/kernel/debug/tracing/events/irq/enable" },
-        { OPT,      "/sys/kernel/debug/tracing/events/ipi/enable" },
-    } },
-    { "irqoff",     "IRQ-disabled code section tracing", 0, {
-        { REQ,      "/sys/kernel/debug/tracing/events/preemptirq/irq_enable/enable" },
-        { REQ,      "/sys/kernel/debug/tracing/events/preemptirq/irq_disable/enable" },
-    } },
-    { "i2c",        "I2C Events",   0, {
-        { REQ,      "/sys/kernel/debug/tracing/events/i2c/enable" },
-        { REQ,      "/sys/kernel/debug/tracing/events/i2c/i2c_read/enable" },
-        { REQ,      "/sys/kernel/debug/tracing/events/i2c/i2c_write/enable" },
-        { REQ,      "/sys/kernel/debug/tracing/events/i2c/i2c_result/enable" },
-        { REQ,      "/sys/kernel/debug/tracing/events/i2c/i2c_reply/enable" },
-    } },
-    { "freq",       "CPU Frequency",    0, {
-        { REQ,      "/sys/kernel/debug/tracing/events/power/cpu_frequency/enable" },
-        { OPT,      "/sys/kernel/debug/tracing/events/power/clock_set_rate/enable" },
-        { OPT,      "/sys/kernel/debug/tracing/events/power/clock_set_rate/enable" },
-        { OPT,      "/sys/kernel/debug/tracing/events/power/clock_disable/enable" },
-        { OPT,      "/sys/kernel/debug/tracing/events/power/clock_enable/enable" },
-        { OPT,      "/sys/kernel/debug/tracing/events/clk/clk_set_rate/enable" },
-        { OPT,      "/sys/kernel/debug/tracing/events/clk/clk_disable/enable" },
-        { OPT,      "/sys/kernel/debug/tracing/events/clk/clk_enable/enable" },
-        { OPT,      "/sys/kernel/debug/tracing/events/power/cpu_frequency_limits/enable" },
-        { OPT,      "/sys/kernel/debug/tracing/events/power/suspend_resume/enable" },
-    } },
-    { "membus",     "Memory Bus Utilization", 0, {
-        { REQ,      "/sys/kernel/debug/tracing/events/memory_bus/enable" },
-    } },
-    { "idle",       "CPU Idle",         0, {
-        { REQ,      "/sys/kernel/debug/tracing/events/power/cpu_idle/enable" },
-    } },
-    { "disk",       "Disk I/O",         0, {
-        { REQ,      "/sys/kernel/debug/tracing/events/ext4/ext4_sync_file_enter/enable" },
-        { REQ,      "/sys/kernel/debug/tracing/events/ext4/ext4_sync_file_exit/enable" },
-        { REQ,      "/sys/kernel/debug/tracing/events/block/block_rq_issue/enable" },
-        { REQ,      "/sys/kernel/debug/tracing/events/block/block_rq_complete/enable" },
-        { OPT,      "/sys/kernel/debug/tracing/events/ext4/ext4_da_write_begin/enable" },
-        { OPT,      "/sys/kernel/debug/tracing/events/ext4/ext4_da_write_end/enable" },
-    } },
-    { "mmc",        "eMMC commands",    0, {
-        { REQ,      "/sys/kernel/debug/tracing/events/mmc/enable" },
-    } },
-    { "load",       "CPU Load",         0, {
-        { REQ,      "/sys/kernel/debug/tracing/events/cpufreq_interactive/enable" },
-    } },
-    { "sync",       "Synchronization",  0, {
-        // linux kernel < 4.9
-        { OPT,      "/sys/kernel/debug/tracing/events/sync/enable" },
-        // linux kernel == 4.9.x
-        { OPT,      "/sys/kernel/debug/tracing/events/fence/enable" },
-        // linux kernel > 4.9
-        { OPT,      "/sys/kernel/debug/tracing/events/dma_fence/enable" },
-    } },
-    { "workq",      "Kernel Workqueues", 0, {
-        { REQ,      "/sys/kernel/debug/tracing/events/workqueue/enable" },
-    } },
-    { "regulators",  "Voltage and Current Regulators", 0, {
-        { REQ,      "/sys/kernel/debug/tracing/events/regulator/enable" },
-    } },
-    { "pagecache",  "Page cache", 0, {
-        { REQ,      "/sys/kernel/debug/tracing/events/filemap/enable" },
-    } },
-#ifdef TTRACE_PROFILE_MOBILE
-#elif defined TTRACE_PROFILE_TV
-    { "system",       "System",                 TTRACE_TAG_SYSTEM, { } },
-    { "perftest",     "For Performance test",   TTRACE_TAG_PERFTEST, { } },
-#elif defined TTRACE_PROFILE_WEARABLE
-#endif
-};
-
-/* Command line options */
-static int g_traceDurationSeconds = 5;
-static bool g_traceOverwrite = false;
-static int g_traceBufferSizeKB = 2048;
-static bool g_compress = false;
-static bool g_nohup = false;
-static int g_initialSleepSecs = 0;
-static const char* g_kernelTraceFuncs = nullptr;
-static const char* g_debugAppCmdLine = "";
-
-/* Global state */
-static bool g_traceAborted = false;
-static bool g_categoryEnables[NELEM(k_categories)] = {};
-static bool g_append_trace = false;
-static bool g_backup_trace = false;
-
-/* Save excluded tags list */
-uint64_t excludedTags;
-
-static bool setCategoryEnable(const char* name, bool enable);
-
-/* Sys file paths */
-static const char* k_traceClockPath =
-    "/sys/kernel/debug/tracing/trace_clock";
-
-static const char* k_traceBufferSizePath =
-    "/sys/kernel/debug/tracing/buffer_size_kb";
-
-static const char* k_tracingOverwriteEnablePath =
-    "/sys/kernel/debug/tracing/options/overwrite";
-
-static const char* k_currentTracerPath =
-    "/sys/kernel/debug/tracing/current_tracer";
-
-static const char* k_printTgidPath =
-    "/sys/kernel/debug/tracing/options/print-tgid";
-
-static const char* k_funcgraphAbsTimePath =
-    "/sys/kernel/debug/tracing/options/funcgraph-abstime";
-
-static const char* k_funcgraphCpuPath =
-    "/sys/kernel/debug/tracing/options/funcgraph-cpu";
-
-static const char* k_funcgraphProcPath =
-    "/sys/kernel/debug/tracing/options/funcgraph-proc";
-
-static const char* k_funcgraphFlatPath =
-    "/sys/kernel/debug/tracing/options/funcgraph-flat";
-
-static const char* k_funcgraphDurationPath =
-    "/sys/kernel/debug/tracing/options/funcgraph-duration";
-
-static const char* k_ftraceFilterPath =
-    "/sys/kernel/debug/tracing/set_ftrace_filter";
-
-static const char* k_tracingOnPath =
-    "/sys/kernel/debug/tracing/tracing_on";
-
-static const char* k_tracePath =
-    "/sys/kernel/debug/tracing/trace";
-
-// Check whether a file exists.
-static bool fileExists(const char* filename) {
-    return access(filename, F_OK) != -1;
-}
-
-// Check whether a file is writable.
-static bool fileIsWritable(const char* filename) {
-    return access(filename, W_OK) != -1;
-}
-
-// Truncate a file.
-static bool truncateFile(const char* path)
-{
-    // This uses creat rather than truncate because some of the debug kernel
-    // device nodes (e.g. k_ftraceFilterPath) currently aren't changed by
-    // calls to truncate, but they are cleared by calls to creat.
-    int traceFD = creat(path, 0);
-    if (traceFD == -1) {
-        fprintf(stderr, "error truncating %s: %s (%d)\n", path,
-            strerror_r(errno, str_error, sizeof(str_error)), errno);
-        return false;
-    }
-
-    close(traceFD);
-
-    return true;
-}
-
-static bool _writeStr(const char* filename, const char* str, int flags)
-{
-    int fd = open(filename, flags);
-    if (fd == -1) {
-        fprintf(stderr, "error opening %s: %s (%d)\n", filename,
-                strerror_r(errno, str_error, sizeof(str_error)), errno);
-        return false;
-    }
-
-    bool ok = true;
-    ssize_t len = strlen(str);
-    if (write(fd, str, len) != len) {
-        fprintf(stderr, "error writing to %s: %s (%d)\n", filename,
-                strerror_r(errno, str_error, sizeof(str_error)), errno);
-        ok = false;
-    }
-
-    close(fd);
-
-    return ok;
-}
-
-// Write a string to a file, returning true if the write was successful.
-static bool writeStr(const char* filename, const char* str)
-{
-    return _writeStr(filename, str, O_WRONLY);
-}
-
-// Append a string to a file, returning true if the write was successful.
-static bool appendStr(const char* filename, const char* str)
-{
-    return _writeStr(filename, str, O_APPEND|O_WRONLY);
-}
-
-// Enable or disable a kernel option by writing a "1" or a "0" into a /sys
-// file.
-static bool setKernelOptionEnable(const char* filename, bool enable)
-{
-    return writeStr(filename, enable ? "1" : "0");
-}
-
-// Check whether the category is supported on the device with the current
-// rootness.  A category is supported only if all its required /sys/ files are
-// writable and if enabling the category will enable one or more tracing tags
-// or /sys/ files.
-static bool isCategorySupported(const TracingCategory& category)
-{
-    bool ok = category.tags != 0;
-    for (int i = 0; i < MAX_SYS_FILES; i++) {
-        const char* path = category.sysfiles[i].path;
-        bool req = category.sysfiles[i].required == REQ;
-        if (path != nullptr) {
-            if (req) {
-                if (!fileIsWritable(path)) {
-                    return false;
-                } else {
-                    ok = true;
-                }
-            } else {
-                ok |= fileIsWritable(path);
-            }
-        }
-    }
-    return ok;
-}
-
-// Check whether the category would be supported on the device if the user
-// were root.  This function assumes that root is able to write to any file
-// that exists.  It performs the same logic as isCategorySupported, but it
-// uses file existance rather than writability in the /sys/ file checks.
-static bool isCategorySupportedForRoot(const TracingCategory& category)
-{
-    bool ok = category.tags != 0;
-    for (int i = 0; i < MAX_SYS_FILES; i++) {
-        const char* path = category.sysfiles[i].path;
-        bool req = category.sysfiles[i].required == REQ;
-        if (path != nullptr) {
-            if (req) {
-                if (!fileExists(path)) {
-                    return false;
-                } else {
-                    ok = true;
-                }
-            } else {
-                ok |= fileExists(path);
-            }
-        }
-    }
-    return ok;
-}
-
-// Enable or disable overwriting of the kernel trace buffers.  Disabling this
-// will cause tracing to stop once the trace buffers have filled up.
-static bool setTraceOverwriteEnable(bool enable)
-{
-    return setKernelOptionEnable(k_tracingOverwriteEnablePath, enable);
-}
-
-// Enable or disable kernel tracing.
-static bool setTracingEnabled(bool enable)
-{
-    return setKernelOptionEnable(k_tracingOnPath, enable);
-}
-
-// Clear the contents of the kernel trace.
-static bool clearKernelTrace()
-{
-    return truncateFile(k_tracePath);
-}
-
-// Set the size of the kernel's trace buffer in kilobytes.
-static bool setTraceBufferSizeKB(int size)
-{
-    char str[32] = "1";
-    if (size < 1) {
-        size = 1;
-    }
-    snprintf(str, 32, "%d", size);
-    return writeStr(k_traceBufferSizePath, str);
-}
-
-// Set the clock to the best available option while tracing. Use 'boot' if it's
-// available; otherwise, use 'mono'. If neither are available use 'global'.
-// Any write to the trace_clock sysfs file will reset the buffer, so only
-// update it if the requested value is not the current value.
-static bool setBestClock(bool enable)
-{
-    std::ifstream clockFile(k_traceClockPath, std::ios::in);
-    std::string clockStr((std::istreambuf_iterator<char>(clockFile)),
-        std::istreambuf_iterator<char>());
-    std::string newClock;
-
-    if (enable == false)
-        return writeStr(k_traceClockPath, "local");
-
-    if (clockStr.find("boot") != std::string::npos)
-        newClock = "boot";
-    else if (clockStr.find("mono") != std::string::npos)
-        newClock = "mono";
-    else
-        newClock = "global";
-
-    size_t begin = clockStr.find('[') + 1;
-    size_t end = clockStr.find(']');
-    if (newClock.compare(0, std::string::npos, clockStr, begin, end-begin) == 0)
-        return true;
-
-    return writeStr(k_traceClockPath, newClock.c_str());
-}
-
-static bool setPrintTgidEnableIfPresent(bool enable)
-{
-    if (fileExists(k_printTgidPath)) {
-        return setKernelOptionEnable(k_printTgidPath, enable);
-    }
-    return true;
-}
-
-static bool getBootupTagStr(char* bootupTagStr, int strSize)
-{
-    if(fileExists(BOOTUP_TRACE)) {
-        FILE *bootupTagFile = nullptr;
-
-        bootupTagFile = fopen(BOOTUP_TRACE, "r");
-        if (bootupTagFile == nullptr) {
-            return false;
-        }
-        if (fgets(bootupTagStr, strSize, bootupTagFile) == NULL) {
-            fclose(bootupTagFile);
-            return false;
-        }
-        fclose(bootupTagFile);
-        fprintf(stderr, "[Info] Loaded tags: %s, bufsize: %d\n",\
-                bootupTagStr, strSize);
-        return true;
-    }
-    return false;
-}
-
-static void setBootupTags(char* bootupTagStr)
-{
-    char* tagPtr;
-    char* nextTagPtr;
-    tagPtr = strtok_r(bootupTagStr, " \n", &nextTagPtr);
-    while (tagPtr != nullptr) {
-        setCategoryEnable(tagPtr, true);
-        fprintf(stderr, "[Info] Tag %s enabled\n", tagPtr);
-        tagPtr = strtok_r(nullptr, " \n", &nextTagPtr);
-    }
-    return;
-}
-
-static bool initEnabledTagFile()
-{
-    uint64_t *sm_for_enabled_tag = nullptr;
-    int fd = -1;
-
-    if(fileExists(ENABLED_TAG_FILE)) {
-        fprintf(stderr, "[Info] T-trace has been already initailized\n");
-        return true; //atrace has been already initailized.
-    }
-
-    fd = open("/tmp/tmp_tag", O_CREAT | O_RDWR | O_CLOEXEC, 0600);
-    if(fd < 0){
-        fprintf(stderr, "Fail to open enabled_tag file: %s(%d)\n", strerror_r(errno, str_error, sizeof(str_error)), errno);
-        return false;
-    }
-
-    if (ftruncate(fd, sizeof(uint64_t)) < 0) {
-        fprintf(stderr, "ftruncate() failed(%s)\n", strerror_r(errno, str_error, sizeof(str_error)));
-        close(fd);
-        return false;
-    }
-    sm_for_enabled_tag = (uint64_t*)mmap(nullptr, sizeof(uint64_t), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
-
-    if(sm_for_enabled_tag == MAP_FAILED) {
-        fprintf(stderr, "mmap() failed(%s)\n", strerror_r(errno, str_error, sizeof(str_error)));
-        close(fd);
-        return false;
-    }
-
-    memset(sm_for_enabled_tag, 0, sizeof(uint64_t));
-    if(-1 == rename("/tmp/tmp_tag", ENABLED_TAG_FILE)) {
-        fprintf(stderr, "Fail to rename enabled_tag file: %s(%d)\n", strerror_r(errno, str_error, sizeof(str_error)), errno);
-    }
-
-    munmap(sm_for_enabled_tag, sizeof(uint64_t));
-    close(fd);
-    return true;
-}
-
-// Set the trace tags that userland tracing uses, and poke the running
-// processes to pick up the new value.
-static bool setTagsProperty(uint64_t tags)
-{
-    uint64_t *sm_for_enabled_tag = nullptr;
-    int fd = -1;
-
-    // atrace normal mode
-    fd = open(ENABLED_TAG_FILE, O_RDWR | O_CLOEXEC, 0600);
-    if(fd < 0){
-        fprintf(stderr, "Fail to open enabled_tag file: %s(%d)\n", strerror_r(errno, str_error, sizeof(str_error)), errno);
-        return false;
-    }
-    sm_for_enabled_tag = (uint64_t*)mmap(nullptr, sizeof(uint64_t), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
-    if(sm_for_enabled_tag == MAP_FAILED) {
-        fprintf(stderr, "mmap() failed(%s)\n", strerror_r(errno, str_error, sizeof(str_error)));
-        close(fd);
-        return false;
-    }
-    *sm_for_enabled_tag = tags;
-
-    // For debug
-    // fprintf(stderr, "Enabled TAGs: %u\n", (uint32_t)*sm_for_enabled_tag);
-    //
-    munmap(sm_for_enabled_tag, sizeof(uint64_t));
-    close(fd);
-    return true;
-}
-
-// Disable all /sys/ enable files.
-static bool disableKernelTraceEvents() {
-    bool ok = true;
-    for (int i = 0; i < NELEM(k_categories); i++) {
-        const TracingCategory &c = k_categories[i];
-        for (int j = 0; j < MAX_SYS_FILES; j++) {
-            const char* path = c.sysfiles[j].path;
-            if (path != nullptr && fileIsWritable(path)) {
-                ok &= setKernelOptionEnable(path, false);
-            }
-        }
-    }
-    return ok;
-}
-
-// Set the comma separated list of functions that the kernel is to trace.
-static bool setKernelTraceFuncs(const char* funcs)
-{
-    bool ok = true;
-    char *ptr[2];
-
-    if (funcs == nullptr || funcs[0] == '\0') {
-        // Disable kernel function tracing.
-        if (fileIsWritable(k_currentTracerPath)) {
-            ok &= writeStr(k_currentTracerPath, "nop");
-        }
-        if (fileIsWritable(k_ftraceFilterPath)) {
-            ok &= truncateFile(k_ftraceFilterPath);
-        }
-    } else {
-        // Enable kernel function tracing.
-        ok &= writeStr(k_currentTracerPath, "function_graph");
-        ok &= setKernelOptionEnable(k_funcgraphAbsTimePath, true);
-        ok &= setKernelOptionEnable(k_funcgraphCpuPath, true);
-        ok &= setKernelOptionEnable(k_funcgraphProcPath, true);
-        ok &= setKernelOptionEnable(k_funcgraphFlatPath, true);
-        ok &= setKernelOptionEnable(k_funcgraphDurationPath, true);
-
-        // Set the requested filter functions.
-        ok &= truncateFile(k_ftraceFilterPath);
-        char* myFuncs = strdup(funcs);
-        char* func = strtok_r(myFuncs, ",", &ptr[0]);
-        while (func) {
-            ok &= appendStr(k_ftraceFilterPath, func);
-            func = strtok_r(NULL, ",", &ptr[1]);
-        }
-        free(myFuncs);
-    }
-
-    return ok;
-}
-
-// Enable tracing in the kernel.
-static bool startTrace()
-{
-    return setTracingEnabled(true);
-}
-
-// Set all the kernel tracing settings to the desired state for this trace
-// capture.
-static bool setUpTrace()
-{
-    bool ok = true;
-
-    // Set up the tracing options.
-    ok &= setTraceOverwriteEnable(g_traceOverwrite);
-    if(!g_append_trace) {
-        ok &= setTraceBufferSizeKB(g_traceBufferSizeKB);
-        ok &= setBestClock(true);
-        ok &= setKernelTraceFuncs(g_kernelTraceFuncs);
-    }
-    ok &= setPrintTgidEnableIfPresent(true);
-
-    // Set up the tags property.
-    uint64_t tags = 0;
-    if (g_categoryEnables[TAG_NONE_IDX]) tags = TTRACE_TAG_NEVER;
-    else {
-        for (int i = 0; i < NELEM(k_categories); i++) {
-            if (g_categoryEnables[i]) {
-                const TracingCategory &c = k_categories[i];
-                if ((c.tags & excludedTags) == 0)
-                    tags |= c.tags;
-            }
-        }
-        if (tags == 0 && excludedTags == 0) {
-            tags |= TTRACE_TAG_ALWAYS;
-        }
-        else if (tags == 0 && excludedTags != 0) {
-            excludedTags |= TTRACE_TAG_ALWAYS;
-            tags |= ~excludedTags;
-        }
-        else {
-            excludedTags |= TTRACE_TAG_ALWAYS;
-            tags &= ~excludedTags;
-        }
-        printf("Tags: 0x%" PRIx64 " excludedTags: 0x%" PRIx64 "\n", tags, excludedTags);
-    }
-
-    ok &= startTrace();
-    if(!g_append_trace) {
-        // Clear Kernel Trace
-        ok &= clearKernelTrace();
-
-        // Disable all the sysfs enables.  This is done as a separate loop from
-        // the enables to allow the same enable to exist in multiple categories.
-        ok &= disableKernelTraceEvents();
-    }
-    ok &= setTagsProperty(tags);
-
-    // Enable all the sysfs enables that are in an enabled category.
-    for (int i = 0; i < NELEM(k_categories); i++) {
-        if (g_categoryEnables[i]) {
-            const TracingCategory &c = k_categories[i];
-            for (int j = 0; j < MAX_SYS_FILES; j++) {
-                const char* path = c.sysfiles[j].path;
-                bool required = c.sysfiles[j].required == REQ;
-                if (path != nullptr) {
-                    if (fileIsWritable(path)) {
-                        ok &= setKernelOptionEnable(path, true);
-                    } else if (required) {
-                        fprintf(stderr, "error writing file %s\n", path);
-                        ok = false;
-                    }
-                }
-            }
-        }
-    }
-
-    return ok;
-}
-
-// Reset all the kernel tracing settings to their default state.
-static void cleanUpTrace()
-{
-    // Disable all tracing that we're able to.
-    disableKernelTraceEvents();
-
-    // Set the options back to their defaults.
-    setTraceOverwriteEnable(true);
-    setTraceBufferSizeKB(1);
-    setBestClock(false);
-    setPrintTgidEnableIfPresent(false);
-    setKernelTraceFuncs(nullptr);
-}
-
-// Disable tracing in the kernel.
-static void stopTrace()
-{
-    setTagsProperty(0);
-    setTracingEnabled(false);
-}
-
-// Read the current kernel trace and write it to stdout.
-static void dumpTrace(bool startup)
-{
-    int backup_fd = -1;
-    int traceFD = -1;
-
-    traceFD = open(k_tracePath, O_RDWR);
-    if (traceFD == -1) {
-        fprintf(stderr, "error opening %s: %s (%d)\n", k_tracePath,
-                strerror_r(errno, str_error, sizeof(str_error)), errno);
-        return;
-    }
-
-    if(startup) {
-        backup_fd = open(BACKUP_TRACE, O_CREAT|O_RDWR|O_TRUNC, 0600);
-        if (backup_fd == -1) {
-            fprintf(stderr, "error opening %s: %s (%d)\n", BACKUP_TRACE,
-                    strerror_r(errno, str_error, sizeof(str_error)), errno);
-            close(traceFD);
-            return;
-        }
-    }
-
-    if (g_compress) {
-        z_stream zs;
-        int result, flush;
-
-        bzero(&zs, sizeof(zs));
-        result = deflateInit(&zs, Z_DEFAULT_COMPRESSION);
-        if (result != Z_OK) {
-            fprintf(stderr, "error initializing zlib: %d\n", result);
-            close(traceFD);
-            if (backup_fd > -1)
-                close(backup_fd);
-            return;
-        }
-
-        const size_t bufSize = 64*1024;
-        std::unique_ptr<uint8_t[]> in(new uint8_t[bufSize]);
-        std::unique_ptr<uint8_t[]> out(new uint8_t[bufSize]);
-        if ((in == nullptr) || (out == nullptr)) {
-            fprintf(stderr, "Could not allocate memory");
-            close(traceFD);
-            if (backup_fd > -1)
-                close(backup_fd);
-            return;
-        }
-        flush = Z_NO_FLUSH;
-
-        zs.next_out = reinterpret_cast<Bytef*>(out.get());
-        zs.avail_out = bufSize;
-
-        do {
-
-            if (zs.avail_in == 0) {
-                // More input is needed.
-                result = read(traceFD, in.get(), bufSize);
-                if (result < 0) {
-                    fprintf(stderr, "error reading trace: %s (%d)\n",
-                            strerror_r(errno, str_error, sizeof(str_error)), errno);
-                    result = Z_STREAM_END;
-                    break;
-                } else if (result == 0) {
-                    flush = Z_FINISH;
-                } else {
-                    zs.next_in = reinterpret_cast<Bytef*>(in.get());
-                    zs.avail_in = result;
-                }
-            }
-
-            if (zs.avail_out == 0) {
-                // Need to write the output.
-                if(startup)
-                    result = write(backup_fd, out.get(), bufSize);
-                else
-                    result = write(STDOUT_FILENO, out.get(), bufSize);
-
-                if ((size_t)result < bufSize) {
-                    fprintf(stderr, "error writing deflated trace: %s (%d)\n",
-                            strerror_r(errno, str_error, sizeof(str_error)), errno);
-                    result = Z_STREAM_END; // skip deflate error message
-                    zs.avail_out = bufSize; // skip the final write
-                    break;
-                }
-                zs.next_out = reinterpret_cast<Bytef*>(out.get());
-                zs.avail_out = bufSize;
-            }
-
-        } while ((result = deflate(&zs, flush)) == Z_OK);
-
-        if (result != Z_STREAM_END) {
-            fprintf(stderr, "error deflating trace: %s\n", zs.msg);
-        }
-
-        if (zs.avail_out < bufSize) {
-            size_t bytes = bufSize - zs.avail_out;
-            if(startup)
-                result = write(backup_fd, out.get(), bytes);
-            else
-                result = write(STDOUT_FILENO, out.get(), bytes);
-
-            if ((size_t)result < bytes) {
-                fprintf(stderr, "error writing deflated trace: %s (%d)\n",
-                        strerror_r(errno, str_error, sizeof(str_error)), errno);
-            }
-        }
-
-        result = deflateEnd(&zs);
-        if (result != Z_OK) {
-            fprintf(stderr, "error cleaning up zlib: %d\n", result);
-        }
-    } else {
-        ssize_t sent = 0;
-        if (startup)
-            while ((sent = sendfile(backup_fd, traceFD, nullptr, 64*1024*1024)) > 0);
-        else
-            while ((sent = sendfile(STDOUT_FILENO, traceFD, nullptr, 64*1024*1024)) > 0);
-
-        if (sent == -1) {
-            fprintf(stderr, "error dumping trace: %s (%d)\n", strerror_r(errno, str_error, sizeof(str_error)),
-                    errno);
-        }
-    }
-
-    if (backup_fd > -1)
-        close(backup_fd);
-    close(traceFD);
-}
-
-static void handleSignal(int signo)
-{
-    if (!g_nohup) {
-        g_traceAborted = true;
-    }
-}
-
-static void registerSigHandler()
-{
-    struct sigaction sa;
-    sigemptyset(&sa.sa_mask);
-    sa.sa_flags = 0;
-    sa.sa_handler = handleSignal;
-    sigaction(SIGHUP, &sa, nullptr);
-    sigaction(SIGINT, &sa, nullptr);
-    sigaction(SIGQUIT, &sa, nullptr);
-    sigaction(SIGTERM, &sa, nullptr);
-}
-
-static bool setCategoryEnable(const char* name, bool enable)
-{
-    for (int i = 0; i < NELEM(k_categories); i++) {
-        const TracingCategory& c = k_categories[i];
-        if (strcmp(name, c.name) == 0) {
-            if (isCategorySupported(c)) {
-                g_categoryEnables[i] = enable;
-                return true;
-            } else {
-                if (isCategorySupportedForRoot(c)) {
-                    fprintf(stderr, "error: category \"%s\" requires root "
-                            "privileges.\n", name);
-                } else {
-                    fprintf(stderr, "error: category \"%s\" is not supported "
-                            "on this device.\n", name);
-                }
-                return false;
-            }
-        }
-    }
-    fprintf(stderr, "error: unknown tracing category \"%s\"\n", name);
-    return false;
-}
-
-static void listSupportedCategories()
-{
-    for (int i = 0; i < NELEM(k_categories); i++) {
-        if(i==TAG_NONE_IDX) continue;
-        const TracingCategory& c = k_categories[i];
-        if (isCategorySupported(c)) {
-            printf("  %10s - %s\n", c.name, c.longname);
-        }
-    }
-}
-
-// Print the command usage help to stderr.
-static void showHelp(const char *cmd)
-{
-    fprintf(stderr, "usage: %s [options] [categories...]\n", cmd);
-    fprintf(stderr, "options include:\n"
-            "  -b N            use a trace buffer size of N KB\n"
-            "  -c              trace into a circular buffer\n"
-            "  -e category     specify a category to exclude [default None]\n"
-            "                   example, $ atrace -e wm -e am -e gfx\n"
-            "  -k fname,...    trace the listed kernel functions\n"
-            "  -n              ignore signals\n"
-            "  -s N            sleep for N seconds before tracing [default 0]\n"
-            "  -t N            trace for N seconds [defualt 5]\n"
-            "  -z              compress the trace dump\n"
-            "  --async_start   start circular trace and return immediatly\n"
-            "  --async_dump    dump the current contents of circular trace buffer\n"
-            "  --async_stop    stop tracing and dump the current contents of circular\n"
-            "                  trace buffer\n"
-            "  --append        append traces to the existing traces. do not clear the trace buffer \n"
-            "                  and kernel trace events set\n"
-            "  --backup        back up the existing traces to /tmp/trace.backup and then clear the trace buffer\n"
-            "  --list_categories\n"
-            "                  list the available tracing categories\n"
-           );
-}
-
-int main(int argc, char **argv)
-{
-    bool async = false;
-    bool traceStart = true;
-    bool traceStop = true;
-    bool traceDump = true;
-
-    char strBuf[128];
-
-    // Global Variable Initialization
-    excludedTags = 0ULL;
-
-    if (argc == 2 && 0 == strcmp(argv[1], "--help")) {
-        showHelp(argv[0]);
-        exit(0);
-    }
-
-    for (;;) {
-        int ret;
-        int option_index = 0;
-        static struct option long_options[] = {
-            {"async_start",     no_argument, nullptr,  0 },
-            {"async_stop",      no_argument, nullptr,  0 },
-            {"async_dump",      no_argument, nullptr,  0 },
-            {"list_categories", no_argument, nullptr,  0 },
-            {"init_exec",       no_argument, nullptr,  0 },
-            {"append",          no_argument, nullptr,  0 },
-            {"backup",          no_argument, nullptr,  0 },
-            {0,                 0,           nullptr,  0 }
-        };
-        ret = getopt_long(argc, argv, "b:ck:e:ns:t:z",
-                long_options, &option_index);
-        if (ret < 0) {
-            for (int i = optind; i < argc; i++) {
-                if (!setCategoryEnable(argv[i], true)) {
-                    fprintf(stderr, "error enabling tracing category \"%s\"\n", argv[i]);
-                    exit(1);
-                }
-            }
-            break;
-        }
-
-        switch(ret) {
-            case 'a':
-                g_debugAppCmdLine = optarg;
-                break;
-
-            case 'b':
-                g_traceBufferSizeKB = atoi(optarg);
-                break;
-
-            case 'c':
-                g_traceOverwrite = true;
-                break;
-
-            case 'e':
-                setCategoryEnable(optarg, true);
-                for (int i = 0; i < NELEM(k_categories); i++) {
-                    const TracingCategory &c = k_categories[i];
-                    if (!strcmp(c.name, optarg)) {
-                        excludedTags |= c.tags;
-                    }
-                }
-                break;
-
-            case 'k':
-                g_kernelTraceFuncs = optarg;
-                break;
-
-            case 'n':
-                g_nohup = true;
-                break;
-
-            case 's':
-                g_initialSleepSecs = atoi(optarg);
-                break;
-
-            case 't':
-                g_traceDurationSeconds = atoi(optarg);
-                break;
-
-            case 'z':
-                g_compress = true;
-                break;
-
-            case 0:
-                if (!strcmp(long_options[option_index].name, "list_categories")) {
-                    listSupportedCategories();
-                    exit(0);
-                }
-                if (!strcmp(long_options[option_index].name, "async_start")) {
-                    async = true;
-                    traceStop = false;
-                    traceDump = false;
-                    g_traceOverwrite = true;
-                } else if (!strcmp(long_options[option_index].name, "async_stop")) {
-                    async = true;
-                    traceStart = false;
-                    traceStop = true;
-                } else if (!strcmp(long_options[option_index].name, "async_dump")) {
-                    async = true;
-                    traceStart = false;
-                    traceStop = false;
-                } else if (!strcmp(long_options[option_index].name, "list_categories")) {
-                    listSupportedCategories();
-                    exit(0);
-                } else if (!strcmp(long_options[option_index].name, "init_exec")) {
-                    fprintf(stderr, "[Info] Initailize T-trace\n");
-                    if(!initEnabledTagFile()) {
-                        exit(-1);
-                    }
-                    if (getBootupTagStr(strBuf, sizeof(strBuf))) {
-                        async = true;
-                        traceStop = false;
-                        traceDump = false;
-                        g_traceOverwrite = true;
-                        setBootupTags(strBuf);
-                    }
-                    else {
-                        exit(0);
-                    }
-                } else if (!strcmp(long_options[option_index].name, "append")) {
-                    g_append_trace = true;
-                } else if (!strcmp(long_options[option_index].name, "backup")) {
-                    g_backup_trace = true;
-                }
-                break;
-
-            default:
-                fprintf(stderr, "\n");
-                showHelp(argv[0]);
-                exit(0);
-                break;
-        }
-    }
-
-    registerSigHandler();
-
-    if (g_initialSleepSecs > 0) {
-        sleep(g_initialSleepSecs);
-    }
-
-    bool ok = true;
-    if(traceStart && g_backup_trace) {
-        //before start tracing by atrace, backup existig traces
-        stopTrace();
-        dumpTrace(true);
-    }
-    if (!(async && !g_traceOverwrite)) {
-        ok &= setUpTrace();
-    }
-    if (ok && traceStart) {
-        // For debug
-        // printf("capturing trace...");
-        //
-        fflush(stdout);
-
-        // We clear the trace after starting it because tracing gets enabled for
-        // each CPU individually in the kernel. Having the beginning of the trace
-        // contain entries from only one CPU can cause "begin" entries without a
-        // matching "end" entry to show up if a task gets migrated from one CPU to
-        // another.
-        if (ok && !async) {
-            // Sleep to allow the trace to be captured.
-            struct timespec timeLeft;
-            timeLeft.tv_sec = g_traceDurationSeconds;
-            timeLeft.tv_nsec = 0;
-            do {
-                if (g_traceAborted) {
-                    break;
-                }
-            } while (nanosleep(&timeLeft, &timeLeft) == -1 && errno == EINTR);
-        }
-    }
-
-    // Stop the trace and restore the default settings.
-    if (traceStop)
-        stopTrace();
-
-    if (ok && traceDump) {
-        if (!g_traceAborted) {
-            printf(" done\nTRACE:\n");
-            fflush(stdout);
-            dumpTrace(false);
-        } else {
-            printf("\ntrace aborted.\n");
-            fflush(stdout);
-        }
-        clearKernelTrace();
-    } else if (!ok) {
-        fprintf(stderr, "unable to start tracing\n");
-    }
-
-    // Reset the trace buffer size to 1.
-    if (traceStop)
-        cleanUpTrace();
-
-    return g_traceAborted ? 1 : 0;
-}
diff --git a/src/atrace_helper/LICENSE b/src/atrace_helper/LICENSE
deleted file mode 100644 (file)
index 8dc3504..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//    * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//    * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//    * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/src/atrace_helper/atrace_process_dump.cc b/src/atrace_helper/atrace_process_dump.cc
deleted file mode 100644 (file)
index bf28553..0000000
+++ /dev/null
@@ -1,248 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "atrace_process_dump.h"
-
-#include <inttypes.h>
-#include <stdint.h>
-
-#include <limits>
-
-#include "file_utils.h"
-#include "logging.h"
-#include "procfs_utils.h"
-
-namespace {
-
-const int kMemInfoIntervalMs = 100;  // 100ms-ish.
-
-}  // namespace
-
-AtraceProcessDump::AtraceProcessDump() {
-  self_pid_ = static_cast<int>(getpid());
-  dump_count_ = 0;
-  out_ = nullptr;
-  snapshot_timestamp_ = 0;
-  dump_interval_in_timer_ticks_ = 0;
-}
-
-AtraceProcessDump::~AtraceProcessDump() {
-}
-
-void AtraceProcessDump::SetDumpInterval(int interval_ms) {
-  CHECK(interval_ms >= kMemInfoIntervalMs);
-  dump_interval_in_timer_ticks_ = interval_ms / kMemInfoIntervalMs;
-  // Approximately equals to kMemInfoIntervalMs.
-  int tick_interval_ms = interval_ms / dump_interval_in_timer_ticks_;
-  snapshot_timer_ = std::unique_ptr<time_utils::PeriodicTimer>(
-      new time_utils::PeriodicTimer(tick_interval_ms));
-}
-
-void AtraceProcessDump::RunAndPrintJson(FILE* stream) {
-  out_ = stream;
-
-  fprintf(out_, "{\"start_ts\": \"%" PRIu64 "\", \"snapshots\":[\n",
-      time_utils::GetTimestamp());
-
-  CHECK(snapshot_timer_);
-  snapshot_timer_->Start();
-
-  int tick_count = std::numeric_limits<int>::max();
-  if (dump_count_ > 0)
-    tick_count = dump_count_ * dump_interval_in_timer_ticks_;
-
-  for (int tick = 0; tick < tick_count; tick++) {
-    if (tick > 0) {
-      if (!snapshot_timer_->Wait())
-        break;  // Interrupted by signal.
-      fprintf(out_, ",\n");
-    }
-    TakeAndSerializeMemInfo();
-    if (!(tick % dump_interval_in_timer_ticks_)) {
-      fprintf(out_, ",\n");
-      TakeGlobalSnapshot();
-      SerializeSnapshot();
-    }
-    fflush(out_);
-  }
-
-  fprintf(out_, "],\n");
-  SerializePersistentProcessInfo();
-  fprintf(out_, "}\n");
-  fflush(out_);
-  Cleanup();
-}
-
-void AtraceProcessDump::Stop() {
-  CHECK(snapshot_timer_);
-  snapshot_timer_->Stop();
-}
-
-void AtraceProcessDump::TakeGlobalSnapshot() {
-  snapshot_.clear();
-  snapshot_timestamp_ = time_utils::GetTimestamp();
-
-  file_utils::ForEachPidInProcPath("/proc", [this](int pid) {
-    // Skip if not regognized as a process.
-    if (!UpdatePersistentProcessInfo(pid))
-      return;
-    const ProcessInfo* process = processes_[pid].get();
-    // Snapshot can't be obtained for kernel workers.
-    if (process->in_kernel)
-      return;
-
-    ProcessSnapshot* process_snapshot = new ProcessSnapshot();
-    snapshot_[pid] = std::unique_ptr<ProcessSnapshot>(process_snapshot);
-
-    process_snapshot->pid = pid;
-    procfs_utils::ReadOomStats(process_snapshot);
-    procfs_utils::ReadPageFaultsAndCpuTimeStats(process_snapshot);
-
-    if (ShouldTakeFullDump(process)) {
-      process_snapshot->memory.ReadFullStats(pid);
-    } else {
-      process_snapshot->memory.ReadLightStats(pid);
-    }
-  });
-}
-
-bool AtraceProcessDump::UpdatePersistentProcessInfo(int pid) {
-  if (!processes_.count(pid)) {
-    if (procfs_utils::ReadTgid(pid) != pid)
-      return false;
-    processes_[pid] = procfs_utils::ReadProcessInfo(pid);
-  }
-  ProcessInfo* process = processes_[pid].get();
-  procfs_utils::ReadProcessThreads(process);
-
-  if (full_dump_mode_ == FullDumpMode::kOnlyWhitelisted &&
-      full_dump_whitelist_.count(process->name)) {
-    full_dump_whitelisted_pids_.insert(pid);
-  }
-  return true;
-}
-
-bool AtraceProcessDump::ShouldTakeFullDump(const ProcessInfo* process) {
-  if (full_dump_mode_ == FullDumpMode::kAllProcesses)
-    return !process->in_kernel && (process->pid != self_pid_);
-  if (full_dump_mode_ == FullDumpMode::kAllJavaApps)
-    return process->is_app;
-  if (full_dump_mode_ == FullDumpMode::kDisabled)
-    return false;
-  return full_dump_whitelisted_pids_.count(process->pid) > 0;
-}
-
-void AtraceProcessDump::SerializeSnapshot() {
-  fprintf(out_, "{\"ts\":\"%" PRIu64 "\",\"memdump\":{\n",
-          snapshot_timestamp_);
-  for (auto it = snapshot_.begin(); it != snapshot_.end();) {
-    const ProcessSnapshot* process = it->second.get();
-    const ProcessMemoryStats* mem = &process->memory;
-    fprintf(out_, "\"%d\":{", process->pid);
-
-    fprintf(out_, "\"vm\":%" PRIu64 ",\"rss\":%" PRIu64,
-            mem->virt_kb(), mem->rss_kb());
-
-    fprintf(out_, ",\"oom_sc\":%d,\"oom_sc_adj\":%d"
-                  ",\"min_flt\":%lu,\"maj_flt\":%lu"
-                  ",\"utime\":%lu,\"stime\":%lu",
-            process->oom_score, process->oom_score_adj,
-            process->minor_faults, process->major_faults,
-            process->utime, process->stime);
-
-    if (mem->full_stats_available()) {
-      fprintf(out_, ",\"pss\":%" PRIu64 ",\"swp\":%" PRIu64
-                    ",\"pc\":%" PRIu64 ",\"pd\":%" PRIu64
-                    ",\"sc\":%" PRIu64 ",\"sd\":%" PRIu64,
-              mem->pss_kb(), mem->swapped_kb(),
-              mem->private_clean_kb(), mem->private_dirty_kb(),
-              mem->shared_clean_kb(), mem->shared_dirty_kb());
-    }
-
-    // Memory maps are too heavy to serialize. Enable only in whitelisting mode.
-    if (print_smaps_ &&
-        full_dump_mode_ == FullDumpMode::kOnlyWhitelisted &&
-        mem->full_stats_available() &&
-        full_dump_whitelisted_pids_.count(process->pid)) {
-
-      fprintf(out_, ", \"mmaps\":[");
-      size_t n_mmaps = mem->mmaps_count();
-      for (size_t k = 0; k < n_mmaps; ++k) {
-        const ProcessMemoryStats::MmapInfo* mm = mem->mmap(k);
-        fprintf(out_,
-                "{\"vm\":\"%" PRIx64 "-%" PRIx64 "\","
-                "\"file\":\"%s\",\"flags\":\"%s\","
-                "\"pss\":%" PRIu64 ",\"rss\":%" PRIu64 ",\"swp\":%" PRIu64 ","
-                "\"pc\":%" PRIu64 ",\"pd\":%" PRIu64 ","
-                "\"sc\":%" PRIu64 ",\"sd\":%" PRIu64 "}",
-                mm->start_addr, mm->end_addr,
-                mm->mapped_file, mm->prot_flags,
-                mm->pss_kb, mm->rss_kb, mm->swapped_kb,
-                mm->private_clean_kb, mm->private_dirty_kb,
-                mm->shared_clean_kb, mm->shared_dirty_kb);
-        if (k < n_mmaps - 1)
-          fprintf(out_, ", ");
-      }
-      fprintf(out_, "]");
-    }
-
-    if (++it != snapshot_.end())
-      fprintf(out_, "},\n");
-    else
-      fprintf(out_, "}}\n");
-  }
-  fprintf(out_, "}");
-}
-
-void AtraceProcessDump::SerializePersistentProcessInfo() {
-  fprintf(out_, "\"processes\":{");
-  for (auto it = processes_.begin(); it != processes_.end();) {
-    const ProcessInfo* process = it->second.get();
-    fprintf(out_, "\"%d\":{", process->pid);
-    fprintf(out_, "\"name\":\"%s\"", process->name);
-
-    if (!process->in_kernel) {
-      fprintf(out_, ",\"exe\":\"%s\",", process->exe);
-      fprintf(out_, "\"threads\":{\n");
-      const auto threads = &process->threads;
-      for (auto thread_it = threads->begin(); thread_it != threads->end();) {
-        const ThreadInfo* thread = &(thread_it->second);
-        fprintf(out_, "\"%d\":{", thread->tid);
-        fprintf(out_, "\"name\":\"%s\"", thread->name);
-
-        if (++thread_it != threads->end())
-          fprintf(out_, "},\n");
-        else
-          fprintf(out_, "}\n");
-      }
-      fprintf(out_, "}");
-    }
-
-    if (++it != processes_.end())
-      fprintf(out_, "},\n");
-    else
-      fprintf(out_, "}\n");
-  }
-  fprintf(out_, "}");
-}
-
-void AtraceProcessDump::TakeAndSerializeMemInfo() {
-  std::map<std::string, uint64_t> mem_info;
-  CHECK(procfs_utils::ReadMemInfoStats(&mem_info));
-  fprintf(out_, "{\"ts\":\"%" PRIu64 "\",\"meminfo\":{\n",
-          time_utils::GetTimestamp());
-  for (auto it = mem_info.begin(); it != mem_info.end(); ++it) {
-    if (it != mem_info.begin())
-      fprintf(out_, ",");
-    fprintf(out_, "\"%s\":%" PRIu64, it->first.c_str(), it->second);
-  }
-  fprintf(out_, "}}");
-}
-
-void AtraceProcessDump::Cleanup() {
-  processes_.clear();
-  snapshot_.clear();
-  full_dump_whitelisted_pids_.clear();
-  snapshot_timer_ = nullptr;
-}
diff --git a/src/atrace_helper/atrace_process_dump.h b/src/atrace_helper/atrace_process_dump.h
deleted file mode 100644 (file)
index 280a18a..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef ATRACE_PROCESS_DUMP_H_
-#define ATRACE_PROCESS_DUMP_H_
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#include <memory>
-#include <set>
-#include <string>
-
-#include "logging.h"
-#include "process_info.h"
-#include "time_utils.h"
-
-// Program that collects processes, thread names, per-process memory stats and
-// other minor metrics from /proc filesystem. It's aimed to extend systrace
-// with more actionable number to hit performance issues.
-class AtraceProcessDump {
- public:
-  enum FullDumpMode {
-    kDisabled,
-    kAllProcesses,
-    kAllJavaApps,
-    kOnlyWhitelisted,
-  };
-
-  AtraceProcessDump();
-  ~AtraceProcessDump();
-
-  void RunAndPrintJson(FILE* stream);
-  void Stop();
-
-  void SetDumpInterval(int interval_ms);
-
-  // Negative number or zero means unlimited number of dumps.
-  void set_dump_count(int count) { dump_count_ = count; }
-
-  void set_full_dump_mode(FullDumpMode mode) { full_dump_mode_ = mode; }
-  void set_full_dump_whitelist(const std::set<std::string> &whitelist) {
-    CHECK(full_dump_mode_ == FullDumpMode::kOnlyWhitelisted);
-    full_dump_whitelist_ = whitelist;
-  }
-  void enable_print_smaps() { print_smaps_ = true; }
-
- private:
-  AtraceProcessDump(const AtraceProcessDump&) = delete;
-  void operator=(const AtraceProcessDump&) = delete;
-
-  using ProcessMap = std::map<int, std::unique_ptr<ProcessInfo>>;
-  using ProcessSnapshotMap = std::map<int, std::unique_ptr<ProcessSnapshot>>;
-
-  void TakeGlobalSnapshot();
-  void TakeAndSerializeMemInfo();
-  bool UpdatePersistentProcessInfo(int pid);
-  bool ShouldTakeFullDump(const ProcessInfo* process);
-  void SerializeSnapshot();
-  void SerializePersistentProcessInfo();
-  void Cleanup();
-
-  int self_pid_;
-  int dump_count_;
-  bool graphics_stats_ = false;
-  bool print_smaps_ = false;
-  FullDumpMode full_dump_mode_ = FullDumpMode::kDisabled;
-  std::set<std::string> full_dump_whitelist_;
-
-  FILE* out_;
-  ProcessMap processes_;
-  ProcessSnapshotMap snapshot_;
-  uint64_t snapshot_timestamp_;
-  std::set<int> full_dump_whitelisted_pids_;
-  std::unique_ptr<time_utils::PeriodicTimer> snapshot_timer_;
-  int dump_interval_in_timer_ticks_;
-};
-
-#endif  // ATRACE_PROCESS_DUMP_H_
diff --git a/src/atrace_helper/file_utils.cc b/src/atrace_helper/file_utils.cc
deleted file mode 100644 (file)
index 7d122d6..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "file_utils.h"
-
-#include <ctype.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-namespace {
-
-bool IsNumeric(const char* str) {
-  if (!str[0])
-    return false;
-  for (const char* c = str; *c; c++) {
-    if (!isdigit(*c))
-      return false;
-  }
-  return true;
-}
-
-}  // namespace
-
-namespace file_utils {
-
-void ForEachPidInProcPath(const char* proc_path,
-                          std::function<void(int)> predicate) {
-  DIR* root_dir = opendir(proc_path);
-  ScopedDir autoclose(root_dir);
-  struct dirent* child_dir;
-  while ((child_dir = readdir(root_dir))) {
-    if (child_dir->d_type != DT_DIR || !IsNumeric(child_dir->d_name))
-      continue;
-    predicate(atoi(child_dir->d_name));
-  }
-}
-
-ssize_t ReadFile(const char* path, char* buf, size_t length) {
-  buf[0] = '\0';
-  int fd = open(path, O_RDONLY);
-  if (fd < 0 && errno == ENOENT)
-    return -1;
-  ScopedFD autoclose(fd);
-  size_t tot_read = 0;
-  do {
-    ssize_t rsize = read(fd, buf + tot_read, length - tot_read);
-    if (rsize == 0)
-      break;
-    if (rsize == -1 && errno == EINTR)
-      continue;
-    else if (rsize < 0)
-      return -1;
-    tot_read += static_cast<size_t>(rsize);
-  } while (tot_read < length);
-  buf[tot_read < length ? tot_read : length - 1] = '\0';
-  return tot_read;
-}
-
-bool ReadFileTrimmed(const char* path, char* buf, size_t length) {
-  ssize_t rsize = ReadFile(path, buf, length);
-  if (rsize < 0)
-    return false;
-  for (ssize_t i = 0; i < rsize; i++) {
-    const char c = buf[i];
-    if (c == '\0' || c == '\r' || c == '\n') {
-      buf[i] = '\0';
-      break;
-    }
-    buf[i] = isprint(c) ? c : '?';
-  }
-  return true;
-}
-
-ssize_t ReadProcFile(int pid, const char* proc_file, char* buf, size_t length) {
-  char proc_path[128];
-  snprintf(proc_path, sizeof(proc_path), "/proc/%d/%s", pid, proc_file);
-  return ReadFile(proc_path, buf, length);
-}
-
-// Reads a single-line proc file, stripping out any \0, \r, \n and replacing
-// non-printable charcters with '?'.
-bool ReadProcFileTrimmed(int pid,
-                         const char* proc_file,
-                         char* buf,
-                         size_t length) {
-  char proc_path[128];
-  snprintf(proc_path, sizeof(proc_path), "/proc/%d/%s", pid, proc_file);
-  return ReadFileTrimmed(proc_path, buf, length);
-}
-
-LineReader::LineReader(char* buf, size_t size)
-    : ptr_(buf), end_(buf + size) {
-}
-
-LineReader::~LineReader() {
-}
-
-const char* LineReader::NextLine() {
-  if (ptr_ >= end_)
-    return nullptr;
-  const char* cur = ptr_;
-  char* next = strchr(ptr_, '\n');
-  if (next) {
-    *next = '\0';
-    ptr_ = next + 1;
-  } else {
-    ptr_ = end_;
-  }
-  return cur;
-}
-
-}  // namespace file_utils
diff --git a/src/atrace_helper/file_utils.h b/src/atrace_helper/file_utils.h
deleted file mode 100644 (file)
index 2b2556b..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef FILE_UTILS_H_
-#define FILE_UTILS_H_
-
-#include <dirent.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <functional>
-#include <map>
-#include <memory>
-
-#include "logging.h"
-
-namespace file_utils {
-
-// RAII classes for auto-releasing fd/dirs.
-template <typename RESOURCE_TYPE, int (*CLOSE_FN)(RESOURCE_TYPE)>
-struct ScopedResource {
-  explicit ScopedResource(RESOURCE_TYPE r) : r_(r) { CHECK(r); }
-  ~ScopedResource() { CLOSE_FN(r_); }
-  RESOURCE_TYPE r_;
-};
-
-using ScopedFD = ScopedResource<int, close>;
-using ScopedDir = ScopedResource<DIR*, closedir>;
-
-// Invokes predicate(pid) for each folder in |proc_path|/[0-9]+ which has
-// a numeric name (typically pids and tids).
-void ForEachPidInProcPath(const char* proc_path,
-                          std::function<void(int)> predicate);
-
-// Reads the contents of |path| fully into |buf| up to |length| chars.
-// |buf| is guaranteed to be null terminated.
-ssize_t ReadFile(const char* path, char* buf, size_t length);
-
-// Reads a single-line file, stripping out any \0, \r, \n and replacing
-// non-printable charcters with '?'. |buf| is guaranteed to be null terminated.
-bool ReadFileTrimmed(const char* path, char* buf, size_t length);
-
-// Convenience wrappers for /proc/|pid|/|proc_file| paths.
-ssize_t ReadProcFile(int pid, const char* proc_file, char* buf, size_t length);
-bool ReadProcFileTrimmed(int pid,
-                         const char* proc_file,
-                         char* buf,
-                         size_t length);
-
-// Takes a C string buffer and chunks it into lines without creating any
-// copies. It modifies the original buffer, by replacing \n with \0.
-class LineReader {
- public:
-  LineReader(char* buf, size_t size);
-  ~LineReader();
-
-  const char* NextLine();
-
- private:
-  char* ptr_;
-  char* end_;
-};
-
-}  // namespace file_utils
-
-#endif  // FILE_UTILS_H_
diff --git a/src/atrace_helper/logging.h b/src/atrace_helper/logging.h
deleted file mode 100644 (file)
index ecbb56b..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef LOGGING_H_
-#define LOGGING_H_
-
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#define CHECK_ARGS(COND, ERR)                                          \
-  "FAILED CHECK(%s) @ %s:%d (errno: %s)\n", #COND, __FILE__, __LINE__, \
-      strerror(ERR)
-
-#define CHECK(x)                                              \
-  do {                                                        \
-    if (!(x)) {                                               \
-      const int e = errno;                                    \
-      fprintf(stderr, "\n" CHECK_ARGS(x, e));                 \
-      fflush(stderr);                                         \
-      abort();                                                \
-    }                                                         \
-  } while (0)
-
-inline void LogError(const char* message) {
-  fprintf(stderr, "\n%s\n", message);
-  fflush(stderr);
-}
-
-#endif  // LOGGING_H_
diff --git a/src/atrace_helper/main.cc b/src/atrace_helper/main.cc
deleted file mode 100644 (file)
index 6079c00..0000000
+++ /dev/null
@@ -1,134 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <inttypes.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <memory>
-#include <set>
-#include <string>
-#include <sstream>
-
-#include "atrace_process_dump.h"
-#include "logging.h"
-
-#define PATH_MAX 256
-
-namespace {
-
-std::unique_ptr<AtraceProcessDump> g_prog;
-
-void ParseFullDumpConfig(const std::string& config, AtraceProcessDump* prog) {
-  using FullDumpMode = AtraceProcessDump::FullDumpMode;
-  if (config == "all") {
-    prog->set_full_dump_mode(FullDumpMode::kAllProcesses);
-  } else if (config == "apps") {
-    prog->set_full_dump_mode(FullDumpMode::kAllJavaApps);
-  } else {
-    std::set<std::string> whitelist;
-    std::istringstream ss(config);
-    std::string entry;
-    while (std::getline(ss, entry, ',')) {
-      whitelist.insert(entry);
-    }
-    if (whitelist.empty())
-      return;
-    prog->set_full_dump_mode(FullDumpMode::kOnlyWhitelisted);
-    prog->set_full_dump_whitelist(whitelist);
-  }
-}
-
-}  // namespace
-
-int main(int argc, char** argv) {
-  if (argc == 2 && !strcmp(argv[1], "--echo-ts")) {
-    // Used by clock sync marker to correct the difference between
-    // Linux monotonic clocks on the device and host.
-    printf("%" PRIu64 "\n", time_utils::GetTimestamp());
-    return 0;
-  }
-
-  bool background = false;
-  int dump_interval_ms = 5000;
-  char out_file[PATH_MAX] = {};
-  bool dump_to_file = false;
-  int count = -1;
-
-  AtraceProcessDump* prog = new AtraceProcessDump();
-  g_prog = std::unique_ptr<AtraceProcessDump>(prog);
-
-  if (geteuid()) {
-    fprintf(stderr, "Must run as root\n");
-    exit(EXIT_FAILURE);
-  }
-
-  int opt;
-  while ((opt = getopt(argc, argv, "bm:st:o:c:")) != -1) {
-    switch (opt) {
-      case 'b':
-        background = true;
-        break;
-      case 'm':
-        ParseFullDumpConfig(optarg, prog);
-        break;
-      case 's':
-        prog->enable_print_smaps();
-        break;
-      case 't':
-        dump_interval_ms = atoi(optarg);
-        CHECK(dump_interval_ms > 0);
-        break;
-      case 'c':
-        count = atoi(optarg);
-        CHECK(count > 0);
-        break;
-      case 'o':
-        strncpy(out_file, optarg, sizeof(out_file));
-        out_file[PATH_MAX - 1] = '\0';
-        dump_to_file = true;
-        break;
-      default:
-        fprintf(stderr,
-                "Usage: %s [-b] [-m full_dump_filter] [-s] "
-                "[-t dump_interval_ms] "
-                "[-c dumps_count] [-o out.json]\n",
-                argv[0]);
-        exit(EXIT_FAILURE);
-    }
-  }
-
-  prog->set_dump_count(count);
-  prog->SetDumpInterval(dump_interval_ms);
-
-  FILE* out_stream = stdout;
-  char tmp_file[PATH_MAX + 4];
-  if (dump_to_file) {
-    unlink(out_file);
-    snprintf(tmp_file, PATH_MAX + 4, "%s.tmp", out_file);
-    out_stream = fopen(tmp_file, "w");
-    CHECK(out_stream);
-  }
-
-  if (background) {
-    if (!dump_to_file) {
-      fprintf(stderr, "-b requires -o for output dump path.\n");
-      exit(EXIT_FAILURE);
-    }
-    printf("Continuing in background. kill -TERM to terminate the daemon.\n");
-    CHECK(daemon(0 /* nochdir */, 0 /* noclose */) == 0);
-  }
-
-  auto on_exit = [](int) { g_prog->Stop(); };
-  signal(SIGINT, on_exit);
-  signal(SIGTERM, on_exit);
-
-  prog->RunAndPrintJson(out_stream);
-  fclose(out_stream);
-
-  if (dump_to_file)
-    rename(tmp_file, out_file);
-}
diff --git a/src/atrace_helper/process_info.h b/src/atrace_helper/process_info.h
deleted file mode 100644 (file)
index 089e77e..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef PROCESS_INFO_H_
-#define PROCESS_INFO_H_
-
-#include <map>
-
-#include "process_memory_stats.h"
-
-struct ThreadInfo {
-  int tid;
-  char name[16];
-};
-
-struct ProcessInfo {
-  int pid;
-  bool in_kernel;
-  bool is_app;
-  char name[256];
-  char exe[256];
-  std::map<int, ThreadInfo> threads;
-};
-
-struct ProcessSnapshot {
-  int pid;
-  ProcessMemoryStats memory;
-  // OOM badness and tolerance (oom_adj is deprecated).
-  int oom_score;
-  int oom_score_adj;
-  // Page faults.
-  unsigned long minor_faults;
-  unsigned long major_faults;
-  // Time spent in userspace and in the kernel.
-  unsigned long utime;
-  unsigned long stime;
-};
-
-#endif  // PROCESS_INFO_H_
diff --git a/src/atrace_helper/process_memory_stats.cc b/src/atrace_helper/process_memory_stats.cc
deleted file mode 100644 (file)
index bcc0678..0000000
+++ /dev/null
@@ -1,124 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "process_memory_stats.h"
-
-#include <inttypes.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <memory>
-
-#include "file_utils.h"
-#include "logging.h"
-
-namespace {
-
-const int kKbPerPage = 4;
-
-const char kRss[] = "Rss";
-const char kPss[] = "Pss";
-const char kSwap[] = "Swap";
-const char kSharedClean[] = "Shared_Clean";
-const char kSharedDirty[] = "Shared_Dirty";
-const char kPrivateClean[] = "Private_Clean";
-const char kPrivateDirty[] = "Private_Dirty";
-
-bool ReadSmapsMetric(
-    const char* line, const char* metric, int metric_size, uint64_t* res) {
-  if (strncmp(line, metric, metric_size - 1))
-    return false;
-  if (line[metric_size - 1] != ':')
-    return false;
-  *res = strtoull(line + metric_size, nullptr, 10);
-  return true;
-}
-
-}  // namespace
-
-bool ProcessMemoryStats::ReadLightStats(int pid) {
-  char buf[64];
-  if (file_utils::ReadProcFile(pid, "statm", buf, sizeof(buf)) <= 0)
-    return false;
-  uint32_t vm_size_pages;
-  uint32_t rss_pages;
-  int res = sscanf(buf, "%u %u", &vm_size_pages, &rss_pages);
-  CHECK(res == 2);
-  rss_kb_ = (uint64_t)rss_pages * kKbPerPage;
-  virt_kb_ = (uint64_t)vm_size_pages * kKbPerPage;
-  return true;
-}
-
-bool ProcessMemoryStats::ReadFullStats(int pid) {
-  const size_t kBufSize = 8u * 1024 * 1024;
-  std::unique_ptr<char[]> buf(new char[kBufSize]);
-  ssize_t rsize = file_utils::ReadProcFile(pid, "smaps", &buf[0], kBufSize);
-  if (rsize <= 0)
-    return false;
-  MmapInfo* last_mmap_entry = nullptr;
-  std::unique_ptr<MmapInfo> new_mmap(new MmapInfo());
-  CHECK(mmaps_.empty());
-  CHECK(rss_kb_ == 0);
-
-  // Iterate over all lines in /proc/PID/smaps.
-  file_utils::LineReader rd(&buf[0], rsize);
-  for (const char* line = rd.NextLine(); line; line = rd.NextLine()) {
-    if (!line[0])
-      continue;
-    // Performance optimization (hack).
-    // Any header line starts with lowercase hex digit but subsequent lines
-    // start with uppercase letter.
-    if (line[0] < 'A' || line[0] > 'Z') {
-      // Note that the mapped file name ([stack]) is optional and won't be
-      // present on anonymous memory maps (hence res >= 3 below).
-      int res = sscanf(line,
-          "%" PRIx64 "-%" PRIx64 " %4s %*x %*[:0-9a-f] "
-          "%*[0-9a-f]%*[ \t]%127[^\n]",
-          &new_mmap->start_addr, &new_mmap->end_addr, new_mmap->prot_flags,
-          new_mmap->mapped_file);
-      last_mmap_entry = new_mmap.get();
-      CHECK(new_mmap->end_addr >= new_mmap->start_addr);
-      new_mmap->virt_kb =
-          (new_mmap->end_addr - new_mmap->start_addr) / 1024;
-      if (res == 3)
-        new_mmap->mapped_file[0] = '\0';
-      virt_kb_ += new_mmap->virt_kb;
-      mmaps_.push_back(std::move(new_mmap));
-      new_mmap.reset(new MmapInfo());
-    } else {
-      // The current line is a metrics line within a mmap entry, e.g.:
-      // Size:   4 kB
-      uint64_t size = 0;
-      CHECK(last_mmap_entry);
-      if (ReadSmapsMetric(line, kRss, sizeof(kRss), &size)) {
-        last_mmap_entry->rss_kb = size;
-        rss_kb_ += size;
-      } else if (ReadSmapsMetric(line, kPss, sizeof(kPss), &size)) {
-        last_mmap_entry->pss_kb = size;
-        pss_kb_ += size;
-      } else if (ReadSmapsMetric(line, kSwap, sizeof(kSwap), &size)) {
-        last_mmap_entry->swapped_kb = size;
-        swapped_kb_ += size;
-      } else if (ReadSmapsMetric(
-                     line, kSharedClean, sizeof(kSharedClean), &size)) {
-        last_mmap_entry->shared_clean_kb = size;
-        shared_clean_kb_ += size;
-      } else if (ReadSmapsMetric(
-                     line, kSharedDirty, sizeof(kSharedDirty), &size)) {
-        last_mmap_entry->shared_dirty_kb = size;
-        shared_dirty_kb_ += size;
-      } else if (ReadSmapsMetric(
-                     line, kPrivateClean, sizeof(kPrivateClean), &size)) {
-        last_mmap_entry->private_clean_kb = size;
-        private_clean_kb_ += size;
-      } else if (ReadSmapsMetric(
-                     line, kPrivateDirty, sizeof(kPrivateDirty), &size)) {
-        last_mmap_entry->private_dirty_kb = size;
-        private_dirty_kb_ += size;
-      }
-    }
-  }
-  full_stats_ = true;
-  return true;
-}
diff --git a/src/atrace_helper/process_memory_stats.h b/src/atrace_helper/process_memory_stats.h
deleted file mode 100644 (file)
index cb72c9c..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef PROCESS_MEMORY_STATS_H_
-#define PROCESS_MEMORY_STATS_H_
-
-#include <stdint.h>
-
-#include <memory>
-#include <vector>
-
-// Reads process memory stats from /proc/pid/{statm,smaps}.
-class ProcessMemoryStats {
- public:
-  struct MmapInfo {
-    char mapped_file[128] = {};
-    char prot_flags[5] = {};
-    uint64_t start_addr = 0;
-    uint64_t end_addr = 0;
-    uint64_t virt_kb = 0;
-    uint64_t pss_kb = 0;  // Proportional Set Size.
-    uint64_t rss_kb = 0;  // Resident Set Size.
-    uint64_t private_clean_kb = 0;
-    uint64_t private_dirty_kb = 0;
-    uint64_t shared_clean_kb = 0;
-    uint64_t shared_dirty_kb = 0;
-    uint64_t swapped_kb = 0;
-  };
-
-  ProcessMemoryStats() {}
-
-  bool ReadLightStats(int pid);
-  bool ReadFullStats(int pid);
-
-  // Available after ReadLightStats().
-  uint64_t virt_kb() const { return virt_kb_; }
-  uint64_t rss_kb() const { return rss_kb_; }
-
-  // Available after ReadFullStats().
-  bool full_stats_available() const { return full_stats_; }
-  uint64_t pss_kb() const { return pss_kb_; }
-  uint64_t private_clean_kb() const { return private_clean_kb_; }
-  uint64_t private_dirty_kb() const { return private_dirty_kb_; }
-  uint64_t shared_clean_kb() const { return shared_clean_kb_; }
-  uint64_t shared_dirty_kb() const { return shared_dirty_kb_; }
-  uint64_t swapped_kb() const { return swapped_kb_; }
-
-  size_t mmaps_count() const { return mmaps_.size(); }
-  const MmapInfo* mmap(size_t index) const { return mmaps_[index].get(); }
-
- private:
-  ProcessMemoryStats(const ProcessMemoryStats&) = delete;
-  void operator=(const ProcessMemoryStats&) = delete;
-
-  // Light stats.
-  uint64_t virt_kb_ = 0;
-  uint64_t rss_kb_ = 0;
-
-  // Full stats.
-  bool full_stats_ = false;
-  uint64_t pss_kb_ = 0;
-  uint64_t private_clean_kb_ = 0;
-  uint64_t private_dirty_kb_ = 0;
-  uint64_t shared_clean_kb_ = 0;
-  uint64_t shared_dirty_kb_ = 0;
-  uint64_t swapped_kb_ = 0;
-
-  std::vector<std::unique_ptr<const MmapInfo>> mmaps_;
-};
-
-#endif  // PROCESS_MEMORY_STATS_H_
diff --git a/src/atrace_helper/procfs_utils.cc b/src/atrace_helper/procfs_utils.cc
deleted file mode 100644 (file)
index 5726a24..0000000
+++ /dev/null
@@ -1,137 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "procfs_utils.h"
-
-#include <stdio.h>
-#include <string.h>
-
-#include "file_utils.h"
-#include "logging.h"
-
-using file_utils::ForEachPidInProcPath;
-using file_utils::ReadProcFile;
-using file_utils::ReadProcFileTrimmed;
-
-namespace procfs_utils {
-
-namespace {
-
-const char kJavaAppPrefix[] = "/system/bin/app_process";
-const char kZygotePrefix[] = "zygote";
-
-inline void ReadProcString(int pid, const char* path, char* buf, size_t size) {
-  if (!file_utils::ReadProcFileTrimmed(pid, path, buf, size))
-    buf[0] = '\0';
-}
-
-inline void ReadExePath(int pid, char* buf, size_t size) {
-  char exe_path[64];
-  snprintf(exe_path, sizeof(exe_path), "/proc/%d/exe", pid);
-  ssize_t res = readlink(exe_path, buf, size - 1);
-  if (res >= 0)
-    buf[res] = '\0';
-  else
-    buf[0] = '\0';
-}
-
-inline bool IsApp(const char* name, const char* exe) {
-  return strncmp(exe, kJavaAppPrefix, sizeof(kJavaAppPrefix) - 1) == 0 &&
-         strncmp(name, kZygotePrefix, sizeof(kZygotePrefix) - 1) != 0;
-}
-
-}  // namespace
-
-int ReadTgid(int pid) {
-  static const char kTgid[] = "\nTgid:";
-  char buf[512];
-  ssize_t rsize = ReadProcFile(pid, "status", buf, sizeof(buf));
-  if (rsize <= 0)
-    return -1;
-  const char* tgid_line = strstr(buf, kTgid);
-  CHECK(tgid_line);
-  return atoi(tgid_line + sizeof(kTgid) - 1);
-}
-
-std::unique_ptr<ProcessInfo> ReadProcessInfo(int pid) {
-  ProcessInfo* process = new ProcessInfo();
-  process->pid = pid;
-  ReadProcString(pid, "cmdline", process->name, sizeof(process->name));
-  if (process->name[0] != 0) {
-    ReadExePath(pid, process->exe, sizeof(process->exe));
-    process->is_app = IsApp(process->name, process->exe);
-  } else {
-    ReadProcString(pid, "comm", process->name, sizeof(process->name));
-    CHECK(process->name[0]);
-    process->in_kernel = true;
-  }
-  return std::unique_ptr<ProcessInfo>(process);
-}
-
-void ReadProcessThreads(ProcessInfo* process) {
-  if (process->in_kernel)
-    return;
-
-  char tasks_path[64];
-  snprintf(tasks_path, sizeof(tasks_path), "/proc/%d/task", process->pid);
-  ForEachPidInProcPath(tasks_path, [process](int tid) {
-    if (process->threads.count(tid))
-      return;
-    ThreadInfo thread = { tid, "" };
-    char task_comm[64];
-    snprintf(task_comm, sizeof(task_comm), "task/%d/comm", tid);
-    ReadProcString(process->pid, task_comm, thread.name, sizeof(thread.name));
-    if (thread.name[0] == '\0' && process->is_app)
-      strcpy(thread.name, "UI Thread");
-    process->threads[tid] = thread;
-  });
-}
-
-bool ReadOomStats(ProcessSnapshot* snapshot) {
-  char buf[64];
-  if (ReadProcFileTrimmed(snapshot->pid, "oom_score", buf, sizeof(buf)))
-    snapshot->oom_score = atoi(buf);
-  else
-    return false;
-  if (ReadProcFileTrimmed(snapshot->pid, "oom_score_adj", buf, sizeof(buf)))
-    snapshot->oom_score_adj = atoi(buf);
-  else
-    return false;
-  return true;
-}
-
-bool ReadPageFaultsAndCpuTimeStats(ProcessSnapshot* snapshot) {
-  char buf[512];
-  if (!ReadProcFileTrimmed(snapshot->pid, "stat", buf, sizeof(buf)))
-    return false;
-  int ret = sscanf(buf,
-      "%*d %*s %*c %*d %*d %*d %*d %*d %*u %lu %*u %lu %*u %lu %lu",
-      &snapshot->minor_faults, &snapshot->major_faults,
-      &snapshot->utime, &snapshot->stime);
-  printf("ret is %d[%s]\n", ret, buf);
-  CHECK(ret == 4);
-  return true;
-}
-
-bool ReadMemInfoStats(std::map<std::string, uint64_t>* mem_info) {
-  char buf[1024];
-  ssize_t rsize = file_utils::ReadFile("/proc/meminfo", buf, sizeof(buf));
-  if (rsize <= 0)
-    return false;
-
-  file_utils::LineReader reader(buf, rsize);
-  for (const char* line = reader.NextLine();
-       line && line[0];
-       line = reader.NextLine()) {
-
-    const char* pos_colon = strstr(line, ":");
-    if (pos_colon == nullptr)
-      continue;  // Should not happen.
-    std::string name(line, pos_colon - line);
-    (*mem_info)[name] = strtoull(&pos_colon[1], nullptr, 10);
-  }
-  return true;
-}
-
-}  // namespace procfs_utils
diff --git a/src/atrace_helper/procfs_utils.h b/src/atrace_helper/procfs_utils.h
deleted file mode 100644 (file)
index e5ce704..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef PROCFS_UTILS_H_
-#define PROCFS_UTILS_H_
-
-#include <map>
-#include <memory>
-#include <string>
-
-#include "process_info.h"
-
-namespace procfs_utils {
-
-// ProcFS doesn't necessarly distinguish PID vs. TID, but all threads of a
-// process have the same Thread Group ID which is equal to Process ID.
-int ReadTgid(int pid);
-
-std::unique_ptr<ProcessInfo> ReadProcessInfo(int pid);
-void ReadProcessThreads(ProcessInfo* process);
-
-bool ReadOomStats(ProcessSnapshot* snapshot);
-bool ReadPageFaultsAndCpuTimeStats(ProcessSnapshot* snapshot);
-
-bool ReadMemInfoStats(std::map<std::string, uint64_t>* mem_info);
-
-}  // namespace procfs_utils
-
-#endif  // PROCFS_UTILS_H_
diff --git a/src/atrace_helper/time_utils.cc b/src/atrace_helper/time_utils.cc
deleted file mode 100644 (file)
index afcc2fc..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "time_utils.h"
-
-#include <sys/time.h>
-#include <sys/timerfd.h>
-#include <time.h>
-#include <unistd.h>
-
-#include "logging.h"
-
-namespace time_utils {
-
-uint64_t GetTimestamp() {
-  struct timespec ts = {};
-  CHECK(clock_gettime(CLOCK_MONOTONIC_COARSE, &ts) == 0);
-  return ((uint64_t)ts.tv_sec * 1000) + ((uint64_t)ts.tv_nsec / 1000000ul);
-}
-
-PeriodicTimer::PeriodicTimer(int interval_ms) : interval_ms_(interval_ms) {
-  timer_fd_ = -1;
-}
-
-PeriodicTimer::~PeriodicTimer() {
-  Stop();
-}
-
-void PeriodicTimer::Start() {
-  Stop();
-  timer_fd_ = timerfd_create(CLOCK_MONOTONIC, 0);
-  CHECK(timer_fd_ >= 0);
-  int sec = interval_ms_ / 1000;
-  int nsec = (interval_ms_ % 1000) * 1000000;
-  struct itimerspec ts = {};
-  ts.it_value.tv_nsec = nsec;
-  ts.it_value.tv_sec = sec;
-  ts.it_interval.tv_nsec = nsec;
-  ts.it_interval.tv_sec = sec;
-  CHECK(timerfd_settime(timer_fd_, 0, &ts, nullptr) == 0);
-}
-
-void PeriodicTimer::Stop() {
-  if (timer_fd_ < 0)
-    return;
-  close(timer_fd_);
-  timer_fd_ = -1;
-}
-
-bool PeriodicTimer::Wait() {
-  if (timer_fd_ < 0)
-    return false;  // Not started yet.
-  uint64_t stub = 0;
-  int res = read(timer_fd_, &stub, sizeof(stub));
-  if (res < 0 && errno == EBADF)
-    return false;  // Interrupted by Stop().
-  CHECK(res > 0);
-  return true;
-}
-
-}  // namespace time_utils
diff --git a/src/atrace_helper/time_utils.h b/src/atrace_helper/time_utils.h
deleted file mode 100644 (file)
index 2319601..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TIME_UTILS_H_
-#define TIME_UTILS_H_
-
-#include <stdint.h>
-
-namespace time_utils {
-
-uint64_t GetTimestamp();
-
-class PeriodicTimer {
- public:
-  PeriodicTimer(int interval_ms);
-  ~PeriodicTimer();
-
-  void Start();
-  void Stop();
-  // Wait for next tick. Returns false if interrupted by Stop() or not started.
-  bool Wait();
-
- private:
-  PeriodicTimer(const PeriodicTimer&) = delete;
-  void operator=(const PeriodicTimer&) = delete;
-
-  const int interval_ms_;
-  int timer_fd_;
-};
-
-}  // namespace time_utils
-
-#endif  // TIME_UTILS_