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