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 "ConnectedClient.h"
18 #include "DefaultVehicleHal.h"
19 #include "MockVehicleCallback.h"
20 #include "MockVehicleHardware.h"
21
22 #include <IVehicleHardware.h>
23 #include <LargeParcelableBase.h>
24 #include <aidl/android/hardware/automotive/vehicle/IVehicle.h>
25 #include <aidl/android/hardware/automotive/vehicle/IVehicleCallback.h>
26
27 #include <android-base/thread_annotations.h>
28 #include <gmock/gmock.h>
29 #include <gtest/gtest.h>
30 #include <sys/mman.h>
31 #include <utils/Log.h>
32 #include <utils/SystemClock.h>
33
34 #include <chrono>
35 #include <list>
36 #include <memory>
37 #include <mutex>
38 #include <optional>
39 #include <thread>
40 #include <unordered_map>
41 #include <vector>
42
43 namespace android {
44 namespace hardware {
45 namespace automotive {
46 namespace vehicle {
47
48 namespace {
49
50 using ::aidl::android::hardware::automotive::vehicle::GetValueRequest;
51 using ::aidl::android::hardware::automotive::vehicle::GetValueRequests;
52 using ::aidl::android::hardware::automotive::vehicle::GetValueResult;
53 using ::aidl::android::hardware::automotive::vehicle::GetValueResults;
54 using ::aidl::android::hardware::automotive::vehicle::IVehicle;
55 using ::aidl::android::hardware::automotive::vehicle::IVehicleCallback;
56 using ::aidl::android::hardware::automotive::vehicle::SetValueRequest;
57 using ::aidl::android::hardware::automotive::vehicle::SetValueRequests;
58 using ::aidl::android::hardware::automotive::vehicle::SetValueResult;
59 using ::aidl::android::hardware::automotive::vehicle::SetValueResults;
60 using ::aidl::android::hardware::automotive::vehicle::StatusCode;
61 using ::aidl::android::hardware::automotive::vehicle::SubscribeOptions;
62 using ::aidl::android::hardware::automotive::vehicle::VehicleAreaWindow;
63 using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig;
64 using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfigs;
65 using ::aidl::android::hardware::automotive::vehicle::VehiclePropError;
66 using ::aidl::android::hardware::automotive::vehicle::VehiclePropErrors;
67 using ::aidl::android::hardware::automotive::vehicle::VehicleProperty;
68 using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyAccess;
69 using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyChangeMode;
70 using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
71 using ::aidl::android::hardware::automotive::vehicle::VehiclePropValues;
72
73 using ::android::automotive::car_binder_lib::LargeParcelableBase;
74 using ::android::base::Result;
75
76 using ::ndk::ScopedAStatus;
77 using ::ndk::ScopedFileDescriptor;
78 using ::ndk::SpAIBinder;
79
80 using ::testing::ContainsRegex;
81 using ::testing::Eq;
82 using ::testing::UnorderedElementsAre;
83 using ::testing::UnorderedElementsAreArray;
84 using ::testing::WhenSortedBy;
85
86 constexpr int32_t INVALID_PROP_ID = 0;
87 // VehiclePropertyGroup:SYSTEM,VehicleArea:WINDOW,VehiclePropertyType:INT32
88 constexpr int32_t INT32_WINDOW_PROP = 10001 + 0x10000000 + 0x03000000 + 0x00400000;
89 // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
90 constexpr int32_t GLOBAL_ON_CHANGE_PROP = 10002 + 0x10000000 + 0x01000000 + 0x00400000;
91 // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
92 constexpr int32_t GLOBAL_CONTINUOUS_PROP = 10003 + 0x10000000 + 0x01000000 + 0x00400000;
93 // VehiclePropertyGroup:SYSTEM,VehicleArea:WINDOW,VehiclePropertyType:INT32
94 constexpr int32_t AREA_ON_CHANGE_PROP = 10004 + 0x10000000 + 0x03000000 + 0x00400000;
95 // VehiclePropertyGroup:SYSTEM,VehicleArea:WINDOW,VehiclePropertyType:INT32
96 constexpr int32_t AREA_CONTINUOUS_PROP = 10005 + 0x10000000 + 0x03000000 + 0x00400000;
97 // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
98 constexpr int32_t READ_ONLY_PROP = 10006 + 0x10000000 + 0x01000000 + 0x00400000;
99 // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
100 constexpr int32_t WRITE_ONLY_PROP = 10007 + 0x10000000 + 0x01000000 + 0x00400000;
101
testInt32VecProp(size_t i)102 int32_t testInt32VecProp(size_t i) {
103 // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32_VEC
104 return static_cast<int32_t>(i) + 0x10000000 + 0x01000000 + 0x00410000;
105 }
106
107 struct PropConfigCmp {
operator ()android::hardware::automotive::vehicle::__anon060c6f7d0111::PropConfigCmp108 bool operator()(const VehiclePropConfig& a, const VehiclePropConfig& b) const {
109 return (a.prop < b.prop);
110 }
111 } propConfigCmp;
112
113 struct SetValuesInvalidRequestTestCase {
114 std::string name;
115 VehiclePropValue request;
116 StatusCode expectedStatus;
117 };
118
getSetValuesInvalidRequestTestCases()119 std::vector<SetValuesInvalidRequestTestCase> getSetValuesInvalidRequestTestCases() {
120 return {{
121 .name = "config_not_found",
122 .request =
123 {
124 // No config for INVALID_PROP_ID.
125 .prop = INVALID_PROP_ID,
126 },
127 .expectedStatus = StatusCode::INVALID_ARG,
128 },
129 {
130 .name = "invalid_prop_value",
131 .request =
132 {
133 .prop = testInt32VecProp(0),
134 // No int32Values for INT32_VEC property.
135 .value.int32Values = {},
136 },
137 .expectedStatus = StatusCode::INVALID_ARG,
138 },
139 {
140 .name = "value_out_of_range",
141 .request =
142 {
143 .prop = testInt32VecProp(0),
144 // We configured the range to be 0-100.
145 .value.int32Values = {0, -1},
146 },
147 .expectedStatus = StatusCode::INVALID_ARG,
148 },
149 {
150 .name = "invalid_area",
151 .request =
152 {
153 .prop = INT32_WINDOW_PROP,
154 .value.int32Values = {0},
155 // Only ROW_1_LEFT is allowed.
156 .areaId = toInt(VehicleAreaWindow::ROW_1_RIGHT),
157 },
158 .expectedStatus = StatusCode::INVALID_ARG,
159 },
160 {
161 .name = "no_write_permission",
162 .request =
163 {
164 .prop = READ_ONLY_PROP,
165 .value.int32Values = {0},
166 },
167 .expectedStatus = StatusCode::ACCESS_DENIED,
168 }};
169 }
170
171 struct SubscribeInvalidOptionsTestCase {
172 std::string name;
173 SubscribeOptions option;
174 };
175
getSubscribeInvalidOptionsTestCases()176 std::vector<SubscribeInvalidOptionsTestCase> getSubscribeInvalidOptionsTestCases() {
177 return {{
178 .name = "invalid_prop",
179 .option =
180 {
181 .propId = INVALID_PROP_ID,
182 },
183 },
184 {
185 .name = "invalid_area_ID",
186 .option =
187 {
188 .propId = AREA_ON_CHANGE_PROP,
189 .areaIds = {0},
190 },
191 },
192 {
193 .name = "invalid_sample_rate",
194 .option =
195 {
196 .propId = GLOBAL_CONTINUOUS_PROP,
197 .sampleRate = 0.0,
198 },
199 },
200 {
201 .name = "static_property",
202 .option =
203 {
204 // Default change mode is static.
205 .propId = testInt32VecProp(0),
206 },
207 }};
208 }
209
210 } // namespace
211
212 class DefaultVehicleHalTest : public testing::Test {
213 public:
SetUp()214 void SetUp() override {
215 auto hardware = std::make_unique<MockVehicleHardware>();
216 std::vector<VehiclePropConfig> testConfigs;
217 for (size_t i = 0; i < 10000; i++) {
218 testConfigs.push_back(VehiclePropConfig{
219 .prop = testInt32VecProp(i),
220 .access = VehiclePropertyAccess::READ_WRITE,
221 .areaConfigs =
222 {
223 {
224 .areaId = 0,
225 .minInt32Value = 0,
226 .maxInt32Value = 100,
227 },
228 },
229 });
230 }
231 // A property with area config.
232 testConfigs.push_back(
233 VehiclePropConfig{.prop = INT32_WINDOW_PROP,
234 .access = VehiclePropertyAccess::READ_WRITE,
235 .areaConfigs = {{
236 .areaId = toInt(VehicleAreaWindow::ROW_1_LEFT),
237 .minInt32Value = 0,
238 .maxInt32Value = 100,
239 }}});
240 // A global on-change property.
241 testConfigs.push_back(VehiclePropConfig{
242 .prop = GLOBAL_ON_CHANGE_PROP,
243 .access = VehiclePropertyAccess::READ_WRITE,
244 .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
245 });
246 // A global continuous property.
247 testConfigs.push_back(VehiclePropConfig{
248 .prop = GLOBAL_CONTINUOUS_PROP,
249 .access = VehiclePropertyAccess::READ_WRITE,
250 .changeMode = VehiclePropertyChangeMode::CONTINUOUS,
251 .minSampleRate = 0.0,
252 .maxSampleRate = 100.0,
253 });
254 // A per-area on-change property.
255 testConfigs.push_back(VehiclePropConfig{
256 .prop = AREA_ON_CHANGE_PROP,
257 .access = VehiclePropertyAccess::READ_WRITE,
258 .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
259 .areaConfigs =
260 {
261 {
262
263 .areaId = toInt(VehicleAreaWindow::ROW_1_LEFT),
264 .minInt32Value = 0,
265 .maxInt32Value = 100,
266 },
267 {
268 .areaId = toInt(VehicleAreaWindow::ROW_1_RIGHT),
269 .minInt32Value = 0,
270 .maxInt32Value = 100,
271 },
272 },
273 });
274 // A per-area continuous property.
275 testConfigs.push_back(VehiclePropConfig{
276 .prop = AREA_CONTINUOUS_PROP,
277 .access = VehiclePropertyAccess::READ_WRITE,
278 .changeMode = VehiclePropertyChangeMode::CONTINUOUS,
279 .minSampleRate = 0.0,
280 .maxSampleRate = 1000.0,
281 .areaConfigs =
282 {
283 {
284
285 .areaId = toInt(VehicleAreaWindow::ROW_1_LEFT),
286 .minInt32Value = 0,
287 .maxInt32Value = 100,
288 },
289 {
290 .areaId = toInt(VehicleAreaWindow::ROW_1_RIGHT),
291 .minInt32Value = 0,
292 .maxInt32Value = 100,
293 },
294 },
295 });
296 // A read-only property.
297 testConfigs.push_back(VehiclePropConfig{
298 .prop = READ_ONLY_PROP,
299 .access = VehiclePropertyAccess::READ,
300 .changeMode = VehiclePropertyChangeMode::CONTINUOUS,
301 .minSampleRate = 0.0,
302 .maxSampleRate = 1000.0,
303 });
304 // A write-only property.
305 testConfigs.push_back(VehiclePropConfig{
306 .prop = WRITE_ONLY_PROP,
307 .access = VehiclePropertyAccess::WRITE,
308 .changeMode = VehiclePropertyChangeMode::CONTINUOUS,
309 .minSampleRate = 0.0,
310 .maxSampleRate = 1000.0,
311 });
312 // Register the heartbeat event property.
313 testConfigs.push_back(VehiclePropConfig{
314 .prop = toInt(VehicleProperty::VHAL_HEARTBEAT),
315 .access = VehiclePropertyAccess::READ,
316 .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
317 });
318 hardware->setPropertyConfigs(testConfigs);
319 mHardwarePtr = hardware.get();
320 mVhal = ndk::SharedRefBase::make<DefaultVehicleHal>(std::move(hardware));
321 mVhalClient = IVehicle::fromBinder(mVhal->asBinder());
322 mCallback = ndk::SharedRefBase::make<MockVehicleCallback>();
323 // Keep the local binder alive.
324 mBinder = mCallback->asBinder();
325 mCallbackClient = IVehicleCallback::fromBinder(mBinder);
326
327 // Set the linkToDeath to a fake implementation that always returns OK.
328 auto handler = std::make_unique<TestBinderLifecycleHandler>();
329 mBinderLifecycleHandler = handler.get();
330 mVhal->setBinderLifecycleHandler(std::move(handler));
331 }
332
TearDown()333 void TearDown() override {
334 ASSERT_EQ(countPendingRequests(), static_cast<size_t>(0))
335 << "must have no pending requests when test finishes";
336 }
337
getHardware()338 MockVehicleHardware* getHardware() { return mHardwarePtr; }
339
getClient()340 std::shared_ptr<IVehicle> getClient() { return mVhal; }
341
getCallbackClient()342 std::shared_ptr<IVehicleCallback> getCallbackClient() { return mCallbackClient; }
343
getCallback()344 MockVehicleCallback* getCallback() { return mCallback.get(); }
345
setTimeout(int64_t timeoutInNano)346 void setTimeout(int64_t timeoutInNano) { mVhal->setTimeout(timeoutInNano); }
347
countPendingRequests()348 size_t countPendingRequests() { return mVhal->mPendingRequestPool->countPendingRequests(); }
349
countClients()350 size_t countClients() {
351 std::scoped_lock<std::mutex> lockGuard(mVhal->mLock);
352 return mVhal->mGetValuesClients.size() + mVhal->mSetValuesClients.size() +
353 mVhal->mSubscriptionClients->countClients();
354 }
355
getPool()356 std::shared_ptr<PendingRequestPool> getPool() { return mVhal->mPendingRequestPool; }
357
onBinderDied(void * cookie)358 void onBinderDied(void* cookie) { return mVhal->onBinderDied(cookie); }
359
onBinderUnlinked(void * cookie)360 void onBinderUnlinked(void* cookie) { return mVhal->onBinderUnlinked(cookie); }
361
getOnBinderDiedContexts(AIBinder * clientId)362 void* getOnBinderDiedContexts(AIBinder* clientId) {
363 std::scoped_lock<std::mutex> lockGuard(mVhal->mLock);
364 return mVhal->mOnBinderDiedContexts[clientId].get();
365 }
366
countOnBinderDiedContexts()367 size_t countOnBinderDiedContexts() {
368 std::scoped_lock<std::mutex> lockGuard(mVhal->mLock);
369 return mVhal->mOnBinderDiedContexts.size();
370 }
371
hasNoSubscriptions()372 bool hasNoSubscriptions() { return mVhal->mSubscriptionManager->isEmpty(); }
373
setBinderAlive(bool isAlive)374 void setBinderAlive(bool isAlive) { mBinderLifecycleHandler->setAlive(isAlive); };
375
getValuesTestCases(size_t size,GetValueRequests & requests,std::vector<GetValueResult> & expectedResults,std::vector<GetValueRequest> & expectedHardwareRequests)376 static Result<void> getValuesTestCases(size_t size, GetValueRequests& requests,
377 std::vector<GetValueResult>& expectedResults,
378 std::vector<GetValueRequest>& expectedHardwareRequests) {
379 expectedHardwareRequests.clear();
380 for (size_t i = 0; i < size; i++) {
381 int64_t requestId = static_cast<int64_t>(i);
382 int32_t propId = testInt32VecProp(i);
383 expectedHardwareRequests.push_back(GetValueRequest{
384 .prop =
385 VehiclePropValue{
386 .prop = propId,
387 },
388 .requestId = requestId,
389 });
390 expectedResults.push_back(GetValueResult{
391 .requestId = requestId,
392 .status = StatusCode::OK,
393 .prop =
394 VehiclePropValue{
395 .prop = propId,
396 .value.int32Values = {1, 2, 3, 4},
397 },
398 });
399 }
400
401 requests.payloads = expectedHardwareRequests;
402 auto result = LargeParcelableBase::parcelableToStableLargeParcelable(requests);
403 if (!result.ok()) {
404 return result.error();
405 }
406 if (result.value() != nullptr) {
407 requests.sharedMemoryFd = std::move(*result.value());
408 requests.payloads.clear();
409 }
410 return {};
411 }
412
setValuesTestCases(size_t size,SetValueRequests & requests,std::vector<SetValueResult> & expectedResults,std::vector<SetValueRequest> & expectedHardwareRequests)413 static Result<void> setValuesTestCases(size_t size, SetValueRequests& requests,
414 std::vector<SetValueResult>& expectedResults,
415 std::vector<SetValueRequest>& expectedHardwareRequests) {
416 expectedHardwareRequests.clear();
417 for (size_t i = 0; i < size; i++) {
418 int64_t requestId = static_cast<int64_t>(i);
419 int32_t propId = testInt32VecProp(i);
420 expectedHardwareRequests.push_back(SetValueRequest{
421 .value =
422 VehiclePropValue{
423 .prop = propId,
424 .value.int32Values = {1, 2, 3, 4},
425 },
426 .requestId = requestId,
427 });
428 expectedResults.push_back(SetValueResult{
429 .requestId = requestId,
430 .status = StatusCode::OK,
431 });
432 }
433
434 requests.payloads = expectedHardwareRequests;
435 auto result = LargeParcelableBase::parcelableToStableLargeParcelable(requests);
436 if (!result.ok()) {
437 return result.error();
438 }
439 if (result.value() != nullptr) {
440 requests.payloads.clear();
441 requests.sharedMemoryFd = std::move(*result.value());
442 requests.payloads.clear();
443 }
444 return {};
445 }
446
447 private:
448 class TestBinderLifecycleHandler final : public DefaultVehicleHal::BinderLifecycleInterface {
449 public:
linkToDeath(AIBinder *,AIBinder_DeathRecipient *,void *)450 binder_status_t linkToDeath(AIBinder*, AIBinder_DeathRecipient*, void*) override {
451 if (mIsAlive) {
452 return STATUS_OK;
453 } else {
454 return STATUS_FAILED_TRANSACTION;
455 }
456 }
457
isAlive(const AIBinder *)458 bool isAlive(const AIBinder*) override { return mIsAlive; }
459
setAlive(bool isAlive)460 void setAlive(bool isAlive) { mIsAlive = isAlive; }
461
462 private:
463 bool mIsAlive = true;
464 };
465
466 std::shared_ptr<DefaultVehicleHal> mVhal;
467 std::shared_ptr<IVehicle> mVhalClient;
468 MockVehicleHardware* mHardwarePtr;
469 std::shared_ptr<MockVehicleCallback> mCallback;
470 std::shared_ptr<IVehicleCallback> mCallbackClient;
471 SpAIBinder mBinder;
472 TestBinderLifecycleHandler* mBinderLifecycleHandler;
473 };
474
TEST_F(DefaultVehicleHalTest,testGetAllPropConfigsSmall)475 TEST_F(DefaultVehicleHalTest, testGetAllPropConfigsSmall) {
476 auto testConfigs = std::vector<VehiclePropConfig>({
477 VehiclePropConfig{
478 .prop = 1,
479 },
480 VehiclePropConfig{
481 .prop = 2,
482 },
483 });
484
485 auto hardware = std::make_unique<MockVehicleHardware>();
486 hardware->setPropertyConfigs(testConfigs);
487 auto vhal = ndk::SharedRefBase::make<DefaultVehicleHal>(std::move(hardware));
488 std::shared_ptr<IVehicle> client = IVehicle::fromBinder(vhal->asBinder());
489
490 VehiclePropConfigs output;
491 auto status = client->getAllPropConfigs(&output);
492
493 ASSERT_TRUE(status.isOk()) << "getAllPropConfigs failed: " << status.getMessage();
494 ASSERT_THAT(output.payloads, WhenSortedBy(propConfigCmp, Eq(testConfigs)));
495 }
496
TEST_F(DefaultVehicleHalTest,testGetAllPropConfigsLarge)497 TEST_F(DefaultVehicleHalTest, testGetAllPropConfigsLarge) {
498 std::vector<VehiclePropConfig> testConfigs;
499 // 5000 VehiclePropConfig exceeds 4k memory limit, so it would be sent through shared memory.
500 for (size_t i = 0; i < 5000; i++) {
501 testConfigs.push_back(VehiclePropConfig{
502 .prop = static_cast<int32_t>(i),
503 });
504 }
505
506 auto hardware = std::make_unique<MockVehicleHardware>();
507 hardware->setPropertyConfigs(testConfigs);
508 auto vhal = ndk::SharedRefBase::make<DefaultVehicleHal>(std::move(hardware));
509 std::shared_ptr<IVehicle> client = IVehicle::fromBinder(vhal->asBinder());
510
511 VehiclePropConfigs output;
512 auto status = client->getAllPropConfigs(&output);
513
514 ASSERT_TRUE(status.isOk()) << "getAllPropConfigs failed: " << status.getMessage();
515 ASSERT_TRUE(output.payloads.empty());
516 auto result = LargeParcelableBase::stableLargeParcelableToParcelable(output);
517 ASSERT_TRUE(result.ok()) << "failed to parse result shared memory file: "
518 << result.error().message();
519 ASSERT_EQ(result.value().getObject()->payloads, testConfigs);
520 }
521
TEST_F(DefaultVehicleHalTest,testGetPropConfigs)522 TEST_F(DefaultVehicleHalTest, testGetPropConfigs) {
523 auto testConfigs = std::vector<VehiclePropConfig>({
524 VehiclePropConfig{
525 .prop = 1,
526 },
527 VehiclePropConfig{
528 .prop = 2,
529 },
530 });
531
532 auto hardware = std::make_unique<MockVehicleHardware>();
533 hardware->setPropertyConfigs(testConfigs);
534 auto vhal = ndk::SharedRefBase::make<DefaultVehicleHal>(std::move(hardware));
535 std::shared_ptr<IVehicle> client = IVehicle::fromBinder(vhal->asBinder());
536
537 VehiclePropConfigs output;
538 auto status = client->getPropConfigs(std::vector<int32_t>({1, 2}), &output);
539
540 ASSERT_TRUE(status.isOk()) << "getPropConfigs failed: " << status.getMessage();
541 ASSERT_EQ(output.payloads, testConfigs);
542 }
543
TEST_F(DefaultVehicleHalTest,testGetPropConfigsInvalidArg)544 TEST_F(DefaultVehicleHalTest, testGetPropConfigsInvalidArg) {
545 auto testConfigs = std::vector<VehiclePropConfig>({
546 VehiclePropConfig{
547 .prop = 1,
548 },
549 VehiclePropConfig{
550 .prop = 2,
551 },
552 });
553
554 auto hardware = std::make_unique<MockVehicleHardware>();
555 hardware->setPropertyConfigs(testConfigs);
556 auto vhal = ndk::SharedRefBase::make<DefaultVehicleHal>(std::move(hardware));
557 std::shared_ptr<IVehicle> client = IVehicle::fromBinder(vhal->asBinder());
558
559 VehiclePropConfigs output;
560 auto status = client->getPropConfigs(std::vector<int32_t>({1, 2, 3}), &output);
561
562 ASSERT_FALSE(status.isOk()) << "getPropConfigs must fail with invalid prop ID";
563 ASSERT_EQ(status.getServiceSpecificError(), toInt(StatusCode::INVALID_ARG));
564 }
565
TEST_F(DefaultVehicleHalTest,testGetValuesSmall)566 TEST_F(DefaultVehicleHalTest, testGetValuesSmall) {
567 GetValueRequests requests;
568 std::vector<GetValueResult> expectedResults;
569 std::vector<GetValueRequest> expectedHardwareRequests;
570
571 ASSERT_TRUE(getValuesTestCases(10, requests, expectedResults, expectedHardwareRequests).ok());
572
573 getHardware()->addGetValueResponses(expectedResults);
574
575 auto status = getClient()->getValues(getCallbackClient(), requests);
576
577 ASSERT_TRUE(status.isOk()) << "getValues failed: " << status.getMessage();
578
579 EXPECT_EQ(getHardware()->nextGetValueRequests(), expectedHardwareRequests)
580 << "requests to hardware mismatch";
581
582 auto maybeGetValueResults = getCallback()->nextGetValueResults();
583 ASSERT_TRUE(maybeGetValueResults.has_value()) << "no results in callback";
584 EXPECT_EQ(maybeGetValueResults.value().payloads, expectedResults) << "results mismatch";
585 EXPECT_EQ(countClients(), static_cast<size_t>(1));
586 }
587
TEST_F(DefaultVehicleHalTest,testGetValuesLarge)588 TEST_F(DefaultVehicleHalTest, testGetValuesLarge) {
589 GetValueRequests requests;
590 std::vector<GetValueResult> expectedResults;
591 std::vector<GetValueRequest> expectedHardwareRequests;
592
593 ASSERT_TRUE(getValuesTestCases(5000, requests, expectedResults, expectedHardwareRequests).ok())
594 << "requests to hardware mismatch";
595
596 getHardware()->addGetValueResponses(expectedResults);
597
598 auto status = getClient()->getValues(getCallbackClient(), requests);
599
600 ASSERT_TRUE(status.isOk()) << "getValues failed: " << status.getMessage();
601
602 EXPECT_EQ(getHardware()->nextGetValueRequests(), expectedHardwareRequests);
603
604 auto maybeGetValueResults = getCallback()->nextGetValueResults();
605 ASSERT_TRUE(maybeGetValueResults.has_value()) << "no results in callback";
606 const GetValueResults& getValueResults = maybeGetValueResults.value();
607 ASSERT_TRUE(getValueResults.payloads.empty())
608 << "payload should be empty, shared memory file should be used";
609
610 auto result = LargeParcelableBase::stableLargeParcelableToParcelable(getValueResults);
611 ASSERT_TRUE(result.ok()) << "failed to parse shared memory file";
612 ASSERT_EQ(result.value().getObject()->payloads, expectedResults) << "results mismatch";
613 EXPECT_EQ(countClients(), static_cast<size_t>(1));
614 }
615
TEST_F(DefaultVehicleHalTest,testGetValuesErrorFromHardware)616 TEST_F(DefaultVehicleHalTest, testGetValuesErrorFromHardware) {
617 GetValueRequests requests;
618 std::vector<GetValueResult> expectedResults;
619 std::vector<GetValueRequest> expectedHardwareRequests;
620
621 ASSERT_TRUE(getValuesTestCases(10, requests, expectedResults, expectedHardwareRequests).ok());
622
623 getHardware()->setStatus("getValues", StatusCode::INTERNAL_ERROR);
624
625 auto status = getClient()->getValues(getCallbackClient(), requests);
626
627 ASSERT_FALSE(status.isOk()) << "expect getValues to fail when hardware returns error";
628 ASSERT_EQ(status.getServiceSpecificError(), toInt(StatusCode::INTERNAL_ERROR));
629 }
630
TEST_F(DefaultVehicleHalTest,testGetValuesInvalidLargeParcelableInput)631 TEST_F(DefaultVehicleHalTest, testGetValuesInvalidLargeParcelableInput) {
632 GetValueRequests requests;
633 requests.sharedMemoryFd = ScopedFileDescriptor(0);
634
635 auto status = getClient()->getValues(getCallbackClient(), requests);
636
637 ASSERT_FALSE(status.isOk()) << "expect getValues to fail when input parcelable is not valid";
638 ASSERT_EQ(status.getServiceSpecificError(), toInt(StatusCode::INVALID_ARG));
639 }
640
TEST_F(DefaultVehicleHalTest,testGetValuesNoReadPermission)641 TEST_F(DefaultVehicleHalTest, testGetValuesNoReadPermission) {
642 GetValueRequests requests = {
643 .sharedMemoryFd = {},
644 .payloads =
645 {
646 {
647 .requestId = 0,
648 .prop =
649 {
650 .prop = WRITE_ONLY_PROP,
651 },
652 },
653 },
654 };
655
656 auto status = getClient()->getValues(getCallbackClient(), requests);
657
658 ASSERT_TRUE(status.isOk()) << "getValue with no read permission should return okay with error "
659 "returned from callback"
660 << ", error: " << status.getMessage();
661 EXPECT_TRUE(getHardware()->nextGetValueRequests().empty()) << "expect no request to hardware";
662
663 auto maybeResult = getCallback()->nextGetValueResults();
664 ASSERT_TRUE(maybeResult.has_value()) << "no results in callback";
665 EXPECT_EQ(maybeResult.value().payloads, std::vector<GetValueResult>({
666 {
667 .requestId = 0,
668 .status = StatusCode::ACCESS_DENIED,
669 },
670 }))
671 << "expect to get ACCESS_DENIED status if no read permission";
672 }
673
TEST_F(DefaultVehicleHalTest,testGetValuesFinishBeforeTimeout)674 TEST_F(DefaultVehicleHalTest, testGetValuesFinishBeforeTimeout) {
675 // timeout: 1s
676 int64_t timeout = 1000000000;
677 setTimeout(timeout);
678
679 GetValueRequests requests;
680 std::vector<GetValueResult> expectedResults;
681 std::vector<GetValueRequest> expectedHardwareRequests;
682
683 ASSERT_TRUE(getValuesTestCases(10, requests, expectedResults, expectedHardwareRequests).ok());
684
685 // The response would be returned after 0.01s.
686 getHardware()->setSleepTime(timeout / 100);
687 getHardware()->addGetValueResponses(expectedResults);
688
689 auto status = getClient()->getValues(getCallbackClient(), requests);
690
691 ASSERT_TRUE(status.isOk()) << "getValues failed: " << status.getMessage();
692
693 ASSERT_TRUE(getCallback()->waitForGetValueResults(1, timeout)) << "no results in callback";
694 auto maybeGetValueResults = getCallback()->nextGetValueResults();
695 ASSERT_TRUE(maybeGetValueResults.has_value()) << "no results in callback";
696 EXPECT_EQ(maybeGetValueResults.value().payloads, expectedResults) << "results mismatch";
697 ASSERT_FALSE(getCallback()->nextGetValueResults().has_value()) << "more results than expected";
698 }
699
TEST_F(DefaultVehicleHalTest,testGetValuesFinishAfterTimeout)700 TEST_F(DefaultVehicleHalTest, testGetValuesFinishAfterTimeout) {
701 // timeout: 0.01s
702 int64_t timeout = 10000000;
703 setTimeout(timeout);
704
705 GetValueRequests requests;
706 std::vector<GetValueResult> expectedResults;
707 std::vector<GetValueRequest> expectedHardwareRequests;
708
709 ASSERT_TRUE(getValuesTestCases(10, requests, expectedResults, expectedHardwareRequests).ok());
710
711 // The response would be returned after 0.1s.
712 getHardware()->setSleepTime(timeout * 10);
713 getHardware()->addGetValueResponses(expectedResults);
714
715 auto status = getClient()->getValues(getCallbackClient(), requests);
716
717 ASSERT_TRUE(status.isOk()) << "getValues failed: " << status.getMessage();
718
719 for (size_t i = 0; i < expectedResults.size(); i++) {
720 expectedResults[i] = {
721 .requestId = expectedResults[i].requestId,
722 .status = StatusCode::TRY_AGAIN,
723 .prop = std::nullopt,
724 };
725 }
726
727 ASSERT_TRUE(getCallback()->waitForGetValueResults(1, timeout * 100))
728 << "no results in callback";
729 auto maybeGetValueResults = getCallback()->nextGetValueResults();
730 ASSERT_TRUE(maybeGetValueResults.has_value()) << "no results in callback";
731 ASSERT_THAT(maybeGetValueResults.value().payloads, UnorderedElementsAreArray(expectedResults))
732 << "results mismatch, expect TRY_AGAIN error.";
733 ASSERT_FALSE(getCallback()->nextGetValueResults().has_value()) << "more results than expected";
734 }
735
TEST_F(DefaultVehicleHalTest,testGetValuesDuplicateRequestIdsInTwoRequests)736 TEST_F(DefaultVehicleHalTest, testGetValuesDuplicateRequestIdsInTwoRequests) {
737 // timeout: 0.1s
738 int64_t timeout = 100000000;
739 setTimeout(timeout);
740
741 GetValueRequests requests;
742 std::vector<GetValueResult> expectedResults;
743 std::vector<GetValueRequest> expectedHardwareRequests;
744
745 ASSERT_TRUE(getValuesTestCases(1, requests, expectedResults, expectedHardwareRequests).ok());
746
747 getHardware()->setSleepTime(timeout * 2);
748 getHardware()->addGetValueResponses(expectedResults);
749
750 auto status = getClient()->getValues(getCallbackClient(), requests);
751
752 ASSERT_TRUE(status.isOk()) << "getValues failed: " << status.getMessage();
753
754 // Use the same request ID again.
755 status = getClient()->getValues(getCallbackClient(), requests);
756
757 ASSERT_FALSE(status.isOk())
758 << "Use the same request ID before the previous request finishes must fail";
759
760 // Wait for the request to finish.
761 std::this_thread::sleep_for(std::chrono::nanoseconds(timeout * 5));
762 }
763
TEST_F(DefaultVehicleHalTest,testGetValuesDuplicateRequestIdsInOneRequest)764 TEST_F(DefaultVehicleHalTest, testGetValuesDuplicateRequestIdsInOneRequest) {
765 GetValueRequests requests = {.payloads = {
766 {
767 .requestId = 0,
768 .prop =
769 VehiclePropValue{
770 .prop = testInt32VecProp(0),
771 },
772 },
773 {
774 .requestId = 0,
775 .prop =
776 VehiclePropValue{
777 .prop = testInt32VecProp(1),
778 },
779 },
780 }};
781
782 auto status = getClient()->getValues(getCallbackClient(), requests);
783
784 ASSERT_FALSE(status.isOk()) << "duplicate Ids in one request must fail";
785 }
786
TEST_F(DefaultVehicleHalTest,testGetValuesDuplicateRequestProps)787 TEST_F(DefaultVehicleHalTest, testGetValuesDuplicateRequestProps) {
788 GetValueRequests requests = {.payloads = {
789 {
790 .requestId = 0,
791 .prop =
792 VehiclePropValue{
793 .prop = testInt32VecProp(0),
794 },
795 },
796 {
797 .requestId = 1,
798 .prop =
799 VehiclePropValue{
800 .prop = testInt32VecProp(0),
801 },
802 },
803 }};
804
805 auto status = getClient()->getValues(getCallbackClient(), requests);
806
807 ASSERT_FALSE(status.isOk()) << "duplicate request properties in one request must fail";
808 }
809
TEST_F(DefaultVehicleHalTest,testGetValuesNewClientDied)810 TEST_F(DefaultVehicleHalTest, testGetValuesNewClientDied) {
811 GetValueRequests requests;
812 std::vector<GetValueResult> expectedResults;
813 std::vector<GetValueRequest> expectedHardwareRequests;
814
815 ASSERT_TRUE(getValuesTestCases(10, requests, expectedResults, expectedHardwareRequests).ok());
816
817 getHardware()->addGetValueResponses(expectedResults);
818
819 setBinderAlive(false);
820
821 auto status = getClient()->getValues(getCallbackClient(), requests);
822
823 ASSERT_FALSE(status.isOk()) << "getValues must fail if client died";
824 ASSERT_EQ(status.getExceptionCode(), EX_TRANSACTION_FAILED);
825 EXPECT_EQ(countClients(), static_cast<size_t>(0))
826 << "No client should be created if the client binder died";
827 }
828
TEST_F(DefaultVehicleHalTest,testGetValuesExistingClientDied)829 TEST_F(DefaultVehicleHalTest, testGetValuesExistingClientDied) {
830 GetValueRequests requests;
831 std::vector<GetValueResult> expectedResults;
832 std::vector<GetValueRequest> expectedHardwareRequests;
833
834 ASSERT_TRUE(getValuesTestCases(10, requests, expectedResults, expectedHardwareRequests).ok());
835
836 getHardware()->addGetValueResponses(expectedResults);
837
838 // Try a normal getValue request to cache a GetValueClient first.
839 auto status = getClient()->getValues(getCallbackClient(), requests);
840
841 ASSERT_TRUE(status.isOk()) << "getValues failed: " << status.getMessage();
842 EXPECT_EQ(countClients(), static_cast<size_t>(1));
843
844 // The client binder died before onBinderUnlinked clean up the GetValueClient.
845 setBinderAlive(false);
846
847 status = getClient()->getValues(getCallbackClient(), requests);
848
849 ASSERT_FALSE(status.isOk()) << "getValues must fail if client died";
850 ASSERT_EQ(status.getExceptionCode(), EX_TRANSACTION_FAILED);
851 // The client count should still be 1 but onBinderUnlinked will remove this later.
852 EXPECT_EQ(countClients(), static_cast<size_t>(1));
853 }
854
TEST_F(DefaultVehicleHalTest,testSetValuesSmall)855 TEST_F(DefaultVehicleHalTest, testSetValuesSmall) {
856 SetValueRequests requests;
857 std::vector<SetValueResult> expectedResults;
858 std::vector<SetValueRequest> expectedHardwareRequests;
859
860 ASSERT_TRUE(setValuesTestCases(10, requests, expectedResults, expectedHardwareRequests).ok());
861
862 getHardware()->addSetValueResponses(expectedResults);
863
864 auto status = getClient()->setValues(getCallbackClient(), requests);
865
866 ASSERT_TRUE(status.isOk()) << "setValues failed: " << status.getMessage();
867
868 EXPECT_EQ(getHardware()->nextSetValueRequests(), expectedHardwareRequests)
869 << "requests to hardware mismatch";
870
871 auto maybeSetValueResults = getCallback()->nextSetValueResults();
872 ASSERT_TRUE(maybeSetValueResults.has_value()) << "no results in callback";
873 ASSERT_EQ(maybeSetValueResults.value().payloads, expectedResults) << "results mismatch";
874 EXPECT_EQ(countClients(), static_cast<size_t>(1));
875 }
876
TEST_F(DefaultVehicleHalTest,testSetValuesLarge)877 TEST_F(DefaultVehicleHalTest, testSetValuesLarge) {
878 SetValueRequests requests;
879 std::vector<SetValueResult> expectedResults;
880 std::vector<SetValueRequest> expectedHardwareRequests;
881
882 ASSERT_TRUE(setValuesTestCases(5000, requests, expectedResults, expectedHardwareRequests).ok());
883
884 getHardware()->addSetValueResponses(expectedResults);
885
886 auto status = getClient()->setValues(getCallbackClient(), requests);
887
888 ASSERT_TRUE(status.isOk()) << "setValues failed: " << status.getMessage();
889
890 EXPECT_EQ(getHardware()->nextSetValueRequests(), expectedHardwareRequests)
891 << "requests to hardware mismatch";
892
893 auto maybeSetValueResults = getCallback()->nextSetValueResults();
894 ASSERT_TRUE(maybeSetValueResults.has_value()) << "no results in callback";
895 const SetValueResults& setValueResults = maybeSetValueResults.value();
896 ASSERT_TRUE(setValueResults.payloads.empty())
897 << "payload should be empty, shared memory file should be used";
898
899 auto result = LargeParcelableBase::stableLargeParcelableToParcelable(setValueResults);
900 ASSERT_TRUE(result.ok()) << "failed to parse shared memory file";
901 ASSERT_EQ(result.value().getObject()->payloads, expectedResults) << "results mismatch";
902 EXPECT_EQ(countClients(), static_cast<size_t>(1));
903 }
904
905 class SetValuesInvalidRequestTest
906 : public DefaultVehicleHalTest,
907 public testing::WithParamInterface<SetValuesInvalidRequestTestCase> {};
908
909 INSTANTIATE_TEST_SUITE_P(
910 SetValuesInvalidRequestTests, SetValuesInvalidRequestTest,
911 testing::ValuesIn(getSetValuesInvalidRequestTestCases()),
__anon060c6f7d0202(const testing::TestParamInfo<SetValuesInvalidRequestTest::ParamType>& info) 912 [](const testing::TestParamInfo<SetValuesInvalidRequestTest::ParamType>& info) {
913 return info.param.name;
914 });
915
TEST_P(SetValuesInvalidRequestTest,testSetValuesInvalidRequest)916 TEST_P(SetValuesInvalidRequestTest, testSetValuesInvalidRequest) {
917 SetValuesInvalidRequestTestCase tc = GetParam();
918 std::vector<SetValueResult> expectedHardwareResults{
919 SetValueResult{
920 .requestId = 1,
921 .status = StatusCode::OK,
922 },
923 };
924 getHardware()->addSetValueResponses(expectedHardwareResults);
925
926 SetValueRequests requests;
927 SetValueRequest invalidRequest{
928 .requestId = 0,
929 .value = tc.request,
930 };
931 SetValueRequest normalRequest{.requestId = 1,
932 .value = {
933 .prop = testInt32VecProp(0),
934 .value.int32Values = {0},
935 }};
936 requests.payloads = {invalidRequest, normalRequest};
937 auto status = getClient()->setValues(getCallbackClient(), requests);
938
939 ASSERT_TRUE(status.isOk()) << "setValues failed: " << status.getMessage();
940
941 EXPECT_EQ(getHardware()->nextSetValueRequests(), std::vector<SetValueRequest>({normalRequest}))
942 << "requests to hardware mismatch";
943
944 auto maybeSetValueResults = getCallback()->nextSetValueResults();
945 ASSERT_TRUE(maybeSetValueResults.has_value()) << "no results in callback";
946 EXPECT_EQ(maybeSetValueResults.value().payloads, std::vector<SetValueResult>({
947 {
948 .requestId = 0,
949 .status = tc.expectedStatus,
950 },
951 }))
952 << "invalid argument result mismatch";
953
954 maybeSetValueResults = getCallback()->nextSetValueResults();
955 ASSERT_TRUE(maybeSetValueResults.has_value()) << "no results from hardware in callback";
956 EXPECT_EQ(maybeSetValueResults.value().payloads, expectedHardwareResults)
957 << "results from hardware mismatch";
958 }
959
TEST_F(DefaultVehicleHalTest,testSetValuesFinishBeforeTimeout)960 TEST_F(DefaultVehicleHalTest, testSetValuesFinishBeforeTimeout) {
961 // timeout: 1s
962 int64_t timeout = 1000000000;
963 setTimeout(timeout);
964
965 SetValueRequests requests;
966 std::vector<SetValueResult> expectedResults;
967 std::vector<SetValueRequest> expectedHardwareRequests;
968
969 ASSERT_TRUE(setValuesTestCases(10, requests, expectedResults, expectedHardwareRequests).ok());
970
971 // The response would be returned after 0.01s.
972 getHardware()->setSleepTime(timeout / 100);
973 getHardware()->addSetValueResponses(expectedResults);
974
975 auto status = getClient()->setValues(getCallbackClient(), requests);
976
977 ASSERT_TRUE(status.isOk()) << "setValues failed: " << status.getMessage();
978
979 ASSERT_TRUE(getCallback()->waitForSetValueResults(1, timeout)) << "no set value results";
980 auto maybeSetValueResults = getCallback()->nextSetValueResults();
981 ASSERT_TRUE(maybeSetValueResults.has_value()) << "no results in callback";
982 EXPECT_EQ(maybeSetValueResults.value().payloads, expectedResults) << "results mismatch";
983 ASSERT_FALSE(getCallback()->nextSetValueResults().has_value()) << "more results than expected";
984 }
985
TEST_F(DefaultVehicleHalTest,testSetValuesFinishAfterTimeout)986 TEST_F(DefaultVehicleHalTest, testSetValuesFinishAfterTimeout) {
987 // timeout: 0.01s
988 int64_t timeout = 10000000;
989 setTimeout(timeout);
990
991 SetValueRequests requests;
992 std::vector<SetValueResult> expectedResults;
993 std::vector<SetValueRequest> expectedHardwareRequests;
994
995 ASSERT_TRUE(setValuesTestCases(10, requests, expectedResults, expectedHardwareRequests).ok());
996
997 // The response would be returned after 0.1s.
998 getHardware()->setSleepTime(timeout * 10);
999 getHardware()->addSetValueResponses(expectedResults);
1000
1001 auto status = getClient()->setValues(getCallbackClient(), requests);
1002
1003 ASSERT_TRUE(status.isOk()) << "setValues failed: " << status.getMessage();
1004
1005 for (size_t i = 0; i < expectedResults.size(); i++) {
1006 expectedResults[i] = {
1007 .requestId = expectedResults[i].requestId,
1008 .status = StatusCode::TRY_AGAIN,
1009 };
1010 }
1011
1012 ASSERT_TRUE(getCallback()->waitForSetValueResults(1, timeout * 100)) << "no set value results";
1013 auto maybeSetValueResults = getCallback()->nextSetValueResults();
1014 ASSERT_TRUE(maybeSetValueResults.has_value()) << "no results in callback";
1015 ASSERT_THAT(maybeSetValueResults.value().payloads, UnorderedElementsAreArray(expectedResults))
1016 << "results mismatch, expect TRY_AGAIN error.";
1017 ASSERT_FALSE(getCallback()->nextSetValueResults().has_value()) << "more results than expected";
1018 }
1019
TEST_F(DefaultVehicleHalTest,testSetValuesDuplicateRequestIdsInTwoRequests)1020 TEST_F(DefaultVehicleHalTest, testSetValuesDuplicateRequestIdsInTwoRequests) {
1021 // timeout: 0.1s
1022 int64_t timeout = 100000000;
1023 setTimeout(timeout);
1024
1025 SetValueRequests requests;
1026 std::vector<SetValueResult> expectedResults;
1027 std::vector<SetValueRequest> expectedHardwareRequests;
1028
1029 ASSERT_TRUE(setValuesTestCases(1, requests, expectedResults, expectedHardwareRequests).ok());
1030
1031 getHardware()->setSleepTime(timeout * 2);
1032 getHardware()->addSetValueResponses(expectedResults);
1033
1034 auto status = getClient()->setValues(getCallbackClient(), requests);
1035
1036 ASSERT_TRUE(status.isOk()) << "setValues failed: " << status.getMessage();
1037
1038 // Use the same request ID again.
1039 status = getClient()->setValues(getCallbackClient(), requests);
1040
1041 ASSERT_FALSE(status.isOk())
1042 << "Use the same request ID before the previous request finishes must fail";
1043
1044 // Wait for the request to finish.
1045 std::this_thread::sleep_for(std::chrono::nanoseconds(timeout * 5));
1046 }
1047
TEST_F(DefaultVehicleHalTest,testSetValuesDuplicateRequestIdsInOneRequest)1048 TEST_F(DefaultVehicleHalTest, testSetValuesDuplicateRequestIdsInOneRequest) {
1049 SetValueRequests requests = {.payloads = {
1050 {
1051 .requestId = 0,
1052 .value =
1053 VehiclePropValue{
1054 .prop = testInt32VecProp(0),
1055 .value.int32Values = {0},
1056 },
1057 },
1058 {
1059 .requestId = 0,
1060 .value =
1061 VehiclePropValue{
1062 .prop = testInt32VecProp(1),
1063 .value.int32Values = {0},
1064 },
1065 },
1066 }};
1067
1068 auto status = getClient()->setValues(getCallbackClient(), requests);
1069
1070 ASSERT_FALSE(status.isOk()) << "duplicate Ids in one request must fail";
1071 }
1072
TEST_F(DefaultVehicleHalTest,testSetValuesDuplicateRequestProps)1073 TEST_F(DefaultVehicleHalTest, testSetValuesDuplicateRequestProps) {
1074 SetValueRequests requests = {.payloads = {
1075 {
1076 .requestId = 0,
1077 .value =
1078 VehiclePropValue{
1079 .prop = testInt32VecProp(0),
1080 .value.int32Values = {0},
1081 },
1082 },
1083 {
1084 .requestId = 1,
1085 .value =
1086 VehiclePropValue{
1087 .prop = testInt32VecProp(0),
1088 .value.int32Values = {0},
1089 },
1090 },
1091 }};
1092
1093 auto status = getClient()->setValues(getCallbackClient(), requests);
1094
1095 ASSERT_FALSE(status.isOk()) << "duplicate request properties in one request must fail";
1096 }
1097
TEST_F(DefaultVehicleHalTest,testSubscribeUnsubscribe)1098 TEST_F(DefaultVehicleHalTest, testSubscribeUnsubscribe) {
1099 std::vector<SubscribeOptions> options = {
1100 {
1101 .propId = GLOBAL_ON_CHANGE_PROP,
1102 },
1103 };
1104
1105 auto status = getClient()->subscribe(getCallbackClient(), options, 0);
1106
1107 ASSERT_TRUE(status.isOk()) << "subscribe failed: " << status.getMessage();
1108
1109 status = getClient()->unsubscribe(getCallbackClient(),
1110 std::vector<int32_t>({GLOBAL_ON_CHANGE_PROP}));
1111
1112 ASSERT_TRUE(status.isOk()) << "unsubscribe failed: " << status.getMessage();
1113 }
1114
TEST_F(DefaultVehicleHalTest,testSubscribeGlobalOnChangeNormal)1115 TEST_F(DefaultVehicleHalTest, testSubscribeGlobalOnChangeNormal) {
1116 std::vector<SubscribeOptions> options = {
1117 {
1118 .propId = GLOBAL_ON_CHANGE_PROP,
1119 },
1120 };
1121
1122 auto status = getClient()->subscribe(getCallbackClient(), options, 0);
1123
1124 ASSERT_TRUE(status.isOk()) << "subscribe failed: " << status.getMessage();
1125
1126 VehiclePropValue testValue{
1127 .prop = GLOBAL_ON_CHANGE_PROP,
1128 .value.int32Values = {0},
1129 };
1130 SetValueRequests setValueRequests = {
1131 .payloads =
1132 {
1133 SetValueRequest{
1134 .requestId = 0,
1135 .value = testValue,
1136 },
1137 },
1138 };
1139 std::vector<SetValueResult> setValueResults = {{
1140 .requestId = 0,
1141 .status = StatusCode::OK,
1142 }};
1143
1144 // Set the value to trigger a property change event.
1145 getHardware()->addSetValueResponses(setValueResults);
1146 status = getClient()->setValues(getCallbackClient(), setValueRequests);
1147
1148 ASSERT_TRUE(status.isOk()) << "setValues failed: " << status.getMessage();
1149
1150 auto maybeResults = getCallback()->nextOnPropertyEventResults();
1151 ASSERT_TRUE(maybeResults.has_value()) << "no results in callback";
1152 ASSERT_THAT(maybeResults.value().payloads, UnorderedElementsAre(testValue))
1153 << "results mismatch, expect on change event for the updated value";
1154 ASSERT_FALSE(getCallback()->nextOnPropertyEventResults().has_value())
1155 << "more results than expected";
1156 EXPECT_EQ(countClients(), static_cast<size_t>(2))
1157 << "expect 2 clients, 1 subscribe client and 1 setvalue client";
1158 }
1159
TEST_F(DefaultVehicleHalTest,testSubscribeGlobalOnchangeUnrelatedEventIgnored)1160 TEST_F(DefaultVehicleHalTest, testSubscribeGlobalOnchangeUnrelatedEventIgnored) {
1161 std::vector<SubscribeOptions> options = {
1162 {
1163 .propId = GLOBAL_ON_CHANGE_PROP,
1164 },
1165 };
1166
1167 auto status = getClient()->subscribe(getCallbackClient(), options, 0);
1168
1169 ASSERT_TRUE(status.isOk()) << "subscribe failed: " << status.getMessage();
1170
1171 VehiclePropValue testValue{
1172 .prop = GLOBAL_CONTINUOUS_PROP,
1173 .value.int32Values = {0},
1174 };
1175
1176 // Set the value to trigger a property change event. This event should be ignored because we
1177 // have not subscribed to it.
1178 getHardware()->addSetValueResponses({{
1179 .requestId = 0,
1180 .status = StatusCode::OK,
1181 }});
1182 status = getClient()->setValues(getCallbackClient(),
1183 {
1184 .payloads =
1185 {
1186 SetValueRequest{
1187 .requestId = 0,
1188 .value = testValue,
1189 },
1190 },
1191 });
1192
1193 ASSERT_TRUE(status.isOk()) << "setValues failed: " << status.getMessage();
1194
1195 ASSERT_FALSE(getCallback()->nextOnPropertyEventResults().has_value())
1196 << "must receive no property update event if the property is not subscribed";
1197 }
1198
TEST_F(DefaultVehicleHalTest,testSubscribeAreaOnChange)1199 TEST_F(DefaultVehicleHalTest, testSubscribeAreaOnChange) {
1200 int testAreaId = toInt(VehicleAreaWindow::ROW_1_LEFT);
1201 std::vector<SubscribeOptions> options = {
1202 {
1203 .propId = AREA_ON_CHANGE_PROP,
1204 .areaIds = {testAreaId},
1205 },
1206 };
1207
1208 auto status = getClient()->subscribe(getCallbackClient(), options, 0);
1209
1210 ASSERT_TRUE(status.isOk()) << "subscribe failed: " << status.getMessage();
1211
1212 VehiclePropValue testValue{
1213 .prop = AREA_ON_CHANGE_PROP,
1214 .areaId = testAreaId,
1215 .value.int32Values = {0},
1216 };
1217
1218 // Set the value to trigger a property change event.
1219 getHardware()->addSetValueResponses({{
1220 .requestId = 0,
1221 .status = StatusCode::OK,
1222 }});
1223 status = getClient()->setValues(getCallbackClient(),
1224 {
1225 .payloads =
1226 {
1227 SetValueRequest{
1228 .requestId = 0,
1229 .value = testValue,
1230 },
1231 },
1232 });
1233
1234 ASSERT_TRUE(status.isOk()) << "setValues failed: " << status.getMessage();
1235
1236 auto maybeResults = getCallback()->nextOnPropertyEventResults();
1237 ASSERT_TRUE(maybeResults.has_value()) << "no results in callback";
1238 ASSERT_THAT(maybeResults.value().payloads, UnorderedElementsAre(testValue))
1239 << "results mismatch, expect on change event for the updated value";
1240 ASSERT_FALSE(getCallback()->nextOnPropertyEventResults().has_value())
1241 << "more results than expected";
1242 }
1243
TEST_F(DefaultVehicleHalTest,testSubscribeAreaOnChangeAllAreas)1244 TEST_F(DefaultVehicleHalTest, testSubscribeAreaOnChangeAllAreas) {
1245 std::vector<SubscribeOptions> options = {
1246 {
1247 .propId = AREA_ON_CHANGE_PROP,
1248 // No areaIds means subscribing to all area IDs.
1249 .areaIds = {},
1250 },
1251 };
1252
1253 auto status = getClient()->subscribe(getCallbackClient(), options, 0);
1254
1255 ASSERT_TRUE(status.isOk()) << "subscribe failed: " << status.getMessage();
1256
1257 VehiclePropValue testValue1{
1258 .prop = AREA_ON_CHANGE_PROP,
1259 .areaId = toInt(VehicleAreaWindow::ROW_1_LEFT),
1260 .value.int32Values = {0},
1261 };
1262 VehiclePropValue testValue2{
1263 .prop = AREA_ON_CHANGE_PROP,
1264 .areaId = toInt(VehicleAreaWindow::ROW_1_RIGHT),
1265 .value.int32Values = {0},
1266 };
1267
1268 // Set the values to trigger property change events for two areas.
1269 getHardware()->addSetValueResponses({{
1270 .requestId = 0,
1271 .status = StatusCode::OK,
1272 },
1273 {
1274 .requestId = 1,
1275 .status = StatusCode::OK,
1276 }});
1277 status = getClient()->setValues(getCallbackClient(),
1278 {
1279 .payloads =
1280 {
1281 SetValueRequest{
1282 .requestId = 0,
1283 .value = testValue1,
1284 },
1285 SetValueRequest{
1286 .requestId = 1,
1287 .value = testValue2,
1288 },
1289 },
1290 });
1291
1292 ASSERT_TRUE(status.isOk()) << "setValues failed: " << status.getMessage();
1293
1294 auto maybeResults = getCallback()->nextOnPropertyEventResults();
1295 ASSERT_TRUE(maybeResults.has_value()) << "no results in callback";
1296 ASSERT_THAT(maybeResults.value().payloads, UnorderedElementsAre(testValue1, testValue2))
1297 << "results mismatch, expect two on-change events for all updated areas";
1298 ASSERT_FALSE(getCallback()->nextOnPropertyEventResults().has_value())
1299 << "more results than expected";
1300 }
1301
TEST_F(DefaultVehicleHalTest,testSubscribeGlobalContinuous)1302 TEST_F(DefaultVehicleHalTest, testSubscribeGlobalContinuous) {
1303 VehiclePropValue testValue{
1304 .prop = GLOBAL_CONTINUOUS_PROP,
1305 };
1306
1307 std::vector<SubscribeOptions> options = {
1308 {
1309 .propId = GLOBAL_CONTINUOUS_PROP,
1310 .sampleRate = 20.0,
1311 },
1312 };
1313
1314 auto status = getClient()->subscribe(getCallbackClient(), options, 0);
1315
1316 ASSERT_TRUE(status.isOk()) << "subscribe failed: " << status.getMessage();
1317
1318 // Sleep for 1s, which should generate ~20 events.
1319 std::this_thread::sleep_for(std::chrono::seconds(1));
1320
1321 // Should trigger about 20 times, check for at least 15 events to be safe.
1322 for (size_t i = 0; i < 15; i++) {
1323 auto maybeResults = getCallback()->nextOnPropertyEventResults();
1324 ASSERT_TRUE(maybeResults.has_value()) << "no results in callback";
1325 ASSERT_THAT(maybeResults.value().payloads, UnorderedElementsAre(testValue))
1326 << "results mismatch, expect to get the updated value";
1327 }
1328 EXPECT_EQ(countClients(), static_cast<size_t>(1));
1329 }
1330
TEST_F(DefaultVehicleHalTest,testSubscribeGlobalContinuousRateOutOfRange)1331 TEST_F(DefaultVehicleHalTest, testSubscribeGlobalContinuousRateOutOfRange) {
1332 // The maxSampleRate is 100, so the sample rate should be the default max 100.
1333 std::vector<SubscribeOptions> options = {
1334 {
1335 .propId = GLOBAL_CONTINUOUS_PROP,
1336 .sampleRate = 1000.0,
1337 },
1338 };
1339
1340 auto status = getClient()->subscribe(getCallbackClient(), options, 0);
1341
1342 ASSERT_TRUE(status.isOk()) << "subscribe failed: " << status.getMessage();
1343
1344 // Sleep for 1s, which should generate ~100 events.
1345 std::this_thread::sleep_for(std::chrono::seconds(1));
1346
1347 size_t eventCount = getCallback()->countOnPropertyEventResults();
1348 ASSERT_GE(eventCount, 50u) << "expect at least 50 events to be generated";
1349 ASSERT_LE(eventCount, 150u) << "expect no more than 150 events to be generated";
1350
1351 EXPECT_EQ(countClients(), static_cast<size_t>(1));
1352 }
1353
TEST_F(DefaultVehicleHalTest,testSubscribeAreaContinuous)1354 TEST_F(DefaultVehicleHalTest, testSubscribeAreaContinuous) {
1355 std::vector<SubscribeOptions> options = {
1356 {
1357 .propId = AREA_CONTINUOUS_PROP,
1358 .sampleRate = 20.0,
1359 .areaIds = {toInt(VehicleAreaWindow::ROW_1_LEFT)},
1360 },
1361 {
1362 .propId = AREA_CONTINUOUS_PROP,
1363 .sampleRate = 10.0,
1364 .areaIds = {toInt(VehicleAreaWindow::ROW_1_RIGHT)},
1365 },
1366 };
1367
1368 auto status = getClient()->subscribe(getCallbackClient(), options, 0);
1369
1370 ASSERT_TRUE(status.isOk()) << "subscribe failed: " << status.getMessage();
1371
1372 // Sleep for 1s, which should generate ~20 events.
1373 std::this_thread::sleep_for(std::chrono::seconds(1));
1374
1375 getClient()->unsubscribe(getCallbackClient(), std::vector<int32_t>({AREA_CONTINUOUS_PROP}));
1376
1377 std::vector<VehiclePropValue> events;
1378 while (true) {
1379 auto maybeResults = getCallback()->nextOnPropertyEventResults();
1380 if (!maybeResults.has_value()) {
1381 break;
1382 }
1383 for (const auto& value : maybeResults.value().payloads) {
1384 events.push_back(value);
1385 }
1386 }
1387
1388 size_t leftCount = 0;
1389 size_t rightCount = 0;
1390
1391 for (const auto& event : events) {
1392 ASSERT_EQ(event.prop, AREA_CONTINUOUS_PROP);
1393 if (event.areaId == toInt(VehicleAreaWindow::ROW_1_LEFT)) {
1394 leftCount++;
1395 continue;
1396 }
1397 rightCount++;
1398 }
1399
1400 // Should trigger about 20 times, check for at least 15 events to be safe.
1401 ASSERT_GE(leftCount, static_cast<size_t>(15));
1402 // Should trigger about 10 times, check for at least 5 events to be safe.
1403 ASSERT_GE(rightCount, static_cast<size_t>(5));
1404 }
1405
TEST_F(DefaultVehicleHalTest,testUnsubscribeOnChange)1406 TEST_F(DefaultVehicleHalTest, testUnsubscribeOnChange) {
1407 std::vector<SubscribeOptions> options = {
1408 {
1409 .propId = GLOBAL_ON_CHANGE_PROP,
1410 },
1411 };
1412
1413 auto status = getClient()->subscribe(getCallbackClient(), options, 0);
1414
1415 ASSERT_TRUE(status.isOk()) << "subscribe failed: " << status.getMessage();
1416
1417 status = getClient()->unsubscribe(getCallbackClient(),
1418 std::vector<int32_t>({GLOBAL_ON_CHANGE_PROP}));
1419
1420 ASSERT_TRUE(status.isOk()) << "unsubscribe failed: " << status.getMessage();
1421
1422 VehiclePropValue testValue{
1423 .prop = GLOBAL_ON_CHANGE_PROP,
1424 .value.int32Values = {0},
1425 };
1426
1427 // Set the value to trigger a property change event.
1428 getHardware()->addSetValueResponses({{
1429 .requestId = 0,
1430 .status = StatusCode::OK,
1431 }});
1432 status = getClient()->setValues(getCallbackClient(),
1433 {
1434 .payloads =
1435 {
1436 SetValueRequest{
1437 .requestId = 0,
1438 .value = testValue,
1439 },
1440 },
1441 });
1442
1443 ASSERT_TRUE(status.isOk()) << "setValues failed: " << status.getMessage();
1444
1445 ASSERT_FALSE(getCallback()->nextOnPropertyEventResults().has_value())
1446 << "No property event should be generated after unsubscription";
1447 }
1448
TEST_F(DefaultVehicleHalTest,testUnsubscribeContinuous)1449 TEST_F(DefaultVehicleHalTest, testUnsubscribeContinuous) {
1450 std::vector<SubscribeOptions> options = {
1451 {
1452 .propId = GLOBAL_CONTINUOUS_PROP,
1453 .sampleRate = 100.0,
1454 },
1455 };
1456
1457 auto status = getClient()->subscribe(getCallbackClient(), options, 0);
1458
1459 ASSERT_TRUE(status.isOk()) << "subscribe failed: " << status.getMessage();
1460
1461 status = getClient()->unsubscribe(getCallbackClient(),
1462 std::vector<int32_t>({GLOBAL_CONTINUOUS_PROP}));
1463
1464 ASSERT_TRUE(status.isOk()) << "unsubscribe failed: " << status.getMessage();
1465
1466 // Wait for the last events to come.
1467 std::this_thread::sleep_for(std::chrono::milliseconds(100));
1468
1469 // Clear existing events.
1470 while (getCallback()->nextOnPropertyEventResults().has_value()) {
1471 // Do nothing.
1472 }
1473
1474 // Wait for a while, make sure no new events are generated. If still subscribed, this should
1475 // generate around 10 events.
1476 std::this_thread::sleep_for(std::chrono::milliseconds(100));
1477
1478 ASSERT_EQ(getCallback()->countOnPropertyEventResults(), 0u)
1479 << "Property event generation must stop after unsubscription";
1480 }
1481
1482 class SubscribeInvalidOptionsTest
1483 : public DefaultVehicleHalTest,
1484 public testing::WithParamInterface<SubscribeInvalidOptionsTestCase> {};
1485
1486 INSTANTIATE_TEST_SUITE_P(
1487 SubscribeInvalidOptionsTests, SubscribeInvalidOptionsTest,
1488 testing::ValuesIn(getSubscribeInvalidOptionsTestCases()),
__anon060c6f7d0302(const testing::TestParamInfo<SubscribeInvalidOptionsTest::ParamType>& info) 1489 [](const testing::TestParamInfo<SubscribeInvalidOptionsTest::ParamType>& info) {
1490 return info.param.name;
1491 });
1492
TEST_P(SubscribeInvalidOptionsTest,testSubscribeInvalidOptions)1493 TEST_P(SubscribeInvalidOptionsTest, testSubscribeInvalidOptions) {
1494 std::vector<SubscribeOptions> options = {GetParam().option};
1495
1496 auto status = getClient()->subscribe(getCallbackClient(), options, 0);
1497
1498 ASSERT_FALSE(status.isOk()) << "invalid subscribe options must fail";
1499 ASSERT_EQ(status.getServiceSpecificError(), toInt(StatusCode::INVALID_ARG));
1500 }
1501
TEST_F(DefaultVehicleHalTest,testSubscribeNoReadPermission)1502 TEST_F(DefaultVehicleHalTest, testSubscribeNoReadPermission) {
1503 std::vector<SubscribeOptions> options = {{
1504 .propId = WRITE_ONLY_PROP,
1505 }};
1506
1507 auto status = getClient()->subscribe(getCallbackClient(), options, 0);
1508
1509 ASSERT_FALSE(status.isOk()) << "subscribe to a write-only property must fail";
1510 ASSERT_EQ(status.getServiceSpecificError(), toInt(StatusCode::ACCESS_DENIED));
1511 }
1512
TEST_F(DefaultVehicleHalTest,testUnsubscribeFailure)1513 TEST_F(DefaultVehicleHalTest, testUnsubscribeFailure) {
1514 auto status = getClient()->unsubscribe(getCallbackClient(),
1515 std::vector<int32_t>({GLOBAL_ON_CHANGE_PROP}));
1516
1517 ASSERT_FALSE(status.isOk()) << "unsubscribe to a not-subscribed property must fail";
1518 ASSERT_EQ(status.getServiceSpecificError(), toInt(StatusCode::INVALID_ARG));
1519 }
1520
TEST_F(DefaultVehicleHalTest,testHeartbeatEvent)1521 TEST_F(DefaultVehicleHalTest, testHeartbeatEvent) {
1522 std::vector<SubscribeOptions> options = {{
1523 .propId = toInt(VehicleProperty::VHAL_HEARTBEAT),
1524 }};
1525 int64_t currentTime = uptimeMillis();
1526 auto status = getClient()->subscribe(getCallbackClient(), options, 0);
1527
1528 ASSERT_TRUE(status.isOk()) << "unable to subscribe to heartbeat event: " << status.getMessage();
1529
1530 // We send out a heartbeat event every 3s, so sleep for 3s.
1531 std::this_thread::sleep_for(std::chrono::seconds(3));
1532
1533 auto maybeResults = getCallback()->nextOnPropertyEventResults();
1534 ASSERT_TRUE(maybeResults.has_value()) << "no results in callback";
1535 ASSERT_EQ(maybeResults.value().payloads.size(), static_cast<size_t>(1));
1536 VehiclePropValue gotValue = maybeResults.value().payloads[0];
1537 ASSERT_EQ(gotValue.prop, toInt(VehicleProperty::VHAL_HEARTBEAT));
1538 ASSERT_EQ(gotValue.value.int64Values.size(), static_cast<size_t>(1));
1539 ASSERT_GE(gotValue.value.int64Values[0], currentTime)
1540 << "expect to get the latest timestamp with the heartbeat event";
1541 }
1542
TEST_F(DefaultVehicleHalTest,testOnBinderDiedUnlinked)1543 TEST_F(DefaultVehicleHalTest, testOnBinderDiedUnlinked) {
1544 // Set responses for all the hardware getValues requests.
1545 getHardware()->setGetValueResponder(
1546 [](std::shared_ptr<const IVehicleHardware::GetValuesCallback> callback,
1547 const std::vector<GetValueRequest>& requests) {
1548 std::vector<GetValueResult> results;
1549 for (auto& request : requests) {
1550 VehiclePropValue prop = request.prop;
1551 prop.value.int32Values = {0};
1552 results.push_back({
1553 .requestId = request.requestId,
1554 .status = StatusCode::OK,
1555 .prop = prop,
1556 });
1557 }
1558 (*callback)(results);
1559 return StatusCode::OK;
1560 });
1561 std::vector<SubscribeOptions> options = {
1562 {
1563 .propId = GLOBAL_CONTINUOUS_PROP,
1564 .sampleRate = 20.0,
1565 },
1566 };
1567 auto status = getClient()->subscribe(getCallbackClient(), options, 0);
1568 ASSERT_TRUE(status.isOk()) << "subscribe failed: " << status.getMessage();
1569 // Sleep for 100ms so that the subscriptionClient gets created because we would at least try to
1570 // get value once.
1571 std::this_thread::sleep_for(std::chrono::milliseconds(100));
1572
1573 // Issue another getValue request on the same client.
1574 GetValueRequests requests;
1575 std::vector<GetValueResult> expectedResults;
1576 std::vector<GetValueRequest> expectedHardwareRequests;
1577 ASSERT_TRUE(getValuesTestCases(1, requests, expectedResults, expectedHardwareRequests).ok());
1578 getHardware()->addGetValueResponses(expectedResults);
1579 status = getClient()->getValues(getCallbackClient(), requests);
1580 ASSERT_TRUE(status.isOk()) << "getValues failed: " << status.getMessage();
1581
1582 ASSERT_EQ(countOnBinderDiedContexts(), static_cast<size_t>(1))
1583 << "expect one OnBinderDied context when one client is registered";
1584
1585 // Get the death recipient cookie for our callback that would be used in onBinderDied and
1586 // onBinderUnlinked.
1587 AIBinder* clientId = getCallbackClient()->asBinder().get();
1588 void* context = getOnBinderDiedContexts(clientId);
1589
1590 onBinderDied(context);
1591
1592 // Sleep for 100ms between checks.
1593 int64_t sleep = 100;
1594 // Timeout: 10s.
1595 int64_t timeout = 10'000'000'000;
1596 int64_t stopTime = elapsedRealtimeNano() + timeout;
1597 // Wait until the onBinderDied event is handled.
1598 while (countClients() != 0u && elapsedRealtimeNano() <= stopTime) {
1599 std::this_thread::sleep_for(std::chrono::milliseconds(sleep));
1600 }
1601
1602 ASSERT_EQ(countClients(), static_cast<size_t>(0))
1603 << "expect all clients to be removed when binder died";
1604 ASSERT_TRUE(hasNoSubscriptions()) << "expect no subscriptions when binder died";
1605
1606 onBinderUnlinked(context);
1607
1608 stopTime = elapsedRealtimeNano() + timeout;
1609 // Wait until the onBinderUnlinked event is handled.
1610 while (countOnBinderDiedContexts() != 0u && elapsedRealtimeNano() <= stopTime) {
1611 std::this_thread::sleep_for(std::chrono::milliseconds(sleep));
1612 }
1613
1614 ASSERT_EQ(countOnBinderDiedContexts(), static_cast<size_t>(0))
1615 << "expect OnBinderDied context to be deleted when binder is unlinked";
1616 }
1617
TEST_F(DefaultVehicleHalTest,testDumpCallerShouldDump)1618 TEST_F(DefaultVehicleHalTest, testDumpCallerShouldDump) {
1619 std::string buffer = "Dump from hardware";
1620 getHardware()->setDumpResult({
1621 .callerShouldDumpState = true,
1622 .buffer = buffer,
1623 });
1624 int fd = memfd_create("memfile", 0);
1625 getClient()->dump(fd, nullptr, 0);
1626
1627 lseek(fd, 0, SEEK_SET);
1628 char buf[10240] = {};
1629 read(fd, buf, sizeof(buf));
1630 close(fd);
1631
1632 std::string msg(buf);
1633
1634 ASSERT_THAT(msg, ContainsRegex(buffer + "\nVehicle HAL State: \n"));
1635 }
1636
TEST_F(DefaultVehicleHalTest,testDumpCallerShouldNotDump)1637 TEST_F(DefaultVehicleHalTest, testDumpCallerShouldNotDump) {
1638 std::string buffer = "Dump from hardware";
1639 getHardware()->setDumpResult({
1640 .callerShouldDumpState = false,
1641 .buffer = buffer,
1642 });
1643 int fd = memfd_create("memfile", 0);
1644 getClient()->dump(fd, nullptr, 0);
1645
1646 lseek(fd, 0, SEEK_SET);
1647 char buf[10240] = {};
1648 read(fd, buf, sizeof(buf));
1649 close(fd);
1650
1651 std::string msg(buf);
1652
1653 ASSERT_THAT(msg, ContainsRegex(buffer));
1654 ASSERT_EQ(msg.find("Vehicle HAL State: "), std::string::npos);
1655 }
1656
TEST_F(DefaultVehicleHalTest,testOnPropertySetErrorEvent)1657 TEST_F(DefaultVehicleHalTest, testOnPropertySetErrorEvent) {
1658 std::vector<SubscribeOptions> options = {
1659 {
1660 .propId = GLOBAL_ON_CHANGE_PROP,
1661 .areaIds = {0},
1662 },
1663 {
1664 .propId = GLOBAL_CONTINUOUS_PROP,
1665 .areaIds = {0},
1666 .sampleRate = 1,
1667 },
1668 };
1669 auto status = getClient()->subscribe(getCallbackClient(), options, 0);
1670 ASSERT_TRUE(status.isOk()) << "subscribe failed: " << status.getMessage();
1671 std::vector<SetValueErrorEvent> errorEvents = {
1672 {
1673 .propId = GLOBAL_ON_CHANGE_PROP,
1674 .areaId = 0,
1675 .errorCode = StatusCode::INTERNAL_ERROR,
1676 },
1677 {
1678 .propId = GLOBAL_ON_CHANGE_PROP,
1679 .areaId = 0,
1680 .errorCode = StatusCode::ACCESS_DENIED,
1681 },
1682 {
1683 .propId = GLOBAL_CONTINUOUS_PROP,
1684 .areaId = 0,
1685 .errorCode = StatusCode::INVALID_ARG,
1686 },
1687 };
1688 std::vector<VehiclePropError> expectedResults = {
1689 {
1690 .propId = GLOBAL_ON_CHANGE_PROP,
1691 .areaId = 0,
1692 .errorCode = StatusCode::INTERNAL_ERROR,
1693 },
1694 {
1695 .propId = GLOBAL_ON_CHANGE_PROP,
1696 .areaId = 0,
1697 .errorCode = StatusCode::ACCESS_DENIED,
1698 },
1699 {
1700 .propId = GLOBAL_CONTINUOUS_PROP,
1701 .areaId = 0,
1702 .errorCode = StatusCode::INVALID_ARG,
1703 },
1704 };
1705 getHardware()->sendOnPropertySetErrorEvent(errorEvents);
1706
1707 ASSERT_EQ(getCallback()->countOnPropertySetErrorResults(), 1u);
1708 auto maybeVehiclePropErrors = getCallback()->nextOnPropertySetErrorResults();
1709 ASSERT_TRUE(maybeVehiclePropErrors.has_value());
1710 const auto& vehiclePropErrors = maybeVehiclePropErrors.value();
1711 ASSERT_THAT(vehiclePropErrors.payloads, UnorderedElementsAreArray(expectedResults));
1712 }
1713
1714 } // namespace vehicle
1715 } // namespace automotive
1716 } // namespace hardware
1717 } // namespace android
1718