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 "IoOveruseConfigs.h"
21 #include "PackageInfoResolver.h"
22 #include "ProcStat.h"
23 #include "UidStatsCollector.h"
24 #include "WatchdogPerfService.h"
25 
26 #include <android-base/result.h>
27 #include <android-base/stringprintf.h>
28 #include <android/automotive/watchdog/BnResourceOveruseListener.h>
29 #include <android/automotive/watchdog/PerStateBytes.h>
30 #include <android/automotive/watchdog/internal/ComponentType.h>
31 #include <android/automotive/watchdog/internal/IoOveruseConfiguration.h>
32 #include <android/automotive/watchdog/internal/PackageInfo.h>
33 #include <android/automotive/watchdog/internal/PackageIoOveruseStats.h>
34 #include <cutils/multiuser.h>
35 #include <utils/Mutex.h>
36 
37 #include <time.h>
38 
39 #include <ostream>
40 #include <string>
41 #include <unordered_map>
42 #include <unordered_set>
43 #include <vector>
44 
45 namespace android {
46 namespace automotive {
47 namespace watchdog {
48 
49 // Number of periodically monitored stats to cache in memory.
50 constexpr int32_t kDefaultPeriodicMonitorBufferSize = 360;
51 // Dumpsys flags.
52 constexpr const char* kResetResourceOveruseStatsFlag = "--reset_resource_overuse_stats";
53 
54 // Forward declaration for testing use only.
55 namespace internal {
56 
57 class IoOveruseMonitorPeer;
58 
59 }  // namespace internal
60 
61 // Used only in tests.
62 std::tuple<int64_t, int64_t> calculateStartAndDuration(const time_t& currentTime);
63 
64 /**
65  * IIoOveruseMonitor interface defines the methods that the I/O overuse monitoring module
66  * should implement.
67  */
68 class IIoOveruseMonitor : virtual public IDataProcessorInterface {
69 public:
70     // Returns whether or not the monitor is initialized.
71     virtual bool isInitialized() const = 0;
72 
73     // Dumps the help text.
74     virtual bool dumpHelpText(int fd) const = 0;
75 
76     // Below API is from internal/ICarWatchdog.aidl. Please refer to the AIDL for description.
77     virtual android::base::Result<void> updateResourceOveruseConfigurations(
78             const std::vector<
79                     android::automotive::watchdog::internal::ResourceOveruseConfiguration>&
80                     configs) = 0;
81     virtual android::base::Result<void> getResourceOveruseConfigurations(
82             std::vector<android::automotive::watchdog::internal::ResourceOveruseConfiguration>*
83                     configs) const = 0;
84 
85     // Below methods support APIs from ICarWatchdog.aidl. Please refer to the AIDL for description.
86     virtual android::base::Result<void> addIoOveruseListener(
87             const sp<IResourceOveruseListener>& listener) = 0;
88 
89     virtual android::base::Result<void> removeIoOveruseListener(
90             const sp<IResourceOveruseListener>& listener) = 0;
91 
92     virtual android::base::Result<void> getIoOveruseStats(IoOveruseStats* ioOveruseStats) const = 0;
93 
94     virtual android::base::Result<void> resetIoOveruseStats(
95             const std::vector<std::string>& packageNames) = 0;
96 
97     // Removes stats for the given user from the internal cache.
98     virtual void removeStatsForUser(userid_t userId) = 0;
99 };
100 
101 class IoOveruseMonitor final : public IIoOveruseMonitor {
102 public:
103     explicit IoOveruseMonitor(const android::sp<IWatchdogServiceHelper>& watchdogServiceHelper);
104 
~IoOveruseMonitor()105     ~IoOveruseMonitor() { terminate(); }
106 
isInitialized()107     bool isInitialized() const override {
108         std::shared_lock readLock(mRwMutex);
109         return isInitializedLocked();
110     }
111 
112     // Below methods implement IDataProcessorInterface.
name()113     std::string name() const override { return "IoOveruseMonitor"; }
114     friend std::ostream& operator<<(std::ostream& os, const IoOveruseMonitor& monitor);
115     android::base::Result<void> onBoottimeCollection(
116             [[maybe_unused]] time_t time,
117             [[maybe_unused]] const android::wp<UidStatsCollectorInterface>& uidStatsCollector,
118             [[maybe_unused]] const android::wp<ProcStat>& procStat) override {
119         // No I/O overuse monitoring during boot-time.
120         return {};
121     }
122 
123     android::base::Result<void> onPeriodicCollection(
124             time_t time, SystemState systemState,
125             const android::wp<UidStatsCollectorInterface>& uidStatsCollector,
126             const android::wp<ProcStat>& procStat) override;
127 
128     android::base::Result<void> onCustomCollection(
129             time_t time, SystemState systemState,
130             const std::unordered_set<std::string>& filterPackages,
131             const android::wp<UidStatsCollectorInterface>& uidStatsCollector,
132             const android::wp<ProcStat>& procStat) override;
133 
134     android::base::Result<void> onPeriodicMonitor(
135             time_t time, const android::wp<IProcDiskStatsInterface>& procDiskStats,
136             const std::function<void()>& alertHandler) override;
137 
138     android::base::Result<void> onDump(int fd) const override;
139 
140     bool dumpHelpText(int fd) const override;
141 
142     android::base::Result<void> onCustomCollectionDump([[maybe_unused]] int fd) override {
143         // No special processing for custom collection. Thus no custom collection dump.
144         return {};
145     }
146 
147     // Below methods implement AIDL interfaces.
148     android::base::Result<void> updateResourceOveruseConfigurations(
149             const std::vector<
150                     android::automotive::watchdog::internal::ResourceOveruseConfiguration>& configs)
151             override;
152 
153     android::base::Result<void> getResourceOveruseConfigurations(
154             std::vector<android::automotive::watchdog::internal::ResourceOveruseConfiguration>*
155                     configs) const override;
156 
157     android::base::Result<void> addIoOveruseListener(
158             const sp<IResourceOveruseListener>& listener) override;
159 
160     android::base::Result<void> removeIoOveruseListener(
161             const sp<IResourceOveruseListener>& listener) override;
162 
163     android::base::Result<void> getIoOveruseStats(IoOveruseStats* ioOveruseStats) const override;
164 
165     android::base::Result<void> resetIoOveruseStats(
166             const std::vector<std::string>& packageName) override;
167 
168     void removeStatsForUser(userid_t userId) override;
169 
170 protected:
171     android::base::Result<void> init();
172 
173     void terminate();
174 
175 private:
176     struct WrittenBytesSnapshot {
177         double pollDurationInSecs;
178         uint64_t bytesInKib;
179     };
180 
181     struct UserPackageIoUsage {
182         UserPackageIoUsage(const android::automotive::watchdog::internal::PackageInfo& packageInfo,
183                            const UidIoStats& uidIoStats, const bool isGarageModeActive);
184         android::automotive::watchdog::internal::PackageInfo packageInfo = {};
185         PerStateBytes writtenBytes = {};
186         PerStateBytes forgivenWriteBytes = {};
187         int totalOveruses = 0;
188         bool isPackageWarned = false;
189         uint64_t lastSyncedWrittenBytes = 0;
190 
191         UserPackageIoUsage& operator+=(const UserPackageIoUsage& r);
192         UserPackageIoUsage& operator+=(
193                 const android::automotive::watchdog::internal::IoUsageStats& r);
194 
195         const std::string id() const;
196         void resetStats();
197     };
198 
199     class BinderDeathRecipient final : public android::IBinder::DeathRecipient {
200     public:
BinderDeathRecipient(const android::sp<IoOveruseMonitor> & service)201         explicit BinderDeathRecipient(const android::sp<IoOveruseMonitor>& service) :
202               mService(service) {}
203 
binderDied(const android::wp<android::IBinder> & who)204         void binderDied(const android::wp<android::IBinder>& who) override {
205             mService->handleBinderDeath(who);
206         }
207 
208     private:
209         android::sp<IoOveruseMonitor> mService;
210     };
211 
212 private:
isInitializedLocked()213     bool isInitializedLocked() const { return mIoOveruseConfigs != nullptr; }
214 
215     void syncTodayIoUsageStatsLocked();
216 
217     void notifyNativePackagesLocked(const std::unordered_map<uid_t, IoOveruseStats>& statsByUid);
218 
219     void handleBinderDeath(const wp<IBinder>& who);
220 
221     using ListenersByUidMap = std::unordered_map<uid_t, android::sp<IResourceOveruseListener>>;
222     using Processor = std::function<void(ListenersByUidMap&, ListenersByUidMap::const_iterator)>;
223     bool findListenerAndProcessLocked(const sp<IBinder>& binder, const Processor& processor);
224 
225     /**
226      * Writes in-memory configs to disk asynchronously if configs are not written after latest
227      * update.
228      */
229     void writeConfigsToDiskAsyncLocked();
230 
231     // Local IPackageInfoResolver instance. Useful to mock in tests.
232     sp<IPackageInfoResolver> mPackageInfoResolver;
233     // Minimum written bytes to sync the stats with the Watchdog service.
234     double mMinSyncWrittenBytes;
235     android::sp<IWatchdogServiceHelper> mWatchdogServiceHelper;
236 
237     // Makes sure only one collection is running at any given time.
238     mutable std::shared_mutex mRwMutex;
239 
240     // Indicates whether or not today's I/O usage stats, that were collected during previous boot,
241     // are read from CarService because CarService persists these stats in database across reboot.
242     bool mDidReadTodayPrevBootStats GUARDED_BY(mRwMutex);
243 
244     // Summary of configs available for all the components and system-wide overuse alert thresholds.
245     sp<IIoOveruseConfigs> mIoOveruseConfigs GUARDED_BY(mRwMutex);
246 
247     /**
248      * Delta of system-wide written kib across all disks from the last |mPeriodicMonitorBufferSize|
249      * polls along with the polling duration.
250      */
251     std::vector<WrittenBytesSnapshot> mSystemWideWrittenBytes GUARDED_BY(mRwMutex);
252     size_t mPeriodicMonitorBufferSize GUARDED_BY(mRwMutex);
253     time_t mLastSystemWideIoMonitorTime GUARDED_BY(mRwMutex);
254 
255     // Cache of I/O usage stats from previous boot that happened today. Key is a unique ID with
256     // the format `packageName:userId`.
257     std::unordered_map<std::string, android::automotive::watchdog::internal::IoUsageStats>
258             mPrevBootIoUsageStatsById GUARDED_BY(mRwMutex);
259 
260     // Cache of per user package I/O usage. Key is a unique ID with the format `packageName:userId`.
261     std::unordered_map<std::string, UserPackageIoUsage> mUserPackageDailyIoUsageById
262             GUARDED_BY(mRwMutex);
263     double mIoOveruseWarnPercentage GUARDED_BY(mRwMutex);
264     time_t mLastUserPackageIoMonitorTime GUARDED_BY(mRwMutex);
265     std::vector<android::automotive::watchdog::internal::PackageIoOveruseStats>
266             mLatestIoOveruseStats;
267 
268     ListenersByUidMap mOveruseListenersByUid GUARDED_BY(mRwMutex);
269     android::sp<BinderDeathRecipient> mBinderDeathRecipient;
270 
271     friend class WatchdogPerfService;
272 
273     // For unit tests.
274     friend class internal::IoOveruseMonitorPeer;
275 };
276 
277 }  // namespace watchdog
278 }  // namespace automotive
279 }  // namespace android
280 
281 #endif  //  CPP_WATCHDOG_SERVER_SRC_IOOVERUSEMONITOR_H_
282