• 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_IOOVERUSEMONITOR_H_
18 #define CPP_WATCHDOG_SERVER_SRC_IOOVERUSEMONITOR_H_
19 
20 #include "IoOveruseConfigs.h"
21 #include "PackageInfoResolver.h"
22 #include "ProcStatCollector.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  * IoOveruseMonitorInterface interface defines the methods that the I/O overuse monitoring module
66  * should implement.
67  */
68 class IoOveruseMonitorInterface : virtual public DataProcessorInterface {
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 IoOveruseMonitorInterface {
102 public:
103     explicit IoOveruseMonitor(
104             const android::sp<WatchdogServiceHelperInterface>& watchdogServiceHelper);
105 
~IoOveruseMonitor()106     ~IoOveruseMonitor() { terminate(); }
107 
isInitialized()108     bool isInitialized() const override {
109         std::shared_lock readLock(mRwMutex);
110         return isInitializedLocked();
111     }
112 
113     // Below methods implement DataProcessorInterface.
name()114     std::string name() const override { return "IoOveruseMonitor"; }
115     friend std::ostream& operator<<(std::ostream& os, const IoOveruseMonitor& monitor);
116 
onSystemStartup()117     android::base::Result<void> onSystemStartup() {
118         // No tracking of boot-time and wake-up events in I/O overuse monitoring.
119         return {};
120     }
121 
onBoottimeCollection(time_t time,const android::wp<UidStatsCollectorInterface> & uidStatsCollector,const android::wp<ProcStatCollectorInterface> & procStatCollector)122     android::base::Result<void> onBoottimeCollection(
123             [[maybe_unused]] time_t time,
124             [[maybe_unused]] const android::wp<UidStatsCollectorInterface>& uidStatsCollector,
125             [[maybe_unused]] const android::wp<ProcStatCollectorInterface>& procStatCollector)
126             override {
127         // No I/O overuse monitoring during boot-time.
128         return {};
129     }
130 
onWakeUpCollection(time_t time,const android::wp<UidStatsCollectorInterface> & uidStatsCollector,const android::wp<ProcStatCollectorInterface> & procStatCollector)131     android::base::Result<void> onWakeUpCollection(
132             [[maybe_unused]] time_t time,
133             [[maybe_unused]] const android::wp<UidStatsCollectorInterface>& uidStatsCollector,
134             [[maybe_unused]] const android::wp<ProcStatCollectorInterface>& procStatCollector)
135             override {
136         // No I/O overuse monitoring during wake up.
137         return {};
138     }
139 
onUserSwitchCollection(time_t time,userid_t from,userid_t to,const android::wp<UidStatsCollectorInterface> & uidStatsCollector,const android::wp<ProcStatCollectorInterface> & procStatCollector)140     android::base::Result<void> onUserSwitchCollection(
141             [[maybe_unused]] time_t time, [[maybe_unused]] userid_t from,
142             [[maybe_unused]] userid_t to,
143             [[maybe_unused]] const android::wp<UidStatsCollectorInterface>& uidStatsCollector,
144             [[maybe_unused]] const android::wp<ProcStatCollectorInterface>& procStatCollector)
145             override {
146         // No I/O overuse monitoring during user switch.
147         return {};
148     }
149 
150     android::base::Result<void> onPeriodicCollection(
151             time_t time, SystemState systemState,
152             const android::wp<UidStatsCollectorInterface>& uidStatsCollector,
153             const android::wp<ProcStatCollectorInterface>& procStatCollector) override;
154 
155     android::base::Result<void> onCustomCollection(
156             time_t time, SystemState systemState,
157             const std::unordered_set<std::string>& filterPackages,
158             const android::wp<UidStatsCollectorInterface>& uidStatsCollector,
159             const android::wp<ProcStatCollectorInterface>& procStatCollector) override;
160 
161     android::base::Result<void> onPeriodicMonitor(
162             time_t time, const android::wp<ProcDiskStatsCollectorInterface>& procDiskStatsCollector,
163             const std::function<void()>& alertHandler) override;
164 
165     android::base::Result<void> onDump(int fd) const override;
166 
167     bool dumpHelpText(int fd) const override;
168 
onCustomCollectionDump(int fd)169     android::base::Result<void> onCustomCollectionDump([[maybe_unused]] int fd) override {
170         // No special processing for custom collection. Thus no custom collection dump.
171         return {};
172     }
173 
174     // Below methods implement AIDL interfaces.
175     android::base::Result<void> updateResourceOveruseConfigurations(
176             const std::vector<
177                     android::automotive::watchdog::internal::ResourceOveruseConfiguration>& configs)
178             override;
179 
180     android::base::Result<void> getResourceOveruseConfigurations(
181             std::vector<android::automotive::watchdog::internal::ResourceOveruseConfiguration>*
182                     configs) const override;
183 
184     android::base::Result<void> addIoOveruseListener(
185             const sp<IResourceOveruseListener>& listener) override;
186 
187     android::base::Result<void> removeIoOveruseListener(
188             const sp<IResourceOveruseListener>& listener) override;
189 
190     android::base::Result<void> getIoOveruseStats(IoOveruseStats* ioOveruseStats) const override;
191 
192     android::base::Result<void> resetIoOveruseStats(
193             const std::vector<std::string>& packageName) override;
194 
195     void removeStatsForUser(userid_t userId) override;
196 
197 protected:
198     android::base::Result<void> init();
199 
200     void terminate();
201 
202 private:
203     struct WrittenBytesSnapshot {
204         double pollDurationInSecs;
205         uint64_t bytesInKib;
206     };
207 
208     struct UserPackageIoUsage {
209         UserPackageIoUsage(const android::automotive::watchdog::internal::PackageInfo& packageInfo,
210                            const UidIoStats& uidIoStats, const bool isGarageModeActive);
211         android::automotive::watchdog::internal::PackageInfo packageInfo = {};
212         PerStateBytes writtenBytes = {};
213         PerStateBytes forgivenWriteBytes = {};
214         int totalOveruses = 0;
215         bool isPackageWarned = false;
216         uint64_t lastSyncedWrittenBytes = 0;
217 
218         UserPackageIoUsage& operator+=(const UserPackageIoUsage& r);
219         UserPackageIoUsage& operator+=(
220                 const android::automotive::watchdog::internal::IoUsageStats& r);
221 
222         const std::string id() const;
223         void resetStats();
224     };
225 
226     class BinderDeathRecipient final : public android::IBinder::DeathRecipient {
227     public:
BinderDeathRecipient(const android::sp<IoOveruseMonitor> & service)228         explicit BinderDeathRecipient(const android::sp<IoOveruseMonitor>& service) :
229               mService(service) {}
230 
binderDied(const android::wp<android::IBinder> & who)231         void binderDied(const android::wp<android::IBinder>& who) override {
232             mService->handleBinderDeath(who);
233         }
234 
235     private:
236         android::sp<IoOveruseMonitor> mService;
237     };
238 
239 private:
isInitializedLocked()240     bool isInitializedLocked() const { return mIoOveruseConfigs != nullptr; }
241 
242     void syncTodayIoUsageStatsLocked();
243 
244     void notifyNativePackagesLocked(const std::unordered_map<uid_t, IoOveruseStats>& statsByUid);
245 
246     void handleBinderDeath(const wp<IBinder>& who);
247 
248     using ListenersByUidMap = std::unordered_map<uid_t, android::sp<IResourceOveruseListener>>;
249     using Processor = std::function<void(ListenersByUidMap&, ListenersByUidMap::const_iterator)>;
250     bool findListenerAndProcessLocked(const sp<IBinder>& binder, const Processor& processor);
251 
252     /**
253      * Writes in-memory configs to disk asynchronously if configs are not written after latest
254      * update.
255      */
256     void writeConfigsToDiskAsyncLocked();
257 
258     // Local PackageInfoResolverInterface instance. Useful to mock in tests.
259     sp<PackageInfoResolverInterface> mPackageInfoResolver;
260     // Minimum written bytes to sync the stats with the Watchdog service.
261     double mMinSyncWrittenBytes;
262     android::sp<WatchdogServiceHelperInterface> mWatchdogServiceHelper;
263 
264     // Makes sure only one collection is running at any given time.
265     mutable std::shared_mutex mRwMutex;
266 
267     // Indicates whether or not today's I/O usage stats, that were collected during previous boot,
268     // are read from CarService because CarService persists these stats in database across reboot.
269     bool mDidReadTodayPrevBootStats GUARDED_BY(mRwMutex);
270 
271     // Summary of configs available for all the components and system-wide overuse alert thresholds.
272     sp<IoOveruseConfigsInterface> mIoOveruseConfigs GUARDED_BY(mRwMutex);
273 
274     /**
275      * Delta of system-wide written kib across all disks from the last |mPeriodicMonitorBufferSize|
276      * polls along with the polling duration.
277      */
278     std::vector<WrittenBytesSnapshot> mSystemWideWrittenBytes GUARDED_BY(mRwMutex);
279     size_t mPeriodicMonitorBufferSize GUARDED_BY(mRwMutex);
280     time_t mLastSystemWideIoMonitorTime GUARDED_BY(mRwMutex);
281 
282     // Cache of I/O usage stats from previous boot that happened today. Key is a unique ID with
283     // the format `packageName:userId`.
284     std::unordered_map<std::string, android::automotive::watchdog::internal::IoUsageStats>
285             mPrevBootIoUsageStatsById GUARDED_BY(mRwMutex);
286 
287     // Cache of per user package I/O usage. Key is a unique ID with the format `packageName:userId`.
288     std::unordered_map<std::string, UserPackageIoUsage> mUserPackageDailyIoUsageById
289             GUARDED_BY(mRwMutex);
290     double mIoOveruseWarnPercentage GUARDED_BY(mRwMutex);
291     time_t mLastUserPackageIoMonitorTime GUARDED_BY(mRwMutex);
292     std::vector<android::automotive::watchdog::internal::PackageIoOveruseStats>
293             mLatestIoOveruseStats;
294 
295     ListenersByUidMap mOveruseListenersByUid GUARDED_BY(mRwMutex);
296     android::sp<BinderDeathRecipient> mBinderDeathRecipient GUARDED_BY(mRwMutex);
297 
298     friend class WatchdogPerfService;
299 
300     // For unit tests.
301     friend class internal::IoOveruseMonitorPeer;
302 };
303 
304 }  // namespace watchdog
305 }  // namespace automotive
306 }  // namespace android
307 
308 #endif  //  CPP_WATCHDOG_SERVER_SRC_IOOVERUSEMONITOR_H_
309