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 "SubscriptionManager.h"
18
19 #include <MockVehicleHardware.h>
20 #include <VehicleHalTypes.h>
21
22 #include <aidl/android/hardware/automotive/vehicle/BnVehicleCallback.h>
23 #include <android-base/thread_annotations.h>
24 #include <gmock/gmock.h>
25 #include <gtest/gtest.h>
26
27 #include <float.h>
28 #include <chrono>
29 #include <list>
30 #include <memory>
31 #include <mutex>
32 #include <thread>
33 #include <vector>
34
35 namespace android {
36 namespace hardware {
37 namespace automotive {
38 namespace vehicle {
39
40 using ::aidl::android::hardware::automotive::vehicle::BnVehicleCallback;
41 using ::aidl::android::hardware::automotive::vehicle::GetValueResults;
42 using ::aidl::android::hardware::automotive::vehicle::IVehicleCallback;
43 using ::aidl::android::hardware::automotive::vehicle::SetValueResults;
44 using ::aidl::android::hardware::automotive::vehicle::SubscribeOptions;
45 using ::aidl::android::hardware::automotive::vehicle::VehiclePropErrors;
46 using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyStatus;
47 using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
48 using ::aidl::android::hardware::automotive::vehicle::VehiclePropValues;
49 using ::ndk::ScopedAStatus;
50 using ::ndk::SpAIBinder;
51 using ::testing::Contains;
52 using ::testing::ElementsAre;
53 using ::testing::UnorderedElementsAre;
54
55 class PropertyCallback final : public BnVehicleCallback {
56 public:
onGetValues(const GetValueResults &)57 ScopedAStatus onGetValues(const GetValueResults&) override { return ScopedAStatus::ok(); }
58
onSetValues(const SetValueResults &)59 ScopedAStatus onSetValues(const SetValueResults&) override { return ScopedAStatus::ok(); }
60
onPropertyEvent(const VehiclePropValues & values,int32_t)61 ScopedAStatus onPropertyEvent(const VehiclePropValues& values, int32_t) override {
62 std::scoped_lock<std::mutex> lockGuard(mLock);
63 for (const auto& value : values.payloads) {
64 mEvents.push_back(value);
65 }
66 return ScopedAStatus::ok();
67 }
68
onPropertySetError(const VehiclePropErrors &)69 ScopedAStatus onPropertySetError(const VehiclePropErrors&) override {
70 return ScopedAStatus::ok();
71 }
72
73 // Test functions.
getEvents()74 std::list<VehiclePropValue> getEvents() {
75 std::scoped_lock<std::mutex> lockGuard(mLock);
76 return mEvents;
77 }
78
clearEvents()79 void clearEvents() {
80 std::scoped_lock<std::mutex> lockGuard(mLock);
81 mEvents.clear();
82 }
83
84 private:
85 std::mutex mLock;
86 std::list<VehiclePropValue> mEvents GUARDED_BY(mLock);
87 };
88
89 class SubscriptionManagerTest : public testing::Test {
90 public:
SetUp()91 void SetUp() override {
92 mHardware = std::make_shared<MockVehicleHardware>();
93 mManager = std::make_unique<SubscriptionManager>(mHardware.get());
94 mCallback = ndk::SharedRefBase::make<PropertyCallback>();
95 // Keep the local binder alive.
96 mBinder = mCallback->asBinder();
97 mCallbackClient = IVehicleCallback::fromBinder(mBinder);
98 std::shared_ptr<IVehicleCallback> callbackClient = mCallbackClient;
99 mHardware->registerOnPropertyChangeEvent(
100 std::make_unique<IVehicleHardware::PropertyChangeCallback>(
101 [callbackClient](std::vector<VehiclePropValue> updatedValues) {
102 VehiclePropValues values = {
103 .payloads = std::move(updatedValues),
104 };
105 callbackClient->onPropertyEvent(values, 0);
106 }));
107 }
108
getManager()109 SubscriptionManager* getManager() { return mManager.get(); }
110
getCallbackClient()111 std::shared_ptr<IVehicleCallback> getCallbackClient() { return mCallbackClient; }
112
getCallback()113 PropertyCallback* getCallback() { return mCallback.get(); }
114
getEvents()115 std::list<VehiclePropValue> getEvents() { return getCallback()->getEvents(); }
116
clearEvents()117 void clearEvents() { return getCallback()->clearEvents(); }
118
getHardware()119 std::shared_ptr<MockVehicleHardware> getHardware() { return mHardware; }
120
121 private:
122 std::unique_ptr<SubscriptionManager> mManager;
123 std::shared_ptr<PropertyCallback> mCallback;
124 std::shared_ptr<IVehicleCallback> mCallbackClient;
125 std::shared_ptr<MockVehicleHardware> mHardware;
126 SpAIBinder mBinder;
127 };
128
TEST_F(SubscriptionManagerTest,testSubscribeGlobalContinuous)129 TEST_F(SubscriptionManagerTest, testSubscribeGlobalContinuous) {
130 std::vector<SubscribeOptions> options = {{
131 .propId = 0,
132 .areaIds = {0},
133 .sampleRate = 10.0,
134 }};
135
136 auto result = getManager()->subscribe(getCallbackClient(), options, true);
137 ASSERT_TRUE(result.ok()) << "failed to subscribe: " << result.error().message();
138
139 ASSERT_THAT(getHardware()->getSubscribedContinuousPropIdAreaIds(),
140 UnorderedElementsAre(std::pair<int32_t, int32_t>(0, 0)));
141
142 std::this_thread::sleep_for(std::chrono::seconds(1));
143
144 // Theoretically trigger 10 times, but check for at least 9 times to be stable.
145 ASSERT_GE(getEvents().size(), static_cast<size_t>(9));
146 EXPECT_EQ(getEvents().back().prop, 0);
147 EXPECT_EQ(getEvents().back().areaId, 0);
148 }
149
TEST_F(SubscriptionManagerTest,testSubscribeMultiplePropsGlobalContinuous)150 TEST_F(SubscriptionManagerTest, testSubscribeMultiplePropsGlobalContinuous) {
151 std::vector<SubscribeOptions> options = {{
152 .propId = 0,
153 .areaIds = {0},
154 .sampleRate = 10.0,
155 },
156 {
157 .propId = 1,
158 .areaIds = {0},
159 .sampleRate = 20.0,
160 }};
161
162 auto result = getManager()->subscribe(getCallbackClient(), options, true);
163 ASSERT_TRUE(result.ok()) << "failed to subscribe: " << result.error().message();
164
165 std::this_thread::sleep_for(std::chrono::seconds(1));
166
167 size_t event0Count = 0;
168 size_t event1Count = 0;
169
170 for (const auto& event : getEvents()) {
171 if (event.prop == 0) {
172 event0Count++;
173 } else {
174 event1Count++;
175 }
176 }
177
178 // Theoretically trigger 10 times, but check for at least 9 times to be stable.
179 EXPECT_GE(event0Count, static_cast<size_t>(9));
180 // Theoretically trigger 20 times, but check for at least 15 times to be stable.
181 EXPECT_GE(event1Count, static_cast<size_t>(15));
182 }
183
TEST_F(SubscriptionManagerTest,testOverrideSubscriptionContinuous)184 TEST_F(SubscriptionManagerTest, testOverrideSubscriptionContinuous) {
185 std::vector<SubscribeOptions> options = {{
186 .propId = 0,
187 .areaIds = {0},
188 .sampleRate = 20.0,
189 }};
190
191 auto result = getManager()->subscribe(getCallbackClient(), options, true);
192 ASSERT_TRUE(result.ok()) << "failed to subscribe: " << result.error().message();
193
194 // Override sample rate to be 10.0.
195 options[0].sampleRate = 10.0;
196 result = getManager()->subscribe(getCallbackClient(), options, true);
197 ASSERT_TRUE(result.ok()) << "failed to subscribe: " << result.error().message();
198
199 std::this_thread::sleep_for(std::chrono::seconds(1));
200
201 // Theoretically trigger 10 times, but check for at least 9 times to be stable.
202 EXPECT_GE(getEvents().size(), static_cast<size_t>(9));
203 EXPECT_LE(getEvents().size(), static_cast<size_t>(15));
204 }
205
TEST_F(SubscriptionManagerTest,testSubscribeMultipleAreasContinuous)206 TEST_F(SubscriptionManagerTest, testSubscribeMultipleAreasContinuous) {
207 std::vector<SubscribeOptions> options = {
208 {
209 .propId = 0,
210 .areaIds = {0, 1},
211 .sampleRate = 10.0,
212 },
213 };
214
215 auto result = getManager()->subscribe(getCallbackClient(), options, true);
216 ASSERT_TRUE(result.ok()) << "failed to subscribe: " << result.error().message();
217
218 std::this_thread::sleep_for(std::chrono::seconds(1));
219
220 size_t area0Count = 0;
221 size_t area1Count = 0;
222
223 for (const auto& event : getEvents()) {
224 if (event.areaId == 0) {
225 area0Count++;
226 } else {
227 area1Count++;
228 }
229 }
230
231 // Theoretically trigger 10 times, but check for at least 9 times to be stable.
232 EXPECT_GE(area0Count, static_cast<size_t>(9));
233 // Theoretically trigger 10 times, but check for at least 9 times to be stable.
234 EXPECT_GE(area1Count, static_cast<size_t>(9));
235 }
236
TEST_F(SubscriptionManagerTest,testUnsubscribeGlobalContinuous)237 TEST_F(SubscriptionManagerTest, testUnsubscribeGlobalContinuous) {
238 std::vector<SubscribeOptions> options = {{
239 .propId = 0,
240 .areaIds = {0},
241 .sampleRate = 100.0,
242 }};
243
244 auto result = getManager()->subscribe(getCallbackClient(), options, true);
245 ASSERT_TRUE(result.ok()) << "failed to subscribe: " << result.error().message();
246
247 result = getManager()->unsubscribe(getCallbackClient()->asBinder().get());
248 ASSERT_TRUE(result.ok()) << "failed to unsubscribe: " << result.error().message();
249
250 ASSERT_EQ(getHardware()->getSubscribedContinuousPropIdAreaIds().size(), 0u);
251
252 // Wait for the last events to come.
253 std::this_thread::sleep_for(std::chrono::milliseconds(100));
254
255 clearEvents();
256
257 std::this_thread::sleep_for(std::chrono::milliseconds(100));
258
259 ASSERT_TRUE(getEvents().empty());
260 }
261
TEST_F(SubscriptionManagerTest,testUnsubscribeMultipleAreas)262 TEST_F(SubscriptionManagerTest, testUnsubscribeMultipleAreas) {
263 std::vector<SubscribeOptions> options = {
264 {
265 .propId = 0,
266 .areaIds = {0, 1, 2, 3, 4},
267 .sampleRate = 10.0,
268 },
269 {
270 .propId = 1,
271 .areaIds = {0},
272 .sampleRate = 10.0,
273 },
274 };
275
276 auto result = getManager()->subscribe(getCallbackClient(), options, true);
277 ASSERT_TRUE(result.ok()) << "failed to subscribe: " << result.error().message();
278
279 result = getManager()->unsubscribe(getCallbackClient()->asBinder().get(),
280 std::vector<int32_t>({0}));
281 ASSERT_TRUE(result.ok()) << "failed to unsubscribe: " << result.error().message();
282
283 // Wait for the last events to come.
284 std::this_thread::sleep_for(std::chrono::milliseconds(100));
285
286 clearEvents();
287
288 std::this_thread::sleep_for(std::chrono::seconds(1));
289
290 // Theoretically trigger 10 times, but check for at least 9 times to be stable.
291 EXPECT_GE(getEvents().size(), static_cast<size_t>(9));
292
293 for (const auto& event : getEvents()) {
294 EXPECT_EQ(event.prop, 1);
295 }
296 }
297
TEST_F(SubscriptionManagerTest,testUnsubscribeByCallback)298 TEST_F(SubscriptionManagerTest, testUnsubscribeByCallback) {
299 std::vector<SubscribeOptions> options = {
300 {
301 .propId = 0,
302 .areaIds = {0, 1, 2, 3, 4},
303 .sampleRate = 10.0,
304 },
305 {
306 .propId = 1,
307 .areaIds = {0},
308 .sampleRate = 10.0,
309 },
310 };
311
312 auto result = getManager()->subscribe(getCallbackClient(), options, true);
313 ASSERT_TRUE(result.ok()) << "failed to subscribe: " << result.error().message();
314
315 result = getManager()->unsubscribe(getCallbackClient()->asBinder().get());
316 ASSERT_TRUE(result.ok()) << "failed to unsubscribe: " << result.error().message();
317
318 // Wait for the last events to come.
319 std::this_thread::sleep_for(std::chrono::milliseconds(100));
320
321 clearEvents();
322
323 std::this_thread::sleep_for(std::chrono::seconds(1));
324
325 EXPECT_TRUE(getEvents().empty());
326 }
327
TEST_F(SubscriptionManagerTest,testUnsubscribeUnsubscribedPropId)328 TEST_F(SubscriptionManagerTest, testUnsubscribeUnsubscribedPropId) {
329 std::vector<SubscribeOptions> options = {
330 {
331 .propId = 0,
332 .areaIds = {0, 1, 2, 3, 4},
333 },
334 {
335 .propId = 1,
336 .areaIds = {0},
337 },
338 };
339
340 auto result = getManager()->subscribe(getCallbackClient(), options, false);
341 ASSERT_TRUE(result.ok()) << "failed to subscribe: " << result.error().message();
342
343 // Property ID: 2 was not subscribed.
344 result = getManager()->unsubscribe(getCallbackClient()->asBinder().get(),
345 std::vector<int32_t>({0, 1, 2}));
346 ASSERT_TRUE(result.ok()) << "unsubscribe an unsubscribed property must do nothing";
347
348 std::vector<VehiclePropValue> updatedValues = {
349 {
350 .prop = 0,
351 .areaId = 0,
352 },
353 {
354 .prop = 1,
355 .areaId = 0,
356 },
357 };
358 auto clients = getManager()->getSubscribedClients(std::vector<VehiclePropValue>(updatedValues));
359
360 ASSERT_EQ(clients.size(), 0u) << "all subscribed properties must be unsubscribed";
361 }
362
TEST_F(SubscriptionManagerTest,testSubscribeOnchange)363 TEST_F(SubscriptionManagerTest, testSubscribeOnchange) {
364 std::vector<SubscribeOptions> options1 = {
365 {
366 .propId = 0,
367 .areaIds = {0, 1},
368 },
369 {
370 .propId = 1,
371 .areaIds = {0},
372 },
373 };
374 std::vector<SubscribeOptions> options2 = {
375 {
376 .propId = 0,
377 .areaIds = {0},
378 },
379 };
380
381 SpAIBinder binder1 = ndk::SharedRefBase::make<PropertyCallback>()->asBinder();
382 std::shared_ptr<IVehicleCallback> client1 = IVehicleCallback::fromBinder(binder1);
383 SpAIBinder binder2 = ndk::SharedRefBase::make<PropertyCallback>()->asBinder();
384 std::shared_ptr<IVehicleCallback> client2 = IVehicleCallback::fromBinder(binder2);
385 auto result = getManager()->subscribe(client1, options1, false);
386 ASSERT_TRUE(result.ok()) << "failed to subscribe: " << result.error().message();
387 result = getManager()->subscribe(client2, options2, false);
388 ASSERT_TRUE(result.ok()) << "failed to subscribe: " << result.error().message();
389 ASSERT_THAT(getHardware()->getSubscribedOnChangePropIdAreaIds(),
390 UnorderedElementsAre(std::pair<int32_t, int32_t>(0, 0),
391 std::pair<int32_t, int32_t>(0, 1),
392 std::pair<int32_t, int32_t>(1, 0)));
393 ASSERT_EQ(getHardware()->getSubscribedContinuousPropIdAreaIds().size(), 0u);
394
395 std::vector<VehiclePropValue> updatedValues = {
396 {
397 .prop = 0,
398 .areaId = 0,
399 },
400 {
401 .prop = 0,
402 .areaId = 1,
403 },
404 {
405 .prop = 1,
406 .areaId = 0,
407 },
408 {
409 .prop = 1,
410 .areaId = 1,
411 },
412 };
413 auto clients = getManager()->getSubscribedClients(std::vector<VehiclePropValue>(updatedValues));
414
415 ASSERT_THAT(clients[client1],
416 UnorderedElementsAre(updatedValues[0], updatedValues[1], updatedValues[2]));
417 ASSERT_THAT(clients[client2], ElementsAre(updatedValues[0]));
418 }
419
TEST_F(SubscriptionManagerTest,testSubscribeInvalidOption)420 TEST_F(SubscriptionManagerTest, testSubscribeInvalidOption) {
421 std::vector<SubscribeOptions> options = {
422 {
423 .propId = 0,
424 .areaIds = {0, 1, 2, 3, 4},
425 // invalid sample rate.
426 .sampleRate = 0.0,
427 },
428 {
429 .propId = 1,
430 .areaIds = {0},
431 .sampleRate = 10.0,
432 },
433 };
434
435 auto result = getManager()->subscribe(getCallbackClient(), options, true);
436 ASSERT_FALSE(result.ok()) << "subscribe with invalid sample rate must fail";
437 ASSERT_TRUE(getManager()
438 ->getSubscribedClients({{
439 .prop = 0,
440 .areaId = 0,
441 },
442 {
443 .prop = 1,
444 .areaId = 0,
445 }})
446 .empty())
447 << "no property should be subscribed if error is returned";
448 }
449
TEST_F(SubscriptionManagerTest,testSubscribeNoAreaIds)450 TEST_F(SubscriptionManagerTest, testSubscribeNoAreaIds) {
451 std::vector<SubscribeOptions> options = {
452 {
453 .propId = 0,
454 .areaIds = {},
455 .sampleRate = 1.0,
456 },
457 {
458 .propId = 1,
459 .areaIds = {0},
460 .sampleRate = 10.0,
461 },
462 };
463
464 auto result = getManager()->subscribe(getCallbackClient(), options, true);
465 ASSERT_FALSE(result.ok()) << "subscribe with invalid sample rate must fail";
466 ASSERT_TRUE(getManager()
467 ->getSubscribedClients({{
468 .prop = 1,
469 .areaId = 0,
470 }})
471 .empty())
472 << "no property should be subscribed if error is returned";
473 }
474
TEST_F(SubscriptionManagerTest,testUnsubscribeOnchange)475 TEST_F(SubscriptionManagerTest, testUnsubscribeOnchange) {
476 std::vector<SubscribeOptions> options = {
477 {
478 .propId = 0,
479 .areaIds = {0, 1},
480 },
481 {
482 .propId = 1,
483 .areaIds = {0},
484 },
485 };
486
487 auto result = getManager()->subscribe(getCallbackClient(), options, false);
488 ASSERT_TRUE(result.ok()) << "failed to subscribe: " << result.error().message();
489
490 result = getManager()->unsubscribe(getCallbackClient()->asBinder().get(),
491 std::vector<int32_t>({0}));
492 ASSERT_TRUE(result.ok()) << "failed to unsubscribe: " << result.error().message();
493
494 std::vector<VehiclePropValue> updatedValues = {
495 {
496 .prop = 0,
497 .areaId = 0,
498 },
499 {
500 .prop = 1,
501 .areaId = 0,
502 },
503 };
504 auto clients = getManager()->getSubscribedClients(std::vector<VehiclePropValue>(updatedValues));
505
506 ASSERT_THAT(clients[getCallbackClient()], ElementsAre(updatedValues[1]));
507 ASSERT_THAT(getHardware()->getSubscribedOnChangePropIdAreaIds(),
508 UnorderedElementsAre(std::pair<int32_t, int32_t>(1, 0)));
509 }
510
TEST_F(SubscriptionManagerTest,testCheckSampleRateHzValid)511 TEST_F(SubscriptionManagerTest, testCheckSampleRateHzValid) {
512 ASSERT_TRUE(SubscriptionManager::checkSampleRateHz(1.0));
513 }
514
TEST_F(SubscriptionManagerTest,testCheckSampleRateHzInvalidTooSmall)515 TEST_F(SubscriptionManagerTest, testCheckSampleRateHzInvalidTooSmall) {
516 ASSERT_FALSE(SubscriptionManager::checkSampleRateHz(FLT_MIN));
517 }
518
TEST_F(SubscriptionManagerTest,testCheckSampleRateHzInvalidZero)519 TEST_F(SubscriptionManagerTest, testCheckSampleRateHzInvalidZero) {
520 ASSERT_FALSE(SubscriptionManager::checkSampleRateHz(0));
521 }
522
TEST_F(SubscriptionManagerTest,testCheckResolutionValid)523 TEST_F(SubscriptionManagerTest, testCheckResolutionValid) {
524 ASSERT_TRUE(SubscriptionManager::checkResolution(0.0));
525 ASSERT_TRUE(SubscriptionManager::checkResolution(0.1));
526 ASSERT_TRUE(SubscriptionManager::checkResolution(1.0));
527 }
528
TEST_F(SubscriptionManagerTest,testCheckResolutionInvalid)529 TEST_F(SubscriptionManagerTest, testCheckResolutionInvalid) {
530 ASSERT_FALSE(SubscriptionManager::checkResolution(2.0));
531 }
532
TEST_F(SubscriptionManagerTest,testSubscribe_enableVur)533 TEST_F(SubscriptionManagerTest, testSubscribe_enableVur) {
534 std::vector<SubscribeOptions> options = {{
535 .propId = 0,
536 .areaIds = {0},
537 .sampleRate = 10.0,
538 .enableVariableUpdateRate = true,
539 }};
540
541 auto result = getManager()->subscribe(getCallbackClient(), options, true);
542 ASSERT_TRUE(result.ok()) << "failed to subscribe: " << result.error().message();
543
544 ASSERT_THAT(getHardware()->getSubscribeOptions(), ElementsAre(options[0]));
545 }
546
TEST_F(SubscriptionManagerTest,testSubscribe_VurStateChange)547 TEST_F(SubscriptionManagerTest, testSubscribe_VurStateChange) {
548 std::vector<SubscribeOptions> options = {{
549 .propId = 0,
550 .areaIds = {0},
551 .sampleRate = 10.0,
552 .enableVariableUpdateRate = true,
553 }};
554
555 auto result = getManager()->subscribe(getCallbackClient(), options, true);
556 ASSERT_TRUE(result.ok()) << "failed to subscribe: " << result.error().message();
557
558 ASSERT_THAT(getHardware()->getSubscribeOptions(), ElementsAre(options[0]));
559
560 getHardware()->clearSubscribeOptions();
561 result = getManager()->subscribe(getCallbackClient(), options, true);
562 ASSERT_TRUE(result.ok()) << "failed to subscribe: " << result.error().message();
563
564 ASSERT_TRUE(getHardware()->getSubscribeOptions().empty());
565
566 std::vector<SubscribeOptions> newOptions = {{
567 .propId = 0,
568 .areaIds = {0},
569 .sampleRate = 10.0,
570 .enableVariableUpdateRate = false,
571 }};
572 result = getManager()->subscribe(getCallbackClient(), newOptions, true);
573 ASSERT_TRUE(result.ok()) << "failed to subscribe: " << result.error().message();
574
575 ASSERT_THAT(getHardware()->getSubscribeOptions(), ElementsAre(newOptions[0]));
576 }
577
TEST_F(SubscriptionManagerTest,testSubscribe_enableVur_filterUnchangedEvents)578 TEST_F(SubscriptionManagerTest, testSubscribe_enableVur_filterUnchangedEvents) {
579 SpAIBinder binder1 = ndk::SharedRefBase::make<PropertyCallback>()->asBinder();
580 std::shared_ptr<IVehicleCallback> client1 = IVehicleCallback::fromBinder(binder1);
581 SpAIBinder binder2 = ndk::SharedRefBase::make<PropertyCallback>()->asBinder();
582 std::shared_ptr<IVehicleCallback> client2 = IVehicleCallback::fromBinder(binder2);
583 SubscribeOptions client1Option = {
584 .propId = 0,
585 .areaIds = {0},
586 .sampleRate = 10.0,
587 .enableVariableUpdateRate = false,
588 };
589 auto result = getManager()->subscribe(client1, {client1Option}, true);
590 ASSERT_TRUE(result.ok()) << "failed to subscribe: " << result.error().message();
591
592 ASSERT_THAT(getHardware()->getSubscribeOptions(), UnorderedElementsAre(client1Option));
593
594 getHardware()->clearSubscribeOptions();
595 SubscribeOptions client2Option = {
596 .propId = 0,
597 .areaIds = {0, 1},
598 .sampleRate = 20.0,
599 .enableVariableUpdateRate = true,
600 };
601
602 result = getManager()->subscribe(client2, {client2Option}, true);
603 ASSERT_TRUE(result.ok()) << "failed to subscribe: " << result.error().message();
604
605 ASSERT_THAT(getHardware()->getSubscribeOptions(),
606 UnorderedElementsAre(
607 SubscribeOptions{
608 .propId = 0,
609 .areaIds = {0},
610 .sampleRate = 20.0,
611 // This is enabled for client2, but disabled for client1.
612 .enableVariableUpdateRate = false,
613 },
614 SubscribeOptions{
615 .propId = 0,
616 .areaIds = {1},
617 .sampleRate = 20.0,
618 .enableVariableUpdateRate = true,
619 }));
620
621 std::vector<VehiclePropValue> propertyEvents = {{
622 .prop = 0,
623 .areaId = 0,
624 .value = {.int32Values = {0}},
625 .timestamp = 1,
626 },
627 {
628 .prop = 0,
629 .areaId = 1,
630 .value = {.int32Values = {1}},
631 .timestamp = 1,
632 }};
633 auto clients =
634 getManager()->getSubscribedClients(std::vector<VehiclePropValue>(propertyEvents));
635
636 ASSERT_THAT(clients[client1], UnorderedElementsAre(propertyEvents[0]));
637 ASSERT_THAT(clients[client2], UnorderedElementsAre(propertyEvents[0], propertyEvents[1]));
638
639 // If the same property events happen again with a new timestamp.
640 // VUR is disabled for client1, enabled for client2.
641 clients = getManager()->getSubscribedClients({{
642 .prop = 0,
643 .areaId = 0,
644 .value = {.int32Values = {0}},
645 .timestamp = 2,
646 }});
647
648 ASSERT_FALSE(clients.find(client1) == clients.end())
649 << "Must not filter out property events if VUR is not enabled";
650 ASSERT_TRUE(clients.find(client2) == clients.end())
651 << "Must filter out property events if VUR is enabled";
652 }
653
TEST_F(SubscriptionManagerTest,testSubscribe_enableVur_filterUnchangedEvents_withResolution)654 TEST_F(SubscriptionManagerTest, testSubscribe_enableVur_filterUnchangedEvents_withResolution) {
655 SpAIBinder binder1 = ndk::SharedRefBase::make<PropertyCallback>()->asBinder();
656 std::shared_ptr<IVehicleCallback> client1 = IVehicleCallback::fromBinder(binder1);
657 SpAIBinder binder2 = ndk::SharedRefBase::make<PropertyCallback>()->asBinder();
658 std::shared_ptr<IVehicleCallback> client2 = IVehicleCallback::fromBinder(binder2);
659 SubscribeOptions client1Option = {
660 .propId = 0,
661 .areaIds = {0},
662 .sampleRate = 10.0,
663 .resolution = 0.01,
664 .enableVariableUpdateRate = false,
665 };
666 auto result = getManager()->subscribe(client1, {client1Option}, true);
667 ASSERT_TRUE(result.ok()) << "failed to subscribe: " << result.error().message();
668
669 ASSERT_THAT(getHardware()->getSubscribeOptions(), UnorderedElementsAre(client1Option));
670
671 getHardware()->clearSubscribeOptions();
672 SubscribeOptions client2Option = {
673 .propId = 0,
674 .areaIds = {0, 1},
675 .sampleRate = 20.0,
676 .resolution = 0.1,
677 .enableVariableUpdateRate = true,
678 };
679
680 result = getManager()->subscribe(client2, {client2Option}, true);
681 ASSERT_TRUE(result.ok()) << "failed to subscribe: " << result.error().message();
682
683 ASSERT_THAT(getHardware()->getSubscribeOptions(),
684 UnorderedElementsAre(
685 SubscribeOptions{
686 .propId = 0,
687 .areaIds = {0},
688 .sampleRate = 20.0,
689 .resolution = 0.01,
690 // This is enabled for client2, but disabled for client1.
691 .enableVariableUpdateRate = false,
692 },
693 SubscribeOptions{
694 .propId = 0,
695 .areaIds = {1},
696 .sampleRate = 20.0,
697 .resolution = 0.1,
698 .enableVariableUpdateRate = true,
699 }));
700
701 std::vector<VehiclePropValue> propertyEvents = {{
702 .prop = 0,
703 .areaId = 0,
704 .value = {.floatValues = {1.0}},
705 .timestamp = 1,
706 },
707 {
708 .prop = 0,
709 .areaId = 1,
710 .value = {.floatValues = {1.0}},
711 .timestamp = 1,
712 }};
713 auto clients =
714 getManager()->getSubscribedClients(std::vector<VehiclePropValue>(propertyEvents));
715
716 ASSERT_THAT(clients[client1], UnorderedElementsAre(propertyEvents[0]));
717 ASSERT_THAT(clients[client2], UnorderedElementsAre(propertyEvents[0], propertyEvents[1]));
718
719 clients = getManager()->getSubscribedClients({{
720 .prop = 0,
721 .areaId = 0,
722 .value = {.floatValues = {1.01}},
723 .timestamp = 2,
724 }});
725
726 ASSERT_FALSE(clients.find(client1) == clients.end())
727 << "Must not filter out property events if VUR is not enabled";
728 ASSERT_TRUE(clients.find(client2) == clients.end())
729 << "Must filter out property events if VUR is enabled and change is too small";
730 ASSERT_TRUE(abs(clients[client1][0].value.floatValues[0] - 1.01) < 0.0000001)
731 << "Expected property value == 1.01, instead got "
732 << clients[client1][0].value.floatValues[0];
733
734 clients = getManager()->getSubscribedClients({{
735 .prop = 0,
736 .areaId = 1,
737 .value = {.floatValues = {1.06}},
738 .timestamp = 3,
739 }});
740
741 ASSERT_TRUE(clients.find(client1) == clients.end())
742 << "Must not get property events for an areaId that the client hasn't subscribed to";
743 ASSERT_FALSE(clients.find(client2) == clients.end())
744 << "Must get property events significant changes";
745 ASSERT_TRUE(abs(clients[client2][0].value.floatValues[0] - 1.1) < 0.0000001)
746 << "Expected property value == 1.1, instead got "
747 << clients[client2][0].value.floatValues[0];
748 }
749
TEST_F(SubscriptionManagerTest,testSubscribe_enableVur_mustNotFilterStatusChange)750 TEST_F(SubscriptionManagerTest, testSubscribe_enableVur_mustNotFilterStatusChange) {
751 SpAIBinder binder1 = ndk::SharedRefBase::make<PropertyCallback>()->asBinder();
752 std::shared_ptr<IVehicleCallback> client1 = IVehicleCallback::fromBinder(binder1);
753 SpAIBinder binder2 = ndk::SharedRefBase::make<PropertyCallback>()->asBinder();
754 std::shared_ptr<IVehicleCallback> client2 = IVehicleCallback::fromBinder(binder2);
755 SubscribeOptions client1Option = {
756 .propId = 0,
757 .areaIds = {0},
758 .sampleRate = 10.0,
759 .enableVariableUpdateRate = false,
760 };
761 auto result = getManager()->subscribe(client1, {client1Option}, true);
762 ASSERT_TRUE(result.ok()) << "failed to subscribe: " << result.error().message();
763
764 ASSERT_THAT(getHardware()->getSubscribeOptions(), UnorderedElementsAre(client1Option));
765
766 getHardware()->clearSubscribeOptions();
767 SubscribeOptions client2Option = {
768 .propId = 0,
769 .areaIds = {0, 1},
770 .sampleRate = 20.0,
771 .enableVariableUpdateRate = true,
772 };
773
774 result = getManager()->subscribe(client2, {client2Option}, true);
775 ASSERT_TRUE(result.ok()) << "failed to subscribe: " << result.error().message();
776
777 ASSERT_THAT(getHardware()->getSubscribeOptions(),
778 UnorderedElementsAre(
779 SubscribeOptions{
780 .propId = 0,
781 .areaIds = {0},
782 .sampleRate = 20.0,
783 // This is enabled for client2, but disabled for client1.
784 .enableVariableUpdateRate = false,
785 },
786 SubscribeOptions{
787 .propId = 0,
788 .areaIds = {1},
789 .sampleRate = 20.0,
790 .enableVariableUpdateRate = true,
791 }));
792
793 VehiclePropValue propValue1 = {
794 .prop = 0,
795 .areaId = 0,
796 .value = {.int32Values = {0}},
797 .timestamp = 1,
798 };
799 auto clients = getManager()->getSubscribedClients(std::vector<VehiclePropValue>({propValue1}));
800
801 ASSERT_THAT(clients[client1], UnorderedElementsAre(propValue1));
802
803 // A new event with the same value, but different status must not be filtered out.
804 VehiclePropValue propValue2 = {
805 .prop = 0,
806 .areaId = 0,
807 .value = {.int32Values = {0}},
808 .status = VehiclePropertyStatus::UNAVAILABLE,
809 .timestamp = 2,
810 };
811 clients = getManager()->getSubscribedClients({propValue2});
812
813 ASSERT_THAT(clients[client1], UnorderedElementsAre(propValue2))
814 << "Must not filter out property events that has status change";
815 }
816
TEST_F(SubscriptionManagerTest,testSubscribe_enableVur_timestampUpdated_filterOutdatedEvent)817 TEST_F(SubscriptionManagerTest, testSubscribe_enableVur_timestampUpdated_filterOutdatedEvent) {
818 SpAIBinder binder1 = ndk::SharedRefBase::make<PropertyCallback>()->asBinder();
819 std::shared_ptr<IVehicleCallback> client1 = IVehicleCallback::fromBinder(binder1);
820 SpAIBinder binder2 = ndk::SharedRefBase::make<PropertyCallback>()->asBinder();
821 std::shared_ptr<IVehicleCallback> client2 = IVehicleCallback::fromBinder(binder2);
822 std::vector<SubscribeOptions> options = {{
823 .propId = 0,
824 .areaIds = {0},
825 .sampleRate = 10.0,
826 .enableVariableUpdateRate = true,
827 }};
828
829 // client1 subscribe with VUR enabled.
830 auto result = getManager()->subscribe(client1, options, true);
831 ASSERT_TRUE(result.ok()) << "failed to subscribe: " << result.error().message();
832
833 // Let client2 subscribe with VUR disabled so that we enabled VUR in DefaultVehicleHal layer.
834 result = getManager()->subscribe(client2,
835 {{
836 .propId = 0,
837 .areaIds = {0},
838 .sampleRate = 10.0,
839 .enableVariableUpdateRate = false,
840 }},
841 true);
842 ASSERT_TRUE(result.ok()) << "failed to subscribe: " << result.error().message();
843
844 VehiclePropValue value0 = {
845 .prop = 0,
846 .areaId = 0,
847 .value = {.int32Values = {0}},
848 .timestamp = 1,
849 };
850 auto clients = getManager()->getSubscribedClients({value0});
851
852 ASSERT_THAT(clients[client1], UnorderedElementsAre(value0));
853
854 // A new event with the same value arrived. This must update timestamp to 3.
855 VehiclePropValue value1 = {
856 .prop = 0,
857 .areaId = 0,
858 .value = {.int32Values = {0}},
859 .timestamp = 3,
860 };
861 clients = getManager()->getSubscribedClients({value1});
862
863 ASSERT_TRUE(clients.find(client1) == clients.end())
864 << "Must filter out duplicate property events if VUR is enabled";
865
866 // The latest timestamp is 3, so even though the value is not the same, this is outdated and
867 // must be ignored.
868 VehiclePropValue value2 = {
869 .prop = 0,
870 .areaId = 0,
871 .value = {.int32Values = {1}},
872 .timestamp = 2,
873 };
874 clients = getManager()->getSubscribedClients({value1});
875
876 ASSERT_TRUE(clients.find(client1) == clients.end())
877 << "Must filter out outdated property events if VUR is enabled";
878 }
879
880 } // namespace vehicle
881 } // namespace automotive
882 } // namespace hardware
883 } // namespace android
884