• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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