1 /*
2  * Copyright 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 "CarTelemetryImpl.h"
18 #include "CarTelemetryInternalImpl.h"
19 #include "FakeLooperWrapper.h"
20 #include "LooperWrapper.h"
21 #include "RingBuffer.h"
22 #include "TelemetryServer.h"
23 
24 #include <aidl/android/automotive/telemetry/internal/BnCarDataListener.h>
25 #include <aidl/android/automotive/telemetry/internal/CarDataInternal.h>
26 #include <aidl/android/automotive/telemetry/internal/ICarTelemetryInternal.h>
27 #include <aidl/android/frameworks/automotive/telemetry/BnCarTelemetryCallback.h>
28 #include <aidl/android/frameworks/automotive/telemetry/CallbackConfig.h>
29 #include <aidl/android/frameworks/automotive/telemetry/CarData.h>
30 #include <aidl/android/frameworks/automotive/telemetry/ICarTelemetry.h>
31 #include <android-base/chrono_utils.h>
32 #include <android-base/logging.h>
33 #include <gmock/gmock.h>
34 #include <gtest/gtest.h>
35 #include <utils/Timers.h>  // for ::systemTime()
36 
37 #include <unistd.h>
38 
39 #include <cstdint>
40 #include <memory>
41 #include <unordered_set>
42 
43 namespace android {
44 namespace automotive {
45 namespace telemetry {
46 
47 using ::aidl::android::automotive::telemetry::internal::BnCarDataListener;
48 using ::aidl::android::automotive::telemetry::internal::CarDataInternal;
49 using ::aidl::android::automotive::telemetry::internal::ICarTelemetryInternal;
50 using ::aidl::android::frameworks::automotive::telemetry::BnCarTelemetryCallback;
51 using ::aidl::android::frameworks::automotive::telemetry::CallbackConfig;
52 using ::aidl::android::frameworks::automotive::telemetry::CarData;
53 using ::aidl::android::frameworks::automotive::telemetry::ICarTelemetry;
54 using ::ndk::ScopedAStatus;
55 using ::testing::_;
56 using ::testing::ByMove;
57 using ::testing::Return;
58 using ::testing::UnorderedElementsAre;
59 
60 constexpr const std::chrono::nanoseconds kPushCarDataDelayNs = 1000ms;
61 constexpr const std::chrono::nanoseconds kAllowedErrorNs = 100ms;
62 const int kMaxBufferSize = 3;
63 
64 // Because `ScopedAStatus` is move-only, `EXPECT_CALL().WillRepeatedly()` will not work.
ReturnOk()65 inline testing::internal::ReturnAction<testing::internal::ByMoveWrapper<ScopedAStatus>> ReturnOk() {
66     return testing::Return(ByMove(ScopedAStatus::ok()));
67 }
68 
69 // Builds CallbackConfig from clients.
buildConfig(const std::vector<int32_t> & ids)70 CallbackConfig buildConfig(const std::vector<int32_t>& ids) {
71     CallbackConfig config;
72     config.carDataIds = ids;
73     return config;
74 }
75 
76 // Builds incoming CarData from writer clients.
buildCarData(int id,const std::vector<uint8_t> & content)77 CarData buildCarData(int id, const std::vector<uint8_t>& content) {
78     CarData msg;
79     msg.id = id;
80     msg.content = content;
81     return msg;
82 }
83 
84 // Builds outgoing CarDataInternal to the CarTelemetryService.
buildCarDataInternal(int id,const std::vector<uint8_t> & content)85 CarDataInternal buildCarDataInternal(int id, const std::vector<uint8_t>& content) {
86     CarDataInternal msg;
87     msg.id = id;
88     msg.content = content;
89     return msg;
90 }
91 
92 // Mock ICarDataListener, behaves as CarTelemetryService.
93 class MockCarDataListener : public BnCarDataListener {
94 public:
95     MOCK_METHOD(ScopedAStatus, onCarDataReceived, (const std::vector<CarDataInternal>& dataList),
96                 (override));
97 };
98 
99 // Mock ICarTelemetryCallback, behaves as client application.
100 class MockCarTelemetryCallback : public BnCarTelemetryCallback {
101 public:
102     MOCK_METHOD(ScopedAStatus, onChange, (const std::vector<int32_t>& ids), (override));
103 };
104 
105 // The main test class. Tests using `ICarTelemetry` and `ICarTelemetryInternal` interfaces.
106 // Pushing data to the listener is done in the looper - always call `mFakeLooper.poll()`.
107 class TelemetryServerTest : public ::testing::Test {
108 protected:
TelemetryServerTest()109     TelemetryServerTest() :
110           mTelemetryServer(&mFakeLooper, kPushCarDataDelayNs, kMaxBufferSize),
111           mDefaultConfig(buildConfig({101})),
112           mMockCarDataListener(ndk::SharedRefBase::make<MockCarDataListener>()),
113           mMockCarTelemetryCallback(ndk::SharedRefBase::make<MockCarTelemetryCallback>()),
114           mTelemetry(ndk::SharedRefBase::make<CarTelemetryImpl>(&mTelemetryServer)),
115           mTelemetryInternal(
116                   ndk::SharedRefBase::make<CarTelemetryInternalImpl>(&mTelemetryServer)) {}
117 
118     // Creates an expectation. This is a nice helper that accepts a std::vector, original
119     // EXPECT_CALL() requires creating std::vector variable.
120     testing::internal::TypedExpectation<ScopedAStatus(const std::vector<CarDataInternal>&)>&
expectMockListenerToReceive(const std::vector<CarDataInternal> & expected)121     expectMockListenerToReceive(const std::vector<CarDataInternal>& expected) {
122         return EXPECT_CALL(*mMockCarDataListener, onCarDataReceived(expected));
123     }
124 
TearDown()125     void TearDown() override {
126         mTelemetryServer.mCarDataIds.clear();
127         mTelemetryServer.mCallbacks.clear();
128         mTelemetryServer.mIdToCallbacksMap.clear();
129     }
130 
131     FakeLooperWrapper mFakeLooper;
132     TelemetryServer mTelemetryServer;
133     CallbackConfig mDefaultConfig;
134     std::shared_ptr<MockCarDataListener> mMockCarDataListener;
135     std::shared_ptr<MockCarTelemetryCallback> mMockCarTelemetryCallback;
136     std::shared_ptr<ICarTelemetry> mTelemetry;
137     std::shared_ptr<ICarTelemetryInternal> mTelemetryInternal;
138 };
139 
TEST_F(TelemetryServerTest,WriteReturnsOk)140 TEST_F(TelemetryServerTest, WriteReturnsOk) {
141     std::vector<CarData> dataList = {buildCarData(101, {1})};
142 
143     auto status = mTelemetry->write(dataList);
144 
145     EXPECT_TRUE(status.isOk()) << status.getMessage();
146 }
147 
TEST_F(TelemetryServerTest,AddCarDataIdsReturnsOk)148 TEST_F(TelemetryServerTest, AddCarDataIdsReturnsOk) {
149     auto status = mTelemetryInternal->addCarDataIds({101});
150 
151     EXPECT_TRUE(status.isOk()) << status.getMessage();
152 }
153 
TEST_F(TelemetryServerTest,AddCarDataIdsNotifiesInterestedCallbacks)154 TEST_F(TelemetryServerTest, AddCarDataIdsNotifiesInterestedCallbacks) {
155     CallbackConfig config = buildConfig({101, 102});
156     std::shared_ptr<MockCarTelemetryCallback> mockCallback =
157             ndk::SharedRefBase::make<MockCarTelemetryCallback>();
158     mTelemetry->addCallback(config, mockCallback);
159     // mDefaultConfig only contains ID 101
160     mTelemetry->addCallback(mDefaultConfig, mMockCarTelemetryCallback);
161 
162     EXPECT_CALL(*mMockCarTelemetryCallback, onChange(UnorderedElementsAre(101)))
163             .Times(1)
164             .WillOnce(ReturnOk());
165     EXPECT_CALL(*mockCallback, onChange(UnorderedElementsAre(101, 102)))
166             .Times(1)
167             .WillOnce(ReturnOk());
168 
169     mTelemetryInternal->addCarDataIds({101, 102, 103, 104});
170 }
171 
TEST_F(TelemetryServerTest,RemoveCarDataIdsReturnsOk)172 TEST_F(TelemetryServerTest, RemoveCarDataIdsReturnsOk) {
173     mTelemetryInternal->addCarDataIds({101, 102, 103});
174     EXPECT_EQ(3, mTelemetryServer.mCarDataIds.size());
175 
176     auto status = mTelemetryInternal->removeCarDataIds({101, 103});
177 
178     EXPECT_TRUE(status.isOk()) << status.getMessage();
179     EXPECT_EQ(1, mTelemetryServer.mCarDataIds.size());
180     EXPECT_NE(mTelemetryServer.mCarDataIds.end(), mTelemetryServer.mCarDataIds.find(102));
181 }
182 
TEST_F(TelemetryServerTest,RemoveCarDataIdsNotifiesInterestedCallbacks)183 TEST_F(TelemetryServerTest, RemoveCarDataIdsNotifiesInterestedCallbacks) {
184     // should only receive updates on IDs 101, 102, 103
185     CallbackConfig config = buildConfig({101, 102, 103});
186     mTelemetry->addCallback(config, mMockCarTelemetryCallback);
187 
188     EXPECT_CALL(*mMockCarTelemetryCallback, onChange(UnorderedElementsAre(101, 102, 103)))
189             .Times(1)
190             .WillOnce(ReturnOk());
191     EXPECT_CALL(*mMockCarTelemetryCallback, onChange(UnorderedElementsAre(101, 102)))
192             .Times(1)
193             .WillOnce(ReturnOk());
194 
195     mTelemetryInternal->addCarDataIds({101, 102, 103, 104});
196     mTelemetryInternal->removeCarDataIds({103, 104});
197 }
198 
TEST_F(TelemetryServerTest,SetListenerReturnsOk)199 TEST_F(TelemetryServerTest, SetListenerReturnsOk) {
200     auto status = mTelemetryInternal->setListener(mMockCarDataListener);
201 
202     EXPECT_TRUE(status.isOk()) << status.getMessage();
203 }
204 
TEST_F(TelemetryServerTest,SetListenerAllowedWhenAlreadySubscribed)205 TEST_F(TelemetryServerTest, SetListenerAllowedWhenAlreadySubscribed) {
206     mTelemetryInternal->setListener(mMockCarDataListener);
207 
208     auto status = mTelemetryInternal->setListener(ndk::SharedRefBase::make<MockCarDataListener>());
209 
210     EXPECT_TRUE(status.isOk()) << status.getMessage();
211 }
212 
TEST_F(TelemetryServerTest,ClearListenerWorks)213 TEST_F(TelemetryServerTest, ClearListenerWorks) {
214     mTelemetryInternal->setListener(mMockCarDataListener);
215 
216     mTelemetryInternal->clearListener();
217 
218     auto status = mTelemetryInternal->setListener(mMockCarDataListener);
219     EXPECT_TRUE(status.isOk()) << status.getMessage();
220 }
221 
TEST_F(TelemetryServerTest,ClearListenerRemovesPushMessagesFromLooper)222 TEST_F(TelemetryServerTest, ClearListenerRemovesPushMessagesFromLooper) {
223     std::vector<CarData> dataList = {buildCarData(101, {1})};
224     mTelemetry->write(dataList);
225     mTelemetryInternal->setListener(mMockCarDataListener);
226     EXPECT_NE(mFakeLooper.getNextMessageUptime(), FakeLooperWrapper::kNoScheduledMessage);
227 
228     mTelemetryInternal->clearListener();
229 
230     EXPECT_EQ(mFakeLooper.getNextMessageUptime(), FakeLooperWrapper::kNoScheduledMessage);
231 }
232 
TEST_F(TelemetryServerTest,AddCallbackReturnsOk)233 TEST_F(TelemetryServerTest, AddCallbackReturnsOk) {
234     auto status = mTelemetry->addCallback(mDefaultConfig, mMockCarTelemetryCallback);
235 
236     EXPECT_TRUE(status.isOk()) << status.getMessage();
237 }
238 
TEST_F(TelemetryServerTest,AddCallbackReturnsErrorForExistingCallback)239 TEST_F(TelemetryServerTest, AddCallbackReturnsErrorForExistingCallback) {
240     mTelemetry->addCallback(mDefaultConfig, mMockCarTelemetryCallback);
241 
242     auto status = mTelemetry->addCallback(mDefaultConfig, mMockCarTelemetryCallback);
243 
244     EXPECT_FALSE(status.isOk()) << status.getMessage();
245 }
246 
TEST_F(TelemetryServerTest,AddCallbackReceivesCarDataIds)247 TEST_F(TelemetryServerTest, AddCallbackReceivesCarDataIds) {
248     CallbackConfig config = buildConfig({101, 102, 103});
249     mTelemetryInternal->addCarDataIds({101, 102, 103, 104});
250 
251     EXPECT_CALL(*mMockCarTelemetryCallback, onChange(UnorderedElementsAre(101, 102, 103)))
252             .Times(1)
253             .WillOnce(ReturnOk());
254 
255     auto status = mTelemetry->addCallback(config, mMockCarTelemetryCallback);
256 }
257 
TEST_F(TelemetryServerTest,RemoveCallbackReturnsOk)258 TEST_F(TelemetryServerTest, RemoveCallbackReturnsOk) {
259     mTelemetry->addCallback(mDefaultConfig, mMockCarTelemetryCallback);
260 
261     auto status = mTelemetry->removeCallback(mMockCarTelemetryCallback);
262 
263     EXPECT_TRUE(status.isOk()) << status.getMessage();
264     EXPECT_EQ(0, mTelemetryServer.mCallbacks.size());
265     EXPECT_EQ(0, mTelemetryServer.mIdToCallbacksMap.size());
266 }
267 
TEST_F(TelemetryServerTest,RemoveCallbackReturnsErrorForNonexistentCallback)268 TEST_F(TelemetryServerTest, RemoveCallbackReturnsErrorForNonexistentCallback) {
269     auto status = mTelemetry->removeCallback(mMockCarTelemetryCallback);
270 
271     EXPECT_FALSE(status.isOk()) << status.getMessage();
272 }
273 
TEST_F(TelemetryServerTest,WriteSchedulesNextMessageAfterRightDelay)274 TEST_F(TelemetryServerTest, WriteSchedulesNextMessageAfterRightDelay) {
275     std::vector<CarData> dataList = {buildCarData(101, {1})};
276     mTelemetryInternal->setListener(mMockCarDataListener);
277 
278     mTelemetry->write(dataList);
279 
280     EXPECT_NEAR(mFakeLooper.getNextMessageUptime(), ::systemTime() + kPushCarDataDelayNs.count(),
281                 kAllowedErrorNs.count());
282 }
283 
TEST_F(TelemetryServerTest,SetListenerSchedulesNextMessageAfterRightDelay)284 TEST_F(TelemetryServerTest, SetListenerSchedulesNextMessageAfterRightDelay) {
285     std::vector<CarData> dataList = {buildCarData(101, {1})};
286     mTelemetry->write(dataList);
287 
288     mTelemetryInternal->setListener(mMockCarDataListener);
289 
290     EXPECT_NEAR(mFakeLooper.getNextMessageUptime(), ::systemTime() + kPushCarDataDelayNs.count(),
291                 kAllowedErrorNs.count());
292 }
293 
TEST_F(TelemetryServerTest,BuffersOnlyLimitedData)294 TEST_F(TelemetryServerTest, BuffersOnlyLimitedData) {
295     mTelemetryInternal->setListener(mMockCarDataListener);
296     std::vector<CarData> dataList1 = {buildCarData(10, {1, 2}), buildCarData(11, {2, 3})};
297     std::vector<CarData> dataList2 = {buildCarData(101, {1, 2}), buildCarData(102, {2, 3}),
298                                       buildCarData(103, {3, 4}), buildCarData(104, {4, 5})};
299     mTelemetryInternal->addCarDataIds({10, 11, 101, 102, 103, 104});
300 
301     mTelemetry->write(dataList1);
302     mTelemetry->write(dataList2);
303 
304     // Only the last 3 CarData should be received, because kMaxBufferSize = 3.
305     expectMockListenerToReceive({buildCarDataInternal(102, {2, 3})}).WillOnce(ReturnOk());
306     expectMockListenerToReceive({buildCarDataInternal(103, {3, 4})}).WillOnce(ReturnOk());
307     expectMockListenerToReceive({buildCarDataInternal(104, {4, 5})}).WillOnce(ReturnOk());
308 
309     mFakeLooper.poll();
310     mFakeLooper.poll();
311     mFakeLooper.poll();
312     mFakeLooper.poll();
313 }
314 
315 // Data is filtered out when mTelemetryInternal->addCarDataIds() is not called
TEST_F(TelemetryServerTest,WriteFiltersDataBasedOnId)316 TEST_F(TelemetryServerTest, WriteFiltersDataBasedOnId) {
317     std::vector<CarData> dataList = {buildCarData(101, {1})};
318     mTelemetryInternal->setListener(mMockCarDataListener);
319 
320     mTelemetry->write(dataList);
321 
322     expectMockListenerToReceive({buildCarDataInternal(101, {1})}).Times(0);
323 
324     mFakeLooper.poll();
325 }
326 
327 // First sets the listener, then writes CarData.
TEST_F(TelemetryServerTest,WhenListenerIsAlreadySetItPushesData)328 TEST_F(TelemetryServerTest, WhenListenerIsAlreadySetItPushesData) {
329     std::vector<CarData> dataList = {buildCarData(101, {1})};
330     mTelemetryInternal->addCarDataIds({101});
331 
332     mTelemetryInternal->setListener(mMockCarDataListener);
333     mTelemetry->write(dataList);
334 
335     expectMockListenerToReceive({buildCarDataInternal(101, {1})}).Times(1).WillOnce(ReturnOk());
336 
337     mFakeLooper.poll();
338 }
339 
340 // First writes CarData, only then sets the listener.
TEST_F(TelemetryServerTest,WhenListenerIsSetLaterItPushesData)341 TEST_F(TelemetryServerTest, WhenListenerIsSetLaterItPushesData) {
342     std::vector<CarData> dataList = {buildCarData(101, {1})};
343     mTelemetryInternal->addCarDataIds({101});
344 
345     mTelemetry->write(dataList);
346     mTelemetryInternal->setListener(mMockCarDataListener);
347 
348     expectMockListenerToReceive({buildCarDataInternal(101, {1})}).Times(1).WillOnce(ReturnOk());
349 
350     mFakeLooper.poll();
351 }
352 
TEST_F(TelemetryServerTest,WriteDuringPushingDataToListener)353 TEST_F(TelemetryServerTest, WriteDuringPushingDataToListener) {
354     mTelemetryInternal->addCarDataIds({101, 102, 103});
355     std::vector<CarData> dataList = {buildCarData(101, {1}), buildCarData(102, {1})};
356     std::vector<CarData> dataList2 = {buildCarData(103, {1})};
357     mTelemetryInternal->setListener(mMockCarDataListener);
358     mTelemetry->write(dataList);
359 
360     expectMockListenerToReceive({buildCarDataInternal(101, {1})}).WillOnce(ReturnOk());
361     expectMockListenerToReceive({buildCarDataInternal(102, {1})}).WillOnce(ReturnOk());
362     expectMockListenerToReceive({buildCarDataInternal(103, {1})}).WillOnce(ReturnOk());
363 
364     mFakeLooper.poll();  // sends only 1 CarData (or possibly 2 depenending on impl)
365     mTelemetry->write(dataList2);
366     mFakeLooper.poll();  // all the polls below send the rest of the CarData
367     mFakeLooper.poll();
368     mFakeLooper.poll();  // extra poll to verify there was not excess push calls
369 }
370 
TEST_F(TelemetryServerTest,ClearListenerDuringPushingDataToListener)371 TEST_F(TelemetryServerTest, ClearListenerDuringPushingDataToListener) {
372     std::vector<CarData> dataList = {buildCarData(101, {1})};
373     mTelemetryInternal->addCarDataIds({101});
374     mTelemetryInternal->setListener(mMockCarDataListener);
375     mTelemetry->write(dataList);
376 
377     expectMockListenerToReceive({buildCarDataInternal(101, {1})}).Times(1).WillOnce(ReturnOk());
378 
379     mFakeLooper.poll();
380     mTelemetry->write(dataList);
381     mTelemetryInternal->clearListener();
382     mFakeLooper.poll();
383 }
384 
TEST_F(TelemetryServerTest,RetriesPushAgainIfListenerFails)385 TEST_F(TelemetryServerTest, RetriesPushAgainIfListenerFails) {
386     std::vector<CarData> dataList = {buildCarData(101, {1})};
387     mTelemetryInternal->addCarDataIds({101});
388     mTelemetryInternal->setListener(mMockCarDataListener);
389     mTelemetry->write(dataList);
390 
391     expectMockListenerToReceive({buildCarDataInternal(101, {1})})
392             .WillOnce(Return(ByMove(ScopedAStatus::fromExceptionCode(::EX_TRANSACTION_FAILED))))
393             .WillOnce(ReturnOk());
394 
395     mFakeLooper.poll();  // listener returns ::EX_TRANSACTION_FAILED
396     mFakeLooper.poll();
397 }
398 
399 // Tests a corner case to make sure `TelemetryServer::mPendingCarDataInternals` variable
400 // is handled properly when transaction fails and clearListener() is called.
TEST_F(TelemetryServerTest,ClearListenerDuringPushingDataAndSetListenerAgain)401 TEST_F(TelemetryServerTest, ClearListenerDuringPushingDataAndSetListenerAgain) {
402     std::vector<CarData> dataList = {buildCarData(101, {1})};
403     mTelemetryInternal->addCarDataIds({101});
404     mTelemetryInternal->setListener(mMockCarDataListener);
405     mTelemetry->write(dataList);
406 
407     expectMockListenerToReceive({buildCarDataInternal(101, {1})})
408             .WillOnce(Return(ByMove(ScopedAStatus::fromExceptionCode(::EX_TRANSACTION_FAILED))))
409             .WillOnce(ReturnOk());
410 
411     mFakeLooper.poll();  // listener returns ::EX_TRANSACTION_FAILED
412     mTelemetryInternal->clearListener();
413     mFakeLooper.poll();  // nothing happens
414     mTelemetryInternal->setListener(mMockCarDataListener);
415     mFakeLooper.poll();  // should work
416 }
417 
418 // Directly calls pushCarDataToListeners() to make sure it can handle edge-cases.
TEST_F(TelemetryServerTest,NoListenerButMultiplePushes)419 TEST_F(TelemetryServerTest, NoListenerButMultiplePushes) {
420     std::vector<CarData> dataList = {buildCarData(101, {1})};
421     mTelemetryInternal->addCarDataIds({101});
422     mTelemetry->write(dataList);
423 
424     mTelemetryServer.pushCarDataToListeners();
425     mTelemetryServer.pushCarDataToListeners();
426     mTelemetryServer.pushCarDataToListeners();
427 
428     EXPECT_CALL(*mMockCarDataListener, onCarDataReceived(_)).Times(0);
429 }
430 
431 // Directly calls pushCarDataToListeners() to make sure it can handle edge-cases.
TEST_F(TelemetryServerTest,NoDataButMultiplePushes)432 TEST_F(TelemetryServerTest, NoDataButMultiplePushes) {
433     mTelemetryInternal->setListener(mMockCarDataListener);
434 
435     mTelemetryServer.pushCarDataToListeners();
436     mTelemetryServer.pushCarDataToListeners();
437     mTelemetryServer.pushCarDataToListeners();
438 
439     EXPECT_CALL(*mMockCarDataListener, onCarDataReceived(_)).Times(0);
440 }
441 
442 }  // namespace telemetry
443 }  // namespace automotive
444 }  // namespace android
445