1 /*
2 * Copyright (C) 2021 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 "FakeVehicleHardware"
18 #define ATRACE_TAG ATRACE_TAG_HAL
19 #define FAKE_VEHICLEHARDWARE_DEBUG false // STOPSHIP if true.
20
21 #include "FakeVehicleHardware.h"
22
23 #include <FakeObd2Frame.h>
24 #include <JsonFakeValueGenerator.h>
25 #include <LinearFakeValueGenerator.h>
26 #include <PropertyUtils.h>
27 #include <TestPropertyUtils.h>
28 #include <VehicleHalTypes.h>
29 #include <VehicleUtils.h>
30
31 #include <android-base/file.h>
32 #include <android-base/parsedouble.h>
33 #include <android-base/properties.h>
34 #include <android-base/strings.h>
35 #include <utils/Log.h>
36 #include <utils/SystemClock.h>
37 #include <utils/Trace.h>
38
39 #include <dirent.h>
40 #include <inttypes.h>
41 #include <sys/types.h>
42 #include <fstream>
43 #include <regex>
44 #include <unordered_set>
45 #include <vector>
46
47 namespace android {
48 namespace hardware {
49 namespace automotive {
50 namespace vehicle {
51 namespace fake {
52
53 namespace {
54
55 using ::aidl::android::hardware::automotive::vehicle::ErrorState;
56 using ::aidl::android::hardware::automotive::vehicle::GetValueRequest;
57 using ::aidl::android::hardware::automotive::vehicle::GetValueResult;
58 using ::aidl::android::hardware::automotive::vehicle::RawPropValues;
59 using ::aidl::android::hardware::automotive::vehicle::SetValueRequest;
60 using ::aidl::android::hardware::automotive::vehicle::SetValueResult;
61 using ::aidl::android::hardware::automotive::vehicle::StatusCode;
62 using ::aidl::android::hardware::automotive::vehicle::VehicleApPowerStateReport;
63 using ::aidl::android::hardware::automotive::vehicle::VehicleApPowerStateReq;
64 using ::aidl::android::hardware::automotive::vehicle::VehicleHwKeyInputAction;
65 using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig;
66 using ::aidl::android::hardware::automotive::vehicle::VehicleProperty;
67 using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyAccess;
68 using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyGroup;
69 using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyStatus;
70 using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType;
71 using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
72 using ::aidl::android::hardware::automotive::vehicle::VehicleUnit;
73
74 using ::android::base::EqualsIgnoreCase;
75 using ::android::base::Error;
76 using ::android::base::GetIntProperty;
77 using ::android::base::ParseFloat;
78 using ::android::base::Result;
79 using ::android::base::ScopedLockAssertion;
80 using ::android::base::StartsWith;
81 using ::android::base::StringPrintf;
82
83 // In order to test large number of vehicle property configs, we might generate additional fake
84 // property config start from this ID. These fake properties are for getPropertyList,
85 // getPropertiesAsync, and setPropertiesAsync.
86 // 0x21403000
87 constexpr int32_t STARTING_VENDOR_CODE_PROPERTIES_FOR_TEST =
88 0x3000 | toInt(testpropertyutils_impl::VehiclePropertyGroup::VENDOR) |
89 toInt(testpropertyutils_impl::VehicleArea::GLOBAL) |
90 toInt(testpropertyutils_impl::VehiclePropertyType::INT32);
91 // 0x21405000
92 constexpr int32_t ENDING_VENDOR_CODE_PROPERTIES_FOR_TEST =
93 0x5000 | toInt(testpropertyutils_impl::VehiclePropertyGroup::VENDOR) |
94 toInt(testpropertyutils_impl::VehicleArea::GLOBAL) |
95 toInt(testpropertyutils_impl::VehiclePropertyType::INT32);
96 // The directory for default property configuration file.
97 // For config file format, see impl/default_config/config/README.md.
98 constexpr char DEFAULT_CONFIG_DIR[] = "/vendor/etc/automotive/vhalconfig/";
99 // The directory for property configuration file that overrides the default configuration file.
100 // For config file format, see impl/default_config/config/README.md.
101 constexpr char OVERRIDE_CONFIG_DIR[] = "/vendor/etc/automotive/vhaloverride/";
102 // If OVERRIDE_PROPERTY is set, we will use the configuration files from OVERRIDE_CONFIG_DIR to
103 // overwrite the default configs.
104 constexpr char OVERRIDE_PROPERTY[] = "persist.vendor.vhal_init_value_override";
105 constexpr char POWER_STATE_REQ_CONFIG_PROPERTY[] = "ro.vendor.fake_vhal.ap_power_state_req.config";
106 // The value to be returned if VENDOR_PROPERTY_ID is set as the property
107 constexpr int VENDOR_ERROR_CODE = 0x00ab0005;
108 // A list of supported options for "--set" command.
109 const std::unordered_set<std::string> SET_PROP_OPTIONS = {
110 // integer.
111 "-i",
112 // 64bit integer.
113 "-i64",
114 // float.
115 "-f",
116 // string.
117 "-s",
118 // bytes in hex format, e.g. 0xDEADBEEF.
119 "-b",
120 // Area id in integer.
121 "-a",
122 // Timestamp in int64.
123 "-t"};
124
125 // ADAS _ENABLED property to list of ADAS state properties using ErrorState enum.
126 const std::unordered_map<int32_t, std::vector<int32_t>> mAdasEnabledPropToAdasPropWithErrorState = {
127 // AEB
128 {
129 toInt(VehicleProperty::AUTOMATIC_EMERGENCY_BRAKING_ENABLED),
130 {
131 toInt(VehicleProperty::AUTOMATIC_EMERGENCY_BRAKING_STATE),
132 },
133 },
134 // FCW
135 {
136 toInt(VehicleProperty::FORWARD_COLLISION_WARNING_ENABLED),
137 {
138 toInt(VehicleProperty::FORWARD_COLLISION_WARNING_STATE),
139 },
140 },
141 // BSW
142 {
143 toInt(VehicleProperty::BLIND_SPOT_WARNING_ENABLED),
144 {
145 toInt(VehicleProperty::BLIND_SPOT_WARNING_STATE),
146 },
147 },
148 // LDW
149 {
150 toInt(VehicleProperty::LANE_DEPARTURE_WARNING_ENABLED),
151 {
152 toInt(VehicleProperty::LANE_DEPARTURE_WARNING_STATE),
153 },
154 },
155 // LKA
156 {
157 toInt(VehicleProperty::LANE_KEEP_ASSIST_ENABLED),
158 {
159 toInt(VehicleProperty::LANE_KEEP_ASSIST_STATE),
160 },
161 },
162 // LCA
163 {
164 toInt(VehicleProperty::LANE_CENTERING_ASSIST_ENABLED),
165 {
166 toInt(VehicleProperty::LANE_CENTERING_ASSIST_STATE),
167 },
168 },
169 // ELKA
170 {
171 toInt(VehicleProperty::EMERGENCY_LANE_KEEP_ASSIST_ENABLED),
172 {
173 toInt(VehicleProperty::EMERGENCY_LANE_KEEP_ASSIST_STATE),
174 },
175 },
176 // CC
177 {
178 toInt(VehicleProperty::CRUISE_CONTROL_ENABLED),
179 {
180 toInt(VehicleProperty::CRUISE_CONTROL_TYPE),
181 toInt(VehicleProperty::CRUISE_CONTROL_STATE),
182 },
183 },
184 // HOD
185 {
186 toInt(VehicleProperty::HANDS_ON_DETECTION_ENABLED),
187 {
188 toInt(VehicleProperty::HANDS_ON_DETECTION_DRIVER_STATE),
189 toInt(VehicleProperty::HANDS_ON_DETECTION_WARNING),
190 },
191 },
192 };
193 } // namespace
194
storePropInitialValue(const ConfigDeclaration & config)195 void FakeVehicleHardware::storePropInitialValue(const ConfigDeclaration& config) {
196 const VehiclePropConfig& vehiclePropConfig = config.config;
197 int propId = vehiclePropConfig.prop;
198
199 // A global property will have only a single area
200 bool globalProp = isGlobalProp(propId);
201 size_t numAreas = globalProp ? 1 : vehiclePropConfig.areaConfigs.size();
202
203 for (size_t i = 0; i < numAreas; i++) {
204 int32_t curArea = globalProp ? 0 : vehiclePropConfig.areaConfigs[i].areaId;
205
206 // Create a separate instance for each individual zone
207 VehiclePropValue prop = {
208 .areaId = curArea,
209 .prop = propId,
210 .timestamp = elapsedRealtimeNano(),
211 };
212
213 if (config.initialAreaValues.empty()) {
214 if (config.initialValue == RawPropValues{}) {
215 // Skip empty initial values.
216 continue;
217 }
218 prop.value = config.initialValue;
219 } else if (auto valueForAreaIt = config.initialAreaValues.find(curArea);
220 valueForAreaIt != config.initialAreaValues.end()) {
221 prop.value = valueForAreaIt->second;
222 } else {
223 ALOGW("failed to get default value for prop 0x%x area 0x%x", propId, curArea);
224 continue;
225 }
226
227 auto result =
228 mServerSidePropStore->writeValue(mValuePool->obtain(prop), /*updateStatus=*/true);
229 if (!result.ok()) {
230 ALOGE("failed to write default config value, error: %s, status: %d",
231 getErrorMsg(result).c_str(), getIntErrorCode(result));
232 }
233 }
234 }
235
FakeVehicleHardware()236 FakeVehicleHardware::FakeVehicleHardware()
237 : FakeVehicleHardware(DEFAULT_CONFIG_DIR, OVERRIDE_CONFIG_DIR, false) {}
238
FakeVehicleHardware(std::string defaultConfigDir,std::string overrideConfigDir,bool forceOverride)239 FakeVehicleHardware::FakeVehicleHardware(std::string defaultConfigDir,
240 std::string overrideConfigDir, bool forceOverride)
241 : mValuePool(std::make_unique<VehiclePropValuePool>()),
242 mServerSidePropStore(new VehiclePropertyStore(mValuePool)),
243 mFakeObd2Frame(new obd2frame::FakeObd2Frame(mServerSidePropStore)),
244 mFakeUserHal(new FakeUserHal(mValuePool)),
245 mRecurrentTimer(new RecurrentTimer()),
246 mGeneratorHub(new GeneratorHub(
247 [this](const VehiclePropValue& value) { eventFromVehicleBus(value); })),
248 mPendingGetValueRequests(this),
249 mPendingSetValueRequests(this),
250 mDefaultConfigDir(defaultConfigDir),
251 mOverrideConfigDir(overrideConfigDir),
252 mForceOverride(forceOverride) {
253 init();
254 }
255
~FakeVehicleHardware()256 FakeVehicleHardware::~FakeVehicleHardware() {
257 mPendingGetValueRequests.stop();
258 mPendingSetValueRequests.stop();
259 mGeneratorHub.reset();
260 }
261
loadConfigDeclarations()262 std::unordered_map<int32_t, ConfigDeclaration> FakeVehicleHardware::loadConfigDeclarations() {
263 std::unordered_map<int32_t, ConfigDeclaration> configsByPropId;
264 loadPropConfigsFromDir(mDefaultConfigDir, &configsByPropId);
265 if (mForceOverride ||
266 android::base::GetBoolProperty(OVERRIDE_PROPERTY, /*default_value=*/false)) {
267 loadPropConfigsFromDir(mOverrideConfigDir, &configsByPropId);
268 }
269 return configsByPropId;
270 }
271
init()272 void FakeVehicleHardware::init() {
273 for (auto& [_, configDeclaration] : loadConfigDeclarations()) {
274 VehiclePropConfig cfg = configDeclaration.config;
275 VehiclePropertyStore::TokenFunction tokenFunction = nullptr;
276
277 if (cfg.prop == toInt(VehicleProperty::AP_POWER_STATE_REQ)) {
278 int config = GetIntProperty(POWER_STATE_REQ_CONFIG_PROPERTY, /*default_value=*/0);
279 cfg.configArray[0] = config;
280 } else if (cfg.prop == OBD2_FREEZE_FRAME) {
281 tokenFunction = [](const VehiclePropValue& propValue) { return propValue.timestamp; };
282 }
283
284 mServerSidePropStore->registerProperty(cfg, tokenFunction);
285 if (obd2frame::FakeObd2Frame::isDiagnosticProperty(cfg)) {
286 // Ignore storing default value for diagnostic property. They have special get/set
287 // logic.
288 continue;
289 }
290 storePropInitialValue(configDeclaration);
291 }
292
293 // OBD2_LIVE_FRAME and OBD2_FREEZE_FRAME must be configured in default configs.
294 auto maybeObd2LiveFrame = mServerSidePropStore->getConfig(OBD2_LIVE_FRAME);
295 if (maybeObd2LiveFrame.has_value()) {
296 mFakeObd2Frame->initObd2LiveFrame(*maybeObd2LiveFrame.value());
297 }
298 auto maybeObd2FreezeFrame = mServerSidePropStore->getConfig(OBD2_FREEZE_FRAME);
299 if (maybeObd2FreezeFrame.has_value()) {
300 mFakeObd2Frame->initObd2FreezeFrame(*maybeObd2FreezeFrame.value());
301 }
302
303 mServerSidePropStore->setOnValueChangeCallback(
304 [this](const VehiclePropValue& value) { return onValueChangeCallback(value); });
305 }
306
getAllPropertyConfigs() const307 std::vector<VehiclePropConfig> FakeVehicleHardware::getAllPropertyConfigs() const {
308 std::vector<VehiclePropConfig> allConfigs = mServerSidePropStore->getAllConfigs();
309 if (mAddExtraTestVendorConfigs) {
310 generateVendorConfigs(/* outAllConfigs= */ allConfigs);
311 }
312 return allConfigs;
313 }
314
createApPowerStateReq(VehicleApPowerStateReq state)315 VehiclePropValuePool::RecyclableType FakeVehicleHardware::createApPowerStateReq(
316 VehicleApPowerStateReq state) {
317 auto req = mValuePool->obtain(VehiclePropertyType::INT32_VEC, 2);
318 req->prop = toInt(VehicleProperty::AP_POWER_STATE_REQ);
319 req->areaId = 0;
320 req->timestamp = elapsedRealtimeNano();
321 req->status = VehiclePropertyStatus::AVAILABLE;
322 req->value.int32Values[0] = toInt(state);
323 // Param = 0.
324 req->value.int32Values[1] = 0;
325 return req;
326 }
327
createAdasStateReq(int32_t propertyId,int32_t areaId,int32_t state)328 VehiclePropValuePool::RecyclableType FakeVehicleHardware::createAdasStateReq(int32_t propertyId,
329 int32_t areaId,
330 int32_t state) {
331 auto req = mValuePool->obtain(VehiclePropertyType::INT32);
332 req->prop = propertyId;
333 req->areaId = areaId;
334 req->timestamp = elapsedRealtimeNano();
335 req->status = VehiclePropertyStatus::AVAILABLE;
336 req->value.int32Values[0] = state;
337 return req;
338 }
339
setApPowerStateReport(const VehiclePropValue & value)340 VhalResult<void> FakeVehicleHardware::setApPowerStateReport(const VehiclePropValue& value) {
341 auto updatedValue = mValuePool->obtain(value);
342 updatedValue->timestamp = elapsedRealtimeNano();
343
344 if (auto writeResult = mServerSidePropStore->writeValue(std::move(updatedValue));
345 !writeResult.ok()) {
346 return StatusError(getErrorCode(writeResult))
347 << "failed to write value into property store, error: " << getErrorMsg(writeResult);
348 }
349
350 VehiclePropValuePool::RecyclableType prop;
351 int32_t state = value.value.int32Values[0];
352 switch (state) {
353 case toInt(VehicleApPowerStateReport::DEEP_SLEEP_EXIT):
354 [[fallthrough]];
355 case toInt(VehicleApPowerStateReport::HIBERNATION_EXIT):
356 [[fallthrough]];
357 case toInt(VehicleApPowerStateReport::SHUTDOWN_CANCELLED):
358 [[fallthrough]];
359 case toInt(VehicleApPowerStateReport::WAIT_FOR_VHAL):
360 // CPMS is in WAIT_FOR_VHAL state, simply move to ON and send back to HAL.
361 prop = createApPowerStateReq(VehicleApPowerStateReq::ON);
362
363 // ALWAYS update status for generated property value, and force a property update event
364 // because in the case when Car Service crashes, the power state would already be ON
365 // when we receive WAIT_FOR_VHAL and thus new property change event would be generated.
366 // However, Car Service always expect a property change event even though there is no
367 // actual state change.
368 if (auto writeResult =
369 mServerSidePropStore->writeValue(std::move(prop), /*updateStatus=*/true,
370 VehiclePropertyStore::EventMode::ALWAYS);
371 !writeResult.ok()) {
372 return StatusError(getErrorCode(writeResult))
373 << "failed to write AP_POWER_STATE_REQ into property store, error: "
374 << getErrorMsg(writeResult);
375 }
376 break;
377 case toInt(VehicleApPowerStateReport::DEEP_SLEEP_ENTRY):
378 [[fallthrough]];
379 case toInt(VehicleApPowerStateReport::HIBERNATION_ENTRY):
380 [[fallthrough]];
381 case toInt(VehicleApPowerStateReport::SHUTDOWN_START):
382 // CPMS is in WAIT_FOR_FINISH state, send the FINISHED command
383 // Send back to HAL
384 // ALWAYS update status for generated property value
385 prop = createApPowerStateReq(VehicleApPowerStateReq::FINISHED);
386 if (auto writeResult =
387 mServerSidePropStore->writeValue(std::move(prop), /*updateStatus=*/true);
388 !writeResult.ok()) {
389 return StatusError(getErrorCode(writeResult))
390 << "failed to write AP_POWER_STATE_REQ into property store, error: "
391 << getErrorMsg(writeResult);
392 }
393 break;
394 default:
395 ALOGE("Unknown VehicleApPowerStateReport: %d", state);
396 break;
397 }
398 return {};
399 }
400
getHvacTempNumIncrements(int requestedTemp,int minTemp,int maxTemp,int increment)401 int FakeVehicleHardware::getHvacTempNumIncrements(int requestedTemp, int minTemp, int maxTemp,
402 int increment) {
403 requestedTemp = std::max(requestedTemp, minTemp);
404 requestedTemp = std::min(requestedTemp, maxTemp);
405 int numIncrements = (requestedTemp - minTemp) / increment;
406 return numIncrements;
407 }
408
updateHvacTemperatureValueSuggestionInput(const std::vector<int> & hvacTemperatureSetConfigArray,std::vector<float> * hvacTemperatureValueSuggestionInput)409 void FakeVehicleHardware::updateHvacTemperatureValueSuggestionInput(
410 const std::vector<int>& hvacTemperatureSetConfigArray,
411 std::vector<float>* hvacTemperatureValueSuggestionInput) {
412 int minTempInCelsius = hvacTemperatureSetConfigArray[0];
413 int maxTempInCelsius = hvacTemperatureSetConfigArray[1];
414 int incrementInCelsius = hvacTemperatureSetConfigArray[2];
415
416 int minTempInFahrenheit = hvacTemperatureSetConfigArray[3];
417 int maxTempInFahrenheit = hvacTemperatureSetConfigArray[4];
418 int incrementInFahrenheit = hvacTemperatureSetConfigArray[5];
419
420 // The HVAC_TEMPERATURE_SET config array values are temperature values that have been multiplied
421 // by 10 and converted to integers. Therefore, requestedTemp must also be multiplied by 10 and
422 // converted to an integer in order for them to be the same units.
423 int requestedTemp = static_cast<int>((*hvacTemperatureValueSuggestionInput)[0] * 10.0f);
424 int numIncrements =
425 (*hvacTemperatureValueSuggestionInput)[1] == toInt(VehicleUnit::CELSIUS)
426 ? getHvacTempNumIncrements(requestedTemp, minTempInCelsius, maxTempInCelsius,
427 incrementInCelsius)
428 : getHvacTempNumIncrements(requestedTemp, minTempInFahrenheit,
429 maxTempInFahrenheit, incrementInFahrenheit);
430
431 int suggestedTempInCelsius = minTempInCelsius + incrementInCelsius * numIncrements;
432 int suggestedTempInFahrenheit = minTempInFahrenheit + incrementInFahrenheit * numIncrements;
433 // HVAC_TEMPERATURE_VALUE_SUGGESTION specifies the temperature values to be in the original
434 // floating point form so we divide by 10 and convert to float.
435 (*hvacTemperatureValueSuggestionInput)[2] = static_cast<float>(suggestedTempInCelsius) / 10.0f;
436 (*hvacTemperatureValueSuggestionInput)[3] =
437 static_cast<float>(suggestedTempInFahrenheit) / 10.0f;
438 }
439
setHvacTemperatureValueSuggestion(const VehiclePropValue & hvacTemperatureValueSuggestion)440 VhalResult<void> FakeVehicleHardware::setHvacTemperatureValueSuggestion(
441 const VehiclePropValue& hvacTemperatureValueSuggestion) {
442 auto hvacTemperatureSetConfigResult =
443 mServerSidePropStore->getConfig(toInt(VehicleProperty::HVAC_TEMPERATURE_SET));
444
445 if (!hvacTemperatureSetConfigResult.ok()) {
446 return StatusError(getErrorCode(hvacTemperatureSetConfigResult)) << StringPrintf(
447 "Failed to set HVAC_TEMPERATURE_VALUE_SUGGESTION because"
448 " HVAC_TEMPERATURE_SET could not be retrieved. Error: %s",
449 getErrorMsg(hvacTemperatureSetConfigResult).c_str());
450 }
451
452 const auto& originalInput = hvacTemperatureValueSuggestion.value.floatValues;
453 if (originalInput.size() != 4) {
454 return StatusError(StatusCode::INVALID_ARG) << StringPrintf(
455 "Failed to set HVAC_TEMPERATURE_VALUE_SUGGESTION because float"
456 " array value is not size 4.");
457 }
458
459 bool isTemperatureUnitSpecified = originalInput[1] == toInt(VehicleUnit::CELSIUS) ||
460 originalInput[1] == toInt(VehicleUnit::FAHRENHEIT);
461 if (!isTemperatureUnitSpecified) {
462 return StatusError(StatusCode::INVALID_ARG) << StringPrintf(
463 "Failed to set HVAC_TEMPERATURE_VALUE_SUGGESTION because float"
464 " value at index 1 is not any of %d or %d, which corresponds to"
465 " VehicleUnit#CELSIUS and VehicleUnit#FAHRENHEIT respectively.",
466 toInt(VehicleUnit::CELSIUS), toInt(VehicleUnit::FAHRENHEIT));
467 }
468
469 auto updatedValue = mValuePool->obtain(hvacTemperatureValueSuggestion);
470 const auto& hvacTemperatureSetConfigArray = hvacTemperatureSetConfigResult.value()->configArray;
471 auto& hvacTemperatureValueSuggestionInput = updatedValue->value.floatValues;
472
473 updateHvacTemperatureValueSuggestionInput(hvacTemperatureSetConfigArray,
474 &hvacTemperatureValueSuggestionInput);
475
476 updatedValue->timestamp = elapsedRealtimeNano();
477 auto writeResult = mServerSidePropStore->writeValue(std::move(updatedValue),
478 /* updateStatus = */ true,
479 VehiclePropertyStore::EventMode::ALWAYS);
480 if (!writeResult.ok()) {
481 return StatusError(getErrorCode(writeResult))
482 << StringPrintf("failed to write value into property store, error: %s",
483 getErrorMsg(writeResult).c_str());
484 }
485
486 return {};
487 }
488
isHvacPropAndHvacNotAvailable(int32_t propId,int32_t areaId) const489 bool FakeVehicleHardware::isHvacPropAndHvacNotAvailable(int32_t propId, int32_t areaId) const {
490 std::unordered_set<int32_t> powerProps(std::begin(HVAC_POWER_PROPERTIES),
491 std::end(HVAC_POWER_PROPERTIES));
492 if (powerProps.count(propId)) {
493 auto hvacPowerOnResults =
494 mServerSidePropStore->readValuesForProperty(toInt(VehicleProperty::HVAC_POWER_ON));
495 if (!hvacPowerOnResults.ok()) {
496 ALOGW("failed to get HVAC_POWER_ON 0x%x, error: %s",
497 toInt(VehicleProperty::HVAC_POWER_ON), getErrorMsg(hvacPowerOnResults).c_str());
498 return false;
499 }
500 auto& hvacPowerOnValues = hvacPowerOnResults.value();
501 for (size_t j = 0; j < hvacPowerOnValues.size(); j++) {
502 auto hvacPowerOnValue = std::move(hvacPowerOnValues[j]);
503 if ((hvacPowerOnValue->areaId & areaId) == areaId) {
504 if (hvacPowerOnValue->value.int32Values.size() == 1 &&
505 hvacPowerOnValue->value.int32Values[0] == 0) {
506 return true;
507 }
508 break;
509 }
510 }
511 }
512 return false;
513 }
514
isAdasPropertyAvailable(int32_t adasStatePropertyId) const515 VhalResult<void> FakeVehicleHardware::isAdasPropertyAvailable(int32_t adasStatePropertyId) const {
516 auto adasStateResult = mServerSidePropStore->readValue(adasStatePropertyId);
517 if (!adasStateResult.ok()) {
518 ALOGW("Failed to get ADAS ENABLED property 0x%x, error: %s", adasStatePropertyId,
519 getErrorMsg(adasStateResult).c_str());
520 return {};
521 }
522
523 if (adasStateResult.value()->value.int32Values.size() == 1 &&
524 adasStateResult.value()->value.int32Values[0] < 0) {
525 auto errorState = adasStateResult.value()->value.int32Values[0];
526 switch (errorState) {
527 case toInt(ErrorState::NOT_AVAILABLE_DISABLED):
528 return StatusError(StatusCode::NOT_AVAILABLE_DISABLED)
529 << "ADAS feature is disabled.";
530 case toInt(ErrorState::NOT_AVAILABLE_SPEED_LOW):
531 return StatusError(StatusCode::NOT_AVAILABLE_SPEED_LOW)
532 << "ADAS feature is disabled because the vehicle speed is too low.";
533 case toInt(ErrorState::NOT_AVAILABLE_SPEED_HIGH):
534 return StatusError(StatusCode::NOT_AVAILABLE_SPEED_HIGH)
535 << "ADAS feature is disabled because the vehicle speed is too high.";
536 case toInt(ErrorState::NOT_AVAILABLE_POOR_VISIBILITY):
537 return StatusError(StatusCode::NOT_AVAILABLE_POOR_VISIBILITY)
538 << "ADAS feature is disabled because the visibility is too poor.";
539 case toInt(ErrorState::NOT_AVAILABLE_SAFETY):
540 return StatusError(StatusCode::NOT_AVAILABLE_SAFETY)
541 << "ADAS feature is disabled because of safety reasons.";
542 default:
543 return StatusError(StatusCode::NOT_AVAILABLE) << "ADAS feature is not available.";
544 }
545 }
546
547 return {};
548 }
549
setUserHalProp(const VehiclePropValue & value)550 VhalResult<void> FakeVehicleHardware::setUserHalProp(const VehiclePropValue& value) {
551 auto result = mFakeUserHal->onSetProperty(value);
552 if (!result.ok()) {
553 return StatusError(getErrorCode(result))
554 << "onSetProperty(): HAL returned error: " << getErrorMsg(result);
555 }
556 auto& updatedValue = result.value();
557 if (updatedValue != nullptr) {
558 ALOGI("onSetProperty(): updating property returned by HAL: %s",
559 updatedValue->toString().c_str());
560 // Update timestamp otherwise writeValue might fail because the timestamp is outdated.
561 updatedValue->timestamp = elapsedRealtimeNano();
562 if (auto writeResult = mServerSidePropStore->writeValue(
563 std::move(result.value()),
564 /*updateStatus=*/true, VehiclePropertyStore::EventMode::ALWAYS);
565 !writeResult.ok()) {
566 return StatusError(getErrorCode(writeResult))
567 << "failed to write value into property store, error: "
568 << getErrorMsg(writeResult);
569 }
570 }
571 return {};
572 }
573
getUserHalProp(const VehiclePropValue & value) const574 FakeVehicleHardware::ValueResultType FakeVehicleHardware::getUserHalProp(
575 const VehiclePropValue& value) const {
576 auto propId = value.prop;
577 ALOGI("get(): getting value for prop %d from User HAL", propId);
578
579 auto result = mFakeUserHal->onGetProperty(value);
580 if (!result.ok()) {
581 return StatusError(getErrorCode(result))
582 << "get(): User HAL returned error: " << getErrorMsg(result);
583 } else {
584 auto& gotValue = result.value();
585 if (gotValue != nullptr) {
586 ALOGI("get(): User HAL returned value: %s", gotValue->toString().c_str());
587 gotValue->timestamp = elapsedRealtimeNano();
588 return result;
589 } else {
590 return StatusError(StatusCode::INTERNAL_ERROR) << "get(): User HAL returned null value";
591 }
592 }
593 }
594
maybeGetSpecialValue(const VehiclePropValue & value,bool * isSpecialValue) const595 FakeVehicleHardware::ValueResultType FakeVehicleHardware::maybeGetSpecialValue(
596 const VehiclePropValue& value, bool* isSpecialValue) const {
597 *isSpecialValue = false;
598 int32_t propId = value.prop;
599 ValueResultType result;
600
601 if (propId >= STARTING_VENDOR_CODE_PROPERTIES_FOR_TEST &&
602 propId < ENDING_VENDOR_CODE_PROPERTIES_FOR_TEST) {
603 *isSpecialValue = true;
604 result = mValuePool->obtainInt32(/* value= */ 5);
605
606 result.value()->prop = propId;
607 result.value()->areaId = 0;
608 result.value()->timestamp = elapsedRealtimeNano();
609 return result;
610 }
611
612 if (mFakeUserHal->isSupported(propId)) {
613 *isSpecialValue = true;
614 return getUserHalProp(value);
615 }
616
617 if (isHvacPropAndHvacNotAvailable(propId, value.areaId)) {
618 *isSpecialValue = true;
619 return StatusError(StatusCode::NOT_AVAILABLE_DISABLED) << "hvac not available";
620 }
621
622 switch (propId) {
623 case OBD2_FREEZE_FRAME:
624 *isSpecialValue = true;
625 result = mFakeObd2Frame->getObd2FreezeFrame(value);
626 if (result.ok()) {
627 result.value()->timestamp = elapsedRealtimeNano();
628 }
629 return result;
630 case OBD2_FREEZE_FRAME_INFO:
631 *isSpecialValue = true;
632 result = mFakeObd2Frame->getObd2DtcInfo();
633 if (result.ok()) {
634 result.value()->timestamp = elapsedRealtimeNano();
635 }
636 return result;
637 case ECHO_REVERSE_BYTES:
638 *isSpecialValue = true;
639 return getEchoReverseBytes(value);
640 case VENDOR_PROPERTY_ID:
641 *isSpecialValue = true;
642 return StatusError((StatusCode)VENDOR_ERROR_CODE);
643 case toInt(VehicleProperty::CRUISE_CONTROL_TARGET_SPEED):
644 [[fallthrough]];
645 case toInt(VehicleProperty::ADAPTIVE_CRUISE_CONTROL_TARGET_TIME_GAP):
646 [[fallthrough]];
647 case toInt(VehicleProperty::ADAPTIVE_CRUISE_CONTROL_LEAD_VEHICLE_MEASURED_DISTANCE): {
648 auto isAdasPropertyAvailableResult =
649 isAdasPropertyAvailable(toInt(VehicleProperty::CRUISE_CONTROL_STATE));
650 if (!isAdasPropertyAvailableResult.ok()) {
651 *isSpecialValue = true;
652 return isAdasPropertyAvailableResult.error();
653 }
654 return nullptr;
655 }
656 default:
657 // Do nothing.
658 break;
659 }
660
661 return nullptr;
662 }
663
getEchoReverseBytes(const VehiclePropValue & value) const664 FakeVehicleHardware::ValueResultType FakeVehicleHardware::getEchoReverseBytes(
665 const VehiclePropValue& value) const {
666 auto readResult = mServerSidePropStore->readValue(value);
667 if (!readResult.ok()) {
668 return readResult;
669 }
670 auto& gotValue = readResult.value();
671 gotValue->timestamp = elapsedRealtimeNano();
672 std::vector<uint8_t> byteValues = gotValue->value.byteValues;
673 size_t byteSize = byteValues.size();
674 for (size_t i = 0; i < byteSize; i++) {
675 gotValue->value.byteValues[i] = byteValues[byteSize - 1 - i];
676 }
677 return std::move(gotValue);
678 }
679
sendHvacPropertiesCurrentValues(int32_t areaId)680 void FakeVehicleHardware::sendHvacPropertiesCurrentValues(int32_t areaId) {
681 for (size_t i = 0; i < sizeof(HVAC_POWER_PROPERTIES) / sizeof(int32_t); i++) {
682 int powerPropId = HVAC_POWER_PROPERTIES[i];
683 auto powerPropResults = mServerSidePropStore->readValuesForProperty(powerPropId);
684 if (!powerPropResults.ok()) {
685 ALOGW("failed to get power prop 0x%x, error: %s", powerPropId,
686 getErrorMsg(powerPropResults).c_str());
687 continue;
688 }
689 auto& powerPropValues = powerPropResults.value();
690 for (size_t j = 0; j < powerPropValues.size(); j++) {
691 auto powerPropValue = std::move(powerPropValues[j]);
692 if ((powerPropValue->areaId & areaId) == powerPropValue->areaId) {
693 powerPropValue->status = VehiclePropertyStatus::AVAILABLE;
694 powerPropValue->timestamp = elapsedRealtimeNano();
695 // This will trigger a property change event for the current hvac property value.
696 mServerSidePropStore->writeValue(std::move(powerPropValue), /*updateStatus=*/true,
697 VehiclePropertyStore::EventMode::ALWAYS);
698 }
699 }
700 }
701 }
702
sendAdasPropertiesState(int32_t propertyId,int32_t state)703 void FakeVehicleHardware::sendAdasPropertiesState(int32_t propertyId, int32_t state) {
704 auto& adasDependentPropIds = mAdasEnabledPropToAdasPropWithErrorState.find(propertyId)->second;
705 for (auto dependentPropId : adasDependentPropIds) {
706 auto dependentPropConfigResult = mServerSidePropStore->getConfig(dependentPropId);
707 if (!dependentPropConfigResult.ok()) {
708 ALOGW("Failed to get config for ADAS property 0x%x, error: %s", dependentPropId,
709 getErrorMsg(dependentPropConfigResult).c_str());
710 continue;
711 }
712 auto& dependentPropConfig = dependentPropConfigResult.value();
713 for (auto& areaConfig : dependentPropConfig->areaConfigs) {
714 auto propValue = createAdasStateReq(dependentPropId, areaConfig.areaId, state);
715 // This will trigger a property change event for the current ADAS property value.
716 mServerSidePropStore->writeValue(std::move(propValue), /*updateStatus=*/true,
717 VehiclePropertyStore::EventMode::ALWAYS);
718 }
719 }
720 }
721
maybeSetSpecialValue(const VehiclePropValue & value,bool * isSpecialValue)722 VhalResult<void> FakeVehicleHardware::maybeSetSpecialValue(const VehiclePropValue& value,
723 bool* isSpecialValue) {
724 *isSpecialValue = false;
725 VehiclePropValuePool::RecyclableType updatedValue;
726 int32_t propId = value.prop;
727
728 if (propId >= STARTING_VENDOR_CODE_PROPERTIES_FOR_TEST &&
729 propId < ENDING_VENDOR_CODE_PROPERTIES_FOR_TEST) {
730 *isSpecialValue = true;
731 return {};
732 }
733
734 if (mFakeUserHal->isSupported(propId)) {
735 *isSpecialValue = true;
736 return setUserHalProp(value);
737 }
738
739 if (propId == toInt(VehicleProperty::HVAC_POWER_ON) && value.value.int32Values.size() == 1 &&
740 value.value.int32Values[0] == 1) {
741 // If we are turning HVAC power on, send current hvac property values through on change
742 // event.
743 sendHvacPropertiesCurrentValues(value.areaId);
744 }
745
746 if (isHvacPropAndHvacNotAvailable(propId, value.areaId)) {
747 *isSpecialValue = true;
748 return StatusError(StatusCode::NOT_AVAILABLE_DISABLED) << "hvac not available";
749 }
750
751 if (mAdasEnabledPropToAdasPropWithErrorState.count(propId) &&
752 value.value.int32Values.size() == 1) {
753 if (value.value.int32Values[0] == 1) {
754 // Set default state to 1 when ADAS feature is enabled.
755 sendAdasPropertiesState(propId, /* state = */ 1);
756 } else {
757 sendAdasPropertiesState(propId, toInt(ErrorState::NOT_AVAILABLE_DISABLED));
758 }
759 }
760
761 switch (propId) {
762 case toInt(VehicleProperty::AP_POWER_STATE_REPORT):
763 *isSpecialValue = true;
764 return setApPowerStateReport(value);
765 case toInt(VehicleProperty::VEHICLE_MAP_SERVICE):
766 // Placeholder for future implementation of VMS property in the default hal. For
767 // now, just returns OK; otherwise, hal clients crash with property not supported.
768 *isSpecialValue = true;
769 return {};
770 case OBD2_FREEZE_FRAME_CLEAR:
771 *isSpecialValue = true;
772 return mFakeObd2Frame->clearObd2FreezeFrames(value);
773 case VENDOR_PROPERTY_ID:
774 *isSpecialValue = true;
775 return StatusError((StatusCode)VENDOR_ERROR_CODE);
776 case toInt(VehicleProperty::HVAC_TEMPERATURE_VALUE_SUGGESTION):
777 *isSpecialValue = true;
778 return setHvacTemperatureValueSuggestion(value);
779 case toInt(VehicleProperty::LANE_CENTERING_ASSIST_COMMAND): {
780 auto isAdasPropertyAvailableResult =
781 isAdasPropertyAvailable(toInt(VehicleProperty::LANE_CENTERING_ASSIST_STATE));
782 if (!isAdasPropertyAvailableResult.ok()) {
783 *isSpecialValue = true;
784 }
785 return isAdasPropertyAvailableResult;
786 }
787 case toInt(VehicleProperty::CRUISE_CONTROL_COMMAND):
788 [[fallthrough]];
789 case toInt(VehicleProperty::ADAPTIVE_CRUISE_CONTROL_TARGET_TIME_GAP): {
790 auto isAdasPropertyAvailableResult =
791 isAdasPropertyAvailable(toInt(VehicleProperty::CRUISE_CONTROL_STATE));
792 if (!isAdasPropertyAvailableResult.ok()) {
793 *isSpecialValue = true;
794 }
795 return isAdasPropertyAvailableResult;
796 }
797
798 #ifdef ENABLE_VEHICLE_HAL_TEST_PROPERTIES
799 case toInt(VehicleProperty::CLUSTER_REPORT_STATE):
800 [[fallthrough]];
801 case toInt(VehicleProperty::CLUSTER_REQUEST_DISPLAY):
802 [[fallthrough]];
803 case toInt(VehicleProperty::CLUSTER_NAVIGATION_STATE):
804 [[fallthrough]];
805 case VENDOR_CLUSTER_SWITCH_UI:
806 [[fallthrough]];
807 case VENDOR_CLUSTER_DISPLAY_STATE:
808 *isSpecialValue = true;
809 updatedValue = mValuePool->obtain(getPropType(value.prop));
810 updatedValue->prop = value.prop & ~toInt(VehiclePropertyGroup::MASK);
811 if (getPropGroup(value.prop) == VehiclePropertyGroup::SYSTEM) {
812 updatedValue->prop |= toInt(VehiclePropertyGroup::VENDOR);
813 } else {
814 updatedValue->prop |= toInt(VehiclePropertyGroup::SYSTEM);
815 }
816 updatedValue->value = value.value;
817 updatedValue->timestamp = elapsedRealtimeNano();
818 updatedValue->areaId = value.areaId;
819 if (auto writeResult = mServerSidePropStore->writeValue(std::move(updatedValue));
820 !writeResult.ok()) {
821 return StatusError(getErrorCode(writeResult))
822 << "failed to write value into property store, error: "
823 << getErrorMsg(writeResult);
824 }
825 return {};
826 #endif // ENABLE_VEHICLE_HAL_TEST_PROPERTIES
827
828 default:
829 break;
830 }
831 return {};
832 }
833
setValues(std::shared_ptr<const SetValuesCallback> callback,const std::vector<SetValueRequest> & requests)834 StatusCode FakeVehicleHardware::setValues(std::shared_ptr<const SetValuesCallback> callback,
835 const std::vector<SetValueRequest>& requests) {
836 for (auto& request : requests) {
837 if (FAKE_VEHICLEHARDWARE_DEBUG) {
838 ALOGD("Set value for property ID: %d", request.value.prop);
839 }
840
841 // In a real VHAL implementation, you could either send the setValue request to vehicle bus
842 // here in the binder thread, or you could send the request in setValue which runs in
843 // the handler thread. If you decide to send the setValue request here, you should not
844 // wait for the response here and the handler thread should handle the setValue response.
845 mPendingSetValueRequests.addRequest(request, callback);
846 }
847
848 return StatusCode::OK;
849 }
850
setValue(const VehiclePropValue & value)851 VhalResult<void> FakeVehicleHardware::setValue(const VehiclePropValue& value) {
852 // In a real VHAL implementation, this will send the request to vehicle bus if not already
853 // sent in setValues, and wait for the response from vehicle bus.
854 // Here we are just updating mValuePool.
855 bool isSpecialValue = false;
856 auto setSpecialValueResult = maybeSetSpecialValue(value, &isSpecialValue);
857 if (isSpecialValue) {
858 if (!setSpecialValueResult.ok()) {
859 return StatusError(getErrorCode(setSpecialValueResult))
860 << StringPrintf("failed to set special value for property ID: %d, error: %s",
861 value.prop, getErrorMsg(setSpecialValueResult).c_str());
862 }
863 return {};
864 }
865
866 auto updatedValue = mValuePool->obtain(value);
867 int64_t timestamp = elapsedRealtimeNano();
868 updatedValue->timestamp = timestamp;
869
870 auto writeResult = mServerSidePropStore->writeValue(std::move(updatedValue));
871 if (!writeResult.ok()) {
872 return StatusError(getErrorCode(writeResult))
873 << StringPrintf("failed to write value into property store, error: %s",
874 getErrorMsg(writeResult).c_str());
875 }
876
877 return {};
878 }
879
handleSetValueRequest(const SetValueRequest & request)880 SetValueResult FakeVehicleHardware::handleSetValueRequest(const SetValueRequest& request) {
881 SetValueResult setValueResult;
882 setValueResult.requestId = request.requestId;
883
884 if (auto result = setValue(request.value); !result.ok()) {
885 ALOGE("failed to set value, error: %s, code: %d", getErrorMsg(result).c_str(),
886 getIntErrorCode(result));
887 setValueResult.status = getErrorCode(result);
888 } else {
889 setValueResult.status = StatusCode::OK;
890 }
891
892 return setValueResult;
893 }
894
getValues(std::shared_ptr<const GetValuesCallback> callback,const std::vector<GetValueRequest> & requests) const895 StatusCode FakeVehicleHardware::getValues(std::shared_ptr<const GetValuesCallback> callback,
896 const std::vector<GetValueRequest>& requests) const {
897 for (auto& request : requests) {
898 if (FAKE_VEHICLEHARDWARE_DEBUG) {
899 ALOGD("getValues(%d)", request.prop.prop);
900 }
901
902 // In a real VHAL implementation, you could either send the getValue request to vehicle bus
903 // here in the binder thread, or you could send the request in getValue which runs in
904 // the handler thread. If you decide to send the getValue request here, you should not
905 // wait for the response here and the handler thread should handle the getValue response.
906 mPendingGetValueRequests.addRequest(request, callback);
907 }
908
909 return StatusCode::OK;
910 }
911
handleGetValueRequest(const GetValueRequest & request)912 GetValueResult FakeVehicleHardware::handleGetValueRequest(const GetValueRequest& request) {
913 GetValueResult getValueResult;
914 getValueResult.requestId = request.requestId;
915
916 auto result = getValue(request.prop);
917 if (!result.ok()) {
918 ALOGE("failed to get value, error: %s, code: %d", getErrorMsg(result).c_str(),
919 getIntErrorCode(result));
920 getValueResult.status = getErrorCode(result);
921 } else {
922 getValueResult.status = StatusCode::OK;
923 getValueResult.prop = *result.value();
924 }
925 return getValueResult;
926 }
927
getValue(const VehiclePropValue & value) const928 FakeVehicleHardware::ValueResultType FakeVehicleHardware::getValue(
929 const VehiclePropValue& value) const {
930 // In a real VHAL implementation, this will send the request to vehicle bus if not already
931 // sent in getValues, and wait for the response from vehicle bus.
932 // Here we are just reading value from mValuePool.
933 bool isSpecialValue = false;
934 auto result = maybeGetSpecialValue(value, &isSpecialValue);
935 if (isSpecialValue) {
936 if (!result.ok()) {
937 return StatusError(getErrorCode(result))
938 << StringPrintf("failed to get special value: %d, error: %s", value.prop,
939 getErrorMsg(result).c_str());
940 } else {
941 return std::move(result);
942 }
943 }
944
945 auto readResult = mServerSidePropStore->readValue(value);
946 if (!readResult.ok()) {
947 StatusCode errorCode = getErrorCode(readResult);
948 if (errorCode == StatusCode::NOT_AVAILABLE) {
949 return StatusError(errorCode) << "value has not been set yet";
950 } else {
951 return StatusError(errorCode)
952 << "failed to get value, error: " << getErrorMsg(readResult);
953 }
954 }
955
956 return std::move(readResult);
957 }
958
dump(const std::vector<std::string> & options)959 DumpResult FakeVehicleHardware::dump(const std::vector<std::string>& options) {
960 DumpResult result;
961 result.callerShouldDumpState = false;
962 if (options.size() == 0) {
963 // We only want caller to dump default state when there is no options.
964 result.callerShouldDumpState = true;
965 result.buffer = dumpAllProperties();
966 return result;
967 }
968 std::string option = options[0];
969 if (EqualsIgnoreCase(option, "--help")) {
970 result.buffer = dumpHelp();
971 return result;
972 } else if (EqualsIgnoreCase(option, "--list")) {
973 result.buffer = dumpListProperties();
974 } else if (EqualsIgnoreCase(option, "--get")) {
975 result.buffer = dumpSpecificProperty(options);
976 } else if (EqualsIgnoreCase(option, "--getWithArg")) {
977 result.buffer = dumpGetPropertyWithArg(options);
978 } else if (EqualsIgnoreCase(option, "--set")) {
979 result.buffer = dumpSetProperties(options);
980 } else if (EqualsIgnoreCase(option, "--save-prop")) {
981 result.buffer = dumpSaveProperty(options);
982 } else if (EqualsIgnoreCase(option, "--restore-prop")) {
983 result.buffer = dumpRestoreProperty(options);
984 } else if (EqualsIgnoreCase(option, "--inject-event")) {
985 result.buffer = dumpInjectEvent(options);
986 } else if (EqualsIgnoreCase(option, kUserHalDumpOption)) {
987 result.buffer = mFakeUserHal->dump();
988 } else if (EqualsIgnoreCase(option, "--genfakedata")) {
989 result.buffer = genFakeDataCommand(options);
990 } else if (EqualsIgnoreCase(option, "--genTestVendorConfigs")) {
991 mAddExtraTestVendorConfigs = true;
992 result.refreshPropertyConfigs = true;
993 result.buffer = "successfully generated vendor configs";
994 } else if (EqualsIgnoreCase(option, "--restoreVendorConfigs")) {
995 mAddExtraTestVendorConfigs = false;
996 result.refreshPropertyConfigs = true;
997 result.buffer = "successfully restored vendor configs";
998 } else {
999 result.buffer = StringPrintf("Invalid option: %s\n", option.c_str());
1000 }
1001 return result;
1002 }
1003
genFakeDataHelp()1004 std::string FakeVehicleHardware::genFakeDataHelp() {
1005 return R"(
1006 Generate Fake Data Usage:
1007 --genfakedata --startlinear [propID] [mValue] [cValue] [dispersion] [increment] [interval]: "
1008 Start a linear generator that generates event with floatValue within range:
1009 [mValue - disperson, mValue + dispersion].
1010 propID(int32): ID for the property to generate event for.
1011 mValue(float): The middle of the possible values for the property.
1012 cValue(float): The start value for the property, must be within the range.
1013 dispersion(float): The range the value can change.
1014 increment(float): The step the value would increase by for each generated event,
1015 if exceed the range, the value would loop back.
1016 interval(int64): The interval in nanoseconds the event would generate by.
1017
1018 --genfakedata --stoplinear [propID(int32)]: Stop a linear generator
1019
1020 --genfakedata --startjson --path [jsonFilePath] [repetition]:
1021 Start a JSON generator that would generate events according to a JSON file.
1022 jsonFilePath(string): The path to a JSON file. The JSON content must be in the format of
1023 [{
1024 "timestamp": 1000000,
1025 "areaId": 0,
1026 "value": 8,
1027 "prop": 289408000
1028 }, {...}]
1029 Each event in the JSON file would be generated by the same interval their timestamp is relative to
1030 the first event's timestamp.
1031 repetition(int32, optional): how many iterations the events would be generated. If it is not
1032 provided, it would iterate indefinitely.
1033
1034 --genfakedata --startjson --content [jsonContent]: Start a JSON generator using the content.
1035
1036 --genfakedata --stopjson [generatorID(string)]: Stop a JSON generator.
1037
1038 --genfakedata --keypress [keyCode(int32)] [display[int32]]: Generate key press.
1039
1040 --genfakedata --keyinputv2 [area(int32)] [display(int32)] [keyCode[int32]] [action[int32]]
1041 [repeatCount(int32)]
1042
1043 --genfakedata --motioninput [area(int32)] [display(int32)] [inputType[int32]] [action[int32]]
1044 [buttonState(int32)] --pointer [pointerId(int32)] [toolType(int32)] [xData(float)] [yData(float)]
1045 [pressure(float)] [size(float)]
1046 Generate a motion input event. --pointer option can be specified multiple times.
1047
1048 --genTestVendorConfigs: Generates fake VehiclePropConfig ranging from 0x5000 to 0x8000 all with
1049 vendor property group, global vehicle area, and int32 vehicle property type. This is mainly used
1050 for testing
1051
1052 --restoreVendorConfigs: Restores to to the default state if genTestVendorConfigs was used.
1053 Otherwise this will do nothing.
1054
1055 )";
1056 }
1057
1058 std::string FakeVehicleHardware::parseErrMsg(std::string fieldName, std::string value,
1059 std::string type) {
1060 return StringPrintf("failed to parse %s as %s: \"%s\"\n%s", fieldName.c_str(), type.c_str(),
1061 value.c_str(), genFakeDataHelp().c_str());
1062 }
1063
1064 void FakeVehicleHardware::generateVendorConfigs(
1065 std::vector<VehiclePropConfig>& outAllConfigs) const {
1066 for (int i = STARTING_VENDOR_CODE_PROPERTIES_FOR_TEST;
1067 i < ENDING_VENDOR_CODE_PROPERTIES_FOR_TEST; i++) {
1068 VehiclePropConfig config;
1069 config.prop = i;
1070 config.access = VehiclePropertyAccess::READ_WRITE;
1071 outAllConfigs.push_back(config);
1072 }
1073 }
1074
1075 std::string FakeVehicleHardware::genFakeDataCommand(const std::vector<std::string>& options) {
1076 if (options.size() < 2) {
1077 return "No subcommand specified for genfakedata\n" + genFakeDataHelp();
1078 }
1079
1080 std::string command = options[1];
1081 if (command == "--startlinear") {
1082 // --genfakedata --startlinear [propID(int32)] [middleValue(float)]
1083 // [currentValue(float)] [dispersion(float)] [increment(float)] [interval(int64)]
1084 if (options.size() != 8) {
1085 return "incorrect argument count, need 8 arguments for --genfakedata --startlinear\n" +
1086 genFakeDataHelp();
1087 }
1088 int32_t propId;
1089 float middleValue;
1090 float currentValue;
1091 float dispersion;
1092 float increment;
1093 int64_t interval;
1094 if (!android::base::ParseInt(options[2], &propId)) {
1095 return parseErrMsg("propId", options[2], "int");
1096 }
1097 if (!android::base::ParseFloat(options[3], &middleValue)) {
1098 return parseErrMsg("middleValue", options[3], "float");
1099 }
1100 if (!android::base::ParseFloat(options[4], ¤tValue)) {
1101 return parseErrMsg("currentValue", options[4], "float");
1102 }
1103 if (!android::base::ParseFloat(options[5], &dispersion)) {
1104 return parseErrMsg("dispersion", options[5], "float");
1105 }
1106 if (!android::base::ParseFloat(options[6], &increment)) {
1107 return parseErrMsg("increment", options[6], "float");
1108 }
1109 if (!android::base::ParseInt(options[7], &interval)) {
1110 return parseErrMsg("interval", options[7], "int");
1111 }
1112 auto generator = std::make_unique<LinearFakeValueGenerator>(
1113 propId, middleValue, currentValue, dispersion, increment, interval);
1114 mGeneratorHub->registerGenerator(propId, std::move(generator));
1115 return "Linear event generator started successfully";
1116 } else if (command == "--stoplinear") {
1117 // --genfakedata --stoplinear [propID(int32)]
1118 if (options.size() != 3) {
1119 return "incorrect argument count, need 3 arguments for --genfakedata --stoplinear\n" +
1120 genFakeDataHelp();
1121 }
1122 int32_t propId;
1123 if (!android::base::ParseInt(options[2], &propId)) {
1124 return parseErrMsg("propId", options[2], "int");
1125 }
1126 if (mGeneratorHub->unregisterGenerator(propId)) {
1127 return "Linear event generator stopped successfully";
1128 }
1129 return StringPrintf("No linear event generator found for property: %d", propId);
1130 } else if (command == "--startjson") {
1131 // --genfakedata --startjson --path path repetition
1132 // or
1133 // --genfakedata --startjson --content content repetition.
1134 if (options.size() != 4 && options.size() != 5) {
1135 return "incorrect argument count, need 4 or 5 arguments for --genfakedata "
1136 "--startjson\n";
1137 }
1138 // Iterate infinitely if repetition number is not provided
1139 int32_t repetition = -1;
1140 if (options.size() == 5) {
1141 if (!android::base::ParseInt(options[4], &repetition)) {
1142 return parseErrMsg("repetition", options[4], "int");
1143 }
1144 }
1145 std::unique_ptr<JsonFakeValueGenerator> generator;
1146 if (options[2] == "--path") {
1147 const std::string& fileName = options[3];
1148 generator = std::make_unique<JsonFakeValueGenerator>(fileName, repetition);
1149 if (!generator->hasNext()) {
1150 return "invalid JSON file, no events";
1151 }
1152 } else if (options[2] == "--content") {
1153 const std::string& content = options[3];
1154 generator =
1155 std::make_unique<JsonFakeValueGenerator>(/*unused=*/true, content, repetition);
1156 if (!generator->hasNext()) {
1157 return "invalid JSON content, no events";
1158 }
1159 }
1160 int32_t cookie = std::hash<std::string>()(options[3]);
1161 mGeneratorHub->registerGenerator(cookie, std::move(generator));
1162 return StringPrintf("JSON event generator started successfully, ID: %" PRId32, cookie);
1163 } else if (command == "--stopjson") {
1164 // --genfakedata --stopjson [generatorID(string)]
1165 if (options.size() != 3) {
1166 return "incorrect argument count, need 3 arguments for --genfakedata --stopjson\n";
1167 }
1168 int32_t cookie;
1169 if (!android::base::ParseInt(options[2], &cookie)) {
1170 return parseErrMsg("cookie", options[2], "int");
1171 }
1172 if (mGeneratorHub->unregisterGenerator(cookie)) {
1173 return "JSON event generator stopped successfully";
1174 } else {
1175 return StringPrintf("No JSON event generator found for ID: %s", options[2].c_str());
1176 }
1177 } else if (command == "--keypress") {
1178 int32_t keyCode;
1179 int32_t display;
1180 // --genfakedata --keypress [keyCode(int32)] [display[int32]]
1181 if (options.size() != 4) {
1182 return "incorrect argument count, need 4 arguments for --genfakedata --keypress\n";
1183 }
1184 if (!android::base::ParseInt(options[2], &keyCode)) {
1185 return parseErrMsg("keyCode", options[2], "int");
1186 }
1187 if (!android::base::ParseInt(options[3], &display)) {
1188 return parseErrMsg("display", options[3], "int");
1189 }
1190 // Send back to HAL
1191 onValueChangeCallback(
1192 createHwInputKeyProp(VehicleHwKeyInputAction::ACTION_DOWN, keyCode, display));
1193 onValueChangeCallback(
1194 createHwInputKeyProp(VehicleHwKeyInputAction::ACTION_UP, keyCode, display));
1195 return "keypress event generated successfully";
1196 } else if (command == "--keyinputv2") {
1197 int32_t area;
1198 int32_t display;
1199 int32_t keyCode;
1200 int32_t action;
1201 int32_t repeatCount;
1202 // --genfakedata --keyinputv2 [area(int32)] [display(int32)] [keyCode[int32]]
1203 // [action[int32]] [repeatCount(int32)]
1204 if (options.size() != 7) {
1205 return "incorrect argument count, need 7 arguments for --genfakedata --keyinputv2\n";
1206 }
1207 if (!android::base::ParseInt(options[2], &area)) {
1208 return parseErrMsg("area", options[2], "int");
1209 }
1210 if (!android::base::ParseInt(options[3], &display)) {
1211 return parseErrMsg("display", options[3], "int");
1212 }
1213 if (!android::base::ParseInt(options[4], &keyCode)) {
1214 return parseErrMsg("keyCode", options[4], "int");
1215 }
1216 if (!android::base::ParseInt(options[5], &action)) {
1217 return parseErrMsg("action", options[5], "int");
1218 }
1219 if (!android::base::ParseInt(options[6], &repeatCount)) {
1220 return parseErrMsg("repeatCount", options[6], "int");
1221 }
1222 // Send back to HAL
1223 onValueChangeCallback(createHwKeyInputV2Prop(area, display, keyCode, action, repeatCount));
1224 return StringPrintf(
1225 "keyinputv2 event generated successfully with area:%d, display:%d,"
1226 " keyCode:%d, action:%d, repeatCount:%d",
1227 area, display, keyCode, action, repeatCount);
1228
1229 } else if (command == "--motioninput") {
1230 int32_t area;
1231 int32_t display;
1232 int32_t inputType;
1233 int32_t action;
1234 int32_t buttonState;
1235 int32_t pointerCount;
1236
1237 // --genfakedata --motioninput [area(int32)] [display(int32)] [inputType[int32]]
1238 // [action[int32]] [buttonState(int32)] [pointerCount(int32)]
1239 // --pointer [pointerId(int32)] [toolType(int32)] [xData(float)] [yData(float)]
1240 // [pressure(float)] [size(float)]
1241 int optionsSize = (int)options.size();
1242 if (optionsSize / 7 < 2) {
1243 return "incorrect argument count, need at least 14 arguments for --genfakedata "
1244 "--motioninput including at least 1 --pointer\n";
1245 }
1246
1247 if (optionsSize % 7 != 0) {
1248 return "incorrect argument count, need 6 arguments for every --pointer\n";
1249 }
1250 pointerCount = (int)optionsSize / 7 - 1;
1251
1252 if (!android::base::ParseInt(options[2], &area)) {
1253 return parseErrMsg("area", options[2], "int");
1254 }
1255 if (!android::base::ParseInt(options[3], &display)) {
1256 return parseErrMsg("display", options[3], "int");
1257 }
1258 if (!android::base::ParseInt(options[4], &inputType)) {
1259 return parseErrMsg("inputType", options[4], "int");
1260 }
1261 if (!android::base::ParseInt(options[5], &action)) {
1262 return parseErrMsg("action", options[5], "int");
1263 }
1264 if (!android::base::ParseInt(options[6], &buttonState)) {
1265 return parseErrMsg("buttonState", options[6], "int");
1266 }
1267
1268 int32_t pointerId[pointerCount];
1269 int32_t toolType[pointerCount];
1270 float xData[pointerCount];
1271 float yData[pointerCount];
1272 float pressure[pointerCount];
1273 float size[pointerCount];
1274
1275 for (int i = 7, pc = 0; i < optionsSize; i += 7, pc += 1) {
1276 int offset = i;
1277 if (options[offset] != "--pointer") {
1278 return "--pointer is needed for the motion input\n";
1279 }
1280 offset += 1;
1281 if (!android::base::ParseInt(options[offset], &pointerId[pc])) {
1282 return parseErrMsg("pointerId", options[offset], "int");
1283 }
1284 offset += 1;
1285 if (!android::base::ParseInt(options[offset], &toolType[pc])) {
1286 return parseErrMsg("toolType", options[offset], "int");
1287 }
1288 offset += 1;
1289 if (!android::base::ParseFloat(options[offset], &xData[pc])) {
1290 return parseErrMsg("xData", options[offset], "float");
1291 }
1292 offset += 1;
1293 if (!android::base::ParseFloat(options[offset], &yData[pc])) {
1294 return parseErrMsg("yData", options[offset], "float");
1295 }
1296 offset += 1;
1297 if (!android::base::ParseFloat(options[offset], &pressure[pc])) {
1298 return parseErrMsg("pressure", options[offset], "float");
1299 }
1300 offset += 1;
1301 if (!android::base::ParseFloat(options[offset], &size[pc])) {
1302 return parseErrMsg("size", options[offset], "float");
1303 }
1304 }
1305
1306 // Send back to HAL
1307 onValueChangeCallback(createHwMotionInputProp(area, display, inputType, action, buttonState,
1308 pointerCount, pointerId, toolType, xData,
1309 yData, pressure, size));
1310
1311 std::string successMessage = StringPrintf(
1312 "motion event generated successfully with area:%d, display:%d,"
1313 " inputType:%d, action:%d, buttonState:%d, pointerCount:%d\n",
1314 area, display, inputType, action, buttonState, pointerCount);
1315 for (int i = 0; i < pointerCount; i++) {
1316 successMessage += StringPrintf(
1317 "Pointer #%d {\n"
1318 " id:%d , tooltype:%d \n"
1319 " x:%f , y:%f\n"
1320 " pressure: %f, data: %f\n"
1321 "}\n",
1322 i, pointerId[i], toolType[i], xData[i], yData[i], pressure[i], size[i]);
1323 }
1324 return successMessage;
1325 }
1326
1327 return StringPrintf("Unknown command: \"%s\"\n%s", command.c_str(), genFakeDataHelp().c_str());
1328 }
1329
1330 VehiclePropValue FakeVehicleHardware::createHwInputKeyProp(VehicleHwKeyInputAction action,
1331 int32_t keyCode, int32_t targetDisplay) {
1332 VehiclePropValue value = {
1333 .prop = toInt(VehicleProperty::HW_KEY_INPUT),
1334 .areaId = 0,
1335 .timestamp = elapsedRealtimeNano(),
1336 .status = VehiclePropertyStatus::AVAILABLE,
1337 .value.int32Values = {toInt(action), keyCode, targetDisplay},
1338 };
1339 return value;
1340 }
1341
1342 VehiclePropValue FakeVehicleHardware::createHwKeyInputV2Prop(int32_t area, int32_t targetDisplay,
1343 int32_t keyCode, int32_t action,
1344 int32_t repeatCount) {
1345 VehiclePropValue value = {.prop = toInt(VehicleProperty::HW_KEY_INPUT_V2),
1346 .areaId = area,
1347 .timestamp = elapsedRealtimeNano(),
1348 .status = VehiclePropertyStatus::AVAILABLE,
1349 .value.int32Values = {targetDisplay, keyCode, action, repeatCount},
1350 .value.int64Values = {elapsedRealtimeNano()}};
1351 return value;
1352 }
1353
1354 VehiclePropValue FakeVehicleHardware::createHwMotionInputProp(
1355 int32_t area, int32_t display, int32_t inputType, int32_t action, int32_t buttonState,
1356 int32_t pointerCount, int32_t pointerId[], int32_t toolType[], float xData[], float yData[],
1357 float pressure[], float size[]) {
1358 std::vector<int> intValues;
1359 intValues.push_back(display);
1360 intValues.push_back(inputType);
1361 intValues.push_back(action);
1362 intValues.push_back(buttonState);
1363 intValues.push_back(pointerCount);
1364 for (int i = 0; i < pointerCount; i++) {
1365 intValues.push_back(pointerId[i]);
1366 }
1367 for (int i = 0; i < pointerCount; i++) {
1368 intValues.push_back(toolType[i]);
1369 }
1370
1371 std::vector<float> floatValues;
1372 for (int i = 0; i < pointerCount; i++) {
1373 floatValues.push_back(xData[i]);
1374 }
1375 for (int i = 0; i < pointerCount; i++) {
1376 floatValues.push_back(yData[i]);
1377 }
1378 for (int i = 0; i < pointerCount; i++) {
1379 floatValues.push_back(pressure[i]);
1380 }
1381 for (int i = 0; i < pointerCount; i++) {
1382 floatValues.push_back(size[i]);
1383 }
1384
1385 VehiclePropValue value = {.prop = toInt(VehicleProperty::HW_MOTION_INPUT),
1386 .areaId = area,
1387 .timestamp = elapsedRealtimeNano(),
1388 .status = VehiclePropertyStatus::AVAILABLE,
1389 .value.int32Values = intValues,
1390 .value.floatValues = floatValues,
1391 .value.int64Values = {elapsedRealtimeNano()}};
1392 return value;
1393 }
1394
1395 void FakeVehicleHardware::eventFromVehicleBus(const VehiclePropValue& value) {
1396 mServerSidePropStore->writeValue(mValuePool->obtain(value));
1397 }
1398
1399 std::string FakeVehicleHardware::dumpHelp() {
1400 return "Usage: \n\n"
1401 "[no args]: dumps (id and value) all supported properties \n"
1402 "--help: shows this help\n"
1403 "--list: lists the ids of all supported properties\n"
1404 "--get <PROP1> [PROP2] [PROPN]: dumps the value of specific properties. \n"
1405 "--getWithArg <PROP> [ValueArguments]: gets the value for a specific property with "
1406 "arguments. \n"
1407 "--set <PROP> [ValueArguments]: sets the value of property PROP. \n"
1408 "--save-prop <prop> [-a AREA_ID]: saves the current value for PROP, integration test"
1409 " that modifies prop value must call this before test and restore-prop after test. \n"
1410 "--restore-prop <prop> [-a AREA_ID]: restores a previously saved property value. \n"
1411 "--inject-event <PROP> [ValueArguments]: inject a property update event from car\n\n"
1412 "ValueArguments are in the format of [-i INT_VALUE [INT_VALUE ...]] "
1413 "[-i64 INT64_VALUE [INT64_VALUE ...]] [-f FLOAT_VALUE [FLOAT_VALUE ...]] [-s STR_VALUE] "
1414 "[-b BYTES_VALUE] [-a AREA_ID].\n"
1415 "Notice that the string, bytes and area value can be set just once, while the other can"
1416 " have multiple values (so they're used in the respective array), "
1417 "BYTES_VALUE is in the form of 0xXXXX, e.g. 0xdeadbeef.\n" +
1418 genFakeDataHelp() + "Fake user HAL usage: \n" + mFakeUserHal->showDumpHelp();
1419 }
1420
1421 std::string FakeVehicleHardware::dumpAllProperties() {
1422 auto configs = mServerSidePropStore->getAllConfigs();
1423 if (configs.size() == 0) {
1424 return "no properties to dump\n";
1425 }
1426 std::string msg = StringPrintf("dumping %zu properties\n", configs.size());
1427 int rowNumber = 1;
1428 for (const VehiclePropConfig& config : configs) {
1429 msg += dumpOnePropertyByConfig(rowNumber++, config);
1430 }
1431 return msg;
1432 }
1433
1434 std::string FakeVehicleHardware::dumpOnePropertyByConfig(int rowNumber,
1435 const VehiclePropConfig& config) {
1436 size_t numberAreas = config.areaConfigs.size();
1437 std::string msg = "";
1438 if (numberAreas == 0) {
1439 msg += StringPrintf("%d: ", rowNumber);
1440 msg += dumpOnePropertyById(config.prop, /* areaId= */ 0);
1441 return msg;
1442 }
1443 for (size_t j = 0; j < numberAreas; ++j) {
1444 if (numberAreas > 1) {
1445 msg += StringPrintf("%d-%zu: ", rowNumber, j);
1446 } else {
1447 msg += StringPrintf("%d: ", rowNumber);
1448 }
1449 msg += dumpOnePropertyById(config.prop, config.areaConfigs[j].areaId);
1450 }
1451 return msg;
1452 }
1453
1454 std::string FakeVehicleHardware::dumpOnePropertyById(int32_t propId, int32_t areaId) {
1455 VehiclePropValue value = {
1456 .prop = propId,
1457 .areaId = areaId,
1458 };
1459 bool isSpecialValue = false;
1460 auto result = maybeGetSpecialValue(value, &isSpecialValue);
1461 if (!isSpecialValue) {
1462 result = mServerSidePropStore->readValue(value);
1463 }
1464 if (!result.ok()) {
1465 return StringPrintf("failed to read property value: %d, error: %s, code: %d\n", propId,
1466 getErrorMsg(result).c_str(), getIntErrorCode(result));
1467
1468 } else {
1469 return result.value()->toString() + "\n";
1470 }
1471 }
1472
1473 std::string FakeVehicleHardware::dumpListProperties() {
1474 auto configs = mServerSidePropStore->getAllConfigs();
1475 if (configs.size() == 0) {
1476 return "no properties to list\n";
1477 }
1478 int rowNumber = 1;
1479 std::string msg = StringPrintf("listing %zu properties\n", configs.size());
1480 for (const auto& config : configs) {
1481 msg += StringPrintf("%d: %d\n", rowNumber++, config.prop);
1482 }
1483 return msg;
1484 }
1485
1486 Result<void> FakeVehicleHardware::checkArgumentsSize(const std::vector<std::string>& options,
1487 size_t minSize) {
1488 size_t size = options.size();
1489 if (size >= minSize) {
1490 return {};
1491 }
1492 return Error() << StringPrintf("Invalid number of arguments: required at least %zu, got %zu\n",
1493 minSize, size);
1494 }
1495
1496 std::string FakeVehicleHardware::dumpSpecificProperty(const std::vector<std::string>& options) {
1497 if (auto result = checkArgumentsSize(options, /*minSize=*/2); !result.ok()) {
1498 return getErrorMsg(result);
1499 }
1500
1501 // options[0] is the command itself...
1502 int rowNumber = 1;
1503 size_t size = options.size();
1504 std::string msg = "";
1505 for (size_t i = 1; i < size; ++i) {
1506 auto propResult = safelyParseInt<int32_t>(i, options[i]);
1507 if (!propResult.ok()) {
1508 msg += getErrorMsg(propResult);
1509 continue;
1510 }
1511 int32_t prop = propResult.value();
1512 auto result = mServerSidePropStore->getConfig(prop);
1513 if (!result.ok()) {
1514 msg += StringPrintf("No property %d\n", prop);
1515 continue;
1516 }
1517 msg += dumpOnePropertyByConfig(rowNumber++, *result.value());
1518 }
1519 return msg;
1520 }
1521
1522 std::vector<std::string> FakeVehicleHardware::getOptionValues(
1523 const std::vector<std::string>& options, size_t* index) {
1524 std::vector<std::string> values;
1525 while (*index < options.size()) {
1526 std::string option = options[*index];
1527 if (SET_PROP_OPTIONS.find(option) != SET_PROP_OPTIONS.end()) {
1528 return std::move(values);
1529 }
1530 values.push_back(option);
1531 (*index)++;
1532 }
1533 return std::move(values);
1534 }
1535
1536 Result<VehiclePropValue> FakeVehicleHardware::parsePropOptions(
1537 const std::vector<std::string>& options) {
1538 // Options format:
1539 // --set/get/inject-event PROP [-f f1 f2...] [-i i1 i2...] [-i64 i1 i2...] [-s s1 s2...]
1540 // [-b b1 b2...] [-a a] [-t timestamp]
1541 size_t optionIndex = 1;
1542 auto result = safelyParseInt<int32_t>(optionIndex, options[optionIndex]);
1543 if (!result.ok()) {
1544 return Error() << StringPrintf("Property value: \"%s\" is not a valid int: %s\n",
1545 options[optionIndex].c_str(), getErrorMsg(result).c_str());
1546 }
1547 VehiclePropValue prop = {};
1548 prop.prop = result.value();
1549 prop.status = VehiclePropertyStatus::AVAILABLE;
1550 optionIndex++;
1551 std::unordered_set<std::string> parsedOptions;
1552
1553 while (optionIndex < options.size()) {
1554 std::string argType = options[optionIndex];
1555 optionIndex++;
1556
1557 size_t currentIndex = optionIndex;
1558 std::vector<std::string> argValues = getOptionValues(options, &optionIndex);
1559 if (parsedOptions.find(argType) != parsedOptions.end()) {
1560 return Error() << StringPrintf("Duplicate \"%s\" options\n", argType.c_str());
1561 }
1562 parsedOptions.insert(argType);
1563 size_t argValuesSize = argValues.size();
1564 if (EqualsIgnoreCase(argType, "-i")) {
1565 if (argValuesSize == 0) {
1566 return Error() << "No values specified when using \"-i\"\n";
1567 }
1568 prop.value.int32Values.resize(argValuesSize);
1569 for (size_t i = 0; i < argValuesSize; i++) {
1570 auto int32Result = safelyParseInt<int32_t>(currentIndex + i, argValues[i]);
1571 if (!int32Result.ok()) {
1572 return Error()
1573 << StringPrintf("Value: \"%s\" is not a valid int: %s\n",
1574 argValues[i].c_str(), getErrorMsg(int32Result).c_str());
1575 }
1576 prop.value.int32Values[i] = int32Result.value();
1577 }
1578 } else if (EqualsIgnoreCase(argType, "-i64")) {
1579 if (argValuesSize == 0) {
1580 return Error() << "No values specified when using \"-i64\"\n";
1581 }
1582 prop.value.int64Values.resize(argValuesSize);
1583 for (size_t i = 0; i < argValuesSize; i++) {
1584 auto int64Result = safelyParseInt<int64_t>(currentIndex + i, argValues[i]);
1585 if (!int64Result.ok()) {
1586 return Error()
1587 << StringPrintf("Value: \"%s\" is not a valid int64: %s\n",
1588 argValues[i].c_str(), getErrorMsg(int64Result).c_str());
1589 }
1590 prop.value.int64Values[i] = int64Result.value();
1591 }
1592 } else if (EqualsIgnoreCase(argType, "-f")) {
1593 if (argValuesSize == 0) {
1594 return Error() << "No values specified when using \"-f\"\n";
1595 }
1596 prop.value.floatValues.resize(argValuesSize);
1597 for (size_t i = 0; i < argValuesSize; i++) {
1598 auto floatResult = safelyParseFloat(currentIndex + i, argValues[i]);
1599 if (!floatResult.ok()) {
1600 return Error()
1601 << StringPrintf("Value: \"%s\" is not a valid float: %s\n",
1602 argValues[i].c_str(), getErrorMsg(floatResult).c_str());
1603 }
1604 prop.value.floatValues[i] = floatResult.value();
1605 }
1606 } else if (EqualsIgnoreCase(argType, "-s")) {
1607 if (argValuesSize != 1) {
1608 return Error() << "Expect exact one value when using \"-s\"\n";
1609 }
1610 prop.value.stringValue = argValues[0];
1611 } else if (EqualsIgnoreCase(argType, "-b")) {
1612 if (argValuesSize != 1) {
1613 return Error() << "Expect exact one value when using \"-b\"\n";
1614 }
1615 auto bytesResult = parseHexString(argValues[0]);
1616 if (!bytesResult.ok()) {
1617 return Error() << StringPrintf("value: \"%s\" is not a valid hex string: %s\n",
1618 argValues[0].c_str(),
1619 getErrorMsg(bytesResult).c_str());
1620 }
1621 prop.value.byteValues = std::move(bytesResult.value());
1622 } else if (EqualsIgnoreCase(argType, "-a")) {
1623 if (argValuesSize != 1) {
1624 return Error() << "Expect exact one value when using \"-a\"\n";
1625 }
1626 auto int32Result = safelyParseInt<int32_t>(currentIndex, argValues[0]);
1627 if (!int32Result.ok()) {
1628 return Error() << StringPrintf("Area ID: \"%s\" is not a valid int: %s\n",
1629 argValues[0].c_str(),
1630 getErrorMsg(int32Result).c_str());
1631 }
1632 prop.areaId = int32Result.value();
1633 } else if (EqualsIgnoreCase(argType, "-t")) {
1634 if (argValuesSize != 1) {
1635 return Error() << "Expect exact one value when using \"-t\"\n";
1636 }
1637 auto int64Result = safelyParseInt<int64_t>(currentIndex, argValues[0]);
1638 if (!int64Result.ok()) {
1639 return Error() << StringPrintf("Timestamp: \"%s\" is not a valid int64: %s\n",
1640 argValues[0].c_str(),
1641 getErrorMsg(int64Result).c_str());
1642 }
1643 prop.timestamp = int64Result.value();
1644 } else {
1645 return Error() << StringPrintf("Unknown option: %s\n", argType.c_str());
1646 }
1647 }
1648
1649 return prop;
1650 }
1651
dumpSetProperties(const std::vector<std::string> & options)1652 std::string FakeVehicleHardware::dumpSetProperties(const std::vector<std::string>& options) {
1653 if (auto result = checkArgumentsSize(options, 3); !result.ok()) {
1654 return getErrorMsg(result);
1655 }
1656
1657 auto parseResult = parsePropOptions(options);
1658 if (!parseResult.ok()) {
1659 return getErrorMsg(parseResult);
1660 }
1661 VehiclePropValue prop = std::move(parseResult.value());
1662 ALOGD("Dump: Setting property: %s", prop.toString().c_str());
1663
1664 bool isSpecialValue = false;
1665 auto setResult = maybeSetSpecialValue(prop, &isSpecialValue);
1666
1667 if (!isSpecialValue) {
1668 auto updatedValue = mValuePool->obtain(prop);
1669 updatedValue->timestamp = elapsedRealtimeNano();
1670 setResult = mServerSidePropStore->writeValue(std::move(updatedValue));
1671 }
1672
1673 if (setResult.ok()) {
1674 return StringPrintf("Set property: %s\n", prop.toString().c_str());
1675 }
1676 return StringPrintf("failed to set property: %s, error: %s\n", prop.toString().c_str(),
1677 getErrorMsg(setResult).c_str());
1678 }
1679
dumpGetPropertyWithArg(const std::vector<std::string> & options)1680 std::string FakeVehicleHardware::dumpGetPropertyWithArg(const std::vector<std::string>& options) {
1681 if (auto result = checkArgumentsSize(options, 3); !result.ok()) {
1682 return getErrorMsg(result);
1683 }
1684
1685 auto parseResult = parsePropOptions(options);
1686 if (!parseResult.ok()) {
1687 return getErrorMsg(parseResult);
1688 }
1689 VehiclePropValue prop = std::move(parseResult.value());
1690 ALOGD("Dump: Getting property: %s", prop.toString().c_str());
1691
1692 bool isSpecialValue = false;
1693 auto result = maybeGetSpecialValue(prop, &isSpecialValue);
1694
1695 if (!isSpecialValue) {
1696 result = mServerSidePropStore->readValue(prop);
1697 }
1698
1699 if (!result.ok()) {
1700 return StringPrintf("failed to read property value: %d, error: %s, code: %d\n", prop.prop,
1701 getErrorMsg(result).c_str(), getIntErrorCode(result));
1702 }
1703 return StringPrintf("Get property result: %s\n", result.value()->toString().c_str());
1704 }
1705
dumpSaveProperty(const std::vector<std::string> & options)1706 std::string FakeVehicleHardware::dumpSaveProperty(const std::vector<std::string>& options) {
1707 // Format: --save-prop PROP [-a areaID]
1708 if (auto result = checkArgumentsSize(options, 2); !result.ok()) {
1709 return getErrorMsg(result);
1710 }
1711
1712 auto parseResult = parsePropOptions(options);
1713 if (!parseResult.ok()) {
1714 return getErrorMsg(parseResult);
1715 }
1716 // We are only using the prop and areaId option.
1717 VehiclePropValue value = std::move(parseResult.value());
1718 int32_t propId = value.prop;
1719 int32_t areaId = value.areaId;
1720
1721 auto readResult = mServerSidePropStore->readValue(value);
1722 if (!readResult.ok()) {
1723 return StringPrintf("Failed to save current property value, error: %s",
1724 getErrorMsg(readResult).c_str());
1725 }
1726
1727 std::scoped_lock<std::mutex> lockGuard(mLock);
1728 mSavedProps[PropIdAreaId{
1729 .propId = propId,
1730 .areaId = areaId,
1731 }] = std::move(readResult.value());
1732
1733 return StringPrintf("Property: %" PRId32 ", areaID: %" PRId32 " saved", propId, areaId);
1734 }
1735
dumpRestoreProperty(const std::vector<std::string> & options)1736 std::string FakeVehicleHardware::dumpRestoreProperty(const std::vector<std::string>& options) {
1737 // Format: --restore-prop PROP [-a areaID]
1738 if (auto result = checkArgumentsSize(options, 2); !result.ok()) {
1739 return getErrorMsg(result);
1740 }
1741
1742 auto parseResult = parsePropOptions(options);
1743 if (!parseResult.ok()) {
1744 return getErrorMsg(parseResult);
1745 }
1746 // We are only using the prop and areaId option.
1747 VehiclePropValue value = std::move(parseResult.value());
1748 int32_t propId = value.prop;
1749 int32_t areaId = value.areaId;
1750 VehiclePropValuePool::RecyclableType savedValue;
1751
1752 {
1753 std::scoped_lock<std::mutex> lockGuard(mLock);
1754 auto it = mSavedProps.find(PropIdAreaId{
1755 .propId = propId,
1756 .areaId = areaId,
1757 });
1758 if (it == mSavedProps.end()) {
1759 return StringPrintf("No saved property for property: %" PRId32 ", areaID: %" PRId32,
1760 propId, areaId);
1761 }
1762
1763 savedValue = std::move(it->second);
1764 // Remove the saved property after restoring it.
1765 mSavedProps.erase(it);
1766 }
1767
1768 // Update timestamp.
1769 savedValue->timestamp = elapsedRealtimeNano();
1770
1771 auto writeResult = mServerSidePropStore->writeValue(std::move(savedValue));
1772 if (!writeResult.ok()) {
1773 return StringPrintf("Failed to restore property value, error: %s",
1774 getErrorMsg(writeResult).c_str());
1775 }
1776
1777 return StringPrintf("Property: %" PRId32 ", areaID: %" PRId32 " restored", propId, areaId);
1778 }
1779
dumpInjectEvent(const std::vector<std::string> & options)1780 std::string FakeVehicleHardware::dumpInjectEvent(const std::vector<std::string>& options) {
1781 if (auto result = checkArgumentsSize(options, 3); !result.ok()) {
1782 return getErrorMsg(result);
1783 }
1784
1785 auto parseResult = parsePropOptions(options);
1786 if (!parseResult.ok()) {
1787 return getErrorMsg(parseResult);
1788 }
1789 VehiclePropValue prop = std::move(parseResult.value());
1790 ALOGD("Dump: Injecting event from vehicle bus: %s", prop.toString().c_str());
1791
1792 eventFromVehicleBus(prop);
1793
1794 return StringPrintf("Event for property: %d injected", prop.prop);
1795 }
1796
checkHealth()1797 StatusCode FakeVehicleHardware::checkHealth() {
1798 // Always return OK for checkHealth.
1799 return StatusCode::OK;
1800 }
1801
registerOnPropertyChangeEvent(std::unique_ptr<const PropertyChangeCallback> callback)1802 void FakeVehicleHardware::registerOnPropertyChangeEvent(
1803 std::unique_ptr<const PropertyChangeCallback> callback) {
1804 if (mOnPropertyChangeCallback != nullptr) {
1805 ALOGE("registerOnPropertyChangeEvent must only be called once");
1806 return;
1807 }
1808 mOnPropertyChangeCallback = std::move(callback);
1809 }
1810
registerOnPropertySetErrorEvent(std::unique_ptr<const PropertySetErrorCallback> callback)1811 void FakeVehicleHardware::registerOnPropertySetErrorEvent(
1812 std::unique_ptr<const PropertySetErrorCallback> callback) {
1813 // In FakeVehicleHardware, we will never use mOnPropertySetErrorCallback.
1814 if (mOnPropertySetErrorCallback != nullptr) {
1815 ALOGE("registerOnPropertySetErrorEvent must only be called once");
1816 return;
1817 }
1818 mOnPropertySetErrorCallback = std::move(callback);
1819 }
1820
updateSampleRate(int32_t propId,int32_t areaId,float sampleRate)1821 StatusCode FakeVehicleHardware::updateSampleRate(int32_t propId, int32_t areaId, float sampleRate) {
1822 // DefaultVehicleHal makes sure that sampleRate must be within minSampleRate and maxSampleRate.
1823 // For fake implementation, we would write the same value with a new timestamp into propStore
1824 // at sample rate.
1825 std::scoped_lock<std::mutex> lockGuard(mLock);
1826
1827 PropIdAreaId propIdAreaId{
1828 .propId = propId,
1829 .areaId = areaId,
1830 };
1831 if (mRecurrentActions.find(propIdAreaId) != mRecurrentActions.end()) {
1832 mRecurrentTimer->unregisterTimerCallback(mRecurrentActions[propIdAreaId]);
1833 }
1834 if (sampleRate == 0) {
1835 return StatusCode::OK;
1836 }
1837 int64_t interval = static_cast<int64_t>(1'000'000'000. / sampleRate);
1838 auto action = std::make_shared<RecurrentTimer::Callback>([this, propId, areaId] {
1839 // Refresh the property value. In real implementation, this should poll the latest value
1840 // from vehicle bus. Here, we are just refreshing the existing value with a new timestamp.
1841 auto result = getValue(VehiclePropValue{
1842 .prop = propId,
1843 .areaId = areaId,
1844 });
1845 if (!result.ok()) {
1846 // Failed to read current value, skip refreshing.
1847 return;
1848 }
1849 result.value()->timestamp = elapsedRealtimeNano();
1850 // For continuous properties, we must generate a new onPropertyChange event periodically
1851 // according to the sample rate.
1852 mServerSidePropStore->writeValue(std::move(result.value()), /*updateStatus=*/true,
1853 VehiclePropertyStore::EventMode::ALWAYS);
1854 });
1855 mRecurrentTimer->registerTimerCallback(interval, action);
1856 mRecurrentActions[propIdAreaId] = action;
1857 return StatusCode::OK;
1858 }
1859
onValueChangeCallback(const VehiclePropValue & value)1860 void FakeVehicleHardware::onValueChangeCallback(const VehiclePropValue& value) {
1861 if (mOnPropertyChangeCallback == nullptr) {
1862 return;
1863 }
1864
1865 std::vector<VehiclePropValue> updatedValues;
1866 updatedValues.push_back(value);
1867 (*mOnPropertyChangeCallback)(std::move(updatedValues));
1868 }
1869
loadPropConfigsFromDir(const std::string & dirPath,std::unordered_map<int32_t,ConfigDeclaration> * configsByPropId)1870 void FakeVehicleHardware::loadPropConfigsFromDir(
1871 const std::string& dirPath,
1872 std::unordered_map<int32_t, ConfigDeclaration>* configsByPropId) {
1873 ALOGI("loading properties from %s", dirPath.c_str());
1874 if (auto dir = opendir(dirPath.c_str()); dir != NULL) {
1875 std::regex regJson(".*[.]json", std::regex::icase);
1876 while (auto f = readdir(dir)) {
1877 if (!std::regex_match(f->d_name, regJson)) {
1878 continue;
1879 }
1880 std::string filePath = dirPath + "/" + std::string(f->d_name);
1881 ALOGI("loading properties from %s", filePath.c_str());
1882 auto result = mLoader.loadPropConfig(filePath);
1883 if (!result.ok()) {
1884 ALOGE("failed to load config file: %s, error: %s", filePath.c_str(),
1885 result.error().message().c_str());
1886 continue;
1887 }
1888 for (auto& [propId, configDeclaration] : result.value()) {
1889 (*configsByPropId)[propId] = std::move(configDeclaration);
1890 }
1891 }
1892 closedir(dir);
1893 }
1894 }
1895
safelyParseFloat(int index,const std::string & s)1896 Result<float> FakeVehicleHardware::safelyParseFloat(int index, const std::string& s) {
1897 float out;
1898 if (!ParseFloat(s, &out)) {
1899 return Error() << StringPrintf("non-float argument at index %d: %s\n", index, s.c_str());
1900 }
1901 return out;
1902 }
1903
parseHexString(const std::string & s)1904 Result<std::vector<uint8_t>> FakeVehicleHardware::parseHexString(const std::string& s) {
1905 std::vector<uint8_t> bytes;
1906 if (s.size() % 2 != 0) {
1907 return Error() << StringPrintf("invalid hex string: %s, should have even size\n",
1908 s.c_str());
1909 }
1910 if (!StartsWith(s, "0x")) {
1911 return Error() << StringPrintf("hex string should start with \"0x\", got %s\n", s.c_str());
1912 }
1913 std::string subs = s.substr(2);
1914 std::transform(subs.begin(), subs.end(), subs.begin(),
1915 [](unsigned char c) { return std::tolower(c); });
1916
1917 bool highDigit = true;
1918 for (size_t i = 0; i < subs.size(); i++) {
1919 char c = subs[i];
1920 uint8_t v;
1921 if (c >= '0' && c <= '9') {
1922 v = c - '0';
1923 } else if (c >= 'a' && c <= 'f') {
1924 v = c - 'a' + 10;
1925 } else {
1926 return Error() << StringPrintf("invalid character %c in hex string %s\n", c,
1927 subs.c_str());
1928 }
1929 if (highDigit) {
1930 bytes.push_back(v * 16);
1931 } else {
1932 bytes[bytes.size() - 1] += v;
1933 }
1934 highDigit = !highDigit;
1935 }
1936 return bytes;
1937 }
1938
1939 template <class CallbackType, class RequestType>
PendingRequestHandler(FakeVehicleHardware * hardware)1940 FakeVehicleHardware::PendingRequestHandler<CallbackType, RequestType>::PendingRequestHandler(
1941 FakeVehicleHardware* hardware)
1942 : mHardware(hardware) {
1943 // Don't initialize mThread in initialization list because mThread depends on mRequests and we
1944 // want mRequests to be initialized first.
1945 mThread = std::thread([this] {
1946 while (mRequests.waitForItems()) {
1947 handleRequestsOnce();
1948 }
1949 });
1950 }
1951
1952 template <class CallbackType, class RequestType>
addRequest(RequestType request,std::shared_ptr<const CallbackType> callback)1953 void FakeVehicleHardware::PendingRequestHandler<CallbackType, RequestType>::addRequest(
1954 RequestType request, std::shared_ptr<const CallbackType> callback) {
1955 mRequests.push({
1956 request,
1957 callback,
1958 });
1959 }
1960
1961 template <class CallbackType, class RequestType>
stop()1962 void FakeVehicleHardware::PendingRequestHandler<CallbackType, RequestType>::stop() {
1963 mRequests.deactivate();
1964 if (mThread.joinable()) {
1965 mThread.join();
1966 }
1967 }
1968
1969 template <>
1970 void FakeVehicleHardware::PendingRequestHandler<FakeVehicleHardware::GetValuesCallback,
handleRequestsOnce()1971 GetValueRequest>::handleRequestsOnce() {
1972 std::unordered_map<std::shared_ptr<const GetValuesCallback>, std::vector<GetValueResult>>
1973 callbackToResults;
1974 for (const auto& rwc : mRequests.flush()) {
1975 ATRACE_BEGIN("FakeVehicleHardware:handleGetValueRequest");
1976 auto result = mHardware->handleGetValueRequest(rwc.request);
1977 ATRACE_END();
1978 callbackToResults[rwc.callback].push_back(std::move(result));
1979 }
1980 for (const auto& [callback, results] : callbackToResults) {
1981 ATRACE_BEGIN("FakeVehicleHardware:call get value result callback");
1982 (*callback)(std::move(results));
1983 ATRACE_END();
1984 }
1985 }
1986
1987 template <>
1988 void FakeVehicleHardware::PendingRequestHandler<FakeVehicleHardware::SetValuesCallback,
handleRequestsOnce()1989 SetValueRequest>::handleRequestsOnce() {
1990 std::unordered_map<std::shared_ptr<const SetValuesCallback>, std::vector<SetValueResult>>
1991 callbackToResults;
1992 for (const auto& rwc : mRequests.flush()) {
1993 ATRACE_BEGIN("FakeVehicleHardware:handleSetValueRequest");
1994 auto result = mHardware->handleSetValueRequest(rwc.request);
1995 ATRACE_END();
1996 callbackToResults[rwc.callback].push_back(std::move(result));
1997 }
1998 for (const auto& [callback, results] : callbackToResults) {
1999 ATRACE_BEGIN("FakeVehicleHardware:call set value result callback");
2000 (*callback)(std::move(results));
2001 ATRACE_END();
2002 }
2003 }
2004
2005 } // namespace fake
2006 } // namespace vehicle
2007 } // namespace automotive
2008 } // namespace hardware
2009 } // namespace android
2010