OSDN Git Service

simpleperf: support "--app" option in record/stat command.
[android-x86/system-extras.git] / simpleperf / cmd_stat.cpp
index a0929bc..c1f21f6 100644 (file)
@@ -26,6 +26,7 @@
 #include <string>
 #include <vector>
 
+#include <android-base/file.h>
 #include <android-base/logging.h>
 #include <android-base/parsedouble.h>
 #include <android-base/strings.h>
@@ -273,6 +274,11 @@ class StatCommand : public Command {
 "       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"
+#if defined(__ANDROID__)
+"--app package_name    Profile the process of an Android application.\n"
+"                      On non-rooted devices, the app must be debuggable,\n"
+"                      because we use run-as to switch to the app's context.\n"
+#endif
 "--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"
@@ -298,6 +304,10 @@ class StatCommand : public Command {
 "-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"
+#if 0
+// Below options are only used internally and shouldn't be visible to the public.
+"--in-app         We are already running in the app's context.\n"
+#endif
                 // clang-format on
                 ),
         verbose_mode_(false),
@@ -306,7 +316,8 @@ class StatCommand : public Command {
         duration_in_sec_(0),
         interval_in_ms_(0),
         event_selection_set_(true),
-        csv_(false) {
+        csv_(false),
+        in_app_context_(false) {
     // Die if parent exits.
     prctl(PR_SET_PDEATHSIG, SIGHUP, 0, 0, 0);
   }
@@ -330,6 +341,8 @@ class StatCommand : public Command {
   EventSelectionSet event_selection_set_;
   std::string output_filename_;
   bool csv_;
+  std::string app_package_name_;
+  bool in_app_context_;
 };
 
 bool StatCommand::Run(const std::vector<std::string>& args) {
@@ -342,6 +355,12 @@ bool StatCommand::Run(const std::vector<std::string>& args) {
   if (!ParseOptions(args, &workload_args)) {
     return false;
   }
+  if (!app_package_name_.empty() && !in_app_context_) {
+    if (!IsRoot()) {
+      return RunInAppContext(app_package_name_, "stat", args, workload_args.size(),
+                             output_filename_);
+    }
+  }
   if (event_selection_set_.empty()) {
     if (!AddDefaultMeasuredEventTypes()) {
       return false;
@@ -364,6 +383,9 @@ bool StatCommand::Run(const std::vector<std::string>& args) {
     if (workload != nullptr) {
       event_selection_set_.AddMonitoredProcesses({workload->GetPid()});
       event_selection_set_.SetEnableOnExec(true);
+    } else if (!app_package_name_.empty()) {
+      int pid = WaitForAppProcess(app_package_name_);
+      event_selection_set_.AddMonitoredProcesses({pid});
     } else {
       LOG(ERROR)
           << "No threads to monitor. Try `simpleperf help stat` for help\n";
@@ -456,6 +478,11 @@ bool StatCommand::ParseOptions(const std::vector<std::string>& args,
   for (i = 0; i < args.size() && args[i].size() > 0 && args[i][0] == '-'; ++i) {
     if (args[i] == "-a") {
       system_wide_collection_ = true;
+    } else if (args[i] == "--app") {
+      if (!NextArgumentOrError(args, &i)) {
+        return false;
+      }
+      app_package_name_ = args[i];
     } else if (args[i] == "--cpu") {
       if (!NextArgumentOrError(args, &i)) {
         return false;
@@ -499,6 +526,8 @@ bool StatCommand::ParseOptions(const std::vector<std::string>& args,
       if (!event_selection_set_.AddEventGroup(event_types)) {
         return false;
       }
+    } else if (args[i] == "--in-app") {
+      in_app_context_ = true;
     } else if (args[i] == "--no-inherit") {
       child_inherit_ = false;
     } else if (args[i] == "-o") {