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 #include <FakeVehicleHardware.h>
18 
19 #include <FakeObd2Frame.h>
20 #include <FakeUserHal.h>
21 #include <PropertyUtils.h>
22 
23 #include <aidl/android/hardware/automotive/vehicle/VehicleApPowerStateShutdownParam.h>
24 #include <android/hardware/automotive/vehicle/TestVendorProperty.h>
25 
26 #include <android-base/expected.h>
27 #include <android-base/file.h>
28 #include <android-base/stringprintf.h>
29 #include <android-base/thread_annotations.h>
30 #include <gmock/gmock.h>
31 #include <gtest/gtest.h>
32 #include <utils/Log.h>
33 #include <utils/SystemClock.h>
34 
35 #include <inttypes.h>
36 #include <chrono>
37 #include <condition_variable>
38 #include <memory>
39 #include <unordered_map>
40 #include <unordered_set>
41 #include <vector>
42 
43 namespace aidl {
44 namespace android {
45 namespace hardware {
46 namespace automotive {
47 namespace vehicle {
48 
PrintTo(const VehiclePropValue & value,std::ostream * os)49 void PrintTo(const VehiclePropValue& value, std::ostream* os) {
50     *os << "\n( " << value.toString() << " )\n";
51 }
52 
53 }  // namespace vehicle
54 }  // namespace automotive
55 }  // namespace hardware
56 }  // namespace android
57 }  // namespace aidl
58 
59 namespace android {
60 namespace hardware {
61 namespace automotive {
62 namespace vehicle {
63 namespace fake {
64 namespace {
65 
66 using ::aidl::android::hardware::automotive::vehicle::CruiseControlCommand;
67 using ::aidl::android::hardware::automotive::vehicle::CruiseControlType;
68 using ::aidl::android::hardware::automotive::vehicle::ErrorState;
69 using ::aidl::android::hardware::automotive::vehicle::GetValueRequest;
70 using ::aidl::android::hardware::automotive::vehicle::GetValueResult;
71 using ::aidl::android::hardware::automotive::vehicle::RawPropValues;
72 using ::aidl::android::hardware::automotive::vehicle::SetValueRequest;
73 using ::aidl::android::hardware::automotive::vehicle::SetValueResult;
74 using ::aidl::android::hardware::automotive::vehicle::StatusCode;
75 using ::aidl::android::hardware::automotive::vehicle::SubscribeOptions;
76 using ::aidl::android::hardware::automotive::vehicle::VehicleApPowerStateReport;
77 using ::aidl::android::hardware::automotive::vehicle::VehicleApPowerStateReq;
78 using ::aidl::android::hardware::automotive::vehicle::VehicleApPowerStateShutdownParam;
79 using ::aidl::android::hardware::automotive::vehicle::VehicleAreaMirror;
80 using ::aidl::android::hardware::automotive::vehicle::VehicleHwKeyInputAction;
81 using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig;
82 using ::aidl::android::hardware::automotive::vehicle::VehicleProperty;
83 using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyAccess;
84 using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyStatus;
85 using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType;
86 using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
87 using ::aidl::android::hardware::automotive::vehicle::VehicleUnit;
88 using ::android::base::expected;
89 using ::android::base::ScopedLockAssertion;
90 using ::android::base::StringPrintf;
91 using ::android::base::unexpected;
92 using ::testing::AnyOfArray;
93 using ::testing::ContainerEq;
94 using ::testing::ContainsRegex;
95 using ::testing::Eq;
96 using ::testing::HasSubstr;
97 using ::testing::IsSubsetOf;
98 using ::testing::UnorderedElementsAre;
99 using ::testing::WhenSortedBy;
100 
101 using std::chrono::milliseconds;
102 
103 constexpr int INVALID_PROP_ID = 0;
104 constexpr char CAR_MAKE[] = "Default Car";
105 
106 }  // namespace
107 
108 // A helper class to access private methods for FakeVehicleHardware.
109 class FakeVehicleHardwareTestHelper {
110   public:
FakeVehicleHardwareTestHelper(FakeVehicleHardware * hardware)111     FakeVehicleHardwareTestHelper(FakeVehicleHardware* hardware) { mHardware = hardware; }
112 
loadConfigDeclarations()113     std::unordered_map<int32_t, ConfigDeclaration> loadConfigDeclarations() {
114         return mHardware->loadConfigDeclarations();
115     }
116 
getHvacPowerDependentProps()117     std::unordered_set<int32_t> getHvacPowerDependentProps() {
118         return mHardware->hvacPowerDependentProps;
119     }
120 
121   private:
122     FakeVehicleHardware* mHardware;
123 };
124 
125 class FakeVehicleHardwareTest : public ::testing::Test {
126   protected:
SetUp()127     void SetUp() override {
128         mHardware = std::make_unique<FakeVehicleHardware>(android::base::GetExecutableDirectory(),
129                                                           /*overrideConfigDir=*/"",
130                                                           /*forceOverride=*/false);
131         auto callback = std::make_unique<IVehicleHardware::PropertyChangeCallback>(
132                 [this](const std::vector<VehiclePropValue>& values) {
133                     onPropertyChangeEvent(values);
134                 });
135         getHardware()->registerOnPropertyChangeEvent(std::move(callback));
136         mSetValuesCallback = std::make_shared<IVehicleHardware::SetValuesCallback>(
137                 [this](std::vector<SetValueResult> results) { onSetValues(results); });
138         mGetValuesCallback = std::make_shared<IVehicleHardware::GetValuesCallback>(
139                 [this](std::vector<GetValueResult> results) { onGetValues(results); });
140     }
141 
TearDown()142     void TearDown() override {
143         // mHardware uses callback which contains reference to 'this', so it has to be destroyed
144         // before 'this'.
145         mHardware.reset();
146     }
147 
getHardware()148     FakeVehicleHardware* getHardware() { return mHardware.get(); }
149 
setHardware(std::unique_ptr<FakeVehicleHardware> hardware)150     void setHardware(std::unique_ptr<FakeVehicleHardware> hardware) {
151         mHardware = std::move(hardware);
152     }
153 
newSubscribeOptions(int32_t propId,int32_t areaId,float sampleRateHz)154     static SubscribeOptions newSubscribeOptions(int32_t propId, int32_t areaId,
155                                                 float sampleRateHz) {
156         SubscribeOptions options;
157         options.areaIds = {areaId};
158         options.propId = propId;
159         options.sampleRate = sampleRateHz;
160         return options;
161     }
162 
setValues(const std::vector<SetValueRequest> & requests)163     StatusCode setValues(const std::vector<SetValueRequest>& requests) {
164         {
165             std::scoped_lock<std::mutex> lockGuard(mLock);
166             for (const auto& request : requests) {
167                 mPendingSetValueRequests.insert(request.requestId);
168             }
169         }
170         if (StatusCode status = getHardware()->setValues(mSetValuesCallback, requests);
171             status != StatusCode::OK) {
172             return status;
173         }
174         std::unique_lock<std::mutex> lk(mLock);
175         // Wait for the onSetValueResults.
176         bool result = mCv.wait_for(lk, milliseconds(1000), [this] {
177             ScopedLockAssertion lockAssertion(mLock);
178             return mPendingSetValueRequests.size() == 0;
179         });
180         if (!result) {
181             ALOGE("wait for callbacks for setValues timed-out");
182             return StatusCode::INTERNAL_ERROR;
183         }
184         return StatusCode::OK;
185     }
186 
getValues(const std::vector<GetValueRequest> & requests)187     StatusCode getValues(const std::vector<GetValueRequest>& requests) {
188         {
189             std::scoped_lock<std::mutex> lockGuard(mLock);
190             for (const auto& request : requests) {
191                 mPendingGetValueRequests.insert(request.requestId);
192             }
193         }
194         if (StatusCode status = getHardware()->getValues(mGetValuesCallback, requests);
195             status != StatusCode::OK) {
196             return status;
197         }
198         std::unique_lock<std::mutex> lk(mLock);
199         // Wait for the onGetValueResults.
200         bool result = mCv.wait_for(lk, milliseconds(1000), [this] {
201             ScopedLockAssertion lockAssertion(mLock);
202             return mPendingGetValueRequests.size() == 0;
203         });
204         if (!result) {
205             ALOGE("wait for callbacks for getValues timed-out");
206             return StatusCode::INTERNAL_ERROR;
207         }
208         return StatusCode::OK;
209     }
210 
setValue(const VehiclePropValue & value)211     StatusCode setValue(const VehiclePropValue& value) {
212         std::vector<SetValueRequest> requests = {
213                 SetValueRequest{
214                         .requestId = 0,
215                         .value = value,
216                 },
217         };
218 
219         if (StatusCode status = setValues(requests); status != StatusCode::OK) {
220             return status;
221         }
222 
223         const SetValueResult& result = getSetValueResults().back();
224 
225         if (result.requestId != 0) {
226             ALOGE("request ID mismatch, got %" PRId64 ", expect 0", result.requestId);
227             return StatusCode::INTERNAL_ERROR;
228         }
229 
230         return result.status;
231     }
232 
getValue(const VehiclePropValue & value)233     expected<VehiclePropValue, StatusCode> getValue(const VehiclePropValue& value) {
234         std::vector<GetValueRequest> requests = {
235                 GetValueRequest{
236                         .requestId = 0,
237                         .prop = value,
238                 },
239         };
240 
241         if (StatusCode status = getValues(requests); status != StatusCode::OK) {
242             return unexpected(status);
243         }
244 
245         const GetValueResult& result = getGetValueResults().back();
246         if (result.requestId != 0) {
247             ALOGE("request ID mismatch, got %" PRId64 ", expect 0", result.requestId);
248             return unexpected(StatusCode::INTERNAL_ERROR);
249         }
250 
251         if (result.status != StatusCode::OK) {
252             return unexpected(result.status);
253         }
254 
255         if (!result.prop.has_value()) {
256             ALOGE("%s", "result property is empty");
257             return unexpected(StatusCode::INTERNAL_ERROR);
258         }
259 
260         return result.prop.value();
261     }
262 
263     template <class T>
getStatus(expected<T,StatusCode> result)264     int getStatus(expected<T, StatusCode> result) {
265         return toInt(result.error());
266     }
267 
onSetValues(std::vector<SetValueResult> results)268     void onSetValues(std::vector<SetValueResult> results) {
269         std::scoped_lock<std::mutex> lockGuard(mLock);
270         for (auto& result : results) {
271             mSetValueResults.push_back(result);
272             mPendingSetValueRequests.erase(result.requestId);
273         }
274         mCv.notify_all();
275     }
276 
getSetValueResults()277     const std::vector<SetValueResult>& getSetValueResults() {
278         std::scoped_lock<std::mutex> lockGuard(mLock);
279         return mSetValueResults;
280     }
281 
onGetValues(std::vector<GetValueResult> results)282     void onGetValues(std::vector<GetValueResult> results) {
283         std::scoped_lock<std::mutex> lockGuard(mLock);
284         for (auto& result : results) {
285             mGetValueResults.push_back(result);
286             mPendingGetValueRequests.erase(result.requestId);
287         }
288         mCv.notify_all();
289     }
290 
getGetValueResults()291     const std::vector<GetValueResult>& getGetValueResults() {
292         std::scoped_lock<std::mutex> lockGuard(mLock);
293         return mGetValueResults;
294     }
295 
onPropertyChangeEvent(std::vector<VehiclePropValue> values)296     void onPropertyChangeEvent(std::vector<VehiclePropValue> values) {
297         std::scoped_lock<std::mutex> lockGuard(mLock);
298         for (auto& value : values) {
299             mChangedProperties.push_back(value);
300             PropIdAreaId propIdAreaId{
301                     .propId = value.prop,
302                     .areaId = value.areaId,
303             };
304             mEventCount[propIdAreaId]++;
305         }
306         mCv.notify_all();
307     }
308 
getChangedProperties()309     const std::vector<VehiclePropValue>& getChangedProperties() {
310         std::scoped_lock<std::mutex> lockGuard(mLock);
311         return mChangedProperties;
312     }
313 
waitForChangedProperties(size_t count,milliseconds timeout)314     bool waitForChangedProperties(size_t count, milliseconds timeout) {
315         std::unique_lock<std::mutex> lk(mLock);
316         return mCv.wait_for(lk, timeout, [this, count] {
317             ScopedLockAssertion lockAssertion(mLock);
318             return mChangedProperties.size() >= count;
319         });
320     }
321 
waitForChangedProperties(int32_t propId,int32_t areaId,size_t count,milliseconds timeout)322     bool waitForChangedProperties(int32_t propId, int32_t areaId, size_t count,
323                                   milliseconds timeout) {
324         PropIdAreaId propIdAreaId{
325                 .propId = propId,
326                 .areaId = areaId,
327         };
328         std::unique_lock<std::mutex> lk(mLock);
329         return mCv.wait_for(lk, timeout, [this, propIdAreaId, count] {
330             ScopedLockAssertion lockAssertion(mLock);
331             return mEventCount[propIdAreaId] >= count;
332         });
333     }
334 
clearChangedProperties()335     void clearChangedProperties() {
336         std::scoped_lock<std::mutex> lockGuard(mLock);
337         mEventCount.clear();
338         mChangedProperties.clear();
339     }
340 
getEventCount(int32_t propId,int32_t areaId)341     size_t getEventCount(int32_t propId, int32_t areaId) {
342         PropIdAreaId propIdAreaId{
343                 .propId = propId,
344                 .areaId = areaId,
345         };
346         std::scoped_lock<std::mutex> lockGuard(mLock);
347         return mEventCount[propIdAreaId];
348     }
349 
subscribe(int32_t propId,int32_t areaId,float sampleRateHz)350     void subscribe(int32_t propId, int32_t areaId, float sampleRateHz) {
351         ASSERT_EQ(StatusCode::OK,
352                   getHardware()->subscribe(newSubscribeOptions(propId, areaId, sampleRateHz)))
353                 << "failed to subscribe to propId: " << propId << "areaId: " << areaId
354                 << ", sampleRateHz: " << sampleRateHz;
355     }
356 
addSetValueRequest(std::vector<SetValueRequest> & requests,std::vector<SetValueResult> & expectedResults,int64_t requestId,const VehiclePropValue & value,StatusCode expectedStatus)357     static void addSetValueRequest(std::vector<SetValueRequest>& requests,
358                                    std::vector<SetValueResult>& expectedResults, int64_t requestId,
359                                    const VehiclePropValue& value, StatusCode expectedStatus) {
360         SetValueRequest request;
361         request.requestId = requestId;
362         request.value = value;
363         request.value.timestamp = elapsedRealtimeNano();
364         requests.push_back(std::move(request));
365 
366         SetValueResult result;
367         result.requestId = requestId;
368         result.status = expectedStatus;
369         expectedResults.push_back(std::move(result));
370     }
371 
addGetValueRequest(std::vector<GetValueRequest> & requests,std::vector<GetValueResult> & expectedResults,int64_t requestId,const VehiclePropValue & value,StatusCode expectedStatus)372     static void addGetValueRequest(std::vector<GetValueRequest>& requests,
373                                    std::vector<GetValueResult>& expectedResults, int64_t requestId,
374                                    const VehiclePropValue& value, StatusCode expectedStatus) {
375         GetValueRequest request;
376         request.requestId = requestId;
377         request.prop.prop = value.prop;
378         request.prop.areaId = value.areaId;
379         requests.push_back(std::move(request));
380 
381         GetValueResult result;
382         result.requestId = requestId;
383         result.status = expectedStatus;
384         if (expectedStatus == StatusCode::OK) {
385             result.prop = value;
386         }
387         expectedResults.push_back(std::move(result));
388     }
389 
getTestPropValues()390     std::vector<VehiclePropValue> getTestPropValues() {
391         VehiclePropValue oilLevel = {
392                 .prop = toInt(VehicleProperty::ENGINE_OIL_LEVEL),
393                 .value = {.int32Values = {1}},
394         };
395 
396         VehiclePropValue leftHvacTemp = {
397                 .prop = toInt(VehicleProperty::HVAC_TEMPERATURE_CURRENT),
398                 .value = {.floatValues = {170.0}},
399                 .areaId = SEAT_1_LEFT,
400         };
401 
402         VehiclePropValue rightHvacTemp = {
403                 .prop = toInt(VehicleProperty::HVAC_TEMPERATURE_CURRENT),
404                 .value = {.floatValues = {180.0}},
405                 .areaId = SEAT_1_RIGHT,
406         };
407 
408         return {oilLevel, leftHvacTemp, rightHvacTemp};
409     }
410 
411     struct PropValueCmp {
operator ()android::hardware::automotive::vehicle::fake::FakeVehicleHardwareTest::PropValueCmp412         bool operator()(const VehiclePropValue& a, const VehiclePropValue& b) const {
413             return (a.prop < b.prop) || ((a.prop == b.prop) && (a.value < b.value)) ||
414                    ((a.prop == b.prop) && (a.value == b.value) && (a.areaId < b.areaId));
415         }
416     } mPropValueCmp;
417 
getVehiclePropConfig(int32_t propertyId)418     std::unique_ptr<VehiclePropConfig> getVehiclePropConfig(int32_t propertyId) {
419         auto configs = mHardware->getAllPropertyConfigs();
420         for (auto& config : configs) {
421             if (config.prop == propertyId) {
422                 auto ptr = std::make_unique<VehiclePropConfig>();
423                 ptr->prop = config.prop;
424                 ptr->access = config.access;
425                 ptr->changeMode = config.changeMode;
426                 ptr->areaConfigs = config.areaConfigs;
427                 ptr->configArray = config.configArray;
428                 ptr->configString = config.configString;
429                 ptr->minSampleRate = config.minSampleRate;
430                 ptr->maxSampleRate = config.maxSampleRate;
431                 return ptr;
432             }
433         }
434         return std::unique_ptr<VehiclePropConfig>(nullptr);
435     }
436 
437   private:
438     std::unique_ptr<FakeVehicleHardware> mHardware;
439     std::shared_ptr<IVehicleHardware::SetValuesCallback> mSetValuesCallback;
440     std::shared_ptr<IVehicleHardware::GetValuesCallback> mGetValuesCallback;
441     std::condition_variable mCv;
442     std::mutex mLock;
443     std::unordered_map<PropIdAreaId, size_t, PropIdAreaIdHash> mEventCount GUARDED_BY(mLock);
444     std::vector<SetValueResult> mSetValueResults GUARDED_BY(mLock);
445     std::vector<GetValueResult> mGetValueResults GUARDED_BY(mLock);
446     std::vector<VehiclePropValue> mChangedProperties GUARDED_BY(mLock);
447     std::unordered_set<int64_t> mPendingSetValueRequests GUARDED_BY(mLock);
448     std::unordered_set<int64_t> mPendingGetValueRequests GUARDED_BY(mLock);
449 };
450 
TEST_F(FakeVehicleHardwareTest,testGetAllPropertyConfigs)451 TEST_F(FakeVehicleHardwareTest, testGetAllPropertyConfigs) {
452     std::vector<VehiclePropConfig> configs = getHardware()->getAllPropertyConfigs();
453 
454     FakeVehicleHardwareTestHelper helper(getHardware());
455     ASSERT_EQ(configs.size(), helper.loadConfigDeclarations().size());
456 }
457 
TEST_F(FakeVehicleHardwareTest,testGetAllPropertyConfigs_defaultSupportVUR)458 TEST_F(FakeVehicleHardwareTest, testGetAllPropertyConfigs_defaultSupportVUR) {
459     std::vector<VehiclePropConfig> configs = getHardware()->getAllPropertyConfigs();
460 
461     for (const auto& config : configs) {
462         bool expectedSupportVUR = true;
463         if (config.prop == toInt(VehicleProperty::VHAL_HEARTBEAT) ||
464             config.prop == toInt(VehicleProperty::CLUSTER_HEARTBEAT)) {
465             expectedSupportVUR = false;
466         }
467         EXPECT_GE(config.areaConfigs.size(), 1u)
468                 << "expect at least one area config, including global area config, propId: "
469                 << config.prop;
470         if (config.areaConfigs.size() == 0) {
471             continue;
472         }
473         for (const auto& areaConfig : config.areaConfigs) {
474             EXPECT_EQ(areaConfig.supportVariableUpdateRate, expectedSupportVUR)
475                     << "unexpected supportVariableUpdateRate for propId: " << config.prop
476                     << ", areaId: " << areaConfig.areaId;
477         }
478     }
479 }
480 
TEST_F(FakeVehicleHardwareTest,testGetDefaultValues)481 TEST_F(FakeVehicleHardwareTest, testGetDefaultValues) {
482     std::vector<GetValueRequest> getValueRequests;
483     std::vector<GetValueResult> expectedGetValueResults;
484     int64_t requestId = 1;
485 
486     FakeVehicleHardwareTestHelper helper(getHardware());
487     for (auto& [propId, config] : helper.loadConfigDeclarations()) {
488         if (obd2frame::FakeObd2Frame::isDiagnosticProperty(config.config)) {
489             // Ignore storing default value for diagnostic property. They have special get/set
490             // logic.
491             continue;
492         }
493 
494         if (FakeUserHal::isSupported(config.config.prop)) {
495             // Ignore fake user HAL properties, they have special logic for getting values.
496             continue;
497         }
498 
499         if (propId == toInt(TestVendorProperty::ECHO_REVERSE_BYTES)) {
500             // Ignore ECHO_REVERSE_BYTES, it has special logic.
501             continue;
502         }
503 
504         if (propId == toInt(TestVendorProperty::VENDOR_PROPERTY_FOR_ERROR_CODE_TESTING)) {
505             // Ignore VENDOR_PROPERTY_FOR_ERROR_CODE_TESTING, it has special logic.
506             continue;
507         }
508 
509         if (propId == toInt(VehicleProperty::VEHICLE_IN_USE) ||
510             propId == toInt(VehicleProperty::AP_POWER_BOOTUP_REASON)) {
511             // These may be controller by an external power control unit.
512             continue;
513         }
514 
515         if (isGlobalProp(propId)) {
516             if (config.initialValue == RawPropValues{}) {
517                 addGetValueRequest(getValueRequests, expectedGetValueResults, requestId++,
518                                    VehiclePropValue{.prop = propId}, StatusCode::NOT_AVAILABLE);
519                 continue;
520             }
521             addGetValueRequest(getValueRequests, expectedGetValueResults, requestId++,
522                                VehiclePropValue{
523                                        .prop = propId,
524                                        .value = config.initialValue,
525                                },
526                                StatusCode::OK);
527             continue;
528         }
529         for (auto areaConfig : config.config.areaConfigs) {
530             StatusCode status = StatusCode::OK;
531             VehiclePropValue propValue{
532                     .prop = propId,
533                     .areaId = areaConfig.areaId,
534             };
535             if (config.initialAreaValues.empty()) {
536                 if (config.initialValue == RawPropValues{}) {
537                     status = StatusCode::NOT_AVAILABLE;
538                 } else {
539                     propValue.value = config.initialValue;
540                 }
541             } else if (auto valueForAreaIt = config.initialAreaValues.find(areaConfig.areaId);
542                        valueForAreaIt != config.initialAreaValues.end()) {
543                 propValue.value = valueForAreaIt->second;
544             } else {
545                 status = StatusCode::NOT_AVAILABLE;
546             }
547             addGetValueRequest(getValueRequests, expectedGetValueResults, requestId++, propValue,
548                                status);
549         }
550     }
551 
552     // In our implementation, this would finish immediately.
553     StatusCode status = getValues(getValueRequests);
554 
555     ASSERT_EQ(status, StatusCode::OK);
556 
557     std::vector<GetValueResult> getValueResultsWithNoTimestamp;
558     for (auto& result : getGetValueResults()) {
559         GetValueResult resultCopy = result;
560         resultCopy.prop->timestamp = 0;
561         getValueResultsWithNoTimestamp.push_back(std::move(resultCopy));
562     }
563     ASSERT_THAT(getValueResultsWithNoTimestamp, ContainerEq(expectedGetValueResults));
564 }
565 
TEST_F(FakeVehicleHardwareTest,testSetValues)566 TEST_F(FakeVehicleHardwareTest, testSetValues) {
567     std::vector<SetValueRequest> requests;
568     std::vector<SetValueResult> expectedResults;
569 
570     int64_t requestId = 1;
571     for (auto& value : getTestPropValues()) {
572         addSetValueRequest(requests, expectedResults, requestId++, value, StatusCode::OK);
573     }
574 
575     StatusCode status = setValues(requests);
576 
577     ASSERT_EQ(status, StatusCode::OK);
578 
579     // Although callback might be called asynchronously, in our implementation, the callback would
580     // be called before setValues returns.
581     ASSERT_THAT(getSetValueResults(), ContainerEq(expectedResults));
582 }
583 
TEST_F(FakeVehicleHardwareTest,testSetValuesError)584 TEST_F(FakeVehicleHardwareTest, testSetValuesError) {
585     std::vector<SetValueRequest> requests;
586     std::vector<SetValueResult> expectedResults;
587 
588     int64_t requestId = 1;
589 
590     VehiclePropValue invalidProp = {
591             .prop = INVALID_PROP_ID,
592     };
593     addSetValueRequest(requests, expectedResults, requestId++, invalidProp,
594                        StatusCode::INVALID_ARG);
595 
596     for (auto& value : getTestPropValues()) {
597         addSetValueRequest(requests, expectedResults, requestId++, value, StatusCode::OK);
598     }
599 
600     StatusCode status = setValues(requests);
601 
602     ASSERT_EQ(status, StatusCode::OK);
603 
604     // Although callback might be called asynchronously, in our implementation, the callback would
605     // be called before setValues returns.
606     ASSERT_THAT(getSetValueResults(), ContainerEq(expectedResults));
607 }
608 
TEST_F(FakeVehicleHardwareTest,testSetValues_getUpdateEvents)609 TEST_F(FakeVehicleHardwareTest, testSetValues_getUpdateEvents) {
610     auto testValues = getTestPropValues();
611     std::vector<SetValueRequest> requests;
612     std::vector<SetValueResult> expectedResults;
613     int64_t requestId = 1;
614     for (auto& value : testValues) {
615         subscribe(value.prop, value.areaId, /*sampleRateHz=*/0);
616         addSetValueRequest(requests, expectedResults, requestId++, value, StatusCode::OK);
617     }
618     int64_t timestamp = elapsedRealtimeNano();
619 
620     StatusCode status = setValues(requests);
621 
622     ASSERT_EQ(status, StatusCode::OK);
623 
624     auto updatedValues = getChangedProperties();
625     std::vector<VehiclePropValue> updatedValuesWithNoTimestamp;
626     for (auto& value : updatedValues) {
627         ASSERT_GE(value.timestamp, timestamp);
628         VehiclePropValue valueCopy = value;
629         valueCopy.timestamp = 0;
630         updatedValuesWithNoTimestamp.push_back(std::move(valueCopy));
631     }
632 
633     ASSERT_THAT(updatedValuesWithNoTimestamp, WhenSortedBy(mPropValueCmp, Eq(testValues)));
634 }
635 
TEST_F(FakeVehicleHardwareTest,testReadValues)636 TEST_F(FakeVehicleHardwareTest, testReadValues) {
637     std::vector<SetValueRequest> setValueRequests;
638     std::vector<SetValueResult> expectedSetValueResults;
639 
640     int64_t requestId = 1;
641     for (auto& value : getTestPropValues()) {
642         addSetValueRequest(setValueRequests, expectedSetValueResults, requestId++, value,
643                            StatusCode::OK);
644     }
645     int64_t timestamp = elapsedRealtimeNano();
646 
647     // In our implementation, this would finish immediately.
648     StatusCode status = setValues(setValueRequests);
649 
650     ASSERT_EQ(status, StatusCode::OK);
651 
652     std::vector<GetValueRequest> getValueRequests;
653     std::vector<GetValueResult> expectedGetValueResults;
654     for (auto& value : getTestPropValues()) {
655         addGetValueRequest(getValueRequests, expectedGetValueResults, requestId++, value,
656                            StatusCode::OK);
657     }
658 
659     // In our implementation, this would finish immediately.
660     status = getValues(getValueRequests);
661 
662     ASSERT_EQ(status, StatusCode::OK);
663 
664     std::vector<GetValueResult> getValueResultsWithNoTimestamp;
665     for (auto& result : getGetValueResults()) {
666         ASSERT_GE(result.prop->timestamp, timestamp);
667         GetValueResult resultCopy = result;
668         resultCopy.prop->timestamp = 0;
669         getValueResultsWithNoTimestamp.push_back(std::move(resultCopy));
670     }
671     ASSERT_THAT(getValueResultsWithNoTimestamp, ContainerEq(expectedGetValueResults));
672 }
673 
TEST_F(FakeVehicleHardwareTest,testReadValuesErrorInvalidProp)674 TEST_F(FakeVehicleHardwareTest, testReadValuesErrorInvalidProp) {
675     std::vector<SetValueRequest> setValueRequests;
676     std::vector<SetValueResult> expectedSetValueResults;
677 
678     int64_t requestId = 1;
679     for (auto& value : getTestPropValues()) {
680         addSetValueRequest(setValueRequests, expectedSetValueResults, requestId++, value,
681                            StatusCode::OK);
682     }
683 
684     // In our implementation, this would finish immediately.
685     StatusCode status = setValues(setValueRequests);
686 
687     ASSERT_EQ(status, StatusCode::OK);
688 
689     std::vector<GetValueRequest> getValueRequests;
690     std::vector<GetValueResult> expectedGetValueResults;
691     VehiclePropValue invalidProp = {
692             .prop = INVALID_PROP_ID,
693     };
694     addGetValueRequest(getValueRequests, expectedGetValueResults, requestId++, invalidProp,
695                        StatusCode::INVALID_ARG);
696 
697     // In our implementation, this would finish immediately.
698     status = getValues(getValueRequests);
699 
700     ASSERT_EQ(status, StatusCode::OK);
701     ASSERT_THAT(getGetValueResults(), ContainerEq(expectedGetValueResults));
702 }
703 
TEST_F(FakeVehicleHardwareTest,testReadValuesErrorNotAvailable)704 TEST_F(FakeVehicleHardwareTest, testReadValuesErrorNotAvailable) {
705     std::vector<GetValueRequest> getValueRequests;
706     std::vector<GetValueResult> expectedGetValueResults;
707     // VEHICLE_MAP_SERVICE does not have initial value, 'get' must always return
708     // StatusCode::NOT_AVAILABLE.
709     addGetValueRequest(getValueRequests, expectedGetValueResults, 0,
710                        VehiclePropValue{
711                                .prop = VEHICLE_MAP_SERVICE,
712                        },
713                        StatusCode::NOT_AVAILABLE);
714 
715     // In our implementation, this would finish immediately.
716     StatusCode status = getValues(getValueRequests);
717 
718     ASSERT_EQ(status, StatusCode::OK);
719     ASSERT_THAT(getGetValueResults(), ContainerEq(expectedGetValueResults));
720 }
721 
TEST_F(FakeVehicleHardwareTest,testSetStatusMustIgnore)722 TEST_F(FakeVehicleHardwareTest, testSetStatusMustIgnore) {
723     VehiclePropValue testValue = getTestPropValues()[0];
724     testValue.status = VehiclePropertyStatus::UNAVAILABLE;
725 
726     std::vector<SetValueRequest> setValueRequests;
727     std::vector<SetValueResult> expectedSetValueResults;
728 
729     int64_t requestId = 1;
730     addSetValueRequest(setValueRequests, expectedSetValueResults, requestId++, testValue,
731                        StatusCode::OK);
732 
733     // In our implementation, this would finish immediately.
734     StatusCode status = setValues(setValueRequests);
735 
736     ASSERT_EQ(status, StatusCode::OK);
737     ASSERT_THAT(getSetValueResults(), ContainerEq(expectedSetValueResults));
738 
739     std::vector<GetValueRequest> getValueRequests;
740     getValueRequests.push_back(GetValueRequest{
741             .requestId = requestId++,
742             .prop = testValue,
743     });
744 
745     // In our implementation, this would finish immediately.
746     status = getValues(getValueRequests);
747 
748     ASSERT_EQ(status, StatusCode::OK);
749     ASSERT_EQ(getGetValueResults().size(), static_cast<size_t>(1));
750     ASSERT_EQ(getGetValueResults()[0].status, StatusCode::OK);
751     // The status should be by-default AVAILABLE for new status.
752     ASSERT_EQ(getGetValueResults()[0].prop->status, VehiclePropertyStatus::AVAILABLE);
753 
754     // Try to set the property again. The status should not be overwritten.
755     status = setValues(setValueRequests);
756 
757     ASSERT_EQ(status, StatusCode::OK);
758 
759     status = getValues(getValueRequests);
760 
761     ASSERT_EQ(status, StatusCode::OK);
762     ASSERT_EQ(getGetValueResults().size(), static_cast<size_t>(2));
763     ASSERT_EQ(getGetValueResults()[1].status, StatusCode::OK);
764     ASSERT_EQ(getGetValueResults()[1].prop->status, VehiclePropertyStatus::AVAILABLE);
765 }
766 
TEST_F(FakeVehicleHardwareTest,testVendorOverrideProperties)767 TEST_F(FakeVehicleHardwareTest, testVendorOverrideProperties) {
768     std::string currentDir = android::base::GetExecutableDirectory();
769     std::string overrideDir = currentDir + "/override/";
770     // Set vendor override directory.
771     std::unique_ptr<FakeVehicleHardware> hardware =
772             std::make_unique<FakeVehicleHardware>(currentDir, overrideDir, /*forceOverride=*/true);
773     setHardware(std::move(hardware));
774 
775     // This is the same as the prop in 'gear_selection.json'.
776     int gearProp = toInt(VehicleProperty::GEAR_SELECTION);
777 
778     auto result = getValue(VehiclePropValue{
779             .prop = gearProp,
780     });
781 
782     ASSERT_TRUE(result.ok()) << "expect to get the overridden property ok: " << getStatus(result);
783     ASSERT_EQ(static_cast<size_t>(1), result.value().value.int32Values.size());
784     ASSERT_EQ(8, result.value().value.int32Values[0]);
785 
786     // If we set the value, it should update despite the override.
787     ASSERT_EQ(setValue(VehiclePropValue{
788                       .prop = gearProp,
789                       .value =
790                               {
791                                       .int32Values = {5},
792                               },
793                       .timestamp = elapsedRealtimeNano(),
794               }),
795               StatusCode::OK)
796             << "expect to set the overridden property ok";
797 
798     result = getValue(VehiclePropValue{
799             .prop = gearProp,
800     });
801 
802     ASSERT_TRUE(result.ok()) << "expect to get the overridden property after setting value ok";
803     ASSERT_EQ(static_cast<size_t>(1), result.value().value.int32Values.size());
804     ASSERT_EQ(5, result.value().value.int32Values[0]);
805 }
806 
TEST_F(FakeVehicleHardwareTest,testVendorOverridePropertiesMultipleAreas)807 TEST_F(FakeVehicleHardwareTest, testVendorOverridePropertiesMultipleAreas) {
808     std::string currentDir = android::base::GetExecutableDirectory();
809     std::string overrideDir = currentDir + "/override/";
810     // Set vendor override directory.
811     std::unique_ptr<FakeVehicleHardware> hardware =
812             std::make_unique<FakeVehicleHardware>(currentDir, overrideDir, /*forceOverride=*/true);
813     setHardware(std::move(hardware));
814 
815     // This is the same as the prop in 'hvac_temperature_set.json'.
816     int hvacProp = toInt(VehicleProperty::HVAC_TEMPERATURE_SET);
817 
818     auto result = getValue(VehiclePropValue{
819             .prop = hvacProp,
820             .areaId = HVAC_LEFT,
821     });
822 
823     ASSERT_TRUE(result.ok()) << "expect to get the overridden property ok: " << getStatus(result);
824     ASSERT_EQ(static_cast<size_t>(1), result.value().value.floatValues.size());
825     ASSERT_EQ(30.0f, result.value().value.floatValues[0]);
826 }
827 
TEST_F(FakeVehicleHardwareTest,testVendorOverridePropertiesDirDoesNotExist)828 TEST_F(FakeVehicleHardwareTest, testVendorOverridePropertiesDirDoesNotExist) {
829     std::string currentDir = android::base::GetExecutableDirectory();
830     std::string overrideDir = currentDir + "/override/";
831     // Set vendor override directory to a non-existing dir.
832     std::unique_ptr<FakeVehicleHardware> hardware =
833             std::make_unique<FakeVehicleHardware>(currentDir, "1234", /*forceOverride=*/true);
834     setHardware(std::move(hardware));
835 
836     auto result = getValue(VehiclePropValue{
837             .prop = toInt(VehicleProperty::GEAR_SELECTION),
838     });
839 
840     ASSERT_TRUE(result.ok()) << "expect to get the default property ok: " << getStatus(result);
841     ASSERT_EQ(static_cast<size_t>(1), result.value().value.int32Values.size());
842     ASSERT_EQ(4, result.value().value.int32Values[0]);
843 }
844 
845 struct SetSpecialValueTestCase {
846     std::string name;
847     std::vector<VehiclePropValue> valuesToSet;
848     std::vector<VehiclePropValue> expectedValuesToGet;
849 };
850 
setSpecialValueTestCases()851 std::vector<SetSpecialValueTestCase> setSpecialValueTestCases() {
852     return {
853             SetSpecialValueTestCase{
854                     .name = "set_ap_power_state_report_deep_sleep_exit",
855                     .valuesToSet =
856                             {
857                                     VehiclePropValue{
858                                             .prop = toInt(VehicleProperty::AP_POWER_STATE_REPORT),
859                                             .value.int32Values = {toInt(
860                                                     VehicleApPowerStateReport::DEEP_SLEEP_EXIT)},
861                                     },
862                             },
863                     .expectedValuesToGet =
864                             {
865                                     VehiclePropValue{
866                                             .prop = toInt(VehicleProperty::AP_POWER_STATE_REQ),
867                                             .status = VehiclePropertyStatus::AVAILABLE,
868                                             .value.int32Values = {toInt(VehicleApPowerStateReq::ON),
869                                                                   0},
870                                     },
871                                     VehiclePropValue{
872                                             .prop = toInt(VehicleProperty::AP_POWER_STATE_REPORT),
873                                             .value.int32Values = {toInt(
874                                                     VehicleApPowerStateReport::DEEP_SLEEP_EXIT)},
875                                     },
876                             },
877             },
878             SetSpecialValueTestCase{
879                     .name = "set_ap_power_state_report_hibernation_exit",
880                     .valuesToSet =
881                             {
882                                     VehiclePropValue{
883                                             .prop = toInt(VehicleProperty::AP_POWER_STATE_REPORT),
884                                             .value.int32Values = {toInt(
885                                                     VehicleApPowerStateReport::HIBERNATION_EXIT)},
886                                     },
887                             },
888                     .expectedValuesToGet =
889                             {
890                                     VehiclePropValue{
891                                             .prop = toInt(VehicleProperty::AP_POWER_STATE_REQ),
892                                             .status = VehiclePropertyStatus::AVAILABLE,
893                                             .value.int32Values = {toInt(VehicleApPowerStateReq::ON),
894                                                                   0},
895                                     },
896                                     VehiclePropValue{
897                                             .prop = toInt(VehicleProperty::AP_POWER_STATE_REPORT),
898                                             .value.int32Values = {toInt(
899                                                     VehicleApPowerStateReport::HIBERNATION_EXIT)},
900                                     },
901                             },
902             },
903             SetSpecialValueTestCase{
904                     .name = "set_ap_power_state_report_shutdown_cancelled",
905                     .valuesToSet =
906                             {
907                                     VehiclePropValue{
908                                             .prop = toInt(VehicleProperty::AP_POWER_STATE_REPORT),
909                                             .value.int32Values = {toInt(
910                                                     VehicleApPowerStateReport::SHUTDOWN_CANCELLED)},
911                                     },
912                             },
913                     .expectedValuesToGet =
914                             {
915                                     VehiclePropValue{
916                                             .prop = toInt(VehicleProperty::AP_POWER_STATE_REQ),
917                                             .status = VehiclePropertyStatus::AVAILABLE,
918                                             .value.int32Values = {toInt(VehicleApPowerStateReq::ON),
919                                                                   0},
920                                     },
921                                     VehiclePropValue{
922                                             .prop = toInt(VehicleProperty::AP_POWER_STATE_REPORT),
923                                             .value.int32Values = {toInt(
924                                                     VehicleApPowerStateReport::SHUTDOWN_CANCELLED)},
925                                     },
926                             },
927             },
928             SetSpecialValueTestCase{
929                     .name = "set_ap_power_state_report_wait_for_vhal",
930                     .valuesToSet =
931                             {
932                                     VehiclePropValue{
933                                             .prop = toInt(VehicleProperty::AP_POWER_STATE_REPORT),
934                                             .value.int32Values = {toInt(
935                                                     VehicleApPowerStateReport::WAIT_FOR_VHAL)},
936                                     },
937                             },
938                     .expectedValuesToGet =
939                             {
940                                     VehiclePropValue{
941                                             .prop = toInt(VehicleProperty::AP_POWER_STATE_REQ),
942                                             .status = VehiclePropertyStatus::AVAILABLE,
943                                             .value.int32Values = {toInt(VehicleApPowerStateReq::ON),
944                                                                   0},
945                                     },
946                                     VehiclePropValue{
947                                             .prop = toInt(VehicleProperty::AP_POWER_STATE_REPORT),
948                                             .value.int32Values = {toInt(
949                                                     VehicleApPowerStateReport::WAIT_FOR_VHAL)},
950                                     },
951                             },
952             },
953             SetSpecialValueTestCase{
954                     .name = "set_ap_power_state_report_deep_sleep_entry",
955                     .valuesToSet =
956                             {
957                                     VehiclePropValue{
958                                             .prop = toInt(VehicleProperty::AP_POWER_STATE_REPORT),
959                                             .value.int32Values = {toInt(
960                                                     VehicleApPowerStateReport::DEEP_SLEEP_ENTRY)},
961                                     },
962                             },
963                     .expectedValuesToGet =
964                             {
965                                     VehiclePropValue{
966                                             .prop = toInt(VehicleProperty::AP_POWER_STATE_REQ),
967                                             .status = VehiclePropertyStatus::AVAILABLE,
968                                             .value.int32Values =
969                                                     {toInt(VehicleApPowerStateReq::FINISHED), 0},
970                                     },
971                                     VehiclePropValue{
972                                             .prop = toInt(VehicleProperty::AP_POWER_STATE_REPORT),
973                                             .value.int32Values = {toInt(
974                                                     VehicleApPowerStateReport::DEEP_SLEEP_ENTRY)},
975                                     },
976                             },
977             },
978             SetSpecialValueTestCase{
979                     .name = "set_ap_power_state_report_hibernation_entry",
980                     .valuesToSet =
981                             {
982                                     VehiclePropValue{
983                                             .prop = toInt(VehicleProperty::AP_POWER_STATE_REPORT),
984                                             .value.int32Values = {toInt(
985                                                     VehicleApPowerStateReport::HIBERNATION_ENTRY)},
986                                     },
987                             },
988                     .expectedValuesToGet =
989                             {
990                                     VehiclePropValue{
991                                             .prop = toInt(VehicleProperty::AP_POWER_STATE_REQ),
992                                             .status = VehiclePropertyStatus::AVAILABLE,
993                                             .value.int32Values =
994                                                     {toInt(VehicleApPowerStateReq::FINISHED), 0},
995                                     },
996                                     VehiclePropValue{
997                                             .prop = toInt(VehicleProperty::AP_POWER_STATE_REPORT),
998                                             .value.int32Values = {toInt(
999                                                     VehicleApPowerStateReport::HIBERNATION_ENTRY)},
1000                                     },
1001                             },
1002             },
1003             SetSpecialValueTestCase{
1004                     .name = "set_ap_power_state_report_shutdown_start",
1005                     .valuesToSet =
1006                             {
1007                                     VehiclePropValue{
1008                                             .prop = toInt(VehicleProperty::AP_POWER_STATE_REPORT),
1009                                             .value.int32Values = {toInt(
1010                                                     VehicleApPowerStateReport::SHUTDOWN_START)},
1011                                     },
1012                             },
1013                     .expectedValuesToGet =
1014                             {
1015                                     VehiclePropValue{
1016                                             .prop = toInt(VehicleProperty::AP_POWER_STATE_REQ),
1017                                             .status = VehiclePropertyStatus::AVAILABLE,
1018                                             .value.int32Values =
1019                                                     {toInt(VehicleApPowerStateReq::FINISHED), 0},
1020                                     },
1021                                     VehiclePropValue{
1022                                             .prop = toInt(VehicleProperty::AP_POWER_STATE_REPORT),
1023                                             .value.int32Values = {toInt(
1024                                                     VehicleApPowerStateReport::SHUTDOWN_START)},
1025                                     },
1026                             },
1027             },
1028             SetSpecialValueTestCase{
1029                     .name = "cluster_report_state_to_vendor",
1030                     .valuesToSet =
1031                             {
1032                                     VehiclePropValue{
1033                                             .prop = toInt(VehicleProperty::CLUSTER_REPORT_STATE),
1034                                             .value.int32Values = {1},
1035                                     },
1036                             },
1037                     .expectedValuesToGet =
1038                             {
1039                                     VehiclePropValue{
1040                                             .prop = toInt(TestVendorProperty::
1041                                                                   VENDOR_CLUSTER_REPORT_STATE),
1042                                             .value.int32Values = {1},
1043                                     },
1044                             },
1045             },
1046             SetSpecialValueTestCase{
1047                     .name = "cluster_request_display_to_vendor",
1048                     .valuesToSet =
1049                             {
1050                                     VehiclePropValue{
1051                                             .prop = toInt(VehicleProperty::CLUSTER_REQUEST_DISPLAY),
1052                                             .value.int32Values = {1},
1053                                     },
1054                             },
1055                     .expectedValuesToGet =
1056                             {
1057                                     VehiclePropValue{
1058                                             .prop = toInt(TestVendorProperty::
1059                                                                   VENDOR_CLUSTER_REQUEST_DISPLAY),
1060                                             .value.int32Values = {1},
1061                                     },
1062                             },
1063             },
1064             SetSpecialValueTestCase{
1065                     .name = "cluster_navigation_state_to_vendor",
1066                     .valuesToSet =
1067                             {
1068                                     VehiclePropValue{
1069                                             .prop = toInt(
1070                                                     VehicleProperty::CLUSTER_NAVIGATION_STATE),
1071                                             .value.byteValues = {0x1},
1072                                     },
1073                             },
1074                     .expectedValuesToGet =
1075                             {
1076                                     VehiclePropValue{
1077                                             .prop = toInt(TestVendorProperty::
1078                                                                   VENDOR_CLUSTER_NAVIGATION_STATE),
1079                                             .value.byteValues = {0x1},
1080                                     },
1081                             },
1082             },
1083             SetSpecialValueTestCase{
1084                     .name = "vendor_cluster_switch_ui_to_system",
1085                     .valuesToSet =
1086                             {
1087                                     VehiclePropValue{
1088                                             .prop = toInt(
1089                                                     TestVendorProperty::VENDOR_CLUSTER_SWITCH_UI),
1090                                             .value.int32Values = {1},
1091                                     },
1092                             },
1093                     .expectedValuesToGet =
1094                             {
1095                                     VehiclePropValue{
1096                                             .prop = toInt(VehicleProperty::CLUSTER_SWITCH_UI),
1097                                             .value.int32Values = {1},
1098                                     },
1099                             },
1100             },
1101             SetSpecialValueTestCase{
1102                     .name = "vendor_cluster_display_state_to_system",
1103                     .valuesToSet =
1104                             {
1105                                     VehiclePropValue{
1106                                             .prop = toInt(TestVendorProperty::
1107                                                                   VENDOR_CLUSTER_DISPLAY_STATE),
1108                                             .value.int32Values = {1, 2},
1109                                     },
1110                             },
1111                     .expectedValuesToGet =
1112                             {
1113                                     VehiclePropValue{
1114                                             .prop = toInt(VehicleProperty::CLUSTER_DISPLAY_STATE),
1115                                             .value.int32Values = {1, 2},
1116                                     },
1117                             },
1118             },
1119             SetSpecialValueTestCase{
1120                     .name = "set_automatic_emergency_braking_enabled_false",
1121                     .valuesToSet =
1122                             {
1123                                     VehiclePropValue{
1124                                             .prop = toInt(
1125                                                     VehicleProperty::
1126                                                             AUTOMATIC_EMERGENCY_BRAKING_ENABLED),
1127                                             .value.int32Values = {0},
1128                                     },
1129                             },
1130                     .expectedValuesToGet =
1131                             {
1132                                     VehiclePropValue{
1133                                             .prop = toInt(
1134                                                     VehicleProperty::
1135                                                             AUTOMATIC_EMERGENCY_BRAKING_ENABLED),
1136                                             .value.int32Values = {0},
1137                                     },
1138                                     VehiclePropValue{
1139                                             .prop = toInt(
1140                                                     VehicleProperty::
1141                                                             AUTOMATIC_EMERGENCY_BRAKING_STATE),
1142                                             .value.int32Values = {toInt(
1143                                                     ErrorState::NOT_AVAILABLE_DISABLED)},
1144                                     },
1145                             },
1146             },
1147             SetSpecialValueTestCase{
1148                     .name = "set_automatic_emergency_braking_enabled_true",
1149                     .valuesToSet =
1150                             {
1151                                     VehiclePropValue{
1152                                             .prop = toInt(
1153                                                     VehicleProperty::
1154                                                             AUTOMATIC_EMERGENCY_BRAKING_ENABLED),
1155                                             .value.int32Values = {1},
1156                                     },
1157                             },
1158                     .expectedValuesToGet =
1159                             {
1160                                     VehiclePropValue{
1161                                             .prop = toInt(
1162                                                     VehicleProperty::
1163                                                             AUTOMATIC_EMERGENCY_BRAKING_ENABLED),
1164                                             .value.int32Values = {1},
1165                                     },
1166                                     VehiclePropValue{
1167                                             .prop = toInt(
1168                                                     VehicleProperty::
1169                                                             AUTOMATIC_EMERGENCY_BRAKING_STATE),
1170                                             .value.int32Values = {1},
1171                                     },
1172                             },
1173             },
1174             SetSpecialValueTestCase{
1175                     .name = "set_forward_collision_warning_enabled_false",
1176                     .valuesToSet =
1177                             {
1178                                     VehiclePropValue{
1179                                             .prop = toInt(
1180                                                     VehicleProperty::
1181                                                             FORWARD_COLLISION_WARNING_ENABLED),
1182                                             .value.int32Values = {0},
1183                                     },
1184                             },
1185                     .expectedValuesToGet =
1186                             {
1187                                     VehiclePropValue{
1188                                             .prop = toInt(
1189                                                     VehicleProperty::
1190                                                             FORWARD_COLLISION_WARNING_ENABLED),
1191                                             .value.int32Values = {0},
1192                                     },
1193                                     VehiclePropValue{
1194                                             .prop = toInt(VehicleProperty::
1195                                                                   FORWARD_COLLISION_WARNING_STATE),
1196                                             .value.int32Values = {toInt(
1197                                                     ErrorState::NOT_AVAILABLE_DISABLED)},
1198                                     },
1199                             },
1200             },
1201             SetSpecialValueTestCase{
1202                     .name = "set_forward_collision_warning_enabled_true",
1203                     .valuesToSet =
1204                             {
1205                                     VehiclePropValue{
1206                                             .prop = toInt(
1207                                                     VehicleProperty::
1208                                                             FORWARD_COLLISION_WARNING_ENABLED),
1209                                             .value.int32Values = {1},
1210                                     },
1211                             },
1212                     .expectedValuesToGet =
1213                             {
1214                                     VehiclePropValue{
1215                                             .prop = toInt(
1216                                                     VehicleProperty::
1217                                                             FORWARD_COLLISION_WARNING_ENABLED),
1218                                             .value.int32Values = {1},
1219                                     },
1220                                     VehiclePropValue{
1221                                             .prop = toInt(VehicleProperty::
1222                                                                   FORWARD_COLLISION_WARNING_STATE),
1223                                             .value.int32Values = {1},
1224                                     },
1225                             },
1226             },
1227             SetSpecialValueTestCase{
1228                     .name = "set_blind_spot_warning_enabled_false",
1229                     .valuesToSet =
1230                             {
1231                                     VehiclePropValue{
1232                                             .prop = toInt(
1233                                                     VehicleProperty::BLIND_SPOT_WARNING_ENABLED),
1234                                             .value.int32Values = {0},
1235                                     },
1236                             },
1237                     .expectedValuesToGet =
1238                             {
1239                                     VehiclePropValue{
1240                                             .prop = toInt(
1241                                                     VehicleProperty::BLIND_SPOT_WARNING_ENABLED),
1242                                             .value.int32Values = {0},
1243                                     },
1244                                     VehiclePropValue{
1245                                             .prop = toInt(
1246                                                     VehicleProperty::BLIND_SPOT_WARNING_STATE),
1247                                             .areaId = toInt(VehicleAreaMirror::DRIVER_LEFT),
1248                                             .value.int32Values = {toInt(
1249                                                     ErrorState::NOT_AVAILABLE_DISABLED)},
1250                                     },
1251                                     VehiclePropValue{
1252                                             .prop = toInt(
1253                                                     VehicleProperty::BLIND_SPOT_WARNING_STATE),
1254                                             .areaId = toInt(VehicleAreaMirror::DRIVER_RIGHT),
1255                                             .value.int32Values = {toInt(
1256                                                     ErrorState::NOT_AVAILABLE_DISABLED)},
1257                                     },
1258                             },
1259             },
1260             SetSpecialValueTestCase{
1261                     .name = "set_blind_spot_warning_enabled_true",
1262                     .valuesToSet =
1263                             {
1264                                     VehiclePropValue{
1265                                             .prop = toInt(
1266                                                     VehicleProperty::BLIND_SPOT_WARNING_ENABLED),
1267                                             .value.int32Values = {1},
1268                                     },
1269                             },
1270                     .expectedValuesToGet =
1271                             {
1272                                     VehiclePropValue{
1273                                             .prop = toInt(
1274                                                     VehicleProperty::BLIND_SPOT_WARNING_ENABLED),
1275                                             .value.int32Values = {1},
1276                                     },
1277                                     VehiclePropValue{
1278                                             .prop = toInt(
1279                                                     VehicleProperty::BLIND_SPOT_WARNING_STATE),
1280                                             .areaId = toInt(VehicleAreaMirror::DRIVER_LEFT),
1281                                             .value.int32Values = {1},
1282                                     },
1283                                     VehiclePropValue{
1284                                             .prop = toInt(
1285                                                     VehicleProperty::BLIND_SPOT_WARNING_STATE),
1286                                             .areaId = toInt(VehicleAreaMirror::DRIVER_RIGHT),
1287                                             .value.int32Values = {1},
1288                                     },
1289                             },
1290             },
1291             SetSpecialValueTestCase{
1292                     .name = "set_lane_departure_warning_enabled_false",
1293                     .valuesToSet =
1294                             {
1295                                     VehiclePropValue{
1296                                             .prop = toInt(VehicleProperty::
1297                                                                   LANE_DEPARTURE_WARNING_ENABLED),
1298                                             .value.int32Values = {0},
1299                                     },
1300                             },
1301                     .expectedValuesToGet =
1302                             {
1303                                     VehiclePropValue{
1304                                             .prop = toInt(VehicleProperty::
1305                                                                   LANE_DEPARTURE_WARNING_ENABLED),
1306                                             .value.int32Values = {0},
1307                                     },
1308                                     VehiclePropValue{
1309                                             .prop = toInt(
1310                                                     VehicleProperty::LANE_DEPARTURE_WARNING_STATE),
1311                                             .value.int32Values = {toInt(
1312                                                     ErrorState::NOT_AVAILABLE_DISABLED)},
1313                                     },
1314                             },
1315             },
1316             SetSpecialValueTestCase{
1317                     .name = "set_lane_departure_warning_enabled_true",
1318                     .valuesToSet =
1319                             {
1320                                     VehiclePropValue{
1321                                             .prop = toInt(VehicleProperty::
1322                                                                   LANE_DEPARTURE_WARNING_ENABLED),
1323                                             .value.int32Values = {1},
1324                                     },
1325                             },
1326                     .expectedValuesToGet =
1327                             {
1328                                     VehiclePropValue{
1329                                             .prop = toInt(VehicleProperty::
1330                                                                   LANE_DEPARTURE_WARNING_ENABLED),
1331                                             .value.int32Values = {1},
1332                                     },
1333                                     VehiclePropValue{
1334                                             .prop = toInt(
1335                                                     VehicleProperty::LANE_DEPARTURE_WARNING_STATE),
1336                                             .value.int32Values = {1},
1337                                     },
1338                             },
1339             },
1340             SetSpecialValueTestCase{
1341                     .name = "set_lane_keep_assist_enabled_false",
1342                     .valuesToSet =
1343                             {
1344                                     VehiclePropValue{
1345                                             .prop = toInt(
1346                                                     VehicleProperty::LANE_KEEP_ASSIST_ENABLED),
1347                                             .value.int32Values = {0},
1348                                     },
1349                             },
1350                     .expectedValuesToGet =
1351                             {
1352                                     VehiclePropValue{
1353                                             .prop = toInt(
1354                                                     VehicleProperty::LANE_KEEP_ASSIST_ENABLED),
1355                                             .value.int32Values = {0},
1356                                     },
1357                                     VehiclePropValue{
1358                                             .prop = toInt(VehicleProperty::LANE_KEEP_ASSIST_STATE),
1359                                             .value.int32Values = {toInt(
1360                                                     ErrorState::NOT_AVAILABLE_DISABLED)},
1361                                     },
1362                             },
1363             },
1364             SetSpecialValueTestCase{
1365                     .name = "set_lane_keep_assist_enabled_true",
1366                     .valuesToSet =
1367                             {
1368                                     VehiclePropValue{
1369                                             .prop = toInt(
1370                                                     VehicleProperty::LANE_KEEP_ASSIST_ENABLED),
1371                                             .value.int32Values = {1},
1372                                     },
1373                             },
1374                     .expectedValuesToGet =
1375                             {
1376                                     VehiclePropValue{
1377                                             .prop = toInt(
1378                                                     VehicleProperty::LANE_KEEP_ASSIST_ENABLED),
1379                                             .value.int32Values = {1},
1380                                     },
1381                                     VehiclePropValue{
1382                                             .prop = toInt(VehicleProperty::LANE_KEEP_ASSIST_STATE),
1383                                             .value.int32Values = {1},
1384                                     },
1385                             },
1386             },
1387             SetSpecialValueTestCase{
1388                     .name = "set_lane_centering_assist_enabled_false",
1389                     .valuesToSet =
1390                             {
1391                                     VehiclePropValue{
1392                                             .prop = toInt(
1393                                                     VehicleProperty::LANE_CENTERING_ASSIST_ENABLED),
1394                                             .value.int32Values = {0},
1395                                     },
1396                             },
1397                     .expectedValuesToGet =
1398                             {
1399                                     VehiclePropValue{
1400                                             .prop = toInt(
1401                                                     VehicleProperty::LANE_CENTERING_ASSIST_ENABLED),
1402                                             .value.int32Values = {0},
1403                                     },
1404                                     VehiclePropValue{
1405                                             .prop = toInt(
1406                                                     VehicleProperty::LANE_CENTERING_ASSIST_STATE),
1407                                             .value.int32Values = {toInt(
1408                                                     ErrorState::NOT_AVAILABLE_DISABLED)},
1409                                     },
1410                             },
1411             },
1412             SetSpecialValueTestCase{
1413                     .name = "set_lane_centering_assist_enabled_true",
1414                     .valuesToSet =
1415                             {
1416                                     VehiclePropValue{
1417                                             .prop = toInt(
1418                                                     VehicleProperty::LANE_CENTERING_ASSIST_ENABLED),
1419                                             .value.int32Values = {1},
1420                                     },
1421                             },
1422                     .expectedValuesToGet =
1423                             {
1424                                     VehiclePropValue{
1425                                             .prop = toInt(
1426                                                     VehicleProperty::LANE_CENTERING_ASSIST_ENABLED),
1427                                             .value.int32Values = {1},
1428                                     },
1429                                     VehiclePropValue{
1430                                             .prop = toInt(
1431                                                     VehicleProperty::LANE_CENTERING_ASSIST_STATE),
1432                                             .value.int32Values = {1},
1433                                     },
1434                             },
1435             },
1436             SetSpecialValueTestCase{
1437                     .name = "set_emergency_lane_keep_assist_enabled_false",
1438                     .valuesToSet =
1439                             {
1440                                     VehiclePropValue{
1441                                             .prop = toInt(
1442                                                     VehicleProperty::
1443                                                             EMERGENCY_LANE_KEEP_ASSIST_ENABLED),
1444                                             .value.int32Values = {0},
1445                                     },
1446                             },
1447                     .expectedValuesToGet =
1448                             {
1449                                     VehiclePropValue{
1450                                             .prop = toInt(
1451                                                     VehicleProperty::
1452                                                             EMERGENCY_LANE_KEEP_ASSIST_ENABLED),
1453                                             .value.int32Values = {0},
1454                                     },
1455                                     VehiclePropValue{
1456                                             .prop = toInt(VehicleProperty::
1457                                                                   EMERGENCY_LANE_KEEP_ASSIST_STATE),
1458                                             .value.int32Values = {toInt(
1459                                                     ErrorState::NOT_AVAILABLE_DISABLED)},
1460                                     },
1461                             },
1462             },
1463             SetSpecialValueTestCase{
1464                     .name = "set_emergency_lane_keep_assist_enabled_true",
1465                     .valuesToSet =
1466                             {
1467                                     VehiclePropValue{
1468                                             .prop = toInt(
1469                                                     VehicleProperty::
1470                                                             EMERGENCY_LANE_KEEP_ASSIST_ENABLED),
1471                                             .value.int32Values = {1},
1472                                     },
1473                             },
1474                     .expectedValuesToGet =
1475                             {
1476                                     VehiclePropValue{
1477                                             .prop = toInt(
1478                                                     VehicleProperty::
1479                                                             EMERGENCY_LANE_KEEP_ASSIST_ENABLED),
1480                                             .value.int32Values = {1},
1481                                     },
1482                                     VehiclePropValue{
1483                                             .prop = toInt(VehicleProperty::
1484                                                                   EMERGENCY_LANE_KEEP_ASSIST_STATE),
1485                                             .value.int32Values = {1},
1486                                     },
1487                             },
1488             },
1489             SetSpecialValueTestCase{
1490                     .name = "set_cruise_control_enabled_false",
1491                     .valuesToSet =
1492                             {
1493                                     VehiclePropValue{
1494                                             .prop = toInt(VehicleProperty::CRUISE_CONTROL_ENABLED),
1495                                             .value.int32Values = {0},
1496                                     },
1497                             },
1498                     .expectedValuesToGet =
1499                             {
1500                                     VehiclePropValue{
1501                                             .prop = toInt(VehicleProperty::CRUISE_CONTROL_ENABLED),
1502                                             .value.int32Values = {0},
1503                                     },
1504                                     VehiclePropValue{
1505                                             .prop = toInt(VehicleProperty::CRUISE_CONTROL_TYPE),
1506                                             .value.int32Values = {toInt(
1507                                                     ErrorState::NOT_AVAILABLE_DISABLED)},
1508                                     },
1509                                     VehiclePropValue{
1510                                             .prop = toInt(VehicleProperty::CRUISE_CONTROL_STATE),
1511                                             .value.int32Values = {toInt(
1512                                                     ErrorState::NOT_AVAILABLE_DISABLED)},
1513                                     },
1514                             },
1515             },
1516             SetSpecialValueTestCase{
1517                     .name = "set_cruise_control_enabled_true",
1518                     .valuesToSet =
1519                             {
1520                                     VehiclePropValue{
1521                                             .prop = toInt(VehicleProperty::CRUISE_CONTROL_ENABLED),
1522                                             .value.int32Values = {1},
1523                                     },
1524                             },
1525                     .expectedValuesToGet =
1526                             {
1527                                     VehiclePropValue{
1528                                             .prop = toInt(VehicleProperty::CRUISE_CONTROL_ENABLED),
1529                                             .value.int32Values = {1},
1530                                     },
1531                                     VehiclePropValue{
1532                                             .prop = toInt(VehicleProperty::CRUISE_CONTROL_TYPE),
1533                                             .value.int32Values = {2},
1534                                     },
1535                                     VehiclePropValue{
1536                                             .prop = toInt(VehicleProperty::CRUISE_CONTROL_STATE),
1537                                             .value.int32Values = {1},
1538                                     },
1539                             },
1540             },
1541             SetSpecialValueTestCase{
1542                     .name = "set_hands_on_detection_enabled_false",
1543                     .valuesToSet =
1544                             {
1545                                     VehiclePropValue{
1546                                             .prop = toInt(
1547                                                     VehicleProperty::HANDS_ON_DETECTION_ENABLED),
1548                                             .value.int32Values = {0},
1549                                     },
1550                             },
1551                     .expectedValuesToGet =
1552                             {
1553                                     VehiclePropValue{
1554                                             .prop = toInt(
1555                                                     VehicleProperty::HANDS_ON_DETECTION_ENABLED),
1556                                             .value.int32Values = {0},
1557                                     },
1558                                     VehiclePropValue{
1559                                             .prop = toInt(VehicleProperty::
1560                                                                   HANDS_ON_DETECTION_DRIVER_STATE),
1561                                             .value.int32Values = {toInt(
1562                                                     ErrorState::NOT_AVAILABLE_DISABLED)},
1563                                     },
1564                                     VehiclePropValue{
1565                                             .prop = toInt(
1566                                                     VehicleProperty::HANDS_ON_DETECTION_WARNING),
1567                                             .value.int32Values = {toInt(
1568                                                     ErrorState::NOT_AVAILABLE_DISABLED)},
1569                                     },
1570                             },
1571             },
1572             SetSpecialValueTestCase{
1573                     .name = "set_hands_on_detection_enabled_true",
1574                     .valuesToSet =
1575                             {
1576                                     VehiclePropValue{
1577                                             .prop = toInt(
1578                                                     VehicleProperty::HANDS_ON_DETECTION_ENABLED),
1579                                             .value.int32Values = {1},
1580                                     },
1581                             },
1582                     .expectedValuesToGet =
1583                             {
1584                                     VehiclePropValue{
1585                                             .prop = toInt(
1586                                                     VehicleProperty::HANDS_ON_DETECTION_ENABLED),
1587                                             .value.int32Values = {1},
1588                                     },
1589                                     VehiclePropValue{
1590                                             .prop = toInt(VehicleProperty::
1591                                                                   HANDS_ON_DETECTION_DRIVER_STATE),
1592                                             .value.int32Values = {1},
1593                                     },
1594                                     VehiclePropValue{
1595                                             .prop = toInt(
1596                                                     VehicleProperty::HANDS_ON_DETECTION_WARNING),
1597                                             .value.int32Values = {1},
1598                                     },
1599                             },
1600             },
1601             SetSpecialValueTestCase{
1602                     .name = "set_low_speed_collision_warning_enabled_false",
1603                     .valuesToSet =
1604                             {
1605                                     VehiclePropValue{
1606                                             .prop = toInt(
1607                                                     VehicleProperty::
1608                                                             LOW_SPEED_COLLISION_WARNING_ENABLED),
1609                                             .value.int32Values = {0},
1610                                     },
1611                             },
1612                     .expectedValuesToGet =
1613                             {
1614                                     VehiclePropValue{
1615                                             .prop = toInt(
1616                                                     VehicleProperty::
1617                                                             LOW_SPEED_COLLISION_WARNING_ENABLED),
1618                                             .value.int32Values = {0},
1619                                     },
1620                                     VehiclePropValue{
1621                                             .prop = toInt(
1622                                                     VehicleProperty::
1623                                                             LOW_SPEED_COLLISION_WARNING_STATE),
1624                                             .value.int32Values = {toInt(
1625                                                     ErrorState::NOT_AVAILABLE_DISABLED)},
1626                                     },
1627                             },
1628             },
1629             SetSpecialValueTestCase{
1630                     .name = "set_low_speed_collision_warning_enabled_true",
1631                     .valuesToSet =
1632                             {
1633                                     VehiclePropValue{
1634                                             .prop = toInt(
1635                                                     VehicleProperty::
1636                                                             LOW_SPEED_COLLISION_WARNING_ENABLED),
1637                                             .value.int32Values = {1},
1638                                     },
1639                             },
1640                     .expectedValuesToGet =
1641                             {
1642                                     VehiclePropValue{
1643                                             .prop = toInt(
1644                                                     VehicleProperty::
1645                                                             LOW_SPEED_COLLISION_WARNING_ENABLED),
1646                                             .value.int32Values = {1},
1647                                     },
1648                                     VehiclePropValue{
1649                                             .prop = toInt(
1650                                                     VehicleProperty::
1651                                                             LOW_SPEED_COLLISION_WARNING_STATE),
1652                                             .value.int32Values = {1},
1653                                     },
1654                             },
1655             },
1656             SetSpecialValueTestCase{
1657                     .name = "set_electronic_stability_control_enabled_false",
1658                     .valuesToSet =
1659                             {
1660                                     VehiclePropValue{
1661                                             .prop = toInt(
1662                                                     VehicleProperty::
1663                                                             ELECTRONIC_STABILITY_CONTROL_ENABLED),
1664                                             .value.int32Values = {0},
1665                                     },
1666                             },
1667                     .expectedValuesToGet =
1668                             {
1669                                     VehiclePropValue{
1670                                             .prop = toInt(
1671                                                     VehicleProperty::
1672                                                             ELECTRONIC_STABILITY_CONTROL_ENABLED),
1673                                             .value.int32Values = {0},
1674                                     },
1675                                     VehiclePropValue{
1676                                             .prop = toInt(
1677                                                     VehicleProperty::
1678                                                             ELECTRONIC_STABILITY_CONTROL_STATE),
1679                                             .value.int32Values = {toInt(
1680                                                     ErrorState::NOT_AVAILABLE_DISABLED)},
1681                                     },
1682                             },
1683             },
1684             SetSpecialValueTestCase{
1685                     .name = "set_electronic_stability_control_enabled_true",
1686                     .valuesToSet =
1687                             {
1688                                     VehiclePropValue{
1689                                             .prop = toInt(
1690                                                     VehicleProperty::
1691                                                             ELECTRONIC_STABILITY_CONTROL_ENABLED),
1692                                             .value.int32Values = {1},
1693                                     },
1694                             },
1695                     .expectedValuesToGet =
1696                             {
1697                                     VehiclePropValue{
1698                                             .prop = toInt(
1699                                                     VehicleProperty::
1700                                                             ELECTRONIC_STABILITY_CONTROL_ENABLED),
1701                                             .value.int32Values = {1},
1702                                     },
1703                                     VehiclePropValue{
1704                                             .prop = toInt(
1705                                                     VehicleProperty::
1706                                                             ELECTRONIC_STABILITY_CONTROL_STATE),
1707                                             .value.int32Values = {1},
1708                                     },
1709                             },
1710             },
1711             SetSpecialValueTestCase{
1712                     .name = "set_shutdown_request",
1713                     .valuesToSet =
1714                             {
1715                                     VehiclePropValue{
1716                                             .prop = toInt(VehicleProperty::SHUTDOWN_REQUEST),
1717                                             .value.int32Values =
1718                                                     {
1719                                                             toInt(VehicleApPowerStateShutdownParam::
1720                                                                           SHUTDOWN_ONLY),
1721                                                     },
1722                                     },
1723                             },
1724                     .expectedValuesToGet =
1725                             {
1726                                     VehiclePropValue{
1727                                             .prop = toInt(VehicleProperty::AP_POWER_STATE_REQ),
1728                                             .value.int32Values =
1729                                                     {
1730                                                             toInt(VehicleApPowerStateReq::
1731                                                                           SHUTDOWN_PREPARE),
1732                                                             toInt(VehicleApPowerStateShutdownParam::
1733                                                                           SHUTDOWN_ONLY),
1734                                                     },
1735                                     },
1736                             },
1737             },
1738     };
1739 }
1740 
1741 class FakeVehicleHardwareSpecialValuesTest
1742     : public FakeVehicleHardwareTest,
1743       public testing::WithParamInterface<SetSpecialValueTestCase> {};
1744 
TEST_P(FakeVehicleHardwareSpecialValuesTest,testSetSpecialProperties)1745 TEST_P(FakeVehicleHardwareSpecialValuesTest, testSetSpecialProperties) {
1746     const SetSpecialValueTestCase& tc = GetParam();
1747 
1748     for (const auto& value : tc.valuesToSet) {
1749         ASSERT_EQ(setValue(value), StatusCode::OK) << "failed to set property " << value.prop;
1750     }
1751 
1752     std::vector<VehiclePropValue> gotValues;
1753 
1754     for (const auto& value : tc.expectedValuesToGet) {
1755         auto result = getValue(VehiclePropValue{.prop = value.prop, .areaId = value.areaId});
1756 
1757         ASSERT_TRUE(result.ok()) << "failed to get property " << value.prop
1758                                  << " status:" << getStatus(result);
1759 
1760         gotValues.push_back(result.value());
1761         VehiclePropValue valueWithNoTimestamp = result.value();
1762         valueWithNoTimestamp.timestamp = 0;
1763 
1764         ASSERT_EQ(valueWithNoTimestamp, value);
1765     }
1766 
1767     // Some of the updated properties might be the same as default config, thus not causing
1768     // a property change event. So the changed properties should be a subset of all the updated
1769     // properties.
1770     ASSERT_THAT(getChangedProperties(), IsSubsetOf(gotValues));
1771 }
1772 
1773 INSTANTIATE_TEST_SUITE_P(
1774         SpecialValuesTests, FakeVehicleHardwareSpecialValuesTest,
1775         testing::ValuesIn(setSpecialValueTestCases()),
__anonf0775ddd0902(const testing::TestParamInfo<FakeVehicleHardwareSpecialValuesTest::ParamType>& info) 1776         [](const testing::TestParamInfo<FakeVehicleHardwareSpecialValuesTest::ParamType>& info) {
1777             return info.param.name;
1778         });
1779 
TEST_F(FakeVehicleHardwareTest,testSetWaitForVhal_alwaysTriggerEvents)1780 TEST_F(FakeVehicleHardwareTest, testSetWaitForVhal_alwaysTriggerEvents) {
1781     int32_t powerReq = toInt(VehicleProperty::AP_POWER_STATE_REQ);
1782     subscribe(powerReq, /*areaId*/ 0, /*sampleRateHz*/ 0);
1783 
1784     int32_t powerReport = toInt(VehicleProperty::AP_POWER_STATE_REPORT);
1785     VehiclePropValue request = VehiclePropValue{
1786             .prop = powerReport,
1787             .value.int32Values = {toInt(VehicleApPowerStateReport::WAIT_FOR_VHAL)},
1788     };
1789     ASSERT_EQ(setValue(request), StatusCode::OK) << "failed to set property " << powerReport;
1790 
1791     // Clear existing events.
1792     clearChangedProperties();
1793 
1794     // Simulate a Car Service crash, Car Service would restart and send the message again.
1795     ASSERT_EQ(setValue(request), StatusCode::OK) << "failed to set property " << powerReport;
1796 
1797     std::vector<VehiclePropValue> events = getChangedProperties();
1798     // Even though the state is already ON, we should receive another ON event.
1799     ASSERT_EQ(events.size(), 1u) << "failed to receive on-change events AP_POWER_STATE_REQ ON";
1800     // Erase the timestamp for comparison.
1801     events[0].timestamp = 0;
1802     auto expectedValue = VehiclePropValue{
1803             .prop = powerReq,
1804             .status = VehiclePropertyStatus::AVAILABLE,
1805             .value.int32Values = {toInt(VehicleApPowerStateReq::ON), 0},
1806     };
1807     ASSERT_EQ(events[0], expectedValue);
1808 }
1809 
TEST_F(FakeVehicleHardwareTest,testGetObd2FreezeFrame)1810 TEST_F(FakeVehicleHardwareTest, testGetObd2FreezeFrame) {
1811     int64_t timestamp = elapsedRealtimeNano();
1812 
1813     auto result = getValue(VehiclePropValue{.prop = OBD2_FREEZE_FRAME_INFO});
1814 
1815     ASSERT_TRUE(result.ok());
1816 
1817     auto propValue = result.value();
1818     ASSERT_GE(propValue.timestamp, timestamp);
1819     ASSERT_EQ(propValue.value.int64Values.size(), static_cast<size_t>(3))
1820             << "expect 3 obd2 freeze frames stored";
1821 
1822     for (int64_t timestamp : propValue.value.int64Values) {
1823         auto freezeFrameResult = getValue(VehiclePropValue{
1824                 .prop = OBD2_FREEZE_FRAME,
1825                 .value.int64Values = {timestamp},
1826         });
1827 
1828         EXPECT_TRUE(result.ok()) << "expect to get freeze frame for timestamp " << timestamp
1829                                  << " ok";
1830         EXPECT_GE(freezeFrameResult.value().timestamp, timestamp);
1831     }
1832 }
1833 
TEST_F(FakeVehicleHardwareTest,testClearObd2FreezeFrame)1834 TEST_F(FakeVehicleHardwareTest, testClearObd2FreezeFrame) {
1835     int64_t timestamp = elapsedRealtimeNano();
1836 
1837     auto getValueResult = getValue(VehiclePropValue{.prop = OBD2_FREEZE_FRAME_INFO});
1838 
1839     ASSERT_TRUE(getValueResult.ok());
1840 
1841     auto propValue = getValueResult.value();
1842     ASSERT_GE(propValue.timestamp, timestamp);
1843     ASSERT_EQ(propValue.value.int64Values.size(), static_cast<size_t>(3))
1844             << "expect 3 obd2 freeze frames stored";
1845 
1846     // No int64Values should clear all freeze frames.
1847     StatusCode status = setValue(VehiclePropValue{.prop = OBD2_FREEZE_FRAME_CLEAR});
1848 
1849     ASSERT_EQ(status, StatusCode::OK);
1850 
1851     getValueResult = getValue(VehiclePropValue{.prop = OBD2_FREEZE_FRAME_INFO});
1852 
1853     ASSERT_TRUE(getValueResult.ok());
1854     ASSERT_EQ(getValueResult.value().value.int64Values.size(), static_cast<size_t>(0))
1855             << "expect 0 obd2 freeze frames after cleared";
1856 }
1857 
TEST_F(FakeVehicleHardwareTest,testSetVehicleMapService)1858 TEST_F(FakeVehicleHardwareTest, testSetVehicleMapService) {
1859     StatusCode status =
1860             setValue(VehiclePropValue{.prop = toInt(VehicleProperty::VEHICLE_MAP_SERVICE)});
1861 
1862     EXPECT_EQ(status, StatusCode::OK);
1863 
1864     auto getValueResult =
1865             getValue(VehiclePropValue{.prop = toInt(VehicleProperty::VEHICLE_MAP_SERVICE)});
1866 
1867     EXPECT_FALSE(getValueResult.ok());
1868     EXPECT_EQ(getValueResult.error(), StatusCode::NOT_AVAILABLE);
1869 }
1870 
TEST_F(FakeVehicleHardwareTest,testGetHvacPropNotAvailable)1871 TEST_F(FakeVehicleHardwareTest, testGetHvacPropNotAvailable) {
1872     FakeVehicleHardwareTestHelper helper(getHardware());
1873     auto hvacPowerOnConfig = std::move(getVehiclePropConfig(toInt(VehicleProperty::HVAC_POWER_ON)));
1874     EXPECT_NE(hvacPowerOnConfig, nullptr);
1875     for (auto& hvacPowerOnAreaConfig : hvacPowerOnConfig->areaConfigs) {
1876         int hvacPowerAreaId = hvacPowerOnAreaConfig.areaId;
1877         // Turn off HVAC_POWER_ON for only 1 area ID
1878         StatusCode status = setValue(VehiclePropValue{.prop = toInt(VehicleProperty::HVAC_POWER_ON),
1879                                                       .areaId = hvacPowerAreaId,
1880                                                       .value.int32Values = {0}});
1881         EXPECT_EQ(status, StatusCode::OK);
1882 
1883         for (auto& powerPropId : helper.getHvacPowerDependentProps()) {
1884             auto powerPropConfig = std::move(getVehiclePropConfig(powerPropId));
1885             EXPECT_NE(powerPropConfig, nullptr);
1886             if (powerPropConfig->access == VehiclePropertyAccess::WRITE) {
1887                 continue;
1888             }
1889             // Try getting a value at each area ID supported by the power dependent property
1890             for (auto& powerPropAreaConfig : powerPropConfig->areaConfigs) {
1891                 int powerDependentAreaId = powerPropAreaConfig.areaId;
1892                 auto getValueResult = getValue(VehiclePropValue{
1893                         .prop = powerPropId,
1894                         .areaId = powerDependentAreaId,
1895                 });
1896 
1897                 // If the current area ID is contained within the HVAC_POWER_ON area ID
1898                 // turned off, then getValue should fail and a StatusCode error should be
1899                 // returned. Otherwise, a value should be returned.
1900                 if ((hvacPowerAreaId & powerDependentAreaId) == powerDependentAreaId) {
1901                     EXPECT_FALSE(getValueResult.ok());
1902                     EXPECT_EQ(getValueResult.error(), StatusCode::NOT_AVAILABLE_DISABLED);
1903                 } else {
1904                     EXPECT_TRUE(getValueResult.ok());
1905                 }
1906             }
1907         }
1908 
1909         // Resetting HVAC_POWER_ON at areaId back to ON state to ensure that there's no dependence
1910         // on this value from any power dependent property values other than those with the same
1911         // areaId.
1912         setValue(VehiclePropValue{.prop = toInt(VehicleProperty::HVAC_POWER_ON),
1913                                   .areaId = hvacPowerAreaId,
1914                                   .value.int32Values = {1}});
1915     }
1916 }
1917 
TEST_F(FakeVehicleHardwareTest,testSetHvacPropNotAvailable)1918 TEST_F(FakeVehicleHardwareTest, testSetHvacPropNotAvailable) {
1919     FakeVehicleHardwareTestHelper helper(getHardware());
1920     auto hvacPowerOnConfig = std::move(getVehiclePropConfig(toInt(VehicleProperty::HVAC_POWER_ON)));
1921     EXPECT_NE(hvacPowerOnConfig, nullptr);
1922     for (auto& hvacPowerOnAreaConfig : hvacPowerOnConfig->areaConfigs) {
1923         int hvacPowerAreaId = hvacPowerOnAreaConfig.areaId;
1924         // Turn off HVAC_POWER_ON for only 1 area ID
1925         StatusCode status = setValue(VehiclePropValue{.prop = toInt(VehicleProperty::HVAC_POWER_ON),
1926                                                       .areaId = hvacPowerAreaId,
1927                                                       .value.int32Values = {0}});
1928         EXPECT_EQ(status, StatusCode::OK);
1929 
1930         for (auto& powerPropId : helper.getHvacPowerDependentProps()) {
1931             auto powerPropConfig = std::move(getVehiclePropConfig(powerPropId));
1932             EXPECT_NE(powerPropConfig, nullptr);
1933             if (powerPropConfig->access == VehiclePropertyAccess::READ) {
1934                 continue;
1935             }
1936             auto propType = getPropType(powerPropId);
1937             // Try setting a value at each area ID supported by the power dependent property
1938             for (auto& powerPropAreaConfig : powerPropConfig->areaConfigs) {
1939                 int powerDependentAreaId = powerPropAreaConfig.areaId;
1940                 auto val = VehiclePropValue{.prop = powerPropId, .areaId = powerDependentAreaId};
1941                 if (propType == VehiclePropertyType::FLOAT) {
1942                     val.value.floatValues.emplace_back(20);
1943                 } else {
1944                     val.value.int32Values.emplace_back(1);
1945                 }
1946                 status = setValue(val);
1947 
1948                 // If the current area ID is contained within the HVAC_POWER_ON area ID
1949                 // turned off, then setValue should fail and a StatusCode error should be
1950                 // returned. Otherwise, an ok StatusCode should be returned.
1951                 if ((hvacPowerAreaId & powerDependentAreaId) == powerDependentAreaId) {
1952                     EXPECT_EQ(status, StatusCode::NOT_AVAILABLE_DISABLED);
1953                 } else {
1954                     EXPECT_EQ(status, StatusCode::OK);
1955                 }
1956             }
1957         }
1958 
1959         // Resetting HVAC_POWER_ON at areaId back to ON state to ensure that there's no dependence
1960         // on this value from any power dependent property values other than those with the same
1961         // areaId.
1962         setValue(VehiclePropValue{.prop = toInt(VehicleProperty::HVAC_POWER_ON),
1963                                   .areaId = hvacPowerAreaId,
1964                                   .value.int32Values = {1}});
1965     }
1966 }
1967 
TEST_F(FakeVehicleHardwareTest,testHvacPowerOnSendCurrentHvacPropValues)1968 TEST_F(FakeVehicleHardwareTest, testHvacPowerOnSendCurrentHvacPropValues) {
1969     FakeVehicleHardwareTestHelper helper(getHardware());
1970     auto hvacPowerOnConfig = std::move(getVehiclePropConfig(toInt(VehicleProperty::HVAC_POWER_ON)));
1971     EXPECT_NE(hvacPowerOnConfig, nullptr);
1972     for (auto& hvacPowerOnAreaConfig : hvacPowerOnConfig->areaConfigs) {
1973         int hvacPowerAreaId = hvacPowerOnAreaConfig.areaId;
1974         StatusCode status = setValue(VehiclePropValue{.prop = toInt(VehicleProperty::HVAC_POWER_ON),
1975                                                       .areaId = hvacPowerAreaId,
1976                                                       .value.int32Values = {0}});
1977         EXPECT_EQ(status, StatusCode::OK);
1978         auto events = getChangedProperties();
1979         for (const auto& event : events) {
1980             // Ignore HVAC_POWER_ON event
1981             if (event.prop == toInt(VehicleProperty::HVAC_POWER_ON)) {
1982                 continue;
1983             }
1984             EXPECT_THAT(event.prop, AnyOfArray(helper.getHvacPowerDependentProps()));
1985             EXPECT_EQ((hvacPowerAreaId & event.areaId), hvacPowerAreaId);
1986             EXPECT_EQ(event.status, VehiclePropertyStatus::UNAVAILABLE);
1987         }
1988         clearChangedProperties();
1989 
1990         status = setValue(VehiclePropValue{.prop = toInt(VehicleProperty::HVAC_POWER_ON),
1991                                            .areaId = hvacPowerAreaId,
1992                                            .value.int32Values = {1}});
1993         EXPECT_EQ(status, StatusCode::OK);
1994         events = getChangedProperties();
1995         for (const auto& event : events) {
1996             // Ignore HVAC_POWER_ON event
1997             if (event.prop == toInt(VehicleProperty::HVAC_POWER_ON)) {
1998                 continue;
1999             }
2000             EXPECT_THAT(event.prop, AnyOfArray(helper.getHvacPowerDependentProps()));
2001             EXPECT_EQ((hvacPowerAreaId & event.areaId), hvacPowerAreaId);
2002             EXPECT_EQ(event.status, VehiclePropertyStatus::AVAILABLE);
2003         }
2004         clearChangedProperties();
2005     }
2006 }
2007 
TEST_F(FakeVehicleHardwareTest,testHvacDualOnSynchronizesTemp)2008 TEST_F(FakeVehicleHardwareTest, testHvacDualOnSynchronizesTemp) {
2009     auto hvacDualOnConfig = std::move(getVehiclePropConfig(toInt(VehicleProperty::HVAC_DUAL_ON)));
2010     auto hvacTemperatureSetConfig =
2011             std::move(getVehiclePropConfig(toInt(VehicleProperty::HVAC_TEMPERATURE_SET)));
2012     EXPECT_NE(hvacDualOnConfig, nullptr);
2013     EXPECT_NE(hvacTemperatureSetConfig, nullptr);
2014     for (auto& hvacTemperatureSetConfig : hvacTemperatureSetConfig->areaConfigs) {
2015         int32_t hvacTemperatureSetAreaId = hvacTemperatureSetConfig.areaId;
2016         subscribe(toInt(VehicleProperty::HVAC_TEMPERATURE_SET), hvacTemperatureSetAreaId,
2017                   /*sampleRateHz*/ 0);
2018     }
2019     for (auto& hvacDualOnConfig : hvacDualOnConfig->areaConfigs) {
2020         int32_t hvacDualOnAreaId = hvacDualOnConfig.areaId;
2021         subscribe(toInt(VehicleProperty::HVAC_DUAL_ON), hvacDualOnAreaId, /*sampleRateHz*/ 0);
2022         StatusCode status = setValue(VehiclePropValue{.prop = toInt(VehicleProperty::HVAC_DUAL_ON),
2023                                                       .areaId = hvacDualOnAreaId,
2024                                                       .value.int32Values = {1}});
2025         EXPECT_EQ(status, StatusCode::OK);
2026 
2027         // Verify there's an event for all HVAC_TEMPERATURE_SET
2028         // area IDs covered by the HVAC_DUAL_ON area ID
2029         auto events = getChangedProperties();
2030         std::unordered_set<float> temperatureValues;
2031         for (const auto& event : events) {
2032             // Ignore HVAC_DUAL_ON event
2033             if (event.prop == toInt(VehicleProperty::HVAC_DUAL_ON)) {
2034                 continue;
2035             }
2036             EXPECT_EQ(event.prop, toInt(VehicleProperty::HVAC_TEMPERATURE_SET));
2037             EXPECT_EQ((hvacDualOnAreaId & event.areaId), event.areaId);
2038             EXPECT_EQ(1u, event.value.floatValues.size());
2039             temperatureValues.insert(event.value.floatValues[0]);
2040         }
2041         // Verify that the temperature value is the same for all events
2042         // Ie the temperature in all area IDs are synchronized
2043         EXPECT_EQ(1u, temperatureValues.size());
2044         clearChangedProperties();
2045 
2046         // Verify when any HVAC_TEMPERATURE_SET area ID is changed all
2047         // area IDs covered by the HVAC_DUAL_ON area ID are also changed
2048         for (auto& hvacTemperatureSetConfig : hvacTemperatureSetConfig->areaConfigs) {
2049             int32_t hvacTemperatureSetAreaId = hvacTemperatureSetConfig.areaId;
2050             if ((hvacDualOnAreaId & hvacTemperatureSetAreaId) != hvacTemperatureSetAreaId) {
2051                 continue;
2052             }
2053             float expectedValue = 25;
2054             status = setValue(VehiclePropValue{.prop = toInt(VehicleProperty::HVAC_TEMPERATURE_SET),
2055                                                .areaId = hvacTemperatureSetAreaId,
2056                                                .value.floatValues = {expectedValue}});
2057             EXPECT_EQ(status, StatusCode::OK);
2058             events = getChangedProperties();
2059             for (const auto& event : events) {
2060                 EXPECT_EQ(event.prop, toInt(VehicleProperty::HVAC_TEMPERATURE_SET));
2061                 EXPECT_EQ(1u, event.value.floatValues.size());
2062                 EXPECT_EQ(expectedValue, event.value.floatValues[0]);
2063             }
2064             clearChangedProperties();
2065         }
2066 
2067         status = setValue(VehiclePropValue{.prop = toInt(VehicleProperty::HVAC_DUAL_ON),
2068                                            .areaId = hvacDualOnAreaId,
2069                                            .value.int32Values = {0}});
2070         EXPECT_EQ(status, StatusCode::OK);
2071 
2072         // When HVAC_DUAL_ON is disabled, there should be no events created
2073         // for HVAC_TEMPERATURE_SET ie no temperature synchronization.
2074         events = getChangedProperties();
2075         EXPECT_EQ(1u, events.size());
2076         EXPECT_EQ(events[0].prop, toInt(VehicleProperty::HVAC_DUAL_ON));
2077         EXPECT_EQ(events[0].areaId, hvacDualOnAreaId);
2078         clearChangedProperties();
2079 
2080         // Verify when any HVAC_TEMPERATURE_SET area ID is
2081         // changed other area IDs do not change.
2082         for (auto& hvacTemperatureSetConfig : hvacTemperatureSetConfig->areaConfigs) {
2083             int32_t hvacTemperatureSetAreaId = hvacTemperatureSetConfig.areaId;
2084             if ((hvacDualOnAreaId & hvacTemperatureSetAreaId) != hvacTemperatureSetAreaId) {
2085                 continue;
2086             }
2087             float expectedValue = 24;
2088             status = setValue(VehiclePropValue{.prop = toInt(VehicleProperty::HVAC_TEMPERATURE_SET),
2089                                                .areaId = hvacTemperatureSetAreaId,
2090                                                .value.floatValues = {expectedValue}});
2091             EXPECT_EQ(status, StatusCode::OK);
2092             events = getChangedProperties();
2093             EXPECT_EQ(1u, events.size());
2094             EXPECT_EQ(events[0].prop, toInt(VehicleProperty::HVAC_TEMPERATURE_SET));
2095             EXPECT_EQ(events[0].areaId, hvacTemperatureSetAreaId);
2096             EXPECT_EQ(1u, events[0].value.floatValues.size());
2097             EXPECT_EQ(expectedValue, events[0].value.floatValues[0]);
2098             clearChangedProperties();
2099         }
2100     }
2101 }
2102 
TEST_F(FakeVehicleHardwareTest,testGetAdasPropNotAvailable)2103 TEST_F(FakeVehicleHardwareTest, testGetAdasPropNotAvailable) {
2104     std::unordered_map<int32_t, std::vector<int32_t>> adasEnabledPropToDependentProps = {
2105             {
2106                     toInt(VehicleProperty::CRUISE_CONTROL_ENABLED),
2107                     {
2108                             toInt(VehicleProperty::CRUISE_CONTROL_TARGET_SPEED),
2109                             toInt(VehicleProperty::ADAPTIVE_CRUISE_CONTROL_TARGET_TIME_GAP),
2110                             toInt(VehicleProperty::
2111                                           ADAPTIVE_CRUISE_CONTROL_LEAD_VEHICLE_MEASURED_DISTANCE),
2112                     },
2113             },
2114     };
2115     for (auto& enabledToDependents : adasEnabledPropToDependentProps) {
2116         int32_t adasEnabledPropertyId = enabledToDependents.first;
2117         StatusCode status =
2118                 setValue(VehiclePropValue{.prop = adasEnabledPropertyId, .value.int32Values = {0}});
2119         EXPECT_EQ(status, StatusCode::OK);
2120 
2121         auto& dependentProps = enabledToDependents.second;
2122         for (auto dependentProp : dependentProps) {
2123             auto getValueResult = getValue(VehiclePropValue{.prop = dependentProp});
2124             EXPECT_FALSE(getValueResult.ok());
2125             EXPECT_EQ(getValueResult.error(), StatusCode::NOT_AVAILABLE_DISABLED);
2126         }
2127     }
2128 }
2129 
TEST_F(FakeVehicleHardwareTest,testSetAdasPropNotAvailable)2130 TEST_F(FakeVehicleHardwareTest, testSetAdasPropNotAvailable) {
2131     std::unordered_map<int32_t, std::vector<int32_t>> adasEnabledPropToDependentProps = {
2132             {
2133                     toInt(VehicleProperty::LANE_CENTERING_ASSIST_ENABLED),
2134                     {
2135                             toInt(VehicleProperty::LANE_CENTERING_ASSIST_COMMAND),
2136                     },
2137             },
2138             {
2139                     toInt(VehicleProperty::CRUISE_CONTROL_ENABLED),
2140                     {
2141                             toInt(VehicleProperty::CRUISE_CONTROL_COMMAND),
2142                             toInt(VehicleProperty::ADAPTIVE_CRUISE_CONTROL_TARGET_TIME_GAP),
2143                     },
2144             },
2145     };
2146     for (auto& enabledToDependents : adasEnabledPropToDependentProps) {
2147         int32_t adasEnabledPropertyId = enabledToDependents.first;
2148         StatusCode status =
2149                 setValue(VehiclePropValue{.prop = adasEnabledPropertyId, .value.int32Values = {0}});
2150         EXPECT_EQ(status, StatusCode::OK);
2151 
2152         auto& dependentProps = enabledToDependents.second;
2153         for (auto dependentProp : dependentProps) {
2154             StatusCode status = setValue(VehiclePropValue{.prop = dependentProp});
2155             EXPECT_EQ(status, StatusCode::NOT_AVAILABLE_DISABLED);
2156         }
2157     }
2158 }
2159 
TEST_F(FakeVehicleHardwareTest,testGetAccPropertiesOnStandardCc)2160 TEST_F(FakeVehicleHardwareTest, testGetAccPropertiesOnStandardCc) {
2161     std::vector<int32_t> ccTypeDependentProperties = {
2162             toInt(VehicleProperty::ADAPTIVE_CRUISE_CONTROL_TARGET_TIME_GAP),
2163             toInt(VehicleProperty::ADAPTIVE_CRUISE_CONTROL_LEAD_VEHICLE_MEASURED_DISTANCE),
2164     };
2165 
2166     StatusCode status =
2167             setValue(VehiclePropValue{.prop = toInt(VehicleProperty::CRUISE_CONTROL_TYPE),
2168                                       .value.int32Values = {toInt(CruiseControlType::STANDARD)}});
2169     EXPECT_EQ(status, StatusCode::OK);
2170 
2171     for (int32_t dependentProp : ccTypeDependentProperties) {
2172         auto getValueResult = getValue(VehiclePropValue{.prop = dependentProp});
2173         EXPECT_FALSE(getValueResult.ok());
2174         EXPECT_EQ(getValueResult.error(), StatusCode::NOT_AVAILABLE_DISABLED);
2175     }
2176 }
2177 
TEST_F(FakeVehicleHardwareTest,testSetAccPropertiesOnStandardCc)2178 TEST_F(FakeVehicleHardwareTest, testSetAccPropertiesOnStandardCc) {
2179     std::vector<VehiclePropValue> testVehiclePropValues = {
2180             VehiclePropValue{
2181                     .prop = toInt(VehicleProperty::ADAPTIVE_CRUISE_CONTROL_TARGET_TIME_GAP),
2182                     .value.int32Values = {3}},
2183             VehiclePropValue{
2184                     .prop = toInt(VehicleProperty::CRUISE_CONTROL_COMMAND),
2185                     .value.int32Values = {toInt(CruiseControlCommand::INCREASE_TARGET_TIME_GAP)}},
2186             VehiclePropValue{
2187                     .prop = toInt(VehicleProperty::CRUISE_CONTROL_COMMAND),
2188                     .value.int32Values = {toInt(CruiseControlCommand::DECREASE_TARGET_TIME_GAP)}}};
2189 
2190     StatusCode status =
2191             setValue(VehiclePropValue{.prop = toInt(VehicleProperty::CRUISE_CONTROL_TYPE),
2192                                       .value.int32Values = {toInt(CruiseControlType::STANDARD)}});
2193     EXPECT_EQ(status, StatusCode::OK);
2194 
2195     for (auto value : testVehiclePropValues) {
2196         status = setValue(value);
2197         EXPECT_EQ(status, StatusCode::NOT_AVAILABLE_DISABLED);
2198     }
2199 }
2200 
TEST_F(FakeVehicleHardwareTest,testSendAdasPropertiesState)2201 TEST_F(FakeVehicleHardwareTest, testSendAdasPropertiesState) {
2202     std::unordered_map<int32_t, std::vector<int32_t>> adasEnabledPropToAdasPropWithErrorState = {
2203             // AEB
2204             {
2205                     toInt(VehicleProperty::AUTOMATIC_EMERGENCY_BRAKING_ENABLED),
2206                     {
2207                             toInt(VehicleProperty::AUTOMATIC_EMERGENCY_BRAKING_STATE),
2208                     },
2209             },
2210             // FCW
2211             {
2212                     toInt(VehicleProperty::FORWARD_COLLISION_WARNING_ENABLED),
2213                     {
2214                             toInt(VehicleProperty::FORWARD_COLLISION_WARNING_STATE),
2215                     },
2216             },
2217             // BSW
2218             {
2219                     toInt(VehicleProperty::BLIND_SPOT_WARNING_ENABLED),
2220                     {
2221                             toInt(VehicleProperty::BLIND_SPOT_WARNING_STATE),
2222                     },
2223             },
2224             // LDW
2225             {
2226                     toInt(VehicleProperty::LANE_DEPARTURE_WARNING_ENABLED),
2227                     {
2228                             toInt(VehicleProperty::LANE_DEPARTURE_WARNING_STATE),
2229                     },
2230             },
2231             // LKA
2232             {
2233                     toInt(VehicleProperty::LANE_KEEP_ASSIST_ENABLED),
2234                     {
2235                             toInt(VehicleProperty::LANE_KEEP_ASSIST_STATE),
2236                     },
2237             },
2238             // LCA
2239             {
2240                     toInt(VehicleProperty::LANE_CENTERING_ASSIST_ENABLED),
2241                     {
2242                             toInt(VehicleProperty::LANE_CENTERING_ASSIST_STATE),
2243                     },
2244             },
2245             // ELKA
2246             {
2247                     toInt(VehicleProperty::EMERGENCY_LANE_KEEP_ASSIST_ENABLED),
2248                     {
2249                             toInt(VehicleProperty::EMERGENCY_LANE_KEEP_ASSIST_STATE),
2250                     },
2251             },
2252             // CC
2253             {
2254                     toInt(VehicleProperty::CRUISE_CONTROL_ENABLED),
2255                     {
2256                             toInt(VehicleProperty::CRUISE_CONTROL_TYPE),
2257                             toInt(VehicleProperty::CRUISE_CONTROL_STATE),
2258                     },
2259             },
2260             // HOD
2261             {
2262                     toInt(VehicleProperty::HANDS_ON_DETECTION_ENABLED),
2263                     {
2264                             toInt(VehicleProperty::HANDS_ON_DETECTION_DRIVER_STATE),
2265                             toInt(VehicleProperty::HANDS_ON_DETECTION_WARNING),
2266                     },
2267             },
2268             // LSCW
2269             {
2270                     toInt(VehicleProperty::LOW_SPEED_COLLISION_WARNING_ENABLED),
2271                     {
2272                             toInt(VehicleProperty::LOW_SPEED_COLLISION_WARNING_STATE),
2273                     },
2274             },
2275             // ESC
2276             {
2277                     toInt(VehicleProperty::ELECTRONIC_STABILITY_CONTROL_ENABLED),
2278                     {
2279                             toInt(VehicleProperty::ELECTRONIC_STABILITY_CONTROL_STATE),
2280                     },
2281             },
2282     };
2283 
2284     // First subscribe to all the properties that we will change.
2285     for (auto& enabledToErrorStateProps : adasEnabledPropToAdasPropWithErrorState) {
2286         std::unordered_set<int32_t> expectedChangedPropIds(enabledToErrorStateProps.second.begin(),
2287                                                            enabledToErrorStateProps.second.end());
2288         expectedChangedPropIds.insert(enabledToErrorStateProps.first);
2289 
2290         for (int32_t propId : expectedChangedPropIds) {
2291             int32_t areaId = 0;
2292             if (propId == toInt(VehicleProperty::BLIND_SPOT_WARNING_STATE)) {
2293                 areaId = toInt(VehicleAreaMirror::DRIVER_LEFT);
2294             }
2295             subscribe(propId, areaId, /*sampleRateHz*/ 0);
2296         }
2297     }
2298 
2299     for (auto& enabledToErrorStateProps : adasEnabledPropToAdasPropWithErrorState) {
2300         int32_t adasEnabledPropertyId = enabledToErrorStateProps.first;
2301         StatusCode status =
2302                 setValue(VehiclePropValue{.prop = adasEnabledPropertyId, .value.int32Values = {0}});
2303         EXPECT_EQ(status, StatusCode::OK);
2304 
2305         clearChangedProperties();
2306         status =
2307                 setValue(VehiclePropValue{.prop = adasEnabledPropertyId, .value.int32Values = {1}});
2308         EXPECT_EQ(status, StatusCode::OK);
2309 
2310         // If we enable the ADAS feature, we expect to receive one property event for every ADAS
2311         // state property plus one event for enabling the feature.
2312         std::unordered_set<int32_t> expectedChangedPropIds(enabledToErrorStateProps.second.begin(),
2313                                                            enabledToErrorStateProps.second.end());
2314         expectedChangedPropIds.insert(adasEnabledPropertyId);
2315 
2316         std::unordered_set<int32_t> changedPropIds;
2317         auto events = getChangedProperties();
2318         for (const auto& event : events) {
2319             changedPropIds.insert(event.prop);
2320         }
2321         EXPECT_EQ(changedPropIds, expectedChangedPropIds);
2322     }
2323 }
2324 
TEST_F(FakeVehicleHardwareTest,testGetUserPropertySetOnly)2325 TEST_F(FakeVehicleHardwareTest, testGetUserPropertySetOnly) {
2326     for (VehicleProperty prop : std::vector<VehicleProperty>({
2327                  VehicleProperty::INITIAL_USER_INFO,
2328                  VehicleProperty::SWITCH_USER,
2329                  VehicleProperty::CREATE_USER,
2330                  VehicleProperty::REMOVE_USER,
2331          })) {
2332         auto result = getValue(VehiclePropValue{.prop = toInt(prop)});
2333 
2334         EXPECT_FALSE(result.ok());
2335         if (!result.ok()) {
2336             EXPECT_EQ(result.error(), StatusCode::INVALID_ARG);
2337         }
2338     }
2339 }
2340 
TEST_F(FakeVehicleHardwareTest,testGetUserIdAssoc)2341 TEST_F(FakeVehicleHardwareTest, testGetUserIdAssoc) {
2342     int32_t userIdAssocProp = toInt(VehicleProperty::USER_IDENTIFICATION_ASSOCIATION);
2343 
2344     auto result = getValue(VehiclePropValue{.prop = userIdAssocProp});
2345 
2346     // Default returns NOT_AVAILABLE.
2347     ASSERT_FALSE(result.ok());
2348     ASSERT_EQ(result.error(), StatusCode::NOT_AVAILABLE);
2349 
2350     // This is the same example as used in User HAL Emulation doc.
2351     VehiclePropValue valueToSet = {
2352             .prop = toInt(VehicleProperty::USER_IDENTIFICATION_ASSOCIATION),
2353             .areaId = 1,
2354             .value.int32Values = {666, 1, 1, 2},
2355     };
2356 
2357     StatusCode status = setValue(valueToSet);
2358 
2359     ASSERT_EQ(status, StatusCode::OK);
2360 
2361     result = getValue(VehiclePropValue{
2362             .prop = userIdAssocProp,
2363             // Request ID
2364             .value.int32Values = {1},
2365     });
2366 
2367     ASSERT_TRUE(result.ok());
2368 
2369     auto& gotValue = result.value();
2370     gotValue.timestamp = 0;
2371 
2372     // Expect to get the same request ID.
2373     valueToSet.value.int32Values[0] = 1;
2374 
2375     ASSERT_EQ(gotValue, valueToSet);
2376 }
2377 
TEST_F(FakeVehicleHardwareTest,testSwitchUser)2378 TEST_F(FakeVehicleHardwareTest, testSwitchUser) {
2379     SubscribeOptions options;
2380     int32_t propSwitchUser = toInt(VehicleProperty::SWITCH_USER);
2381     options.propId = propSwitchUser;
2382     options.areaIds = {0, 1};
2383     ASSERT_EQ(StatusCode::OK, getHardware()->subscribe(options))
2384             << "failed to subscribe to propId: " << propSwitchUser;
2385 
2386     // This is the same example as used in User HAL Emulation doc.
2387     VehiclePropValue valueToSet = {
2388             .prop = propSwitchUser,
2389             .areaId = 1,
2390             .value.int32Values = {666, 3, 2},
2391     };
2392 
2393     StatusCode status = setValue(valueToSet);
2394 
2395     ASSERT_EQ(status, StatusCode::OK);
2396 
2397     // Simulate a request from Android side.
2398     VehiclePropValue switchUserRequest = {
2399             .prop = propSwitchUser,
2400             .areaId = 0,
2401             .value.int32Values = {666, 3},
2402     };
2403     // Clear existing events.
2404     clearChangedProperties();
2405 
2406     status = setValue(switchUserRequest);
2407 
2408     ASSERT_EQ(status, StatusCode::OK);
2409 
2410     // Should generate an event for user hal response.
2411     auto events = getChangedProperties();
2412     ASSERT_EQ(events.size(), static_cast<size_t>(1));
2413 
2414     events[0].timestamp = 0;
2415     // The returned event will have area ID 0.
2416     valueToSet.areaId = 0;
2417     ASSERT_EQ(events[0], valueToSet);
2418 
2419     // Try to get switch_user again, should return default value.
2420     clearChangedProperties();
2421     status = setValue(switchUserRequest);
2422     ASSERT_EQ(status, StatusCode::OK);
2423 
2424     events = getChangedProperties();
2425     ASSERT_EQ(events.size(), static_cast<size_t>(1));
2426     events[0].timestamp = 0;
2427     auto expectedValue = VehiclePropValue{
2428             .areaId = 0,
2429             .prop = propSwitchUser,
2430             .value.int32Values =
2431                     {
2432                             // Request ID
2433                             666,
2434                             // VEHICLE_RESPONSE
2435                             3,
2436                             // SUCCESS
2437                             1,
2438                     },
2439     };
2440     ASSERT_EQ(events[0], expectedValue);
2441 }
2442 
TEST_F(FakeVehicleHardwareTest,testCreateUser)2443 TEST_F(FakeVehicleHardwareTest, testCreateUser) {
2444     SubscribeOptions options;
2445     int32_t propCreateUser = toInt(VehicleProperty::CREATE_USER);
2446     options.propId = propCreateUser;
2447     options.areaIds = {0, 1};
2448     ASSERT_EQ(StatusCode::OK, getHardware()->subscribe(options))
2449             << "failed to subscribe to propId: " << propCreateUser;
2450 
2451     // This is the same example as used in User HAL Emulation doc.
2452     VehiclePropValue valueToSet = {
2453             .prop = toInt(VehicleProperty::CREATE_USER),
2454             .areaId = 1,
2455             .value.int32Values = {666, 2},
2456     };
2457 
2458     StatusCode status = setValue(valueToSet);
2459 
2460     ASSERT_EQ(status, StatusCode::OK);
2461 
2462     // Simulate a request from Android side.
2463     VehiclePropValue createUserRequest = {
2464             .prop = propCreateUser,
2465             .areaId = 0,
2466             .value.int32Values = {666},
2467     };
2468     // Clear existing events.
2469     clearChangedProperties();
2470 
2471     status = setValue(createUserRequest);
2472 
2473     ASSERT_EQ(status, StatusCode::OK);
2474 
2475     // Should generate an event for user hal response.
2476     auto events = getChangedProperties();
2477     ASSERT_EQ(events.size(), static_cast<size_t>(1));
2478     events[0].timestamp = 0;
2479     // The returned event will have area ID 0.
2480     valueToSet.areaId = 0;
2481     EXPECT_EQ(events[0], valueToSet);
2482 
2483     // Try to get create_user again, should return default value.
2484     clearChangedProperties();
2485     status = setValue(createUserRequest);
2486     ASSERT_EQ(status, StatusCode::OK);
2487 
2488     events = getChangedProperties();
2489     ASSERT_EQ(events.size(), static_cast<size_t>(1));
2490     events[0].timestamp = 0;
2491     auto expectedValue = VehiclePropValue{
2492             .areaId = 0,
2493             .prop = propCreateUser,
2494             .value.int32Values =
2495                     {
2496                             // Request ID
2497                             666,
2498                             // SUCCESS
2499                             1,
2500                     },
2501     };
2502     ASSERT_EQ(events[0], expectedValue);
2503 }
2504 
TEST_F(FakeVehicleHardwareTest,testInitialUserInfo)2505 TEST_F(FakeVehicleHardwareTest, testInitialUserInfo) {
2506     SubscribeOptions options;
2507     int32_t propInitialUserInfo = toInt(VehicleProperty::INITIAL_USER_INFO);
2508     options.propId = propInitialUserInfo;
2509     options.areaIds = {0, 1};
2510     ASSERT_EQ(StatusCode::OK, getHardware()->subscribe(options))
2511             << "failed to subscribe to propId: " << propInitialUserInfo;
2512 
2513     // This is the same example as used in User HAL Emulation doc.
2514     VehiclePropValue valueToSet = {
2515             .prop = propInitialUserInfo,
2516             .areaId = 1,
2517             .value.int32Values = {666, 1, 11},
2518     };
2519 
2520     StatusCode status = setValue(valueToSet);
2521 
2522     ASSERT_EQ(status, StatusCode::OK);
2523 
2524     // Simulate a request from Android side.
2525     VehiclePropValue initialUserInfoRequest = {
2526             .prop = propInitialUserInfo,
2527             .areaId = 0,
2528             .value.int32Values = {3},
2529     };
2530     // Clear existing events.
2531     clearChangedProperties();
2532 
2533     status = setValue(initialUserInfoRequest);
2534 
2535     ASSERT_EQ(status, StatusCode::OK);
2536 
2537     // Should generate an event for user hal response.
2538     auto events = getChangedProperties();
2539     ASSERT_EQ(events.size(), static_cast<size_t>(1));
2540     events[0].timestamp = 0;
2541     auto expectedValue = VehiclePropValue{
2542             .areaId = 0,
2543             .prop = propInitialUserInfo,
2544             .value.int32Values = {3, 1, 11},
2545     };
2546     EXPECT_EQ(events[0], expectedValue);
2547 
2548     // Try to get create_user again, should return default value.
2549     clearChangedProperties();
2550     status = setValue(initialUserInfoRequest);
2551     ASSERT_EQ(status, StatusCode::OK);
2552 
2553     events = getChangedProperties();
2554     ASSERT_EQ(events.size(), static_cast<size_t>(1));
2555     events[0].timestamp = 0;
2556     expectedValue = VehiclePropValue{
2557             .areaId = 0,
2558             .prop = propInitialUserInfo,
2559             .value.int32Values =
2560                     {
2561                             // Request ID
2562                             3,
2563                             // ACTION: DEFAULT
2564                             0,
2565                             // User id: 0
2566                             0,
2567                             // Flags: 0
2568                             0,
2569                     },
2570             .value.stringValue = "||",
2571     };
2572     EXPECT_EQ(events[0], expectedValue);
2573 }
2574 
TEST_F(FakeVehicleHardwareTest,testDumpAllProperties)2575 TEST_F(FakeVehicleHardwareTest, testDumpAllProperties) {
2576     std::vector<std::string> options;
2577     DumpResult result = getHardware()->dump(options);
2578     ASSERT_TRUE(result.callerShouldDumpState);
2579     ASSERT_NE(result.buffer, "");
2580     ASSERT_THAT(result.buffer, ContainsRegex("dumping .+ properties"));
2581 }
2582 
TEST_F(FakeVehicleHardwareTest,testDumpHelp)2583 TEST_F(FakeVehicleHardwareTest, testDumpHelp) {
2584     std::vector<std::string> options;
2585     options.push_back("--help");
2586     DumpResult result = getHardware()->dump(options);
2587     ASSERT_FALSE(result.callerShouldDumpState);
2588     ASSERT_NE(result.buffer, "");
2589     ASSERT_THAT(result.buffer, ContainsRegex("Usage: "));
2590 }
2591 
TEST_F(FakeVehicleHardwareTest,testDumpListProperties)2592 TEST_F(FakeVehicleHardwareTest, testDumpListProperties) {
2593     std::vector<std::string> options;
2594     options.push_back("--list");
2595     DumpResult result = getHardware()->dump(options);
2596     ASSERT_FALSE(result.callerShouldDumpState);
2597     ASSERT_NE(result.buffer, "");
2598     ASSERT_THAT(result.buffer, ContainsRegex("listing .+ properties"));
2599 }
2600 
TEST_F(FakeVehicleHardwareTest,testDumpSpecificProperties)2601 TEST_F(FakeVehicleHardwareTest, testDumpSpecificProperties) {
2602     std::vector<std::string> options;
2603     options.push_back("--get");
2604     std::string prop1 = std::to_string(toInt(VehicleProperty::INFO_FUEL_CAPACITY));
2605     std::string prop2 = std::to_string(toInt(VehicleProperty::TIRE_PRESSURE));
2606     options.push_back(prop1);
2607     options.push_back(prop2);
2608     DumpResult result = getHardware()->dump(options);
2609     ASSERT_FALSE(result.callerShouldDumpState);
2610     ASSERT_NE(result.buffer, "");
2611     ASSERT_THAT(result.buffer,
2612                 ContainsRegex(StringPrintf("1:.*prop: %s.*\n2-0:.*prop: %s.*\n2-1:.*prop: %s.*\n",
2613                                            prop1.c_str(), prop2.c_str(), prop2.c_str())));
2614 }
2615 
TEST_F(FakeVehicleHardwareTest,testDumpSpecificPropertiesWithName)2616 TEST_F(FakeVehicleHardwareTest, testDumpSpecificPropertiesWithName) {
2617     std::vector<std::string> options;
2618     options.push_back("--get");
2619     std::string prop1 = "INFO_FUEL_CAPACITY";
2620     std::string prop2 = "TIRE_PRESSURE";
2621     int prop1Int = toInt(VehicleProperty::INFO_FUEL_CAPACITY);
2622     int prop2Int = toInt(VehicleProperty::TIRE_PRESSURE);
2623     options.push_back(prop1);
2624     options.push_back(prop2);
2625     DumpResult result = getHardware()->dump(options);
2626     ASSERT_FALSE(result.callerShouldDumpState);
2627     ASSERT_NE(result.buffer, "");
2628     ASSERT_THAT(result.buffer,
2629                 ContainsRegex(StringPrintf("1:.*prop: %d.*\n2-0:.*prop: %d.*\n2-1:.*prop: %d.*\n",
2630                                            prop1Int, prop2Int, prop2Int)));
2631 }
2632 
TEST_F(FakeVehicleHardwareTest,testDumpSpecificPropertiesInvalidProp)2633 TEST_F(FakeVehicleHardwareTest, testDumpSpecificPropertiesInvalidProp) {
2634     std::vector<std::string> options;
2635     options.push_back("--get");
2636     std::string prop1 = std::to_string(toInt(VehicleProperty::INFO_FUEL_CAPACITY));
2637     std::string prop2 = std::to_string(INVALID_PROP_ID);
2638     options.push_back(prop1);
2639     options.push_back(prop2);
2640     DumpResult result = getHardware()->dump(options);
2641     ASSERT_FALSE(result.callerShouldDumpState);
2642     ASSERT_NE(result.buffer, "");
2643     ASSERT_THAT(result.buffer, ContainsRegex(StringPrintf("1:.*prop: %s.*\nNo property INVALID\n",
2644                                                           prop1.c_str())));
2645 }
2646 
TEST_F(FakeVehicleHardwareTest,testDumpSpecificPropertiesNoArg)2647 TEST_F(FakeVehicleHardwareTest, testDumpSpecificPropertiesNoArg) {
2648     std::vector<std::string> options;
2649     options.push_back("--get");
2650 
2651     // No arguments.
2652     DumpResult result = getHardware()->dump(options);
2653     ASSERT_FALSE(result.callerShouldDumpState);
2654     ASSERT_NE(result.buffer, "");
2655     ASSERT_THAT(result.buffer, ContainsRegex("Invalid number of arguments"));
2656 }
2657 
TEST_F(FakeVehicleHardwareTest,testDumpSpecificPropertyWithArg)2658 TEST_F(FakeVehicleHardwareTest, testDumpSpecificPropertyWithArg) {
2659     auto getValueResult = getValue(VehiclePropValue{.prop = OBD2_FREEZE_FRAME_INFO});
2660     ASSERT_TRUE(getValueResult.ok());
2661     auto propValue = getValueResult.value();
2662     ASSERT_EQ(propValue.value.int64Values.size(), static_cast<size_t>(3))
2663             << "expect 3 obd2 freeze frames stored";
2664 
2665     std::string propIdStr = StringPrintf("%d", OBD2_FREEZE_FRAME);
2666     DumpResult result;
2667     for (int64_t timestamp : propValue.value.int64Values) {
2668         result = getHardware()->dump(
2669                 {"--getWithArg", propIdStr, "-i64", StringPrintf("%" PRId64, timestamp)});
2670 
2671         ASSERT_FALSE(result.callerShouldDumpState);
2672         ASSERT_NE(result.buffer, "");
2673         ASSERT_THAT(result.buffer, ContainsRegex("Get property result:"));
2674     }
2675 
2676     // Set the timestamp argument to 0.
2677     result = getHardware()->dump({"--getWithArg", propIdStr, "-i64", "0"});
2678 
2679     ASSERT_FALSE(result.callerShouldDumpState);
2680     // There is no freeze obd2 frame at timestamp 0.
2681     ASSERT_THAT(result.buffer, ContainsRegex("failed to read property value"));
2682 }
2683 
TEST_F(FakeVehicleHardwareTest,testSaveRestoreProp)2684 TEST_F(FakeVehicleHardwareTest, testSaveRestoreProp) {
2685     int32_t prop = toInt(VehicleProperty::TIRE_PRESSURE);
2686     std::string propIdStr = std::to_string(prop);
2687     std::string areaIdStr = std::to_string(WHEEL_FRONT_LEFT);
2688 
2689     DumpResult result = getHardware()->dump({"--save-prop", propIdStr, "-a", areaIdStr});
2690 
2691     ASSERT_FALSE(result.callerShouldDumpState);
2692     ASSERT_THAT(result.buffer, ContainsRegex("saved"));
2693 
2694     ASSERT_EQ(setValue(VehiclePropValue{
2695                       .prop = prop,
2696                       .areaId = WHEEL_FRONT_LEFT,
2697                       .value =
2698                               {
2699                                       .floatValues = {210.0},
2700                               },
2701               }),
2702               StatusCode::OK);
2703 
2704     result = getHardware()->dump({"--restore-prop", propIdStr, "-a", areaIdStr});
2705 
2706     ASSERT_FALSE(result.callerShouldDumpState);
2707     ASSERT_THAT(result.buffer, ContainsRegex("restored"));
2708 
2709     auto getResult = getValue(VehiclePropValue{.prop = prop, .areaId = WHEEL_FRONT_LEFT});
2710 
2711     ASSERT_TRUE(getResult.ok());
2712     // The default value is 200.0.
2713     ASSERT_EQ(getResult.value().value.floatValues, std::vector<float>{200.0});
2714 }
2715 
TEST_F(FakeVehicleHardwareTest,testDumpInjectEvent)2716 TEST_F(FakeVehicleHardwareTest, testDumpInjectEvent) {
2717     int32_t prop = toInt(VehicleProperty::ENGINE_OIL_LEVEL);
2718     std::string propIdStr = std::to_string(prop);
2719 
2720     subscribe(prop, /*areaId*/ 0, /*sampleRateHz*/ 0);
2721 
2722     int64_t timestamp = elapsedRealtimeNano();
2723     DumpResult result = getHardware()->dump(
2724             {"--inject-event", propIdStr, "-i", "1234", "-t", std::to_string(timestamp)});
2725 
2726     ASSERT_FALSE(result.callerShouldDumpState);
2727     ASSERT_THAT(result.buffer, ContainsRegex("Event for property: ENGINE_OIL_LEVEL injected"));
2728     ASSERT_TRUE(waitForChangedProperties(prop, 0, /*count=*/1, milliseconds(1000)))
2729             << "No changed event received for injected event from vehicle bus";
2730     auto events = getChangedProperties();
2731     ASSERT_EQ(events.size(), 1u);
2732     auto event = events[0];
2733     ASSERT_EQ(event.timestamp, timestamp);
2734     ASSERT_EQ(event.value.int32Values, std::vector<int32_t>({1234}));
2735 }
2736 
TEST_F(FakeVehicleHardwareTest,testDumpInvalidOptions)2737 TEST_F(FakeVehicleHardwareTest, testDumpInvalidOptions) {
2738     std::vector<std::string> options;
2739     options.push_back("--invalid");
2740 
2741     DumpResult result = getHardware()->dump(options);
2742     ASSERT_FALSE(result.callerShouldDumpState);
2743     ASSERT_NE(result.buffer, "");
2744     ASSERT_THAT(result.buffer, ContainsRegex("Invalid option: --invalid"));
2745 }
2746 
TEST_F(FakeVehicleHardwareTest,testDumpFakeUserHal)2747 TEST_F(FakeVehicleHardwareTest, testDumpFakeUserHal) {
2748     std::vector<std::string> options;
2749     options.push_back("--user-hal");
2750 
2751     DumpResult result = getHardware()->dump(options);
2752     ASSERT_FALSE(result.callerShouldDumpState);
2753     ASSERT_NE(result.buffer, "");
2754     ASSERT_THAT(result.buffer,
2755                 ContainsRegex("No InitialUserInfo response\nNo SwitchUser response\nNo CreateUser "
2756                               "response\nNo SetUserIdentificationAssociation response\n"));
2757 }
2758 
2759 struct SetPropTestCase {
2760     std::string test_name;
2761     std::vector<std::string> options;
2762     bool success;
2763     std::string errorMsg = "";
2764 };
2765 
2766 class FakeVehicleHardwareSetPropTest : public FakeVehicleHardwareTest,
2767                                        public testing::WithParamInterface<SetPropTestCase> {};
2768 
TEST_P(FakeVehicleHardwareSetPropTest,cmdSetOneProperty)2769 TEST_P(FakeVehicleHardwareSetPropTest, cmdSetOneProperty) {
2770     const SetPropTestCase& tc = GetParam();
2771 
2772     DumpResult result = getHardware()->dump(tc.options);
2773     ASSERT_FALSE(result.callerShouldDumpState);
2774     ASSERT_NE(result.buffer, "");
2775     if (tc.success) {
2776         ASSERT_THAT(result.buffer, ContainsRegex("Set property:"));
2777     } else {
2778         ASSERT_THAT(result.buffer, ContainsRegex(tc.errorMsg));
2779     }
2780 }
2781 
GenSetPropParams()2782 std::vector<SetPropTestCase> GenSetPropParams() {
2783     std::string infoMakeProperty = std::to_string(toInt(VehicleProperty::INFO_MAKE));
2784     return {
2785             {"success_set_string", {"--set", infoMakeProperty, "-s", CAR_MAKE}, true},
2786             {"success_set_with_name", {"--set", "INFO_MAKE", "-s", CAR_MAKE}, true},
2787             {"success_set_bytes", {"--set", infoMakeProperty, "-b", "0xdeadbeef"}, true},
2788             {"success_set_bytes_caps", {"--set", infoMakeProperty, "-b", "0xDEADBEEF"}, true},
2789             {"success_set_int", {"--set", infoMakeProperty, "-i", "2147483647"}, true},
2790             {"success_set_ints",
2791              {"--set", infoMakeProperty, "-i", "2147483647", "0", "-2147483648"},
2792              true},
2793             {"success_set_int64",
2794              {"--set", infoMakeProperty, "-i64", "-9223372036854775808"},
2795              true},
2796             {"success_set_int64s",
2797              {"--set", infoMakeProperty, "-i64", "-9223372036854775808", "0",
2798               "9223372036854775807"},
2799              true},
2800             {"success_set_float", {"--set", infoMakeProperty, "-f", "1.175494351E-38"}, true},
2801             {"success_set_floats",
2802              {"--set", infoMakeProperty, "-f", "-3.402823466E+38", "0", "3.402823466E+38"},
2803              true},
2804             {"success_set_area", {"--set", infoMakeProperty, "-a", "2147483647"}, true},
2805             {"fail_no_options", {"--set", infoMakeProperty}, false, "Invalid number of arguments"},
2806             {"fail_less_than_4_options",
2807              {"--set", infoMakeProperty, "-i"},
2808              false,
2809              "No values specified"},
2810             {"fail_unknown_options", {"--set", infoMakeProperty, "-abcd"}, false, "Unknown option"},
2811             {"fail_invalid_property", {"--set", "not_valid", "-s", CAR_MAKE}, false, "not valid"},
2812             {"fail_duplicate_string",
2813              {"--set", infoMakeProperty, "-s", CAR_MAKE, "-s", CAR_MAKE},
2814              false,
2815              "Duplicate \"-s\" options"},
2816             {"fail_multiple_strings",
2817              {"--set", infoMakeProperty, "-s", CAR_MAKE, CAR_MAKE},
2818              false,
2819              "Expect exact one value"},
2820             {"fail_no_string_value",
2821              {"--set", infoMakeProperty, "-s", "-a", "1234"},
2822              false,
2823              "Expect exact one value"},
2824             {"fail_duplicate_bytes",
2825              {"--set", infoMakeProperty, "-b", "0xdeadbeef", "-b", "0xdeadbeef"},
2826              false,
2827              "Duplicate \"-b\" options"},
2828             {"fail_multiple_bytes",
2829              {"--set", infoMakeProperty, "-b", "0xdeadbeef", "0xdeadbeef"},
2830              false,
2831              "Expect exact one value"},
2832             {"fail_invalid_bytes",
2833              {"--set", infoMakeProperty, "-b", "0xgood"},
2834              false,
2835              "not a valid hex string"},
2836             {"fail_invalid_bytes_no_prefix",
2837              {"--set", infoMakeProperty, "-b", "deadbeef"},
2838              false,
2839              "not a valid hex string"},
2840             {"fail_invalid_int",
2841              {"--set", infoMakeProperty, "-i", "abc"},
2842              false,
2843              "not a valid int"},
2844             {"fail_int_out_of_range",
2845              {"--set", infoMakeProperty, "-i", "2147483648"},
2846              false,
2847              "not a valid int"},
2848             {"fail_no_int_value",
2849              {"--set", infoMakeProperty, "-i", "-s", CAR_MAKE},
2850              false,
2851              "No values specified"},
2852             {"fail_invalid_int64",
2853              {"--set", infoMakeProperty, "-i64", "abc"},
2854              false,
2855              "not a valid int64"},
2856             {"fail_int64_out_of_range",
2857              {"--set", infoMakeProperty, "-i64", "-9223372036854775809"},
2858              false,
2859              "not a valid int64"},
2860             {"fail_no_int64_value",
2861              {"--set", infoMakeProperty, "-i64", "-s", CAR_MAKE},
2862              false,
2863              "No values specified"},
2864             {"fail_invalid_float",
2865              {"--set", infoMakeProperty, "-f", "abc"},
2866              false,
2867              "not a valid float"},
2868             {"fail_float_out_of_range",
2869              {"--set", infoMakeProperty, "-f", "-3.402823466E+39"},
2870              false,
2871              "not a valid float"},
2872             {"fail_no_float_value",
2873              {"--set", infoMakeProperty, "-f", "-s", CAR_MAKE},
2874              false,
2875              "No values specified"},
2876             {"fail_multiple_areas",
2877              {"--set", infoMakeProperty, "-a", "2147483648", "0"},
2878              false,
2879              "Expect exact one value"},
2880             {"fail_invalid_area",
2881              {"--set", infoMakeProperty, "-a", "abc"},
2882              false,
2883              "not a valid int"},
2884             {"fail_area_out_of_range",
2885              {"--set", infoMakeProperty, "-a", "2147483648"},
2886              false,
2887              "not a valid int"},
2888             {"fail_no_area_value",
2889              {"--set", infoMakeProperty, "-a", "-s", CAR_MAKE},
2890              false,
2891              "Expect exact one value"},
2892     };
2893 }
2894 
2895 INSTANTIATE_TEST_SUITE_P(
2896         FakeVehicleHardwareSetPropTests, FakeVehicleHardwareSetPropTest,
2897         testing::ValuesIn(GenSetPropParams()),
__anonf0775ddd0a02(const testing::TestParamInfo<FakeVehicleHardwareSetPropTest::ParamType>& info) 2898         [](const testing::TestParamInfo<FakeVehicleHardwareSetPropTest::ParamType>& info) {
2899             return info.param.test_name;
2900         });
2901 
TEST_F(FakeVehicleHardwareTest,SetComplexPropTest)2902 TEST_F(FakeVehicleHardwareTest, SetComplexPropTest) {
2903     std::string infoMakeProperty = std::to_string(toInt(VehicleProperty::INFO_MAKE));
2904     getHardware()->dump({"--set", infoMakeProperty,      "-s",   CAR_MAKE,
2905                          "-b",    "0xdeadbeef",          "-i",   "2147483647",
2906                          "0",     "-2147483648",         "-i64", "-9223372036854775808",
2907                          "0",     "9223372036854775807", "-f",   "-3.402823466E+38",
2908                          "0",     "3.402823466E+38",     "-a",   "123"});
2909     VehiclePropValue requestProp;
2910     requestProp.prop = toInt(VehicleProperty::INFO_MAKE);
2911     requestProp.areaId = 123;
2912     auto result = getValue(requestProp);
2913     ASSERT_TRUE(result.ok());
2914     VehiclePropValue value = result.value();
2915     ASSERT_EQ(value.prop, toInt(VehicleProperty::INFO_MAKE));
2916     ASSERT_EQ(value.areaId, 123);
2917     ASSERT_STREQ(CAR_MAKE, value.value.stringValue.c_str());
2918     uint8_t bytes[] = {0xde, 0xad, 0xbe, 0xef};
2919     ASSERT_FALSE(memcmp(bytes, value.value.byteValues.data(), sizeof(bytes)));
2920     ASSERT_EQ(3u, value.value.int32Values.size());
2921     ASSERT_EQ(2147483647, value.value.int32Values[0]);
2922     ASSERT_EQ(0, value.value.int32Values[1]);
2923     ASSERT_EQ(-2147483648, value.value.int32Values[2]);
2924     ASSERT_EQ(3u, value.value.int64Values.size());
2925     // -9223372036854775808 is not a valid literal since '-' and '9223372036854775808' would be two
2926     // tokens and the later does not fit in unsigned long long.
2927     ASSERT_EQ(-9223372036854775807 - 1, value.value.int64Values[0]);
2928     ASSERT_EQ(0, value.value.int64Values[1]);
2929     ASSERT_EQ(9223372036854775807, value.value.int64Values[2]);
2930     ASSERT_EQ(3u, value.value.floatValues.size());
2931     ASSERT_EQ(-3.402823466E+38f, value.value.floatValues[0]);
2932     ASSERT_EQ(0.0f, value.value.floatValues[1]);
2933     ASSERT_EQ(3.402823466E+38f, value.value.floatValues[2]);
2934 }
2935 
2936 struct OptionsTestCase {
2937     std::string name;
2938     std::vector<std::string> options;
2939     std::string expectMsg;
2940 };
2941 
2942 class FakeVehicleHardwareOptionsTest : public FakeVehicleHardwareTest,
2943                                        public testing::WithParamInterface<OptionsTestCase> {};
2944 
GenInvalidOptions()2945 std::vector<OptionsTestCase> GenInvalidOptions() {
2946     return {{"unknown_command", {"--unknown"}, "Invalid option: --unknown"},
2947             {"help", {"--help"}, "Usage:"},
2948             {"genfakedata_no_subcommand",
2949              {"--genfakedata"},
2950              "No subcommand specified for genfakedata"},
2951             {"genfakedata_unknown_subcommand",
2952              {"--genfakedata", "--unknown"},
2953              "Unknown command: \"--unknown\""},
2954             {"genfakedata_start_linear_no_args",
2955              {"--genfakedata", "--startlinear"},
2956              "incorrect argument count"},
2957             {"genfakedata_start_linear_invalid_propId",
2958              {"--genfakedata", "--startlinear", "abcd", "0.1", "0.1", "0.1", "0.1", "100000000"},
2959              "failed to parse propId as int: \"abcd\""},
2960             {"genfakedata_start_linear_invalid_middleValue",
2961              {"--genfakedata", "--startlinear", "1", "abcd", "0.1", "0.1", "0.1", "100000000"},
2962              "failed to parse middleValue as float: \"abcd\""},
2963             {"genfakedata_start_linear_invalid_currentValue",
2964              {"--genfakedata", "--startlinear", "1", "0.1", "abcd", "0.1", "0.1", "100000000"},
2965              "failed to parse currentValue as float: \"abcd\""},
2966             {"genfakedata_start_linear_invalid_dispersion",
2967              {"--genfakedata", "--startlinear", "1", "0.1", "0.1", "abcd", "0.1", "100000000"},
2968              "failed to parse dispersion as float: \"abcd\""},
2969             {"genfakedata_start_linear_invalid_increment",
2970              {"--genfakedata", "--startlinear", "1", "0.1", "0.1", "0.1", "abcd", "100000000"},
2971              "failed to parse increment as float: \"abcd\""},
2972             {"genfakedata_start_linear_invalid_interval",
2973              {"--genfakedata", "--startlinear", "1", "0.1", "0.1", "0.1", "0.1", "0.1"},
2974              "failed to parse interval as int: \"0.1\""},
2975             {"genfakedata_stop_linear_no_args",
2976              {"--genfakedata", "--stoplinear"},
2977              "incorrect argument count"},
2978             {"genfakedata_stop_linear_invalid_propId",
2979              {"--genfakedata", "--stoplinear", "abcd"},
2980              "failed to parse propId as int: \"abcd\""},
2981             {"genfakedata_startjson_no_args",
2982              {"--genfakedata", "--startjson"},
2983              "incorrect argument count"},
2984             {"genfakedata_startjson_invalid_repetition",
2985              {"--genfakedata", "--startjson", "--path", "file", "0.1"},
2986              "failed to parse repetition as int: \"0.1\""},
2987             {"genfakedata_startjson_invalid_json_file",
2988              {"--genfakedata", "--startjson", "--path", "file", "1"},
2989              "invalid JSON file"},
2990             {"genfakedata_stopjson_no_args",
2991              {"--genfakedata", "--stopjson"},
2992              "incorrect argument count"},
2993             {"genfakedata_keypress_no_args",
2994              {"--genfakedata", "--keypress"},
2995              "incorrect argument count"},
2996             {"genfakedata_keypress_invalid_keyCode",
2997              {"--genfakedata", "--keypress", "0.1", "1"},
2998              "failed to parse keyCode as int: \"0.1\""},
2999             {"genfakedata_keypress_invalid_display",
3000              {"--genfakedata", "--keypress", "1", "0.1"},
3001              "failed to parse display as int: \"0.1\""},
3002             {"genfakedata_keyinputv2_incorrect_arguments",
3003              {"--genfakedata", "--keyinputv2", "1", "1"},
3004              "incorrect argument count, need 7 arguments for --genfakedata --keyinputv2\n"},
3005             {"genfakedata_keyinputv2_invalid_area",
3006              {"--genfakedata", "--keyinputv2", "0.1", "1", "1", "1", "1"},
3007              "failed to parse area as int: \"0.1\""},
3008             {"genfakedata_keyinputv2_invalid_display",
3009              {"--genfakedata", "--keyinputv2", "1", "0.1", "1", "1", "1"},
3010              "failed to parse display as int: \"0.1\""},
3011             {"genfakedata_keyinputv2_invalid_keycode",
3012              {"--genfakedata", "--keyinputv2", "1", "1", "0.1", "1", "1"},
3013              "failed to parse keyCode as int: \"0.1\""},
3014             {"genfakedata_keyinputv2_invalid_action",
3015              {"--genfakedata", "--keyinputv2", "1", "1", "1", "0.1", "1"},
3016              "failed to parse action as int: \"0.1\""},
3017             {"genfakedata_keyinputv2_invalid_repeatcount",
3018              {"--genfakedata", "--keyinputv2", "1", "1", "1", "1", "0.1"},
3019              "failed to parse repeatCount as int: \"0.1\""},
3020             {"genfakedata_motioninput_invalid_argument_count",
3021              {"--genfakedata", "--motioninput", "1", "1", "1", "1", "1"},
3022              "incorrect argument count, need at least 14 arguments for --genfakedata "
3023              "--motioninput including at least 1 --pointer\n"},
3024             {"genfakedata_motioninput_pointer_invalid_argument_count",
3025              {"--genfakedata", "--motioninput", "1", "1", "1", "1", "1", "--pointer", "1", "1", "1",
3026               "1", "1", "1", "--pointer"},
3027              "incorrect argument count, need 6 arguments for every --pointer\n"},
3028             {"genfakedata_motioninput_invalid_area",
3029              {"--genfakedata", "--motioninput", "0.1", "1", "1", "1", "1", "--pointer", "1", "1",
3030               "1", "1", "1", "1"},
3031              "failed to parse area as int: \"0.1\""},
3032             {"genfakedata_motioninput_invalid_display",
3033              {"--genfakedata", "--motioninput", "1", "0.1", "1", "1", "1", "--pointer", "1", "1",
3034               "1", "1", "1", "1"},
3035              "failed to parse display as int: \"0.1\""},
3036             {"genfakedata_motioninput_invalid_inputtype",
3037              {"--genfakedata", "--motioninput", "1", "1", "0.1", "1", "1", "--pointer", "1", "1",
3038               "1", "1", "1", "1"},
3039              "failed to parse inputType as int: \"0.1\""},
3040             {"genfakedata_motioninput_invalid_action",
3041              {"--genfakedata", "--motioninput", "1", "1", "1", "0.1", "1", "--pointer", "1", "1",
3042               "1", "1", "1", "1"},
3043              "failed to parse action as int: \"0.1\""},
3044             {"genfakedata_motioninput_invalid_buttonstate",
3045              {"--genfakedata", "--motioninput", "1", "1", "1", "1", "0.1", "--pointer", "1", "1",
3046               "1.2", "1.2", "1.2", "1.2"},
3047              "failed to parse buttonState as int: \"0.1\""},
3048             {"genfakedata_motioninput_invalid_pointerid",
3049              {"--genfakedata", "--motioninput", "1", "1", "1", "1", "1", "--pointer", "0.1", "1",
3050               "1.2", "1", "1", "1"},
3051              "failed to parse pointerId as int: \"0.1\""},
3052             {"genfakedata_motioninput_invalid_tooltype",
3053              {"--genfakedata", "--motioninput", "1", "1", "1", "1", "1", "--pointer", "1", "0.1",
3054               "1.2", "1", "1", "1"},
3055              "failed to parse toolType as int: \"0.1\""}};
3056 }
3057 
TEST_P(FakeVehicleHardwareOptionsTest,testInvalidOptions)3058 TEST_P(FakeVehicleHardwareOptionsTest, testInvalidOptions) {
3059     auto tc = GetParam();
3060 
3061     DumpResult result = getHardware()->dump(tc.options);
3062 
3063     EXPECT_FALSE(result.callerShouldDumpState);
3064     EXPECT_THAT(result.buffer, HasSubstr(tc.expectMsg));
3065 }
3066 
3067 INSTANTIATE_TEST_SUITE_P(
3068         FakeVehicleHardwareOptionsTests, FakeVehicleHardwareOptionsTest,
3069         testing::ValuesIn(GenInvalidOptions()),
__anonf0775ddd0b02(const testing::TestParamInfo<FakeVehicleHardwareOptionsTest::ParamType>& info) 3070         [](const testing::TestParamInfo<FakeVehicleHardwareOptionsTest::ParamType>& info) {
3071             return info.param.name;
3072         });
3073 
TEST_F(FakeVehicleHardwareTest,testDebugGenFakeDataLinear)3074 TEST_F(FakeVehicleHardwareTest, testDebugGenFakeDataLinear) {
3075     // Start a fake linear data generator for engine oil level at 0.1s interval.
3076     // range: 0 - 100, current value: 30, step: 20.
3077     int32_t prop = toInt(VehicleProperty::ENGINE_OIL_LEVEL);
3078 
3079     subscribe(prop, /*areaId*/ 0, /*sampleRateHz*/ 0);
3080 
3081     std::string propIdString = StringPrintf("%d", prop);
3082     std::vector<std::string> options = {"--genfakedata",         "--startlinear", propIdString,
3083                                         /*middleValue=*/"50",
3084                                         /*currentValue=*/"30",
3085                                         /*dispersion=*/"50",
3086                                         /*increment=*/"20",
3087                                         /*interval=*/"100000000"};
3088 
3089     DumpResult result = getHardware()->dump(options);
3090 
3091     ASSERT_FALSE(result.callerShouldDumpState);
3092     ASSERT_THAT(result.buffer, HasSubstr("successfully"));
3093 
3094     ASSERT_TRUE(waitForChangedProperties(prop, 0, /*count=*/5, milliseconds(1000)))
3095             << "not enough events generated for linear data generator";
3096 
3097     int32_t value = 30;
3098     auto events = getChangedProperties();
3099     for (size_t i = 0; i < 5; i++) {
3100         ASSERT_EQ(1u, events[i].value.int32Values.size());
3101         EXPECT_EQ(value, events[i].value.int32Values[0]);
3102         value = (value + 20) % 100;
3103     }
3104 
3105     // Stop the linear generator.
3106     options = {"--genfakedata", "--stoplinear", propIdString};
3107 
3108     result = getHardware()->dump(options);
3109 
3110     ASSERT_FALSE(result.callerShouldDumpState);
3111     ASSERT_THAT(result.buffer, HasSubstr("successfully"));
3112 
3113     clearChangedProperties();
3114     std::this_thread::sleep_for(std::chrono::milliseconds(200));
3115 
3116     // There should be no new events generated.
3117     EXPECT_EQ(0u, getEventCount(prop, 0));
3118 }
3119 
getTestFilePath(const char * filename)3120 std::string getTestFilePath(const char* filename) {
3121     static std::string baseDir = android::base::GetExecutableDirectory();
3122     return baseDir + "/fakedata/" + filename;
3123 }
3124 
TEST_F(FakeVehicleHardwareTest,testDebugGenFakeDataJson)3125 TEST_F(FakeVehicleHardwareTest, testDebugGenFakeDataJson) {
3126     subscribe(toInt(VehicleProperty::GEAR_SELECTION), /*areaId*/ 0, /*sampleRateHz*/ 0);
3127 
3128     std::vector<std::string> options = {"--genfakedata", "--startjson", "--path",
3129                                         getTestFilePath("prop.json"), "2"};
3130 
3131     DumpResult result = getHardware()->dump(options);
3132 
3133     ASSERT_FALSE(result.callerShouldDumpState);
3134     ASSERT_THAT(result.buffer, HasSubstr("successfully"));
3135 
3136     ASSERT_TRUE(waitForChangedProperties(/*count=*/8, milliseconds(1000)))
3137             << "not enough events generated for JSON data generator";
3138 
3139     auto events = getChangedProperties();
3140     ASSERT_EQ(8u, events.size());
3141     // First set of events, we test 1st and the last.
3142     EXPECT_EQ(1u, events[0].value.int32Values.size());
3143     EXPECT_EQ(8, events[0].value.int32Values[0]);
3144     EXPECT_EQ(1u, events[3].value.int32Values.size());
3145     EXPECT_EQ(10, events[3].value.int32Values[0]);
3146     // Second set of the same events.
3147     EXPECT_EQ(1u, events[4].value.int32Values.size());
3148     EXPECT_EQ(8, events[4].value.int32Values[0]);
3149     EXPECT_EQ(1u, events[7].value.int32Values.size());
3150     EXPECT_EQ(10, events[7].value.int32Values[0]);
3151 }
3152 
TEST_F(FakeVehicleHardwareTest,testDebugGenFakeDataJsonByContent)3153 TEST_F(FakeVehicleHardwareTest, testDebugGenFakeDataJsonByContent) {
3154     subscribe(toInt(VehicleProperty::GEAR_SELECTION), /*areaId*/ 0, /*sampleRateHz*/ 0);
3155 
3156     std::vector<std::string> options = {
3157             "--genfakedata", "--startjson", "--content",
3158             "[{\"timestamp\":1000000,\"areaId\":0,\"value\":8,\"prop\":289408000}]", "1"};
3159 
3160     DumpResult result = getHardware()->dump(options);
3161 
3162     ASSERT_FALSE(result.callerShouldDumpState);
3163     ASSERT_THAT(result.buffer, HasSubstr("successfully"));
3164 
3165     ASSERT_TRUE(waitForChangedProperties(/*count=*/1, milliseconds(1000)))
3166             << "not enough events generated for JSON data generator";
3167 
3168     auto events = getChangedProperties();
3169     ASSERT_EQ(1u, events.size());
3170     EXPECT_EQ(1u, events[0].value.int32Values.size());
3171     EXPECT_EQ(8, events[0].value.int32Values[0]);
3172 }
3173 
TEST_F(FakeVehicleHardwareTest,testDebugGenFakeDataJsonInvalidContent)3174 TEST_F(FakeVehicleHardwareTest, testDebugGenFakeDataJsonInvalidContent) {
3175     std::vector<std::string> options = {"--genfakedata", "--startjson", "--content", "[{", "2"};
3176 
3177     DumpResult result = getHardware()->dump(options);
3178 
3179     ASSERT_FALSE(result.callerShouldDumpState);
3180     ASSERT_THAT(result.buffer, HasSubstr("invalid JSON content"));
3181 }
3182 
TEST_F(FakeVehicleHardwareTest,testDebugGenFakeDataJsonInvalidFile)3183 TEST_F(FakeVehicleHardwareTest, testDebugGenFakeDataJsonInvalidFile) {
3184     std::vector<std::string> options = {"--genfakedata", "--startjson", "--path",
3185                                         getTestFilePath("blahblah.json"), "2"};
3186 
3187     DumpResult result = getHardware()->dump(options);
3188 
3189     ASSERT_FALSE(result.callerShouldDumpState);
3190     ASSERT_THAT(result.buffer, HasSubstr("invalid JSON file"));
3191 }
3192 
TEST_F(FakeVehicleHardwareTest,testDebugGenFakeDataJsonStop)3193 TEST_F(FakeVehicleHardwareTest, testDebugGenFakeDataJsonStop) {
3194     // No iteration number provided, would loop indefinitely.
3195     std::vector<std::string> options = {"--genfakedata", "--startjson", "--path",
3196                                         getTestFilePath("prop.json")};
3197 
3198     DumpResult result = getHardware()->dump(options);
3199 
3200     ASSERT_FALSE(result.callerShouldDumpState);
3201     ASSERT_THAT(result.buffer, HasSubstr("successfully"));
3202 
3203     std::string id = result.buffer.substr(result.buffer.find("ID: ") + 4);
3204 
3205     result = getHardware()->dump({"--genfakedata", "--stopjson", id});
3206 
3207     ASSERT_FALSE(result.callerShouldDumpState);
3208     ASSERT_THAT(result.buffer, HasSubstr("successfully"));
3209 }
3210 
TEST_F(FakeVehicleHardwareTest,testDebugGenFakeDataJsonStopInvalidFile)3211 TEST_F(FakeVehicleHardwareTest, testDebugGenFakeDataJsonStopInvalidFile) {
3212     // No iteration number provided, would loop indefinitely.
3213     std::vector<std::string> options = {"--genfakedata", "--startjson", "--path",
3214                                         getTestFilePath("prop.json")};
3215 
3216     DumpResult result = getHardware()->dump(options);
3217 
3218     ASSERT_FALSE(result.callerShouldDumpState);
3219     ASSERT_THAT(result.buffer, HasSubstr("successfully"));
3220 
3221     result = getHardware()->dump({"--genfakedata", "--stopjson", "1234"});
3222 
3223     ASSERT_FALSE(result.callerShouldDumpState);
3224     ASSERT_THAT(result.buffer, HasSubstr("No JSON event generator found"));
3225 
3226     // TearDown function should destroy the generator which stops the iteration.
3227 }
3228 
TEST_F(FakeVehicleHardwareTest,testDebugGenFakeDataKeyPress)3229 TEST_F(FakeVehicleHardwareTest, testDebugGenFakeDataKeyPress) {
3230     int32_t propHwKeyInput = toInt(VehicleProperty::HW_KEY_INPUT);
3231     std::vector<std::string> options = {"--genfakedata", "--keypress", "1", "2"};
3232 
3233     subscribe(propHwKeyInput, /*areaId*/ 0, /*sampleRateHz*/ 0);
3234 
3235     DumpResult result = getHardware()->dump(options);
3236 
3237     ASSERT_FALSE(result.callerShouldDumpState);
3238     ASSERT_THAT(result.buffer, HasSubstr("successfully"));
3239 
3240     auto events = getChangedProperties();
3241     ASSERT_EQ(2u, events.size());
3242     EXPECT_EQ(propHwKeyInput, events[0].prop);
3243     EXPECT_EQ(propHwKeyInput, events[1].prop);
3244     ASSERT_EQ(3u, events[0].value.int32Values.size());
3245     ASSERT_EQ(3u, events[1].value.int32Values.size());
3246     EXPECT_EQ(toInt(VehicleHwKeyInputAction::ACTION_DOWN), events[0].value.int32Values[0]);
3247     EXPECT_EQ(1, events[0].value.int32Values[1]);
3248     EXPECT_EQ(2, events[0].value.int32Values[2]);
3249     EXPECT_EQ(toInt(VehicleHwKeyInputAction::ACTION_UP), events[1].value.int32Values[0]);
3250     EXPECT_EQ(1, events[1].value.int32Values[1]);
3251     EXPECT_EQ(2, events[1].value.int32Values[2]);
3252 }
3253 
TEST_F(FakeVehicleHardwareTest,testDebugGenFakeDataKeyInputV2)3254 TEST_F(FakeVehicleHardwareTest, testDebugGenFakeDataKeyInputV2) {
3255     int32_t propHwKeyInputV2 = toInt(VehicleProperty::HW_KEY_INPUT_V2);
3256     std::vector<std::string> options = {"--genfakedata", "--keyinputv2", "1", "2", "3", "4", "5"};
3257 
3258     subscribe(propHwKeyInputV2, /*areaId*/ 1, /*sampleRateHz*/ 0);
3259 
3260     DumpResult result = getHardware()->dump(options);
3261 
3262     ASSERT_FALSE(result.callerShouldDumpState);
3263     ASSERT_THAT(result.buffer, HasSubstr("successfully"));
3264 
3265     auto events = getChangedProperties();
3266     ASSERT_EQ(1u, events.size());
3267     EXPECT_EQ(toInt(VehicleProperty::HW_KEY_INPUT_V2), events[0].prop);
3268     ASSERT_EQ(4u, events[0].value.int32Values.size());
3269     EXPECT_EQ(2, events[0].value.int32Values[0]);
3270     EXPECT_EQ(3, events[0].value.int32Values[1]);
3271     EXPECT_EQ(4, events[0].value.int32Values[2]);
3272     EXPECT_EQ(5, events[0].value.int32Values[3]);
3273     ASSERT_EQ(1u, events[0].value.int64Values.size());
3274 }
3275 
TEST_F(FakeVehicleHardwareTest,testDebugGenFakeDataMotionInput)3276 TEST_F(FakeVehicleHardwareTest, testDebugGenFakeDataMotionInput) {
3277     int32_t propHwMotionInput = toInt(VehicleProperty::HW_MOTION_INPUT);
3278     std::vector<std::string> options = {"--genfakedata",
3279                                         "--motioninput",
3280                                         "1",
3281                                         "2",
3282                                         "3",
3283                                         "4",
3284                                         "5",
3285                                         "--pointer",
3286                                         "11",
3287                                         "22",
3288                                         "33.3",
3289                                         "44.4",
3290                                         "55.5",
3291                                         "66.6",
3292                                         "--pointer",
3293                                         "21",
3294                                         "32",
3295                                         "43.3",
3296                                         "54.4",
3297                                         "65.5",
3298                                         "76.6"};
3299 
3300     subscribe(propHwMotionInput, /*areaId*/ 1, /*sampleRateHz*/ 0);
3301 
3302     DumpResult result = getHardware()->dump(options);
3303 
3304     ASSERT_FALSE(result.callerShouldDumpState);
3305     ASSERT_THAT(result.buffer, HasSubstr("successfully"));
3306 
3307     auto events = getChangedProperties();
3308     ASSERT_EQ(1u, events.size());
3309     EXPECT_EQ(propHwMotionInput, events[0].prop);
3310     ASSERT_EQ(9u, events[0].value.int32Values.size());
3311     EXPECT_EQ(2, events[0].value.int32Values[0]);
3312     EXPECT_EQ(3, events[0].value.int32Values[1]);
3313     EXPECT_EQ(4, events[0].value.int32Values[2]);
3314     EXPECT_EQ(5, events[0].value.int32Values[3]);
3315     EXPECT_EQ(2, events[0].value.int32Values[4]);
3316     EXPECT_EQ(11, events[0].value.int32Values[5]);
3317     EXPECT_EQ(21, events[0].value.int32Values[6]);
3318     EXPECT_EQ(22, events[0].value.int32Values[7]);
3319     EXPECT_EQ(32, events[0].value.int32Values[8]);
3320     ASSERT_EQ(8u, events[0].value.floatValues.size());
3321     EXPECT_FLOAT_EQ(33.3, events[0].value.floatValues[0]);
3322     EXPECT_FLOAT_EQ(43.3, events[0].value.floatValues[1]);
3323     EXPECT_FLOAT_EQ(44.4, events[0].value.floatValues[2]);
3324     EXPECT_FLOAT_EQ(54.4, events[0].value.floatValues[3]);
3325     EXPECT_FLOAT_EQ(55.5, events[0].value.floatValues[4]);
3326     EXPECT_FLOAT_EQ(65.5, events[0].value.floatValues[5]);
3327     EXPECT_FLOAT_EQ(66.6, events[0].value.floatValues[6]);
3328     EXPECT_FLOAT_EQ(76.6, events[0].value.floatValues[7]);
3329     ASSERT_EQ(1u, events[0].value.int64Values.size());
3330 }
3331 
TEST_F(FakeVehicleHardwareTest,testGetEchoReverseBytes)3332 TEST_F(FakeVehicleHardwareTest, testGetEchoReverseBytes) {
3333     ASSERT_EQ(setValue(VehiclePropValue{
3334                       .prop = toInt(TestVendorProperty::ECHO_REVERSE_BYTES),
3335                       .value =
3336                               {
3337                                       .byteValues = {0x01, 0x02, 0x03, 0x04},
3338                               },
3339               }),
3340               StatusCode::OK);
3341 
3342     auto result = getValue(VehiclePropValue{
3343             .prop = toInt(TestVendorProperty::ECHO_REVERSE_BYTES),
3344     });
3345 
3346     ASSERT_TRUE(result.ok()) << "failed to get ECHO_REVERSE_BYTES value: " << getStatus(result);
3347     ASSERT_EQ(result.value().value.byteValues, std::vector<uint8_t>({0x04, 0x03, 0x02, 0x01}));
3348 }
3349 
TEST_F(FakeVehicleHardwareTest,testSubscribeUnsubscribe_continuous)3350 TEST_F(FakeVehicleHardwareTest, testSubscribeUnsubscribe_continuous) {
3351     int32_t propSpeed = toInt(VehicleProperty::PERF_VEHICLE_SPEED);
3352     int32_t propSteering = toInt(VehicleProperty::PERF_STEERING_ANGLE);
3353     int32_t areaId = 0;
3354 
3355     auto status = getHardware()->subscribe(newSubscribeOptions(propSpeed, areaId, 5));
3356     ASSERT_EQ(status, StatusCode::OK) << "failed to subscribe";
3357 
3358     ASSERT_TRUE(waitForChangedProperties(propSpeed, areaId, /*count=*/5, milliseconds(1500)))
3359             << "not enough events generated for speed";
3360 
3361     status = getHardware()->subscribe(newSubscribeOptions(propSteering, areaId, 10));
3362     ASSERT_EQ(status, StatusCode::OK) << "failed to subscribe";
3363 
3364     ASSERT_TRUE(waitForChangedProperties(propSteering, areaId, /*count=*/10, milliseconds(1500)))
3365             << "not enough events generated for steering";
3366 
3367     int64_t timestamp = elapsedRealtimeNano();
3368     // Disable refreshing for propSpeed.
3369     status = getHardware()->unsubscribe(propSpeed, areaId);
3370     ASSERT_EQ(status, StatusCode::OK) << "failed to unsubscribe";
3371     clearChangedProperties();
3372 
3373     ASSERT_TRUE(waitForChangedProperties(propSteering, areaId, /*count=*/5, milliseconds(1500)))
3374             << "should still receive steering events after disable polling for speed";
3375     auto updatedValues = getChangedProperties();
3376     for (auto& value : updatedValues) {
3377         ASSERT_GE(value.timestamp, timestamp);
3378         ASSERT_EQ(value.prop, propSteering);
3379         ASSERT_EQ(value.areaId, areaId);
3380     }
3381 }
3382 
TEST_F(FakeVehicleHardwareTest,testSubscribe_enableVUR)3383 TEST_F(FakeVehicleHardwareTest, testSubscribe_enableVUR) {
3384     int32_t propSpeed = toInt(VehicleProperty::PERF_VEHICLE_SPEED);
3385     int32_t areaId = 0;
3386     SubscribeOptions options;
3387     options.propId = propSpeed;
3388     options.areaIds = {areaId};
3389     options.enableVariableUpdateRate = true;
3390     options.sampleRate = 5;
3391     int64_t timestamp = elapsedRealtimeNano();
3392 
3393     auto status = getHardware()->subscribe(options);
3394     ASSERT_EQ(status, StatusCode::OK) << "failed to subscribe";
3395 
3396     status = setValue({
3397             .prop = propSpeed,
3398             .areaId = 0,
3399             .value.floatValues = {1.1f},
3400     });
3401     ASSERT_EQ(status, StatusCode::OK) << "failed to set speed";
3402 
3403     status = setValue({
3404             .prop = propSpeed,
3405             .areaId = 0,
3406             .value.floatValues = {1.2f},
3407     });
3408     ASSERT_EQ(status, StatusCode::OK) << "failed to set speed";
3409 
3410     ASSERT_TRUE(waitForChangedProperties(propSpeed, areaId, /*count=*/2, milliseconds(100)))
3411             << "not enough events generated for speed";
3412     auto updatedValues = getChangedProperties();
3413     std::unordered_set<float> gotValues;
3414     for (auto& value : updatedValues) {
3415         EXPECT_GE(value.timestamp, timestamp) << "timestamp must be updated";
3416         EXPECT_EQ(value.prop, propSpeed) << "propId must be correct";
3417         EXPECT_EQ(value.areaId, areaId) << "areaId must be correct";
3418         gotValues.insert(value.value.floatValues[0]);
3419     }
3420     EXPECT_THAT(gotValues, UnorderedElementsAre(1.1f, 1.2f))
3421             << "must only receive property event for changed value";
3422 }
3423 
TEST_F(FakeVehicleHardwareTest,testSubscribeUnusubscribe_onChange)3424 TEST_F(FakeVehicleHardwareTest, testSubscribeUnusubscribe_onChange) {
3425     int32_t propHvac = toInt(VehicleProperty::HVAC_TEMPERATURE_SET);
3426     int32_t areaId = SEAT_1_LEFT;
3427 
3428     auto status = getHardware()->subscribe(newSubscribeOptions(propHvac, areaId, 0));
3429     ASSERT_EQ(status, StatusCode::OK) << "failed to subscribe";
3430 
3431     status = setValue({
3432             .prop = propHvac,
3433             .areaId = areaId,
3434             .value.floatValues = {20.0f},
3435     });
3436     ASSERT_EQ(status, StatusCode::OK) << "failed to set hvac value";
3437 
3438     ASSERT_TRUE(waitForChangedProperties(propHvac, areaId, /*count=*/1, milliseconds(100)))
3439             << "not enough on change events generated for hvac";
3440     clearChangedProperties();
3441 
3442     status = setValue({
3443             .prop = propHvac,
3444             .areaId = areaId,
3445             .value.floatValues = {21.0f},
3446     });
3447     ASSERT_EQ(status, StatusCode::OK) << "failed to set hvac value";
3448 
3449     ASSERT_TRUE(waitForChangedProperties(propHvac, areaId, /*count=*/1, milliseconds(100)))
3450             << "not enough on change events generated for hvac";
3451     clearChangedProperties();
3452 
3453     status = getHardware()->unsubscribe(propHvac, areaId);
3454     ASSERT_EQ(status, StatusCode::OK);
3455 
3456     status = setValue({
3457             .prop = propHvac,
3458             .areaId = areaId,
3459             .value.floatValues = {22.0f},
3460     });
3461     ASSERT_EQ(status, StatusCode::OK) << "failed to set hvac value";
3462 
3463     ASSERT_FALSE(waitForChangedProperties(propHvac, areaId, /*count=*/1, milliseconds(100)))
3464             << "must not receive on change events if the propId, areaId is unsubscribed";
3465 }
3466 
TEST_F(FakeVehicleHardwareTest,testSubscribeContinuous_rate0_mustReturnInvalidArg)3467 TEST_F(FakeVehicleHardwareTest, testSubscribeContinuous_rate0_mustReturnInvalidArg) {
3468     int32_t propSpeed = toInt(VehicleProperty::PERF_VEHICLE_SPEED);
3469     int32_t areaId = 0;
3470     auto status = getHardware()->subscribe(newSubscribeOptions(propSpeed, areaId, 0));
3471 
3472     ASSERT_EQ(status, StatusCode::INVALID_ARG);
3473 }
3474 
TEST_F(FakeVehicleHardwareTest,testSetHvacTemperatureValueSuggestion)3475 TEST_F(FakeVehicleHardwareTest, testSetHvacTemperatureValueSuggestion) {
3476     float CELSIUS = static_cast<float>(toInt(VehicleUnit::CELSIUS));
3477     float FAHRENHEIT = static_cast<float>(toInt(VehicleUnit::FAHRENHEIT));
3478     int32_t propHvacTempValueSuggest = toInt(VehicleProperty::HVAC_TEMPERATURE_VALUE_SUGGESTION);
3479 
3480     subscribe(propHvacTempValueSuggest, HVAC_ALL, /*sampleRateHz*/ 0);
3481 
3482     VehiclePropValue floatArraySizeFour = {
3483             .prop = propHvacTempValueSuggest,
3484             .areaId = HVAC_ALL,
3485             .value.floatValues = {0, CELSIUS, 0, 0},
3486     };
3487     StatusCode status = setValue(floatArraySizeFour);
3488     EXPECT_EQ(status, StatusCode::OK);
3489 
3490     VehiclePropValue floatArraySizeZero = {
3491             .prop = propHvacTempValueSuggest,
3492             .areaId = HVAC_ALL,
3493     };
3494     status = setValue(floatArraySizeZero);
3495     EXPECT_EQ(status, StatusCode::INVALID_ARG);
3496 
3497     VehiclePropValue floatArraySizeFive = {
3498             .prop = propHvacTempValueSuggest,
3499             .areaId = HVAC_ALL,
3500             .value.floatValues = {0, CELSIUS, 0, 0, 0},
3501     };
3502     status = setValue(floatArraySizeFive);
3503     EXPECT_EQ(status, StatusCode::INVALID_ARG);
3504 
3505     VehiclePropValue invalidUnit = {
3506             .prop = propHvacTempValueSuggest,
3507             .areaId = HVAC_ALL,
3508             .value.floatValues = {0, 0, 0, 0},
3509     };
3510     status = setValue(floatArraySizeFive);
3511     EXPECT_EQ(status, StatusCode::INVALID_ARG);
3512     clearChangedProperties();
3513 
3514     // Config array values from HVAC_TEMPERATURE_SET in DefaultProperties.json
3515     auto configs = getHardware()->getAllPropertyConfigs();
3516     auto hvacTemperatureSetConfig =
3517             std::move(getVehiclePropConfig(toInt(VehicleProperty::HVAC_TEMPERATURE_SET)));
3518     EXPECT_NE(hvacTemperatureSetConfig, nullptr);
3519 
3520     auto& hvacTemperatureSetConfigArray = hvacTemperatureSetConfig->configArray;
3521     // The HVAC_TEMPERATURE_SET config array values are temperature values that have been multiplied
3522     // by 10 and converted to integers. HVAC_TEMPERATURE_VALUE_SUGGESTION specifies the temperature
3523     // values to be in the original floating point form so we divide by 10 and convert to float.
3524     float minTempInCelsius = hvacTemperatureSetConfigArray[0] / 10.0f;
3525     float maxTempInCelsius = hvacTemperatureSetConfigArray[1] / 10.0f;
3526     float incrementInCelsius = hvacTemperatureSetConfigArray[2] / 10.0f;
3527     float minTempInFahrenheit = hvacTemperatureSetConfigArray[3] / 10.0f;
3528     float maxTempInFahrenheit = hvacTemperatureSetConfigArray[4] / 10.0f;
3529     float incrementInFahrenheit = hvacTemperatureSetConfigArray[5] / 10.0f;
3530 
3531     auto testCases = {
3532             SetSpecialValueTestCase{
3533                     .name = "min_celsius_temperature",
3534                     .valuesToSet =
3535                             {
3536                                     VehiclePropValue{
3537                                             .prop = propHvacTempValueSuggest,
3538                                             .areaId = HVAC_ALL,
3539                                             .value.floatValues = {minTempInCelsius, CELSIUS, 0, 0},
3540                                     },
3541                             },
3542                     .expectedValuesToGet =
3543                             {
3544                                     VehiclePropValue{
3545                                             .prop = propHvacTempValueSuggest,
3546                                             .areaId = HVAC_ALL,
3547                                             .value.floatValues = {minTempInCelsius, CELSIUS,
3548                                                                   minTempInCelsius,
3549                                                                   minTempInFahrenheit},
3550                                     },
3551                             },
3552             },
3553             SetSpecialValueTestCase{
3554                     .name = "min_fahrenheit_temperature",
3555                     .valuesToSet =
3556                             {
3557                                     VehiclePropValue{
3558                                             .prop = propHvacTempValueSuggest,
3559                                             .areaId = HVAC_ALL,
3560                                             .value.floatValues = {minTempInFahrenheit, FAHRENHEIT,
3561                                                                   0, 0},
3562                                     },
3563                             },
3564                     .expectedValuesToGet =
3565                             {
3566                                     VehiclePropValue{
3567                                             .prop = propHvacTempValueSuggest,
3568                                             .areaId = HVAC_ALL,
3569                                             .value.floatValues = {minTempInFahrenheit, FAHRENHEIT,
3570                                                                   minTempInCelsius,
3571                                                                   minTempInFahrenheit},
3572                                     },
3573                             },
3574             },
3575             SetSpecialValueTestCase{
3576                     .name = "max_celsius_temperature",
3577                     .valuesToSet =
3578                             {
3579                                     VehiclePropValue{
3580                                             .prop = propHvacTempValueSuggest,
3581                                             .areaId = HVAC_ALL,
3582                                             .value.floatValues = {maxTempInCelsius, CELSIUS, 0, 0},
3583                                     },
3584                             },
3585                     .expectedValuesToGet =
3586                             {
3587                                     VehiclePropValue{
3588                                             .prop = propHvacTempValueSuggest,
3589                                             .areaId = HVAC_ALL,
3590                                             .value.floatValues = {maxTempInCelsius, CELSIUS,
3591                                                                   maxTempInCelsius,
3592                                                                   maxTempInFahrenheit},
3593                                     },
3594                             },
3595             },
3596             SetSpecialValueTestCase{
3597                     .name = "max_fahrenheit_temperature",
3598                     .valuesToSet =
3599                             {
3600                                     VehiclePropValue{
3601                                             .prop = propHvacTempValueSuggest,
3602                                             .areaId = HVAC_ALL,
3603                                             .value.floatValues = {maxTempInFahrenheit, FAHRENHEIT,
3604                                                                   0, 0},
3605                                     },
3606                             },
3607                     .expectedValuesToGet =
3608                             {
3609                                     VehiclePropValue{
3610                                             .prop = propHvacTempValueSuggest,
3611                                             .areaId = HVAC_ALL,
3612                                             .value.floatValues = {maxTempInFahrenheit, FAHRENHEIT,
3613                                                                   maxTempInCelsius,
3614                                                                   maxTempInFahrenheit},
3615                                     },
3616                             },
3617             },
3618             SetSpecialValueTestCase{
3619                     .name = "below_min_celsius_temperature",
3620                     .valuesToSet =
3621                             {
3622                                     VehiclePropValue{
3623                                             .prop = propHvacTempValueSuggest,
3624                                             .areaId = HVAC_ALL,
3625                                             .value.floatValues = {minTempInCelsius - 1, CELSIUS, 0,
3626                                                                   0},
3627                                     },
3628                             },
3629                     .expectedValuesToGet =
3630                             {
3631                                     VehiclePropValue{
3632                                             .prop = propHvacTempValueSuggest,
3633                                             .areaId = HVAC_ALL,
3634                                             .value.floatValues = {minTempInCelsius - 1, CELSIUS,
3635                                                                   minTempInCelsius,
3636                                                                   minTempInFahrenheit},
3637                                     },
3638                             },
3639             },
3640             SetSpecialValueTestCase{
3641                     .name = "below_min_fahrenheit_temperature",
3642                     .valuesToSet =
3643                             {
3644                                     VehiclePropValue{
3645                                             .prop = propHvacTempValueSuggest,
3646                                             .areaId = HVAC_ALL,
3647                                             .value.floatValues = {minTempInFahrenheit - 1,
3648                                                                   FAHRENHEIT, 0, 0},
3649                                     },
3650                             },
3651                     .expectedValuesToGet =
3652                             {
3653                                     VehiclePropValue{
3654                                             .prop = propHvacTempValueSuggest,
3655                                             .areaId = HVAC_ALL,
3656                                             .value.floatValues = {minTempInFahrenheit - 1,
3657                                                                   FAHRENHEIT, minTempInCelsius,
3658                                                                   minTempInFahrenheit},
3659                                     },
3660                             },
3661             },
3662             SetSpecialValueTestCase{
3663                     .name = "above_max_celsius_temperature",
3664                     .valuesToSet =
3665                             {
3666                                     VehiclePropValue{
3667                                             .prop = propHvacTempValueSuggest,
3668                                             .areaId = HVAC_ALL,
3669                                             .value.floatValues = {maxTempInCelsius + 1, CELSIUS, 0,
3670                                                                   0},
3671                                     },
3672                             },
3673                     .expectedValuesToGet =
3674                             {
3675                                     VehiclePropValue{
3676                                             .prop = propHvacTempValueSuggest,
3677                                             .areaId = HVAC_ALL,
3678                                             .value.floatValues = {maxTempInCelsius + 1, CELSIUS,
3679                                                                   maxTempInCelsius,
3680                                                                   maxTempInFahrenheit},
3681                                     },
3682                             },
3683             },
3684             SetSpecialValueTestCase{
3685                     .name = "above_max_fahrenheit_temperature",
3686                     .valuesToSet =
3687                             {
3688                                     VehiclePropValue{
3689                                             .prop = propHvacTempValueSuggest,
3690                                             .areaId = HVAC_ALL,
3691                                             .value.floatValues = {maxTempInFahrenheit + 1,
3692                                                                   FAHRENHEIT, 0, 0},
3693                                     },
3694                             },
3695                     .expectedValuesToGet =
3696                             {
3697                                     VehiclePropValue{
3698                                             .prop = propHvacTempValueSuggest,
3699                                             .areaId = HVAC_ALL,
3700                                             .value.floatValues = {maxTempInFahrenheit + 1,
3701                                                                   FAHRENHEIT, maxTempInCelsius,
3702                                                                   maxTempInFahrenheit},
3703                                     },
3704                             },
3705             },
3706             SetSpecialValueTestCase{
3707                     .name = "inbetween_value_celsius",
3708                     .valuesToSet =
3709                             {
3710                                     VehiclePropValue{
3711                                             .prop = propHvacTempValueSuggest,
3712                                             .areaId = HVAC_ALL,
3713                                             .value.floatValues = {minTempInCelsius +
3714                                                                           incrementInCelsius * 2.5f,
3715                                                                   CELSIUS, 0, 0},
3716                                     },
3717                             },
3718                     .expectedValuesToGet =
3719                             {
3720                                     VehiclePropValue{
3721                                             .prop = propHvacTempValueSuggest,
3722                                             .areaId = HVAC_ALL,
3723                                             .value.floatValues =
3724                                                     {minTempInCelsius + incrementInCelsius * 2.5f,
3725                                                      CELSIUS,
3726                                                      minTempInCelsius + incrementInCelsius * 2,
3727                                                      minTempInFahrenheit +
3728                                                              incrementInFahrenheit * 2},
3729                                     },
3730                             },
3731             },
3732             SetSpecialValueTestCase{
3733                     .name = "inbetween_value_fahrenheit",
3734                     .valuesToSet =
3735                             {
3736                                     VehiclePropValue{
3737                                             .prop = propHvacTempValueSuggest,
3738                                             .areaId = HVAC_ALL,
3739                                             .value.floatValues = {minTempInFahrenheit +
3740                                                                           incrementInFahrenheit *
3741                                                                                   2.5f,
3742                                                                   FAHRENHEIT, 0, 0},
3743                                     },
3744                             },
3745                     .expectedValuesToGet =
3746                             {
3747                                     VehiclePropValue{
3748                                             .prop = propHvacTempValueSuggest,
3749                                             .areaId = HVAC_ALL,
3750                                             .value.floatValues =
3751                                                     {minTempInFahrenheit +
3752                                                              incrementInFahrenheit * 2.5f,
3753                                                      FAHRENHEIT,
3754                                                      minTempInCelsius + incrementInCelsius * 2,
3755                                                      minTempInFahrenheit +
3756                                                              incrementInFahrenheit * 2},
3757                                     },
3758                             },
3759             },
3760     };
3761 
3762     for (auto& tc : testCases) {
3763         StatusCode status = setValue(tc.valuesToSet[0]);
3764         EXPECT_EQ(status, StatusCode::OK);
3765 
3766         auto events = getChangedProperties();
3767         EXPECT_EQ(events.size(), static_cast<size_t>(1));
3768         events[0].timestamp = 0;
3769 
3770         EXPECT_EQ(events[0], tc.expectedValuesToGet[0]);
3771         clearChangedProperties();
3772     }
3773 }
3774 
3775 }  // namespace fake
3776 }  // namespace vehicle
3777 }  // namespace automotive
3778 }  // namespace hardware
3779 }  // namespace android
3780