" can be used to change target of sampling information.\n"
" The default options are: -e cpu-cycles -f 4000 -o perf.data.\n"
"-a System-wide collection.\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
"-b Enable take branch stack sampling. Same as '-j any'\n"
"-c count Set event sample period. It means recording one sample when\n"
" [count] events happen. Can't be used with -f/-F option.\n"
" This option is used to provide files with symbol table and\n"
" debug information, which are used for unwinding and dumping symbols.\n"
"-t tid1,tid2,... Record events on existing threads. Mutually exclusive with -a.\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
),
use_sample_freq_(false),
start_sampling_time_in_ns_(0),
sample_record_count_(0),
lost_record_count_(0),
- start_profiling_fd_(-1) {
+ start_profiling_fd_(-1),
+ in_app_context_(false) {
// Stop profiling if parent exits.
prctl(PR_SET_PDEATHSIG, SIGHUP, 0, 0, 0);
}
uint64_t sample_record_count_;
uint64_t lost_record_count_;
int start_profiling_fd_;
+ std::string app_package_name_;
+ bool in_app_context_;
};
bool RecordCommand::Run(const std::vector<std::string>& args) {
if (!ParseOptions(args, &workload_args)) {
return false;
}
+ if (!app_package_name_.empty() && !in_app_context_) {
+ // Some users want to profile non debuggable apps on rooted devices. If we use run-as,
+ // it will be impossible when using --app. So don't switch to app's context when we are
+ // root.
+ if (!IsRoot()) {
+ return RunInAppContext(app_package_name_, "record", args, workload_args.size(),
+ record_filename_);
+ }
+ }
if (event_selection_set_.empty()) {
if (!event_selection_set_.AddEventType(default_measured_event_type)) {
return false;
return false;
}
}
+ } else if (!app_package_name_.empty()) {
+ // If app process is not created, wait for it. This allows simpleperf starts before
+ // app process. In this way, we can have a better support of app start-up time profiling.
+ int pid = WaitForAppProcess(app_package_name_);
+ event_selection_set_.AddMonitoredProcesses({pid});
} else {
LOG(ERROR)
<< "No threads to monitor. Try `simpleperf help record` for help";
for (i = 0; i < args.size() && !args[i].empty() && 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] == "-b") {
branch_sampling_ = branch_sampling_type_map["any"];
} else if (args[i] == "-c") {
if (!event_selection_set_.AddEventGroup(event_types)) {
return false;
}
+ } else if (args[i] == "--in-app") {
+ in_app_context_ = true;
} else if (args[i] == "-j") {
if (!NextArgumentOrError(args, &i)) {
return false;