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