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