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