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 <VehicleHalTypes.h>
28 #include <VehicleUtils.h>
29 
30 #include <android-base/file.h>
31 #include <android-base/parsedouble.h>
32 #include <android-base/properties.h>
33 #include <android-base/strings.h>
34 #include <android/hardware/automotive/vehicle/TestVendorProperty.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 <regex>
43 #include <unordered_set>
44 #include <vector>
45 
46 namespace android {
47 namespace hardware {
48 namespace automotive {
49 namespace vehicle {
50 namespace fake {
51 
52 namespace {
53 
54 #define PROP_ID_TO_CSTR(A) (propIdToString(A).c_str())
55 
56 using ::aidl::android::hardware::automotive::vehicle::CruiseControlCommand;
57 using ::aidl::android::hardware::automotive::vehicle::CruiseControlType;
58 using ::aidl::android::hardware::automotive::vehicle::DriverDistractionState;
59 using ::aidl::android::hardware::automotive::vehicle::DriverDistractionWarning;
60 using ::aidl::android::hardware::automotive::vehicle::DriverDrowsinessAttentionState;
61 using ::aidl::android::hardware::automotive::vehicle::DriverDrowsinessAttentionWarning;
62 using ::aidl::android::hardware::automotive::vehicle::ErrorState;
63 using ::aidl::android::hardware::automotive::vehicle::GetValueRequest;
64 using ::aidl::android::hardware::automotive::vehicle::GetValueResult;
65 using ::aidl::android::hardware::automotive::vehicle::RawPropValues;
66 using ::aidl::android::hardware::automotive::vehicle::SetValueRequest;
67 using ::aidl::android::hardware::automotive::vehicle::SetValueResult;
68 using ::aidl::android::hardware::automotive::vehicle::StatusCode;
69 using ::aidl::android::hardware::automotive::vehicle::SubscribeOptions;
70 using ::aidl::android::hardware::automotive::vehicle::toString;
71 using ::aidl::android::hardware::automotive::vehicle::VehicleApPowerStateReport;
72 using ::aidl::android::hardware::automotive::vehicle::VehicleApPowerStateReq;
73 using ::aidl::android::hardware::automotive::vehicle::VehicleArea;
74 using ::aidl::android::hardware::automotive::vehicle::VehicleHwKeyInputAction;
75 using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig;
76 using ::aidl::android::hardware::automotive::vehicle::VehicleProperty;
77 using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyAccess;
78 using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyChangeMode;
79 using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyGroup;
80 using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyStatus;
81 using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType;
82 using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
83 using ::aidl::android::hardware::automotive::vehicle::VehicleUnit;
84 
85 using ::android::hardware::automotive::remoteaccess::GetApPowerBootupReasonRequest;
86 using ::android::hardware::automotive::remoteaccess::GetApPowerBootupReasonResponse;
87 using ::android::hardware::automotive::remoteaccess::IsVehicleInUseRequest;
88 using ::android::hardware::automotive::remoteaccess::IsVehicleInUseResponse;
89 using ::android::hardware::automotive::remoteaccess::PowerController;
90 
91 using ::android::base::EqualsIgnoreCase;
92 using ::android::base::Error;
93 using ::android::base::GetIntProperty;
94 using ::android::base::ParseFloat;
95 using ::android::base::Result;
96 using ::android::base::ScopedLockAssertion;
97 using ::android::base::StartsWith;
98 using ::android::base::StringPrintf;
99 
100 // In order to test large number of vehicle property configs, we might generate additional fake
101 // property config start from this ID. These fake properties are for getPropertyList,
102 //  getPropertiesAsync, and setPropertiesAsync.
103 // 0x21403000
104 constexpr int32_t STARTING_VENDOR_CODE_PROPERTIES_FOR_TEST =
105         0x3000 | toInt(VehiclePropertyGroup::VENDOR) | toInt(VehicleArea::GLOBAL) |
106         toInt(VehiclePropertyType::INT32);
107 // 0x21405000
108 constexpr int32_t ENDING_VENDOR_CODE_PROPERTIES_FOR_TEST =
109         0x5000 | toInt(VehiclePropertyGroup::VENDOR) | toInt(VehicleArea::GLOBAL) |
110         toInt(VehiclePropertyType::INT32);
111 // The directory for default property configuration file.
112 // For config file format, see impl/default_config/config/README.md.
113 constexpr char DEFAULT_CONFIG_DIR[] = "/vendor/etc/automotive/vhalconfig/";
114 // The directory for property configuration file that overrides the default configuration file.
115 // For config file format, see impl/default_config/config/README.md.
116 constexpr char OVERRIDE_CONFIG_DIR[] = "/vendor/etc/automotive/vhaloverride/";
117 // The optional config file for power controller grpc service that provides vehicleInUse and
118 // ApPowerBootupReason property.
119 constexpr char GRPC_SERVICE_CONFIG_FILE[] = "/vendor/etc/automotive/powercontroller/serverconfig";
120 // If OVERRIDE_PROPERTY is set, we will use the configuration files from OVERRIDE_CONFIG_DIR to
121 // overwrite the default configs.
122 constexpr char OVERRIDE_PROPERTY[] = "persist.vendor.vhal_init_value_override";
123 constexpr char POWER_STATE_REQ_CONFIG_PROPERTY[] = "ro.vendor.fake_vhal.ap_power_state_req.config";
124 // The value to be returned if VENDOR_PROPERTY_FOR_ERROR_CODE_TESTING is set as the property
125 constexpr int VENDOR_ERROR_CODE = 0x00ab0005;
126 // A list of supported options for "--set" command.
127 const std::unordered_set<std::string> SET_PROP_OPTIONS = {
128         // integer.
129         "-i",
130         // 64bit integer.
131         "-i64",
132         // float.
133         "-f",
134         // string.
135         "-s",
136         // bytes in hex format, e.g. 0xDEADBEEF.
137         "-b",
138         // Area id in integer.
139         "-a",
140         // Timestamp in int64.
141         "-t"};
142 
143 // ADAS _ENABLED property to list of ADAS state properties using ErrorState enum.
144 const std::unordered_map<int32_t, std::vector<int32_t>> mAdasEnabledPropToAdasPropWithErrorState = {
145         // AEB
146         {
147                 toInt(VehicleProperty::AUTOMATIC_EMERGENCY_BRAKING_ENABLED),
148                 {
149                         toInt(VehicleProperty::AUTOMATIC_EMERGENCY_BRAKING_STATE),
150                 },
151         },
152         // FCW
153         {
154                 toInt(VehicleProperty::FORWARD_COLLISION_WARNING_ENABLED),
155                 {
156                         toInt(VehicleProperty::FORWARD_COLLISION_WARNING_STATE),
157                 },
158         },
159         // BSW
160         {
161                 toInt(VehicleProperty::BLIND_SPOT_WARNING_ENABLED),
162                 {
163                         toInt(VehicleProperty::BLIND_SPOT_WARNING_STATE),
164                 },
165         },
166         // LDW
167         {
168                 toInt(VehicleProperty::LANE_DEPARTURE_WARNING_ENABLED),
169                 {
170                         toInt(VehicleProperty::LANE_DEPARTURE_WARNING_STATE),
171                 },
172         },
173         // LKA
174         {
175                 toInt(VehicleProperty::LANE_KEEP_ASSIST_ENABLED),
176                 {
177                         toInt(VehicleProperty::LANE_KEEP_ASSIST_STATE),
178                 },
179         },
180         // LCA
181         {
182                 toInt(VehicleProperty::LANE_CENTERING_ASSIST_ENABLED),
183                 {
184                         toInt(VehicleProperty::LANE_CENTERING_ASSIST_STATE),
185                 },
186         },
187         // ELKA
188         {
189                 toInt(VehicleProperty::EMERGENCY_LANE_KEEP_ASSIST_ENABLED),
190                 {
191                         toInt(VehicleProperty::EMERGENCY_LANE_KEEP_ASSIST_STATE),
192                 },
193         },
194         // CC
195         {
196                 toInt(VehicleProperty::CRUISE_CONTROL_ENABLED),
197                 {
198                         toInt(VehicleProperty::CRUISE_CONTROL_TYPE),
199                         toInt(VehicleProperty::CRUISE_CONTROL_STATE),
200                 },
201         },
202         // HOD
203         {
204                 toInt(VehicleProperty::HANDS_ON_DETECTION_ENABLED),
205                 {
206                         toInt(VehicleProperty::HANDS_ON_DETECTION_DRIVER_STATE),
207                         toInt(VehicleProperty::HANDS_ON_DETECTION_WARNING),
208                 },
209         },
210         // Driver Drowsiness and Attention
211         {
212                 toInt(VehicleProperty::DRIVER_DROWSINESS_ATTENTION_SYSTEM_ENABLED),
213                 {
214                         toInt(VehicleProperty::DRIVER_DROWSINESS_ATTENTION_STATE),
215                 },
216         },
217         // Driver Drowsiness and Attention Warning
218         {
219                 toInt(VehicleProperty::DRIVER_DROWSINESS_ATTENTION_WARNING_ENABLED),
220                 {
221                         toInt(VehicleProperty::DRIVER_DROWSINESS_ATTENTION_WARNING),
222                 },
223         },
224         // Driver Distraction
225         {
226                 toInt(VehicleProperty::DRIVER_DISTRACTION_SYSTEM_ENABLED),
227                 {
228                         toInt(VehicleProperty::DRIVER_DISTRACTION_STATE),
229                         toInt(VehicleProperty::DRIVER_DISTRACTION_WARNING),
230                 },
231         },
232         // Driver Distraction Warning
233         {
234                 toInt(VehicleProperty::DRIVER_DISTRACTION_WARNING_ENABLED),
235                 {
236                         toInt(VehicleProperty::DRIVER_DISTRACTION_WARNING),
237                 },
238         },
239         // LSCW
240         {
241                 toInt(VehicleProperty::LOW_SPEED_COLLISION_WARNING_ENABLED),
242                 {
243                         toInt(VehicleProperty::LOW_SPEED_COLLISION_WARNING_STATE),
244                 },
245         },
246         // ESC
247         {
248                 toInt(VehicleProperty::ELECTRONIC_STABILITY_CONTROL_ENABLED),
249                 {
250                         toInt(VehicleProperty::ELECTRONIC_STABILITY_CONTROL_STATE),
251                 },
252         },
253         // CTMW
254         {
255                 toInt(VehicleProperty::CROSS_TRAFFIC_MONITORING_ENABLED),
256                 {
257                         toInt(VehicleProperty::CROSS_TRAFFIC_MONITORING_WARNING_STATE),
258                 },
259         },
260         // LSAEB
261         {
262                 toInt(VehicleProperty::LOW_SPEED_AUTOMATIC_EMERGENCY_BRAKING_ENABLED),
263                 {
264                         toInt(VehicleProperty::LOW_SPEED_AUTOMATIC_EMERGENCY_BRAKING_STATE),
265                 },
266         },
267 };
268 
269 // The list of VHAL properties that might be handled by an external power controller.
270 const std::unordered_set<int32_t> mPowerPropIds = {toInt(VehicleProperty::VEHICLE_IN_USE),
271                                                    toInt(VehicleProperty::AP_POWER_BOOTUP_REASON)};
272 
maybeGetGrpcServiceInfo(std::string * address)273 void maybeGetGrpcServiceInfo(std::string* address) {
274     std::ifstream ifs(GRPC_SERVICE_CONFIG_FILE);
275     if (!ifs) {
276         ALOGI("Cannot open grpc service config file at: %s, assume no service is available",
277               GRPC_SERVICE_CONFIG_FILE);
278         return;
279     }
280     ifs >> *address;
281     ifs.close();
282 }
283 
vecToStringOfHexValues(const std::vector<int32_t> & vec)284 inline std::string vecToStringOfHexValues(const std::vector<int32_t>& vec) {
285     std::stringstream ss;
286     ss << "[";
287     for (size_t i = 0; i < vec.size(); i++) {
288         if (i != 0) {
289             ss << ",";
290         }
291         ss << std::showbase << std::hex << vec[i];
292     }
293     ss << "]";
294     return ss.str();
295 }
296 
297 }  // namespace
298 
storePropInitialValue(const ConfigDeclaration & config)299 void FakeVehicleHardware::storePropInitialValue(const ConfigDeclaration& config) {
300     const VehiclePropConfig& vehiclePropConfig = config.config;
301     int propId = vehiclePropConfig.prop;
302 
303     // A global property will have only a single area
304     bool globalProp = isGlobalProp(propId);
305     size_t numAreas = globalProp ? 1 : vehiclePropConfig.areaConfigs.size();
306 
307     if (propId == toInt(VehicleProperty::HVAC_POWER_ON)) {
308         const auto& configArray = vehiclePropConfig.configArray;
309         hvacPowerDependentProps.insert(configArray.begin(), configArray.end());
310     }
311 
312     for (size_t i = 0; i < numAreas; i++) {
313         int32_t curArea = globalProp ? 0 : vehiclePropConfig.areaConfigs[i].areaId;
314 
315         // Create a separate instance for each individual zone
316         VehiclePropValue prop = {
317                 .timestamp = elapsedRealtimeNano(),
318                 .areaId = curArea,
319                 .prop = propId,
320                 .value = {},
321         };
322 
323         if (config.initialAreaValues.empty()) {
324             if (config.initialValue == RawPropValues{}) {
325                 // Skip empty initial values.
326                 continue;
327             }
328             prop.value = config.initialValue;
329         } else if (auto valueForAreaIt = config.initialAreaValues.find(curArea);
330                    valueForAreaIt != config.initialAreaValues.end()) {
331             prop.value = valueForAreaIt->second;
332         } else {
333             ALOGW("failed to get default value for prop 0x%x area 0x%x", propId, curArea);
334             continue;
335         }
336 
337         auto result =
338                 mServerSidePropStore->writeValue(mValuePool->obtain(prop), /*updateStatus=*/true);
339         if (!result.ok()) {
340             ALOGE("failed to write default config value, error: %s, status: %d",
341                   getErrorMsg(result).c_str(), getIntErrorCode(result));
342         }
343     }
344 }
345 
FakeVehicleHardware()346 FakeVehicleHardware::FakeVehicleHardware()
347     : FakeVehicleHardware(DEFAULT_CONFIG_DIR, OVERRIDE_CONFIG_DIR, false) {}
348 
FakeVehicleHardware(std::string defaultConfigDir,std::string overrideConfigDir,bool forceOverride)349 FakeVehicleHardware::FakeVehicleHardware(std::string defaultConfigDir,
350                                          std::string overrideConfigDir, bool forceOverride)
351     : mValuePool(std::make_unique<VehiclePropValuePool>()),
352       mServerSidePropStore(new VehiclePropertyStore(mValuePool)),
353       mDefaultConfigDir(defaultConfigDir),
354       mOverrideConfigDir(overrideConfigDir),
355       mFakeObd2Frame(new obd2frame::FakeObd2Frame(mServerSidePropStore)),
356       mFakeUserHal(new FakeUserHal(mValuePool)),
357       mRecurrentTimer(new RecurrentTimer()),
358       mGeneratorHub(new GeneratorHub(
359               [this](const VehiclePropValue& value) { eventFromVehicleBus(value); })),
360       mPendingGetValueRequests(this),
361       mPendingSetValueRequests(this),
362       mForceOverride(forceOverride) {
363     init();
364 }
365 
~FakeVehicleHardware()366 FakeVehicleHardware::~FakeVehicleHardware() {
367     mPendingGetValueRequests.stop();
368     mPendingSetValueRequests.stop();
369     mGeneratorHub.reset();
370 }
371 
UseOverrideConfigDir()372 bool FakeVehicleHardware::UseOverrideConfigDir() {
373     return mForceOverride ||
374            android::base::GetBoolProperty(OVERRIDE_PROPERTY, /*default_value=*/false);
375 }
376 
loadConfigDeclarations()377 std::unordered_map<int32_t, ConfigDeclaration> FakeVehicleHardware::loadConfigDeclarations() {
378     std::unordered_map<int32_t, ConfigDeclaration> configsByPropId;
379     bool defaultConfigLoaded = loadPropConfigsFromDir(mDefaultConfigDir, &configsByPropId);
380     if (!defaultConfigLoaded) {
381         // This cannot work without a valid default config.
382         ALOGE("Failed to load default config, exiting");
383         exit(1);
384     }
385     if (UseOverrideConfigDir()) {
386         loadPropConfigsFromDir(mOverrideConfigDir, &configsByPropId);
387     }
388     return configsByPropId;
389 }
390 
init()391 void FakeVehicleHardware::init() {
392     maybeGetGrpcServiceInfo(&mPowerControllerServiceAddress);
393 
394     for (auto& [_, configDeclaration] : loadConfigDeclarations()) {
395         VehiclePropConfig cfg = configDeclaration.config;
396         VehiclePropertyStore::TokenFunction tokenFunction = nullptr;
397 
398         if (cfg.prop == toInt(VehicleProperty::AP_POWER_STATE_REQ)) {
399             int config = GetIntProperty(POWER_STATE_REQ_CONFIG_PROPERTY, /*default_value=*/0);
400             cfg.configArray[0] = config;
401         } else if (cfg.prop == OBD2_FREEZE_FRAME) {
402             tokenFunction = [](const VehiclePropValue& propValue) { return propValue.timestamp; };
403         }
404 
405         mServerSidePropStore->registerProperty(cfg, tokenFunction);
406         if (obd2frame::FakeObd2Frame::isDiagnosticProperty(cfg)) {
407             // Ignore storing default value for diagnostic property. They have special get/set
408             // logic.
409             continue;
410         }
411         storePropInitialValue(configDeclaration);
412     }
413 
414     // OBD2_LIVE_FRAME and OBD2_FREEZE_FRAME must be configured in default configs.
415     auto maybeObd2LiveFrame = mServerSidePropStore->getPropConfig(OBD2_LIVE_FRAME);
416     if (maybeObd2LiveFrame.has_value()) {
417         mFakeObd2Frame->initObd2LiveFrame(maybeObd2LiveFrame.value());
418     }
419     auto maybeObd2FreezeFrame = mServerSidePropStore->getPropConfig(OBD2_FREEZE_FRAME);
420     if (maybeObd2FreezeFrame.has_value()) {
421         mFakeObd2Frame->initObd2FreezeFrame(maybeObd2FreezeFrame.value());
422     }
423 
424     mServerSidePropStore->setOnValuesChangeCallback([this](std::vector<VehiclePropValue> values) {
425         return onValuesChangeCallback(std::move(values));
426     });
427 }
428 
getAllPropertyConfigs() const429 std::vector<VehiclePropConfig> FakeVehicleHardware::getAllPropertyConfigs() const {
430     std::vector<VehiclePropConfig> allConfigs = mServerSidePropStore->getAllConfigs();
431     if (mAddExtraTestVendorConfigs) {
432         generateVendorConfigs(/* outAllConfigs= */ allConfigs);
433     }
434     return allConfigs;
435 }
436 
createApPowerStateReq(VehicleApPowerStateReq state)437 VehiclePropValuePool::RecyclableType FakeVehicleHardware::createApPowerStateReq(
438         VehicleApPowerStateReq state) {
439     auto req = mValuePool->obtain(VehiclePropertyType::INT32_VEC, 2);
440     req->prop = toInt(VehicleProperty::AP_POWER_STATE_REQ);
441     req->areaId = 0;
442     req->timestamp = elapsedRealtimeNano();
443     req->status = VehiclePropertyStatus::AVAILABLE;
444     req->value.int32Values[0] = toInt(state);
445     // Param = 0.
446     req->value.int32Values[1] = 0;
447     return req;
448 }
449 
createAdasStateReq(int32_t propertyId,int32_t areaId,int32_t state)450 VehiclePropValuePool::RecyclableType FakeVehicleHardware::createAdasStateReq(int32_t propertyId,
451                                                                              int32_t areaId,
452                                                                              int32_t state) {
453     auto req = mValuePool->obtain(VehiclePropertyType::INT32);
454     req->prop = propertyId;
455     req->areaId = areaId;
456     req->timestamp = elapsedRealtimeNano();
457     req->status = VehiclePropertyStatus::AVAILABLE;
458     req->value.int32Values[0] = state;
459     return req;
460 }
461 
setApPowerStateReqShutdown(const VehiclePropValue & value)462 VhalResult<void> FakeVehicleHardware::setApPowerStateReqShutdown(const VehiclePropValue& value) {
463     if (value.value.int32Values.size() != 1) {
464         return StatusError(StatusCode::INVALID_ARG)
465                << "Failed to set SHUTDOWN_REQUEST, expect 1 int value: "
466                << "VehicleApPowerStateShutdownParam";
467     }
468     int powerStateShutdownParam = value.value.int32Values[0];
469     auto prop = createApPowerStateReq(VehicleApPowerStateReq::SHUTDOWN_PREPARE);
470     prop->value.int32Values[1] = powerStateShutdownParam;
471     if (auto writeResult = mServerSidePropStore->writeValue(
472                 std::move(prop), /*updateStatus=*/true, VehiclePropertyStore::EventMode::ALWAYS);
473         !writeResult.ok()) {
474         return StatusError(getErrorCode(writeResult))
475                << "failed to write AP_POWER_STATE_REQ into property store, error: "
476                << getErrorMsg(writeResult);
477     }
478     return {};
479 }
480 
setApPowerStateReport(const VehiclePropValue & value)481 VhalResult<void> FakeVehicleHardware::setApPowerStateReport(const VehiclePropValue& value) {
482     auto updatedValue = mValuePool->obtain(value);
483     updatedValue->timestamp = elapsedRealtimeNano();
484 
485     if (auto writeResult = mServerSidePropStore->writeValue(std::move(updatedValue));
486         !writeResult.ok()) {
487         return StatusError(getErrorCode(writeResult))
488                << "failed to write value into property store, error: " << getErrorMsg(writeResult);
489     }
490 
491     VehiclePropValuePool::RecyclableType prop;
492     int32_t state = value.value.int32Values[0];
493     switch (state) {
494         case toInt(VehicleApPowerStateReport::DEEP_SLEEP_EXIT):
495             [[fallthrough]];
496         case toInt(VehicleApPowerStateReport::HIBERNATION_EXIT):
497             [[fallthrough]];
498         case toInt(VehicleApPowerStateReport::SHUTDOWN_CANCELLED):
499             [[fallthrough]];
500         case toInt(VehicleApPowerStateReport::WAIT_FOR_VHAL):
501             // CPMS is in WAIT_FOR_VHAL state, simply move to ON and send back to HAL.
502             prop = createApPowerStateReq(VehicleApPowerStateReq::ON);
503 
504             // ALWAYS update status for generated property value, and force a property update event
505             // because in the case when Car Service crashes, the power state would already be ON
506             // when we receive WAIT_FOR_VHAL and thus new property change event would be generated.
507             // However, Car Service always expect a property change event even though there is no
508             // actual state change.
509             if (auto writeResult =
510                         mServerSidePropStore->writeValue(std::move(prop), /*updateStatus=*/true,
511                                                          VehiclePropertyStore::EventMode::ALWAYS);
512                 !writeResult.ok()) {
513                 return StatusError(getErrorCode(writeResult))
514                        << "failed to write AP_POWER_STATE_REQ into property store, error: "
515                        << getErrorMsg(writeResult);
516             }
517             break;
518         case toInt(VehicleApPowerStateReport::DEEP_SLEEP_ENTRY):
519             [[fallthrough]];
520         case toInt(VehicleApPowerStateReport::HIBERNATION_ENTRY):
521             [[fallthrough]];
522         case toInt(VehicleApPowerStateReport::SHUTDOWN_START):
523             // CPMS is in WAIT_FOR_FINISH state, send the FINISHED command
524             // Send back to HAL
525             // ALWAYS update status for generated property value
526             prop = createApPowerStateReq(VehicleApPowerStateReq::FINISHED);
527             if (auto writeResult =
528                         mServerSidePropStore->writeValue(std::move(prop), /*updateStatus=*/true);
529                 !writeResult.ok()) {
530                 return StatusError(getErrorCode(writeResult))
531                        << "failed to write AP_POWER_STATE_REQ into property store, error: "
532                        << getErrorMsg(writeResult);
533             }
534             break;
535         default:
536             ALOGE("Unknown VehicleApPowerStateReport: %d", state);
537             break;
538     }
539     return {};
540 }
541 
getHvacTempNumIncrements(int requestedTemp,int minTemp,int maxTemp,int increment)542 int FakeVehicleHardware::getHvacTempNumIncrements(int requestedTemp, int minTemp, int maxTemp,
543                                                   int increment) {
544     requestedTemp = std::max(requestedTemp, minTemp);
545     requestedTemp = std::min(requestedTemp, maxTemp);
546     int numIncrements = std::round((requestedTemp - minTemp) / static_cast<float>(increment));
547     return numIncrements;
548 }
549 
updateHvacTemperatureValueSuggestionInput(const std::vector<int> & hvacTemperatureSetConfigArray,std::vector<float> * hvacTemperatureValueSuggestionInput)550 void FakeVehicleHardware::updateHvacTemperatureValueSuggestionInput(
551         const std::vector<int>& hvacTemperatureSetConfigArray,
552         std::vector<float>* hvacTemperatureValueSuggestionInput) {
553     int minTempInCelsius = hvacTemperatureSetConfigArray[0];
554     int maxTempInCelsius = hvacTemperatureSetConfigArray[1];
555     int incrementInCelsius = hvacTemperatureSetConfigArray[2];
556 
557     int minTempInFahrenheit = hvacTemperatureSetConfigArray[3];
558     int maxTempInFahrenheit = hvacTemperatureSetConfigArray[4];
559     int incrementInFahrenheit = hvacTemperatureSetConfigArray[5];
560 
561     // The HVAC_TEMPERATURE_SET config array values are temperature values that have been multiplied
562     // by 10 and converted to integers. Therefore, requestedTemp must also be multiplied by 10 and
563     // converted to an integer in order for them to be the same units.
564     int requestedTemp = static_cast<int>((*hvacTemperatureValueSuggestionInput)[0] * 10.0f);
565     int numIncrements =
566             (*hvacTemperatureValueSuggestionInput)[1] == toInt(VehicleUnit::CELSIUS)
567                     ? getHvacTempNumIncrements(requestedTemp, minTempInCelsius, maxTempInCelsius,
568                                                incrementInCelsius)
569                     : getHvacTempNumIncrements(requestedTemp, minTempInFahrenheit,
570                                                maxTempInFahrenheit, incrementInFahrenheit);
571 
572     int suggestedTempInCelsius = minTempInCelsius + incrementInCelsius * numIncrements;
573     int suggestedTempInFahrenheit = minTempInFahrenheit + incrementInFahrenheit * numIncrements;
574     // HVAC_TEMPERATURE_VALUE_SUGGESTION specifies the temperature values to be in the original
575     // floating point form so we divide by 10 and convert to float.
576     (*hvacTemperatureValueSuggestionInput)[2] = static_cast<float>(suggestedTempInCelsius) / 10.0f;
577     (*hvacTemperatureValueSuggestionInput)[3] =
578             static_cast<float>(suggestedTempInFahrenheit) / 10.0f;
579 }
580 
setHvacTemperatureValueSuggestion(const VehiclePropValue & hvacTemperatureValueSuggestion)581 VhalResult<void> FakeVehicleHardware::setHvacTemperatureValueSuggestion(
582         const VehiclePropValue& hvacTemperatureValueSuggestion) {
583     auto hvacTemperatureSetConfigResult =
584             mServerSidePropStore->getPropConfig(toInt(VehicleProperty::HVAC_TEMPERATURE_SET));
585 
586     if (!hvacTemperatureSetConfigResult.ok()) {
587         return StatusError(getErrorCode(hvacTemperatureSetConfigResult)) << StringPrintf(
588                        "Failed to set HVAC_TEMPERATURE_VALUE_SUGGESTION because"
589                        " HVAC_TEMPERATURE_SET could not be retrieved. Error: %s",
590                        getErrorMsg(hvacTemperatureSetConfigResult).c_str());
591     }
592 
593     const auto& originalInput = hvacTemperatureValueSuggestion.value.floatValues;
594     if (originalInput.size() != 4) {
595         return StatusError(StatusCode::INVALID_ARG) << StringPrintf(
596                        "Failed to set HVAC_TEMPERATURE_VALUE_SUGGESTION because float"
597                        " array value is not size 4.");
598     }
599 
600     bool isTemperatureUnitSpecified = originalInput[1] == toInt(VehicleUnit::CELSIUS) ||
601                                       originalInput[1] == toInt(VehicleUnit::FAHRENHEIT);
602     if (!isTemperatureUnitSpecified) {
603         return StatusError(StatusCode::INVALID_ARG) << StringPrintf(
604                        "Failed to set HVAC_TEMPERATURE_VALUE_SUGGESTION because float"
605                        " value at index 1 is not any of %d or %d, which corresponds to"
606                        " VehicleUnit#CELSIUS and VehicleUnit#FAHRENHEIT respectively.",
607                        toInt(VehicleUnit::CELSIUS), toInt(VehicleUnit::FAHRENHEIT));
608     }
609 
610     auto updatedValue = mValuePool->obtain(hvacTemperatureValueSuggestion);
611     const auto& hvacTemperatureSetConfigArray = hvacTemperatureSetConfigResult.value().configArray;
612     auto& hvacTemperatureValueSuggestionInput = updatedValue->value.floatValues;
613 
614     updateHvacTemperatureValueSuggestionInput(hvacTemperatureSetConfigArray,
615                                               &hvacTemperatureValueSuggestionInput);
616 
617     updatedValue->timestamp = elapsedRealtimeNano();
618     auto writeResult = mServerSidePropStore->writeValue(std::move(updatedValue),
619                                                         /* updateStatus = */ true,
620                                                         VehiclePropertyStore::EventMode::ALWAYS);
621     if (!writeResult.ok()) {
622         return StatusError(getErrorCode(writeResult))
623                << StringPrintf("failed to write value into property store, error: %s",
624                                getErrorMsg(writeResult).c_str());
625     }
626 
627     return {};
628 }
629 
isHvacPropAndHvacNotAvailable(int32_t propId,int32_t areaId) const630 bool FakeVehicleHardware::isHvacPropAndHvacNotAvailable(int32_t propId, int32_t areaId) const {
631     if (hvacPowerDependentProps.count(propId)) {
632         auto hvacPowerOnResults =
633                 mServerSidePropStore->readValuesForProperty(toInt(VehicleProperty::HVAC_POWER_ON));
634         if (!hvacPowerOnResults.ok()) {
635             ALOGW("failed to get HVAC_POWER_ON 0x%x, error: %s",
636                   toInt(VehicleProperty::HVAC_POWER_ON), getErrorMsg(hvacPowerOnResults).c_str());
637             return false;
638         }
639         auto& hvacPowerOnValues = hvacPowerOnResults.value();
640         for (size_t j = 0; j < hvacPowerOnValues.size(); j++) {
641             auto hvacPowerOnValue = std::move(hvacPowerOnValues[j]);
642             if ((hvacPowerOnValue->areaId & areaId) == areaId) {
643                 if (hvacPowerOnValue->value.int32Values.size() == 1 &&
644                     hvacPowerOnValue->value.int32Values[0] == 0) {
645                     return true;
646                 }
647                 break;
648             }
649         }
650     }
651     return false;
652 }
653 
isAdasPropertyAvailable(int32_t adasStatePropertyId) const654 VhalResult<void> FakeVehicleHardware::isAdasPropertyAvailable(int32_t adasStatePropertyId) const {
655     auto adasStateResult = mServerSidePropStore->readValue(adasStatePropertyId);
656     if (!adasStateResult.ok()) {
657         ALOGW("Failed to get ADAS ENABLED property 0x%x, error: %s", adasStatePropertyId,
658               getErrorMsg(adasStateResult).c_str());
659         return {};
660     }
661 
662     if (adasStateResult.value()->value.int32Values.size() == 1 &&
663         adasStateResult.value()->value.int32Values[0] < 0) {
664         auto errorState = adasStateResult.value()->value.int32Values[0];
665         switch (errorState) {
666             case toInt(ErrorState::NOT_AVAILABLE_DISABLED):
667                 return StatusError(StatusCode::NOT_AVAILABLE_DISABLED)
668                        << "ADAS feature is disabled.";
669             case toInt(ErrorState::NOT_AVAILABLE_SPEED_LOW):
670                 return StatusError(StatusCode::NOT_AVAILABLE_SPEED_LOW)
671                        << "ADAS feature is disabled because the vehicle speed is too low.";
672             case toInt(ErrorState::NOT_AVAILABLE_SPEED_HIGH):
673                 return StatusError(StatusCode::NOT_AVAILABLE_SPEED_HIGH)
674                        << "ADAS feature is disabled because the vehicle speed is too high.";
675             case toInt(ErrorState::NOT_AVAILABLE_POOR_VISIBILITY):
676                 return StatusError(StatusCode::NOT_AVAILABLE_POOR_VISIBILITY)
677                        << "ADAS feature is disabled because the visibility is too poor.";
678             case toInt(ErrorState::NOT_AVAILABLE_SAFETY):
679                 return StatusError(StatusCode::NOT_AVAILABLE_SAFETY)
680                        << "ADAS feature is disabled because of safety reasons.";
681             default:
682                 return StatusError(StatusCode::NOT_AVAILABLE) << "ADAS feature is not available.";
683         }
684     }
685 
686     return {};
687 }
688 
setUserHalProp(const VehiclePropValue & value)689 VhalResult<void> FakeVehicleHardware::setUserHalProp(const VehiclePropValue& value) {
690     auto result = mFakeUserHal->onSetProperty(value);
691     if (!result.ok()) {
692         return StatusError(getErrorCode(result))
693                << "onSetProperty(): HAL returned error: " << getErrorMsg(result);
694     }
695     auto& updatedValue = result.value();
696     if (updatedValue != nullptr) {
697         ALOGI("onSetProperty(): updating property returned by HAL: %s",
698               updatedValue->toString().c_str());
699         // Update timestamp otherwise writeValue might fail because the timestamp is outdated.
700         updatedValue->timestamp = elapsedRealtimeNano();
701         if (auto writeResult = mServerSidePropStore->writeValue(
702                     std::move(result.value()),
703                     /*updateStatus=*/true, VehiclePropertyStore::EventMode::ALWAYS);
704             !writeResult.ok()) {
705             return StatusError(getErrorCode(writeResult))
706                    << "failed to write value into property store, error: "
707                    << getErrorMsg(writeResult);
708         }
709     }
710     return {};
711 }
712 
synchronizeHvacTemp(int32_t hvacDualOnAreaId,std::optional<float> newTempC) const713 VhalResult<void> FakeVehicleHardware::synchronizeHvacTemp(int32_t hvacDualOnAreaId,
714                                                           std::optional<float> newTempC) const {
715     auto hvacTemperatureSetResults = mServerSidePropStore->readValuesForProperty(
716             toInt(VehicleProperty::HVAC_TEMPERATURE_SET));
717     if (!hvacTemperatureSetResults.ok()) {
718         return StatusError(StatusCode::NOT_AVAILABLE)
719                << "Failed to get HVAC_TEMPERATURE_SET, error: "
720                << getErrorMsg(hvacTemperatureSetResults);
721     }
722     auto& hvacTemperatureSetValues = hvacTemperatureSetResults.value();
723     std::optional<float> tempCToSynchronize = newTempC;
724     for (size_t i = 0; i < hvacTemperatureSetValues.size(); i++) {
725         int32_t areaId = hvacTemperatureSetValues[i]->areaId;
726         if ((hvacDualOnAreaId & areaId) != areaId) {
727             continue;
728         }
729         if (hvacTemperatureSetValues[i]->status != VehiclePropertyStatus::AVAILABLE) {
730             continue;
731         }
732         // When HVAC_DUAL_ON is initially enabled, synchronize all area IDs
733         // to the temperature of the first area ID, which is the driver's.
734         if (!tempCToSynchronize.has_value()) {
735             tempCToSynchronize = hvacTemperatureSetValues[i]->value.floatValues[0];
736             continue;
737         }
738         auto updatedValue = std::move(hvacTemperatureSetValues[i]);
739         updatedValue->value.floatValues[0] = tempCToSynchronize.value();
740         updatedValue->timestamp = elapsedRealtimeNano();
741         // This will trigger a property change event for the current hvac property value.
742         auto writeResult =
743                 mServerSidePropStore->writeValue(std::move(updatedValue), /*updateStatus=*/true,
744                                                  VehiclePropertyStore::EventMode::ALWAYS);
745         if (!writeResult.ok()) {
746             return StatusError(getErrorCode(writeResult))
747                    << "Failed to write value into property store, error: "
748                    << getErrorMsg(writeResult);
749         }
750     }
751     return {};
752 }
753 
getSyncedAreaIdIfHvacDualOn(int32_t hvacTemperatureSetAreaId) const754 std::optional<int32_t> FakeVehicleHardware::getSyncedAreaIdIfHvacDualOn(
755         int32_t hvacTemperatureSetAreaId) const {
756     auto hvacDualOnResults =
757             mServerSidePropStore->readValuesForProperty(toInt(VehicleProperty::HVAC_DUAL_ON));
758     if (!hvacDualOnResults.ok()) {
759         return std::nullopt;
760     }
761     auto& hvacDualOnValues = hvacDualOnResults.value();
762     for (size_t i = 0; i < hvacDualOnValues.size(); i++) {
763         if ((hvacDualOnValues[i]->areaId & hvacTemperatureSetAreaId) == hvacTemperatureSetAreaId &&
764             hvacDualOnValues[i]->value.int32Values.size() == 1 &&
765             hvacDualOnValues[i]->value.int32Values[0] == 1) {
766             return hvacDualOnValues[i]->areaId;
767         }
768     }
769     return std::nullopt;
770 }
771 
getUserHalProp(const VehiclePropValue & value) const772 FakeVehicleHardware::ValueResultType FakeVehicleHardware::getUserHalProp(
773         const VehiclePropValue& value) const {
774     auto propId = value.prop;
775     ALOGI("get(): getting value for prop %s from User HAL", PROP_ID_TO_CSTR(propId));
776 
777     auto result = mFakeUserHal->onGetProperty(value);
778     if (!result.ok()) {
779         return StatusError(getErrorCode(result))
780                << "get(): User HAL returned error: " << getErrorMsg(result);
781     } else {
782         auto& gotValue = result.value();
783         if (gotValue != nullptr) {
784             ALOGI("get(): User HAL returned value: %s", gotValue->toString().c_str());
785             gotValue->timestamp = elapsedRealtimeNano();
786             return result;
787         } else {
788             return StatusError(StatusCode::INTERNAL_ERROR) << "get(): User HAL returned null value";
789         }
790     }
791 }
792 
isCruiseControlTypeStandard() const793 VhalResult<bool> FakeVehicleHardware::isCruiseControlTypeStandard() const {
794     auto isCruiseControlTypeAvailableResult =
795             isAdasPropertyAvailable(toInt(VehicleProperty::CRUISE_CONTROL_TYPE));
796     if (!isCruiseControlTypeAvailableResult.ok()) {
797         return isCruiseControlTypeAvailableResult.error();
798     }
799     auto cruiseControlTypeValue =
800             mServerSidePropStore->readValue(toInt(VehicleProperty::CRUISE_CONTROL_TYPE));
801     return cruiseControlTypeValue.value()->value.int32Values[0] ==
802            toInt(CruiseControlType::STANDARD);
803 }
804 
maybeGetSpecialValue(const VehiclePropValue & value,bool * isSpecialValue) const805 FakeVehicleHardware::ValueResultType FakeVehicleHardware::maybeGetSpecialValue(
806         const VehiclePropValue& value, bool* isSpecialValue) const {
807     *isSpecialValue = false;
808     int32_t propId = value.prop;
809     ValueResultType result;
810 
811     if (mPowerControllerServiceAddress != "") {
812         if (mPowerPropIds.find(propId) != mPowerPropIds.end()) {
813             *isSpecialValue = true;
814             return getPowerPropFromExternalService(propId);
815         }
816     }
817 
818     if (propId >= STARTING_VENDOR_CODE_PROPERTIES_FOR_TEST &&
819         propId < ENDING_VENDOR_CODE_PROPERTIES_FOR_TEST) {
820         *isSpecialValue = true;
821         result = mValuePool->obtainInt32(/* value= */ 5);
822 
823         result.value()->prop = propId;
824         result.value()->areaId = 0;
825         result.value()->timestamp = elapsedRealtimeNano();
826         return result;
827     }
828 
829     if (mFakeUserHal->isSupported(propId)) {
830         *isSpecialValue = true;
831         return getUserHalProp(value);
832     }
833 
834     if (isHvacPropAndHvacNotAvailable(propId, value.areaId)) {
835         *isSpecialValue = true;
836         return StatusError(StatusCode::NOT_AVAILABLE_DISABLED) << "hvac not available";
837     }
838 
839     VhalResult<void> isAdasPropertyAvailableResult;
840     switch (propId) {
841         case OBD2_FREEZE_FRAME:
842             *isSpecialValue = true;
843             result = mFakeObd2Frame->getObd2FreezeFrame(value);
844             if (result.ok()) {
845                 result.value()->timestamp = elapsedRealtimeNano();
846             }
847             return result;
848         case OBD2_FREEZE_FRAME_INFO:
849             *isSpecialValue = true;
850             result = mFakeObd2Frame->getObd2DtcInfo();
851             if (result.ok()) {
852                 result.value()->timestamp = elapsedRealtimeNano();
853             }
854             return result;
855         case toInt(TestVendorProperty::ECHO_REVERSE_BYTES):
856             *isSpecialValue = true;
857             return getEchoReverseBytes(value);
858         case toInt(TestVendorProperty::VENDOR_PROPERTY_FOR_ERROR_CODE_TESTING):
859             *isSpecialValue = true;
860             return StatusError((StatusCode)VENDOR_ERROR_CODE);
861         case toInt(VehicleProperty::CRUISE_CONTROL_TARGET_SPEED):
862             isAdasPropertyAvailableResult =
863                     isAdasPropertyAvailable(toInt(VehicleProperty::CRUISE_CONTROL_STATE));
864             if (!isAdasPropertyAvailableResult.ok()) {
865                 *isSpecialValue = true;
866                 return isAdasPropertyAvailableResult.error();
867             }
868             return nullptr;
869         case toInt(VehicleProperty::ADAPTIVE_CRUISE_CONTROL_TARGET_TIME_GAP):
870             [[fallthrough]];
871         case toInt(VehicleProperty::ADAPTIVE_CRUISE_CONTROL_LEAD_VEHICLE_MEASURED_DISTANCE): {
872             isAdasPropertyAvailableResult =
873                     isAdasPropertyAvailable(toInt(VehicleProperty::CRUISE_CONTROL_STATE));
874             if (!isAdasPropertyAvailableResult.ok()) {
875                 *isSpecialValue = true;
876                 return isAdasPropertyAvailableResult.error();
877             }
878             auto isCruiseControlTypeStandardResult = isCruiseControlTypeStandard();
879             if (!isCruiseControlTypeStandardResult.ok()) {
880                 *isSpecialValue = true;
881                 return isCruiseControlTypeStandardResult.error();
882             }
883             if (isCruiseControlTypeStandardResult.value()) {
884                 *isSpecialValue = true;
885                 return StatusError(StatusCode::NOT_AVAILABLE_DISABLED)
886                        << "tried to get target time gap or lead vehicle measured distance value "
887                        << "while on a standard CC setting";
888             }
889             return nullptr;
890         }
891         default:
892             // Do nothing.
893             break;
894     }
895 
896     return nullptr;
897 }
898 
getPowerPropFromExternalService(int32_t propId) const899 FakeVehicleHardware::ValueResultType FakeVehicleHardware::getPowerPropFromExternalService(
900         int32_t propId) const {
901     auto channel =
902             grpc::CreateChannel(mPowerControllerServiceAddress, grpc::InsecureChannelCredentials());
903     auto clientStub = PowerController::NewStub(channel);
904     switch (propId) {
905         case toInt(VehicleProperty::VEHICLE_IN_USE):
906             return getVehicleInUse(clientStub.get());
907         case toInt(VehicleProperty::AP_POWER_BOOTUP_REASON):
908             return getApPowerBootupReason(clientStub.get());
909         default:
910             return StatusError(StatusCode::INTERNAL_ERROR)
911                    << "Unsupported power property ID: " << propId;
912     }
913 }
914 
getVehicleInUse(PowerController::Stub * clientStub) const915 FakeVehicleHardware::ValueResultType FakeVehicleHardware::getVehicleInUse(
916         PowerController::Stub* clientStub) const {
917     IsVehicleInUseRequest request = {};
918     IsVehicleInUseResponse response = {};
919     grpc::ClientContext context;
920     auto status = clientStub->IsVehicleInUse(&context, request, &response);
921     if (!status.ok()) {
922         return StatusError(StatusCode::TRY_AGAIN) << "Cannot connect to GRPC service "
923                                                   << ", error: " << status.error_message();
924     }
925     auto result = mValuePool->obtainBoolean(response.isvehicleinuse());
926     result->prop = toInt(VehicleProperty::VEHICLE_IN_USE);
927     result->areaId = 0;
928     result->status = VehiclePropertyStatus::AVAILABLE;
929     result->timestamp = elapsedRealtimeNano();
930     return result;
931 }
932 
getApPowerBootupReason(PowerController::Stub * clientStub) const933 FakeVehicleHardware::ValueResultType FakeVehicleHardware::getApPowerBootupReason(
934         PowerController::Stub* clientStub) const {
935     GetApPowerBootupReasonRequest request = {};
936     GetApPowerBootupReasonResponse response = {};
937     grpc::ClientContext context;
938     auto status = clientStub->GetApPowerBootupReason(&context, request, &response);
939     if (!status.ok()) {
940         return StatusError(StatusCode::TRY_AGAIN) << "Cannot connect to GRPC service "
941                                                   << ", error: " << status.error_message();
942     }
943     auto result = mValuePool->obtainInt32(response.bootupreason());
944     result->prop = toInt(VehicleProperty::AP_POWER_BOOTUP_REASON);
945     result->areaId = 0;
946     result->status = VehiclePropertyStatus::AVAILABLE;
947     result->timestamp = elapsedRealtimeNano();
948     return result;
949 }
950 
getEchoReverseBytes(const VehiclePropValue & value) const951 FakeVehicleHardware::ValueResultType FakeVehicleHardware::getEchoReverseBytes(
952         const VehiclePropValue& value) const {
953     auto readResult = mServerSidePropStore->readValue(value);
954     if (!readResult.ok()) {
955         return readResult;
956     }
957     auto& gotValue = readResult.value();
958     gotValue->timestamp = elapsedRealtimeNano();
959     std::vector<uint8_t> byteValues = gotValue->value.byteValues;
960     size_t byteSize = byteValues.size();
961     for (size_t i = 0; i < byteSize; i++) {
962         gotValue->value.byteValues[i] = byteValues[byteSize - 1 - i];
963     }
964     return std::move(gotValue);
965 }
966 
sendHvacPropertiesCurrentValues(int32_t areaId,int32_t hvacPowerOnVal)967 void FakeVehicleHardware::sendHvacPropertiesCurrentValues(int32_t areaId, int32_t hvacPowerOnVal) {
968     for (auto& powerPropId : hvacPowerDependentProps) {
969         auto powerPropResults = mServerSidePropStore->readValuesForProperty(powerPropId);
970         if (!powerPropResults.ok()) {
971             ALOGW("failed to get power prop 0x%x, error: %s", powerPropId,
972                   getErrorMsg(powerPropResults).c_str());
973             continue;
974         }
975         auto& powerPropValues = powerPropResults.value();
976         for (size_t j = 0; j < powerPropValues.size(); j++) {
977             auto powerPropValue = std::move(powerPropValues[j]);
978             if ((powerPropValue->areaId & areaId) == powerPropValue->areaId) {
979                 powerPropValue->status = hvacPowerOnVal ? VehiclePropertyStatus::AVAILABLE
980                                                         : VehiclePropertyStatus::UNAVAILABLE;
981                 powerPropValue->timestamp = elapsedRealtimeNano();
982                 // This will trigger a property change event for the current hvac property value.
983                 mServerSidePropStore->writeValue(std::move(powerPropValue), /*updateStatus=*/true,
984                                                  VehiclePropertyStore::EventMode::ALWAYS);
985             }
986         }
987     }
988 }
989 
sendAdasPropertiesState(int32_t propertyId,int32_t state)990 void FakeVehicleHardware::sendAdasPropertiesState(int32_t propertyId, int32_t state) {
991     auto& adasDependentPropIds = mAdasEnabledPropToAdasPropWithErrorState.find(propertyId)->second;
992     for (auto dependentPropId : adasDependentPropIds) {
993         auto dependentPropConfigResult = mServerSidePropStore->getPropConfig(dependentPropId);
994         if (!dependentPropConfigResult.ok()) {
995             ALOGW("Failed to get config for ADAS property 0x%x, error: %s", dependentPropId,
996                   getErrorMsg(dependentPropConfigResult).c_str());
997             continue;
998         }
999         auto& dependentPropConfig = dependentPropConfigResult.value();
1000         for (auto& areaConfig : dependentPropConfig.areaConfigs) {
1001             int32_t hardcoded_state = state;
1002             // TODO: restore old/initial values here instead of hardcoded value (b/295542701)
1003             if (state == 1 && dependentPropId == toInt(VehicleProperty::CRUISE_CONTROL_TYPE)) {
1004                 hardcoded_state = toInt(CruiseControlType::ADAPTIVE);
1005             }
1006             auto propValue =
1007                     createAdasStateReq(dependentPropId, areaConfig.areaId, hardcoded_state);
1008             // This will trigger a property change event for the current ADAS property value.
1009             mServerSidePropStore->writeValue(std::move(propValue), /*updateStatus=*/true,
1010                                              VehiclePropertyStore::EventMode::ALWAYS);
1011         }
1012     }
1013 }
1014 
maybeSetSpecialValue(const VehiclePropValue & value,bool * isSpecialValue)1015 VhalResult<void> FakeVehicleHardware::maybeSetSpecialValue(const VehiclePropValue& value,
1016                                                            bool* isSpecialValue) {
1017     *isSpecialValue = false;
1018     VehiclePropValuePool::RecyclableType updatedValue;
1019     int32_t propId = value.prop;
1020 
1021     if (propId >= STARTING_VENDOR_CODE_PROPERTIES_FOR_TEST &&
1022         propId < ENDING_VENDOR_CODE_PROPERTIES_FOR_TEST) {
1023         *isSpecialValue = true;
1024         return {};
1025     }
1026 
1027     if (mFakeUserHal->isSupported(propId)) {
1028         *isSpecialValue = true;
1029         return setUserHalProp(value);
1030     }
1031 
1032     if (isHvacPropAndHvacNotAvailable(propId, value.areaId)) {
1033         *isSpecialValue = true;
1034         return StatusError(StatusCode::NOT_AVAILABLE_DISABLED) << "hvac not available";
1035     }
1036 
1037     if (mAdasEnabledPropToAdasPropWithErrorState.count(propId) &&
1038         value.value.int32Values.size() == 1) {
1039         if (value.value.int32Values[0] == 1) {
1040             // Set default state to 1 when ADAS feature is enabled.
1041             sendAdasPropertiesState(propId, /* state = */ 1);
1042         } else {
1043             sendAdasPropertiesState(propId, toInt(ErrorState::NOT_AVAILABLE_DISABLED));
1044         }
1045     }
1046 
1047     VhalResult<void> isAdasPropertyAvailableResult;
1048     VhalResult<bool> isCruiseControlTypeStandardResult;
1049     switch (propId) {
1050         case toInt(VehicleProperty::AP_POWER_STATE_REPORT):
1051             *isSpecialValue = true;
1052             return setApPowerStateReport(value);
1053         case toInt(VehicleProperty::SHUTDOWN_REQUEST):
1054             // If we receive SHUTDOWN_REQUEST, we should send this to an external component which
1055             // should shutdown Android system via sending an AP_POWER_STATE_REQ event. Here we have
1056             // no external components to notify, so we just send the event.
1057             *isSpecialValue = true;
1058             return setApPowerStateReqShutdown(value);
1059         case toInt(VehicleProperty::VEHICLE_MAP_SERVICE):
1060             // Placeholder for future implementation of VMS property in the default hal. For
1061             // now, just returns OK; otherwise, hal clients crash with property not supported.
1062             *isSpecialValue = true;
1063             return {};
1064         case OBD2_FREEZE_FRAME_CLEAR:
1065             *isSpecialValue = true;
1066             return mFakeObd2Frame->clearObd2FreezeFrames(value);
1067         case toInt(TestVendorProperty::VENDOR_PROPERTY_FOR_ERROR_CODE_TESTING):
1068             *isSpecialValue = true;
1069             return StatusError((StatusCode)VENDOR_ERROR_CODE);
1070         case toInt(VehicleProperty::HVAC_POWER_ON):
1071             if (value.value.int32Values.size() != 1) {
1072                 *isSpecialValue = true;
1073                 return StatusError(StatusCode::INVALID_ARG)
1074                        << "HVAC_POWER_ON requires only one int32 value";
1075             }
1076             // When changing HVAC power state, send current hvac property values
1077             // through on change event.
1078             sendHvacPropertiesCurrentValues(value.areaId, value.value.int32Values[0]);
1079             return {};
1080         case toInt(VehicleProperty::HVAC_TEMPERATURE_VALUE_SUGGESTION):
1081             *isSpecialValue = true;
1082             return setHvacTemperatureValueSuggestion(value);
1083         case toInt(VehicleProperty::HVAC_TEMPERATURE_SET):
1084             if (value.value.floatValues.size() != 1) {
1085                 *isSpecialValue = true;
1086                 return StatusError(StatusCode::INVALID_ARG)
1087                        << "HVAC_DUAL_ON requires only one float value";
1088             }
1089             if (auto hvacDualOnAreaId = getSyncedAreaIdIfHvacDualOn(value.areaId);
1090                 hvacDualOnAreaId.has_value()) {
1091                 *isSpecialValue = true;
1092                 return synchronizeHvacTemp(hvacDualOnAreaId.value(), value.value.floatValues[0]);
1093             }
1094             return {};
1095         case toInt(VehicleProperty::HVAC_DUAL_ON):
1096             if (value.value.int32Values.size() != 1) {
1097                 *isSpecialValue = true;
1098                 return StatusError(StatusCode::INVALID_ARG)
1099                        << "HVAC_DUAL_ON requires only one int32 value";
1100             }
1101             if (value.value.int32Values[0] == 1) {
1102                 synchronizeHvacTemp(value.areaId, std::nullopt);
1103             }
1104             return {};
1105         case toInt(VehicleProperty::LANE_CENTERING_ASSIST_COMMAND): {
1106             isAdasPropertyAvailableResult =
1107                     isAdasPropertyAvailable(toInt(VehicleProperty::LANE_CENTERING_ASSIST_STATE));
1108             if (!isAdasPropertyAvailableResult.ok()) {
1109                 *isSpecialValue = true;
1110             }
1111             return isAdasPropertyAvailableResult;
1112         }
1113         case toInt(VehicleProperty::CRUISE_CONTROL_COMMAND):
1114             isAdasPropertyAvailableResult =
1115                     isAdasPropertyAvailable(toInt(VehicleProperty::CRUISE_CONTROL_STATE));
1116             if (!isAdasPropertyAvailableResult.ok()) {
1117                 *isSpecialValue = true;
1118                 return isAdasPropertyAvailableResult;
1119             }
1120             isCruiseControlTypeStandardResult = isCruiseControlTypeStandard();
1121             if (!isCruiseControlTypeStandardResult.ok()) {
1122                 *isSpecialValue = true;
1123                 return isCruiseControlTypeStandardResult.error();
1124             }
1125             if (isCruiseControlTypeStandardResult.value() &&
1126                 (value.value.int32Values[0] ==
1127                          toInt(CruiseControlCommand::INCREASE_TARGET_TIME_GAP) ||
1128                  value.value.int32Values[0] ==
1129                          toInt(CruiseControlCommand::DECREASE_TARGET_TIME_GAP))) {
1130                 *isSpecialValue = true;
1131                 return StatusError(StatusCode::NOT_AVAILABLE_DISABLED)
1132                        << "tried to use a change target time gap command while on a standard CC "
1133                        << "setting";
1134             }
1135             return {};
1136         case toInt(VehicleProperty::ADAPTIVE_CRUISE_CONTROL_TARGET_TIME_GAP): {
1137             isAdasPropertyAvailableResult =
1138                     isAdasPropertyAvailable(toInt(VehicleProperty::CRUISE_CONTROL_STATE));
1139             if (!isAdasPropertyAvailableResult.ok()) {
1140                 *isSpecialValue = true;
1141                 return isAdasPropertyAvailableResult;
1142             }
1143             isCruiseControlTypeStandardResult = isCruiseControlTypeStandard();
1144             if (!isCruiseControlTypeStandardResult.ok()) {
1145                 *isSpecialValue = true;
1146                 return isCruiseControlTypeStandardResult.error();
1147             }
1148             if (isCruiseControlTypeStandardResult.value()) {
1149                 *isSpecialValue = true;
1150                 return StatusError(StatusCode::NOT_AVAILABLE_DISABLED)
1151                        << "tried to set target time gap or lead vehicle measured distance value "
1152                        << "while on a standard CC setting";
1153             }
1154             return {};
1155         }
1156 
1157 #ifdef ENABLE_VEHICLE_HAL_TEST_PROPERTIES
1158         case toInt(VehicleProperty::CLUSTER_REPORT_STATE):
1159             [[fallthrough]];
1160         case toInt(VehicleProperty::CLUSTER_REQUEST_DISPLAY):
1161             [[fallthrough]];
1162         case toInt(VehicleProperty::CLUSTER_NAVIGATION_STATE):
1163             [[fallthrough]];
1164         case toInt(TestVendorProperty::VENDOR_CLUSTER_SWITCH_UI):
1165             [[fallthrough]];
1166         case toInt(TestVendorProperty::VENDOR_CLUSTER_DISPLAY_STATE):
1167             *isSpecialValue = true;
1168             updatedValue = mValuePool->obtain(getPropType(value.prop));
1169             updatedValue->prop = value.prop & ~toInt(VehiclePropertyGroup::MASK);
1170             if (getPropGroup(value.prop) == VehiclePropertyGroup::SYSTEM) {
1171                 updatedValue->prop |= toInt(VehiclePropertyGroup::VENDOR);
1172             } else {
1173                 updatedValue->prop |= toInt(VehiclePropertyGroup::SYSTEM);
1174             }
1175             updatedValue->value = value.value;
1176             updatedValue->timestamp = elapsedRealtimeNano();
1177             updatedValue->areaId = value.areaId;
1178             if (auto writeResult = mServerSidePropStore->writeValue(std::move(updatedValue));
1179                 !writeResult.ok()) {
1180                 return StatusError(getErrorCode(writeResult))
1181                        << "failed to write value into property store, error: "
1182                        << getErrorMsg(writeResult);
1183             }
1184             return {};
1185 #endif  // ENABLE_VEHICLE_HAL_TEST_PROPERTIES
1186 
1187         default:
1188             break;
1189     }
1190     return {};
1191 }
1192 
setValues(std::shared_ptr<const SetValuesCallback> callback,const std::vector<SetValueRequest> & requests)1193 StatusCode FakeVehicleHardware::setValues(std::shared_ptr<const SetValuesCallback> callback,
1194                                           const std::vector<SetValueRequest>& requests) {
1195     for (auto& request : requests) {
1196         if (FAKE_VEHICLEHARDWARE_DEBUG) {
1197             ALOGD("Set value for property ID: %s", PROP_ID_TO_CSTR(request.value.prop));
1198         }
1199 
1200         // In a real VHAL implementation, you could either send the setValue request to vehicle bus
1201         // here in the binder thread, or you could send the request in setValue which runs in
1202         // the handler thread. If you decide to send the setValue request here, you should not
1203         // wait for the response here and the handler thread should handle the setValue response.
1204         mPendingSetValueRequests.addRequest(request, callback);
1205     }
1206 
1207     return StatusCode::OK;
1208 }
1209 
setValue(const VehiclePropValue & value)1210 VhalResult<void> FakeVehicleHardware::setValue(const VehiclePropValue& value) {
1211     // In a real VHAL implementation, this will send the request to vehicle bus if not already
1212     // sent in setValues, and wait for the response from vehicle bus.
1213     // Here we are just updating mValuePool.
1214     bool isSpecialValue = false;
1215     auto setSpecialValueResult = maybeSetSpecialValue(value, &isSpecialValue);
1216     if (isSpecialValue) {
1217         if (!setSpecialValueResult.ok()) {
1218             return StatusError(getErrorCode(setSpecialValueResult)) << StringPrintf(
1219                            "failed to set special value for property ID: %s, error: %s",
1220                            PROP_ID_TO_CSTR(value.prop), getErrorMsg(setSpecialValueResult).c_str());
1221         }
1222         return {};
1223     }
1224 
1225     auto updatedValue = mValuePool->obtain(value);
1226 
1227     auto writeResult = mServerSidePropStore->writeValue(
1228             std::move(updatedValue),
1229             /*updateStatus=*/false, /*mode=*/VehiclePropertyStore::EventMode::ON_VALUE_CHANGE,
1230             /*useCurrentTimestamp=*/true);
1231     if (!writeResult.ok()) {
1232         return StatusError(getErrorCode(writeResult))
1233                << StringPrintf("failed to write value into property store, error: %s",
1234                                getErrorMsg(writeResult).c_str());
1235     }
1236 
1237     return {};
1238 }
1239 
handleSetValueRequest(const SetValueRequest & request)1240 SetValueResult FakeVehicleHardware::handleSetValueRequest(const SetValueRequest& request) {
1241     SetValueResult setValueResult;
1242     setValueResult.requestId = request.requestId;
1243 
1244     if (auto result = setValue(request.value); !result.ok()) {
1245         ALOGE("failed to set value, error: %s, code: %d", getErrorMsg(result).c_str(),
1246               getIntErrorCode(result));
1247         setValueResult.status = getErrorCode(result);
1248     } else {
1249         setValueResult.status = StatusCode::OK;
1250     }
1251 
1252     return setValueResult;
1253 }
1254 
getValues(std::shared_ptr<const GetValuesCallback> callback,const std::vector<GetValueRequest> & requests) const1255 StatusCode FakeVehicleHardware::getValues(std::shared_ptr<const GetValuesCallback> callback,
1256                                           const std::vector<GetValueRequest>& requests) const {
1257     for (auto& request : requests) {
1258         if (FAKE_VEHICLEHARDWARE_DEBUG) {
1259             ALOGD("getValues(%s)", PROP_ID_TO_CSTR(request.prop.prop));
1260         }
1261 
1262         // In a real VHAL implementation, you could either send the getValue request to vehicle bus
1263         // here in the binder thread, or you could send the request in getValue which runs in
1264         // the handler thread. If you decide to send the getValue request here, you should not
1265         // wait for the response here and the handler thread should handle the getValue response.
1266         mPendingGetValueRequests.addRequest(request, callback);
1267     }
1268 
1269     return StatusCode::OK;
1270 }
1271 
handleGetValueRequest(const GetValueRequest & request)1272 GetValueResult FakeVehicleHardware::handleGetValueRequest(const GetValueRequest& request) {
1273     GetValueResult getValueResult;
1274     getValueResult.requestId = request.requestId;
1275 
1276     auto result = getValue(request.prop);
1277     if (!result.ok()) {
1278         ALOGE("failed to get value, error: %s, code: %d", getErrorMsg(result).c_str(),
1279               getIntErrorCode(result));
1280         getValueResult.status = getErrorCode(result);
1281     } else {
1282         getValueResult.status = StatusCode::OK;
1283         getValueResult.prop = *result.value();
1284     }
1285     return getValueResult;
1286 }
1287 
getValue(const VehiclePropValue & value) const1288 FakeVehicleHardware::ValueResultType FakeVehicleHardware::getValue(
1289         const VehiclePropValue& value) const {
1290     // In a real VHAL implementation, this will send the request to vehicle bus if not already
1291     // sent in getValues, and wait for the response from vehicle bus.
1292     // Here we are just reading value from mValuePool.
1293     bool isSpecialValue = false;
1294     auto result = maybeGetSpecialValue(value, &isSpecialValue);
1295     if (isSpecialValue) {
1296         if (!result.ok()) {
1297             return StatusError(getErrorCode(result))
1298                    << StringPrintf("failed to get special value: %s, error: %s",
1299                                    PROP_ID_TO_CSTR(value.prop), getErrorMsg(result).c_str());
1300         } else {
1301             return result;
1302         }
1303     }
1304 
1305     auto readResult = mServerSidePropStore->readValue(value);
1306     if (!readResult.ok()) {
1307         StatusCode errorCode = getErrorCode(readResult);
1308         if (errorCode == StatusCode::NOT_AVAILABLE) {
1309             return StatusError(errorCode) << "value has not been set yet";
1310         } else {
1311             return StatusError(errorCode)
1312                    << "failed to get value, error: " << getErrorMsg(readResult);
1313         }
1314     }
1315 
1316     return readResult;
1317 }
1318 
dump(const std::vector<std::string> & options)1319 DumpResult FakeVehicleHardware::dump(const std::vector<std::string>& options) {
1320     DumpResult result;
1321     result.callerShouldDumpState = false;
1322     if (options.size() == 0) {
1323         // We only want caller to dump default state when there is no options.
1324         result.callerShouldDumpState = true;
1325         result.buffer = dumpAllProperties();
1326         return result;
1327     }
1328     std::string option = options[0];
1329     if (EqualsIgnoreCase(option, "--help")) {
1330         result.buffer = dumpHelp();
1331         return result;
1332     } else if (EqualsIgnoreCase(option, "--list")) {
1333         result.buffer = dumpListProperties();
1334     } else if (EqualsIgnoreCase(option, "--get")) {
1335         result.buffer = dumpSpecificProperty(options);
1336     } else if (EqualsIgnoreCase(option, "--getWithArg")) {
1337         result.buffer = dumpGetPropertyWithArg(options);
1338     } else if (EqualsIgnoreCase(option, "--set")) {
1339         result.buffer = dumpSetProperties(options);
1340     } else if (EqualsIgnoreCase(option, "--save-prop")) {
1341         result.buffer = dumpSaveProperty(options);
1342     } else if (EqualsIgnoreCase(option, "--restore-prop")) {
1343         result.buffer = dumpRestoreProperty(options);
1344     } else if (EqualsIgnoreCase(option, "--inject-event")) {
1345         result.buffer = dumpInjectEvent(options);
1346     } else if (EqualsIgnoreCase(option, kUserHalDumpOption)) {
1347         result.buffer = mFakeUserHal->dump();
1348     } else if (EqualsIgnoreCase(option, "--genfakedata")) {
1349         result.buffer = genFakeDataCommand(options);
1350     } else if (EqualsIgnoreCase(option, "--genTestVendorConfigs")) {
1351         mAddExtraTestVendorConfigs = true;
1352         result.refreshPropertyConfigs = true;
1353         result.buffer = "successfully generated vendor configs";
1354     } else if (EqualsIgnoreCase(option, "--restoreVendorConfigs")) {
1355         mAddExtraTestVendorConfigs = false;
1356         result.refreshPropertyConfigs = true;
1357         result.buffer = "successfully restored vendor configs";
1358     } else if (EqualsIgnoreCase(option, "--dumpSub")) {
1359         result.buffer = dumpSubscriptions();
1360     } else {
1361         result.buffer = StringPrintf("Invalid option: %s\n", option.c_str());
1362     }
1363     return result;
1364 }
1365 
genFakeDataHelp()1366 std::string FakeVehicleHardware::genFakeDataHelp() {
1367     return R"(
1368 Generate Fake Data Usage:
1369 --genfakedata --startlinear [propID] [mValue] [cValue] [dispersion] [increment] [interval]: "
1370 Start a linear generator that generates event with floatValue within range:
1371 [mValue - disperson, mValue + dispersion].
1372 propID(int32): ID for the property to generate event for.
1373 mValue(float): The middle of the possible values for the property.
1374 cValue(float): The start value for the property, must be within the range.
1375 dispersion(float): The range the value can change.
1376 increment(float): The step the value would increase by for each generated event,
1377 if exceed the range, the value would loop back.
1378 interval(int64): The interval in nanoseconds the event would generate by.
1379 
1380 --genfakedata --stoplinear [propID(int32)]: Stop a linear generator
1381 
1382 --genfakedata --startjson --path [jsonFilePath] [repetition]:
1383 Start a JSON generator that would generate events according to a JSON file.
1384 jsonFilePath(string): The path to a JSON file. The JSON content must be in the format of
1385 [{
1386     "timestamp": 1000000,
1387     "areaId": 0,
1388     "value": 8,
1389     "prop": 289408000
1390 }, {...}]
1391 Each event in the JSON file would be generated by the same interval their timestamp is relative to
1392 the first event's timestamp.
1393 repetition(int32, optional): how many iterations the events would be generated. If it is not
1394 provided, it would iterate indefinitely.
1395 
1396 --genfakedata --startjson --content [jsonContent]: Start a JSON generator using the content.
1397 
1398 --genfakedata --stopjson [generatorID(string)]: Stop a JSON generator.
1399 
1400 --genfakedata --keypress [keyCode(int32)] [display[int32]]: Generate key press.
1401 
1402 --genfakedata --keyinputv2 [area(int32)] [display(int32)] [keyCode[int32]] [action[int32]]
1403   [repeatCount(int32)]
1404 
1405 --genfakedata --motioninput [area(int32)] [display(int32)] [inputType[int32]] [action[int32]]
1406   [buttonState(int32)] --pointer [pointerId(int32)] [toolType(int32)] [xData(float)] [yData(float)]
1407   [pressure(float)] [size(float)]
1408   Generate a motion input event. --pointer option can be specified multiple times.
1409 
1410 --genTestVendorConfigs: Generates fake VehiclePropConfig ranging from 0x5000 to 0x8000 all with
1411   vendor property group, global vehicle area, and int32 vehicle property type. This is mainly used
1412   for testing
1413 
1414 --restoreVendorConfigs: Restores to to the default state if genTestVendorConfigs was used.
1415   Otherwise this will do nothing.
1416 
1417 )";
1418 }
1419 
1420 std::string FakeVehicleHardware::parseErrMsg(std::string fieldName, std::string value,
1421                                              std::string type) {
1422     return StringPrintf("failed to parse %s as %s: \"%s\"\n%s", fieldName.c_str(), type.c_str(),
1423                         value.c_str(), genFakeDataHelp().c_str());
1424 }
1425 
1426 void FakeVehicleHardware::generateVendorConfigs(
1427         std::vector<VehiclePropConfig>& outAllConfigs) const {
1428     for (int i = STARTING_VENDOR_CODE_PROPERTIES_FOR_TEST;
1429          i < ENDING_VENDOR_CODE_PROPERTIES_FOR_TEST; i++) {
1430         VehiclePropConfig config;
1431         config.prop = i;
1432         config.access = VehiclePropertyAccess::READ_WRITE;
1433         outAllConfigs.push_back(config);
1434     }
1435 }
1436 
1437 std::string FakeVehicleHardware::genFakeDataCommand(const std::vector<std::string>& options) {
1438     if (options.size() < 2) {
1439         return "No subcommand specified for genfakedata\n" + genFakeDataHelp();
1440     }
1441 
1442     std::string command = options[1];
1443     if (command == "--startlinear") {
1444         // --genfakedata --startlinear [propID(int32)] [middleValue(float)]
1445         // [currentValue(float)] [dispersion(float)] [increment(float)] [interval(int64)]
1446         if (options.size() != 8) {
1447             return "incorrect argument count, need 8 arguments for --genfakedata --startlinear\n" +
1448                    genFakeDataHelp();
1449         }
1450         int32_t propId;
1451         float middleValue;
1452         float currentValue;
1453         float dispersion;
1454         float increment;
1455         int64_t interval;
1456         if (!android::base::ParseInt(options[2], &propId)) {
1457             return parseErrMsg("propId", options[2], "int");
1458         }
1459         if (!android::base::ParseFloat(options[3], &middleValue)) {
1460             return parseErrMsg("middleValue", options[3], "float");
1461         }
1462         if (!android::base::ParseFloat(options[4], &currentValue)) {
1463             return parseErrMsg("currentValue", options[4], "float");
1464         }
1465         if (!android::base::ParseFloat(options[5], &dispersion)) {
1466             return parseErrMsg("dispersion", options[5], "float");
1467         }
1468         if (!android::base::ParseFloat(options[6], &increment)) {
1469             return parseErrMsg("increment", options[6], "float");
1470         }
1471         if (!android::base::ParseInt(options[7], &interval)) {
1472             return parseErrMsg("interval", options[7], "int");
1473         }
1474         auto generator = std::make_unique<LinearFakeValueGenerator>(
1475                 propId, middleValue, currentValue, dispersion, increment, interval);
1476         mGeneratorHub->registerGenerator(propId, std::move(generator));
1477         return "Linear event generator started successfully";
1478     } else if (command == "--stoplinear") {
1479         // --genfakedata --stoplinear [propID(int32)]
1480         if (options.size() != 3) {
1481             return "incorrect argument count, need 3 arguments for --genfakedata --stoplinear\n" +
1482                    genFakeDataHelp();
1483         }
1484         int32_t propId;
1485         if (!android::base::ParseInt(options[2], &propId)) {
1486             return parseErrMsg("propId", options[2], "int");
1487         }
1488         if (mGeneratorHub->unregisterGenerator(propId)) {
1489             return "Linear event generator stopped successfully";
1490         }
1491         return StringPrintf("No linear event generator found for property: %s",
1492                             PROP_ID_TO_CSTR(propId));
1493     } else if (command == "--startjson") {
1494         // --genfakedata --startjson --path path repetition
1495         // or
1496         // --genfakedata --startjson --content content repetition.
1497         if (options.size() != 4 && options.size() != 5) {
1498             return "incorrect argument count, need 4 or 5 arguments for --genfakedata "
1499                    "--startjson\n";
1500         }
1501         // Iterate infinitely if repetition number is not provided
1502         int32_t repetition = -1;
1503         if (options.size() == 5) {
1504             if (!android::base::ParseInt(options[4], &repetition)) {
1505                 return parseErrMsg("repetition", options[4], "int");
1506             }
1507         }
1508         std::unique_ptr<JsonFakeValueGenerator> generator;
1509         if (options[2] == "--path") {
1510             const std::string& fileName = options[3];
1511             generator = std::make_unique<JsonFakeValueGenerator>(fileName, repetition);
1512             if (!generator->hasNext()) {
1513                 return "invalid JSON file, no events";
1514             }
1515         } else if (options[2] == "--content") {
1516             const std::string& content = options[3];
1517             generator =
1518                     std::make_unique<JsonFakeValueGenerator>(/*unused=*/true, content, repetition);
1519             if (!generator->hasNext()) {
1520                 return "invalid JSON content, no events";
1521             }
1522         }
1523         int32_t cookie = std::hash<std::string>()(options[3]);
1524         mGeneratorHub->registerGenerator(cookie, std::move(generator));
1525         return StringPrintf("JSON event generator started successfully, ID: %" PRId32, cookie);
1526     } else if (command == "--stopjson") {
1527         // --genfakedata --stopjson [generatorID(string)]
1528         if (options.size() != 3) {
1529             return "incorrect argument count, need 3 arguments for --genfakedata --stopjson\n";
1530         }
1531         int32_t cookie;
1532         if (!android::base::ParseInt(options[2], &cookie)) {
1533             return parseErrMsg("cookie", options[2], "int");
1534         }
1535         if (mGeneratorHub->unregisterGenerator(cookie)) {
1536             return "JSON event generator stopped successfully";
1537         } else {
1538             return StringPrintf("No JSON event generator found for ID: %s", options[2].c_str());
1539         }
1540     } else if (command == "--keypress") {
1541         int32_t keyCode;
1542         int32_t display;
1543         // --genfakedata --keypress [keyCode(int32)] [display[int32]]
1544         if (options.size() != 4) {
1545             return "incorrect argument count, need 4 arguments for --genfakedata --keypress\n";
1546         }
1547         if (!android::base::ParseInt(options[2], &keyCode)) {
1548             return parseErrMsg("keyCode", options[2], "int");
1549         }
1550         if (!android::base::ParseInt(options[3], &display)) {
1551             return parseErrMsg("display", options[3], "int");
1552         }
1553         // Send back to HAL
1554         onValueChangeCallback(
1555                 createHwInputKeyProp(VehicleHwKeyInputAction::ACTION_DOWN, keyCode, display));
1556         onValueChangeCallback(
1557                 createHwInputKeyProp(VehicleHwKeyInputAction::ACTION_UP, keyCode, display));
1558         return "keypress event generated successfully";
1559     } else if (command == "--keyinputv2") {
1560         int32_t area;
1561         int32_t display;
1562         int32_t keyCode;
1563         int32_t action;
1564         int32_t repeatCount;
1565         // --genfakedata --keyinputv2 [area(int32)] [display(int32)] [keyCode[int32]]
1566         // [action[int32]] [repeatCount(int32)]
1567         if (options.size() != 7) {
1568             return "incorrect argument count, need 7 arguments for --genfakedata --keyinputv2\n";
1569         }
1570         if (!android::base::ParseInt(options[2], &area)) {
1571             return parseErrMsg("area", options[2], "int");
1572         }
1573         if (!android::base::ParseInt(options[3], &display)) {
1574             return parseErrMsg("display", options[3], "int");
1575         }
1576         if (!android::base::ParseInt(options[4], &keyCode)) {
1577             return parseErrMsg("keyCode", options[4], "int");
1578         }
1579         if (!android::base::ParseInt(options[5], &action)) {
1580             return parseErrMsg("action", options[5], "int");
1581         }
1582         if (!android::base::ParseInt(options[6], &repeatCount)) {
1583             return parseErrMsg("repeatCount", options[6], "int");
1584         }
1585         // Send back to HAL
1586         onValueChangeCallback(createHwKeyInputV2Prop(area, display, keyCode, action, repeatCount));
1587         return StringPrintf(
1588                 "keyinputv2 event generated successfully with area:%d, display:%d,"
1589                 " keyCode:%d, action:%d, repeatCount:%d",
1590                 area, display, keyCode, action, repeatCount);
1591 
1592     } else if (command == "--motioninput") {
1593         int32_t area;
1594         int32_t display;
1595         int32_t inputType;
1596         int32_t action;
1597         int32_t buttonState;
1598         int32_t pointerCount;
1599 
1600         // --genfakedata --motioninput [area(int32)] [display(int32)] [inputType[int32]]
1601         // [action[int32]] [buttonState(int32)] [pointerCount(int32)]
1602         // --pointer [pointerId(int32)] [toolType(int32)] [xData(float)] [yData(float)]
1603         // [pressure(float)] [size(float)]
1604         int optionsSize = (int)options.size();
1605         if (optionsSize / 7 < 2) {
1606             return "incorrect argument count, need at least 14 arguments for --genfakedata "
1607                    "--motioninput including at least 1 --pointer\n";
1608         }
1609 
1610         if (optionsSize % 7 != 0) {
1611             return "incorrect argument count, need 6 arguments for every --pointer\n";
1612         }
1613         pointerCount = (int)optionsSize / 7 - 1;
1614 
1615         if (!android::base::ParseInt(options[2], &area)) {
1616             return parseErrMsg("area", options[2], "int");
1617         }
1618         if (!android::base::ParseInt(options[3], &display)) {
1619             return parseErrMsg("display", options[3], "int");
1620         }
1621         if (!android::base::ParseInt(options[4], &inputType)) {
1622             return parseErrMsg("inputType", options[4], "int");
1623         }
1624         if (!android::base::ParseInt(options[5], &action)) {
1625             return parseErrMsg("action", options[5], "int");
1626         }
1627         if (!android::base::ParseInt(options[6], &buttonState)) {
1628             return parseErrMsg("buttonState", options[6], "int");
1629         }
1630 
1631         int32_t pointerId[pointerCount];
1632         int32_t toolType[pointerCount];
1633         float xData[pointerCount];
1634         float yData[pointerCount];
1635         float pressure[pointerCount];
1636         float size[pointerCount];
1637 
1638         for (int i = 7, pc = 0; i < optionsSize; i += 7, pc += 1) {
1639             int offset = i;
1640             if (options[offset] != "--pointer") {
1641                 return "--pointer is needed for the motion input\n";
1642             }
1643             offset += 1;
1644             if (!android::base::ParseInt(options[offset], &pointerId[pc])) {
1645                 return parseErrMsg("pointerId", options[offset], "int");
1646             }
1647             offset += 1;
1648             if (!android::base::ParseInt(options[offset], &toolType[pc])) {
1649                 return parseErrMsg("toolType", options[offset], "int");
1650             }
1651             offset += 1;
1652             if (!android::base::ParseFloat(options[offset], &xData[pc])) {
1653                 return parseErrMsg("xData", options[offset], "float");
1654             }
1655             offset += 1;
1656             if (!android::base::ParseFloat(options[offset], &yData[pc])) {
1657                 return parseErrMsg("yData", options[offset], "float");
1658             }
1659             offset += 1;
1660             if (!android::base::ParseFloat(options[offset], &pressure[pc])) {
1661                 return parseErrMsg("pressure", options[offset], "float");
1662             }
1663             offset += 1;
1664             if (!android::base::ParseFloat(options[offset], &size[pc])) {
1665                 return parseErrMsg("size", options[offset], "float");
1666             }
1667         }
1668 
1669         // Send back to HAL
1670         onValueChangeCallback(createHwMotionInputProp(area, display, inputType, action, buttonState,
1671                                                       pointerCount, pointerId, toolType, xData,
1672                                                       yData, pressure, size));
1673 
1674         std::string successMessage = StringPrintf(
1675                 "motion event generated successfully with area:%d, display:%d,"
1676                 " inputType:%d, action:%d, buttonState:%d, pointerCount:%d\n",
1677                 area, display, inputType, action, buttonState, pointerCount);
1678         for (int i = 0; i < pointerCount; i++) {
1679             successMessage += StringPrintf(
1680                     "Pointer #%d {\n"
1681                     " id:%d , tooltype:%d \n"
1682                     " x:%f , y:%f\n"
1683                     " pressure: %f, data: %f\n"
1684                     "}\n",
1685                     i, pointerId[i], toolType[i], xData[i], yData[i], pressure[i], size[i]);
1686         }
1687         return successMessage;
1688     }
1689 
1690     return StringPrintf("Unknown command: \"%s\"\n%s", command.c_str(), genFakeDataHelp().c_str());
1691 }
1692 
1693 VehiclePropValue FakeVehicleHardware::createHwInputKeyProp(VehicleHwKeyInputAction action,
1694                                                            int32_t keyCode, int32_t targetDisplay) {
1695     VehiclePropValue value = {
1696             .timestamp = elapsedRealtimeNano(),
1697             .areaId = 0,
1698             .prop = toInt(VehicleProperty::HW_KEY_INPUT),
1699             .status = VehiclePropertyStatus::AVAILABLE,
1700             .value.int32Values = {toInt(action), keyCode, targetDisplay},
1701     };
1702     return value;
1703 }
1704 
1705 VehiclePropValue FakeVehicleHardware::createHwKeyInputV2Prop(int32_t area, int32_t targetDisplay,
1706                                                              int32_t keyCode, int32_t action,
1707                                                              int32_t repeatCount) {
1708     VehiclePropValue value = {.timestamp = elapsedRealtimeNano(),
1709                               .areaId = area,
1710                               .prop = toInt(VehicleProperty::HW_KEY_INPUT_V2),
1711                               .status = VehiclePropertyStatus::AVAILABLE,
1712                               .value.int32Values = {targetDisplay, keyCode, action, repeatCount},
1713                               .value.int64Values = {elapsedRealtimeNano()}};
1714     return value;
1715 }
1716 
1717 VehiclePropValue FakeVehicleHardware::createHwMotionInputProp(
1718         int32_t area, int32_t display, int32_t inputType, int32_t action, int32_t buttonState,
1719         int32_t pointerCount, int32_t pointerId[], int32_t toolType[], float xData[], float yData[],
1720         float pressure[], float size[]) {
1721     std::vector<int> intValues;
1722     intValues.push_back(display);
1723     intValues.push_back(inputType);
1724     intValues.push_back(action);
1725     intValues.push_back(buttonState);
1726     intValues.push_back(pointerCount);
1727     for (int i = 0; i < pointerCount; i++) {
1728         intValues.push_back(pointerId[i]);
1729     }
1730     for (int i = 0; i < pointerCount; i++) {
1731         intValues.push_back(toolType[i]);
1732     }
1733 
1734     std::vector<float> floatValues;
1735     for (int i = 0; i < pointerCount; i++) {
1736         floatValues.push_back(xData[i]);
1737     }
1738     for (int i = 0; i < pointerCount; i++) {
1739         floatValues.push_back(yData[i]);
1740     }
1741     for (int i = 0; i < pointerCount; i++) {
1742         floatValues.push_back(pressure[i]);
1743     }
1744     for (int i = 0; i < pointerCount; i++) {
1745         floatValues.push_back(size[i]);
1746     }
1747 
1748     VehiclePropValue value = {.timestamp = elapsedRealtimeNano(),
1749                               .areaId = area,
1750                               .prop = toInt(VehicleProperty::HW_MOTION_INPUT),
1751                               .status = VehiclePropertyStatus::AVAILABLE,
1752                               .value.int32Values = intValues,
1753                               .value.floatValues = floatValues,
1754                               .value.int64Values = {elapsedRealtimeNano()}};
1755     return value;
1756 }
1757 
1758 void FakeVehicleHardware::eventFromVehicleBus(const VehiclePropValue& value) {
1759     mServerSidePropStore->writeValue(mValuePool->obtain(value));
1760 }
1761 
1762 std::string FakeVehicleHardware::dumpSubscriptions() {
1763     std::scoped_lock<std::mutex> lockGuard(mLock);
1764     std::string result = "Subscriptions: \n";
1765     for (const auto& [interval, actionForInterval] : mActionByIntervalInNanos) {
1766         for (const auto& propIdAreaId : actionForInterval.propIdAreaIdsToRefresh) {
1767             const auto& refreshInfo = mRefreshInfoByPropIdAreaId[propIdAreaId];
1768             bool vur = (refreshInfo.eventMode == VehiclePropertyStore::EventMode::ON_VALUE_CHANGE);
1769             float sampleRateHz = 1'000'000'000. / refreshInfo.intervalInNanos;
1770             result += StringPrintf("Continuous{property: %s, areaId: %d, rate: %lf hz, vur: %b}\n",
1771                                    PROP_ID_TO_CSTR(propIdAreaId.propId), propIdAreaId.areaId,
1772                                    sampleRateHz, vur);
1773         }
1774     }
1775     for (const auto& propIdAreaId : mSubOnChangePropIdAreaIds) {
1776         result += StringPrintf("OnChange{property: %s, areaId: %d}\n",
1777                                PROP_ID_TO_CSTR(propIdAreaId.propId), propIdAreaId.areaId);
1778     }
1779     return result;
1780 }
1781 
dumpHelp()1782 std::string FakeVehicleHardware::dumpHelp() {
1783     return "Usage: \n\n"
1784            "[no args]: dumps (id and value) all supported properties \n"
1785            "--help: shows this help\n"
1786            "--list: lists the property IDs and their supported area IDs for all supported "
1787            "properties\n"
1788            "--get <PROP_ID_1> [PROP_ID_2] [PROP_ID_N]: dumps the value of specific properties. \n"
1789            "--getWithArg <PROP_ID> [ValueArguments]: gets the value for a specific property. "
1790            "The value arguments constructs a VehiclePropValue used in the getValue request. \n"
1791            "--set <PROP_ID> [ValueArguments]: sets the value of property PROP_ID, the value "
1792            "arguments constructs a VehiclePropValue used in the setValue request. \n"
1793            "--save-prop <PROP_ID> [-a AREA_ID]: saves the current value for PROP_ID, integration "
1794            "tests that modify prop value must call this before test and restore-prop after test. \n"
1795            "--restore-prop <PROP_ID> [-a AREA_ID]: restores a previously saved property value. \n"
1796            "--inject-event <PROP_ID> [ValueArguments]: inject a property update event from car\n\n"
1797            "ValueArguments are in the format of [-a OPTIONAL_AREA_ID] "
1798            "[-i INT_VALUE_1 [INT_VALUE_2 ...]] "
1799            "[-i64 INT64_VALUE_1 [INT64_VALUE_2 ...]] "
1800            "[-f FLOAT_VALUE_1 [FLOAT_VALUE_2 ...]] "
1801            "[-s STR_VALUE] "
1802            "[-b BYTES_VALUE].\n"
1803            "For example: to set property ID 0x1234, areaId 0x1 to int32 values: [1, 2, 3], "
1804            "use \"--set 0x1234 -a 0x1 -i 1 2 3\"\n"
1805            "Note that the string, bytes and area value can be set just once, while the other can"
1806            " have multiple values (so they're used in the respective array), "
1807            "BYTES_VALUE is in the form of 0xXXXX, e.g. 0xdeadbeef.\n" +
1808            genFakeDataHelp() + "Fake user HAL usage: \n" + mFakeUserHal->showDumpHelp();
1809 }
1810 
dumpAllProperties()1811 std::string FakeVehicleHardware::dumpAllProperties() {
1812     auto configs = mServerSidePropStore->getAllConfigs();
1813     if (configs.size() == 0) {
1814         return "no properties to dump\n";
1815     }
1816     std::string msg = StringPrintf("dumping %zu properties\n", configs.size());
1817     int rowNumber = 1;
1818     for (const VehiclePropConfig& config : configs) {
1819         msg += dumpOnePropertyByConfig(rowNumber++, config);
1820     }
1821     return msg;
1822 }
1823 
dumpOnePropertyByConfig(int rowNumber,const VehiclePropConfig & config)1824 std::string FakeVehicleHardware::dumpOnePropertyByConfig(int rowNumber,
1825                                                          const VehiclePropConfig& config) {
1826     size_t numberAreas = config.areaConfigs.size();
1827     std::string msg = "";
1828     if (numberAreas == 0) {
1829         msg += StringPrintf("%d: ", rowNumber);
1830         msg += dumpOnePropertyById(config.prop, /* areaId= */ 0);
1831         return msg;
1832     }
1833     for (size_t j = 0; j < numberAreas; ++j) {
1834         if (numberAreas > 1) {
1835             msg += StringPrintf("%d-%zu: ", rowNumber, j);
1836         } else {
1837             msg += StringPrintf("%d: ", rowNumber);
1838         }
1839         msg += dumpOnePropertyById(config.prop, config.areaConfigs[j].areaId);
1840     }
1841     return msg;
1842 }
1843 
dumpOnePropertyById(int32_t propId,int32_t areaId)1844 std::string FakeVehicleHardware::dumpOnePropertyById(int32_t propId, int32_t areaId) {
1845     VehiclePropValue value = {
1846             .areaId = areaId,
1847             .prop = propId,
1848             .value = {},
1849     };
1850     bool isSpecialValue = false;
1851     auto result = maybeGetSpecialValue(value, &isSpecialValue);
1852     if (!isSpecialValue) {
1853         result = mServerSidePropStore->readValue(value);
1854     }
1855     if (!result.ok()) {
1856         return StringPrintf("failed to read property value: %s, error: %s, code: %d\n",
1857                             PROP_ID_TO_CSTR(propId), getErrorMsg(result).c_str(),
1858                             getIntErrorCode(result));
1859 
1860     } else {
1861         return result.value()->toString() + "\n";
1862     }
1863 }
1864 
dumpListProperties()1865 std::string FakeVehicleHardware::dumpListProperties() {
1866     auto configs = mServerSidePropStore->getAllConfigs();
1867     if (configs.size() == 0) {
1868         return "no properties to list\n";
1869     }
1870     int rowNumber = 1;
1871     std::stringstream ss;
1872     ss << "listing " << configs.size() << " properties" << std::endl;
1873     for (const auto& config : configs) {
1874         std::vector<int32_t> areaIds;
1875         for (const auto& areaConfig : config.areaConfigs) {
1876             areaIds.push_back(areaConfig.areaId);
1877         }
1878         ss << rowNumber++ << ": " << PROP_ID_TO_CSTR(config.prop) << ", propID: " << std::showbase
1879            << std::hex << config.prop << std::noshowbase << std::dec
1880            << ", areaIDs: " << vecToStringOfHexValues(areaIds) << std::endl;
1881     }
1882     return ss.str();
1883 }
1884 
checkArgumentsSize(const std::vector<std::string> & options,size_t minSize)1885 Result<void> FakeVehicleHardware::checkArgumentsSize(const std::vector<std::string>& options,
1886                                                      size_t minSize) {
1887     size_t size = options.size();
1888     if (size >= minSize) {
1889         return {};
1890     }
1891     return Error() << StringPrintf("Invalid number of arguments: required at least %zu, got %zu\n",
1892                                    minSize, size);
1893 }
1894 
parsePropId(const std::vector<std::string> & options,size_t index)1895 Result<int32_t> FakeVehicleHardware::parsePropId(const std::vector<std::string>& options,
1896                                                  size_t index) {
1897     const std::string& propIdStr = options[index];
1898     auto result = stringToPropId(propIdStr);
1899     if (result.ok()) {
1900         return result;
1901     }
1902     return safelyParseInt<int32_t>(index, propIdStr);
1903 }
1904 
dumpSpecificProperty(const std::vector<std::string> & options)1905 std::string FakeVehicleHardware::dumpSpecificProperty(const std::vector<std::string>& options) {
1906     if (auto result = checkArgumentsSize(options, /*minSize=*/2); !result.ok()) {
1907         return getErrorMsg(result);
1908     }
1909 
1910     // options[0] is the command itself...
1911     int rowNumber = 1;
1912     size_t size = options.size();
1913     std::string msg = "";
1914     for (size_t i = 1; i < size; ++i) {
1915         auto propResult = parsePropId(options, i);
1916         if (!propResult.ok()) {
1917             msg += getErrorMsg(propResult);
1918             continue;
1919         }
1920         int32_t prop = propResult.value();
1921         auto result = mServerSidePropStore->getPropConfig(prop);
1922         if (!result.ok()) {
1923             msg += StringPrintf("No property %s\n", PROP_ID_TO_CSTR(prop));
1924             continue;
1925         }
1926         msg += dumpOnePropertyByConfig(rowNumber++, result.value());
1927     }
1928     return msg;
1929 }
1930 
getOptionValues(const std::vector<std::string> & options,size_t * index)1931 std::vector<std::string> FakeVehicleHardware::getOptionValues(
1932         const std::vector<std::string>& options, size_t* index) {
1933     std::vector<std::string> values;
1934     while (*index < options.size()) {
1935         std::string option = options[*index];
1936         if (SET_PROP_OPTIONS.find(option) != SET_PROP_OPTIONS.end()) {
1937             return values;
1938         }
1939         values.push_back(option);
1940         (*index)++;
1941     }
1942     return values;
1943 }
1944 
parsePropOptions(const std::vector<std::string> & options)1945 Result<VehiclePropValue> FakeVehicleHardware::parsePropOptions(
1946         const std::vector<std::string>& options) {
1947     // Options format:
1948     // --set/get/inject-event PROP [-f f1 f2...] [-i i1 i2...] [-i64 i1 i2...] [-s s1 s2...]
1949     // [-b b1 b2...] [-a a] [-t timestamp]
1950     size_t optionIndex = 1;
1951     auto result = parsePropId(options, optionIndex);
1952     if (!result.ok()) {
1953         return Error() << StringPrintf("Property ID/Name: \"%s\" is not valid: %s\n",
1954                                        options[optionIndex].c_str(), getErrorMsg(result).c_str());
1955     }
1956     VehiclePropValue prop = {};
1957     prop.prop = result.value();
1958     prop.status = VehiclePropertyStatus::AVAILABLE;
1959     optionIndex++;
1960     std::unordered_set<std::string> parsedOptions;
1961 
1962     while (optionIndex < options.size()) {
1963         std::string argType = options[optionIndex];
1964         optionIndex++;
1965 
1966         size_t currentIndex = optionIndex;
1967         std::vector<std::string> argValues = getOptionValues(options, &optionIndex);
1968         if (parsedOptions.find(argType) != parsedOptions.end()) {
1969             return Error() << StringPrintf("Duplicate \"%s\" options\n", argType.c_str());
1970         }
1971         parsedOptions.insert(argType);
1972         size_t argValuesSize = argValues.size();
1973         if (EqualsIgnoreCase(argType, "-i")) {
1974             if (argValuesSize == 0) {
1975                 return Error() << "No values specified when using \"-i\"\n";
1976             }
1977             prop.value.int32Values.resize(argValuesSize);
1978             for (size_t i = 0; i < argValuesSize; i++) {
1979                 auto int32Result = safelyParseInt<int32_t>(currentIndex + i, argValues[i]);
1980                 if (!int32Result.ok()) {
1981                     return Error()
1982                            << StringPrintf("Value: \"%s\" is not a valid int: %s\n",
1983                                            argValues[i].c_str(), getErrorMsg(int32Result).c_str());
1984                 }
1985                 prop.value.int32Values[i] = int32Result.value();
1986             }
1987         } else if (EqualsIgnoreCase(argType, "-i64")) {
1988             if (argValuesSize == 0) {
1989                 return Error() << "No values specified when using \"-i64\"\n";
1990             }
1991             prop.value.int64Values.resize(argValuesSize);
1992             for (size_t i = 0; i < argValuesSize; i++) {
1993                 auto int64Result = safelyParseInt<int64_t>(currentIndex + i, argValues[i]);
1994                 if (!int64Result.ok()) {
1995                     return Error()
1996                            << StringPrintf("Value: \"%s\" is not a valid int64: %s\n",
1997                                            argValues[i].c_str(), getErrorMsg(int64Result).c_str());
1998                 }
1999                 prop.value.int64Values[i] = int64Result.value();
2000             }
2001         } else if (EqualsIgnoreCase(argType, "-f")) {
2002             if (argValuesSize == 0) {
2003                 return Error() << "No values specified when using \"-f\"\n";
2004             }
2005             prop.value.floatValues.resize(argValuesSize);
2006             for (size_t i = 0; i < argValuesSize; i++) {
2007                 auto floatResult = safelyParseFloat(currentIndex + i, argValues[i]);
2008                 if (!floatResult.ok()) {
2009                     return Error()
2010                            << StringPrintf("Value: \"%s\" is not a valid float: %s\n",
2011                                            argValues[i].c_str(), getErrorMsg(floatResult).c_str());
2012                 }
2013                 prop.value.floatValues[i] = floatResult.value();
2014             }
2015         } else if (EqualsIgnoreCase(argType, "-s")) {
2016             if (argValuesSize != 1) {
2017                 return Error() << "Expect exact one value when using \"-s\"\n";
2018             }
2019             prop.value.stringValue = argValues[0];
2020         } else if (EqualsIgnoreCase(argType, "-b")) {
2021             if (argValuesSize != 1) {
2022                 return Error() << "Expect exact one value when using \"-b\"\n";
2023             }
2024             auto bytesResult = parseHexString(argValues[0]);
2025             if (!bytesResult.ok()) {
2026                 return Error() << StringPrintf("value: \"%s\" is not a valid hex string: %s\n",
2027                                                argValues[0].c_str(),
2028                                                getErrorMsg(bytesResult).c_str());
2029             }
2030             prop.value.byteValues = std::move(bytesResult.value());
2031         } else if (EqualsIgnoreCase(argType, "-a")) {
2032             if (argValuesSize != 1) {
2033                 return Error() << "Expect exact one value when using \"-a\"\n";
2034             }
2035             auto int32Result = safelyParseInt<int32_t>(currentIndex, argValues[0]);
2036             if (!int32Result.ok()) {
2037                 return Error() << StringPrintf("Area ID: \"%s\" is not a valid int: %s\n",
2038                                                argValues[0].c_str(),
2039                                                getErrorMsg(int32Result).c_str());
2040             }
2041             prop.areaId = int32Result.value();
2042         } else if (EqualsIgnoreCase(argType, "-t")) {
2043             if (argValuesSize != 1) {
2044                 return Error() << "Expect exact one value when using \"-t\"\n";
2045             }
2046             auto int64Result = safelyParseInt<int64_t>(currentIndex, argValues[0]);
2047             if (!int64Result.ok()) {
2048                 return Error() << StringPrintf("Timestamp: \"%s\" is not a valid int64: %s\n",
2049                                                argValues[0].c_str(),
2050                                                getErrorMsg(int64Result).c_str());
2051             }
2052             prop.timestamp = int64Result.value();
2053         } else {
2054             return Error() << StringPrintf("Unknown option: %s\n", argType.c_str());
2055         }
2056     }
2057 
2058     return prop;
2059 }
2060 
dumpSetProperties(const std::vector<std::string> & options)2061 std::string FakeVehicleHardware::dumpSetProperties(const std::vector<std::string>& options) {
2062     if (auto result = checkArgumentsSize(options, 3); !result.ok()) {
2063         return getErrorMsg(result);
2064     }
2065 
2066     auto parseResult = parsePropOptions(options);
2067     if (!parseResult.ok()) {
2068         return getErrorMsg(parseResult);
2069     }
2070     VehiclePropValue prop = std::move(parseResult.value());
2071     ALOGD("Dump: Setting property: %s", prop.toString().c_str());
2072 
2073     bool isSpecialValue = false;
2074     auto setResult = maybeSetSpecialValue(prop, &isSpecialValue);
2075 
2076     if (!isSpecialValue) {
2077         auto updatedValue = mValuePool->obtain(prop);
2078         updatedValue->timestamp = elapsedRealtimeNano();
2079         setResult = mServerSidePropStore->writeValue(std::move(updatedValue));
2080     }
2081 
2082     if (setResult.ok()) {
2083         return StringPrintf("Set property: %s\n", prop.toString().c_str());
2084     }
2085     return StringPrintf("failed to set property: %s, error: %s\n", prop.toString().c_str(),
2086                         getErrorMsg(setResult).c_str());
2087 }
2088 
dumpGetPropertyWithArg(const std::vector<std::string> & options)2089 std::string FakeVehicleHardware::dumpGetPropertyWithArg(const std::vector<std::string>& options) {
2090     if (auto result = checkArgumentsSize(options, 3); !result.ok()) {
2091         return getErrorMsg(result);
2092     }
2093 
2094     auto parseResult = parsePropOptions(options);
2095     if (!parseResult.ok()) {
2096         return getErrorMsg(parseResult);
2097     }
2098     VehiclePropValue prop = std::move(parseResult.value());
2099     ALOGD("Dump: Getting property: %s", prop.toString().c_str());
2100 
2101     bool isSpecialValue = false;
2102     auto result = maybeGetSpecialValue(prop, &isSpecialValue);
2103 
2104     if (!isSpecialValue) {
2105         result = mServerSidePropStore->readValue(prop);
2106     }
2107 
2108     if (!result.ok()) {
2109         return StringPrintf("failed to read property value: %s, error: %s, code: %d\n",
2110                             PROP_ID_TO_CSTR(prop.prop), getErrorMsg(result).c_str(),
2111                             getIntErrorCode(result));
2112     }
2113     return StringPrintf("Get property result: %s\n", result.value()->toString().c_str());
2114 }
2115 
dumpSaveProperty(const std::vector<std::string> & options)2116 std::string FakeVehicleHardware::dumpSaveProperty(const std::vector<std::string>& options) {
2117     // Format: --save-prop PROP [-a areaID]
2118     if (auto result = checkArgumentsSize(options, 2); !result.ok()) {
2119         return getErrorMsg(result);
2120     }
2121 
2122     auto parseResult = parsePropOptions(options);
2123     if (!parseResult.ok()) {
2124         return getErrorMsg(parseResult);
2125     }
2126     // We are only using the prop and areaId option.
2127     VehiclePropValue value = std::move(parseResult.value());
2128     int32_t propId = value.prop;
2129     int32_t areaId = value.areaId;
2130 
2131     auto readResult = mServerSidePropStore->readValue(value);
2132     if (!readResult.ok()) {
2133         return StringPrintf("Failed to save current property value, error: %s",
2134                             getErrorMsg(readResult).c_str());
2135     }
2136 
2137     std::scoped_lock<std::mutex> lockGuard(mLock);
2138     mSavedProps[PropIdAreaId{
2139             .propId = propId,
2140             .areaId = areaId,
2141     }] = std::move(readResult.value());
2142 
2143     return StringPrintf("Property: %" PRId32 ", areaID: %" PRId32 " saved", propId, areaId);
2144 }
2145 
dumpRestoreProperty(const std::vector<std::string> & options)2146 std::string FakeVehicleHardware::dumpRestoreProperty(const std::vector<std::string>& options) {
2147     // Format: --restore-prop PROP [-a areaID]
2148     if (auto result = checkArgumentsSize(options, 2); !result.ok()) {
2149         return getErrorMsg(result);
2150     }
2151 
2152     auto parseResult = parsePropOptions(options);
2153     if (!parseResult.ok()) {
2154         return getErrorMsg(parseResult);
2155     }
2156     // We are only using the prop and areaId option.
2157     VehiclePropValue value = std::move(parseResult.value());
2158     int32_t propId = value.prop;
2159     int32_t areaId = value.areaId;
2160     VehiclePropValuePool::RecyclableType savedValue;
2161 
2162     {
2163         std::scoped_lock<std::mutex> lockGuard(mLock);
2164         auto it = mSavedProps.find(PropIdAreaId{
2165                 .propId = propId,
2166                 .areaId = areaId,
2167         });
2168         if (it == mSavedProps.end()) {
2169             return StringPrintf("No saved property for property: %" PRId32 ", areaID: %" PRId32,
2170                                 propId, areaId);
2171         }
2172 
2173         savedValue = std::move(it->second);
2174         // Remove the saved property after restoring it.
2175         mSavedProps.erase(it);
2176     }
2177 
2178     // Update timestamp.
2179     savedValue->timestamp = elapsedRealtimeNano();
2180 
2181     auto writeResult = mServerSidePropStore->writeValue(std::move(savedValue));
2182     if (!writeResult.ok()) {
2183         return StringPrintf("Failed to restore property value, error: %s",
2184                             getErrorMsg(writeResult).c_str());
2185     }
2186 
2187     return StringPrintf("Property: %" PRId32 ", areaID: %" PRId32 " restored", propId, areaId);
2188 }
2189 
dumpInjectEvent(const std::vector<std::string> & options)2190 std::string FakeVehicleHardware::dumpInjectEvent(const std::vector<std::string>& options) {
2191     if (auto result = checkArgumentsSize(options, 3); !result.ok()) {
2192         return getErrorMsg(result);
2193     }
2194 
2195     auto parseResult = parsePropOptions(options);
2196     if (!parseResult.ok()) {
2197         return getErrorMsg(parseResult);
2198     }
2199     VehiclePropValue prop = std::move(parseResult.value());
2200     ALOGD("Dump: Injecting event from vehicle bus: %s", prop.toString().c_str());
2201 
2202     eventFromVehicleBus(prop);
2203 
2204     return StringPrintf("Event for property: %s injected", PROP_ID_TO_CSTR(prop.prop));
2205 }
2206 
checkHealth()2207 StatusCode FakeVehicleHardware::checkHealth() {
2208     // Always return OK for checkHealth.
2209     return StatusCode::OK;
2210 }
2211 
registerOnPropertyChangeEvent(std::unique_ptr<const PropertyChangeCallback> callback)2212 void FakeVehicleHardware::registerOnPropertyChangeEvent(
2213         std::unique_ptr<const PropertyChangeCallback> callback) {
2214     if (mOnPropertyChangeCallback != nullptr) {
2215         ALOGE("registerOnPropertyChangeEvent must only be called once");
2216         return;
2217     }
2218     mOnPropertyChangeCallback = std::move(callback);
2219 }
2220 
registerOnPropertySetErrorEvent(std::unique_ptr<const PropertySetErrorCallback> callback)2221 void FakeVehicleHardware::registerOnPropertySetErrorEvent(
2222         std::unique_ptr<const PropertySetErrorCallback> callback) {
2223     // In FakeVehicleHardware, we will never use mOnPropertySetErrorCallback.
2224     if (mOnPropertySetErrorCallback != nullptr) {
2225         ALOGE("registerOnPropertySetErrorEvent must only be called once");
2226         return;
2227     }
2228     mOnPropertySetErrorCallback = std::move(callback);
2229 }
2230 
subscribe(SubscribeOptions options)2231 StatusCode FakeVehicleHardware::subscribe(SubscribeOptions options) {
2232     int32_t propId = options.propId;
2233 
2234     auto configResult = mServerSidePropStore->getPropConfig(propId);
2235     if (!configResult.ok()) {
2236         ALOGE("subscribe: property: %" PRId32 " is not supported", propId);
2237         return StatusCode::INVALID_ARG;
2238     }
2239 
2240     std::scoped_lock<std::mutex> lockGuard(mLock);
2241     for (int areaId : options.areaIds) {
2242         if (StatusCode status = subscribePropIdAreaIdLocked(propId, areaId, options.sampleRate,
2243                                                             options.enableVariableUpdateRate,
2244                                                             configResult.value());
2245             status != StatusCode::OK) {
2246             return status;
2247         }
2248     }
2249     return StatusCode::OK;
2250 }
2251 
isVariableUpdateRateSupported(const VehiclePropConfig & vehiclePropConfig,int32_t areaId)2252 bool FakeVehicleHardware::isVariableUpdateRateSupported(const VehiclePropConfig& vehiclePropConfig,
2253                                                         int32_t areaId) {
2254     for (size_t i = 0; i < vehiclePropConfig.areaConfigs.size(); i++) {
2255         const auto& areaConfig = vehiclePropConfig.areaConfigs[i];
2256         if (areaConfig.areaId != areaId) {
2257             continue;
2258         }
2259         if (areaConfig.supportVariableUpdateRate) {
2260             return true;
2261         }
2262         break;
2263     }
2264     return false;
2265 }
2266 
refreshTimestampForInterval(int64_t intervalInNanos)2267 void FakeVehicleHardware::refreshTimestampForInterval(int64_t intervalInNanos) {
2268     std::unordered_map<PropIdAreaId, VehiclePropertyStore::EventMode, PropIdAreaIdHash>
2269             eventModeByPropIdAreaId;
2270 
2271     {
2272         std::scoped_lock<std::mutex> lockGuard(mLock);
2273 
2274         if (mActionByIntervalInNanos.find(intervalInNanos) == mActionByIntervalInNanos.end()) {
2275             ALOGE("No actions scheduled for the interval: %" PRId64 ", ignore the refresh request",
2276                   intervalInNanos);
2277             return;
2278         }
2279 
2280         ActionForInterval actionForInterval = mActionByIntervalInNanos[intervalInNanos];
2281 
2282         // Make a copy so that we don't hold the lock while trying to refresh the timestamp.
2283         // Refreshing the timestamp will inovke onValueChangeCallback which also requires lock, so
2284         // we must not hold lock.
2285         for (const PropIdAreaId& propIdAreaId : actionForInterval.propIdAreaIdsToRefresh) {
2286             const RefreshInfo& refreshInfo = mRefreshInfoByPropIdAreaId[propIdAreaId];
2287             eventModeByPropIdAreaId[propIdAreaId] = refreshInfo.eventMode;
2288         }
2289     }
2290 
2291     mServerSidePropStore->refreshTimestamps(eventModeByPropIdAreaId);
2292 }
2293 
registerRefreshLocked(PropIdAreaId propIdAreaId,VehiclePropertyStore::EventMode eventMode,float sampleRateHz)2294 void FakeVehicleHardware::registerRefreshLocked(PropIdAreaId propIdAreaId,
2295                                                 VehiclePropertyStore::EventMode eventMode,
2296                                                 float sampleRateHz) {
2297     if (mRefreshInfoByPropIdAreaId.find(propIdAreaId) != mRefreshInfoByPropIdAreaId.end()) {
2298         unregisterRefreshLocked(propIdAreaId);
2299     }
2300 
2301     int64_t intervalInNanos = static_cast<int64_t>(1'000'000'000. / sampleRateHz);
2302     RefreshInfo refreshInfo = {
2303             .eventMode = eventMode,
2304             .intervalInNanos = intervalInNanos,
2305     };
2306     mRefreshInfoByPropIdAreaId[propIdAreaId] = refreshInfo;
2307 
2308     if (mActionByIntervalInNanos.find(intervalInNanos) != mActionByIntervalInNanos.end()) {
2309         // If we have already registered for this interval, then add the action info to the
2310         // actions list.
2311         mActionByIntervalInNanos[intervalInNanos].propIdAreaIdsToRefresh.insert(propIdAreaId);
2312         return;
2313     }
2314 
2315     // This is the first action for the interval, register a timer callback for that interval.
2316     auto action = std::make_shared<RecurrentTimer::Callback>(
2317             [this, intervalInNanos] { refreshTimestampForInterval(intervalInNanos); });
2318     mActionByIntervalInNanos[intervalInNanos] = ActionForInterval{
2319             .propIdAreaIdsToRefresh = {propIdAreaId},
2320             .recurrentAction = action,
2321     };
2322     mRecurrentTimer->registerTimerCallback(intervalInNanos, action);
2323 }
2324 
unregisterRefreshLocked(PropIdAreaId propIdAreaId)2325 void FakeVehicleHardware::unregisterRefreshLocked(PropIdAreaId propIdAreaId) {
2326     if (mRefreshInfoByPropIdAreaId.find(propIdAreaId) == mRefreshInfoByPropIdAreaId.end()) {
2327         ALOGW("PropId: %" PRId32 ", areaId: %" PRId32 " was not registered for refresh, ignore",
2328               propIdAreaId.propId, propIdAreaId.areaId);
2329         return;
2330     }
2331 
2332     int64_t intervalInNanos = mRefreshInfoByPropIdAreaId[propIdAreaId].intervalInNanos;
2333     auto& actionForInterval = mActionByIntervalInNanos[intervalInNanos];
2334     actionForInterval.propIdAreaIdsToRefresh.erase(propIdAreaId);
2335     if (actionForInterval.propIdAreaIdsToRefresh.empty()) {
2336         mRecurrentTimer->unregisterTimerCallback(actionForInterval.recurrentAction);
2337         mActionByIntervalInNanos.erase(intervalInNanos);
2338     }
2339     mRefreshInfoByPropIdAreaId.erase(propIdAreaId);
2340 }
2341 
subscribePropIdAreaIdLocked(int32_t propId,int32_t areaId,float sampleRateHz,bool enableVariableUpdateRate,const VehiclePropConfig & vehiclePropConfig)2342 StatusCode FakeVehicleHardware::subscribePropIdAreaIdLocked(
2343         int32_t propId, int32_t areaId, float sampleRateHz, bool enableVariableUpdateRate,
2344         const VehiclePropConfig& vehiclePropConfig) {
2345     PropIdAreaId propIdAreaId{
2346             .propId = propId,
2347             .areaId = areaId,
2348     };
2349     switch (vehiclePropConfig.changeMode) {
2350         case VehiclePropertyChangeMode::STATIC:
2351             ALOGW("subscribe to a static property, do nothing.");
2352             return StatusCode::OK;
2353         case VehiclePropertyChangeMode::ON_CHANGE:
2354             mSubOnChangePropIdAreaIds.insert(std::move(propIdAreaId));
2355             return StatusCode::OK;
2356         case VehiclePropertyChangeMode::CONTINUOUS:
2357             if (sampleRateHz == 0.f) {
2358                 ALOGE("Must not use sample rate 0 for a continuous property");
2359                 return StatusCode::INVALID_ARG;
2360             }
2361             // For continuous properties, we must generate a new onPropertyChange event
2362             // periodically according to the sample rate.
2363             auto eventMode = VehiclePropertyStore::EventMode::ALWAYS;
2364             if (isVariableUpdateRateSupported(vehiclePropConfig, areaId) &&
2365                 enableVariableUpdateRate) {
2366                 eventMode = VehiclePropertyStore::EventMode::ON_VALUE_CHANGE;
2367             }
2368 
2369             registerRefreshLocked(propIdAreaId, eventMode, sampleRateHz);
2370             return StatusCode::OK;
2371     }
2372 }
2373 
unsubscribe(int32_t propId,int32_t areaId)2374 StatusCode FakeVehicleHardware::unsubscribe(int32_t propId, int32_t areaId) {
2375     std::scoped_lock<std::mutex> lockGuard(mLock);
2376     PropIdAreaId propIdAreaId{
2377             .propId = propId,
2378             .areaId = areaId,
2379     };
2380     if (mRefreshInfoByPropIdAreaId.find(propIdAreaId) != mRefreshInfoByPropIdAreaId.end()) {
2381         unregisterRefreshLocked(propIdAreaId);
2382     }
2383     mSubOnChangePropIdAreaIds.erase(propIdAreaId);
2384     return StatusCode::OK;
2385 }
2386 
onValueChangeCallback(const VehiclePropValue & value)2387 void FakeVehicleHardware::onValueChangeCallback(const VehiclePropValue& value) {
2388     ATRACE_CALL();
2389     onValuesChangeCallback({value});
2390 }
2391 
onValuesChangeCallback(std::vector<VehiclePropValue> values)2392 void FakeVehicleHardware::onValuesChangeCallback(std::vector<VehiclePropValue> values) {
2393     ATRACE_CALL();
2394     std::vector<VehiclePropValue> subscribedUpdatedValues;
2395 
2396     {
2397         std::scoped_lock<std::mutex> lockGuard(mLock);
2398         if (mOnPropertyChangeCallback == nullptr) {
2399             return;
2400         }
2401 
2402         for (const auto& value : values) {
2403             PropIdAreaId propIdAreaId{
2404                     .propId = value.prop,
2405                     .areaId = value.areaId,
2406             };
2407             if (mRefreshInfoByPropIdAreaId.find(propIdAreaId) == mRefreshInfoByPropIdAreaId.end() &&
2408                 mSubOnChangePropIdAreaIds.find(propIdAreaId) == mSubOnChangePropIdAreaIds.end()) {
2409                 if (FAKE_VEHICLEHARDWARE_DEBUG) {
2410                     ALOGD("The updated property value: %s is not subscribed, ignore",
2411                           value.toString().c_str());
2412                 }
2413                 continue;
2414             }
2415 
2416             subscribedUpdatedValues.push_back(value);
2417         }
2418     }
2419 
2420     (*mOnPropertyChangeCallback)(std::move(subscribedUpdatedValues));
2421 }
2422 
loadPropConfigsFromDir(const std::string & dirPath,std::unordered_map<int32_t,ConfigDeclaration> * configsByPropId)2423 bool FakeVehicleHardware::loadPropConfigsFromDir(
2424         const std::string& dirPath,
2425         std::unordered_map<int32_t, ConfigDeclaration>* configsByPropId) {
2426     ALOGI("loading properties from %s", dirPath.c_str());
2427     auto dir = opendir(dirPath.c_str());
2428     if (dir == nullptr) {
2429         ALOGE("Failed to open config directory: %s", dirPath.c_str());
2430         return false;
2431     }
2432 
2433     std::regex regJson(".*[.]json", std::regex::icase);
2434     while (auto f = readdir(dir)) {
2435         if (!std::regex_match(f->d_name, regJson)) {
2436             continue;
2437         }
2438         std::string filePath = dirPath + "/" + std::string(f->d_name);
2439         ALOGI("loading properties from %s", filePath.c_str());
2440         auto result = mLoader.loadPropConfig(filePath);
2441         if (!result.ok()) {
2442             ALOGE("failed to load config file: %s, error: %s", filePath.c_str(),
2443                   result.error().message().c_str());
2444             continue;
2445         }
2446         for (auto& [propId, configDeclaration] : result.value()) {
2447             (*configsByPropId)[propId] = std::move(configDeclaration);
2448         }
2449     }
2450     closedir(dir);
2451     return true;
2452 }
2453 
safelyParseFloat(int index,const std::string & s)2454 Result<float> FakeVehicleHardware::safelyParseFloat(int index, const std::string& s) {
2455     float out;
2456     if (!ParseFloat(s, &out)) {
2457         return Error() << StringPrintf("non-float argument at index %d: %s\n", index, s.c_str());
2458     }
2459     return out;
2460 }
2461 
parseHexString(const std::string & s)2462 Result<std::vector<uint8_t>> FakeVehicleHardware::parseHexString(const std::string& s) {
2463     std::vector<uint8_t> bytes;
2464     if (s.size() % 2 != 0) {
2465         return Error() << StringPrintf("invalid hex string: %s, should have even size\n",
2466                                        s.c_str());
2467     }
2468     if (!StartsWith(s, "0x")) {
2469         return Error() << StringPrintf("hex string should start with \"0x\", got %s\n", s.c_str());
2470     }
2471     std::string subs = s.substr(2);
2472     std::transform(subs.begin(), subs.end(), subs.begin(),
2473                    [](unsigned char c) { return std::tolower(c); });
2474 
2475     bool highDigit = true;
2476     for (size_t i = 0; i < subs.size(); i++) {
2477         char c = subs[i];
2478         uint8_t v;
2479         if (c >= '0' && c <= '9') {
2480             v = c - '0';
2481         } else if (c >= 'a' && c <= 'f') {
2482             v = c - 'a' + 10;
2483         } else {
2484             return Error() << StringPrintf("invalid character %c in hex string %s\n", c,
2485                                            subs.c_str());
2486         }
2487         if (highDigit) {
2488             bytes.push_back(v * 16);
2489         } else {
2490             bytes[bytes.size() - 1] += v;
2491         }
2492         highDigit = !highDigit;
2493     }
2494     return bytes;
2495 }
2496 
2497 template <class CallbackType, class RequestType>
PendingRequestHandler(FakeVehicleHardware * hardware)2498 FakeVehicleHardware::PendingRequestHandler<CallbackType, RequestType>::PendingRequestHandler(
2499         FakeVehicleHardware* hardware)
2500     : mHardware(hardware) {
2501     // Don't initialize mThread in initialization list because mThread depends on mRequests and we
2502     // want mRequests to be initialized first.
2503     mThread = std::thread([this] {
2504         while (mRequests.waitForItems()) {
2505             handleRequestsOnce();
2506         }
2507     });
2508 }
2509 
2510 template <class CallbackType, class RequestType>
addRequest(RequestType request,std::shared_ptr<const CallbackType> callback)2511 void FakeVehicleHardware::PendingRequestHandler<CallbackType, RequestType>::addRequest(
2512         RequestType request, std::shared_ptr<const CallbackType> callback) {
2513     mRequests.push({
2514             request,
2515             callback,
2516     });
2517 }
2518 
2519 template <class CallbackType, class RequestType>
stop()2520 void FakeVehicleHardware::PendingRequestHandler<CallbackType, RequestType>::stop() {
2521     mRequests.deactivate();
2522     if (mThread.joinable()) {
2523         mThread.join();
2524     }
2525 }
2526 
2527 template <>
2528 void FakeVehicleHardware::PendingRequestHandler<FakeVehicleHardware::GetValuesCallback,
handleRequestsOnce()2529                                                 GetValueRequest>::handleRequestsOnce() {
2530     std::unordered_map<std::shared_ptr<const GetValuesCallback>, std::vector<GetValueResult>>
2531             callbackToResults;
2532     for (const auto& rwc : mRequests.flush()) {
2533         ATRACE_BEGIN("FakeVehicleHardware:handleGetValueRequest");
2534         auto result = mHardware->handleGetValueRequest(rwc.request);
2535         ATRACE_END();
2536         callbackToResults[rwc.callback].push_back(std::move(result));
2537     }
2538     for (const auto& [callback, results] : callbackToResults) {
2539         ATRACE_BEGIN("FakeVehicleHardware:call get value result callback");
2540         (*callback)(std::move(results));
2541         ATRACE_END();
2542     }
2543 }
2544 
2545 template <>
2546 void FakeVehicleHardware::PendingRequestHandler<FakeVehicleHardware::SetValuesCallback,
handleRequestsOnce()2547                                                 SetValueRequest>::handleRequestsOnce() {
2548     std::unordered_map<std::shared_ptr<const SetValuesCallback>, std::vector<SetValueResult>>
2549             callbackToResults;
2550     for (const auto& rwc : mRequests.flush()) {
2551         ATRACE_BEGIN("FakeVehicleHardware:handleSetValueRequest");
2552         auto result = mHardware->handleSetValueRequest(rwc.request);
2553         ATRACE_END();
2554         callbackToResults[rwc.callback].push_back(std::move(result));
2555     }
2556     for (const auto& [callback, results] : callbackToResults) {
2557         ATRACE_BEGIN("FakeVehicleHardware:call set value result callback");
2558         (*callback)(std::move(results));
2559         ATRACE_END();
2560     }
2561 }
2562 
2563 }  // namespace fake
2564 }  // namespace vehicle
2565 }  // namespace automotive
2566 }  // namespace hardware
2567 }  // namespace android
2568