• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2020, 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_WATCHDOG_SERVER_SRC_WATCHDOGPERFSERVICE_H_
18 #define CPP_WATCHDOG_SERVER_SRC_WATCHDOGPERFSERVICE_H_
19 
20 #include "LooperWrapper.h"
21 #include "ProcDiskStats.h"
22 #include "ProcPidStat.h"
23 #include "ProcStat.h"
24 #include "UidIoStats.h"
25 
26 #include <android-base/chrono_utils.h>
27 #include <android-base/result.h>
28 #include <android/automotive/watchdog/internal/PowerCycle.h>
29 #include <cutils/multiuser.h>
30 #include <gtest/gtest_prod.h>
31 #include <utils/Errors.h>
32 #include <utils/Looper.h>
33 #include <utils/Mutex.h>
34 #include <utils/RefBase.h>
35 #include <utils/String16.h>
36 #include <utils/StrongPointer.h>
37 #include <utils/Vector.h>
38 
39 #include <time.h>
40 
41 #include <string>
42 #include <thread>  // NOLINT(build/c++11)
43 #include <unordered_set>
44 
45 namespace android {
46 namespace automotive {
47 namespace watchdog {
48 
49 // Forward declaration for testing use only.
50 namespace internal {
51 
52 class WatchdogPerfServicePeer;
53 
54 }  // namespace internal
55 
56 constexpr const char* kStartCustomCollectionFlag = "--start_perf";
57 constexpr const char* kEndCustomCollectionFlag = "--stop_perf";
58 constexpr const char* kIntervalFlag = "--interval";
59 constexpr const char* kMaxDurationFlag = "--max_duration";
60 constexpr const char* kFilterPackagesFlag = "--filter_packages";
61 
62 enum SystemState {
63     NORMAL_MODE = 0,
64     GARAGE_MODE = 1,
65 };
66 
67 /*
68  * DataProcessor defines methods that must be implemented in order to process the data collected
69  * by |WatchdogPerfService|.
70  */
71 class IDataProcessorInterface : public android::RefBase {
72 public:
IDataProcessorInterface()73     IDataProcessorInterface() {}
~IDataProcessorInterface()74     virtual ~IDataProcessorInterface() {}
75     // Returns the name of the data processor.
76     virtual std::string name() = 0;
77     // Callback to initialize the data processor.
78     virtual android::base::Result<void> init() = 0;
79     // Callback to terminate the data processor.
80     virtual void terminate() = 0;
81     // Callback to process the data collected during boot-time.
82     virtual android::base::Result<void> onBoottimeCollection(
83             time_t time, const android::wp<UidIoStats>& uidIoStats,
84             const android::wp<ProcStat>& procStat, const android::wp<ProcPidStat>& procPidStat) = 0;
85     // Callback to process the data collected periodically post boot complete.
86     virtual android::base::Result<void> onPeriodicCollection(
87             time_t time, SystemState systemState, const android::wp<UidIoStats>& uidIoStats,
88             const android::wp<ProcStat>& procStat, const android::wp<ProcPidStat>& procPidStat) = 0;
89     /*
90      * Callback to process the data collected on custom collection and filter the results only to
91      * the specified |filterPackages|.
92      */
93     virtual android::base::Result<void> onCustomCollection(
94             time_t time, SystemState systemState,
95             const std::unordered_set<std::string>& filterPackages,
96             const android::wp<UidIoStats>& uidIoStats, const android::wp<ProcStat>& procStat,
97             const android::wp<ProcPidStat>& procPidStat) = 0;
98     /*
99      * Callback to periodically monitor the collected data and trigger the given |alertHandler|
100      * on detecting resource overuse.
101      */
102     virtual android::base::Result<void> onPeriodicMonitor(
103             time_t time, const android::wp<IProcDiskStatsInterface>& procDiskStats,
104             const std::function<void()>& alertHandler) = 0;
105     // Callback to dump the boot-time collected and periodically collected data.
106     virtual android::base::Result<void> onDump(int fd) = 0;
107     /*
108      * Callback to dump the custom collected data. When fd == -1, clear the custom collection cache.
109      */
110     virtual android::base::Result<void> onCustomCollectionDump(int fd) = 0;
111 };
112 
113 enum EventType {
114     // WatchdogPerfService's state.
115     INIT = 0,
116     TERMINATED,
117 
118     // Collection events.
119     BOOT_TIME_COLLECTION,
120     PERIODIC_COLLECTION,
121     CUSTOM_COLLECTION,
122 
123     // Monitor event.
124     PERIODIC_MONITOR,
125 
126     LAST_EVENT,
127 };
128 
129 enum SwitchMessage {
130     /*
131      * On receiving this message, collect the last boot-time record and start periodic collection
132      * and monitor.
133      */
134     END_BOOTTIME_COLLECTION = EventType::LAST_EVENT + 1,
135 
136     /*
137      * On receiving this message, ends custom collection, discard collected data and start periodic
138      * collection and monitor.
139      */
140     END_CUSTOM_COLLECTION,
141 };
142 
143 /*
144  * WatchdogPerfServiceInterface collects performance data during boot-time and periodically post
145  * boot complete. It exposes APIs that the main thread and binder service can call to start a
146  * collection, switch the collection type, and generate collection dumps.
147  */
148 class WatchdogPerfServiceInterface : public MessageHandler {
149 public:
150     // Register a data processor to process the data collected by |WatchdogPerfService|.
151     virtual android::base::Result<void> registerDataProcessor(
152             android::sp<IDataProcessorInterface> processor) = 0;
153     /*
154      * Starts the boot-time collection in the looper handler on a new thread and returns
155      * immediately. Must be called only once. Otherwise, returns an error.
156      */
157     virtual android::base::Result<void> start() = 0;
158     // Terminates the collection thread and returns.
159     virtual void terminate() = 0;
160     // Sets the system state.
161     virtual void setSystemState(SystemState systemState) = 0;
162     // Ends the boot-time collection by switching to periodic collection and returns immediately.
163     virtual android::base::Result<void> onBootFinished() = 0;
164     /*
165      * Depending on the arguments, it either:
166      * 1. Starts a custom collection.
167      * 2. Or ends the current custom collection and dumps the collected data.
168      * Returns any error observed during the dump generation.
169      */
170     virtual android::base::Result<void> onCustomCollection(
171             int fd, const Vector<android::String16>& args) = 0;
172     // Generates a dump from the boot-time and periodic collection events.
173     virtual android::base::Result<void> onDump(int fd) = 0;
174     // Dumps the help text.
175     virtual bool dumpHelpText(int fd) = 0;
176 };
177 
178 class WatchdogPerfService final : public WatchdogPerfServiceInterface {
179 public:
WatchdogPerfService()180     WatchdogPerfService() :
181           mHandlerLooper(android::sp<LooperWrapper>::make()),
182           mSystemState(NORMAL_MODE),
183           mBoottimeCollection({}),
184           mPeriodicCollection({}),
185           mCustomCollection({}),
186           mPeriodicMonitor({}),
187           mCurrCollectionEvent(EventType::INIT),
188           mUidIoStats(android::sp<UidIoStats>::make()),
189           mProcStat(android::sp<ProcStat>::make()),
190           mProcPidStat(android::sp<ProcPidStat>::make()),
191           mProcDiskStats(android::sp<ProcDiskStats>::make()),
192           mDataProcessors({}) {}
193 
~WatchdogPerfService()194     ~WatchdogPerfService() { terminate(); }
195 
196     android::base::Result<void> registerDataProcessor(
197             android::sp<IDataProcessorInterface> processor) override;
198 
199     android::base::Result<void> start() override;
200 
201     void terminate() override;
202 
203     void setSystemState(SystemState systemState) override;
204 
205     android::base::Result<void> onBootFinished() override;
206 
207     android::base::Result<void> onCustomCollection(int fd,
208                                                    const Vector<android::String16>& args) override;
209 
210     android::base::Result<void> onDump(int fd) override;
211 
212     bool dumpHelpText(int fd) override;
213 
214 private:
215     struct EventMetadata {
216         // Collection or monitor event.
217         EventType eventType = EventType::LAST_EVENT;
218         // Interval between subsequent events.
219         std::chrono::nanoseconds interval = 0ns;
220         // Used to calculate the uptime for next event.
221         nsecs_t lastUptime = 0;
222         // Filter the results only to the specified packages.
223         std::unordered_set<std::string> filterPackages;
224 
225         std::string toString() const;
226     };
227 
228     // Dumps the collectors' status when they are disabled.
229     android::base::Result<void> dumpCollectorsStatusLocked(int fd);
230 
231     /*
232      * Starts a custom collection on the looper handler, temporarily stops the periodic collection
233      * (won't discard the collected data), and returns immediately. Returns any error observed
234      * during this process.
235      * The custom collection happens once every |interval| seconds. When the |maxDuration| is
236      * reached, the looper receives a message to end the collection, discards the collected data,
237      * and starts the periodic collection. This is needed to ensure the custom collection doesn't
238      * run forever when a subsequent |endCustomCollection| call is not received.
239      * When |kFilterPackagesFlag| value specified, the results are filtered only to the specified
240      * package names.
241      */
242     android::base::Result<void> startCustomCollection(
243             std::chrono::nanoseconds interval, std::chrono::nanoseconds maxDuration,
244             const std::unordered_set<std::string>& filterPackages);
245 
246     /*
247      * Ends the current custom collection, generates a dump, sends a looper message to start the
248      * periodic collection, and returns immediately. Returns an error when there is no custom
249      * collection running or when a dump couldn't be generated from the custom collection.
250      */
251     android::base::Result<void> endCustomCollection(int fd);
252 
253     // Handles the messages received by the lopper.
254     void handleMessage(const Message& message) override;
255 
256     // Processes the collection events received by |handleMessage|.
257     android::base::Result<void> processCollectionEvent(EventMetadata* metadata);
258 
259     // Collects/processes the performance data for the current collection event.
260     android::base::Result<void> collectLocked(EventMetadata* metadata);
261 
262     // Processes the monitor events received by |handleMessage|.
263     android::base::Result<void> processMonitorEvent(EventMetadata* metadata);
264 
265     /*
266      * Returns the metadata for the current collection based on |mCurrCollectionEvent|. Returns
267      * nullptr on invalid collection event.
268      */
269     EventMetadata* currCollectionMetadataLocked();
270 
271     // Thread on which the actual collection happens.
272     std::thread mCollectionThread;
273 
274     // Makes sure only one collection is running at any given time.
275     Mutex mMutex;
276 
277     // Handler lopper to execute different collection events on the collection thread.
278     android::sp<LooperWrapper> mHandlerLooper GUARDED_BY(mMutex);
279 
280     // Current system state.
281     SystemState mSystemState GUARDED_BY(mMutex);
282 
283     // Info for the |CollectionEvent::BOOT_TIME| collection event.
284     EventMetadata mBoottimeCollection GUARDED_BY(mMutex);
285 
286     // Info for the |CollectionEvent::PERIODIC| collection event.
287     EventMetadata mPeriodicCollection GUARDED_BY(mMutex);
288 
289     /*
290      * Info for the |CollectionEvent::CUSTOM| collection event. The info is cleared at the end of
291      * every custom collection.
292      */
293     EventMetadata mCustomCollection GUARDED_BY(mMutex);
294 
295     // Info for the |EventType::PERIODIC| monitor event.
296     EventMetadata mPeriodicMonitor GUARDED_BY(mMutex);
297 
298     /*
299      * Tracks either the WatchdogPerfService's state or current collection event. Updated on
300      * |start|, |onBootComplete|, |startCustomCollection|, |endCustomCollection|, and |terminate|.
301      */
302     EventType mCurrCollectionEvent GUARDED_BY(mMutex);
303 
304     // Collector/parser for `/proc/uid_io/stats`.
305     android::sp<UidIoStats> mUidIoStats GUARDED_BY(mMutex);
306 
307     // Collector/parser for `/proc/stat`.
308     android::sp<ProcStat> mProcStat GUARDED_BY(mMutex);
309 
310     // Collector/parser for `/proc/PID/*` stat files.
311     android::sp<ProcPidStat> mProcPidStat GUARDED_BY(mMutex);
312 
313     // Collector/parser for `/proc/diskstats` file.
314     android::sp<IProcDiskStatsInterface> mProcDiskStats GUARDED_BY(mMutex);
315 
316     // Data processors for the collected performance data.
317     std::vector<android::sp<IDataProcessorInterface>> mDataProcessors GUARDED_BY(mMutex);
318 
319     // For unit tests.
320     friend class internal::WatchdogPerfServicePeer;
321     FRIEND_TEST(WatchdogPerfServiceTest, TestServiceStartAndTerminate);
322 };
323 
324 }  // namespace watchdog
325 }  // namespace automotive
326 }  // namespace android
327 
328 #endif  //  CPP_WATCHDOG_SERVER_SRC_WATCHDOGPERFSERVICE_H_
329