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 #pragma once
18 
19 #include "AIBinderDeathRegistrationWrapper.h"
20 #include "IoOveruseConfigs.h"
21 #include "PackageInfoResolver.h"
22 #include "ProcStatCollector.h"
23 #include "UidStatsCollector.h"
24 #include "WatchdogPerfService.h"
25 
26 #include <aidl/android/automotive/watchdog/IResourceOveruseListener.h>
27 #include <aidl/android/automotive/watchdog/PerStateBytes.h>
28 #include <aidl/android/automotive/watchdog/internal/ComponentType.h>
29 #include <aidl/android/automotive/watchdog/internal/PackageInfo.h>
30 #include <aidl/android/automotive/watchdog/internal/PackageIoOveruseStats.h>
31 #include <aidl/android/automotive/watchdog/internal/ResourceOveruseConfiguration.h>
32 #include <android-base/result.h>
33 #include <android-base/stringprintf.h>
34 #include <android/binder_auto_utils.h>
35 #include <android/util/ProtoOutputStream.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_point_millis& 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_point_millis 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_point_millis 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_point_millis time,const android::wp<UidStatsCollectorInterface> & uidStatsCollector,const android::wp<ProcStatCollectorInterface> & procStatCollector)146     android::base::Result<void> onWakeUpCollection(
147             [[maybe_unused]] time_point_millis 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_point_millis 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_point_millis 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_point_millis 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_point_millis 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     android::base::Result<void> onDumpProto(
184             const CollectionIntervals& collectionIntervals,
185             android::util::ProtoOutputStream& outProto) const override;
186 
187     bool dumpHelpText(int fd) const override;
188 
onCustomCollectionDump(int fd)189     android::base::Result<void> onCustomCollectionDump([[maybe_unused]] int fd) override {
190         // No special processing for custom collection. Thus no custom collection dump.
191         return {};
192     }
193 
194     // Below methods implement AIDL interfaces.
195     android::base::Result<void> updateResourceOveruseConfigurations(
196             const std::vector<
197                     aidl::android::automotive::watchdog::internal::ResourceOveruseConfiguration>&
198                     configs) override;
199 
200     android::base::Result<void> getResourceOveruseConfigurations(
201             std::vector<
202                     aidl::android::automotive::watchdog::internal::ResourceOveruseConfiguration>*
203                     configs) const override;
204 
205     android::base::Result<void> onTodayIoUsageStatsFetched(
206             const std::vector<
207                     aidl::android::automotive::watchdog::internal::UserPackageIoUsageStats>&
208                     userPackageIoUsageStats) override;
209 
210     android::base::Result<void> addIoOveruseListener(
211             const std::shared_ptr<aidl::android::automotive::watchdog::IResourceOveruseListener>&
212                     listener) override;
213 
214     android::base::Result<void> removeIoOveruseListener(
215             const std::shared_ptr<aidl::android::automotive::watchdog::IResourceOveruseListener>&
216                     listener) override;
217 
218     void handleBinderDeath(void* cookie) override;
219 
220     android::base::Result<void> getIoOveruseStats(
221             aidl::android::automotive::watchdog::IoOveruseStats* ioOveruseStats) const override;
222 
223     android::base::Result<void> resetIoOveruseStats(
224             const std::vector<std::string>& packageName) override;
225 
226     void removeStatsForUser(userid_t userId) override;
227 
228 protected:
229     android::base::Result<void> init();
230 
231     void terminate();
232 
233 private:
234     struct WrittenBytesSnapshot {
235         double pollDurationInSecs;
236         uint64_t bytesInKib;
237     };
238 
239     struct UserPackageIoUsage {
240         UserPackageIoUsage(
241                 const aidl::android::automotive::watchdog::internal::PackageInfo& packageInfo,
242                 const UidIoStats& uidIoStats, const bool isGarageModeActive);
243         aidl::android::automotive::watchdog::internal::PackageInfo packageInfo = {};
244         aidl::android::automotive::watchdog::PerStateBytes writtenBytes = {};
245         aidl::android::automotive::watchdog::PerStateBytes forgivenWriteBytes = {};
246         int totalOveruses = 0;
247         bool isPackageWarned = false;
248         uint64_t lastSyncedWrittenBytes = 0;
249 
250         UserPackageIoUsage& operator+=(const UserPackageIoUsage& r);
251         UserPackageIoUsage& operator+=(
252                 const aidl::android::automotive::watchdog::internal::IoUsageStats& r);
253 
254         const std::string id() const;
255         void resetStats();
256     };
257 
258 private:
isInitializedLocked()259     bool isInitializedLocked() const { return mIoOveruseConfigs != nullptr; }
260 
261     void requestTodayIoUsageStatsLocked();
262 
263     void notifyNativePackagesLocked(
264             const std::unordered_map<uid_t, aidl::android::automotive::watchdog::IoOveruseStats>&
265                     statsByUid);
266 
267     using ListenersByUidMap = std::unordered_map<
268             uid_t, std::shared_ptr<aidl::android::automotive::watchdog::IResourceOveruseListener>>;
269     using Processor = std::function<void(ListenersByUidMap&, ListenersByUidMap::const_iterator)>;
270     bool findListenerAndProcessLocked(uintptr_t binderPtrId, const Processor& processor);
271 
272     /**
273      * Writes in-memory configs to disk asynchronously if configs are not written after latest
274      * update.
275      */
276     void writeConfigsToDiskAsyncLocked();
277 
278     // Local PackageInfoResolverInterface instance. Useful to mock in tests.
279     std::shared_ptr<PackageInfoResolverInterface> mPackageInfoResolver;
280 
281     // Minimum written bytes to sync the stats with the Watchdog service.
282     double mMinSyncWrittenBytes;
283 
284     // Helper to communicate with the CarWatchdogService.
285     android::sp<WatchdogServiceHelperInterface> mWatchdogServiceHelper;
286 
287     // AIBinder death registration wrapper. Useful for mocking in tests.
288     android::sp<AIBinderDeathRegistrationWrapperInterface> mDeathRegistrationWrapper;
289 
290     // Makes sure only one collection is running at any given time.
291     mutable std::shared_mutex mRwMutex;
292 
293     // This is the thread on which the write to disk is performed. In the event the monitor begins
294     // to terminate before the write has completed, the termination procedure should wait for this
295     // thread to complete. Otherwise, this thread will run independently, which will cause
296     // the thread to access stale lock or member fields leading to crashing the process.
297     std::thread mWriteToDiskThread;
298 
299     // Tracks if mWriteToDiskThread is actively writing to disk.
300     bool mIsWriteToDiskPending GUARDED_BY(mRwMutex);
301 
302     // Indicates whether or not today's I/O usage stats, that were collected during previous boot,
303     // are read from CarService because CarService persists these stats in database across reboot.
304     bool mDidReadTodayPrevBootStats GUARDED_BY(mRwMutex);
305 
306     // Summary of configs available for all the components and system-wide overuse alert thresholds.
307     sp<IoOveruseConfigsInterface> mIoOveruseConfigs GUARDED_BY(mRwMutex);
308 
309     /**
310      * Delta of system-wide written kib across all disks from the last |mPeriodicMonitorBufferSize|
311      * polls along with the polling duration.
312      */
313     std::vector<WrittenBytesSnapshot> mSystemWideWrittenBytes GUARDED_BY(mRwMutex);
314     size_t mPeriodicMonitorBufferSize GUARDED_BY(mRwMutex);
315     time_t mLastSystemWideIoMonitorTime GUARDED_BY(mRwMutex);
316 
317     // Cache of I/O usage stats from previous boot that happened today. Key is a unique ID with
318     // the format `packageName:userId`.
319     std::unordered_map<std::string, aidl::android::automotive::watchdog::internal::IoUsageStats>
320             mPrevBootIoUsageStatsById GUARDED_BY(mRwMutex);
321 
322     // Cache of per user package I/O usage. Key is a unique ID with the format `packageName:userId`.
323     std::unordered_map<std::string, UserPackageIoUsage> mUserPackageDailyIoUsageById
324             GUARDED_BY(mRwMutex);
325     double mIoOveruseWarnPercentage GUARDED_BY(mRwMutex);
326     time_point_millis mLastUserPackageIoMonitorTime GUARDED_BY(mRwMutex);
327     std::vector<aidl::android::automotive::watchdog::internal::PackageIoOveruseStats>
328             mLatestIoOveruseStats;
329 
330     ListenersByUidMap mOveruseListenersByUid GUARDED_BY(mRwMutex);
331     ndk::ScopedAIBinder_DeathRecipient mBinderDeathRecipient;
332 
333     friend class WatchdogPerfService;
334 
335     // For unit tests.
336     friend class internal::IoOveruseMonitorPeer;
337 };
338 
339 }  // namespace watchdog
340 }  // namespace automotive
341 }  // namespace android
342