• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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], &currentValue)) {
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