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 = { .prop = propId, .areaId = areaId };
124 StatusCode halStatus;
125 auto val = mHal->get(request, &halStatus);
126 if (val != nullptr) {
127 emulator::VehiclePropValue* protoVal = respMsg.add_value();
128 populateProtoVehiclePropValue(protoVal, val.get());
129 status = emulator::RESULT_OK;
130 }
131 }
132
133 respMsg.set_status(status);
134 }
135
doGetPropertyAll(VehicleEmulator::EmulatorMessage const &,VehicleEmulator::EmulatorMessage & respMsg)136 void VehicleEmulator::doGetPropertyAll(VehicleEmulator::EmulatorMessage const& /* rxMsg */,
137 VehicleEmulator::EmulatorMessage& respMsg) {
138 respMsg.set_msg_type(emulator::GET_PROPERTY_ALL_RESP);
139 respMsg.set_status(emulator::RESULT_OK);
140
141 {
142 for (const auto& prop : mHal->getAllProperties()) {
143 emulator::VehiclePropValue* protoVal = respMsg.add_value();
144 populateProtoVehiclePropValue(protoVal, &prop);
145 }
146 }
147 }
148
doSetProperty(VehicleEmulator::EmulatorMessage const & rxMsg,VehicleEmulator::EmulatorMessage & respMsg)149 void VehicleEmulator::doSetProperty(VehicleEmulator::EmulatorMessage const& rxMsg,
150 VehicleEmulator::EmulatorMessage& respMsg) {
151 emulator::VehiclePropValue protoVal = rxMsg.value(0);
152 VehiclePropValue val = {
153 .prop = protoVal.prop(),
154 .areaId = protoVal.area_id(),
155 .status = (VehiclePropertyStatus)protoVal.status(),
156 .timestamp = elapsedRealtimeNano(),
157 };
158
159 respMsg.set_msg_type(emulator::SET_PROPERTY_RESP);
160
161 // Copy value data if it is set. This automatically handles complex data types if needed.
162 if (protoVal.has_string_value()) {
163 val.value.stringValue = protoVal.string_value().c_str();
164 }
165
166 if (protoVal.has_bytes_value()) {
167 val.value.bytes = std::vector<uint8_t> { protoVal.bytes_value().begin(),
168 protoVal.bytes_value().end() };
169 }
170
171 if (protoVal.int32_values_size() > 0) {
172 val.value.int32Values = std::vector<int32_t> { protoVal.int32_values().begin(),
173 protoVal.int32_values().end() };
174 }
175
176 if (protoVal.int64_values_size() > 0) {
177 val.value.int64Values = std::vector<int64_t> { protoVal.int64_values().begin(),
178 protoVal.int64_values().end() };
179 }
180
181 if (protoVal.float_values_size() > 0) {
182 val.value.floatValues = std::vector<float> { protoVal.float_values().begin(),
183 protoVal.float_values().end() };
184 }
185
186 bool halRes = mHal->setPropertyFromVehicle(val);
187 respMsg.set_status(halRes ? emulator::RESULT_OK : emulator::ERROR_INVALID_PROPERTY);
188 }
189
processMessage(emulator::EmulatorMessage const & rxMsg,emulator::EmulatorMessage & respMsg)190 void VehicleEmulator::processMessage(emulator::EmulatorMessage const& rxMsg,
191 emulator::EmulatorMessage& respMsg) {
192 switch (rxMsg.msg_type()) {
193 case emulator::GET_CONFIG_CMD:
194 doGetConfig(rxMsg, respMsg);
195 break;
196 case emulator::GET_CONFIG_ALL_CMD:
197 doGetConfigAll(rxMsg, respMsg);
198 break;
199 case emulator::GET_PROPERTY_CMD:
200 doGetProperty(rxMsg, respMsg);
201 break;
202 case emulator::GET_PROPERTY_ALL_CMD:
203 doGetPropertyAll(rxMsg, respMsg);
204 break;
205 case emulator::SET_PROPERTY_CMD:
206 doSetProperty(rxMsg, respMsg);
207 break;
208 default:
209 ALOGW("%s: Unknown message received, type = %d", __func__, rxMsg.msg_type());
210 respMsg.set_status(emulator::ERROR_UNIMPLEMENTED_CMD);
211 break;
212 }
213 }
214
populateProtoVehicleConfig(emulator::VehiclePropConfig * protoCfg,const VehiclePropConfig & cfg)215 void VehicleEmulator::populateProtoVehicleConfig(emulator::VehiclePropConfig* protoCfg,
216 const VehiclePropConfig& cfg) {
217 protoCfg->set_prop(cfg.prop);
218 protoCfg->set_access(toInt(cfg.access));
219 protoCfg->set_change_mode(toInt(cfg.changeMode));
220 protoCfg->set_value_type(toInt(getPropType(cfg.prop)));
221
222 for (auto& configElement : cfg.configArray) {
223 protoCfg->add_config_array(configElement);
224 }
225
226 if (cfg.configString.size() > 0) {
227 protoCfg->set_config_string(cfg.configString.c_str(), cfg.configString.size());
228 }
229
230 // Populate the min/max values based on property type
231 switch (getPropType(cfg.prop)) {
232 case VehiclePropertyType::STRING:
233 case VehiclePropertyType::BOOLEAN:
234 case VehiclePropertyType::INT32_VEC:
235 case VehiclePropertyType::INT64_VEC:
236 case VehiclePropertyType::FLOAT_VEC:
237 case VehiclePropertyType::BYTES:
238 case VehiclePropertyType::MIXED:
239 // Do nothing. These types don't have min/max values
240 break;
241 case VehiclePropertyType::INT64:
242 if (cfg.areaConfigs.size() > 0) {
243 emulator::VehicleAreaConfig* aCfg = protoCfg->add_area_configs();
244 aCfg->set_min_int64_value(cfg.areaConfigs[0].minInt64Value);
245 aCfg->set_max_int64_value(cfg.areaConfigs[0].maxInt64Value);
246 }
247 break;
248 case VehiclePropertyType::FLOAT:
249 if (cfg.areaConfigs.size() > 0) {
250 emulator::VehicleAreaConfig* aCfg = protoCfg->add_area_configs();
251 aCfg->set_min_float_value(cfg.areaConfigs[0].minFloatValue);
252 aCfg->set_max_float_value(cfg.areaConfigs[0].maxFloatValue);
253 }
254 break;
255 case VehiclePropertyType::INT32:
256 if (cfg.areaConfigs.size() > 0) {
257 emulator::VehicleAreaConfig* aCfg = protoCfg->add_area_configs();
258 aCfg->set_min_int32_value(cfg.areaConfigs[0].minInt32Value);
259 aCfg->set_max_int32_value(cfg.areaConfigs[0].maxInt32Value);
260 }
261 break;
262 default:
263 ALOGW("%s: Unknown property type: 0x%x", __func__, toInt(getPropType(cfg.prop)));
264 break;
265 }
266
267 protoCfg->set_min_sample_rate(cfg.minSampleRate);
268 protoCfg->set_max_sample_rate(cfg.maxSampleRate);
269 }
270
populateProtoVehiclePropValue(emulator::VehiclePropValue * protoVal,const VehiclePropValue * val)271 void VehicleEmulator::populateProtoVehiclePropValue(emulator::VehiclePropValue* protoVal,
272 const VehiclePropValue* val) {
273 protoVal->set_prop(val->prop);
274 protoVal->set_value_type(toInt(getPropType(val->prop)));
275 protoVal->set_timestamp(val->timestamp);
276 protoVal->set_status((emulator::VehiclePropStatus)(val->status));
277 protoVal->set_area_id(val->areaId);
278
279 // Copy value data if it is set.
280 // - for bytes and strings, this is indicated by size > 0
281 // - for int32, int64, and float, copy the values if vectors have data
282 if (val->value.stringValue.size() > 0) {
283 protoVal->set_string_value(val->value.stringValue.c_str(), val->value.stringValue.size());
284 }
285
286 if (val->value.bytes.size() > 0) {
287 protoVal->set_bytes_value(val->value.bytes.data(), val->value.bytes.size());
288 }
289
290 for (auto& int32Value : val->value.int32Values) {
291 protoVal->add_int32_values(int32Value);
292 }
293
294 for (auto& int64Value : val->value.int64Values) {
295 protoVal->add_int64_values(int64Value);
296 }
297
298 for (auto& floatValue : val->value.floatValues) {
299 protoVal->add_float_values(floatValue);
300 }
301 }
302
303 } // impl
304
305 } // namespace V2_0
306 } // namespace vehicle
307 } // namespace automotive
308 } // namespace hardware
309 } // namespace android
310