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 #define LOG_TAG "VehicleEmulator"
17
18 #include "VehicleEmulator.h"
19
20 #include <utils/Log.h>
21 #include <utils/SystemClock.h>
22 #include <algorithm>
23 #include <vector>
24
25 #include <VehicleUtils.h>
26 #include <IVehicleHardware.h>
27 #include <PipeComm.h>
28 #include <SocketComm.h>
29
30 namespace android {
31 namespace hardware {
32 namespace automotive {
33 namespace vehicle {
34 namespace fake {
35
36 using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
37 using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig;
38 using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyStatus;
39 using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType;
40
41 using ::android::hardware::automotive::vehicle::V2_0::impl::SocketComm;
42 using ::android::hardware::automotive::vehicle::V2_0::impl::PipeComm;
43 using ::android::hardware::automotive::vehicle::V2_0::impl::MessageSender;
44
VehicleEmulator(EmulatedVehicleHardware * hal)45 VehicleEmulator::VehicleEmulator(EmulatedVehicleHardware* hal) : mHal(hal) {
46 ALOGI("Starting SocketComm");
47 mSocketComm = std::make_unique<SocketComm>(this);
48 mSocketComm->start();
49
50 if (hal->isInQemu()) {
51 ALOGI("Starting PipeComm");
52 mPipeComm = std::make_unique<PipeComm>(this);
53 mPipeComm->start();
54 }
55 }
56
VehicleEmulator(std::unique_ptr<MessageSender> socketComm,std::unique_ptr<MessageSender> pipeComm,EmulatedVehicleHardware * hal)57 VehicleEmulator::VehicleEmulator(
58 std::unique_ptr<MessageSender> socketComm,
59 std::unique_ptr<MessageSender> pipeComm,
60 EmulatedVehicleHardware* hal) : mHal(hal), mSocketComm(std::move(socketComm)),
61 mPipeComm(std::move(pipeComm)) {};
62
~VehicleEmulator()63 VehicleEmulator::~VehicleEmulator() {
64 mSocketComm->stop();
65 if (mPipeComm) {
66 mPipeComm->stop();
67 }
68 }
69
70 /**
71 * This is called by the HAL when a property changes. We need to notify our clients that it has
72 * changed.
73 */
doSetValueFromClient(const VehiclePropValue & propValue)74 void VehicleEmulator::doSetValueFromClient(const VehiclePropValue& propValue) {
75 vhal_proto::EmulatorMessage msg;
76 vhal_proto::VehiclePropValue* val = msg.add_value();
77 populateProtoVehiclePropValue(propValue, val);
78 msg.set_status(vhal_proto::RESULT_OK);
79 msg.set_msg_type(vhal_proto::SET_PROPERTY_ASYNC);
80
81 mSocketComm->sendMessage(msg);
82 if (mPipeComm) {
83 mPipeComm->sendMessage(msg);
84 }
85 }
86
doGetConfig(const VehicleEmulator::EmulatorMessage & rxMsg,VehicleEmulator::EmulatorMessage * respMsg)87 void VehicleEmulator::doGetConfig(const VehicleEmulator::EmulatorMessage& rxMsg,
88 VehicleEmulator::EmulatorMessage* respMsg) {
89 respMsg->set_msg_type(vhal_proto::GET_CONFIG_RESP);
90
91 if (rxMsg.prop_size() < 1) {
92 ALOGE("Invalid GET_CONFIG_CMD msg, missing prop");
93 respMsg->set_status(vhal_proto::ERROR_INVALID_OPERATION);
94 return;
95 }
96
97 vhal_proto::VehiclePropGet getProp = rxMsg.prop(0);
98
99 int32_t propId = getProp.prop();
100 auto result = mHal->getPropConfig(propId);
101 if (!result.ok()) {
102 ALOGE("No config for property: %d\n", propId);
103 respMsg->set_status(vhal_proto::ERROR_INVALID_PROPERTY);
104 return;
105 }
106
107 vhal_proto::VehiclePropConfig* protoCfg = respMsg->add_config();
108 populateProtoVehicleConfig(*result.value(), protoCfg);
109 respMsg->set_status(vhal_proto::RESULT_OK);
110 }
111
doGetConfigAll(const VehicleEmulator::EmulatorMessage &,VehicleEmulator::EmulatorMessage * respMsg)112 void VehicleEmulator::doGetConfigAll(const VehicleEmulator::EmulatorMessage& /* rxMsg */,
113 VehicleEmulator::EmulatorMessage* respMsg) {
114 respMsg->set_msg_type(vhal_proto::GET_CONFIG_ALL_RESP);
115
116 std::vector<VehiclePropConfig> configs = mHal->getAllPropertyConfigs();
117 respMsg->set_status(vhal_proto::RESULT_OK);
118
119 for (auto& config : configs) {
120 vhal_proto::VehiclePropConfig* protoCfg = respMsg->add_config();
121 populateProtoVehicleConfig(config, protoCfg);
122 }
123 }
124
doGetProperty(const VehicleEmulator::EmulatorMessage & rxMsg,VehicleEmulator::EmulatorMessage * respMsg)125 void VehicleEmulator::doGetProperty(const VehicleEmulator::EmulatorMessage& rxMsg,
126 VehicleEmulator::EmulatorMessage* respMsg) {
127 respMsg->set_msg_type(vhal_proto::GET_PROPERTY_RESP);
128
129 if (rxMsg.prop_size() < 1) {
130 ALOGE("Invalid GET_PROPERTY_CMD msg, missing prop");
131 respMsg->set_status(vhal_proto::ERROR_INVALID_OPERATION);
132 return;
133 }
134
135 vhal_proto::VehiclePropGet getProp = rxMsg.prop(0);
136 int32_t propId = getProp.prop();
137 vhal_proto::Status status;
138
139 ALOGD("get property: %d", propId);
140
141 int32_t areaId = 0;
142 if (getProp.has_area_id()) {
143 areaId = getProp.area_id();
144 }
145
146 VehiclePropValue request = {
147 .areaId = areaId,
148 .prop = propId,
149 };
150 auto result = mHal->getValue(request);
151 if (result.ok()) {
152 vhal_proto::VehiclePropValue* protoVal = respMsg->add_value();
153 populateProtoVehiclePropValue(*result.value(), protoVal);
154 status = vhal_proto::RESULT_OK;
155 } else {
156 ALOGW("Failed to get value, error: %s", getErrorMsg(result).c_str());
157 status = vhal_proto::ERROR_INVALID_PROPERTY;
158 }
159
160 respMsg->set_status(status);
161 }
162
doGetPropertyAll(const VehicleEmulator::EmulatorMessage &,VehicleEmulator::EmulatorMessage * respMsg)163 void VehicleEmulator::doGetPropertyAll(const VehicleEmulator::EmulatorMessage& /* rxMsg */,
164 VehicleEmulator::EmulatorMessage* respMsg) {
165 respMsg->set_msg_type(vhal_proto::GET_PROPERTY_ALL_RESP);
166
167 respMsg->set_status(vhal_proto::RESULT_OK);
168
169 {
170 for (const auto& prop : mHal->getAllProperties()) {
171 vhal_proto::VehiclePropValue* protoVal = respMsg->add_value();
172 populateProtoVehiclePropValue(*prop, protoVal);
173 }
174 }
175 }
176
doSetProperty(const VehicleEmulator::EmulatorMessage & rxMsg,VehicleEmulator::EmulatorMessage * respMsg)177 void VehicleEmulator::doSetProperty(const VehicleEmulator::EmulatorMessage& rxMsg,
178 VehicleEmulator::EmulatorMessage* respMsg) {
179 respMsg->set_msg_type(vhal_proto::SET_PROPERTY_RESP);
180
181 if (rxMsg.value_size() < 1) {
182 ALOGE("Invalid SET_PROPERTY_CMD msg, missing value");
183 respMsg->set_status(vhal_proto::ERROR_INVALID_OPERATION);
184 return;
185 }
186
187 vhal_proto::VehiclePropValue protoVal = rxMsg.value(0);
188 VehiclePropValue val = {
189 .timestamp = elapsedRealtimeNano(),
190 .areaId = protoVal.area_id(),
191 .prop = protoVal.prop(),
192 .status = static_cast<VehiclePropertyStatus>(protoVal.status()),
193 };
194
195 ALOGD("set property: %d", protoVal.prop());
196
197 // Copy value data if it is set. This automatically handles complex data types if needed.
198 if (protoVal.has_string_value()) {
199 val.value.stringValue = protoVal.string_value().c_str();
200 }
201
202 if (protoVal.has_bytes_value()) {
203 val.value.byteValues = std::vector<uint8_t> { protoVal.bytes_value().begin(),
204 protoVal.bytes_value().end() };
205 }
206
207 if (protoVal.int32_values_size() > 0) {
208 val.value.int32Values = std::vector<int32_t> { protoVal.int32_values().begin(),
209 protoVal.int32_values().end() };
210 }
211
212 if (protoVal.int64_values_size() > 0) {
213 val.value.int64Values = std::vector<int64_t> { protoVal.int64_values().begin(),
214 protoVal.int64_values().end() };
215 }
216
217 if (protoVal.float_values_size() > 0) {
218 val.value.floatValues = std::vector<float> { protoVal.float_values().begin(),
219 protoVal.float_values().end() };
220 }
221
222 auto result = mHal->setValue(val);
223 respMsg->set_status(result.ok() ? vhal_proto::RESULT_OK : vhal_proto::ERROR_INVALID_PROPERTY);
224 }
225
doDebug(const vhal_proto::EmulatorMessage & rxMsg,vhal_proto::EmulatorMessage * respMsg)226 void VehicleEmulator::doDebug(const vhal_proto::EmulatorMessage& rxMsg,
227 vhal_proto::EmulatorMessage* respMsg) {
228 respMsg->set_msg_type(vhal_proto::DEBUG_RESP);
229
230 auto protoCommands = rxMsg.debug_commands();
231 std::vector<std::string> commands = std::vector<std::string>(
232 protoCommands.begin(), protoCommands.end());
233 DumpResult msg = mHal->dump(commands);
234 respMsg->set_status(vhal_proto::RESULT_OK);
235 respMsg->set_debug_result(msg.buffer);
236 }
237
processMessage(const vhal_proto::EmulatorMessage & rxMsg,vhal_proto::EmulatorMessage * respMsg)238 void VehicleEmulator::processMessage(const vhal_proto::EmulatorMessage& rxMsg,
239 vhal_proto::EmulatorMessage* respMsg) {
240 switch (rxMsg.msg_type()) {
241 case vhal_proto::GET_CONFIG_CMD:
242 doGetConfig(rxMsg, respMsg);
243 break;
244 case vhal_proto::GET_CONFIG_ALL_CMD:
245 doGetConfigAll(rxMsg, respMsg);
246 break;
247 case vhal_proto::GET_PROPERTY_CMD:
248 doGetProperty(rxMsg, respMsg);
249 break;
250 case vhal_proto::GET_PROPERTY_ALL_CMD:
251 doGetPropertyAll(rxMsg, respMsg);
252 break;
253 case vhal_proto::SET_PROPERTY_CMD:
254 doSetProperty(rxMsg, respMsg);
255 break;
256 case vhal_proto::DEBUG_CMD:
257 doDebug(rxMsg, respMsg);
258 break;
259 default:
260 ALOGW("%s: Unknown message received, type = %d", __func__, rxMsg.msg_type());
261 respMsg->set_status(vhal_proto::ERROR_UNIMPLEMENTED_CMD);
262 break;
263 }
264 }
265
populateProtoVehicleConfig(const VehiclePropConfig & cfg,vhal_proto::VehiclePropConfig * protoCfg)266 void VehicleEmulator::populateProtoVehicleConfig(const VehiclePropConfig& cfg,
267 vhal_proto::VehiclePropConfig* protoCfg) {
268 protoCfg->set_prop(cfg.prop);
269 protoCfg->set_access(toInt(cfg.access));
270 protoCfg->set_change_mode(toInt(cfg.changeMode));
271 protoCfg->set_value_type(toInt(getPropType(cfg.prop)));
272
273 for (auto& configElement : cfg.configArray) {
274 protoCfg->add_config_array(configElement);
275 }
276
277 if (cfg.configString.size() > 0) {
278 protoCfg->set_config_string(cfg.configString.c_str(), cfg.configString.size());
279 }
280
281 protoCfg->clear_area_configs();
282 for (auto& areaConfig : cfg.areaConfigs) {
283 auto* protoACfg = protoCfg->add_area_configs();
284 protoACfg->set_area_id(areaConfig.areaId);
285
286 switch (getPropType(cfg.prop)) {
287 case VehiclePropertyType::STRING:
288 case VehiclePropertyType::BOOLEAN:
289 case VehiclePropertyType::INT32_VEC:
290 case VehiclePropertyType::INT64_VEC:
291 case VehiclePropertyType::FLOAT_VEC:
292 case VehiclePropertyType::BYTES:
293 case VehiclePropertyType::MIXED:
294 // Do nothing. These types don't have min/max values
295 break;
296 case VehiclePropertyType::INT64:
297 protoACfg->set_min_int64_value(areaConfig.minInt64Value);
298 protoACfg->set_max_int64_value(areaConfig.maxInt64Value);
299 break;
300 case VehiclePropertyType::FLOAT:
301 protoACfg->set_min_float_value(areaConfig.minFloatValue);
302 protoACfg->set_max_float_value(areaConfig.maxFloatValue);
303 break;
304 case VehiclePropertyType::INT32:
305 protoACfg->set_min_int32_value(areaConfig.minInt32Value);
306 protoACfg->set_max_int32_value(areaConfig.maxInt32Value);
307 break;
308 default:
309 ALOGW("%s: Unknown property type: 0x%x", __func__, toInt(getPropType(cfg.prop)));
310 break;
311 }
312 }
313
314 protoCfg->set_min_sample_rate(cfg.minSampleRate);
315 protoCfg->set_max_sample_rate(cfg.maxSampleRate);
316 }
317
populateProtoVehiclePropValue(const VehiclePropValue & val,vhal_proto::VehiclePropValue * protoVal)318 void VehicleEmulator::populateProtoVehiclePropValue(const VehiclePropValue& val,
319 vhal_proto::VehiclePropValue* protoVal) {
320 protoVal->set_prop(val.prop);
321 protoVal->set_value_type(toInt(getPropType(val.prop)));
322 protoVal->set_timestamp(val.timestamp);
323 protoVal->set_status(static_cast<vhal_proto::VehiclePropStatus>(val.status));
324 protoVal->set_area_id(val.areaId);
325
326 // Copy value data if it is set.
327 // - for bytes and strings, this is indicated by size > 0
328 // - for int32, int64, and float, copy the values if vectors have data
329 if (val.value.stringValue.size() > 0) {
330 protoVal->set_string_value(val.value.stringValue.c_str(), val.value.stringValue.size());
331 }
332
333 if (val.value.byteValues.size() > 0) {
334 protoVal->set_bytes_value(val.value.byteValues.data(), val.value.byteValues.size());
335 }
336
337 for (auto& int32Value : val.value.int32Values) {
338 protoVal->add_int32_values(int32Value);
339 }
340
341 for (auto& int64Value : val.value.int64Values) {
342 protoVal->add_int64_values(int64Value);
343 }
344
345 for (auto& floatValue : val.value.floatValues) {
346 protoVal->add_float_values(floatValue);
347 }
348 }
349
350 } // namespace fake
351 } // namespace vehicle
352 } // namespace automotive
353 } // namespace hardware
354 } // namespace android
355