• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <string>
18 #include <vector>
19 
20 #include "perfetto/base/logging.h"
21 #include "perfetto/ext/base/getopt.h"
22 #include "perfetto/ext/base/unix_task_runner.h"
23 #include "perfetto/ext/traced/traced.h"
24 #include "src/android_stats/statsd_logging_helper.h"
25 #include "src/perfetto_cmd/trigger_producer.h"
26 
27 namespace perfetto {
28 namespace {
29 
PrintUsage(const char * argv0)30 int PrintUsage(const char* argv0) {
31   PERFETTO_ELOG(R"(
32 Usage: %s TRIGGER...
33   -h|--help  Show this message
34 )",
35                 argv0);
36   return 1;
37 }
38 
39 }  // namespace
40 
TriggerPerfettoMain(int argc,char ** argv)41 int PERFETTO_EXPORT_ENTRYPOINT TriggerPerfettoMain(int argc, char** argv) {
42   static const option long_options[] = {{"help", no_argument, nullptr, 'h'},
43                                         {nullptr, 0, nullptr, 0}};
44 
45   // Set opterror to zero to disable |getopt_long| from printing an error and
46   // exiting when it encounters an unknown option. Instead, |getopt_long|
47   // will return '?' which we silently ignore.
48   //
49   // We prefer ths behaviour rather than erroring on unknown options because
50   // trigger_perfetto can be called by apps so it's command line API needs to
51   // be backward and forward compatible. If we introduce an option here which
52   // apps will use in the future, we don't want to cause errors on older
53   // platforms where the command line flag did not exist.
54   //
55   // This behaviour was introduced in Android S.
56   opterr = 0;
57 
58   std::vector<std::string> triggers_to_activate;
59   bool seen_unknown_arg = false;
60 
61   for (;;) {
62     int option = getopt_long(argc, argv, "h", long_options, nullptr);
63 
64     if (option == 'h')
65       return PrintUsage(argv[0]);
66 
67     if (option == '?') {
68       seen_unknown_arg = true;
69     }
70 
71     if (option == -1)
72       break;  // EOF.
73   }
74 
75   // See above for rationale on why we just ignore unknown args instead of
76   // exiting.
77   if (seen_unknown_arg) {
78     PERFETTO_ELOG("Ignoring unknown arguments. See --help for usage.");
79   }
80 
81   for (int i = optind; i < argc; i++)
82     triggers_to_activate.push_back(std::string(argv[i]));
83 
84   if (triggers_to_activate.empty()) {
85     PERFETTO_ELOG("At least one trigger must the specified.");
86     return PrintUsage(argv[0]);
87   }
88 
89   android_stats::MaybeLogTriggerEvents(
90       PerfettoTriggerAtom::kTriggerPerfettoTrigger, triggers_to_activate);
91 
92   bool finished_with_success = false;
93   base::UnixTaskRunner task_runner;
94   TriggerProducer producer(
95       &task_runner,
96       [&task_runner, &finished_with_success](bool success) {
97         finished_with_success = success;
98         task_runner.Quit();
99       },
100       &triggers_to_activate);
101   task_runner.Run();
102 
103   if (!finished_with_success) {
104     android_stats::MaybeLogTriggerEvents(
105         PerfettoTriggerAtom::kTriggerPerfettoTriggerFail, triggers_to_activate);
106     return 1;
107   }
108   return 0;
109 }
110 
111 }  // namespace perfetto
112