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