1 /*
2  * Copyright (C) 2016 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 <unordered_map>
18 #include <iostream>
19 
20 #include <android-base/macros.h>
21 #include <cutils/native_handle.h>
22 #include <utils/SystemClock.h>
23 
24 #include <gtest/gtest.h>
25 
26 #include "vhal_v2_0/VehicleHalManager.h"
27 
28 #include "VehicleHalTestUtils.h"
29 
30 namespace android {
31 namespace hardware {
32 namespace automotive {
33 namespace vehicle {
34 namespace V2_0 {
35 
36 // A simple helper class to expose 'cmdSetOneProperty' to the unit tests.
37 class VehicleHalManagerTestHelper {
38   public:
VehicleHalManagerTestHelper(VehicleHalManager * manager)39     VehicleHalManagerTestHelper(VehicleHalManager* manager) { mManager = manager; }
cmdSetOneProperty(int fd,const hidl_vec<hidl_string> & options)40     bool cmdSetOneProperty(int fd, const hidl_vec<hidl_string>& options) {
41         return mManager->cmdSetOneProperty(fd, options);
42     }
43 
44   public:
45     VehicleHalManager* mManager;
46 };
47 
48 namespace {
49 
50 using namespace std::placeholders;
51 
52 constexpr char kCarMake[] = "Default Car";
53 constexpr int kRetriablePropMockedAttempts = 3;
54 
55 class MockedVehicleHal : public VehicleHal {
56 public:
MockedVehicleHal()57     MockedVehicleHal() {
58         mConfigs.assign(std::begin(kVehicleProperties),
59                         std::end(kVehicleProperties));
60     }
61 
listProperties()62     std::vector<VehiclePropConfig> listProperties() override {
63         return mConfigs;
64     }
65 
get(const VehiclePropValue & requestedPropValue,StatusCode * outStatus)66     VehiclePropValuePtr get(const VehiclePropValue& requestedPropValue,
67              StatusCode* outStatus) override {
68         *outStatus = StatusCode::OK;
69         VehiclePropValuePtr pValue;
70         auto property = static_cast<VehicleProperty>(requestedPropValue.prop);
71         int32_t areaId = requestedPropValue.areaId;
72 
73         if (property == VehicleProperty::INFO_FUEL_CAPACITY) {
74             if (fuelCapacityAttemptsLeft-- > 0) {
75                 // Emulate property not ready yet.
76                 *outStatus = StatusCode::TRY_AGAIN;
77             } else {
78                 pValue = getValuePool()->obtainFloat(42.42);
79             }
80         } else {
81             auto key = makeKey(requestedPropValue);
82             if (mValues.count(key) == 0) {
83                 ALOGW("key not found\n");
84                 *outStatus = StatusCode::INVALID_ARG;
85                 return pValue;
86             }
87             pValue = getValuePool()->obtain(mValues[key]);
88         }
89 
90         if (*outStatus == StatusCode::OK && pValue.get() != nullptr) {
91             pValue->prop = toInt(property);
92             pValue->areaId = areaId;
93             pValue->timestamp = elapsedRealtimeNano();
94         }
95 
96         return pValue;
97     }
98 
set(const VehiclePropValue & propValue)99     StatusCode set(const VehiclePropValue& propValue) override {
100         if (toInt(VehicleProperty::MIRROR_FOLD) == propValue.prop
101                 && mirrorFoldAttemptsLeft-- > 0) {
102             return StatusCode::TRY_AGAIN;
103         }
104         mValues[makeKey(propValue)] = propValue;
105         return StatusCode::OK;
106     }
107 
subscribe(int32_t,float)108     StatusCode subscribe(int32_t /* property */,
109                          float /* sampleRate */) override {
110         return StatusCode::OK;
111     }
112 
unsubscribe(int32_t)113     StatusCode unsubscribe(int32_t /* property */) override {
114         return StatusCode::OK;
115     }
116 
sendPropEvent(recyclable_ptr<VehiclePropValue> value)117     void sendPropEvent(recyclable_ptr<VehiclePropValue> value) {
118         doHalEvent(std::move(value));
119     }
120 
sendHalError(StatusCode error,int32_t property,int32_t areaId)121     void sendHalError(StatusCode error, int32_t property, int32_t areaId) {
122         doHalPropertySetError(error, property, areaId);
123     }
124 
125 public:
126     int fuelCapacityAttemptsLeft = kRetriablePropMockedAttempts;
127     int mirrorFoldAttemptsLeft = kRetriablePropMockedAttempts;
128 
129 private:
makeKey(const VehiclePropValue & v) const130     int64_t makeKey(const VehiclePropValue& v) const {
131         return makeKey(v.prop, v.areaId);
132     }
133 
makeKey(int32_t prop,int32_t area) const134     int64_t makeKey(int32_t prop, int32_t area) const {
135         return (static_cast<int64_t>(prop) << 32) | area;
136     }
137 
138 private:
139     std::vector<VehiclePropConfig> mConfigs;
140     std::unordered_map<int64_t, VehiclePropValue> mValues;
141 };
142 
143 class VehicleHalManagerTest : public ::testing::Test {
144 protected:
SetUp()145     void SetUp() override {
146         hal.reset(new MockedVehicleHal);
147         manager.reset(new VehicleHalManager(hal.get()));
148 
149         objectPool = hal->getValuePool();
150     }
151 
TearDown()152     void TearDown() override {
153         manager.reset(nullptr);
154         hal.reset(nullptr);
155     }
156 public:
invokeGet(int32_t property,int32_t areaId)157     void invokeGet(int32_t property, int32_t areaId) {
158         VehiclePropValue requestedValue {};
159         requestedValue.prop = property;
160         requestedValue.areaId = areaId;
161 
162         invokeGet(requestedValue);
163     }
164 
invokeGet(const VehiclePropValue & requestedPropValue)165     void invokeGet(const VehiclePropValue& requestedPropValue) {
166         actualValue = VehiclePropValue {};  // reset previous values
167 
168         StatusCode refStatus;
169         VehiclePropValue refValue;
170         bool called = false;
171         manager->get(requestedPropValue, [&refStatus, &refValue, &called]
172             (StatusCode status, const VehiclePropValue& value) {
173             refStatus = status;
174             refValue = value;
175             called = true;
176         });
177         ASSERT_TRUE(called) << "callback wasn't called for prop: "
178                             << hexString(requestedPropValue.prop);
179 
180         actualValue = refValue;
181         actualStatusCode = refStatus;
182     }
183 
getComplexProperty()184     MockedVehicleHal::VehiclePropValuePtr getComplexProperty() {
185         auto pValue = objectPool->obtainComplex();
186         pValue->prop = kCustomComplexProperty;
187         pValue->areaId = 0;
188         pValue->value.int32Values = hidl_vec<int32_t>{10, 20};
189         pValue->value.int64Values = hidl_vec<int64_t>{30, 40};
190         pValue->value.floatValues = hidl_vec<float_t>{1.1, 2.2};
191         pValue->value.bytes = hidl_vec<uint8_t>{1, 2, 3};
192         pValue->value.stringValue = kCarMake;
193         return pValue;
194     }
195 
196 public:
197     VehiclePropValue actualValue;
198     StatusCode actualStatusCode;
199 
200     VehiclePropValuePool* objectPool;
201     std::unique_ptr<MockedVehicleHal> hal;
202     std::unique_ptr<VehicleHalManager> manager;
203 };
204 
TEST_F(VehicleHalManagerTest,getPropConfigs)205 TEST_F(VehicleHalManagerTest, getPropConfigs) {
206     hidl_vec<int32_t> properties =
207         { toInt(VehicleProperty::HVAC_FAN_SPEED),
208           toInt(VehicleProperty::INFO_MAKE) };
209     bool called = false;
210 
211     manager->getPropConfigs(properties,
212             [&called] (StatusCode status,
213                        const hidl_vec<VehiclePropConfig>& c) {
214         ASSERT_EQ(StatusCode::OK, status);
215         ASSERT_EQ(2u, c.size());
216         called = true;
217     });
218 
219     ASSERT_TRUE(called);  // Verify callback received.
220 
221     called = false;
222     manager->getPropConfigs({ toInt(VehicleProperty::HVAC_FAN_SPEED) },
223             [&called] (StatusCode status,
224                        const hidl_vec<VehiclePropConfig>& c) {
225         ASSERT_EQ(StatusCode::OK, status);
226         ASSERT_EQ(1u, c.size());
227         ASSERT_EQ(toString(kVehicleProperties[1]), toString(c[0]));
228         called = true;
229     });
230     ASSERT_TRUE(called);  // Verify callback received.
231 
232     // TODO(pavelm): add case case when property was not declared.
233 }
234 
TEST_F(VehicleHalManagerTest,getAllPropConfigs)235 TEST_F(VehicleHalManagerTest, getAllPropConfigs) {
236     bool called = false;
237     manager->getAllPropConfigs(
238             [&called] (const hidl_vec<VehiclePropConfig>& propConfigs) {
239         ASSERT_EQ(arraysize(kVehicleProperties), propConfigs.size());
240 
241         for (size_t i = 0; i < propConfigs.size(); i++) {
242             ASSERT_EQ(toString(kVehicleProperties[i]),
243                       toString(propConfigs[i]));
244         }
245         called = true;
246     });
247     ASSERT_TRUE(called);  // Verify callback received.
248 }
249 
TEST_F(VehicleHalManagerTest,halErrorEvent)250 TEST_F(VehicleHalManagerTest, halErrorEvent) {
251     const auto PROP = toInt(VehicleProperty::DISPLAY_BRIGHTNESS);
252 
253     sp<MockedVehicleCallback> cb = new MockedVehicleCallback();
254 
255     hidl_vec<SubscribeOptions> options = {
256         SubscribeOptions{.propId = PROP, .flags = SubscribeFlags::EVENTS_FROM_CAR},
257     };
258 
259     StatusCode res = manager->subscribe(cb, options);
260     ASSERT_EQ(StatusCode::OK, res);
261 
262     hal->sendHalError(StatusCode::TRY_AGAIN, PROP, 0 /* area id*/);
263 }
264 
TEST_F(VehicleHalManagerTest,subscribe)265 TEST_F(VehicleHalManagerTest, subscribe) {
266     const auto PROP = toInt(VehicleProperty::DISPLAY_BRIGHTNESS);
267 
268     sp<MockedVehicleCallback> cb = new MockedVehicleCallback();
269 
270     hidl_vec<SubscribeOptions> options = {
271         SubscribeOptions{.propId = PROP, .flags = SubscribeFlags::EVENTS_FROM_CAR}};
272 
273     StatusCode res = manager->subscribe(cb, options);
274     ASSERT_EQ(StatusCode::OK, res);
275 
276     auto unsubscribedValue = objectPool->obtain(VehiclePropertyType::INT32);
277     unsubscribedValue->prop = toInt(VehicleProperty::HVAC_FAN_SPEED);
278 
279     hal->sendPropEvent(std::move(unsubscribedValue));
280     auto& receivedEnvents = cb->getReceivedEvents();
281 
282     ASSERT_TRUE(cb->waitForExpectedEvents(0)) << " Unexpected events received: "
283                                               << receivedEnvents.size()
284                                               << (receivedEnvents.size() > 0
285                                                   ? toString(receivedEnvents.front()[0]) : "");
286 
287     auto subscribedValue = objectPool->obtain(VehiclePropertyType::INT32);
288     subscribedValue->prop = PROP;
289     subscribedValue->value.int32Values[0] = 42;
290 
291     cb->reset();
292     VehiclePropValue actualValue(*subscribedValue.get());
293     hal->sendPropEvent(std::move(subscribedValue));
294 
295     ASSERT_TRUE(cb->waitForExpectedEvents(1)) << "Events received: "
296                                               << receivedEnvents.size();
297 
298     ASSERT_EQ(toString(actualValue),
299               toString(cb->getReceivedEvents().front()[0]));
300 }
301 
TEST_F(VehicleHalManagerTest,subscribe_WriteOnly)302 TEST_F(VehicleHalManagerTest, subscribe_WriteOnly) {
303     const auto PROP = toInt(VehicleProperty::HVAC_SEAT_TEMPERATURE);
304 
305     sp<MockedVehicleCallback> cb = new MockedVehicleCallback();
306 
307     hidl_vec<SubscribeOptions> options = {
308         SubscribeOptions{.propId = PROP, .flags = SubscribeFlags::EVENTS_FROM_CAR},
309     };
310 
311     StatusCode res = manager->subscribe(cb, options);
312     // Unable to subscribe on Hal Events for write-only properties.
313     ASSERT_EQ(StatusCode::INVALID_ARG, res);
314 
315     options[0].flags = SubscribeFlags::EVENTS_FROM_ANDROID;
316 
317     res = manager->subscribe(cb, options);
318     // OK to subscribe on SET method call for write-only properties.
319     ASSERT_EQ(StatusCode::OK, res);
320 }
321 
TEST_F(VehicleHalManagerTest,get_Complex)322 TEST_F(VehicleHalManagerTest, get_Complex) {
323     ASSERT_EQ(StatusCode::OK, hal->set(*getComplexProperty().get()));
324 
325     invokeGet(kCustomComplexProperty, 0);
326 
327     ASSERT_EQ(StatusCode::OK, actualStatusCode);
328     ASSERT_EQ(kCustomComplexProperty, actualValue.prop);
329 
330     ASSERT_EQ(3u, actualValue.value.bytes.size());
331     ASSERT_EQ(1, actualValue.value.bytes[0]);
332     ASSERT_EQ(2, actualValue.value.bytes[1]);
333     ASSERT_EQ(3, actualValue.value.bytes[2]);
334 
335     ASSERT_EQ(2u, actualValue.value.int32Values.size());
336     ASSERT_EQ(10, actualValue.value.int32Values[0]);
337     ASSERT_EQ(20, actualValue.value.int32Values[1]);
338 
339     ASSERT_EQ(2u, actualValue.value.floatValues.size());
340     ASSERT_FLOAT_EQ(1.1, actualValue.value.floatValues[0]);
341     ASSERT_FLOAT_EQ(2.2, actualValue.value.floatValues[1]);
342 
343     ASSERT_EQ(2u, actualValue.value.int64Values.size());
344     ASSERT_FLOAT_EQ(30, actualValue.value.int64Values[0]);
345     ASSERT_FLOAT_EQ(40, actualValue.value.int64Values[1]);
346 
347     ASSERT_STREQ(kCarMake, actualValue.value.stringValue.c_str());
348 }
349 
TEST_F(VehicleHalManagerTest,get_StaticString)350 TEST_F(VehicleHalManagerTest, get_StaticString) {
351     auto pValue = objectPool->obtainString(kCarMake);
352     pValue->prop = toInt(VehicleProperty::INFO_MAKE);
353     pValue->areaId = 0;
354     ASSERT_EQ(StatusCode::OK, hal->set(*pValue.get()));
355 
356     invokeGet(toInt(VehicleProperty::INFO_MAKE), 0);
357 
358     ASSERT_EQ(StatusCode::OK, actualStatusCode);
359     ASSERT_EQ(toInt(VehicleProperty::INFO_MAKE), actualValue.prop);
360     ASSERT_STREQ(kCarMake, actualValue.value.stringValue.c_str());
361 }
362 
TEST_F(VehicleHalManagerTest,get_NegativeCases)363 TEST_F(VehicleHalManagerTest, get_NegativeCases) {
364     // Write-only property must fail.
365     invokeGet(toInt(VehicleProperty::HVAC_SEAT_TEMPERATURE), 0);
366     ASSERT_EQ(StatusCode::ACCESS_DENIED, actualStatusCode);
367 
368     // Unknown property must fail.
369     invokeGet(toInt(VehicleProperty::MIRROR_Z_MOVE), 0);
370     ASSERT_EQ(StatusCode::INVALID_ARG, actualStatusCode);
371 }
372 
TEST_F(VehicleHalManagerTest,get_Retriable)373 TEST_F(VehicleHalManagerTest, get_Retriable) {
374     actualStatusCode = StatusCode::TRY_AGAIN;
375     int attempts = 0;
376     while (StatusCode::TRY_AGAIN == actualStatusCode && ++attempts < 10) {
377         invokeGet(toInt(VehicleProperty::INFO_FUEL_CAPACITY), 0);
378 
379     }
380     ASSERT_EQ(StatusCode::OK, actualStatusCode);
381     ASSERT_EQ(kRetriablePropMockedAttempts + 1, attempts);
382     ASSERT_FLOAT_EQ(42.42, actualValue.value.floatValues[0]);
383 }
384 
TEST_F(VehicleHalManagerTest,set_Basic)385 TEST_F(VehicleHalManagerTest, set_Basic) {
386     const auto PROP = toInt(VehicleProperty::DISPLAY_BRIGHTNESS);
387     const auto VAL = 7;
388 
389     auto expectedValue = hal->getValuePool()->obtainInt32(VAL);
390     expectedValue->prop = PROP;
391     expectedValue->areaId = 0;
392 
393     actualStatusCode = manager->set(*expectedValue.get());
394     ASSERT_EQ(StatusCode::OK, actualStatusCode);
395 
396     invokeGet(PROP, 0);
397     ASSERT_EQ(StatusCode::OK, actualStatusCode);
398     ASSERT_EQ(PROP, actualValue.prop);
399     ASSERT_EQ(VAL, actualValue.value.int32Values[0]);
400 }
401 
TEST_F(VehicleHalManagerTest,set_DifferentAreas)402 TEST_F(VehicleHalManagerTest, set_DifferentAreas) {
403     const auto PROP = toInt(VehicleProperty::HVAC_FAN_SPEED);
404     const auto VAL1 = 1;
405     const auto VAL2 = 2;
406     const auto AREA1 = toInt(VehicleAreaSeat::ROW_1_LEFT);
407     const auto AREA2 = toInt(VehicleAreaSeat::ROW_1_RIGHT);
408 
409     {
410         auto expectedValue1 = hal->getValuePool()->obtainInt32(VAL1);
411         expectedValue1->prop = PROP;
412         expectedValue1->areaId = AREA1;
413         actualStatusCode = manager->set(*expectedValue1.get());
414         ASSERT_EQ(StatusCode::OK, actualStatusCode);
415 
416         auto expectedValue2 = hal->getValuePool()->obtainInt32(VAL2);
417         expectedValue2->prop = PROP;
418         expectedValue2->areaId = AREA2;
419         actualStatusCode = manager->set(*expectedValue2.get());
420         ASSERT_EQ(StatusCode::OK, actualStatusCode);
421     }
422 
423     {
424         invokeGet(PROP, AREA1);
425         ASSERT_EQ(StatusCode::OK, actualStatusCode);
426         ASSERT_EQ(PROP, actualValue.prop);
427         ASSERT_EQ(AREA1, actualValue.areaId);
428         ASSERT_EQ(VAL1, actualValue.value.int32Values[0]);
429 
430         invokeGet(PROP, AREA2);
431         ASSERT_EQ(StatusCode::OK, actualStatusCode);
432         ASSERT_EQ(PROP, actualValue.prop);
433         ASSERT_EQ(AREA2, actualValue.areaId);
434         ASSERT_EQ(VAL2, actualValue.value.int32Values[0]);
435     }
436 }
437 
TEST_F(VehicleHalManagerTest,set_Retriable)438 TEST_F(VehicleHalManagerTest, set_Retriable) {
439     const auto PROP = toInt(VehicleProperty::MIRROR_FOLD);
440 
441     auto v = hal->getValuePool()->obtainBoolean(true);
442     v->prop = PROP;
443     v->areaId = 0;
444 
445     actualStatusCode = StatusCode::TRY_AGAIN;
446     int attempts = 0;
447     while (StatusCode::TRY_AGAIN == actualStatusCode && ++attempts < 10) {
448         actualStatusCode = manager->set(*v.get());
449     }
450 
451     ASSERT_EQ(StatusCode::OK, actualStatusCode);
452     ASSERT_EQ(kRetriablePropMockedAttempts + 1, attempts);
453 
454     invokeGet(PROP, 0);
455     ASSERT_EQ(StatusCode::OK, actualStatusCode);
456     ASSERT_TRUE(actualValue.value.int32Values[0]);
457 }
458 
TEST(HalClientVectorTest,basic)459 TEST(HalClientVectorTest, basic) {
460     HalClientVector clients;
461     sp<IVehicleCallback> callback1 = new MockedVehicleCallback();
462 
463     sp<HalClient> c1 = new HalClient(callback1);
464     sp<HalClient> c2 = new HalClient(callback1);
465 
466     clients.addOrUpdate(c1);
467     clients.addOrUpdate(c1);
468     clients.addOrUpdate(c2);
469     ASSERT_EQ(2u, clients.size());
470     ASSERT_FALSE(clients.isEmpty());
471     ASSERT_LE(0, clients.indexOf(c1));
472     ASSERT_LE(0, clients.remove(c1));
473     ASSERT_GT(0, clients.indexOf(c1));  // c1 was already removed
474     ASSERT_GT(0, clients.remove(c1));   // attempt to remove c1 again
475     ASSERT_LE(0, clients.remove(c2));
476 
477     ASSERT_TRUE(clients.isEmpty());
478 }
479 
TEST_F(VehicleHalManagerTest,debug)480 TEST_F(VehicleHalManagerTest, debug) {
481     hidl_handle fd = {};
482     fd.setTo(native_handle_create(/*numFds=*/1, /*numInts=*/0), /*shouldOwn=*/true);
483 
484     // Because debug function returns void, so no way to check return value.
485     manager->debug(fd, {});
486     manager->debug(fd, {"--help"});
487     manager->debug(fd, {"--list"});
488     manager->debug(fd, {"--get"});
489     manager->debug(fd, {"--set"});
490     manager->debug(fd, {"invalid"});
491 }
492 
493 struct SetPropTestCase {
494     std::string test_name;
495     const hidl_vec<hidl_string> configs;
496     bool success;
497 };
498 
499 class VehicleHalManagerSetPropTest : public VehicleHalManagerTest,
500                                      public testing::WithParamInterface<SetPropTestCase> {};
501 
TEST_P(VehicleHalManagerSetPropTest,cmdSetOneProperty)502 TEST_P(VehicleHalManagerSetPropTest, cmdSetOneProperty) {
503     const SetPropTestCase& tc = GetParam();
504     VehicleHalManagerTestHelper helper(manager.get());
505     ASSERT_EQ(tc.success, helper.cmdSetOneProperty(STDERR_FILENO, tc.configs));
506 }
507 
GenSetPropParams()508 std::vector<SetPropTestCase> GenSetPropParams() {
509     char infoMakeProperty[100] = {};
510     snprintf(infoMakeProperty, sizeof(infoMakeProperty), "%d", toInt(VehicleProperty::INFO_MAKE));
511     return {
512             {"success_set_string", {"--set", infoMakeProperty, "-s", kCarMake}, true},
513             {"success_set_bytes", {"--set", infoMakeProperty, "-b", "0xdeadbeef"}, true},
514             {"success_set_bytes_caps", {"--set", infoMakeProperty, "-b", "0xDEADBEEF"}, true},
515             {"success_set_int", {"--set", infoMakeProperty, "-i", "2147483647"}, true},
516             {"success_set_ints",
517              {"--set", infoMakeProperty, "-i", "2147483647", "0", "-2147483648"},
518              true},
519             {"success_set_int64",
520              {"--set", infoMakeProperty, "-i64", "-9223372036854775808"},
521              true},
522             {"success_set_int64s",
523              {"--set", infoMakeProperty, "-i64", "-9223372036854775808", "0",
524               "9223372036854775807"},
525              true},
526             {"success_set_float", {"--set", infoMakeProperty, "-f", "1.175494351E-38"}, true},
527             {"success_set_floats",
528              {"--set", infoMakeProperty, "-f", "-3.402823466E+38", "0", "3.402823466E+38"},
529              true},
530             {"success_set_area", {"--set", infoMakeProperty, "-a", "2147483647"}, true},
531             {"fail_no_options", {}, false},
532             {"fail_less_than_4_options", {"--set", infoMakeProperty, "-i"}, false},
533             {"fail_unknown_options", {"--set", infoMakeProperty, "-s", kCarMake, "-abcd"}, false},
534             {"fail_invalid_property", {"--set", "not valid", "-s", kCarMake}, false},
535             {"fail_duplicate_string",
536              {"--set", infoMakeProperty, "-s", kCarMake, "-s", kCarMake},
537              false},
538             {"fail_multiple_strings", {"--set", infoMakeProperty, "-s", kCarMake, kCarMake}, false},
539             {"fail_no_string_value", {"--set", infoMakeProperty, "-s", "-a", "1234"}, false},
540             {"fail_duplicate_bytes",
541              {"--set", infoMakeProperty, "-b", "0xdeadbeef", "-b", "0xdeadbeef"},
542              false},
543             {"fail_multiple_bytes",
544              {"--set", infoMakeProperty, "-b", "0xdeadbeef", "0xdeadbeef"},
545              false},
546             {"fail_invalid_bytes", {"--set", infoMakeProperty, "-b", "0xgood"}, false},
547             {"fail_invalid_bytes_no_prefix", {"--set", infoMakeProperty, "-b", "deadbeef"}, false},
548             {"fail_invalid_int", {"--set", infoMakeProperty, "-i", "abc"}, false},
549             {"fail_int_out_of_range", {"--set", infoMakeProperty, "-i", "2147483648"}, false},
550             {"fail_no_int_value", {"--set", infoMakeProperty, "-i", "-s", kCarMake}, false},
551             {"fail_invalid_int64", {"--set", infoMakeProperty, "-i64", "abc"}, false},
552             {"fail_int64_out_of_range",
553              {"--set", infoMakeProperty, "-i64", "-9223372036854775809"},
554              false},
555             {"fail_no_int64_value", {"--set", infoMakeProperty, "-i64", "-s", kCarMake}, false},
556             {"fail_invalid_float", {"--set", infoMakeProperty, "-f", "abc"}, false},
557             {"fail_float_out_of_range",
558              {"--set", infoMakeProperty, "-f", "-3.402823466E+39"},
559              false},
560             {"fail_no_float_value", {"--set", infoMakeProperty, "-f", "-s", kCarMake}, false},
561             {"fail_multiple_areas", {"--set", infoMakeProperty, "-a", "2147483648", "0"}, false},
562             {"fail_invalid_area", {"--set", infoMakeProperty, "-a", "abc"}, false},
563             {"fail_area_out_of_range", {"--set", infoMakeProperty, "-a", "2147483648"}, false},
564             {"fail_no_area_value", {"--set", infoMakeProperty, "-a", "-s", kCarMake}, false},
565     };
566 }
567 
568 INSTANTIATE_TEST_SUITE_P(
569         VehicleHalManagerSetPropTests, VehicleHalManagerSetPropTest,
570         testing::ValuesIn(GenSetPropParams()),
__anon2922a9af0602(const testing::TestParamInfo<VehicleHalManagerSetPropTest::ParamType>& info) 571         [](const testing::TestParamInfo<VehicleHalManagerSetPropTest::ParamType>& info) {
572             return info.param.test_name;
573         });
574 
TEST_F(VehicleHalManagerTest,SetComplexPropTest)575 TEST_F(VehicleHalManagerTest, SetComplexPropTest) {
576     char infoMakeProperty[100] = {};
577     snprintf(infoMakeProperty, sizeof(infoMakeProperty), "%d", toInt(VehicleProperty::INFO_MAKE));
578     VehicleHalManagerTestHelper helper(manager.get());
579     ASSERT_TRUE(helper.cmdSetOneProperty(
580             STDERR_FILENO, {"--set", infoMakeProperty,      "-s",   kCarMake,
581                             "-b",    "0xdeadbeef",          "-i",   "2147483647",
582                             "0",     "-2147483648",         "-i64", "-9223372036854775808",
583                             "0",     "9223372036854775807", "-f",   "-3.402823466E+38",
584                             "0",     "3.402823466E+38",     "-a",   "123"}));
585     StatusCode status = StatusCode::OK;
586     VehiclePropValue requestProp;
587     requestProp.prop = toInt(VehicleProperty::INFO_MAKE);
588     requestProp.areaId = 123;
589     auto value = hal->get(requestProp, &status);
590     ASSERT_EQ(StatusCode::OK, status);
591     ASSERT_EQ(value->prop, toInt(VehicleProperty::INFO_MAKE));
592     ASSERT_EQ(value->areaId, 123);
593     ASSERT_STREQ(kCarMake, value->value.stringValue.c_str());
594     uint8_t bytes[] = {0xde, 0xad, 0xbe, 0xef};
595     ASSERT_FALSE(memcmp(bytes, value->value.bytes.data(), sizeof(bytes)));
596     ASSERT_EQ(3u, value->value.int32Values.size());
597     ASSERT_EQ(2147483647, value->value.int32Values[0]);
598     ASSERT_EQ(0, value->value.int32Values[1]);
599     ASSERT_EQ(-2147483648, value->value.int32Values[2]);
600     ASSERT_EQ(3u, value->value.int64Values.size());
601     // -9223372036854775808 is not a valid literal since '-' and '9223372036854775808' would be two
602     // tokens and the later does not fit in unsigned long long.
603     ASSERT_EQ(-9223372036854775807 - 1, value->value.int64Values[0]);
604     ASSERT_EQ(0, value->value.int64Values[1]);
605     ASSERT_EQ(9223372036854775807, value->value.int64Values[2]);
606     ASSERT_EQ(3u, value->value.floatValues.size());
607     ASSERT_EQ(-3.402823466E+38f, value->value.floatValues[0]);
608     ASSERT_EQ(0.0f, value->value.floatValues[1]);
609     ASSERT_EQ(3.402823466E+38f, value->value.floatValues[2]);
610 }
611 
612 }  // namespace anonymous
613 
614 }  // namespace V2_0
615 }  // namespace vehicle
616 }  // namespace automotive
617 }  // namespace hardware
618 }  // namespace android
619