blob: 4a20ea532dcf42d72b993adb4a67fc48e12e4172 [file] [log] [blame]
Pavel Maltseve2603e32016-10-25 16:03:23 -07001/*
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
Pavel Maltsev6fee6282016-12-02 16:43:24 -080020#include <utils/SystemClock.h>
21
Pavel Maltseve2603e32016-10-25 16:03:23 -070022#include <gtest/gtest.h>
23
Pavel Maltsev6fee6282016-12-02 16:43:24 -080024#include "vehicle_hal_manager/VehicleHalManager.h"
Pavel Maltseve2603e32016-10-25 16:03:23 -070025
26#include "VehicleHalTestUtils.h"
27
28namespace android {
29namespace hardware {
30namespace vehicle {
31namespace V2_0 {
32
33namespace {
34
35using namespace std::placeholders;
36
Pavel Maltsevdb179c52016-10-27 15:43:06 -070037constexpr char kCarMake[] = "Default Car";
38constexpr int kRetriablePropMockedAttempts = 3;
39
Pavel Maltseve2603e32016-10-25 16:03:23 -070040class MockedVehicleHal : public VehicleHal {
41public:
42 MockedVehicleHal() {
43 mConfigs.assign(std::begin(kVehicleProperties),
44 std::end(kVehicleProperties));
45 }
46
47 std::vector<VehiclePropConfig> listProperties() override {
48 return mConfigs;
49 }
50
Pavel Maltsevdb179c52016-10-27 15:43:06 -070051 VehiclePropValuePtr get(const VehiclePropValue& requestedPropValue,
52 StatusCode* outStatus) override {
53 *outStatus = StatusCode::OK;
54 VehiclePropValuePtr pValue;
55 VehicleProperty property = requestedPropValue.prop;
56 int32_t areaId = requestedPropValue.areaId;
57
58 switch (property) {
59 case VehicleProperty::INFO_MAKE:
60 pValue = getValuePool()->obtainString(kCarMake);
61 break;
62 case VehicleProperty::INFO_FUEL_CAPACITY:
63 if (fuelCapacityAttemptsLeft-- > 0) {
64 // Emulate property not ready yet.
65 *outStatus = StatusCode::TRY_AGAIN;
66 } else {
67 pValue = getValuePool()->obtainFloat(42.42);
68 }
69 break;
Pavel Maltsevf21639f2016-12-22 11:17:29 -080070 case VehicleProperty::VEHICLE_MAPS_DATA_SERVICE:
71 pValue = getValuePool()->obtainComplex();
72 pValue->value.int32Values = hidl_vec<int32_t> { 10, 20 };
73 pValue->value.int64Values = hidl_vec<int64_t> { 30, 40 };
74 pValue->value.floatValues = hidl_vec<float_t> { 1.1, 2.2 };
75 pValue->value.bytes = hidl_vec<uint8_t> { 1, 2, 3 };
76 pValue->value.stringValue = kCarMake;
77 break;
Pavel Maltsevdb179c52016-10-27 15:43:06 -070078 default:
79 auto key = makeKey(property, areaId);
80 if (mValues.count(key) == 0) {
81 ALOGW("");
82 }
83 pValue = getValuePool()->obtain(mValues[key]);
84 }
85
86 if (*outStatus == StatusCode::OK && pValue.get() != nullptr) {
87 pValue->prop = property;
88 pValue->areaId = areaId;
89 pValue->timestamp = elapsedRealtimeNano();
90 }
91
92 return pValue;
Pavel Maltseve2603e32016-10-25 16:03:23 -070093 }
94
Pavel Maltsevdb179c52016-10-27 15:43:06 -070095 StatusCode set(const VehiclePropValue& propValue) override {
96 if (VehicleProperty::MIRROR_FOLD == propValue.prop
97 && mirrorFoldAttemptsLeft-- > 0) {
98 return StatusCode::TRY_AGAIN;
99 }
100
101 mValues[makeKey(propValue)] = propValue;
102 return StatusCode::OK;
Pavel Maltseve2603e32016-10-25 16:03:23 -0700103 }
104
Pavel Maltsevdb179c52016-10-27 15:43:06 -0700105 StatusCode subscribe(VehicleProperty property,
Pavel Maltseve2603e32016-10-25 16:03:23 -0700106 int32_t areas,
107 float sampleRate) override {
Pavel Maltsevdb179c52016-10-27 15:43:06 -0700108 return StatusCode::OK;
Pavel Maltseve2603e32016-10-25 16:03:23 -0700109 }
110
Pavel Maltsevdb179c52016-10-27 15:43:06 -0700111 StatusCode unsubscribe(VehicleProperty property) override {
112 return StatusCode::OK;
Pavel Maltseve2603e32016-10-25 16:03:23 -0700113 }
114
115 void sendPropEvent(recyclable_ptr<VehiclePropValue> value) {
116 doHalEvent(std::move(value));
117 }
118
Pavel Maltsevdb179c52016-10-27 15:43:06 -0700119 void sendHalError(StatusCode error, VehicleProperty property,
120 int32_t areaId) {
121 doHalPropertySetError(error, property, areaId);
122 }
123
124public:
125 int fuelCapacityAttemptsLeft = kRetriablePropMockedAttempts;
126 int mirrorFoldAttemptsLeft = kRetriablePropMockedAttempts;
127
128private:
129 int64_t makeKey(const VehiclePropValue& v) const {
130 return makeKey(v.prop, v.areaId);
131 }
132
133 int64_t makeKey(VehicleProperty prop, int32_t area) const {
134 return (static_cast<int64_t>(prop) << 32) | area;
135 }
136
Pavel Maltseve2603e32016-10-25 16:03:23 -0700137private:
138 std::vector<VehiclePropConfig> mConfigs;
Pavel Maltsevdb179c52016-10-27 15:43:06 -0700139 std::unordered_map<int64_t, VehiclePropValue> mValues;
Pavel Maltseve2603e32016-10-25 16:03:23 -0700140};
141
142class VehicleHalManagerTest : public ::testing::Test {
143protected:
144 void SetUp() override {
145 hal.reset(new MockedVehicleHal);
146 manager.reset(new VehicleHalManager(hal.get()));
147
148 objectPool = hal->getValuePool();
149 }
150
151 void TearDown() override {
152 manager.reset(nullptr);
153 hal.reset(nullptr);
154 }
Pavel Maltsevdb179c52016-10-27 15:43:06 -0700155public:
156 void invokeGet(VehicleProperty property, int32_t areaId) {
157 VehiclePropValue requestedValue {};
158 requestedValue.prop = property;
159 requestedValue.areaId = areaId;
160
161 invokeGet(requestedValue);
162 }
163
164 void invokeGet(const VehiclePropValue& requestedPropValue) {
165 actualValue = VehiclePropValue {}; // reset previous values
166
167 StatusCode refStatus;
168 VehiclePropValue refValue;
169 bool called = false;
170 manager->get(requestedPropValue, [&refStatus, &refValue, &called]
171 (StatusCode status, const VehiclePropValue& value) {
172 refStatus = status;
173 refValue = value;
174 called = true;
175 });
176 ASSERT_TRUE(called) << "callback wasn't called for prop: "
177 << enumToHexString(requestedPropValue.prop);
178
179 actualValue = refValue;
180 actualStatusCode = refStatus;
181 }
Pavel Maltseve2603e32016-10-25 16:03:23 -0700182
183public:
Pavel Maltsevdb179c52016-10-27 15:43:06 -0700184 VehiclePropValue actualValue;
185 StatusCode actualStatusCode;
186
Pavel Maltseve2603e32016-10-25 16:03:23 -0700187 VehiclePropValuePool* objectPool;
188 std::unique_ptr<MockedVehicleHal> hal;
189 std::unique_ptr<VehicleHalManager> manager;
190};
191
Pavel Maltseve2603e32016-10-25 16:03:23 -0700192TEST_F(VehicleHalManagerTest, getPropConfigs) {
Pavel Maltsev0e0a9252016-12-05 11:03:52 -0800193 hidl_vec<VehicleProperty> properties =
194 { VehicleProperty::HVAC_FAN_SPEED, VehicleProperty::INFO_MAKE };
Pavel Maltseve2603e32016-10-25 16:03:23 -0700195 bool called = false;
Pavel Maltsevdb179c52016-10-27 15:43:06 -0700196
Pavel Maltseve2603e32016-10-25 16:03:23 -0700197 manager->getPropConfigs(properties,
Pavel Maltsevdb179c52016-10-27 15:43:06 -0700198 [&called] (StatusCode status,
199 const hidl_vec<VehiclePropConfig>& c) {
200 ASSERT_EQ(StatusCode::OK, status);
Pavel Maltseve2603e32016-10-25 16:03:23 -0700201 ASSERT_EQ(2u, c.size());
202 called = true;
203 });
Pavel Maltsevdb179c52016-10-27 15:43:06 -0700204
Pavel Maltseve2603e32016-10-25 16:03:23 -0700205 ASSERT_TRUE(called); // Verify callback received.
206
207 called = false;
Pavel Maltsev0e0a9252016-12-05 11:03:52 -0800208 manager->getPropConfigs({ VehicleProperty::HVAC_FAN_SPEED },
Pavel Maltsevdb179c52016-10-27 15:43:06 -0700209 [&called] (StatusCode status,
210 const hidl_vec<VehiclePropConfig>& c) {
211 ASSERT_EQ(StatusCode::OK, status);
Pavel Maltseve2603e32016-10-25 16:03:23 -0700212 ASSERT_EQ(1u, c.size());
213 ASSERT_EQ(toString(kVehicleProperties[1]), toString(c[0]));
214 called = true;
215 });
216 ASSERT_TRUE(called); // Verify callback received.
Pavel Maltsevdb179c52016-10-27 15:43:06 -0700217
218 // TODO(pavelm): add case case when property was not declared.
Pavel Maltseve2603e32016-10-25 16:03:23 -0700219}
220
221TEST_F(VehicleHalManagerTest, getAllPropConfigs) {
222 bool called = false;
223 manager->getAllPropConfigs(
224 [&called] (const hidl_vec<VehiclePropConfig>& propConfigs) {
225 ASSERT_EQ(arraysize(kVehicleProperties), propConfigs.size());
226
227 for (size_t i = 0; i < propConfigs.size(); i++) {
228 ASSERT_EQ(toString(kVehicleProperties[i]),
229 toString(propConfigs[i]));
230 }
231 called = true;
232 });
233 ASSERT_TRUE(called); // Verify callback received.
234}
235
Pavel Maltsevdb179c52016-10-27 15:43:06 -0700236TEST_F(VehicleHalManagerTest, halErrorEvent) {
237 const VehicleProperty PROP = VehicleProperty::DISPLAY_BRIGHTNESS;
238
239 sp<MockedVehicleCallback> cb = new MockedVehicleCallback();
240
Pavel Maltsev0e0a9252016-12-05 11:03:52 -0800241 hidl_vec<SubscribeOptions> options = {
242 SubscribeOptions {
243 .propId = PROP,
244 .flags = SubscribeFlags::DEFAULT
245 },
246 };
Pavel Maltsevdb179c52016-10-27 15:43:06 -0700247
248 StatusCode res = manager->subscribe(cb, options);
249 ASSERT_EQ(StatusCode::OK, res);
250
251 hal->sendHalError(StatusCode::TRY_AGAIN, PROP, 0 /* area id*/);
252}
253
Pavel Maltseve2603e32016-10-25 16:03:23 -0700254TEST_F(VehicleHalManagerTest, subscribe) {
255 const VehicleProperty PROP = VehicleProperty::DISPLAY_BRIGHTNESS;
256
257 sp<MockedVehicleCallback> cb = new MockedVehicleCallback();
258
Pavel Maltsev0e0a9252016-12-05 11:03:52 -0800259 hidl_vec<SubscribeOptions> options = {
260 SubscribeOptions {
261 .propId = PROP,
262 .flags = SubscribeFlags::DEFAULT
263 }
264 };
Pavel Maltseve2603e32016-10-25 16:03:23 -0700265
266 StatusCode res = manager->subscribe(cb, options);
267 ASSERT_EQ(StatusCode::OK, res);
268
269 auto unsubscribedValue = objectPool->obtain(VehiclePropertyType::INT32);
270 unsubscribedValue->prop = VehicleProperty::HVAC_FAN_SPEED;
271
272 hal->sendPropEvent(std::move(unsubscribedValue));
273 auto& receivedEnvents = cb->getReceivedEvents();
274
275 ASSERT_TRUE(cb->waitForExpectedEvents(0)) << " Unexpected events received: "
Pavel Maltsevdb179c52016-10-27 15:43:06 -0700276 << receivedEnvents.size()
277 << (receivedEnvents.size() > 0
278 ? toString(receivedEnvents.front()[0]) : "");
Pavel Maltseve2603e32016-10-25 16:03:23 -0700279
280 auto subscribedValue = objectPool->obtain(VehiclePropertyType::INT32);
281 subscribedValue->prop = PROP;
282 subscribedValue->value.int32Values[0] = 42;
283
284 cb->reset();
285 VehiclePropValue actualValue(*subscribedValue.get());
286 hal->sendPropEvent(std::move(subscribedValue));
287
288 ASSERT_TRUE(cb->waitForExpectedEvents(1)) << "Events received: "
Pavel Maltsevdb179c52016-10-27 15:43:06 -0700289 << receivedEnvents.size();
Pavel Maltseve2603e32016-10-25 16:03:23 -0700290
291 ASSERT_EQ(toString(actualValue),
292 toString(cb->getReceivedEvents().front()[0]));
293}
294
Pavel Maltsevdb179c52016-10-27 15:43:06 -0700295TEST_F(VehicleHalManagerTest, subscribe_WriteOnly) {
296 const VehicleProperty PROP = VehicleProperty::HVAC_SEAT_TEMPERATURE;
297
298 sp<MockedVehicleCallback> cb = new MockedVehicleCallback();
299
Pavel Maltsev0e0a9252016-12-05 11:03:52 -0800300 hidl_vec<SubscribeOptions> options = {
301 SubscribeOptions {
302 .propId = PROP,
303 .flags = SubscribeFlags::HAL_EVENT
304 },
305 };
Pavel Maltsevdb179c52016-10-27 15:43:06 -0700306
307 StatusCode res = manager->subscribe(cb, options);
308 // Unable to subscribe on Hal Events for write-only properties.
309 ASSERT_EQ(StatusCode::INVALID_ARG, res);
310
311
312 options[0].flags = SubscribeFlags::SET_CALL;
313
314 res = manager->subscribe(cb, options);
315 // OK to subscribe on SET method call for write-only properties.
316 ASSERT_EQ(StatusCode::OK, res);
317}
318
Pavel Maltsevf21639f2016-12-22 11:17:29 -0800319TEST_F(VehicleHalManagerTest, get_Complex) {
320 invokeGet(VehicleProperty::VEHICLE_MAPS_DATA_SERVICE, 0);
321
322 ASSERT_EQ(StatusCode::OK, actualStatusCode);
323 ASSERT_EQ(VehicleProperty::VEHICLE_MAPS_DATA_SERVICE, actualValue.prop);
324
325 ASSERT_EQ(3, actualValue.value.bytes.size());
326 ASSERT_EQ(1, actualValue.value.bytes[0]);
327 ASSERT_EQ(2, actualValue.value.bytes[1]);
328 ASSERT_EQ(3, actualValue.value.bytes[2]);
329
330 ASSERT_EQ(2, actualValue.value.int32Values.size());
331 ASSERT_EQ(10, actualValue.value.int32Values[0]);
332 ASSERT_EQ(20, actualValue.value.int32Values[1]);
333
334 ASSERT_EQ(2, actualValue.value.floatValues.size());
335 ASSERT_FLOAT_EQ(1.1, actualValue.value.floatValues[0]);
336 ASSERT_FLOAT_EQ(2.2, actualValue.value.floatValues[1]);
337
338 ASSERT_EQ(2, actualValue.value.int64Values.size());
339 ASSERT_FLOAT_EQ(30, actualValue.value.int64Values[0]);
340 ASSERT_FLOAT_EQ(40, actualValue.value.int64Values[1]);
341
342 ASSERT_STREQ(kCarMake, actualValue.value.stringValue.c_str());
343}
344
Pavel Maltsevdb179c52016-10-27 15:43:06 -0700345TEST_F(VehicleHalManagerTest, get_StaticString) {
346 invokeGet(VehicleProperty::INFO_MAKE, 0);
347
348 ASSERT_EQ(StatusCode::OK, actualStatusCode);
349 ASSERT_EQ(VehicleProperty::INFO_MAKE, actualValue.prop);
350 ASSERT_STREQ(kCarMake, actualValue.value.stringValue.c_str());
351}
352
353TEST_F(VehicleHalManagerTest, get_NegativeCases) {
354 // Write-only property must fail.
355 invokeGet(VehicleProperty::HVAC_SEAT_TEMPERATURE, 0);
Pavel Maltsev85db07a2017-01-17 17:45:00 -0800356 ASSERT_EQ(StatusCode::ACCESS_DENIED, actualStatusCode);
Pavel Maltsevdb179c52016-10-27 15:43:06 -0700357
358 // Unknown property must fail.
359 invokeGet(VehicleProperty::MIRROR_Z_MOVE, 0);
360 ASSERT_EQ(StatusCode::INVALID_ARG, actualStatusCode);
361}
362
363TEST_F(VehicleHalManagerTest, get_Retriable) {
364 actualStatusCode = StatusCode::TRY_AGAIN;
365 int attempts = 0;
366 while (StatusCode::TRY_AGAIN == actualStatusCode && ++attempts < 10) {
367 invokeGet(VehicleProperty::INFO_FUEL_CAPACITY, 0);
368
369 }
370 ASSERT_EQ(StatusCode::OK, actualStatusCode);
371 ASSERT_EQ(kRetriablePropMockedAttempts + 1, attempts);
372 ASSERT_FLOAT_EQ(42.42, actualValue.value.floatValues[0]);
373}
374
375TEST_F(VehicleHalManagerTest, set_Basic) {
376 const auto PROP = VehicleProperty::DISPLAY_BRIGHTNESS;
377 const auto VAL = 7;
378
379 auto expectedValue = hal->getValuePool()->obtainInt32(VAL);
380 expectedValue->prop = PROP;
381 expectedValue->areaId = 0;
382
383 actualStatusCode = manager->set(*expectedValue.get());
384 ASSERT_EQ(StatusCode::OK, actualStatusCode);
385
386 invokeGet(PROP, 0);
387 ASSERT_EQ(StatusCode::OK, actualStatusCode);
388 ASSERT_EQ(PROP, actualValue.prop);
389 ASSERT_EQ(VAL, actualValue.value.int32Values[0]);
390}
391
392TEST_F(VehicleHalManagerTest, set_DifferentAreas) {
393 const auto PROP = VehicleProperty::HVAC_FAN_SPEED;
394 const auto VAL1 = 1;
395 const auto VAL2 = 2;
396 const auto AREA1 = toInt(VehicleAreaZone::ROW_1_LEFT);
397 const auto AREA2 = toInt(VehicleAreaZone::ROW_1_RIGHT);
398
399 {
400 auto expectedValue1 = hal->getValuePool()->obtainInt32(VAL1);
401 expectedValue1->prop = PROP;
402 expectedValue1->areaId = AREA1;
403 actualStatusCode = manager->set(*expectedValue1.get());
404 ASSERT_EQ(StatusCode::OK, actualStatusCode);
405
406 auto expectedValue2 = hal->getValuePool()->obtainInt32(VAL2);
407 expectedValue2->prop = PROP;
408 expectedValue2->areaId = AREA2;
409 actualStatusCode = manager->set(*expectedValue2.get());
410 ASSERT_EQ(StatusCode::OK, actualStatusCode);
411 }
412
413 {
414 invokeGet(PROP, AREA1);
415 ASSERT_EQ(StatusCode::OK, actualStatusCode);
416 ASSERT_EQ(PROP, actualValue.prop);
417 ASSERT_EQ(AREA1, actualValue.areaId);
418 ASSERT_EQ(VAL1, actualValue.value.int32Values[0]);
419
420 invokeGet(PROP, AREA2);
421 ASSERT_EQ(StatusCode::OK, actualStatusCode);
422 ASSERT_EQ(PROP, actualValue.prop);
423 ASSERT_EQ(AREA2, actualValue.areaId);
424 ASSERT_EQ(VAL2, actualValue.value.int32Values[0]);
425 }
426}
427
428TEST_F(VehicleHalManagerTest, set_Retriable) {
429 const auto PROP = VehicleProperty::MIRROR_FOLD;
430
431 auto v = hal->getValuePool()->obtainBoolean(true);
432 v->prop = PROP;
433 v->areaId = 0;
434
435 actualStatusCode = StatusCode::TRY_AGAIN;
436 int attempts = 0;
437 while (StatusCode::TRY_AGAIN == actualStatusCode && ++attempts < 10) {
438 actualStatusCode = manager->set(*v.get());
439 }
440
441 ASSERT_EQ(StatusCode::OK, actualStatusCode);
442 ASSERT_EQ(kRetriablePropMockedAttempts + 1, attempts);
443
444 invokeGet(PROP, 0);
445 ASSERT_EQ(StatusCode::OK, actualStatusCode);
446 ASSERT_TRUE(actualValue.value.int32Values[0]);
447}
448
449TEST(HalClientVectorTest, basic) {
450 HalClientVector clients;
Pavel Maltseve2603e32016-10-25 16:03:23 -0700451 sp<IVehicleCallback> callback1 = new MockedVehicleCallback();
452
453 sp<HalClient> c1 = new HalClient(callback1, 10, 20);
454 sp<HalClient> c2 = new HalClient(callback1, 10, 20);
455
456 clients.addOrUpdate(c1);
457 clients.addOrUpdate(c1);
458 clients.addOrUpdate(c2);
459 ASSERT_EQ(2u, clients.size());
460 ASSERT_FALSE(clients.isEmpty());
Pavel Maltsev6fee6282016-12-02 16:43:24 -0800461 ASSERT_LE(0, clients.indexOf(c1));
462 ASSERT_LE(0, clients.remove(c1));
463 ASSERT_GT(0, clients.indexOf(c1)); // c1 was already removed
464 ASSERT_GT(0, clients.remove(c1)); // attempt to remove c1 again
465 ASSERT_LE(0, clients.remove(c2));
Pavel Maltseve2603e32016-10-25 16:03:23 -0700466
467 ASSERT_TRUE(clients.isEmpty());
468}
469
470} // namespace anonymous
471
472} // namespace V2_0
473} // namespace vehicle
474} // namespace hardware
475} // namespace android