Merge "Fix clang-tidy performance warnings in libfec."
diff --git a/simpleperf/cmd_record.cpp b/simpleperf/cmd_record.cpp
index 6957767..c24042a 100644
--- a/simpleperf/cmd_record.cpp
+++ b/simpleperf/cmd_record.cpp
@@ -78,7 +78,8 @@
             "record", "record sampling info in perf.data",
             // clang-format off
 "Usage: simpleperf record [options] [command [command-args]]\n"
-"       Gather sampling information when running [command].\n"
+"       Gather sampling information of running [command]. And -a/-p/-t option\n"
+"       can be used to change target of sampling information.\n"
 "-a     System-wide collection.\n"
 "-b     Enable take branch stack sampling. Same as '-j any'\n"
 "-c count     Set event sample period. It means recording one sample when\n"
@@ -94,6 +95,9 @@
 "--dump-symbols  Dump symbols in perf.data. By default perf.data doesn't contain\n"
 "                symbol information for samples. This option is used when there\n"
 "                is no symbol information in report environment.\n"
+"--duration time_in_sec  Monitor for time_in_sec seconds instead of running\n"
+"                        [command]. Here time_in_sec may be any positive\n"
+"                        floating point number.\n"
 "-e event1[:modifier1],event2[:modifier2],...\n"
 "             Select the event list to sample. Use `simpleperf list` to find\n"
 "             all possible event names. Modifiers can be added to define how\n"
@@ -342,6 +346,7 @@
 bool RecordCommand::ParseOptions(const std::vector<std::string>& args,
                                  std::vector<std::string>* non_option_args) {
   std::set<pid_t> tid_set;
+  double duration_in_sec = 0;
   size_t i;
   for (i = 0; i < args.size() && !args[i].empty() && args[i][0] == '-'; ++i) {
     if (args[i] == "-a") {
@@ -403,6 +408,17 @@
       cpus_ = GetCpusFromString(args[i]);
     } else if (args[i] == "--dump-symbols") {
       dump_symbols_ = true;
+    } else if (args[i] == "--duration") {
+      if (!NextArgumentOrError(args, &i)) {
+        return false;
+      }
+      errno = 0;
+      char* endptr;
+      duration_in_sec = strtod(args[i].c_str(), &endptr);
+      if (duration_in_sec <= 0 || *endptr != '\0' || errno == ERANGE) {
+        LOG(ERROR) << "Invalid duration: " << args[i].c_str();
+        return false;
+      }
     } else if (args[i] == "-e") {
       if (!NextArgumentOrError(args, &i)) {
         return false;
@@ -544,11 +560,19 @@
     can_dump_kernel_symbols_ = false;
   }
 
-  if (non_option_args != nullptr) {
-    non_option_args->clear();
-    for (; i < args.size(); ++i) {
-      non_option_args->push_back(args[i]);
+  non_option_args->clear();
+  for (; i < args.size(); ++i) {
+    non_option_args->push_back(args[i]);
+  }
+  if (duration_in_sec != 0) {
+    if (!non_option_args->empty()) {
+      LOG(ERROR) << "Using --duration option while running a command is not "
+                    "supported.";
+      return false;
     }
+    non_option_args->insert(
+        non_option_args->end(),
+        {"sleep", android::base::StringPrintf("%f", duration_in_sec)});
   }
   return true;
 }
diff --git a/simpleperf/cmd_record_test.cpp b/simpleperf/cmd_record_test.cpp
index afd5bdd..8a750a6 100644
--- a/simpleperf/cmd_record_test.cpp
+++ b/simpleperf/cmd_record_test.cpp
@@ -313,3 +313,8 @@
 }
 
 TEST(record_cmd, symfs_option) { ASSERT_TRUE(RunRecordCmd({"--symfs", "/"})); }
+
+TEST(record_cmd, duration_option) {
+  TemporaryFile tmpfile;
+  ASSERT_TRUE(RecordCmd()->Run({"--duration", "1.2", "-o", tmpfile.path}));
+}
diff --git a/simpleperf/cmd_report_sample.cpp b/simpleperf/cmd_report_sample.cpp
index 9c407d3..e27fa99 100644
--- a/simpleperf/cmd_report_sample.cpp
+++ b/simpleperf/cmd_report_sample.cpp
@@ -78,7 +78,10 @@
         use_protobuf_(false),
         report_fp_(nullptr),
         coded_os_(nullptr),
-        sample_count_(0) {}
+        sample_count_(0) {
+    thread_tree_.ShowMarkForUnknownSymbol();
+    thread_tree_.ShowIpForUnknownSymbol();
+  }
 
   bool Run(const std::vector<std::string>& args) override;
 
diff --git a/simpleperf/cmd_report_test.cpp b/simpleperf/cmd_report_test.cpp
index d6231bf..e0b35bf 100644
--- a/simpleperf/cmd_report_test.cpp
+++ b/simpleperf/cmd_report_test.cpp
@@ -159,7 +159,7 @@
 TEST_F(ReportCommandTest, callgraph_option) {
   Report(CALLGRAPH_FP_PERF_DATA, {"-g"});
   ASSERT_TRUE(success);
-  ASSERT_TRUE(CheckCalleeMode(lines));
+  ASSERT_TRUE(CheckCallerMode(lines));
   Report(CALLGRAPH_FP_PERF_DATA, {"-g", "callee"});
   ASSERT_TRUE(success);
   ASSERT_TRUE(CheckCalleeMode(lines));
diff --git a/simpleperf/cmd_stat.cpp b/simpleperf/cmd_stat.cpp
index f5792f8..42be557 100644
--- a/simpleperf/cmd_stat.cpp
+++ b/simpleperf/cmd_stat.cpp
@@ -125,7 +125,7 @@
 
 class CounterSummaries {
  public:
-  explicit CounterSummaries(bool csv): csv_(csv) {}
+  explicit CounterSummaries(bool csv) : csv_(csv) {}
   void AddSummary(const CounterSummary& summary) {
     summaries_.push_back(summary);
   }
@@ -153,7 +153,8 @@
         if (other != nullptr && other->IsMonitoredAtTheSameTime(s)) {
           if (FindSummary(s.type_name, "") == nullptr) {
             AddSummary(CounterSummary(s.type_name, "", s.group_id,
-                                      s.count + other->count, s.scale, true, csv_));
+                                      s.count + other->count, s.scale, true,
+                                      csv_));
           }
         }
       }
@@ -179,11 +180,9 @@
 
     for (auto& s : summaries_) {
       if (csv_) {
-        fprintf(fp, "%s,%s,%s,(%.0lf%%)%s\n",
-                s.readable_count.c_str(),
-                s.Name().c_str(),
-                s.comment.c_str(),
-                1.0 / s.scale * 100, (s.auto_generated ? " (generated)," : ","));
+        fprintf(fp, "%s,%s,%s,(%.0lf%%)%s\n", s.readable_count.c_str(),
+                s.Name().c_str(), s.comment.c_str(), 1.0 / s.scale * 100,
+                (s.auto_generated ? " (generated)," : ","));
       } else {
         fprintf(fp, "  %*s  %-*s   # %-*s  (%.0lf%%)%s\n",
                 static_cast<int>(count_column_width), s.readable_count.c_str(),
@@ -219,7 +218,8 @@
       const CounterSummary* other = FindSummary("cpu-cycles", s.modifier);
       if (other != nullptr && other->IsMonitoredAtTheSameTime(s)) {
         double cpi = static_cast<double>(other->count) / s.count;
-        return android::base::StringPrintf("%lf%ccycles per instruction", cpi, sap_mid);
+        return android::base::StringPrintf("%lf%ccycles per instruction", cpi,
+                                           sap_mid);
       }
     }
     if (android::base::EndsWith(s.type_name, "-misses")) {
@@ -236,7 +236,8 @@
       if (other != nullptr && other->IsMonitoredAtTheSameTime(s) &&
           other->count != 0) {
         double miss_rate = static_cast<double>(s.count) / other->count;
-        return android::base::StringPrintf("%lf%%%cmiss rate", miss_rate * 100, sap_mid);
+        return android::base::StringPrintf("%lf%%%cmiss rate", miss_rate * 100,
+                                           sap_mid);
       }
     }
     double rate = s.count / (duration_in_sec / s.scale);
@@ -260,16 +261,19 @@
 class StatCommand : public Command {
  public:
   StatCommand()
-      : Command(
-            "stat", "gather performance counter information",
-            // clang-format off
+      : Command("stat", "gather performance counter information",
+                // clang-format off
 "Usage: simpleperf stat [options] [command [command-args]]\n"
-"    Gather performance counter information of running [command].\n"
+"       Gather performance counter information of running [command].\n"
+"       And -a/-p/-t option can be used to change target of counter information.\n"
 "-a           Collect system-wide information.\n"
 "--cpu cpu_item1,cpu_item2,...\n"
 "                 Collect information only on the selected cpus. cpu_item can\n"
 "                 be a cpu number like 1, or a cpu range like 0-3.\n"
 "--csv            Write report in comma separate form.\n"
+"--duration time_in_sec  Monitor for time_in_sec seconds instead of running\n"
+"                        [command]. Here time_in_sec may be any positive\n"
+"                        floating point number.\n"
 "-e event1[:modifier1],event2[:modifier2],...\n"
 "                 Select the event list to count. Use `simpleperf list` to find\n"
 "                 all possible event names. Modifiers can be added to define\n"
@@ -285,8 +289,8 @@
 "-p pid1,pid2,... Stat events on existing processes. Mutually exclusive with -a.\n"
 "-t tid1,tid2,... Stat events on existing threads. Mutually exclusive with -a.\n"
 "--verbose        Show result in verbose mode.\n"
-            // clang-format on
-            ),
+                // clang-format on
+                ),
         verbose_mode_(false),
         system_wide_collection_(false),
         child_inherit_(true),
@@ -399,6 +403,7 @@
 bool StatCommand::ParseOptions(const std::vector<std::string>& args,
                                std::vector<std::string>* non_option_args) {
   std::set<pid_t> tid_set;
+  double duration_in_sec = 0;
   size_t i;
   for (i = 0; i < args.size() && args[i].size() > 0 && args[i][0] == '-'; ++i) {
     if (args[i] == "-a") {
@@ -410,6 +415,17 @@
       cpus_ = GetCpusFromString(args[i]);
     } else if (args[i] == "--csv") {
       csv_ = true;
+    } else if (args[i] == "--duration") {
+      if (!NextArgumentOrError(args, &i)) {
+        return false;
+      }
+      errno = 0;
+      char* endptr;
+      duration_in_sec = strtod(args[i].c_str(), &endptr);
+      if (duration_in_sec <= 0 || *endptr != '\0' || errno == ERANGE) {
+        LOG(ERROR) << "Invalid duration: " << args[i].c_str();
+        return false;
+      }
     } else if (args[i] == "-e") {
       if (!NextArgumentOrError(args, &i)) {
         return false;
@@ -464,12 +480,24 @@
                   "used at the same time.";
     return false;
   }
+  if (system_wide_collection_ && !IsRoot()) {
+    LOG(ERROR) << "System wide profiling needs root privilege.";
+    return false;
+  }
 
-  if (non_option_args != nullptr) {
-    non_option_args->clear();
-    for (; i < args.size(); ++i) {
-      non_option_args->push_back(args[i]);
+  non_option_args->clear();
+  for (; i < args.size(); ++i) {
+    non_option_args->push_back(args[i]);
+  }
+  if (duration_in_sec != 0) {
+    if (!non_option_args->empty()) {
+      LOG(ERROR) << "Using --duration option while running a command is not "
+                    "supported.";
+      return false;
     }
+    non_option_args->insert(
+        non_option_args->end(),
+        {"sleep", android::base::StringPrintf("%f", duration_in_sec)});
   }
   return true;
 }
@@ -521,9 +549,8 @@
           counters_info.selection->event_type_modifier;
       for (auto& counter_info : counters_info.counters) {
         if (csv_) {
-          fprintf(fp,
-                  "%s,tid,%d,cpu,%d,count,%" PRIu64 ",time_enabled,%" PRIu64
-                  ",time running,%" PRIu64 ",id,%" PRIu64 ",\n",
+          fprintf(fp, "%s,tid,%d,cpu,%d,count,%" PRIu64 ",time_enabled,%" PRIu64
+                      ",time running,%" PRIu64 ",id,%" PRIu64 ",\n",
                   event_type.name.c_str(), counter_info.tid, counter_info.cpu,
                   counter_info.counter.value, counter_info.counter.time_enabled,
                   counter_info.counter.time_running, counter_info.counter.id);
diff --git a/simpleperf/cmd_stat_test.cpp b/simpleperf/cmd_stat_test.cpp
index 4d63498..2610926 100644
--- a/simpleperf/cmd_stat_test.cpp
+++ b/simpleperf/cmd_stat_test.cpp
@@ -109,3 +109,7 @@
   // Check if the summary of cpu-clock is generated.
   ASSERT_NE(s.npos, s.find("cpu-clock", pos));
 }
+
+TEST(stat_cmd, duration_option) {
+  ASSERT_TRUE(StatCmd()->Run({"--duration", "1.2"}));
+}
diff --git a/simpleperf/runtest/function_fork.cpp b/simpleperf/runtest/function_fork.cpp
index b813702..b1477a6 100644
--- a/simpleperf/runtest/function_fork.cpp
+++ b/simpleperf/runtest/function_fork.cpp
@@ -1,14 +1,20 @@
+#include <stdlib.h>
 #include <unistd.h>
 
 constexpr int LOOP_COUNT = 100000000;
 
+volatile int a[2];
 void ParentFunction() {
-  for (volatile int i = 0; i < LOOP_COUNT; ++i) {
+  volatile int* p = a + atoi("0");
+  for (int i = 0; i < LOOP_COUNT; ++i) {
+    *p = i;
   }
 }
 
 void ChildFunction() {
-  for (volatile int i = 0; i < LOOP_COUNT; ++i) {
+  volatile int* p = a + atoi("1");
+  for (int i = 0; i < LOOP_COUNT; ++i) {
+    *p = i;
   }
 }
 
diff --git a/simpleperf/runtest/runtest.py b/simpleperf/runtest/runtest.py
index e4cc0d2..33a3a6c 100644
--- a/simpleperf/runtest/runtest.py
+++ b/simpleperf/runtest/runtest.py
@@ -25,6 +25,8 @@
 The information of all runtests is stored in runtest.conf.
 """
 
+import os
+import os.path
 import re
 import subprocess
 import sys
@@ -314,6 +316,11 @@
 
   """Run perf test on device."""
 
+  def __init__(self, perf_path):
+    self._download(os.environ['OUT'] + '/system/xbin/' + perf_path,
+                   '/data/local/tmp')
+    self.perf_path = '/data/local/tmp/' + perf_path
+
   def _call(self, args, output_file=None):
     output_fh = None
     if output_file is not None:
@@ -324,6 +331,15 @@
     if output_fh is not None:
       output_fh.close()
 
+  def _download(self, file, to_dir):
+    args = ['adb', 'push', file, to_dir]
+    subprocess.check_call(args)
+
+  def record(self, test_executable_name, record_file, additional_options=[]):
+    self._download(os.environ['OUT'] + '/system/bin/' + test_executable_name,
+                   '/data/local/tmp')
+    super(DeviceRunner, self).record('/data/local/tmp/' + test_executable_name,
+                                     record_file, additional_options)
 
 class ReportAnalyzer(object):
 
@@ -497,7 +513,8 @@
 
 
 def runtest(host, device, normal, callgraph, selected_tests):
-  tests = load_config_file('runtest.conf')
+  tests = load_config_file(os.path.dirname(os.path.realpath(__file__)) + \
+                           '/runtest.conf')
   host_runner = HostRunner('simpleperf')
   device_runner = DeviceRunner('simpleperf')
   report_analyzer = ReportAnalyzer()
@@ -530,11 +547,11 @@
       host_runner.record(
           test.executable_name,
           'perf_g.data',
-          additional_options=['-g'])
+          additional_options=['-g', '-f', '1000'])
       host_runner.report(
           'perf_g.data',
           'perf_g.report',
-          additional_options=['-g'] + test.report_options)
+          additional_options=['-g', 'callee'] + test.report_options)
       result = report_analyzer.check_report_file(test, 'perf_g.report', True)
       print 'call-graph test %s on host %s' % (
           test.test_name, 'Succeeded' if result else 'Failed')
@@ -542,14 +559,16 @@
         exit(1)
 
     if device and callgraph:
+      # Decrease sampling frequency by -f 1000 to avoid losing records
+      # while recording call-graph.
       device_runner.record(
           test.executable_name,
           '/data/perf_g.data',
-          additional_options=['-g'])
+          additional_options=['-g', '-f', '1000'])
       device_runner.report(
           '/data/perf_g.data',
           'perf_g.report',
-          additional_options=['-g'] + test.report_options)
+          additional_options=['-g', 'callee'] + test.report_options)
       result = report_analyzer.check_report_file(test, 'perf_g.report', True)
       print 'call-graph test %s on device %s' % (
           test.test_name, 'Succeeded' if result else 'Failed')
diff --git a/simpleperf/runtest/two_functions.cpp b/simpleperf/runtest/two_functions.cpp
index 1511102..1d3e389 100644
--- a/simpleperf/runtest/two_functions.cpp
+++ b/simpleperf/runtest/two_functions.cpp
@@ -1,12 +1,19 @@
+#include <stdlib.h>
+
 constexpr int LOOP_COUNT = 100000000;
 
+volatile int a[2];
 void Function1() {
-  for (volatile int i = 0; i < LOOP_COUNT; ++i) {
+  volatile int* p = a + atoi("0");
+  for (int i = 0; i < LOOP_COUNT; ++i) {
+    *p = i;
   }
 }
 
 void Function2() {
-  for (volatile int i = 0; i < LOOP_COUNT; ++i) {
+  volatile int* p = a + atoi("1");
+  for (int i = 0; i < LOOP_COUNT; ++i) {
+    *p = i;
   }
 }
 
diff --git a/simpleperf/thread_tree.cpp b/simpleperf/thread_tree.cpp
index fafefa0..3a20ee7 100644
--- a/simpleperf/thread_tree.cpp
+++ b/simpleperf/thread_tree.cpp
@@ -228,7 +228,9 @@
   if (symbol == nullptr) {
     if (show_ip_for_unknown_symbol_) {
       std::string name = android::base::StringPrintf(
-          "%s[+%" PRIx64 "]", dso->FileName().c_str(), vaddr_in_file);
+          "%s%s[+%" PRIx64 "]",
+          (show_mark_for_unknown_symbol_ ? "*" : ""),
+          dso->FileName().c_str(), vaddr_in_file);
       dso->InsertSymbol(Symbol(name, vaddr_in_file, 1));
       symbol = dso->FindSymbol(vaddr_in_file);
       CHECK(symbol != nullptr);
diff --git a/simpleperf/thread_tree.h b/simpleperf/thread_tree.h
index a8d3fa0..5498df5 100644
--- a/simpleperf/thread_tree.h
+++ b/simpleperf/thread_tree.h
@@ -69,6 +69,7 @@
  public:
   ThreadTree()
       : show_ip_for_unknown_symbol_(false),
+        show_mark_for_unknown_symbol_(false),
         unknown_symbol_("unknown", 0,
                         std::numeric_limits<unsigned long long>::max()) {
     unknown_dso_ = Dso::CreateDso(DSO_ELF_FILE, "unknown");
@@ -94,6 +95,10 @@
   const Symbol* UnknownSymbol() const { return &unknown_symbol_; }
 
   void ShowIpForUnknownSymbol() { show_ip_for_unknown_symbol_ = true; }
+  void ShowMarkForUnknownSymbol() {
+    show_mark_for_unknown_symbol_ = true;
+    unknown_symbol_ = Symbol("*unknown", 0, ULLONG_MAX);
+  }
   // Clear thread and map information, but keep loaded dso information. It saves
   // the time to reload dso information.
   void ClearThreadAndMap();
@@ -120,6 +125,7 @@
   std::unordered_map<std::string, std::unique_ptr<Dso>> user_dso_tree_;
   std::unique_ptr<Dso> unknown_dso_;
   bool show_ip_for_unknown_symbol_;
+  bool show_mark_for_unknown_symbol_;
   Symbol unknown_symbol_;
   std::unordered_map<uint64_t, Dso*> dso_id_to_dso_map_;
 };
diff --git a/verity/Android.mk b/verity/Android.mk
index ffa4a2c..1a7351f 100644
--- a/verity/Android.mk
+++ b/verity/Android.mk
@@ -7,7 +7,7 @@
 LOCAL_SRC_FILES := verify_boot_signature.c
 LOCAL_MODULE_CLASS := EXECUTABLES
 LOCAL_MODULE_TAGS := optional
-LOCAL_SHARED_LIBRARIES := libcrypto-host
+LOCAL_SHARED_LIBRARIES := libcrypto
 LOCAL_C_INCLUDES += external/openssl/include system/extras/ext4_utils system/core/mkbootimg
 include $(BUILD_HOST_EXECUTABLE)
 
@@ -18,7 +18,7 @@
 LOCAL_SRC_FILES := generate_verity_key.c
 LOCAL_MODULE_CLASS := EXECUTABLES
 LOCAL_MODULE_TAGS := optional
-LOCAL_SHARED_LIBRARIES := libcrypto_utils libcrypto-host
+LOCAL_SHARED_LIBRARIES := libcrypto_utils libcrypto
 include $(BUILD_HOST_EXECUTABLE)
 
 include $(CLEAR_VARS)
@@ -85,7 +85,7 @@
 LOCAL_SRC_FILES := build_verity_tree.cpp
 LOCAL_MODULE_TAGS := optional
 LOCAL_STATIC_LIBRARIES := libsparse_host libz
-LOCAL_SHARED_LIBRARIES := libcrypto-host libbase
+LOCAL_SHARED_LIBRARIES := libcrypto libbase
 LOCAL_CFLAGS += -Wall -Werror
 include $(BUILD_HOST_EXECUTABLE)