• 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::VehiclePropValue;
47 using ::aidl::android::hardware::automotive::vehicle::VehiclePropValues;
48 using ::ndk::ScopedAStatus;
49 using ::ndk::SpAIBinder;
50 using ::testing::ElementsAre;
51 using ::testing::WhenSorted;
52 
53 class PropertyCallback final : public BnVehicleCallback {
54   public:
onGetValues(const GetValueResults &)55     ScopedAStatus onGetValues(const GetValueResults&) override { return ScopedAStatus::ok(); }
56 
onSetValues(const SetValueResults &)57     ScopedAStatus onSetValues(const SetValueResults&) override { return ScopedAStatus::ok(); }
58 
onPropertyEvent(const VehiclePropValues & values,int32_t)59     ScopedAStatus onPropertyEvent(const VehiclePropValues& values, int32_t) override {
60         std::scoped_lock<std::mutex> lockGuard(mLock);
61         for (const auto& value : values.payloads) {
62             mEvents.push_back(value);
63         }
64         return ScopedAStatus::ok();
65     }
66 
onPropertySetError(const VehiclePropErrors &)67     ScopedAStatus onPropertySetError(const VehiclePropErrors&) override {
68         return ScopedAStatus::ok();
69     }
70 
71     // Test functions.
getEvents()72     std::list<VehiclePropValue> getEvents() {
73         std::scoped_lock<std::mutex> lockGuard(mLock);
74         return mEvents;
75     }
76 
clearEvents()77     void clearEvents() {
78         std::scoped_lock<std::mutex> lockGuard(mLock);
79         mEvents.clear();
80     }
81 
82   private:
83     std::mutex mLock;
84     std::list<VehiclePropValue> mEvents GUARDED_BY(mLock);
85 };
86 
87 class SubscriptionManagerTest : public testing::Test {
88   public:
SetUp()89     void SetUp() override {
90         mHardware = std::make_shared<MockVehicleHardware>();
91         mManager = std::make_unique<SubscriptionManager>(mHardware.get());
92         mCallback = ndk::SharedRefBase::make<PropertyCallback>();
93         // Keep the local binder alive.
94         mBinder = mCallback->asBinder();
95         mCallbackClient = IVehicleCallback::fromBinder(mBinder);
96         std::shared_ptr<IVehicleCallback> callbackClient = mCallbackClient;
97         mHardware->registerOnPropertyChangeEvent(
98                 std::make_unique<IVehicleHardware::PropertyChangeCallback>(
99                         [callbackClient](std::vector<VehiclePropValue> updatedValues) {
100                             VehiclePropValues values = {
101                                     .payloads = std::move(updatedValues),
102                             };
103                             callbackClient->onPropertyEvent(values, 0);
104                         }));
105     }
106 
getManager()107     SubscriptionManager* getManager() { return mManager.get(); }
108 
getCallbackClient()109     std::shared_ptr<IVehicleCallback> getCallbackClient() { return mCallbackClient; }
110 
getCallback()111     PropertyCallback* getCallback() { return mCallback.get(); }
112 
getEvents()113     std::list<VehiclePropValue> getEvents() { return getCallback()->getEvents(); }
114 
clearEvents()115     void clearEvents() { return getCallback()->clearEvents(); }
116 
117   private:
118     std::unique_ptr<SubscriptionManager> mManager;
119     std::shared_ptr<PropertyCallback> mCallback;
120     std::shared_ptr<IVehicleCallback> mCallbackClient;
121     std::shared_ptr<MockVehicleHardware> mHardware;
122     SpAIBinder mBinder;
123 };
124 
TEST_F(SubscriptionManagerTest,testSubscribeGlobalContinuous)125 TEST_F(SubscriptionManagerTest, testSubscribeGlobalContinuous) {
126     std::vector<SubscribeOptions> options = {{
127             .propId = 0,
128             .areaIds = {0},
129             .sampleRate = 10.0,
130     }};
131 
132     auto result = getManager()->subscribe(getCallbackClient(), options, true);
133     ASSERT_TRUE(result.ok()) << "failed to subscribe: " << result.error().message();
134 
135     std::this_thread::sleep_for(std::chrono::seconds(1));
136 
137     // Theoretically trigger 10 times, but check for at least 9 times to be stable.
138     ASSERT_GE(getEvents().size(), static_cast<size_t>(9));
139     EXPECT_EQ(getEvents().back().prop, 0);
140     EXPECT_EQ(getEvents().back().areaId, 0);
141 }
142 
TEST_F(SubscriptionManagerTest,testSubscribeMultiplePropsGlobalContinuous)143 TEST_F(SubscriptionManagerTest, testSubscribeMultiplePropsGlobalContinuous) {
144     std::vector<SubscribeOptions> options = {{
145                                                      .propId = 0,
146                                                      .areaIds = {0},
147                                                      .sampleRate = 10.0,
148                                              },
149                                              {
150                                                      .propId = 1,
151                                                      .areaIds = {0},
152                                                      .sampleRate = 20.0,
153                                              }};
154 
155     auto result = getManager()->subscribe(getCallbackClient(), options, true);
156     ASSERT_TRUE(result.ok()) << "failed to subscribe: " << result.error().message();
157 
158     std::this_thread::sleep_for(std::chrono::seconds(1));
159 
160     size_t event0Count = 0;
161     size_t event1Count = 0;
162 
163     for (const auto& event : getEvents()) {
164         if (event.prop == 0) {
165             event0Count++;
166         } else {
167             event1Count++;
168         }
169     }
170 
171     // Theoretically trigger 10 times, but check for at least 9 times to be stable.
172     EXPECT_GE(event0Count, static_cast<size_t>(9));
173     // Theoretically trigger 20 times, but check for at least 15 times to be stable.
174     EXPECT_GE(event1Count, static_cast<size_t>(15));
175 }
176 
TEST_F(SubscriptionManagerTest,testOverrideSubscriptionContinuous)177 TEST_F(SubscriptionManagerTest, testOverrideSubscriptionContinuous) {
178     std::vector<SubscribeOptions> options = {{
179             .propId = 0,
180             .areaIds = {0},
181             .sampleRate = 20.0,
182     }};
183 
184     auto result = getManager()->subscribe(getCallbackClient(), options, true);
185     ASSERT_TRUE(result.ok()) << "failed to subscribe: " << result.error().message();
186 
187     // Override sample rate to be 10.0.
188     options[0].sampleRate = 10.0;
189     result = getManager()->subscribe(getCallbackClient(), options, true);
190     ASSERT_TRUE(result.ok()) << "failed to subscribe: " << result.error().message();
191 
192     std::this_thread::sleep_for(std::chrono::seconds(1));
193 
194     // Theoretically trigger 10 times, but check for at least 9 times to be stable.
195     EXPECT_GE(getEvents().size(), static_cast<size_t>(9));
196     EXPECT_LE(getEvents().size(), static_cast<size_t>(15));
197 }
198 
TEST_F(SubscriptionManagerTest,testSubscribeMultipleAreasContinuous)199 TEST_F(SubscriptionManagerTest, testSubscribeMultipleAreasContinuous) {
200     std::vector<SubscribeOptions> options = {
201             {
202                     .propId = 0,
203                     .areaIds = {0, 1},
204                     .sampleRate = 10.0,
205             },
206     };
207 
208     auto result = getManager()->subscribe(getCallbackClient(), options, true);
209     ASSERT_TRUE(result.ok()) << "failed to subscribe: " << result.error().message();
210 
211     std::this_thread::sleep_for(std::chrono::seconds(1));
212 
213     size_t area0Count = 0;
214     size_t area1Count = 0;
215 
216     for (const auto& event : getEvents()) {
217         if (event.areaId == 0) {
218             area0Count++;
219         } else {
220             area1Count++;
221         }
222     }
223 
224     // Theoretically trigger 10 times, but check for at least 9 times to be stable.
225     EXPECT_GE(area0Count, static_cast<size_t>(9));
226     // Theoretically trigger 10 times, but check for at least 9 times to be stable.
227     EXPECT_GE(area1Count, static_cast<size_t>(9));
228 }
229 
TEST_F(SubscriptionManagerTest,testUnsubscribeGlobalContinuous)230 TEST_F(SubscriptionManagerTest, testUnsubscribeGlobalContinuous) {
231     std::vector<SubscribeOptions> options = {{
232             .propId = 0,
233             .areaIds = {0},
234             .sampleRate = 100.0,
235     }};
236 
237     auto result = getManager()->subscribe(getCallbackClient(), options, true);
238     ASSERT_TRUE(result.ok()) << "failed to subscribe: " << result.error().message();
239 
240     result = getManager()->unsubscribe(getCallbackClient()->asBinder().get());
241     ASSERT_TRUE(result.ok()) << "failed to unsubscribe: " << result.error().message();
242 
243     // Wait for the last events to come.
244     std::this_thread::sleep_for(std::chrono::milliseconds(100));
245 
246     clearEvents();
247 
248     std::this_thread::sleep_for(std::chrono::milliseconds(100));
249 
250     ASSERT_TRUE(getEvents().empty());
251 }
252 
TEST_F(SubscriptionManagerTest,testUnsubscribeMultipleAreas)253 TEST_F(SubscriptionManagerTest, testUnsubscribeMultipleAreas) {
254     std::vector<SubscribeOptions> options = {
255             {
256                     .propId = 0,
257                     .areaIds = {0, 1, 2, 3, 4},
258                     .sampleRate = 10.0,
259             },
260             {
261                     .propId = 1,
262                     .areaIds = {0},
263                     .sampleRate = 10.0,
264             },
265     };
266 
267     auto result = getManager()->subscribe(getCallbackClient(), options, true);
268     ASSERT_TRUE(result.ok()) << "failed to subscribe: " << result.error().message();
269 
270     result = getManager()->unsubscribe(getCallbackClient()->asBinder().get(),
271                                        std::vector<int32_t>({0}));
272     ASSERT_TRUE(result.ok()) << "failed to unsubscribe: " << result.error().message();
273 
274     // Wait for the last events to come.
275     std::this_thread::sleep_for(std::chrono::milliseconds(100));
276 
277     clearEvents();
278 
279     std::this_thread::sleep_for(std::chrono::seconds(1));
280 
281     // Theoretically trigger 10 times, but check for at least 9 times to be stable.
282     EXPECT_GE(getEvents().size(), static_cast<size_t>(9));
283 
284     for (const auto& event : getEvents()) {
285         EXPECT_EQ(event.prop, 1);
286     }
287 }
288 
TEST_F(SubscriptionManagerTest,testUnsubscribeByCallback)289 TEST_F(SubscriptionManagerTest, testUnsubscribeByCallback) {
290     std::vector<SubscribeOptions> options = {
291             {
292                     .propId = 0,
293                     .areaIds = {0, 1, 2, 3, 4},
294                     .sampleRate = 10.0,
295             },
296             {
297                     .propId = 1,
298                     .areaIds = {0},
299                     .sampleRate = 10.0,
300             },
301     };
302 
303     auto result = getManager()->subscribe(getCallbackClient(), options, true);
304     ASSERT_TRUE(result.ok()) << "failed to subscribe: " << result.error().message();
305 
306     result = getManager()->unsubscribe(getCallbackClient()->asBinder().get());
307     ASSERT_TRUE(result.ok()) << "failed to unsubscribe: " << result.error().message();
308 
309     // Wait for the last events to come.
310     std::this_thread::sleep_for(std::chrono::milliseconds(100));
311 
312     clearEvents();
313 
314     std::this_thread::sleep_for(std::chrono::seconds(1));
315 
316     EXPECT_TRUE(getEvents().empty());
317 }
318 
TEST_F(SubscriptionManagerTest,testUnsubscribeFailure)319 TEST_F(SubscriptionManagerTest, testUnsubscribeFailure) {
320     std::vector<SubscribeOptions> options = {
321             {
322                     .propId = 0,
323                     .areaIds = {0, 1, 2, 3, 4},
324             },
325             {
326                     .propId = 1,
327                     .areaIds = {0},
328             },
329     };
330 
331     auto result = getManager()->subscribe(getCallbackClient(), options, false);
332     ASSERT_TRUE(result.ok()) << "failed to subscribe: " << result.error().message();
333 
334     // Property ID: 2 was not subscribed.
335     result = getManager()->unsubscribe(getCallbackClient()->asBinder().get(),
336                                        std::vector<int32_t>({0, 1, 2}));
337     ASSERT_FALSE(result.ok()) << "unsubscribe an unsubscribed property must fail";
338 
339     // Since property 0 and property 1 was not unsubscribed successfully, we should be able to
340     // unsubscribe them again.
341     result = getManager()->unsubscribe(getCallbackClient()->asBinder().get(),
342                                        std::vector<int32_t>({0, 1}));
343     ASSERT_TRUE(result.ok()) << "a failed unsubscription must not unsubscribe any properties"
344                              << result.error().message();
345 }
346 
TEST_F(SubscriptionManagerTest,testSubscribeOnchange)347 TEST_F(SubscriptionManagerTest, testSubscribeOnchange) {
348     std::vector<SubscribeOptions> options1 = {
349             {
350                     .propId = 0,
351                     .areaIds = {0, 1},
352             },
353             {
354                     .propId = 1,
355                     .areaIds = {0},
356             },
357     };
358     std::vector<SubscribeOptions> options2 = {
359             {
360                     .propId = 0,
361                     .areaIds = {0},
362             },
363     };
364 
365     SpAIBinder binder1 = ndk::SharedRefBase::make<PropertyCallback>()->asBinder();
366     std::shared_ptr<IVehicleCallback> client1 = IVehicleCallback::fromBinder(binder1);
367     SpAIBinder binder2 = ndk::SharedRefBase::make<PropertyCallback>()->asBinder();
368     std::shared_ptr<IVehicleCallback> client2 = IVehicleCallback::fromBinder(binder2);
369     auto result = getManager()->subscribe(client1, options1, false);
370     ASSERT_TRUE(result.ok()) << "failed to subscribe: " << result.error().message();
371     result = getManager()->subscribe(client2, options2, false);
372     ASSERT_TRUE(result.ok()) << "failed to subscribe: " << result.error().message();
373 
374     std::vector<VehiclePropValue> updatedValues = {
375             {
376                     .prop = 0,
377                     .areaId = 0,
378             },
379             {
380                     .prop = 0,
381                     .areaId = 1,
382             },
383             {
384                     .prop = 1,
385                     .areaId = 0,
386             },
387             {
388                     .prop = 1,
389                     .areaId = 1,
390             },
391     };
392     auto clients = getManager()->getSubscribedClients(updatedValues);
393 
394     ASSERT_THAT(clients[client1],
395                 WhenSorted(ElementsAre(&updatedValues[0], &updatedValues[1], &updatedValues[2])));
396     ASSERT_THAT(clients[client2], ElementsAre(&updatedValues[0]));
397 }
398 
TEST_F(SubscriptionManagerTest,testSubscribeInvalidOption)399 TEST_F(SubscriptionManagerTest, testSubscribeInvalidOption) {
400     std::vector<SubscribeOptions> options = {
401             {
402                     .propId = 0,
403                     .areaIds = {0, 1, 2, 3, 4},
404                     // invalid sample rate.
405                     .sampleRate = 0.0,
406             },
407             {
408                     .propId = 1,
409                     .areaIds = {0},
410                     .sampleRate = 10.0,
411             },
412     };
413 
414     auto result = getManager()->subscribe(getCallbackClient(), options, true);
415     ASSERT_FALSE(result.ok()) << "subscribe with invalid sample rate must fail";
416     ASSERT_TRUE(getManager()
417                         ->getSubscribedClients({{
418                                                         .prop = 0,
419                                                         .areaId = 0,
420                                                 },
421                                                 {
422                                                         .prop = 1,
423                                                         .areaId = 0,
424                                                 }})
425                         .empty())
426             << "no property should be subscribed if error is returned";
427 }
428 
TEST_F(SubscriptionManagerTest,testSubscribeNoAreaIds)429 TEST_F(SubscriptionManagerTest, testSubscribeNoAreaIds) {
430     std::vector<SubscribeOptions> options = {
431             {
432                     .propId = 0,
433                     .areaIds = {},
434                     .sampleRate = 1.0,
435             },
436             {
437                     .propId = 1,
438                     .areaIds = {0},
439                     .sampleRate = 10.0,
440             },
441     };
442 
443     auto result = getManager()->subscribe(getCallbackClient(), options, true);
444     ASSERT_FALSE(result.ok()) << "subscribe with invalid sample rate must fail";
445     ASSERT_TRUE(getManager()
446                         ->getSubscribedClients({{
447                                 .prop = 1,
448                                 .areaId = 0,
449                         }})
450                         .empty())
451             << "no property should be subscribed if error is returned";
452 }
453 
TEST_F(SubscriptionManagerTest,testUnsubscribeOnchange)454 TEST_F(SubscriptionManagerTest, testUnsubscribeOnchange) {
455     std::vector<SubscribeOptions> options = {
456             {
457                     .propId = 0,
458                     .areaIds = {0, 1},
459             },
460             {
461                     .propId = 1,
462                     .areaIds = {0},
463             },
464     };
465 
466     auto result = getManager()->subscribe(getCallbackClient(), options, false);
467     ASSERT_TRUE(result.ok()) << "failed to subscribe: " << result.error().message();
468 
469     result = getManager()->unsubscribe(getCallbackClient()->asBinder().get(),
470                                        std::vector<int32_t>({0}));
471     ASSERT_TRUE(result.ok()) << "failed to unsubscribe: " << result.error().message();
472 
473     std::vector<VehiclePropValue> updatedValues = {
474             {
475                     .prop = 0,
476                     .areaId = 0,
477             },
478             {
479                     .prop = 1,
480                     .areaId = 0,
481             },
482     };
483     auto clients = getManager()->getSubscribedClients(updatedValues);
484 
485     ASSERT_THAT(clients[getCallbackClient()], ElementsAre(&updatedValues[1]));
486 }
487 
TEST_F(SubscriptionManagerTest,testCheckSampleRateHzValid)488 TEST_F(SubscriptionManagerTest, testCheckSampleRateHzValid) {
489     ASSERT_TRUE(SubscriptionManager::checkSampleRateHz(1.0));
490 }
491 
TEST_F(SubscriptionManagerTest,testCheckSampleRateHzInvalidTooSmall)492 TEST_F(SubscriptionManagerTest, testCheckSampleRateHzInvalidTooSmall) {
493     ASSERT_FALSE(SubscriptionManager::checkSampleRateHz(FLT_MIN));
494 }
495 
TEST_F(SubscriptionManagerTest,testCheckSampleRateHzInvalidZero)496 TEST_F(SubscriptionManagerTest, testCheckSampleRateHzInvalidZero) {
497     ASSERT_FALSE(SubscriptionManager::checkSampleRateHz(0));
498 }
499 
500 }  // namespace vehicle
501 }  // namespace automotive
502 }  // namespace hardware
503 }  // namespace android
504