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
18 #include <android/log.h>
19
20 #include <android-base/properties.h>
21 #include <log/log.h>
22 #include <utils/SystemClock.h>
23 #include <algorithm>
24
25 #include <vhal_v2_0/ProtoMessageConverter.h>
26 #include <vhal_v2_0/VehicleUtils.h>
27
28 #include "PipeComm.h"
29 #include "SocketComm.h"
30
31 #include "VehicleEmulator.h"
32
33 namespace android {
34 namespace hardware {
35 namespace automotive {
36 namespace vehicle {
37 namespace V2_0 {
38
39 namespace impl {
40
VehicleEmulator(EmulatedServerIface * hal)41 VehicleEmulator::VehicleEmulator(EmulatedServerIface* hal) : mHal{hal} {
42 mHal->registerEmulator(this);
43
44 ALOGI("Starting SocketComm");
45 mSocketComm = std::make_unique<SocketComm>(this);
46 mSocketComm->start();
47
48 if (isInQEMU()) {
49 ALOGI("Starting PipeComm");
50 mPipeComm = std::make_unique<PipeComm>(this);
51 mPipeComm->start();
52 }
53 }
54
~VehicleEmulator()55 VehicleEmulator::~VehicleEmulator() {
56 mSocketComm->stop();
57 if (mPipeComm) {
58 mPipeComm->stop();
59 }
60 }
61
62 /**
63 * This is called by the HAL when a property changes. We need to notify our clients that it has
64 * changed.
65 */
doSetValueFromClient(const VehiclePropValue & propValue)66 void VehicleEmulator::doSetValueFromClient(const VehiclePropValue& propValue) {
67 vhal_proto::EmulatorMessage msg;
68 vhal_proto::VehiclePropValue* val = msg.add_value();
69 populateProtoVehiclePropValue(val, &propValue);
70 msg.set_status(vhal_proto::RESULT_OK);
71 msg.set_msg_type(vhal_proto::SET_PROPERTY_ASYNC);
72
73 mSocketComm->sendMessage(msg);
74 if (mPipeComm) {
75 mPipeComm->sendMessage(msg);
76 }
77 }
78
doGetConfig(const VehicleEmulator::EmulatorMessage & rxMsg,VehicleEmulator::EmulatorMessage * respMsg)79 void VehicleEmulator::doGetConfig(const VehicleEmulator::EmulatorMessage& rxMsg,
80 VehicleEmulator::EmulatorMessage* respMsg) {
81 std::vector<VehiclePropConfig> configs = mHal->listProperties();
82 vhal_proto::VehiclePropGet getProp = rxMsg.prop(0);
83
84 respMsg->set_msg_type(vhal_proto::GET_CONFIG_RESP);
85 respMsg->set_status(vhal_proto::ERROR_INVALID_PROPERTY);
86
87 for (auto& config : configs) {
88 // Find the config we are looking for
89 if (config.prop == getProp.prop()) {
90 vhal_proto::VehiclePropConfig* protoCfg = respMsg->add_config();
91 populateProtoVehicleConfig(protoCfg, config);
92 respMsg->set_status(vhal_proto::RESULT_OK);
93 break;
94 }
95 }
96 }
97
doGetConfigAll(const VehicleEmulator::EmulatorMessage &,VehicleEmulator::EmulatorMessage * respMsg)98 void VehicleEmulator::doGetConfigAll(const VehicleEmulator::EmulatorMessage& /* rxMsg */,
99 VehicleEmulator::EmulatorMessage* respMsg) {
100 std::vector<VehiclePropConfig> configs = mHal->listProperties();
101
102 respMsg->set_msg_type(vhal_proto::GET_CONFIG_ALL_RESP);
103 respMsg->set_status(vhal_proto::RESULT_OK);
104
105 for (auto& config : configs) {
106 vhal_proto::VehiclePropConfig* protoCfg = respMsg->add_config();
107 populateProtoVehicleConfig(protoCfg, config);
108 }
109 }
110
doGetProperty(const VehicleEmulator::EmulatorMessage & rxMsg,VehicleEmulator::EmulatorMessage * respMsg)111 void VehicleEmulator::doGetProperty(const VehicleEmulator::EmulatorMessage& rxMsg,
112 VehicleEmulator::EmulatorMessage* respMsg) {
113 int32_t areaId = 0;
114 vhal_proto::VehiclePropGet getProp = rxMsg.prop(0);
115 int32_t propId = getProp.prop();
116 vhal_proto::Status status = vhal_proto::ERROR_INVALID_PROPERTY;
117
118 respMsg->set_msg_type(vhal_proto::GET_PROPERTY_RESP);
119
120 if (getProp.has_area_id()) {
121 areaId = getProp.area_id();
122 }
123
124 {
125 VehiclePropValue request = {
126 .areaId = areaId,
127 .prop = propId,
128 };
129 StatusCode halStatus;
130 auto val = mHal->get(request, &halStatus);
131 if (val != nullptr) {
132 vhal_proto::VehiclePropValue* protoVal = respMsg->add_value();
133 populateProtoVehiclePropValue(protoVal, val.get());
134 status = vhal_proto::RESULT_OK;
135 }
136 }
137
138 respMsg->set_status(status);
139 }
140
doGetPropertyAll(const VehicleEmulator::EmulatorMessage &,VehicleEmulator::EmulatorMessage * respMsg)141 void VehicleEmulator::doGetPropertyAll(const VehicleEmulator::EmulatorMessage& /* rxMsg */,
142 VehicleEmulator::EmulatorMessage* respMsg) {
143 respMsg->set_msg_type(vhal_proto::GET_PROPERTY_ALL_RESP);
144 respMsg->set_status(vhal_proto::RESULT_OK);
145
146 {
147 for (const auto& prop : mHal->getAllProperties()) {
148 vhal_proto::VehiclePropValue* protoVal = respMsg->add_value();
149 populateProtoVehiclePropValue(protoVal, &prop);
150 }
151 }
152 }
153
doSetProperty(const VehicleEmulator::EmulatorMessage & rxMsg,VehicleEmulator::EmulatorMessage * respMsg)154 void VehicleEmulator::doSetProperty(const VehicleEmulator::EmulatorMessage& rxMsg,
155 VehicleEmulator::EmulatorMessage* respMsg) {
156 vhal_proto::VehiclePropValue protoVal = rxMsg.value(0);
157 VehiclePropValue val = {
158 .timestamp = elapsedRealtimeNano(),
159 .areaId = protoVal.area_id(),
160 .prop = protoVal.prop(),
161 .status = (VehiclePropertyStatus)protoVal.status(),
162 };
163
164 respMsg->set_msg_type(vhal_proto::SET_PROPERTY_RESP);
165
166 // Copy value data if it is set. This automatically handles complex data types if needed.
167 if (protoVal.has_string_value()) {
168 val.value.stringValue = protoVal.string_value().c_str();
169 }
170
171 if (protoVal.has_bytes_value()) {
172 val.value.bytes = std::vector<uint8_t> { protoVal.bytes_value().begin(),
173 protoVal.bytes_value().end() };
174 }
175
176 if (protoVal.int32_values_size() > 0) {
177 val.value.int32Values = std::vector<int32_t> { protoVal.int32_values().begin(),
178 protoVal.int32_values().end() };
179 }
180
181 if (protoVal.int64_values_size() > 0) {
182 val.value.int64Values = std::vector<int64_t> { protoVal.int64_values().begin(),
183 protoVal.int64_values().end() };
184 }
185
186 if (protoVal.float_values_size() > 0) {
187 val.value.floatValues = std::vector<float> { protoVal.float_values().begin(),
188 protoVal.float_values().end() };
189 }
190
191 bool halRes = mHal->setPropertyFromVehicle(val);
192 respMsg->set_status(halRes ? vhal_proto::RESULT_OK : vhal_proto::ERROR_INVALID_PROPERTY);
193 }
194
doDebug(const vhal_proto::EmulatorMessage & rxMsg,vhal_proto::EmulatorMessage * respMsg)195 void VehicleEmulator::doDebug(const vhal_proto::EmulatorMessage& rxMsg,
196 vhal_proto::EmulatorMessage* respMsg) {
197 auto protoCommands = rxMsg.debug_commands();
198 std::vector<std::string> commands = std::vector<std::string>(
199 protoCommands.begin(), protoCommands.end());
200 IVehicleServer::DumpResult result = mHal->debug(commands);
201 respMsg->set_status(vhal_proto::RESULT_OK);
202 respMsg->set_msg_type(vhal_proto::DEBUG_RESP);
203 respMsg->set_debug_result(result.buffer);
204 }
205
processMessage(const vhal_proto::EmulatorMessage & rxMsg,vhal_proto::EmulatorMessage * respMsg)206 void VehicleEmulator::processMessage(const vhal_proto::EmulatorMessage& rxMsg,
207 vhal_proto::EmulatorMessage* respMsg) {
208 switch (rxMsg.msg_type()) {
209 case vhal_proto::GET_CONFIG_CMD:
210 doGetConfig(rxMsg, respMsg);
211 break;
212 case vhal_proto::GET_CONFIG_ALL_CMD:
213 doGetConfigAll(rxMsg, respMsg);
214 break;
215 case vhal_proto::GET_PROPERTY_CMD:
216 doGetProperty(rxMsg, respMsg);
217 break;
218 case vhal_proto::GET_PROPERTY_ALL_CMD:
219 doGetPropertyAll(rxMsg, respMsg);
220 break;
221 case vhal_proto::SET_PROPERTY_CMD:
222 doSetProperty(rxMsg, respMsg);
223 break;
224 case vhal_proto::DEBUG_CMD:
225 doDebug(rxMsg, respMsg);
226 break;
227 default:
228 ALOGW("%s: Unknown message received, type = %d", __func__, rxMsg.msg_type());
229 respMsg->set_status(vhal_proto::ERROR_UNIMPLEMENTED_CMD);
230 break;
231 }
232 }
233
populateProtoVehicleConfig(vhal_proto::VehiclePropConfig * protoCfg,const VehiclePropConfig & cfg)234 void VehicleEmulator::populateProtoVehicleConfig(vhal_proto::VehiclePropConfig* protoCfg,
235 const VehiclePropConfig& cfg) {
236 return proto_msg_converter::toProto(protoCfg, cfg);
237 }
238
populateProtoVehiclePropValue(vhal_proto::VehiclePropValue * protoVal,const VehiclePropValue * val)239 void VehicleEmulator::populateProtoVehiclePropValue(vhal_proto::VehiclePropValue* protoVal,
240 const VehiclePropValue* val) {
241 return proto_msg_converter::toProto(protoVal, *val);
242 }
243
isInQEMU()244 bool isInQEMU() {
245 return android::base::GetBoolProperty("ro.boot.qemu", false);
246 }
247
248 } // impl
249
250 } // namespace V2_0
251 } // namespace vehicle
252 } // namespace automotive
253 } // namespace hardware
254 } // namespace android
255