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 "IoOveruseConfigs.h" 21 #include "PackageInfoResolver.h" 22 #include "ProcPidStat.h" 23 #include "ProcStat.h" 24 #include "UidIoStats.h" 25 #include "WatchdogPerfService.h" 26 27 #include <android-base/result.h> 28 #include <android-base/stringprintf.h> 29 #include <android/automotive/watchdog/BnResourceOveruseListener.h> 30 #include <android/automotive/watchdog/PerStateBytes.h> 31 #include <android/automotive/watchdog/internal/ComponentType.h> 32 #include <android/automotive/watchdog/internal/IoOveruseConfiguration.h> 33 #include <android/automotive/watchdog/internal/PackageInfo.h> 34 #include <android/automotive/watchdog/internal/PackageIoOveruseStats.h> 35 #include <android/automotive/watchdog/internal/PackageResourceOveruseAction.h> 36 #include <utils/Mutex.h> 37 38 #include <time.h> 39 40 #include <ostream> 41 #include <string> 42 #include <unordered_map> 43 #include <unordered_set> 44 #include <vector> 45 46 namespace android { 47 namespace automotive { 48 namespace watchdog { 49 50 // Number of periodically monitored stats to cache in memory. 51 constexpr int32_t kDefaultPeriodicMonitorBufferSize = 360; 52 // Dumpsys flags. 53 constexpr const char* kResetResourceOveruseStatsFlag = "--reset_resource_overuse_stats"; 54 55 // Forward declaration for testing use only. 56 namespace internal { 57 58 class IoOveruseMonitorPeer; 59 60 } // namespace internal 61 62 // Used only in tests. 63 std::tuple<int64_t, int64_t> calculateStartAndDuration(const time_t& currentTime); 64 65 /* 66 * IIoOveruseMonitor interface defines the methods that the I/O overuse monitoring module 67 * should implement. 68 */ 69 class IIoOveruseMonitor : virtual public IDataProcessorInterface { 70 public: 71 // Returns whether or not the monitor is initialized. 72 virtual bool isInitialized() = 0; 73 74 // Dumps the help text. 75 virtual bool dumpHelpText(int fd) = 0; 76 77 // Below API is from internal/ICarWatchdog.aidl. Please refer to the AIDL for description. 78 virtual android::base::Result<void> updateResourceOveruseConfigurations( 79 const std::vector< 80 android::automotive::watchdog::internal::ResourceOveruseConfiguration>& 81 configs) = 0; 82 virtual android::base::Result<void> getResourceOveruseConfigurations( 83 std::vector<android::automotive::watchdog::internal::ResourceOveruseConfiguration>* 84 configs) = 0; 85 virtual android::base::Result<void> actionTakenOnIoOveruse( 86 const std::vector< 87 android::automotive::watchdog::internal::PackageResourceOveruseAction>& 88 actions) = 0; 89 90 // Below methods support APIs from ICarWatchdog.aidl. Please refer to the AIDL for description. 91 virtual android::base::Result<void> addIoOveruseListener( 92 const sp<IResourceOveruseListener>& listener) = 0; 93 94 virtual android::base::Result<void> removeIoOveruseListener( 95 const sp<IResourceOveruseListener>& listener) = 0; 96 97 virtual android::base::Result<void> getIoOveruseStats(IoOveruseStats* ioOveruseStats) = 0; 98 99 virtual android::base::Result<void> resetIoOveruseStats( 100 const std::vector<std::string>& packageNames) = 0; 101 }; 102 103 class IoOveruseMonitor final : public IIoOveruseMonitor { 104 public: 105 explicit IoOveruseMonitor(const android::sp<IWatchdogServiceHelper>& watchdogServiceHelper); 106 ~IoOveruseMonitor()107 ~IoOveruseMonitor() { terminate(); } 108 isInitialized()109 bool isInitialized() { 110 std::shared_lock readLock(mRwMutex); 111 return isInitializedLocked(); 112 } 113 114 // Below methods implement IDataProcessorInterface. name()115 std::string name() { return "IoOveruseMonitor"; } 116 friend std::ostream& operator<<(std::ostream& os, const IoOveruseMonitor& monitor); onBoottimeCollection(time_t,const android::wp<UidIoStats> &,const android::wp<ProcStat> &,const android::wp<ProcPidStat> &)117 android::base::Result<void> onBoottimeCollection( 118 time_t /*time*/, const android::wp<UidIoStats>& /*uidIoStats*/, 119 const android::wp<ProcStat>& /*procStat*/, 120 const android::wp<ProcPidStat>& /*procPidStat*/) { 121 // No I/O overuse monitoring during boot-time. 122 return {}; 123 } 124 125 android::base::Result<void> onPeriodicCollection(time_t time, SystemState systemState, 126 const android::wp<UidIoStats>& uidIoStats, 127 const android::wp<ProcStat>& procStat, 128 const android::wp<ProcPidStat>& procPidStat); 129 130 android::base::Result<void> onCustomCollection( 131 time_t time, SystemState systemState, 132 const std::unordered_set<std::string>& filterPackages, 133 const android::wp<UidIoStats>& uidIoStats, const android::wp<ProcStat>& procStat, 134 const android::wp<ProcPidStat>& procPidStat); 135 136 android::base::Result<void> onPeriodicMonitor( 137 time_t time, const android::wp<IProcDiskStatsInterface>& procDiskStats, 138 const std::function<void()>& alertHandler); 139 140 android::base::Result<void> onDump(int fd); 141 142 bool dumpHelpText(int fd); 143 onCustomCollectionDump(int)144 android::base::Result<void> onCustomCollectionDump(int /*fd*/) { 145 // No special processing for custom collection. Thus no custom collection dump. 146 return {}; 147 } 148 149 // Below methods implement AIDL interfaces. 150 android::base::Result<void> updateResourceOveruseConfigurations( 151 const std::vector< 152 android::automotive::watchdog::internal::ResourceOveruseConfiguration>& 153 configs); 154 155 android::base::Result<void> getResourceOveruseConfigurations( 156 std::vector<android::automotive::watchdog::internal::ResourceOveruseConfiguration>* 157 configs); 158 159 android::base::Result<void> actionTakenOnIoOveruse( 160 const std::vector< 161 android::automotive::watchdog::internal::PackageResourceOveruseAction>& 162 actions); 163 164 android::base::Result<void> addIoOveruseListener(const sp<IResourceOveruseListener>& listener); 165 166 android::base::Result<void> removeIoOveruseListener( 167 const sp<IResourceOveruseListener>& listener); 168 169 android::base::Result<void> getIoOveruseStats(IoOveruseStats* ioOveruseStats); 170 171 android::base::Result<void> resetIoOveruseStats(const std::vector<std::string>& packageName); 172 173 protected: 174 android::base::Result<void> init(); 175 176 void terminate(); 177 178 private: 179 struct WrittenBytesSnapshot { 180 double pollDurationInSecs; 181 uint64_t bytesInKib; 182 }; 183 184 struct UserPackageIoUsage { 185 UserPackageIoUsage(const android::automotive::watchdog::internal::PackageInfo& packageInfo, 186 const IoUsage& IoUsage, const bool isGarageModeActive); 187 android::automotive::watchdog::internal::PackageInfo packageInfo = {}; 188 PerStateBytes writtenBytes = {}; 189 PerStateBytes forgivenWriteBytes = {}; 190 int totalOveruses = 0; 191 bool isPackageWarned = false; 192 uint64_t lastSyncedWrittenBytes = 0; 193 194 UserPackageIoUsage& operator+=(const UserPackageIoUsage& r); 195 196 const std::string id() const; 197 void resetStats(); 198 }; 199 200 class BinderDeathRecipient final : public android::IBinder::DeathRecipient { 201 public: BinderDeathRecipient(const android::sp<IoOveruseMonitor> & service)202 explicit BinderDeathRecipient(const android::sp<IoOveruseMonitor>& service) : 203 mService(service) {} 204 binderDied(const android::wp<android::IBinder> & who)205 void binderDied(const android::wp<android::IBinder>& who) override { 206 mService->handleBinderDeath(who); 207 } 208 209 private: 210 android::sp<IoOveruseMonitor> mService; 211 }; 212 213 private: isInitializedLocked()214 bool isInitializedLocked() { return mIoOveruseConfigs != nullptr; } 215 216 void notifyNativePackagesLocked(const std::unordered_map<uid_t, IoOveruseStats>& statsByUid); 217 218 void handleBinderDeath(const wp<IBinder>& who); 219 220 using ListenersByUidMap = std::unordered_map<uid_t, android::sp<IResourceOveruseListener>>; 221 using Processor = std::function<void(ListenersByUidMap&, ListenersByUidMap::const_iterator)>; 222 bool findListenerAndProcessLocked(const sp<IBinder>& binder, const Processor& processor); 223 224 /* 225 * Writes in-memory configs to disk asynchronously if configs are not written after latest 226 * update. 227 */ 228 void writeConfigsToDiskAsyncLocked(); 229 230 // Local IPackageInfoResolver instance. Useful to mock in tests. 231 sp<IPackageInfoResolver> mPackageInfoResolver; 232 // Minimum written bytes to sync the stats with the Watchdog service. 233 double mMinSyncWrittenBytes; 234 android::sp<IWatchdogServiceHelper> mWatchdogServiceHelper; 235 236 // Makes sure only one collection is running at any given time. 237 mutable std::shared_mutex mRwMutex; 238 239 // Summary of configs available for all the components and system-wide overuse alert thresholds. 240 sp<IIoOveruseConfigs> mIoOveruseConfigs GUARDED_BY(mRwMutex); 241 242 /* 243 * Delta of system-wide written kib across all disks from the last |mPeriodicMonitorBufferSize| 244 * polls along with the polling duration. 245 */ 246 std::vector<WrittenBytesSnapshot> mSystemWideWrittenBytes GUARDED_BY(mRwMutex); 247 size_t mPeriodicMonitorBufferSize GUARDED_BY(mRwMutex); 248 time_t mLastSystemWideIoMonitorTime GUARDED_BY(mRwMutex); 249 250 // Cache of per user package I/O usage. Key is a unique ID with the format `packageName:userId`. 251 std::unordered_map<std::string, UserPackageIoUsage> mUserPackageDailyIoUsageById 252 GUARDED_BY(mRwMutex); 253 double mIoOveruseWarnPercentage GUARDED_BY(mRwMutex); 254 time_t mLastUserPackageIoMonitorTime GUARDED_BY(mRwMutex); 255 std::vector<android::automotive::watchdog::internal::PackageIoOveruseStats> 256 mLatestIoOveruseStats; 257 258 ListenersByUidMap mOveruseListenersByUid GUARDED_BY(mRwMutex); 259 android::sp<BinderDeathRecipient> mBinderDeathRecipient; 260 261 friend class WatchdogPerfService; 262 263 // For unit tests. 264 friend class internal::IoOveruseMonitorPeer; 265 }; 266 267 } // namespace watchdog 268 } // namespace automotive 269 } // namespace android 270 271 #endif // CPP_WATCHDOG_SERVER_SRC_IOOVERUSEMONITOR_H_ 272