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