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