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