blob: 7697c03d74fddf2f56384fb43b5bd8585b1519c0 [file] [log] [blame]
Hao Chen32d46702023-04-10 15:59:50 -07001/*
2 * Copyright (C) 2023 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 "GRPCVehicleProxyServer.h"
18
19#include "ProtoMessageConverter.h"
20
21#include <grpc++/grpc++.h>
22
23#include <android-base/logging.h>
24
25#include <algorithm>
26#include <condition_variable>
27#include <mutex>
28#include <unordered_set>
29#include <utility>
30#include <vector>
31
32namespace android::hardware::automotive::vehicle::virtualization {
33
34std::atomic<uint64_t> GrpcVehicleProxyServer::ConnectionDescriptor::connection_id_counter_{0};
35
36static std::shared_ptr<::grpc::ServerCredentials> getServerCredentials() {
37 // TODO(chenhaosjtuacm): get secured credentials here
38 return ::grpc::InsecureServerCredentials();
39}
40
41GrpcVehicleProxyServer::GrpcVehicleProxyServer(std::string serverAddr,
42 std::unique_ptr<IVehicleHardware>&& hardware)
Yu Shanb02b7722024-06-18 17:38:11 -070043 : GrpcVehicleProxyServer(std::vector<std::string>({serverAddr}), std::move(hardware)){};
44
45GrpcVehicleProxyServer::GrpcVehicleProxyServer(std::vector<std::string> serverAddrs,
46 std::unique_ptr<IVehicleHardware>&& hardware)
47 : mServiceAddrs(std::move(serverAddrs)), mHardware(std::move(hardware)) {
Hao Chen32d46702023-04-10 15:59:50 -070048 mHardware->registerOnPropertyChangeEvent(
49 std::make_unique<const IVehicleHardware::PropertyChangeCallback>(
50 [this](std::vector<aidlvhal::VehiclePropValue> values) {
51 OnVehiclePropChange(values);
52 }));
53}
54
55::grpc::Status GrpcVehicleProxyServer::GetAllPropertyConfig(
56 ::grpc::ServerContext* context, const ::google::protobuf::Empty* request,
57 ::grpc::ServerWriter<proto::VehiclePropConfig>* stream) {
58 for (const auto& config : mHardware->getAllPropertyConfigs()) {
59 proto::VehiclePropConfig protoConfig;
60 proto_msg_converter::aidlToProto(config, &protoConfig);
61 if (!stream->Write(protoConfig)) {
62 return ::grpc::Status(::grpc::StatusCode::ABORTED, "Connection lost.");
63 }
64 }
65 return ::grpc::Status::OK;
66}
67
68::grpc::Status GrpcVehicleProxyServer::SetValues(::grpc::ServerContext* context,
69 const proto::VehiclePropValueRequests* requests,
70 proto::SetValueResults* results) {
71 std::vector<aidlvhal::SetValueRequest> aidlRequests;
Yu Shanb561e442024-07-11 15:11:29 -070072 std::unordered_set<int64_t> requestIds;
Hao Chen32d46702023-04-10 15:59:50 -070073 for (const auto& protoRequest : requests->requests()) {
74 auto& aidlRequest = aidlRequests.emplace_back();
Yu Shanb561e442024-07-11 15:11:29 -070075 int64_t requestId = protoRequest.request_id();
76 aidlRequest.requestId = requestId;
Hao Chen32d46702023-04-10 15:59:50 -070077 proto_msg_converter::protoToAidl(protoRequest.value(), &aidlRequest.value);
Yu Shanb561e442024-07-11 15:11:29 -070078 requestIds.insert(requestId);
Hao Chen32d46702023-04-10 15:59:50 -070079 }
80 auto waitMtx = std::make_shared<std::mutex>();
81 auto waitCV = std::make_shared<std::condition_variable>();
82 auto complete = std::make_shared<bool>(false);
83 auto tmpResults = std::make_shared<proto::SetValueResults>();
84 auto aidlStatus = mHardware->setValues(
85 std::make_shared<const IVehicleHardware::SetValuesCallback>(
Yu Shanb561e442024-07-11 15:11:29 -070086 [waitMtx, waitCV, complete, tmpResults,
87 &requestIds](std::vector<aidlvhal::SetValueResult> setValueResults) {
88 bool receivedAllResults = false;
Hao Chen32d46702023-04-10 15:59:50 -070089 {
90 std::lock_guard lck(*waitMtx);
Yu Shanb561e442024-07-11 15:11:29 -070091 for (const auto& aidlResult : setValueResults) {
92 auto& protoResult = *tmpResults->add_results();
93 int64_t requestIdForResult = aidlResult.requestId;
94 protoResult.set_request_id(requestIdForResult);
95 protoResult.set_status(
96 static_cast<proto::StatusCode>(aidlResult.status));
97 requestIds.erase(requestIdForResult);
98 }
99 if (requestIds.empty()) {
100 receivedAllResults = true;
101 *complete = true;
102 }
Hao Chen32d46702023-04-10 15:59:50 -0700103 }
Yu Shanb561e442024-07-11 15:11:29 -0700104 if (receivedAllResults) {
105 waitCV->notify_all();
106 }
Hao Chen32d46702023-04-10 15:59:50 -0700107 }),
108 aidlRequests);
109 if (aidlStatus != aidlvhal::StatusCode::OK) {
110 return ::grpc::Status(::grpc::StatusCode::INTERNAL,
111 "The underlying hardware fails to set values, VHAL status: " +
112 toString(aidlStatus));
113 }
114 std::unique_lock lck(*waitMtx);
115 bool success = waitCV->wait_for(lck, kHardwareOpTimeout, [complete] { return *complete; });
116 if (!success) {
117 return ::grpc::Status(::grpc::StatusCode::INTERNAL,
118 "The underlying hardware set values timeout.");
119 }
120 *results = std::move(*tmpResults);
121 return ::grpc::Status::OK;
122}
123
124::grpc::Status GrpcVehicleProxyServer::GetValues(::grpc::ServerContext* context,
125 const proto::VehiclePropValueRequests* requests,
126 proto::GetValueResults* results) {
127 std::vector<aidlvhal::GetValueRequest> aidlRequests;
Yu Shanb561e442024-07-11 15:11:29 -0700128 std::unordered_set<int64_t> requestIds;
Hao Chen32d46702023-04-10 15:59:50 -0700129 for (const auto& protoRequest : requests->requests()) {
130 auto& aidlRequest = aidlRequests.emplace_back();
Yu Shanb561e442024-07-11 15:11:29 -0700131 int64_t requestId = protoRequest.request_id();
132 aidlRequest.requestId = requestId;
Hao Chen32d46702023-04-10 15:59:50 -0700133 proto_msg_converter::protoToAidl(protoRequest.value(), &aidlRequest.prop);
Yu Shanb561e442024-07-11 15:11:29 -0700134 requestIds.insert(requestId);
Hao Chen32d46702023-04-10 15:59:50 -0700135 }
136 auto waitMtx = std::make_shared<std::mutex>();
137 auto waitCV = std::make_shared<std::condition_variable>();
138 auto complete = std::make_shared<bool>(false);
139 auto tmpResults = std::make_shared<proto::GetValueResults>();
140 auto aidlStatus = mHardware->getValues(
141 std::make_shared<const IVehicleHardware::GetValuesCallback>(
Yu Shanb561e442024-07-11 15:11:29 -0700142 [waitMtx, waitCV, complete, tmpResults,
143 &requestIds](std::vector<aidlvhal::GetValueResult> getValueResults) {
144 bool receivedAllResults = false;
Hao Chen32d46702023-04-10 15:59:50 -0700145 {
146 std::lock_guard lck(*waitMtx);
Yu Shanb561e442024-07-11 15:11:29 -0700147 for (const auto& aidlResult : getValueResults) {
148 auto& protoResult = *tmpResults->add_results();
149 int64_t requestIdForResult = aidlResult.requestId;
150 protoResult.set_request_id(requestIdForResult);
151 protoResult.set_status(
152 static_cast<proto::StatusCode>(aidlResult.status));
153 if (aidlResult.prop) {
154 auto* valuePtr = protoResult.mutable_value();
155 proto_msg_converter::aidlToProto(*aidlResult.prop, valuePtr);
156 }
157 requestIds.erase(requestIdForResult);
158 }
159 if (requestIds.empty()) {
160 receivedAllResults = true;
161 *complete = true;
162 }
Hao Chen32d46702023-04-10 15:59:50 -0700163 }
Yu Shanb561e442024-07-11 15:11:29 -0700164 if (receivedAllResults) {
165 waitCV->notify_all();
166 }
Hao Chen32d46702023-04-10 15:59:50 -0700167 }),
168 aidlRequests);
169 if (aidlStatus != aidlvhal::StatusCode::OK) {
170 return ::grpc::Status(::grpc::StatusCode::INTERNAL,
171 "The underlying hardware fails to get values, VHAL status: " +
172 toString(aidlStatus));
173 }
174 std::unique_lock lck(*waitMtx);
175 bool success = waitCV->wait_for(lck, kHardwareOpTimeout, [complete] { return *complete; });
176 if (!success) {
177 return ::grpc::Status(::grpc::StatusCode::INTERNAL,
178 "The underlying hardware get values timeout.");
179 }
180 *results = std::move(*tmpResults);
181 return ::grpc::Status::OK;
182}
183
Hao Chena810fb22023-04-11 15:27:44 -0700184::grpc::Status GrpcVehicleProxyServer::UpdateSampleRate(
185 ::grpc::ServerContext* context, const proto::UpdateSampleRateRequest* request,
186 proto::VehicleHalCallStatus* status) {
187 const auto status_code = mHardware->updateSampleRate(request->prop(), request->area_id(),
188 request->sample_rate());
189 status->set_status_code(static_cast<proto::StatusCode>(status_code));
190 return ::grpc::Status::OK;
191}
192
Yu Shan5c846f72024-05-16 15:39:51 -0700193::grpc::Status GrpcVehicleProxyServer::Subscribe(::grpc::ServerContext* context,
194 const proto::SubscribeRequest* request,
195 proto::VehicleHalCallStatus* status) {
196 const auto& protoSubscribeOptions = request->options();
197 aidlvhal::SubscribeOptions aidlSubscribeOptions = {};
198 proto_msg_converter::protoToAidl(protoSubscribeOptions, &aidlSubscribeOptions);
199 const auto status_code = mHardware->subscribe(aidlSubscribeOptions);
200 status->set_status_code(static_cast<proto::StatusCode>(status_code));
201 return ::grpc::Status::OK;
202}
203
Yu Shan2c37c112024-05-20 17:27:19 -0700204::grpc::Status GrpcVehicleProxyServer::Unsubscribe(::grpc::ServerContext* context,
205 const proto::UnsubscribeRequest* request,
206 proto::VehicleHalCallStatus* status) {
207 int32_t propId = request->prop_id();
208 int32_t areaId = request->area_id();
209 const auto status_code = mHardware->unsubscribe(propId, areaId);
210 status->set_status_code(static_cast<proto::StatusCode>(status_code));
211 return ::grpc::Status::OK;
212}
213
Hao Chena810fb22023-04-11 15:27:44 -0700214::grpc::Status GrpcVehicleProxyServer::CheckHealth(::grpc::ServerContext* context,
215 const ::google::protobuf::Empty*,
216 proto::VehicleHalCallStatus* status) {
217 status->set_status_code(static_cast<proto::StatusCode>(mHardware->checkHealth()));
218 return ::grpc::Status::OK;
219}
220
221::grpc::Status GrpcVehicleProxyServer::Dump(::grpc::ServerContext* context,
222 const proto::DumpOptions* options,
223 proto::DumpResult* result) {
224 std::vector<std::string> dumpOptionStrings(options->options().begin(),
225 options->options().end());
226 auto dumpResult = mHardware->dump(dumpOptionStrings);
227 result->set_caller_should_dump_state(dumpResult.callerShouldDumpState);
228 result->set_buffer(dumpResult.buffer);
terryguan465d8d72024-08-21 13:17:12 -0700229 result->set_refresh_property_configs(dumpResult.refreshPropertyConfigs);
Hao Chena810fb22023-04-11 15:27:44 -0700230 return ::grpc::Status::OK;
231}
232
Hao Chen32d46702023-04-10 15:59:50 -0700233::grpc::Status GrpcVehicleProxyServer::StartPropertyValuesStream(
234 ::grpc::ServerContext* context, const ::google::protobuf::Empty* request,
235 ::grpc::ServerWriter<proto::VehiclePropValues>* stream) {
236 auto conn = std::make_shared<ConnectionDescriptor>(stream);
237 {
238 std::lock_guard lck(mConnectionMutex);
239 mValueStreamingConnections.push_back(conn);
240 }
241 conn->Wait();
242 LOG(ERROR) << __func__ << ": Stream lost, ID : " << conn->ID();
243 return ::grpc::Status(::grpc::StatusCode::ABORTED, "Connection lost.");
244}
245
246void GrpcVehicleProxyServer::OnVehiclePropChange(
247 const std::vector<aidlvhal::VehiclePropValue>& values) {
248 std::unordered_set<uint64_t> brokenConn;
249 proto::VehiclePropValues protoValues;
250 for (const auto& value : values) {
251 auto* protoValuePtr = protoValues.add_values();
252 proto_msg_converter::aidlToProto(value, protoValuePtr);
253 }
254 {
255 std::shared_lock read_lock(mConnectionMutex);
256 for (auto& connection : mValueStreamingConnections) {
257 auto writeOK = connection->Write(protoValues);
258 if (!writeOK) {
259 LOG(ERROR) << __func__
260 << ": Server Write failed, connection lost. ID: " << connection->ID();
261 brokenConn.insert(connection->ID());
262 }
263 }
264 }
265 if (brokenConn.empty()) {
266 return;
267 }
268 std::unique_lock write_lock(mConnectionMutex);
269 mValueStreamingConnections.erase(
270 std::remove_if(mValueStreamingConnections.begin(), mValueStreamingConnections.end(),
271 [&brokenConn](const auto& conn) {
272 return brokenConn.find(conn->ID()) != brokenConn.end();
273 }),
274 mValueStreamingConnections.end());
275}
276
277GrpcVehicleProxyServer& GrpcVehicleProxyServer::Start() {
278 if (mServer) {
279 LOG(WARNING) << __func__ << ": GrpcVehicleProxyServer has already started.";
280 return *this;
281 }
282 ::grpc::ServerBuilder builder;
283 builder.RegisterService(this);
Yu Shanb02b7722024-06-18 17:38:11 -0700284 for (const std::string& serviceAddr : mServiceAddrs) {
285 builder.AddListeningPort(serviceAddr, getServerCredentials());
286 }
Hao Chen32d46702023-04-10 15:59:50 -0700287 mServer = builder.BuildAndStart();
288 CHECK(mServer) << __func__ << ": failed to create the GRPC server, "
289 << "please make sure the configuration and permissions are correct";
290 return *this;
291}
292
293GrpcVehicleProxyServer& GrpcVehicleProxyServer::Shutdown() {
294 std::shared_lock read_lock(mConnectionMutex);
295 for (auto& conn : mValueStreamingConnections) {
296 conn->Shutdown();
297 }
298 if (mServer) {
299 mServer->Shutdown();
300 }
301 return *this;
302}
303
304void GrpcVehicleProxyServer::Wait() {
305 if (mServer) {
306 mServer->Wait();
307 }
308 mServer.reset();
309}
310
311GrpcVehicleProxyServer::ConnectionDescriptor::~ConnectionDescriptor() {
312 Shutdown();
313}
314
315bool GrpcVehicleProxyServer::ConnectionDescriptor::Write(const proto::VehiclePropValues& values) {
316 if (!mStream) {
317 LOG(ERROR) << __func__ << ": Empty stream. ID: " << ID();
318 Shutdown();
319 return false;
320 }
321 {
322 std::lock_guard lck(*mMtx);
323 if (!mShutdownFlag && mStream->Write(values)) {
324 return true;
325 } else {
326 LOG(ERROR) << __func__ << ": Server Write failed, connection lost. ID: " << ID();
327 }
328 }
329 Shutdown();
330 return false;
331}
332
333void GrpcVehicleProxyServer::ConnectionDescriptor::Wait() {
334 std::unique_lock lck(*mMtx);
335 mCV->wait(lck, [this] { return mShutdownFlag; });
336}
337
338void GrpcVehicleProxyServer::ConnectionDescriptor::Shutdown() {
339 {
340 std::lock_guard lck(*mMtx);
341 mShutdownFlag = true;
342 }
343 mCV->notify_all();
344}
345
346} // namespace android::hardware::automotive::vehicle::virtualization