1 /*
2  * Copyright (C) 2022 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 #include "TracingClient.h"
17 #include "vsockinfo.h"
18 
19 #include <android-base/logging.h>
20 
21 #include <getopt.h>
22 #include <unistd.h>
23 
24 using ::android::hardware::automotive::utils::VsockConnectionInfo;
25 using ::android::tools::automotive::tracing::TracingClient;
26 
main(int argc,char * argv[])27 int main(int argc, char* argv[]) {
28     enum class Options {
29         OPT_SERVER_ADDR,
30         OPT_CMD,
31         OPT_HOST_CONFIG,
32         OPT_SESSION_ID,
33         OPT_FILE_DIR,
34     };
35     enum class TracingCommand {
36         INVALID_CMD_CODE,
37         START_TRACING,
38         STOP_TRACING,
39         GET_TRACING_FILE,
40     };
41     struct option options[] = {
42             {
43                     .name = "server_addr",
44                     .has_arg = 1,
45                     .flag = 0,
46                     .val = static_cast<int>(Options::OPT_SERVER_ADDR),
47             },
48             {
49                     .name = "cmd",
50                     .has_arg = 1,
51                     .flag = 0,
52                     .val = static_cast<int>(Options::OPT_CMD),
53             },
54             {
55                     .name = "host_config",
56                     .has_arg = 1,
57                     .flag = 0,
58                     .val = static_cast<int>(Options::OPT_HOST_CONFIG),
59             },
60             {
61                     .name = "session_id",
62                     .has_arg = 1,
63                     .flag = 0,
64                     .val = static_cast<int>(Options::OPT_SESSION_ID),
65             },
66             {
67                     .name = "dir",
68                     .has_arg = 1,
69                     .flag = 0,
70                     .val = static_cast<int>(Options::OPT_FILE_DIR),
71             },
72             {},
73     };
74 
75     std::string tracing_service_addr;
76     TracingCommand cmd_code = TracingCommand::INVALID_CMD_CODE;
77     std::string host_config;
78     std::string file_dir;
79     uint64_t session_id = 0;
80 
81     int opt_value;
82     int index = 0;
83     while ((opt_value = getopt_long_only(argc, argv, ":", options, &index)) != -1) {
84         switch (static_cast<Options>(opt_value)) {
85             case Options::OPT_SERVER_ADDR:
86                 tracing_service_addr = optarg;
87                 break;
88             case Options::OPT_CMD: {
89                 const auto optarg_str = std::string(optarg);
90                 if (optarg_str == "start") {
91                     cmd_code = TracingCommand::START_TRACING;
92                 } else if (optarg_str == "stop") {
93                     cmd_code = TracingCommand::STOP_TRACING;
94                 } else if (optarg_str == "get") {
95                     cmd_code = TracingCommand::GET_TRACING_FILE;
96                 } else {
97                     std::cerr << "tracing-client doesn't support command: " << optarg << std::endl;
98                     return -1;
99                 }
100                 break;
101             }
102             case Options::OPT_HOST_CONFIG:
103                 host_config = optarg;
104                 break;
105             case Options::OPT_FILE_DIR:
106                 file_dir = optarg;
107                 break;
108             case Options::OPT_SESSION_ID:
109                 session_id = std::stoull(optarg);
110                 break;
111             default:
112                 std::cerr << "tracing-client can't process option: " << argv[optind - 1]
113                           << std::endl;
114                 return -1;
115         }
116     }
117 
118     if (opt_value == -1 && optind < argc) {
119         std::cerr << "tracing-client doesn't support option: " << argv[optind - 1] << std::endl;
120         return -1;
121     }
122 
123     if (tracing_service_addr.empty()) {
124         const auto si = VsockConnectionInfo::fromRoPropertyStore(
125                 {
126                         "ro.boot.vendor.tracing.server.cid",
127                         "ro.vendor.tracing.server.cid",
128                 },
129                 {
130                         "ro.boot.vendor.tracing.server.port",
131                         "ro.vendor.tracing.server.port",
132                 });
133         if (!si) {
134             std::cerr << "tracing-client failed to get server connection cid/port." << std::endl;
135             return -1;
136         }
137         tracing_service_addr = si->str();
138     }
139 
140     TracingClient client(tracing_service_addr);
141     switch (cmd_code) {
142         case TracingCommand::START_TRACING: {
143             return client.StartTracing(host_config, session_id) ? 0 : -1;
144 
145             case TracingCommand::STOP_TRACING:
146                 return client.StopTracing(session_id) ? 0 : -1;
147 
148             case TracingCommand::GET_TRACING_FILE:
149                 return client.GetTracingFile(session_id, file_dir) ? 0 : -1;
150 
151             default:
152                 std::cerr << "tracing-client input has wrong command code "
153                           << static_cast<int>(cmd_code) << std::endl;
154                 return -1;
155         }
156     }
157 }
158