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