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
17 #include "TracingClient.h"
18 #include "perfetto_trace.pb.h"
19
20 #include <android-base/logging.h>
21
22 #include <fstream>
23 #include <string>
24
25 namespace android::tools::automotive::tracing {
26
27 // TODO: Using a secure channel.
getChannelCredentials()28 static std::shared_ptr<::grpc::ChannelCredentials> getChannelCredentials() {
29 return ::grpc::InsecureChannelCredentials();
30 }
31
TracingClient(const std::string & addr)32 TracingClient::TracingClient(const std::string& addr)
33 : mServiceAddr(addr),
34 mGrpcChannel(::grpc::CreateChannel(mServiceAddr, getChannelCredentials())),
35 mGrpcStub(tracing_vm_proto::TracingServer::NewStub(mGrpcChannel)) {}
36
StartTracing(const std::string & host_config,uint64_t & session_num)37 bool TracingClient::StartTracing(const std::string& host_config, uint64_t& session_num) {
38 ::grpc::ClientContext context;
39 tracing_vm_proto::StartTracingRequest request;
40 if (host_config.empty()) {
41 std::cerr << __func__ << ": missing HostConfigFile.\n";
42 return false;
43 }
44
45 std::ifstream config_file_stream(host_config, std::fstream::binary);
46 if (!config_file_stream) {
47 std::cerr << __func__ << ": file not found " << host_config << std::endl;
48 return false;
49 }
50
51 perfetto::protos::TraceConfig* trace_config = request.mutable_host_config();
52 if (trace_config->ParseFromIstream(&config_file_stream)) {
53 std::cerr << __func__ << ": faled to parse the host_config file " << std::endl;
54 return false;
55 }
56
57 tracing_vm_proto::RequestStatus request_status;
58 auto grpc_status = mGrpcStub->StartTracing(&context, request, &request_status);
59 if (!grpc_status.ok()) {
60 std::cerr << __func__ << ": failed due to grpc error: " << grpc_status.error_message()
61 << std::endl;
62 return false;
63 }
64 if (!request_status.is_ok()) {
65 std::cerr << __func__ << ": failed with error: " << request_status.error_str() << std::endl;
66 return false;
67 }
68
69 std::cout << __func__ << ": succeed for session_id "
70 << request_status.session_id().session_id();
71 session_num = request_status.session_id().session_id();
72 return true;
73 }
74
StopTracing(const uint64_t session_num)75 bool TracingClient::StopTracing(const uint64_t session_num) {
76 ::grpc::ClientContext context;
77 tracing_vm_proto::TracingSessionIdentifier session_id;
78 tracing_vm_proto::RequestStatus request_status;
79 session_id.set_session_id(session_num);
80 auto grpc_status = mGrpcStub->StopTracing(&context, session_id, &request_status);
81 if (!grpc_status.ok()) {
82 std::cerr << __func__ << ": for session_id " << session_num
83 << " failed due to grpc error: " << grpc_status.error_message() << std::endl;
84 return false;
85 }
86 if (!request_status.is_ok()) {
87 std::cerr << __func__ << ": for session_id " << session_num
88 << " failed with error code: " << request_status.error_str();
89 return false;
90 }
91
92 std::cout << __func__ << ": succeed for session_id " << session_num << std::endl;
93 return true;
94 }
95
GetTracingFile(const uint64_t session_num,const std::string & file_path)96 bool TracingClient::GetTracingFile(const uint64_t session_num, const std::string& file_path) {
97 if (file_path.empty()) {
98 std::cerr << __func__ << ": missing file_path.\n";
99 return false;
100 }
101 std::ofstream file_stream(file_path, std::fstream::binary);
102
103 if (!file_stream) {
104 std::cerr << __func__ << ": for session_id " << session_num << " failed to open file "
105 << file_path << std::endl;
106 return false;
107 }
108
109 ::grpc::ClientContext context;
110 tracing_vm_proto::TracingSessionIdentifier session_id;
111 session_id.set_session_id(session_num);
112 auto grpc_reader = mGrpcStub->GetTracingFile(&context, session_id);
113 tracing_vm_proto::TracingFileBuffer file_buffer;
114
115 while (grpc_reader->Read(&file_buffer)) {
116 const auto& write_buffer = file_buffer.buffer();
117 file_stream.write(write_buffer.c_str(), write_buffer.size());
118 }
119
120 auto grpcStatus = grpc_reader->Finish();
121 if (!grpcStatus.ok()) {
122 std::cerr << __func__ << " failed for session_id " << session_num
123 << "due to grpc error:" << grpcStatus.error_message() << std::endl;
124 return false;
125 }
126
127 return true;
128 }
129
130 } // namespace android::tools::automotive::tracing
131