1 /*
2 * Copyright (C) 2020 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
17 #define LOG_TAG "VehicleHalServer"
18
19 #include "VehicleHalServer.h"
20
21 #include <fstream>
22
23 #include <android-base/logging.h>
24 #include <utils/SystemClock.h>
25
26 #include "DefaultConfig.h"
27 #include "JsonFakeValueGenerator.h"
28 #include "LinearFakeValueGenerator.h"
29 #include "Obd2SensorStore.h"
30
31 namespace android::hardware::automotive::vehicle::V2_0::impl {
32
getGenerator()33 GeneratorHub* VehicleHalServer::getGenerator() {
34 return &mGeneratorHub;
35 }
36
getValuePool() const37 VehiclePropValuePool* VehicleHalServer::getValuePool() const {
38 if (!mValuePool) {
39 LOG(WARNING) << __func__ << ": Value pool not set!";
40 }
41 return mValuePool;
42 }
43
setValuePool(VehiclePropValuePool * valuePool)44 void VehicleHalServer::setValuePool(VehiclePropValuePool* valuePool) {
45 if (!valuePool) {
46 LOG(WARNING) << __func__ << ": Setting value pool to nullptr!";
47 }
48 mValuePool = valuePool;
49 }
50
onFakeValueGenerated(const VehiclePropValue & value)51 void VehicleHalServer::onFakeValueGenerated(const VehiclePropValue& value) {
52 constexpr bool updateStatus = true;
53 LOG(DEBUG) << __func__ << ": " << toString(value);
54 auto updatedPropValue = getValuePool()->obtain(value);
55 if (updatedPropValue) {
56 updatedPropValue->timestamp = value.timestamp;
57 updatedPropValue->status = VehiclePropertyStatus::AVAILABLE;
58 onPropertyValueFromCar(*updatedPropValue, updateStatus);
59 }
60 }
61
onGetAllPropertyConfig() const62 std::vector<VehiclePropConfig> VehicleHalServer::onGetAllPropertyConfig() const {
63 std::vector<VehiclePropConfig> vehiclePropConfigs;
64 constexpr size_t numOfVehiclePropConfigs =
65 sizeof(kVehicleProperties) / sizeof(kVehicleProperties[0]);
66 vehiclePropConfigs.reserve(numOfVehiclePropConfigs);
67 for (auto& it : kVehicleProperties) {
68 vehiclePropConfigs.emplace_back(it.config);
69 }
70 return vehiclePropConfigs;
71 }
72
handleGenerateFakeDataRequest(const VehiclePropValue & request)73 StatusCode VehicleHalServer::handleGenerateFakeDataRequest(const VehiclePropValue& request) {
74 constexpr bool updateStatus = true;
75
76 LOG(INFO) << __func__;
77 const auto& v = request.value;
78 if (!v.int32Values.size()) {
79 LOG(ERROR) << __func__ << ": expected at least \"command\" field in int32Values";
80 return StatusCode::INVALID_ARG;
81 }
82
83 FakeDataCommand command = static_cast<FakeDataCommand>(v.int32Values[0]);
84
85 switch (command) {
86 case FakeDataCommand::StartLinear: {
87 LOG(INFO) << __func__ << ", FakeDataCommand::StartLinear";
88 if (v.int32Values.size() < 2) {
89 LOG(ERROR) << __func__ << ": expected property ID in int32Values";
90 return StatusCode::INVALID_ARG;
91 }
92 if (!v.int64Values.size()) {
93 LOG(ERROR) << __func__ << ": interval is not provided in int64Values";
94 return StatusCode::INVALID_ARG;
95 }
96 if (v.floatValues.size() < 3) {
97 LOG(ERROR) << __func__ << ": expected at least 3 elements in floatValues, got: "
98 << v.floatValues.size();
99 return StatusCode::INVALID_ARG;
100 }
101 int32_t cookie = v.int32Values[1];
102 getGenerator()->registerGenerator(cookie,
103 std::make_unique<LinearFakeValueGenerator>(request));
104 break;
105 }
106 case FakeDataCommand::StartJson: {
107 LOG(INFO) << __func__ << ", FakeDataCommand::StartJson";
108 if (v.stringValue.empty()) {
109 LOG(ERROR) << __func__ << ": path to JSON file is missing";
110 return StatusCode::INVALID_ARG;
111 }
112 int32_t cookie = std::hash<std::string>()(v.stringValue);
113 getGenerator()->registerGenerator(cookie,
114 std::make_unique<JsonFakeValueGenerator>(request));
115 break;
116 }
117 case FakeDataCommand::StopLinear: {
118 LOG(INFO) << __func__ << ", FakeDataCommand::StopLinear";
119 if (v.int32Values.size() < 2) {
120 LOG(ERROR) << __func__ << ": expected property ID in int32Values";
121 return StatusCode::INVALID_ARG;
122 }
123 int32_t cookie = v.int32Values[1];
124 getGenerator()->unregisterGenerator(cookie);
125 break;
126 }
127 case FakeDataCommand::StopJson: {
128 LOG(INFO) << __func__ << ", FakeDataCommand::StopJson";
129 if (v.stringValue.empty()) {
130 LOG(ERROR) << __func__ << ": path to JSON file is missing";
131 return StatusCode::INVALID_ARG;
132 }
133 int32_t cookie = std::hash<std::string>()(v.stringValue);
134 getGenerator()->unregisterGenerator(cookie);
135 break;
136 }
137 case FakeDataCommand::KeyPress: {
138 LOG(INFO) << __func__ << ", FakeDataCommand::KeyPress";
139 int32_t keyCode = request.value.int32Values[2];
140 int32_t display = request.value.int32Values[3];
141 // Send back to HAL
142 onPropertyValueFromCar(
143 *createHwInputKeyProp(VehicleHwKeyInputAction::ACTION_DOWN, keyCode, display),
144 updateStatus);
145 onPropertyValueFromCar(
146 *createHwInputKeyProp(VehicleHwKeyInputAction::ACTION_UP, keyCode, display),
147 updateStatus);
148 break;
149 }
150 default: {
151 LOG(ERROR) << __func__ << ": unexpected command: " << toInt(command);
152 return StatusCode::INVALID_ARG;
153 }
154 }
155 return StatusCode::OK;
156 }
157
createApPowerStateReq(VehicleApPowerStateReq state,int32_t param)158 VehicleHalServer::VehiclePropValuePtr VehicleHalServer::createApPowerStateReq(
159 VehicleApPowerStateReq state, int32_t param) {
160 auto req = getValuePool()->obtain(VehiclePropertyType::INT32_VEC, 2);
161 req->prop = toInt(VehicleProperty::AP_POWER_STATE_REQ);
162 req->areaId = 0;
163 req->timestamp = elapsedRealtimeNano();
164 req->status = VehiclePropertyStatus::AVAILABLE;
165 req->value.int32Values[0] = toInt(state);
166 req->value.int32Values[1] = param;
167 return req;
168 }
169
createHwInputKeyProp(VehicleHwKeyInputAction action,int32_t keyCode,int32_t targetDisplay)170 VehicleHalServer::VehiclePropValuePtr VehicleHalServer::createHwInputKeyProp(
171 VehicleHwKeyInputAction action, int32_t keyCode, int32_t targetDisplay) {
172 auto keyEvent = getValuePool()->obtain(VehiclePropertyType::INT32_VEC, 3);
173 keyEvent->prop = toInt(VehicleProperty::HW_KEY_INPUT);
174 keyEvent->areaId = 0;
175 keyEvent->timestamp = elapsedRealtimeNano();
176 keyEvent->status = VehiclePropertyStatus::AVAILABLE;
177 keyEvent->value.int32Values[0] = toInt(action);
178 keyEvent->value.int32Values[1] = keyCode;
179 keyEvent->value.int32Values[2] = targetDisplay;
180 return keyEvent;
181 }
182
onSetProperty(const VehiclePropValue & value,bool updateStatus)183 StatusCode VehicleHalServer::onSetProperty(const VehiclePropValue& value, bool updateStatus) {
184 LOG(DEBUG) << "onSetProperty(" << value.prop << ")";
185
186 // Some properties need to be treated non-trivially
187 switch (value.prop) {
188 case kGenerateFakeDataControllingProperty:
189 return handleGenerateFakeDataRequest(value);
190
191 // set the value from vehicle side, used in end to end test.
192 case kSetIntPropertyFromVehicleForTest: {
193 auto updatedPropValue = createVehiclePropValue(VehiclePropertyType::INT32, 1);
194 updatedPropValue->prop = value.value.int32Values[0];
195 updatedPropValue->value.int32Values[0] = value.value.int32Values[1];
196 updatedPropValue->timestamp = value.value.int64Values[0];
197 updatedPropValue->areaId = value.areaId;
198 onPropertyValueFromCar(*updatedPropValue, updateStatus);
199 return StatusCode::OK;
200 }
201 case kSetFloatPropertyFromVehicleForTest: {
202 auto updatedPropValue = createVehiclePropValue(VehiclePropertyType::FLOAT, 1);
203 updatedPropValue->prop = value.value.int32Values[0];
204 updatedPropValue->value.floatValues[0] = value.value.floatValues[0];
205 updatedPropValue->timestamp = value.value.int64Values[0];
206 updatedPropValue->areaId = value.areaId;
207 onPropertyValueFromCar(*updatedPropValue, updateStatus);
208 return StatusCode::OK;
209 }
210 case kSetBooleanPropertyFromVehicleForTest: {
211 auto updatedPropValue = createVehiclePropValue(VehiclePropertyType::BOOLEAN, 1);
212 updatedPropValue->prop = value.value.int32Values[1];
213 updatedPropValue->value.int32Values[0] = value.value.int32Values[0];
214 updatedPropValue->timestamp = value.value.int64Values[0];
215 updatedPropValue->areaId = value.areaId;
216 onPropertyValueFromCar(*updatedPropValue, updateStatus);
217 return StatusCode::OK;
218 }
219
220 case AP_POWER_STATE_REPORT:
221 switch (value.value.int32Values[0]) {
222 case toInt(VehicleApPowerStateReport::DEEP_SLEEP_EXIT):
223 case toInt(VehicleApPowerStateReport::SHUTDOWN_CANCELLED):
224 case toInt(VehicleApPowerStateReport::WAIT_FOR_VHAL):
225 // CPMS is in WAIT_FOR_VHAL state, simply move to ON
226 // Send back to HAL
227 // ALWAYS update status for generated property value
228 onPropertyValueFromCar(*createApPowerStateReq(VehicleApPowerStateReq::ON, 0),
229 true /* updateStatus */);
230 break;
231 case toInt(VehicleApPowerStateReport::DEEP_SLEEP_ENTRY):
232 case toInt(VehicleApPowerStateReport::SHUTDOWN_START):
233 // CPMS is in WAIT_FOR_FINISH state, send the FINISHED command
234 // Send back to HAL
235 // ALWAYS update status for generated property value
236 onPropertyValueFromCar(
237 *createApPowerStateReq(VehicleApPowerStateReq::FINISHED, 0),
238 true /* updateStatus */);
239 break;
240 case toInt(VehicleApPowerStateReport::ON):
241 case toInt(VehicleApPowerStateReport::SHUTDOWN_POSTPONE):
242 case toInt(VehicleApPowerStateReport::SHUTDOWN_PREPARE):
243 // Do nothing
244 break;
245 default:
246 // Unknown state
247 break;
248 }
249 break;
250 default:
251 break;
252 }
253
254 // In the real vhal, the value will be sent to Car ECU.
255 // We just pretend it is done here and send back to HAL
256 auto updatedPropValue = getValuePool()->obtain(value);
257 updatedPropValue->timestamp = elapsedRealtimeNano();
258
259 onPropertyValueFromCar(*updatedPropValue, updateStatus);
260 return StatusCode::OK;
261 }
262
263 } // namespace android::hardware::automotive::vehicle::V2_0::impl
264