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