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 #ifndef CPP_TELEMETRY_CARTELEMETRYD_TESTS_FAKELOOPERWRAPPER_H_
18 #define CPP_TELEMETRY_CARTELEMETRYD_TESTS_FAKELOOPERWRAPPER_H_
19 
20 #include "LooperWrapper.h"
21 
22 #include <algorithm>
23 #include <deque>
24 #include <map>
25 
26 namespace android {
27 namespace automotive {
28 namespace telemetry {
29 
30 // Fake `utils/Looper.h` implementation. Explicitly use `FakeLooperWrapper::poll()` method
31 // to process the messages.
32 //
33 // Not thread-safe.
34 class FakeLooperWrapper : public LooperWrapper {
35 public:
36     static inline constexpr int kNoScheduledMessage = -1;
37 
FakeLooperWrapper()38     FakeLooperWrapper() : LooperWrapper(nullptr) {}
39 
pollAll(int timeoutMillis)40     int pollAll(int timeoutMillis) override { return 0; }
41 
sendMessageDelayed(nsecs_t uptime,const android::sp<MessageHandler> & handler,const Message & message)42     void sendMessageDelayed(nsecs_t uptime, const android::sp<MessageHandler>& handler,
43                             const Message& message) override {
44         mUptimeEntries[::systemTime() + uptime].push_back(
45                 {.mHandler = handler, .mMessage = message});
46     }
47 
removeMessages(const android::sp<MessageHandler> & handler,int what)48     void removeMessages(const android::sp<MessageHandler>& handler, int what) override {
49         for (auto it = mUptimeEntries.begin(); it != mUptimeEntries.end();) {
50             auto [entryUptime, entries] = *it;
51             for (auto eit = entries.begin(); eit != entries.end();) {
52                 if (eit->mMessage.what == what) {
53                     eit = entries.erase(eit);
54                 } else {
55                     ++eit;
56                 }
57             }
58             if (entries.empty()) {
59                 it = mUptimeEntries.erase(it);
60             } else {
61                 ++it;
62             }
63         }
64     }
65 
66     // Processes the next message.
poll()67     void poll() {
68         auto it = mUptimeEntries.begin();
69         if (it == mUptimeEntries.end() || it->second.empty()) {
70             return;
71         }
72         auto entry = std::move(it->second.front());
73         it->second.pop_front();
74         if (it->second.empty()) {
75             // if entries is empty, erase the uptime from the map.
76             mUptimeEntries.erase(it);
77         }
78         entry.mHandler->handleMessage(entry.mMessage);
79     }
80 
81     // Returns the next scheduled message uptime. kNoScheduledMessage if there is no message.
getNextMessageUptime()82     nsecs_t getNextMessageUptime() {
83         auto it = mUptimeEntries.begin();
84         return it == mUptimeEntries.end() ? kNoScheduledMessage : it->first;
85     }
86 
87 private:
88     struct LooperEntry {
89         sp<MessageHandler> mHandler;
90         Message mMessage;
91     };
92 
93 private:
94     using Entries = std::deque<LooperEntry>;
95 
96     // <uptimeNanos, entries> - where uptimeNanos is time since boot.
97     std::map<nsecs_t, Entries> mUptimeEntries;
98 };
99 
100 }  // namespace telemetry
101 }  // namespace automotive
102 }  // namespace android
103 
104 #endif  // CPP_TELEMETRY_CARTELEMETRYD_TESTS_FAKELOOPERWRAPPER_H_
105