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_IOOVERUSEMONITOR_H_
18 #define CPP_WATCHDOG_SERVER_SRC_IOOVERUSEMONITOR_H_
19 
20 #include "AIBinderDeathRegistrationWrapper.h"
21 #include "IoOveruseConfigs.h"
22 #include "PackageInfoResolver.h"
23 #include "ProcStatCollector.h"
24 #include "UidStatsCollector.h"
25 #include "WatchdogPerfService.h"
26 
27 #include <aidl/android/automotive/watchdog/IResourceOveruseListener.h>
28 #include <aidl/android/automotive/watchdog/PerStateBytes.h>
29 #include <aidl/android/automotive/watchdog/internal/ComponentType.h>
30 #include <aidl/android/automotive/watchdog/internal/PackageInfo.h>
31 #include <aidl/android/automotive/watchdog/internal/PackageIoOveruseStats.h>
32 #include <aidl/android/automotive/watchdog/internal/ResourceOveruseConfiguration.h>
33 #include <android-base/result.h>
34 #include <android-base/stringprintf.h>
35 #include <android/binder_auto_utils.h>
36 #include <android/util/ProtoOutputStream.h>
37 #include <cutils/multiuser.h>
38 #include <utils/Mutex.h>
39 
40 #include <time.h>
41 
42 #include <ostream>
43 #include <string>
44 #include <unordered_map>
45 #include <unordered_set>
46 #include <vector>
47 
48 namespace android {
49 namespace automotive {
50 namespace watchdog {
51 
52 // Number of periodically monitored stats to cache in memory.
53 constexpr int32_t kDefaultPeriodicMonitorBufferSize = 360;
54 // Dumpsys flags.
55 constexpr const char* kResetResourceOveruseStatsFlag = "--reset_resource_overuse_stats";
56 
57 // Forward declaration for testing use only.
58 namespace internal {
59 
60 class IoOveruseMonitorPeer;
61 
62 }  // namespace internal
63 
64 // Used only in tests.
65 std::tuple<int64_t, int64_t> calculateStartAndDuration(const time_point_millis& currentTime);
66 
67 /**
68  * IoOveruseMonitorInterface interface defines the methods that the I/O overuse monitoring module
69  * should implement.
70  */
71 class IoOveruseMonitorInterface : virtual public DataProcessorInterface {
72 public:
73     // Returns whether or not the monitor is initialized.
74     virtual bool isInitialized() const = 0;
75 
76     // Dumps the help text.
77     virtual bool dumpHelpText(int fd) const = 0;
78 
79     // Below API is from internal/ICarWatchdog.aidl. Please refer to the AIDL for description.
80     virtual android::base::Result<void> updateResourceOveruseConfigurations(
81             const std::vector<
82                     aidl::android::automotive::watchdog::internal::ResourceOveruseConfiguration>&
83                     configs) = 0;
84     virtual android::base::Result<void> getResourceOveruseConfigurations(
85             std::vector<
86                     aidl::android::automotive::watchdog::internal::ResourceOveruseConfiguration>*
87                     configs) const = 0;
88     virtual android::base::Result<void> onTodayIoUsageStatsFetched(
89             const std::vector<
90                     aidl::android::automotive::watchdog::internal::UserPackageIoUsageStats>&
91                     userPackageIoUsageStats) = 0;
92 
93     // Below methods support APIs from ICarWatchdog.aidl. Please refer to the AIDL for description.
94     virtual android::base::Result<void> addIoOveruseListener(
95             const std::shared_ptr<aidl::android::automotive::watchdog::IResourceOveruseListener>&
96                     listener) = 0;
97 
98     virtual android::base::Result<void> removeIoOveruseListener(
99             const std::shared_ptr<aidl::android::automotive::watchdog::IResourceOveruseListener>&
100                     listener) = 0;
101 
102     virtual void handleBinderDeath(void* cookie) = 0;
103 
104     virtual android::base::Result<void> getIoOveruseStats(
105             aidl::android::automotive::watchdog::IoOveruseStats* ioOveruseStats) const = 0;
106 
107     virtual android::base::Result<void> resetIoOveruseStats(
108             const std::vector<std::string>& packageNames) = 0;
109 
110     // Removes stats for the given user from the internal cache.
111     virtual void removeStatsForUser(userid_t userId) = 0;
112 };
113 
114 class IoOveruseMonitor final : public IoOveruseMonitorInterface {
115 public:
116     explicit IoOveruseMonitor(
117             const android::sp<WatchdogServiceHelperInterface>& watchdogServiceHelper);
118 
~IoOveruseMonitor()119     ~IoOveruseMonitor() { terminate(); }
120 
isInitialized()121     bool isInitialized() const override {
122         std::shared_lock readLock(mRwMutex);
123         return isInitializedLocked();
124     }
125 
126     void onCarWatchdogServiceRegistered() override;
127 
128     // Below methods implement DataProcessorInterface.
name()129     std::string name() const override { return "IoOveruseMonitor"; }
130     friend std::ostream& operator<<(std::ostream& os, const IoOveruseMonitor& monitor);
131 
onSystemStartup()132     android::base::Result<void> onSystemStartup() {
133         // No tracking of boot-time and wake-up events in I/O overuse monitoring.
134         return {};
135     }
136 
onBoottimeCollection(time_point_millis time,const android::wp<UidStatsCollectorInterface> & uidStatsCollector,const android::wp<ProcStatCollectorInterface> & procStatCollector,aidl::android::automotive::watchdog::internal::ResourceStats * resourceStats)137     android::base::Result<void> onBoottimeCollection(
138             [[maybe_unused]] time_point_millis time,
139             [[maybe_unused]] const android::wp<UidStatsCollectorInterface>& uidStatsCollector,
140             [[maybe_unused]] const android::wp<ProcStatCollectorInterface>& procStatCollector,
141             [[maybe_unused]] aidl::android::automotive::watchdog::internal::ResourceStats*
142                     resourceStats) override {
143         // No I/O overuse monitoring during boot-time.
144         return {};
145     }
146 
onWakeUpCollection(time_point_millis time,const android::wp<UidStatsCollectorInterface> & uidStatsCollector,const android::wp<ProcStatCollectorInterface> & procStatCollector)147     android::base::Result<void> onWakeUpCollection(
148             [[maybe_unused]] time_point_millis time,
149             [[maybe_unused]] const android::wp<UidStatsCollectorInterface>& uidStatsCollector,
150             [[maybe_unused]] const android::wp<ProcStatCollectorInterface>& procStatCollector)
151             override {
152         // No I/O overuse monitoring during wake up.
153         return {};
154     }
155 
onUserSwitchCollection(time_point_millis time,userid_t from,userid_t to,const android::wp<UidStatsCollectorInterface> & uidStatsCollector,const android::wp<ProcStatCollectorInterface> & procStatCollector)156     android::base::Result<void> onUserSwitchCollection(
157             [[maybe_unused]] time_point_millis time, [[maybe_unused]] userid_t from,
158             [[maybe_unused]] userid_t to,
159             [[maybe_unused]] const android::wp<UidStatsCollectorInterface>& uidStatsCollector,
160             [[maybe_unused]] const android::wp<ProcStatCollectorInterface>& procStatCollector)
161             override {
162         // No I/O overuse monitoring during user switch.
163         return {};
164     }
165 
166     android::base::Result<void> onPeriodicCollection(
167             time_point_millis time, SystemState systemState,
168             const android::wp<UidStatsCollectorInterface>& uidStatsCollector,
169             const android::wp<ProcStatCollectorInterface>& procStatCollector,
170             aidl::android::automotive::watchdog::internal::ResourceStats* resourceStats) override;
171 
172     android::base::Result<void> onCustomCollection(
173             time_point_millis time, SystemState systemState,
174             const std::unordered_set<std::string>& filterPackages,
175             const android::wp<UidStatsCollectorInterface>& uidStatsCollector,
176             const android::wp<ProcStatCollectorInterface>& procStatCollector,
177             aidl::android::automotive::watchdog::internal::ResourceStats* resourceStats) override;
178 
179     android::base::Result<void> onPeriodicMonitor(
180             time_t time, const android::wp<ProcDiskStatsCollectorInterface>& procDiskStatsCollector,
181             const std::function<void()>& alertHandler) override;
182 
183     android::base::Result<void> onDump(int fd) const override;
184     android::base::Result<void> onDumpProto(
185             const CollectionIntervals& collectionIntervals,
186             android::util::ProtoOutputStream& outProto) const override;
187 
188     bool dumpHelpText(int fd) const override;
189 
onCustomCollectionDump(int fd)190     android::base::Result<void> onCustomCollectionDump([[maybe_unused]] int fd) override {
191         // No special processing for custom collection. Thus no custom collection dump.
192         return {};
193     }
194 
195     // Below methods implement AIDL interfaces.
196     android::base::Result<void> updateResourceOveruseConfigurations(
197             const std::vector<
198                     aidl::android::automotive::watchdog::internal::ResourceOveruseConfiguration>&
199                     configs) override;
200 
201     android::base::Result<void> getResourceOveruseConfigurations(
202             std::vector<
203                     aidl::android::automotive::watchdog::internal::ResourceOveruseConfiguration>*
204                     configs) const override;
205 
206     android::base::Result<void> onTodayIoUsageStatsFetched(
207             const std::vector<
208                     aidl::android::automotive::watchdog::internal::UserPackageIoUsageStats>&
209                     userPackageIoUsageStats) override;
210 
211     android::base::Result<void> addIoOveruseListener(
212             const std::shared_ptr<aidl::android::automotive::watchdog::IResourceOveruseListener>&
213                     listener) override;
214 
215     android::base::Result<void> removeIoOveruseListener(
216             const std::shared_ptr<aidl::android::automotive::watchdog::IResourceOveruseListener>&
217                     listener) override;
218 
219     void handleBinderDeath(void* cookie) override;
220 
221     android::base::Result<void> getIoOveruseStats(
222             aidl::android::automotive::watchdog::IoOveruseStats* ioOveruseStats) const override;
223 
224     android::base::Result<void> resetIoOveruseStats(
225             const std::vector<std::string>& packageName) override;
226 
227     void removeStatsForUser(userid_t userId) override;
228 
229 protected:
230     android::base::Result<void> init();
231 
232     void terminate();
233 
234 private:
235     struct WrittenBytesSnapshot {
236         double pollDurationInSecs;
237         uint64_t bytesInKib;
238     };
239 
240     struct UserPackageIoUsage {
241         UserPackageIoUsage(
242                 const aidl::android::automotive::watchdog::internal::PackageInfo& packageInfo,
243                 const UidIoStats& uidIoStats, const bool isGarageModeActive);
244         aidl::android::automotive::watchdog::internal::PackageInfo packageInfo = {};
245         aidl::android::automotive::watchdog::PerStateBytes writtenBytes = {};
246         aidl::android::automotive::watchdog::PerStateBytes forgivenWriteBytes = {};
247         int totalOveruses = 0;
248         bool isPackageWarned = false;
249         uint64_t lastSyncedWrittenBytes = 0;
250 
251         UserPackageIoUsage& operator+=(const UserPackageIoUsage& r);
252         UserPackageIoUsage& operator+=(
253                 const aidl::android::automotive::watchdog::internal::IoUsageStats& r);
254 
255         const std::string id() const;
256         void resetStats();
257     };
258 
259 private:
isInitializedLocked()260     bool isInitializedLocked() const { return mIoOveruseConfigs != nullptr; }
261 
262     void requestTodayIoUsageStatsLocked();
263 
264     void notifyNativePackagesLocked(
265             const std::unordered_map<uid_t, aidl::android::automotive::watchdog::IoOveruseStats>&
266                     statsByUid);
267 
268     using ListenersByUidMap = std::unordered_map<
269             uid_t, std::shared_ptr<aidl::android::automotive::watchdog::IResourceOveruseListener>>;
270     using Processor = std::function<void(ListenersByUidMap&, ListenersByUidMap::const_iterator)>;
271     bool findListenerAndProcessLocked(uintptr_t binderPtrId, const Processor& processor);
272 
273     /**
274      * Writes in-memory configs to disk asynchronously if configs are not written after latest
275      * update.
276      */
277     void writeConfigsToDiskAsyncLocked();
278 
279     // Local PackageInfoResolverInterface instance. Useful to mock in tests.
280     sp<PackageInfoResolverInterface> mPackageInfoResolver;
281 
282     // Minimum written bytes to sync the stats with the Watchdog service.
283     double mMinSyncWrittenBytes;
284 
285     // Helper to communicate with the CarWatchdogService.
286     android::sp<WatchdogServiceHelperInterface> mWatchdogServiceHelper;
287 
288     // AIBinder death registration wrapper. Useful for mocking in tests.
289     android::sp<AIBinderDeathRegistrationWrapperInterface> mDeathRegistrationWrapper;
290 
291     // Makes sure only one collection is running at any given time.
292     mutable std::shared_mutex mRwMutex;
293 
294     // This is the thread on which the write to disk is performed. In the event the monitor begins
295     // to terminate before the write has completed, the termination procedure should wait for this
296     // thread to complete. Otherwise, this thread will run independently, which will cause
297     // the thread to access stale lock or member fields leading to crashing the process.
298     std::thread mWriteToDiskThread;
299 
300     // Tracks if mWriteToDiskThread is actively writing to disk.
301     bool mIsWriteToDiskPending GUARDED_BY(mRwMutex);
302 
303     // Indicates whether or not today's I/O usage stats, that were collected during previous boot,
304     // are read from CarService because CarService persists these stats in database across reboot.
305     bool mDidReadTodayPrevBootStats GUARDED_BY(mRwMutex);
306 
307     // Summary of configs available for all the components and system-wide overuse alert thresholds.
308     sp<IoOveruseConfigsInterface> mIoOveruseConfigs GUARDED_BY(mRwMutex);
309 
310     /**
311      * Delta of system-wide written kib across all disks from the last |mPeriodicMonitorBufferSize|
312      * polls along with the polling duration.
313      */
314     std::vector<WrittenBytesSnapshot> mSystemWideWrittenBytes GUARDED_BY(mRwMutex);
315     size_t mPeriodicMonitorBufferSize GUARDED_BY(mRwMutex);
316     time_t mLastSystemWideIoMonitorTime GUARDED_BY(mRwMutex);
317 
318     // Cache of I/O usage stats from previous boot that happened today. Key is a unique ID with
319     // the format `packageName:userId`.
320     std::unordered_map<std::string, aidl::android::automotive::watchdog::internal::IoUsageStats>
321             mPrevBootIoUsageStatsById GUARDED_BY(mRwMutex);
322 
323     // Cache of per user package I/O usage. Key is a unique ID with the format `packageName:userId`.
324     std::unordered_map<std::string, UserPackageIoUsage> mUserPackageDailyIoUsageById
325             GUARDED_BY(mRwMutex);
326     double mIoOveruseWarnPercentage GUARDED_BY(mRwMutex);
327     time_point_millis mLastUserPackageIoMonitorTime GUARDED_BY(mRwMutex);
328     std::vector<aidl::android::automotive::watchdog::internal::PackageIoOveruseStats>
329             mLatestIoOveruseStats;
330 
331     ListenersByUidMap mOveruseListenersByUid GUARDED_BY(mRwMutex);
332     ndk::ScopedAIBinder_DeathRecipient mBinderDeathRecipient;
333 
334     friend class WatchdogPerfService;
335 
336     // For unit tests.
337     friend class internal::IoOveruseMonitorPeer;
338 };
339 
340 }  // namespace watchdog
341 }  // namespace automotive
342 }  // namespace android
343 
344 #endif  //  CPP_WATCHDOG_SERVER_SRC_IOOVERUSEMONITOR_H_
345