• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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