• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2021 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 #include "IoOveruseMonitor.h"
18 #include "MockAIBinderDeathRegistrationWrapper.h"
19 #include "MockIoOveruseConfigs.h"
20 #include "MockPackageInfoResolver.h"
21 #include "MockProcDiskStatsCollector.h"
22 #include "MockResourceOveruseListener.h"
23 #include "MockUidStatsCollector.h"
24 #include "MockWatchdogServiceHelper.h"
25 #include "PackageInfoTestUtils.h"
26 
27 #include <binder/IPCThreadState.h>
28 #include <utils/RefBase.h>
29 
30 #include <functional>
31 #include <tuple>
32 #include <unordered_map>
33 
34 namespace android {
35 namespace automotive {
36 namespace watchdog {
37 
38 using ::aidl::android::automotive::watchdog::IoOveruseStats;
39 using ::aidl::android::automotive::watchdog::PerStateBytes;
40 using ::aidl::android::automotive::watchdog::ResourceOveruseStats;
41 using ::aidl::android::automotive::watchdog::internal::IoOveruseAlertThreshold;
42 using ::aidl::android::automotive::watchdog::internal::PackageIdentifier;
43 using ::aidl::android::automotive::watchdog::internal::PackageInfo;
44 using ::aidl::android::automotive::watchdog::internal::PackageIoOveruseStats;
45 using ::aidl::android::automotive::watchdog::internal::ResourceOveruseConfiguration;
46 using ::aidl::android::automotive::watchdog::internal::ResourceStats;
47 using ::aidl::android::automotive::watchdog::internal::UidType;
48 using ::aidl::android::automotive::watchdog::internal::UserPackageIoUsageStats;
49 using ::android::IPCThreadState;
50 using ::android::RefBase;
51 using ::android::sp;
52 using ::android::base::Error;
53 using ::android::base::Result;
54 using ::android::base::StringAppendF;
55 using ::ndk::ScopedAStatus;
56 using ::ndk::SharedRefBase;
57 using ::testing::_;
58 using ::testing::ByMove;
59 using ::testing::DoAll;
60 using ::testing::Eq;
61 using ::testing::Return;
62 using ::testing::ReturnRef;
63 using ::testing::SaveArg;
64 using ::testing::SetArgPointee;
65 using ::testing::UnorderedElementsAreArray;
66 
67 namespace {
68 
69 constexpr size_t kTestMonitorBufferSize = 3;
70 constexpr int64_t KTestMinSyncWrittenBytes = 5'000;
71 constexpr double kTestIoOveruseWarnPercentage = 80;
72 constexpr std::chrono::seconds kTestMonitorInterval = 5s;
73 constexpr std::chrono::seconds kMaxWaitSeconds = 5s;
74 
toIoOveruseAlertThreshold(const int64_t durationInSeconds,const int64_t writtenBytesPerSecond)75 IoOveruseAlertThreshold toIoOveruseAlertThreshold(const int64_t durationInSeconds,
76                                                   const int64_t writtenBytesPerSecond) {
77     IoOveruseAlertThreshold threshold;
78     threshold.durationInSeconds = durationInSeconds;
79     threshold.writtenBytesPerSecond = writtenBytesPerSecond;
80     return threshold;
81 }
82 
83 struct PackageWrittenBytes {
84     PackageInfo packageInfo;
85     int32_t foregroundBytes;
86     int32_t backgroundBytes;
87 };
88 
constructPerStateBytes(const int64_t fgBytes,const int64_t bgBytes,const int64_t gmBytes)89 PerStateBytes constructPerStateBytes(const int64_t fgBytes, const int64_t bgBytes,
90                                      const int64_t gmBytes) {
91     PerStateBytes perStateBytes;
92     perStateBytes.foregroundBytes = fgBytes;
93     perStateBytes.backgroundBytes = bgBytes;
94     perStateBytes.garageModeBytes = gmBytes;
95     return perStateBytes;
96 }
97 
constructIoOveruseStats(const bool isKillable,const PerStateBytes & remaining,const PerStateBytes & written,const int totalOveruses,const int64_t startTime,const int64_t durationInSeconds)98 IoOveruseStats constructIoOveruseStats(const bool isKillable, const PerStateBytes& remaining,
99                                        const PerStateBytes& written, const int totalOveruses,
100                                        const int64_t startTime, const int64_t durationInSeconds) {
101     IoOveruseStats stats;
102     stats.killableOnOveruse = isKillable;
103     stats.remainingWriteBytes = remaining;
104     stats.startTime = startTime;
105     stats.durationInSeconds = durationInSeconds;
106     stats.writtenBytes = written;
107     stats.totalOveruses = totalOveruses;
108 
109     return stats;
110 }
111 
constructResourceOveruseStats(IoOveruseStats ioOveruseStats)112 ResourceOveruseStats constructResourceOveruseStats(IoOveruseStats ioOveruseStats) {
113     ResourceOveruseStats stats;
114     stats.set<ResourceOveruseStats::ioOveruseStats>(ioOveruseStats);
115     return stats;
116 }
117 
constructPackageIoOveruseStats(const int32_t uid,const bool shouldNotify,const bool isKillable,const PerStateBytes & remaining,const PerStateBytes & written,const PerStateBytes & forgiven,const int totalOveruses,const int64_t startTime,const int64_t durationInSeconds)118 PackageIoOveruseStats constructPackageIoOveruseStats(
119         const int32_t uid, const bool shouldNotify, const bool isKillable,
120         const PerStateBytes& remaining, const PerStateBytes& written, const PerStateBytes& forgiven,
121         const int totalOveruses, const int64_t startTime, const int64_t durationInSeconds) {
122     PackageIoOveruseStats stats;
123     stats.uid = uid;
124     stats.shouldNotify = shouldNotify;
125     stats.forgivenWriteBytes = forgiven;
126     stats.ioOveruseStats = constructIoOveruseStats(isKillable, remaining, written, totalOveruses,
127                                                    startTime, durationInSeconds);
128 
129     return stats;
130 }
131 
constructUserPackageIoUsageStats(userid_t userId,const std::string & packageName,const PerStateBytes & writtenBytes,const PerStateBytes & forgivenWriteBytes,int32_t totalOveruses)132 UserPackageIoUsageStats constructUserPackageIoUsageStats(userid_t userId,
133                                                          const std::string& packageName,
134                                                          const PerStateBytes& writtenBytes,
135                                                          const PerStateBytes& forgivenWriteBytes,
136                                                          int32_t totalOveruses) {
137     UserPackageIoUsageStats stats;
138     stats.userId = userId;
139     stats.packageName = packageName;
140     stats.ioUsageStats.writtenBytes = writtenBytes;
141     stats.ioUsageStats.forgivenWriteBytes = forgivenWriteBytes;
142     stats.ioUsageStats.totalOveruses = totalOveruses;
143     return stats;
144 }
145 
146 class ScopedChangeCallingUid final : public RefBase {
147 public:
ScopedChangeCallingUid(uid_t uid)148     explicit ScopedChangeCallingUid(uid_t uid) {
149         mCallingUid = IPCThreadState::self()->getCallingUid();
150         mCallingPid = IPCThreadState::self()->getCallingPid();
151         if (mCallingUid == uid) {
152             return;
153         }
154         mChangedUid = uid;
155         int64_t token = ((int64_t)mChangedUid << 32) | mCallingPid;
156         IPCThreadState::self()->restoreCallingIdentity(token);
157     }
~ScopedChangeCallingUid()158     ~ScopedChangeCallingUid() {
159         if (mCallingUid == mChangedUid) {
160             return;
161         }
162         int64_t token = ((int64_t)mCallingUid << 32) | mCallingPid;
163         IPCThreadState::self()->restoreCallingIdentity(token);
164     }
165 
166 private:
167     uid_t mCallingUid;
168     uid_t mChangedUid;
169     pid_t mCallingPid;
170 };
171 
toString(const std::vector<PackageIoOveruseStats> & ioOveruseStats)172 std::string toString(const std::vector<PackageIoOveruseStats>& ioOveruseStats) {
173     if (ioOveruseStats.empty()) {
174         return "empty";
175     }
176     std::string buffer;
177     for (const auto& stats : ioOveruseStats) {
178         StringAppendF(&buffer, "%s\n", stats.toString().c_str());
179     }
180     return buffer;
181 }
182 
183 }  // namespace
184 
185 namespace internal {
186 
187 class IoOveruseMonitorPeer final : public RefBase {
188 public:
IoOveruseMonitorPeer(const sp<IoOveruseMonitor> & ioOveruseMonitor)189     explicit IoOveruseMonitorPeer(const sp<IoOveruseMonitor>& ioOveruseMonitor) :
190           mIoOveruseMonitor(ioOveruseMonitor) {}
191 
init(const sp<AIBinderDeathRegistrationWrapperInterface> & deathRegistrationWrapper,const sp<IoOveruseConfigsInterface> & ioOveruseConfigs,const sp<PackageInfoResolverInterface> & packageInfoResolver)192     Result<void> init(const sp<AIBinderDeathRegistrationWrapperInterface>& deathRegistrationWrapper,
193                       const sp<IoOveruseConfigsInterface>& ioOveruseConfigs,
194                       const sp<PackageInfoResolverInterface>& packageInfoResolver) {
195         if (const auto result = mIoOveruseMonitor->init(); !result.ok()) {
196             return result;
197         }
198         mIoOveruseMonitor->mMinSyncWrittenBytes = KTestMinSyncWrittenBytes;
199         mIoOveruseMonitor->mPeriodicMonitorBufferSize = kTestMonitorBufferSize;
200         mIoOveruseMonitor->mIoOveruseWarnPercentage = kTestIoOveruseWarnPercentage;
201         mIoOveruseMonitor->mDeathRegistrationWrapper = deathRegistrationWrapper;
202         mIoOveruseMonitor->mIoOveruseConfigs = ioOveruseConfigs;
203         mIoOveruseMonitor->mPackageInfoResolver = packageInfoResolver;
204         return {};
205     }
206 
207 private:
208     sp<IoOveruseMonitor> mIoOveruseMonitor;
209 };
210 
211 }  // namespace internal
212 
213 class IoOveruseMonitorTest : public ::testing::Test {
214 protected:
SetUp()215     virtual void SetUp() {
216         mMockWatchdogServiceHelper = sp<MockWatchdogServiceHelper>::make();
217         mMockDeathRegistrationWrapper = sp<MockAIBinderDeathRegistrationWrapper>::make();
218         mMockIoOveruseConfigs = sp<MockIoOveruseConfigs>::make();
219         mMockPackageInfoResolver = sp<MockPackageInfoResolver>::make();
220         mMockUidStatsCollector = sp<MockUidStatsCollector>::make();
221         mIoOveruseMonitor = sp<IoOveruseMonitor>::make(mMockWatchdogServiceHelper);
222         mIoOveruseMonitorPeer = sp<internal::IoOveruseMonitorPeer>::make(mIoOveruseMonitor);
223         mIoOveruseMonitorPeer->init(mMockDeathRegistrationWrapper, mMockIoOveruseConfigs,
224                                     mMockPackageInfoResolver);
225         setUpPackagesAndConfigurations();
226     }
227 
TearDown()228     virtual void TearDown() {
229         mMockWatchdogServiceHelper.clear();
230         mMockDeathRegistrationWrapper.clear();
231         mMockIoOveruseConfigs.clear();
232         mMockPackageInfoResolver.clear();
233         mMockUidStatsCollector.clear();
234         mIoOveruseMonitor.clear();
235         mIoOveruseMonitorPeer.clear();
236     }
237 
setUpPackagesAndConfigurations()238     void setUpPackagesAndConfigurations() {
239         ON_CALL(*mMockPackageInfoResolver, getPackageInfosForUids(_))
240                 .WillByDefault(Return(kPackageInfosByUid));
241         mMockIoOveruseConfigs->injectPackageConfigs({
242                 {"system.daemon",
243                  {constructPerStateBytes(/*fgBytes=*/80'000, /*bgBytes=*/40'000,
244                                          /*gmBytes=*/100'000),
245                   /*isSafeToKill=*/false}},
246                 {"com.android.google.package",
247                  {constructPerStateBytes(/*fgBytes=*/70'000, /*bgBytes=*/30'000,
248                                          /*gmBytes=*/100'000),
249                   /*isSafeToKill=*/true}},
250                 {"com.android.kitchensink",
251                  {constructPerStateBytes(/*fgBytes=*/30'000, /*bgBytes=*/15'000,
252                                          /*gmBytes=*/10'000),
253                   /*isSafeToKill=*/true}},
254         });
255     }
256 
constructUidStats(std::unordered_map<uid_t,std::tuple<int32_t,int32_t>> writtenBytesByUid)257     std::vector<UidStats> constructUidStats(
258             std::unordered_map<uid_t, std::tuple<int32_t, int32_t>> writtenBytesByUid) {
259         std::vector<UidStats> uidStats;
260         for (const auto& [uid, writtenBytes] : writtenBytesByUid) {
261             PackageInfo packageInfo;
262             if (kPackageInfosByUid.find(uid) != kPackageInfosByUid.end()) {
263                 packageInfo = kPackageInfosByUid.at(uid);
264             } else {
265                 packageInfo.packageIdentifier.uid = uid;
266             }
267             uidStats.push_back(UidStats{.packageInfo = packageInfo,
268                                         .ioStats = {/*fgRdBytes=*/989'000,
269                                                     /*bgRdBytes=*/678'000,
270                                                     /*fgWrBytes=*/std::get<0>(writtenBytes),
271                                                     /*bgWrBytes=*/std::get<1>(writtenBytes),
272                                                     /*fgFsync=*/10'000, /*bgFsync=*/50'000}});
273         }
274         return uidStats;
275     }
276 
executeAsUid(uid_t uid,std::function<void ()> func)277     void executeAsUid(uid_t uid, std::function<void()> func) {
278         sp<ScopedChangeCallingUid> scopedChangeCallingUid = sp<ScopedChangeCallingUid>::make(uid);
279         ASSERT_NO_FATAL_FAILURE(func());
280     }
281 
expectLinkToDeath(AIBinder * aiBinder,ndk::ScopedAStatus expectedStatus)282     void expectLinkToDeath(AIBinder* aiBinder, ndk::ScopedAStatus expectedStatus) {
283         EXPECT_CALL(*mMockDeathRegistrationWrapper,
284                     linkToDeath(Eq(aiBinder), _, static_cast<void*>(aiBinder)))
285                 .WillOnce(Return(ByMove(std::move(expectedStatus))));
286     }
287 
expectUnlinkToDeath(AIBinder * aiBinder,ndk::ScopedAStatus expectedStatus)288     void expectUnlinkToDeath(AIBinder* aiBinder, ndk::ScopedAStatus expectedStatus) {
289         EXPECT_CALL(*mMockDeathRegistrationWrapper,
290                     unlinkToDeath(Eq(aiBinder), _, static_cast<void*>(aiBinder)))
291                 .WillOnce(Return(ByMove(std::move(expectedStatus))));
292     }
293 
expectNoUnlinkToDeath(AIBinder * aiBinder)294     void expectNoUnlinkToDeath(AIBinder* aiBinder) {
295         EXPECT_CALL(*mMockDeathRegistrationWrapper,
296                     unlinkToDeath(Eq(aiBinder), _, static_cast<void*>(aiBinder)))
297                 .Times(0);
298     }
299 
300     sp<MockWatchdogServiceHelper> mMockWatchdogServiceHelper;
301     sp<MockAIBinderDeathRegistrationWrapper> mMockDeathRegistrationWrapper;
302     sp<MockIoOveruseConfigs> mMockIoOveruseConfigs;
303     sp<MockPackageInfoResolver> mMockPackageInfoResolver;
304     sp<MockUidStatsCollector> mMockUidStatsCollector;
305     sp<IoOveruseMonitor> mIoOveruseMonitor;
306     sp<internal::IoOveruseMonitorPeer> mIoOveruseMonitorPeer;
307 
308     static const std::unordered_map<uid_t, PackageInfo> kPackageInfosByUid;
309 };
310 
311 const std::unordered_map<uid_t, PackageInfo> IoOveruseMonitorTest::kPackageInfosByUid =
312         {{1001000,
313           constructPackageInfo(
314                   /*packageName=*/"system.daemon",
315                   /*uid=*/1001000, UidType::NATIVE)},
316          {1112345,
317           constructPackageInfo(
318                   /*packageName=*/"com.android.google.package",
319                   /*uid=*/1112345, UidType::APPLICATION)},
320          {1113999,
321           constructPackageInfo(
322                   /*packageName=*/"com.android.google.package",
323                   /*uid=*/1113999, UidType::APPLICATION)},
324          {1212345,
325           constructPackageInfo(
326                   /*packageName=*/"com.android.google.package",
327                   /*uid=*/1212345, UidType::APPLICATION)},
328          {1245678,
329           constructPackageInfo(
330                   /*packageName=*/"com.android.kitchensink",
331                   /*uid=*/1245678, UidType::APPLICATION)},
332          {1312345,
333           constructPackageInfo(
334                   /*packageName=*/"com.android.google.package",
335                   /*uid=*/1312345, UidType::APPLICATION)}};
336 
TEST_F(IoOveruseMonitorTest,TestOnCarWatchdogServiceRegistered)337 TEST_F(IoOveruseMonitorTest, TestOnCarWatchdogServiceRegistered) {
338     EXPECT_CALL(*mMockWatchdogServiceHelper, requestTodayIoUsageStats())
339             .Times(1)
340             .WillOnce(Return(ByMove(ScopedAStatus::ok())));
341 
342     mIoOveruseMonitor->onCarWatchdogServiceRegistered();
343 }
344 
TEST_F(IoOveruseMonitorTest,TestOnPeriodicCollection)345 TEST_F(IoOveruseMonitorTest, TestOnPeriodicCollection) {
346     std::shared_ptr<MockResourceOveruseListener> mockResourceOveruseListener =
347             SharedRefBase::make<MockResourceOveruseListener>();
348     ASSERT_NO_FATAL_FAILURE(executeAsUid(1001000, [&]() {
349         ASSERT_RESULT_OK(mIoOveruseMonitor->addIoOveruseListener(mockResourceOveruseListener));
350     }));
351 
352     EXPECT_CALL(*mMockWatchdogServiceHelper, requestTodayIoUsageStats())
353             .WillOnce(Return(ByMove(ScopedAStatus::ok())));
354 
355     /*
356      * Package "system.daemon" (UID: 1001000) exceeds warn threshold percentage of 80% but no
357      * warning is issued as it is a native UID.
358      */
359     EXPECT_CALL(*mMockUidStatsCollector, deltaStats())
360             .WillOnce(Return(
361                     constructUidStats({{1001000, {/*fgWrBytes=*/70'000, /*bgWrBytes=*/20'000}},
362                                        {1112345, {/*fgWrBytes=*/35'000, /*bgWrBytes=*/15'000}},
363                                        {1212345, {/*fgWrBytes=*/70'000, /*bgWrBytes=*/20'000}}})));
364 
365     ResourceStats actualResourceStats = {};
366 
367     time_t currentTime = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
368     const auto [startTime, durationInSeconds] = calculateStartAndDuration(currentTime);
369 
370     ASSERT_RESULT_OK(mIoOveruseMonitor->onPeriodicCollection(currentTime, SystemState::NORMAL_MODE,
371                                                              mMockUidStatsCollector, nullptr,
372                                                              &actualResourceStats));
373 
374     std::vector<PackageIoOveruseStats> expectedIoOveruseStats =
375             {constructPackageIoOveruseStats(/*uid=*/1001000, /*shouldNotify=*/false,
376                                             /*isKillable=*/false, /*remaining=*/
377                                             constructPerStateBytes(10'000, 20'000, 100'000),
378                                             /*written=*/constructPerStateBytes(70'000, 20'000, 0),
379                                             /*forgiven=*/constructPerStateBytes(0, 0, 0),
380                                             /*totalOveruses=*/0, startTime, durationInSeconds),
381              constructPackageIoOveruseStats(/*uid=*/1112345, /*shouldNotify=*/false,
382                                             /*isKillable=*/true, /*remaining=*/
383                                             constructPerStateBytes(35'000, 15'000, 100'000),
384                                             /*written=*/constructPerStateBytes(35'000, 15'000, 0),
385                                             /*forgiven=*/constructPerStateBytes(0, 0, 0),
386                                             /*totalOveruses=*/0, startTime, durationInSeconds),
387              // Exceeds threshold.
388              constructPackageIoOveruseStats(/*uid=*/1212345, /*shouldNotify=*/true,
389                                             /*isKillable=*/true,
390                                             /*remaining=*/
391                                             constructPerStateBytes(0, 10'000, 100'000),
392                                             /*written=*/constructPerStateBytes(70'000, 20'000, 0),
393                                             /*forgiven=*/constructPerStateBytes(70'000, 0, 0),
394                                             /*totalOveruses=*/1, startTime, durationInSeconds)};
395 
396     EXPECT_THAT(actualResourceStats.resourceOveruseStats->packageIoOveruseStats,
397                 UnorderedElementsAreArray(expectedIoOveruseStats))
398             << "Expected: " << toString(expectedIoOveruseStats) << "\nActual: "
399             << toString(actualResourceStats.resourceOveruseStats->packageIoOveruseStats);
400 
401     // Sync IoOveruseMonitor with the today's I/O usage stats.
402     ASSERT_RESULT_OK(mIoOveruseMonitor->onTodayIoUsageStatsFetched(/*userPackageIoUsageStats=*/{}));
403 
404     ResourceOveruseStats actualOverusingNativeStats;
405     // Package "com.android.google.package" for user 11 changed uid from 1112345 to 1113999.
406     EXPECT_CALL(*mMockUidStatsCollector, deltaStats())
407             .WillOnce(Return(
408                     constructUidStats({{1001000, {/*fgWrBytes=*/30'000, /*bgWrBytes=*/0}},
409                                        {1113999, {/*fgWrBytes=*/25'000, /*bgWrBytes=*/10'000}},
410                                        {1212345, {/*fgWrBytes=*/20'000, /*bgWrBytes=*/30'000}}})));
411 
412     actualResourceStats.resourceOveruseStats->packageIoOveruseStats.clear();
413     EXPECT_CALL(*mockResourceOveruseListener, onOveruse(_))
414             .WillOnce(DoAll(SaveArg<0>(&actualOverusingNativeStats),
415                             Return(ByMove(ScopedAStatus::ok()))));
416 
417     ASSERT_RESULT_OK(mIoOveruseMonitor->onPeriodicCollection(currentTime, SystemState::NORMAL_MODE,
418                                                              mMockUidStatsCollector, nullptr,
419                                                              &actualResourceStats));
420 
421     const auto expectedOverusingNativeStats = constructResourceOveruseStats(
422             constructIoOveruseStats(/*isKillable=*/false,
423                                     /*remaining=*/constructPerStateBytes(0, 20'000, 100'000),
424                                     /*written=*/constructPerStateBytes(100'000, 20'000, 0),
425                                     /*totalOveruses=*/1, startTime, durationInSeconds));
426     EXPECT_THAT(actualOverusingNativeStats, Eq(expectedOverusingNativeStats))
427             << "Expected: " << expectedOverusingNativeStats.toString()
428             << "\nActual: " << actualOverusingNativeStats.toString();
429 
430     expectedIoOveruseStats =
431             {constructPackageIoOveruseStats(/*uid=*/1001000, /*shouldNotify=*/true,
432                                             /*isKillable=*/false, /*remaining=*/
433                                             constructPerStateBytes(0, 20'000, 100'000),
434                                             /*written=*/constructPerStateBytes(100'000, 20'000, 0),
435                                             /*forgiven=*/constructPerStateBytes(80'000, 0, 0),
436                                             /*totalOveruses=*/1, startTime, durationInSeconds),
437              // Exceeds warn threshold percentage.
438              constructPackageIoOveruseStats(/*uid=*/1113999, /*shouldNotify=*/true,
439                                             /*isKillable=*/true, /*remaining=*/
440                                             constructPerStateBytes(10'000, 5'000, 100'000),
441                                             /*written=*/constructPerStateBytes(60'000, 25'000, 0),
442                                             /*forgiven=*/constructPerStateBytes(0, 0, 0),
443                                             /*totalOveruses=*/0, startTime, durationInSeconds),
444              /*
445               * Exceeds threshold.
446               * The package was forgiven on previous overuse so the remaining bytes should only
447               * reflect the bytes written after the forgiven bytes.
448               */
449              constructPackageIoOveruseStats(/*uid=*/1212345, /*shouldNotify=*/true,
450                                             /*isKillable=*/true, /*remaining=*/
451                                             constructPerStateBytes(50'000, 0, 100'000),
452                                             /*written=*/constructPerStateBytes(90'000, 50'000, 0),
453                                             /*forgiven=*/constructPerStateBytes(70'000, 30'000, 0),
454                                             /*totalOveruses=*/2, startTime, durationInSeconds)};
455     EXPECT_THAT(actualResourceStats.resourceOveruseStats->packageIoOveruseStats,
456                 UnorderedElementsAreArray(expectedIoOveruseStats))
457             << "Expected: " << toString(expectedIoOveruseStats) << "\nActual: "
458             << toString(actualResourceStats.resourceOveruseStats->packageIoOveruseStats);
459 
460     /*
461      * Current date changed so the daily I/O usage stats should be reset and the latest I/O overuse
462      * stats should not aggregate with the previous day's stats.
463      */
464     EXPECT_CALL(*mMockUidStatsCollector, deltaStats())
465             .WillOnce(Return(
466                     constructUidStats({{1001000, {/*fgWrBytes=*/78'000, /*bgWrBytes=*/38'000}},
467                                        {1113999, {/*fgWrBytes=*/55'000, /*bgWrBytes=*/23'000}},
468                                        {1212345, {/*fgWrBytes=*/55'000, /*bgWrBytes=*/23'000}}})));
469     actualResourceStats.resourceOveruseStats->packageIoOveruseStats.clear();
470 
471     currentTime += (24 * 60 * 60);  // Change collection time to next day.
472     ASSERT_RESULT_OK(mIoOveruseMonitor->onPeriodicCollection(currentTime, SystemState::NORMAL_MODE,
473                                                              mMockUidStatsCollector, nullptr,
474                                                              &actualResourceStats));
475 
476     const auto [nextDayStartTime, nextDayDuration] = calculateStartAndDuration(currentTime);
477     expectedIoOveruseStats =
478             {constructPackageIoOveruseStats(/*uid=*/1001000, /*shouldNotify=*/false,
479                                             /*isKillable=*/false, /*remaining=*/
480                                             constructPerStateBytes(2'000, 2'000, 100'000),
481                                             /*written=*/constructPerStateBytes(78'000, 38'000, 0),
482                                             /*forgiven=*/constructPerStateBytes(0, 0, 0),
483                                             /*totalOveruses=*/0, nextDayStartTime, nextDayDuration),
484              constructPackageIoOveruseStats(/*uid=*/1113999, /*shouldNotify=*/false,
485                                             /*isKillable=*/true, /*remaining=*/
486                                             constructPerStateBytes(15'000, 7'000, 100'000),
487                                             /*written=*/constructPerStateBytes(55'000, 23'000, 0),
488                                             /*forgiven=*/constructPerStateBytes(0, 0, 0),
489                                             /*totalOveruses=*/0, nextDayStartTime, nextDayDuration),
490              constructPackageIoOveruseStats(/*uid=*/1212345, /*shouldNotify=*/false,
491                                             /*isKillable=*/true, /*remaining=*/
492                                             constructPerStateBytes(15'000, 7'000, 100'000),
493                                             /*written=*/constructPerStateBytes(55'000, 23'000, 0),
494                                             /*forgiven=*/constructPerStateBytes(0, 0, 0),
495                                             /*totalOveruses=*/0, nextDayStartTime,
496                                             nextDayDuration)};
497 
498     EXPECT_THAT(actualResourceStats.resourceOveruseStats->packageIoOveruseStats,
499                 UnorderedElementsAreArray(expectedIoOveruseStats))
500             << "Expected: " << toString(expectedIoOveruseStats) << "\nActual: "
501             << toString(actualResourceStats.resourceOveruseStats->packageIoOveruseStats);
502 }
503 
TEST_F(IoOveruseMonitorTest,TestOnPeriodicCollectionWithGarageMode)504 TEST_F(IoOveruseMonitorTest, TestOnPeriodicCollectionWithGarageMode) {
505     std::shared_ptr<MockResourceOveruseListener> mockResourceOveruseListener =
506             SharedRefBase::make<MockResourceOveruseListener>();
507     ASSERT_NO_FATAL_FAILURE(executeAsUid(1001000, [&]() {
508         ASSERT_RESULT_OK(mIoOveruseMonitor->addIoOveruseListener(mockResourceOveruseListener));
509     }));
510 
511     EXPECT_CALL(*mMockWatchdogServiceHelper, requestTodayIoUsageStats())
512             .WillOnce(Return(ByMove(ScopedAStatus::ok())));
513 
514     /*
515      * Package "system.daemon" (UID: 1001000) exceeds warn threshold percentage of 80% but no
516      * warning is issued as it is a native UID.
517      */
518     EXPECT_CALL(*mMockUidStatsCollector, deltaStats())
519             .WillOnce(Return(
520                     constructUidStats({{1001000, {/*fgWrBytes=*/70'000, /*bgWrBytes=*/60'000}},
521                                        {1112345, {/*fgWrBytes=*/35'000, /*bgWrBytes=*/15'000}},
522                                        {1212345, {/*fgWrBytes=*/90'000, /*bgWrBytes=*/20'000}}})));
523 
524     ResourceOveruseStats actualOverusingNativeStats;
525     EXPECT_CALL(*mockResourceOveruseListener, onOveruse(_))
526             .WillOnce(DoAll(SaveArg<0>(&actualOverusingNativeStats),
527                             Return(ByMove(ScopedAStatus::ok()))));
528 
529     ResourceStats actualResourceStats = {};
530 
531     time_t currentTime = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
532     const auto [startTime, durationInSeconds] = calculateStartAndDuration(currentTime);
533 
534     ASSERT_RESULT_OK(mIoOveruseMonitor->onPeriodicCollection(currentTime, SystemState::GARAGE_MODE,
535                                                              mMockUidStatsCollector, nullptr,
536                                                              &actualResourceStats));
537 
538     const auto expectedOverusingNativeStats = constructResourceOveruseStats(
539             constructIoOveruseStats(/*isKillable=*/false,
540                                     /*remaining=*/constructPerStateBytes(80'000, 40'000, 0),
541                                     /*written=*/constructPerStateBytes(0, 0, 130'000),
542                                     /*totalOveruses=*/1, startTime, durationInSeconds));
543     EXPECT_THAT(actualOverusingNativeStats, Eq(expectedOverusingNativeStats))
544             << "Expected: " << expectedOverusingNativeStats.toString()
545             << "\nActual: " << actualOverusingNativeStats.toString();
546 
547     const std::vector<PackageIoOveruseStats> expectedIoOveruseStats =
548             {constructPackageIoOveruseStats(/*uid=*/1001000, /*shouldNotify=*/true,
549                                             /*isKillable=*/false, /*remaining=*/
550                                             constructPerStateBytes(80'000, 40'000, 0),
551                                             /*written=*/constructPerStateBytes(0, 0, 130'000),
552                                             /*forgiven=*/constructPerStateBytes(0, 0, 100'000),
553                                             /*totalOveruses=*/1, startTime, durationInSeconds),
554              constructPackageIoOveruseStats(/*uid=*/1112345, /*shouldNotify=*/false,
555                                             /*isKillable=*/true, /*remaining=*/
556                                             constructPerStateBytes(70'000, 30'000, 50'000),
557                                             /*written=*/constructPerStateBytes(0, 0, 50'000),
558                                             /*forgiven=*/constructPerStateBytes(0, 0, 0),
559                                             /*totalOveruses=*/0, startTime, durationInSeconds),
560              // Exceeds threshold.
561              constructPackageIoOveruseStats(/*uid=*/1212345, /*shouldNotify=*/true,
562                                             /*isKillable=*/true,
563                                             /*remaining=*/
564                                             constructPerStateBytes(70'000, 30'000, 0),
565                                             /*written=*/constructPerStateBytes(0, 0, 110'000),
566                                             /*forgiven=*/constructPerStateBytes(0, 0, 100'000),
567                                             /*totalOveruses=*/1, startTime, durationInSeconds)};
568     EXPECT_THAT(actualResourceStats.resourceOveruseStats->packageIoOveruseStats,
569                 UnorderedElementsAreArray(expectedIoOveruseStats))
570             << "Expected: " << toString(expectedIoOveruseStats) << "\nActual: "
571             << toString(actualResourceStats.resourceOveruseStats->packageIoOveruseStats);
572 }
573 
TEST_F(IoOveruseMonitorTest,TestOnPeriodicCollectionWithZeroWriteBytes)574 TEST_F(IoOveruseMonitorTest, TestOnPeriodicCollectionWithZeroWriteBytes) {
575     EXPECT_CALL(*mMockWatchdogServiceHelper, requestTodayIoUsageStats())
576             .WillOnce(Return(ByMove(ScopedAStatus::ok())));
577 
578     EXPECT_CALL(*mMockUidStatsCollector, deltaStats())
579             .WillOnce(Return(constructUidStats({{1001000, {/*fgWrBytes=*/0, /*bgWrBytes=*/0}},
580                                                 {1112345, {/*fgWrBytes=*/0, /*bgWrBytes=*/0}},
581                                                 {1212345, {/*fgWrBytes=*/0, /*bgWrBytes=*/0}}})));
582 
583     EXPECT_CALL(*mMockPackageInfoResolver, getPackageInfosForUids(_)).Times(0);
584     EXPECT_CALL(*mMockIoOveruseConfigs, fetchThreshold(_)).Times(0);
585     EXPECT_CALL(*mMockIoOveruseConfigs, isSafeToKill(_)).Times(0);
586 
587     ResourceStats actualResourceStats = {};
588 
589     ASSERT_RESULT_OK(
590             mIoOveruseMonitor->onPeriodicCollection(std::chrono::system_clock::to_time_t(
591                                                             std::chrono::system_clock::now()),
592                                                     SystemState::NORMAL_MODE,
593                                                     mMockUidStatsCollector, nullptr,
594                                                     &actualResourceStats));
595 
596     EXPECT_TRUE(actualResourceStats.resourceOveruseStats->packageIoOveruseStats.empty())
597             << "I/O overuse stats list is not empty";
598 }
599 
TEST_F(IoOveruseMonitorTest,TestOnPeriodicCollectionWithExtremeOveruse)600 TEST_F(IoOveruseMonitorTest, TestOnPeriodicCollectionWithExtremeOveruse) {
601     EXPECT_CALL(*mMockWatchdogServiceHelper, requestTodayIoUsageStats())
602             .WillOnce(Return(ByMove(ScopedAStatus::ok())));
603 
604     EXPECT_CALL(*mMockUidStatsCollector, deltaStats())
605             .WillOnce(Return(
606                     constructUidStats({{1001000, {/*fgWrBytes=*/190'000, /*bgWrBytes=*/42'000}},
607                                        {1212345, {/*fgWrBytes=*/90'000, /*bgWrBytes=*/90'000}}})));
608 
609     time_t currentTime = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
610     const auto [startTime, durationInSeconds] = calculateStartAndDuration(currentTime);
611 
612     ResourceStats actualResourceStats = {};
613 
614     ASSERT_RESULT_OK(mIoOveruseMonitor->onPeriodicCollection(currentTime, SystemState::NORMAL_MODE,
615                                                              mMockUidStatsCollector, nullptr,
616                                                              &actualResourceStats));
617 
618     std::vector<PackageIoOveruseStats> expectedPackageIoOveruseStats =
619             {constructPackageIoOveruseStats(/*uid=*/1001000, /*shouldNotify=*/true,
620                                             /*isKillable=*/false, /*remaining=*/
621                                             constructPerStateBytes(0, 0, 100'000),
622                                             /*written=*/constructPerStateBytes(190'000, 42'000, 0),
623                                             /*forgiven=*/constructPerStateBytes(160'000, 40'000, 0),
624                                             /*totalOveruses=*/3, startTime, durationInSeconds),
625              constructPackageIoOveruseStats(/*uid=*/1212345, /*shouldNotify=*/true,
626                                             /*isKillable=*/true, /*remaining=*/
627                                             constructPerStateBytes(0, 0, 100'000),
628                                             /*written=*/constructPerStateBytes(90'000, 90'000, 0),
629                                             /*forgiven=*/constructPerStateBytes(70'000, 90'000, 0),
630                                             /*totalOveruses=*/4, startTime, durationInSeconds)};
631     EXPECT_THAT(actualResourceStats.resourceOveruseStats->packageIoOveruseStats,
632                 UnorderedElementsAreArray(expectedPackageIoOveruseStats))
633             << "Expected: " << toString(expectedPackageIoOveruseStats) << "\nActual: "
634             << toString(actualResourceStats.resourceOveruseStats->packageIoOveruseStats);
635 }
636 
TEST_F(IoOveruseMonitorTest,TestOnPeriodicCollectionWithExtremeOveruseInGarageMode)637 TEST_F(IoOveruseMonitorTest, TestOnPeriodicCollectionWithExtremeOveruseInGarageMode) {
638     EXPECT_CALL(*mMockWatchdogServiceHelper, requestTodayIoUsageStats())
639             .WillOnce(Return(ByMove(ScopedAStatus::ok())));
640 
641     EXPECT_CALL(*mMockUidStatsCollector, deltaStats())
642             .WillOnce(Return(
643                     constructUidStats({{1001000, {/*fgWrBytes=*/190'000, /*bgWrBytes=*/42'000}},
644                                        {1212345, {/*fgWrBytes=*/90'000, /*bgWrBytes=*/90'000}}})));
645 
646     time_t currentTime = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
647     const auto [startTime, durationInSeconds] = calculateStartAndDuration(currentTime);
648 
649     ResourceStats actualResourceStats = {};
650 
651     ASSERT_RESULT_OK(mIoOveruseMonitor->onPeriodicCollection(currentTime, SystemState::GARAGE_MODE,
652                                                              mMockUidStatsCollector, nullptr,
653                                                              &actualResourceStats));
654 
655     std::vector<PackageIoOveruseStats> expectedPackageIoOveruseStats =
656             {constructPackageIoOveruseStats(/*uid=*/1001000, /*shouldNotify=*/true,
657                                             /*isKillable=*/false, /*remaining=*/
658                                             constructPerStateBytes(80'000, 40'000, 0),
659                                             /*written=*/constructPerStateBytes(0, 0, 232'000),
660                                             /*forgiven=*/constructPerStateBytes(0, 0, 200'000),
661                                             /*totalOveruses=*/2, startTime, durationInSeconds),
662              constructPackageIoOveruseStats(/*uid=*/1212345, /*shouldNotify=*/true,
663                                             /*isKillable=*/true, /*remaining=*/
664                                             constructPerStateBytes(70'000, 30'000, 0),
665                                             /*written=*/constructPerStateBytes(0, 0, 180'000),
666                                             /*forgiven=*/constructPerStateBytes(0, 0, 100'000),
667                                             /*totalOveruses=*/1, startTime, durationInSeconds)};
668     EXPECT_THAT(actualResourceStats.resourceOveruseStats->packageIoOveruseStats,
669                 UnorderedElementsAreArray(expectedPackageIoOveruseStats))
670             << "Expected: " << toString(expectedPackageIoOveruseStats) << "\nActual: "
671             << toString(actualResourceStats.resourceOveruseStats->packageIoOveruseStats);
672 }
673 
TEST_F(IoOveruseMonitorTest,TestOnPeriodicCollectionWithSmallWrittenBytes)674 TEST_F(IoOveruseMonitorTest, TestOnPeriodicCollectionWithSmallWrittenBytes) {
675     EXPECT_CALL(*mMockWatchdogServiceHelper, requestTodayIoUsageStats())
676             .WillOnce(Return(ByMove(ScopedAStatus::ok())));
677 
678     /*
679      * UID 1212345 current written bytes < |KTestMinSyncWrittenBytes| so the UID's stats are not
680      * synced.
681      */
682     EXPECT_CALL(*mMockUidStatsCollector, deltaStats())
683             .WillOnce(Return(
684                     constructUidStats({{1001000, {/*fgWrBytes=*/59'200, /*bgWrBytes=*/0}},
685                                        {1112345, {/*fgWrBytes=*/0, /*bgWrBytes=*/25'200}},
686                                        {1212345, {/*fgWrBytes=*/300, /*bgWrBytes=*/600}},
687                                        {1312345, {/*fgWrBytes=*/51'200, /*bgWrBytes=*/0}}})));
688 
689     ResourceStats actualResourceStats = {};
690 
691     time_t currentTime = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
692     const auto [startTime, durationInSeconds] = calculateStartAndDuration(currentTime);
693 
694     ASSERT_RESULT_OK(mIoOveruseMonitor->onPeriodicCollection(currentTime, SystemState::NORMAL_MODE,
695                                                              mMockUidStatsCollector, nullptr,
696                                                              &actualResourceStats));
697 
698     std::vector<PackageIoOveruseStats> expectedIoOveruseStats =
699             {constructPackageIoOveruseStats(/*uid=*/1001000, /*shouldNotify=*/false,
700                                             /*isKillable=*/false, /*remaining=*/
701                                             constructPerStateBytes(20'800, 40'000, 100'000),
702                                             /*written=*/
703                                             constructPerStateBytes(59'200, 0, 0),
704                                             /*forgiven=*/constructPerStateBytes(0, 0, 0),
705                                             /*totalOveruses=*/0, startTime, durationInSeconds),
706              constructPackageIoOveruseStats(/*uid=*/1112345, /*shouldNotify=*/true,
707                                             /*isKillable=*/true, /*remaining=*/
708                                             constructPerStateBytes(70'000, 4'800, 100'000),
709                                             /*written=*/constructPerStateBytes(0, 25'200, 0),
710                                             /*forgiven=*/constructPerStateBytes(0, 0, 0),
711                                             /*totalOveruses=*/0, startTime, durationInSeconds),
712              constructPackageIoOveruseStats(/*uid=*/1312345, /*shouldNotify=*/false,
713                                             /*isKillable=*/true, /*remaining=*/
714                                             constructPerStateBytes(18'800, 30'000, 100'000),
715                                             /*written=*/constructPerStateBytes(51'200, 0, 0),
716                                             /*forgiven=*/constructPerStateBytes(0, 0, 0),
717                                             /*totalOveruses=*/0, startTime, durationInSeconds)};
718 
719     EXPECT_THAT(actualResourceStats.resourceOveruseStats->packageIoOveruseStats,
720                 UnorderedElementsAreArray(expectedIoOveruseStats))
721             << "Expected: " << toString(expectedIoOveruseStats) << "\nActual: "
722             << toString(actualResourceStats.resourceOveruseStats->packageIoOveruseStats);
723 
724     ASSERT_RESULT_OK(mIoOveruseMonitor->onTodayIoUsageStatsFetched(/*userPackageIoUsageStats=*/{}));
725 
726     /*
727      * UID 1001000 current written bytes is < |kTestMinSyncWrittenBytes| but exceeds warn threshold
728      * but not killable so the UID's stats are not synced.
729      * UID 1112345 current written bytes is < |kTestMinSyncWrittenBytes| but exceeds threshold so
730      * the UID's stats are synced.
731      * UID 1212345 current written bytes is < |kTestMinSyncWrittenBytes| but total written bytes
732      * since last synced > |kTestMinSyncWrittenBytes| so the UID's stats are synced.
733      * UID 1312345 current written bytes is < |kTestMinSyncWrittenBytes| but exceeds warn threshold
734      * and killable so the UID's stat are synced.
735      */
736     EXPECT_CALL(*mMockUidStatsCollector, deltaStats())
737             .WillOnce(Return(constructUidStats(
738                     {{1001000, {/*fgWrBytes=*/KTestMinSyncWrittenBytes - 100, /*bgWrBytes=*/0}},
739                      {1112345, {/*fgWrBytes=*/0, /*bgWrBytes=*/KTestMinSyncWrittenBytes - 100}},
740                      {1212345, {/*fgWrBytes=*/KTestMinSyncWrittenBytes - 300, /*bgWrBytes=*/0}},
741                      {1312345, {/*fgWrBytes=*/KTestMinSyncWrittenBytes - 100, /*bgWrBytes=*/0}}})));
742 
743     ASSERT_RESULT_OK(mIoOveruseMonitor->onPeriodicCollection(currentTime, SystemState::NORMAL_MODE,
744                                                              mMockUidStatsCollector, nullptr,
745                                                              &actualResourceStats));
746 
747     expectedIoOveruseStats =
748             {constructPackageIoOveruseStats(/*uid=*/1112345, /*shouldNotify=*/true,
749                                             /*isKillable=*/true, /*remaining=*/
750                                             constructPerStateBytes(70'000, 0, 100'000),
751                                             /*written=*/constructPerStateBytes(0, 30'100, 0),
752                                             /*forgiven=*/
753                                             constructPerStateBytes(0, 30'000, 0),
754                                             /*totalOveruses=*/1, startTime, durationInSeconds),
755              constructPackageIoOveruseStats(/*uid=*/1212345, /*shouldNotify=*/false,
756                                             /*isKillable=*/true, /*remaining=*/
757                                             constructPerStateBytes(65'000, 29'400, 100'000),
758                                             /*written=*/constructPerStateBytes(5'000, 600, 0),
759                                             /*forgiven=*/constructPerStateBytes(0, 0, 0),
760                                             /*totalOveruses=*/0, startTime, durationInSeconds),
761              constructPackageIoOveruseStats(/*uid=*/1312345, /*shouldNotify=*/true,
762                                             /*isKillable=*/true, /*remaining=*/
763                                             constructPerStateBytes(13'900, 30'000, 100'000),
764                                             /*written=*/constructPerStateBytes(56'100, 0, 0),
765                                             /*forgiven=*/constructPerStateBytes(0, 0, 0),
766                                             /*totalOveruses=*/0, startTime, durationInSeconds)};
767     EXPECT_THAT(actualResourceStats.resourceOveruseStats->packageIoOveruseStats,
768                 UnorderedElementsAreArray(expectedIoOveruseStats))
769             << "Expected: " << toString(expectedIoOveruseStats) << "\nActual: "
770             << toString(actualResourceStats.resourceOveruseStats->packageIoOveruseStats);
771 }
772 
TEST_F(IoOveruseMonitorTest,TestOnPeriodicCollectionWithNoPackageInfo)773 TEST_F(IoOveruseMonitorTest, TestOnPeriodicCollectionWithNoPackageInfo) {
774     EXPECT_CALL(*mMockWatchdogServiceHelper, requestTodayIoUsageStats())
775             .WillOnce(Return(ByMove(ScopedAStatus::ok())));
776 
777     EXPECT_CALL(*mMockUidStatsCollector, deltaStats())
778             .WillOnce(Return(
779                     constructUidStats({{2301000, {/*fgWrBytes=*/70'000, /*bgWrBytes=*/20'000}},
780                                        {2412345, {/*fgWrBytes=*/35'000, /*bgWrBytes=*/15'000}},
781                                        {2512345, {/*fgWrBytes=*/70'000, /*bgWrBytes=*/20'000}}})));
782 
783     EXPECT_CALL(*mMockIoOveruseConfigs, fetchThreshold(_)).Times(0);
784     EXPECT_CALL(*mMockIoOveruseConfigs, isSafeToKill(_)).Times(0);
785 
786     ResourceStats actualResourceStats = {};
787 
788     ASSERT_RESULT_OK(
789             mIoOveruseMonitor->onPeriodicCollection(std::chrono::system_clock::to_time_t(
790                                                             std::chrono::system_clock::now()),
791                                                     SystemState::NORMAL_MODE,
792                                                     mMockUidStatsCollector, nullptr,
793                                                     &actualResourceStats));
794 
795     EXPECT_TRUE(actualResourceStats.resourceOveruseStats->packageIoOveruseStats.empty())
796             << "I/O overuse stats list is not empty";
797 }
798 
799 // TODO(262605181): Create a test where the syncing is done when the carwatchdog
800 // service is registered.
801 
TEST_F(IoOveruseMonitorTest,TestOnPeriodicCollectionWithPrevBootStats)802 TEST_F(IoOveruseMonitorTest, TestOnPeriodicCollectionWithPrevBootStats) {
803     EXPECT_CALL(*mMockWatchdogServiceHelper, requestTodayIoUsageStats())
804             .WillOnce(Return(ByMove(ScopedAStatus::ok())));
805 
806     EXPECT_CALL(*mMockUidStatsCollector, deltaStats())
807             .WillOnce(Return(
808                     constructUidStats({{1001000, {/*fgWrBytes=*/70'000, /*bgWrBytes=*/20'000}},
809                                        {1112345, {/*fgWrBytes=*/35'000, /*bgWrBytes=*/15'000}}})));
810 
811     ResourceStats actualResourceStats = {};
812 
813     time_t currentTime = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
814     const auto [startTime, durationInSeconds] = calculateStartAndDuration(currentTime);
815 
816     ASSERT_RESULT_OK(mIoOveruseMonitor->onPeriodicCollection(currentTime, SystemState::NORMAL_MODE,
817                                                              mMockUidStatsCollector, nullptr,
818                                                              &actualResourceStats));
819 
820     std::vector<PackageIoOveruseStats> expectedIoOveruseStats =
821             {constructPackageIoOveruseStats(
822                      /*uid*=*/1001000, /*shouldNotify=*/false, /*isKillable=*/false,
823                      /*remaining=*/constructPerStateBytes(10'000, 20'000, 100'000),
824                      /*written=*/constructPerStateBytes(70'000, 20'000, 0),
825                      /*forgiven=*/constructPerStateBytes(0, 0, 0),
826                      /*totalOveruses=*/0, startTime, durationInSeconds),
827              constructPackageIoOveruseStats(
828                      /*uid*=*/1112345, /*shouldNotify=*/false, /*isKillable=*/true,
829                      /*remaining=*/constructPerStateBytes(35'000, 15'000, 100'000),
830                      /*written=*/constructPerStateBytes(35'000, 15'000, 0),
831                      /*forgiven=*/constructPerStateBytes(0, 0, 0),
832                      /*totalOveruses=*/0, startTime, durationInSeconds)};
833 
834     EXPECT_THAT(actualResourceStats.resourceOveruseStats->packageIoOveruseStats,
835                 UnorderedElementsAreArray(expectedIoOveruseStats))
836             << "Expected: " << toString(expectedIoOveruseStats) << "\nActual: "
837             << toString(actualResourceStats.resourceOveruseStats->packageIoOveruseStats);
838 
839     std::vector<UserPackageIoUsageStats> todayIoUsageStats =
840             {constructUserPackageIoUsageStats(
841                      /*userId=*/11, "com.android.google.package",
842                      /*writtenBytes=*/constructPerStateBytes(100'000, 85'000, 120'000),
843                      /*forgivenWriteBytes=*/constructPerStateBytes(70'000, 60'000, 100'000),
844                      /*totalOveruses=*/3),
845              constructUserPackageIoUsageStats(
846                      /*userId=*/12, "com.android.kitchensink",
847                      /*writtenBytes=*/constructPerStateBytes(50'000, 40'000, 35'000),
848                      /*forgivenWriteBytes=*/constructPerStateBytes(30'000, 30'000, 30'000),
849                      /*totalOveruses=*/6)};
850 
851     // Sync today's I/O usage stats
852     ASSERT_RESULT_OK(mIoOveruseMonitor->onTodayIoUsageStatsFetched(todayIoUsageStats));
853 
854     EXPECT_CALL(*mMockUidStatsCollector, deltaStats())
855             .WillOnce(Return(
856                     constructUidStats({{1112345, {/*fgWrBytes=*/70'000, /*bgWrBytes=*/40'000}},
857                                        {1245678, {/*fgWrBytes=*/30'000, /*bgWrBytes=*/10'000}}})));
858 
859     ASSERT_RESULT_OK(mIoOveruseMonitor->onPeriodicCollection(currentTime, SystemState::GARAGE_MODE,
860                                                              mMockUidStatsCollector, nullptr,
861                                                              &actualResourceStats));
862 
863     expectedIoOveruseStats = {constructPackageIoOveruseStats(
864                                       /*uid*=*/1112345, /*shouldNotify=*/true, /*isKillable=*/true,
865                                       /*remaining=*/constructPerStateBytes(5'000, 0, 0),
866                                       /*written=*/constructPerStateBytes(135'000, 100'000, 230'000),
867                                       /*forgiven=*/constructPerStateBytes(70'000, 90'000, 200'000),
868                                       /*totalOveruses=*/5, startTime, durationInSeconds),
869                               constructPackageIoOveruseStats(
870                                       /*uid*=*/1245678, /*shouldNotify=*/true, /*isKillable=*/true,
871                                       /*remaining=*/constructPerStateBytes(10'000, 5'000, 0),
872                                       /*written=*/constructPerStateBytes(50'000, 40'000, 75'000),
873                                       /*forgiven=*/constructPerStateBytes(30'000, 30'000, 70'000),
874                                       /*totalOveruses=*/10, startTime, durationInSeconds)};
875 
876     EXPECT_THAT(actualResourceStats.resourceOveruseStats->packageIoOveruseStats,
877                 UnorderedElementsAreArray(expectedIoOveruseStats))
878             << "Expected: " << toString(expectedIoOveruseStats) << "\nActual: "
879             << toString(actualResourceStats.resourceOveruseStats->packageIoOveruseStats);
880 }
881 
TEST_F(IoOveruseMonitorTest,TestOnPeriodicCollectionWithErrorFetchingPrevBootStats)882 TEST_F(IoOveruseMonitorTest, TestOnPeriodicCollectionWithErrorFetchingPrevBootStats) {
883     EXPECT_CALL(*mMockWatchdogServiceHelper, requestTodayIoUsageStats())
884             .WillOnce(Return(ByMove(ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_STATE,
885                                                                                 "Illegal state"))));
886 
887     EXPECT_CALL(*mMockUidStatsCollector, deltaStats())
888             .WillOnce(Return(
889                     constructUidStats({{1112345, {/*fgWrBytes=*/15'000, /*bgWrBytes=*/15'000}}})));
890 
891     time_t currentTime = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
892     const auto [startTime, durationInSeconds] = calculateStartAndDuration(currentTime);
893     ResourceStats actualResourceStats = {};
894 
895     ASSERT_RESULT_OK(mIoOveruseMonitor->onPeriodicCollection(currentTime, SystemState::NORMAL_MODE,
896                                                              mMockUidStatsCollector, nullptr,
897                                                              &actualResourceStats));
898 
899     std::vector<UserPackageIoUsageStats> todayIoUsageStats = {constructUserPackageIoUsageStats(
900             /*userId=*/11, "com.android.google.package",
901             /*writtenBytes=*/constructPerStateBytes(100'000, 85'000, 120'000),
902             /*forgivenWriteBytes=*/constructPerStateBytes(70'000, 60'000, 100'000),
903             /*totalOveruses=*/3)};
904     ASSERT_RESULT_OK(mIoOveruseMonitor->onTodayIoUsageStatsFetched(todayIoUsageStats));
905 
906     EXPECT_CALL(*mMockUidStatsCollector, deltaStats())
907             .WillOnce(Return(
908                     constructUidStats({{1112345, {/*fgWrBytes=*/20'000, /*bgWrBytes=*/40'000}}})));
909 
910     ASSERT_RESULT_OK(mIoOveruseMonitor->onPeriodicCollection(currentTime, SystemState::NORMAL_MODE,
911                                                              mMockUidStatsCollector, nullptr,
912                                                              &actualResourceStats));
913 
914     std::vector<PackageIoOveruseStats> expectedIoOveruseStats = {constructPackageIoOveruseStats(
915             /*uid*=*/1112345, /*shouldNotify=*/true, /*isKillable=*/true,
916             /*remaining=*/constructPerStateBytes(5'000, 0, 80'000),
917             /*written=*/constructPerStateBytes(135'000, 140'000, 120'000),
918             /*forgiven=*/constructPerStateBytes(70'000, 120'000, 100'000),
919             /*totalOveruses=*/5, startTime, durationInSeconds)};
920     EXPECT_THAT(actualResourceStats.resourceOveruseStats->packageIoOveruseStats,
921                 UnorderedElementsAreArray(expectedIoOveruseStats))
922             << "Expected: " << toString(expectedIoOveruseStats) << "\nActual: "
923             << toString(actualResourceStats.resourceOveruseStats->packageIoOveruseStats);
924 }
925 
TEST_F(IoOveruseMonitorTest,TestOnPeriodicMonitor)926 TEST_F(IoOveruseMonitorTest, TestOnPeriodicMonitor) {
927     IoOveruseConfigsInterface::IoOveruseAlertThresholdSet alertThresholds =
928             {toIoOveruseAlertThreshold(
929                      /*durationInSeconds=*/10, /*writtenBytesPerSecond=*/15'360),
930              toIoOveruseAlertThreshold(
931                      /*durationInSeconds=*/17, /*writtenBytesPerSecond=*/10'240),
932              toIoOveruseAlertThreshold(
933                      /*durationInSeconds=*/23, /*writtenBytesPerSecond=*/7'168)};
934     ON_CALL(*mMockIoOveruseConfigs, systemWideAlertThresholds())
935             .WillByDefault(ReturnRef(alertThresholds));
936 
937     time_t time = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
938     const auto nextCollectionTime = [&]() -> time_t {
939         time += kTestMonitorInterval.count();
940         return time;
941     };
942     bool isAlertReceived = false;
943     const auto alertHandler = [&]() { isAlertReceived = true; };
944 
945     // 1st polling is ignored
946     sp<MockProcDiskStatsCollector> mockProcDiskStatsCollector =
947             sp<MockProcDiskStatsCollector>::make();
948     EXPECT_CALL(*mockProcDiskStatsCollector, deltaSystemWideDiskStats()).Times(0);
949 
950     ASSERT_RESULT_OK(mIoOveruseMonitor->onPeriodicMonitor(nextCollectionTime(),
951                                                           mockProcDiskStatsCollector,
952                                                           alertHandler));
953     EXPECT_FALSE(isAlertReceived) << "Triggered spurious alert because first polling is ignored";
954 
955     // 2nd polling - guarded by the heuristic to handle spurious alerting on partially filled buffer
956     EXPECT_CALL(*mockProcDiskStatsCollector, deltaSystemWideDiskStats())
957             .WillOnce([]() -> DiskStats { return DiskStats{.numKibWritten = 70}; });
958 
959     ASSERT_RESULT_OK(mIoOveruseMonitor->onPeriodicMonitor(nextCollectionTime(),
960                                                           mockProcDiskStatsCollector,
961                                                           alertHandler));
962     EXPECT_FALSE(isAlertReceived) << "Triggered spurious alert when not exceeding the threshold";
963 
964     // 3rd polling exceeds first threshold
965     EXPECT_CALL(*mockProcDiskStatsCollector, deltaSystemWideDiskStats())
966             .WillOnce([]() -> DiskStats { return DiskStats{.numKibWritten = 90}; });
967 
968     ASSERT_RESULT_OK(mIoOveruseMonitor->onPeriodicMonitor(nextCollectionTime(),
969                                                           mockProcDiskStatsCollector,
970                                                           alertHandler));
971     EXPECT_TRUE(isAlertReceived) << "Failed to trigger alert when exceeding the threshold";
972 
973     isAlertReceived = false;
974 
975     // 4th polling - guarded by the heuristic to handle spurious alerting on partially filled buffer
976     EXPECT_CALL(*mockProcDiskStatsCollector, deltaSystemWideDiskStats())
977             .WillOnce([]() -> DiskStats { return DiskStats{.numKibWritten = 10}; });
978 
979     ASSERT_RESULT_OK(mIoOveruseMonitor->onPeriodicMonitor(nextCollectionTime(),
980                                                           mockProcDiskStatsCollector,
981                                                           alertHandler));
982     EXPECT_FALSE(isAlertReceived) << "Triggered spurious alert when not exceeding the threshold";
983 
984     // 5th polling exceeds second threshold
985     EXPECT_CALL(*mockProcDiskStatsCollector, deltaSystemWideDiskStats())
986             .WillOnce([]() -> DiskStats { return DiskStats{.numKibWritten = 80}; });
987 
988     ASSERT_RESULT_OK(mIoOveruseMonitor->onPeriodicMonitor(nextCollectionTime(),
989                                                           mockProcDiskStatsCollector,
990                                                           alertHandler));
991     EXPECT_TRUE(isAlertReceived) << "Failed to trigger alert when exceeding the threshold";
992 
993     isAlertReceived = false;
994 
995     // 6th polling exceeds third threshold
996     EXPECT_CALL(*mockProcDiskStatsCollector, deltaSystemWideDiskStats())
997             .WillOnce([]() -> DiskStats { return DiskStats{.numKibWritten = 10}; });
998 
999     ASSERT_RESULT_OK(mIoOveruseMonitor->onPeriodicMonitor(nextCollectionTime(),
1000                                                           mockProcDiskStatsCollector,
1001                                                           alertHandler));
1002     EXPECT_TRUE(isAlertReceived) << "Failed to trigger alert when exceeding the threshold";
1003 }
1004 
TEST_F(IoOveruseMonitorTest,TestRegisterResourceOveruseListener)1005 TEST_F(IoOveruseMonitorTest, TestRegisterResourceOveruseListener) {
1006     std::shared_ptr<MockResourceOveruseListener> mockResourceOveruseListener =
1007             SharedRefBase::make<MockResourceOveruseListener>();
1008 
1009     expectLinkToDeath(mockResourceOveruseListener->asBinder().get(),
1010                       std::move(ScopedAStatus::ok()));
1011 
1012     ASSERT_RESULT_OK(mIoOveruseMonitor->addIoOveruseListener(mockResourceOveruseListener));
1013 
1014     ASSERT_RESULT_OK(mIoOveruseMonitor->addIoOveruseListener(mockResourceOveruseListener));
1015 }
1016 
TEST_F(IoOveruseMonitorTest,TestErrorsRegisterResourceOveruseListenerOnLinkToDeathError)1017 TEST_F(IoOveruseMonitorTest, TestErrorsRegisterResourceOveruseListenerOnLinkToDeathError) {
1018     std::shared_ptr<MockResourceOveruseListener> mockResourceOveruseListener =
1019             SharedRefBase::make<MockResourceOveruseListener>();
1020 
1021     ASSERT_NO_FATAL_FAILURE(
1022             expectLinkToDeath(mockResourceOveruseListener->asBinder().get(),
1023                               std::move(ScopedAStatus::fromExceptionCode(EX_TRANSACTION_FAILED))));
1024 
1025     ASSERT_FALSE(mIoOveruseMonitor->addIoOveruseListener(mockResourceOveruseListener).ok());
1026 }
1027 
TEST_F(IoOveruseMonitorTest,TestDuplicateRemoveIoOveruseListener)1028 TEST_F(IoOveruseMonitorTest, TestDuplicateRemoveIoOveruseListener) {
1029     std::shared_ptr<MockResourceOveruseListener> mockResourceOveruseListener =
1030             SharedRefBase::make<MockResourceOveruseListener>();
1031 
1032     ASSERT_RESULT_OK(mIoOveruseMonitor->addIoOveruseListener(mockResourceOveruseListener));
1033 
1034     expectUnlinkToDeath(mockResourceOveruseListener->asBinder().get(),
1035                         std::move(ScopedAStatus::ok()));
1036 
1037     ASSERT_RESULT_OK(mIoOveruseMonitor->removeIoOveruseListener(mockResourceOveruseListener));
1038 
1039     ASSERT_FALSE(mIoOveruseMonitor->removeIoOveruseListener(mockResourceOveruseListener).ok())
1040             << "Should error on duplicate unregister";
1041 }
1042 
TEST_F(IoOveruseMonitorTest,TestRemoveIoOveruseListenerOnUnlinkToDeathError)1043 TEST_F(IoOveruseMonitorTest, TestRemoveIoOveruseListenerOnUnlinkToDeathError) {
1044     std::shared_ptr<MockResourceOveruseListener> mockResourceOveruseListener =
1045             SharedRefBase::make<MockResourceOveruseListener>();
1046 
1047     ASSERT_RESULT_OK(mIoOveruseMonitor->addIoOveruseListener(mockResourceOveruseListener));
1048 
1049     expectUnlinkToDeath(mockResourceOveruseListener->asBinder().get(),
1050                         std::move(ScopedAStatus::fromExceptionCode(EX_TRANSACTION_FAILED)));
1051 
1052     ASSERT_RESULT_OK(mIoOveruseMonitor->removeIoOveruseListener(mockResourceOveruseListener));
1053 }
1054 
TEST_F(IoOveruseMonitorTest,TestRemoveDeadIoOveruseListener)1055 TEST_F(IoOveruseMonitorTest, TestRemoveDeadIoOveruseListener) {
1056     std::shared_ptr<MockResourceOveruseListener> mockResourceOveruseListener =
1057             SharedRefBase::make<MockResourceOveruseListener>();
1058 
1059     ASSERT_RESULT_OK(mIoOveruseMonitor->addIoOveruseListener(mockResourceOveruseListener));
1060 
1061     AIBinder* binder = mockResourceOveruseListener->asBinder().get();
1062     mIoOveruseMonitor->handleBinderDeath(static_cast<void*>(binder));
1063 
1064     ASSERT_NO_FATAL_FAILURE(expectNoUnlinkToDeath(binder));
1065 
1066     ASSERT_FALSE(mIoOveruseMonitor->removeIoOveruseListener(mockResourceOveruseListener).ok())
1067             << "Should error on removing dead listener";
1068 }
1069 
TEST_F(IoOveruseMonitorTest,TestGetIoOveruseStats)1070 TEST_F(IoOveruseMonitorTest, TestGetIoOveruseStats) {
1071     EXPECT_CALL(*mMockWatchdogServiceHelper, requestTodayIoUsageStats())
1072             .WillOnce(Return(ByMove(ScopedAStatus::ok())));
1073     EXPECT_CALL(*mMockUidStatsCollector, deltaStats())
1074             .WillOnce(Return(
1075                     constructUidStats({{1001000, {/*fgWrBytes=*/90'000, /*bgWrBytes=*/20'000}}})));
1076 
1077     time_t currentTime = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
1078     const auto [startTime, durationInSeconds] = calculateStartAndDuration(currentTime);
1079     ResourceStats resourceStats = {};
1080 
1081     ASSERT_RESULT_OK(mIoOveruseMonitor->onPeriodicCollection(currentTime, SystemState::NORMAL_MODE,
1082                                                              mMockUidStatsCollector, nullptr,
1083                                                              &resourceStats));
1084 
1085     const auto expected =
1086             constructIoOveruseStats(/*isKillable=*/false,
1087                                     /*remaining=*/
1088                                     constructPerStateBytes(70'000, 20'000, 100'000),
1089                                     /*written=*/
1090                                     constructPerStateBytes(90'000, 20'000, 0),
1091                                     /*totalOveruses=*/1, startTime, durationInSeconds);
1092     IoOveruseStats actual;
1093     ASSERT_NO_FATAL_FAILURE(executeAsUid(1001000, [&]() {
1094         ASSERT_RESULT_OK(mIoOveruseMonitor->getIoOveruseStats(&actual));
1095     }));
1096     EXPECT_THAT(actual, expected) << "Expected: " << expected.toString()
1097                                   << "\nActual: " << actual.toString();
1098 }
1099 
TEST_F(IoOveruseMonitorTest,TestResetIoOveruseStats)1100 TEST_F(IoOveruseMonitorTest, TestResetIoOveruseStats) {
1101     EXPECT_CALL(*mMockWatchdogServiceHelper, requestTodayIoUsageStats())
1102             .WillOnce(Return(ByMove(ScopedAStatus::ok())));
1103     EXPECT_CALL(*mMockUidStatsCollector, deltaStats())
1104             .WillOnce(Return(
1105                     constructUidStats({{1001000, {/*fgWrBytes=*/90'000, /*bgWrBytes=*/20'000}}})));
1106 
1107     ResourceStats resourceStats = {};
1108 
1109     ASSERT_RESULT_OK(
1110             mIoOveruseMonitor->onPeriodicCollection(std::chrono::system_clock::to_time_t(
1111                                                             std::chrono::system_clock::now()),
1112                                                     SystemState::NORMAL_MODE,
1113                                                     mMockUidStatsCollector, nullptr,
1114                                                     &resourceStats));
1115 
1116     IoOveruseStats actual;
1117     ASSERT_NO_FATAL_FAILURE(executeAsUid(1001000, [&]() {
1118         ASSERT_RESULT_OK(mIoOveruseMonitor->getIoOveruseStats(&actual));
1119     }));
1120 
1121     EXPECT_NE(actual.totalOveruses, 0);
1122     EXPECT_NE(actual.writtenBytes.foregroundBytes, 0);
1123     EXPECT_NE(actual.writtenBytes.backgroundBytes, 0);
1124 
1125     std::vector<std::string> packageNames = {"system.daemon"};
1126     EXPECT_CALL(*mMockWatchdogServiceHelper, resetResourceOveruseStats(packageNames))
1127             .WillOnce(Return(ByMove(ScopedAStatus::ok())));
1128 
1129     ASSERT_RESULT_OK(mIoOveruseMonitor->resetIoOveruseStats(packageNames));
1130 
1131     ASSERT_NO_FATAL_FAILURE(executeAsUid(1001000, [&]() {
1132         ASSERT_RESULT_OK(mIoOveruseMonitor->getIoOveruseStats(&actual));
1133     }));
1134 
1135     EXPECT_EQ(actual.totalOveruses, 0);
1136     EXPECT_EQ(actual.writtenBytes.foregroundBytes, 0);
1137     EXPECT_EQ(actual.writtenBytes.backgroundBytes, 0);
1138 }
1139 
TEST_F(IoOveruseMonitorTest,TestErrorsResetIoOveruseStatsOnWatchdogServiceHelperError)1140 TEST_F(IoOveruseMonitorTest, TestErrorsResetIoOveruseStatsOnWatchdogServiceHelperError) {
1141     std::vector<std::string> packageNames = {"system.daemon"};
1142     EXPECT_CALL(*mMockWatchdogServiceHelper, resetResourceOveruseStats(packageNames))
1143             .WillOnce(Return(ByMove(ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE))));
1144 
1145     ASSERT_FALSE(mIoOveruseMonitor->resetIoOveruseStats(packageNames).ok())
1146             << "Must return error when WatchdogServiceHelper fails to reset stats";
1147 }
1148 
TEST_F(IoOveruseMonitorTest,TestErrorsGetIoOveruseStatsOnNoStats)1149 TEST_F(IoOveruseMonitorTest, TestErrorsGetIoOveruseStatsOnNoStats) {
1150     ON_CALL(*mMockPackageInfoResolver, getPackageInfosForUids(_))
1151             .WillByDefault([]() -> std::unordered_map<uid_t, PackageInfo> {
1152                 return {{1001000,
1153                          constructPackageInfo(/*packageName=*/"system.daemon", /*uid=*/1001000,
1154                                               UidType::NATIVE)}};
1155             });
1156     IoOveruseStats actual;
1157     ASSERT_NO_FATAL_FAILURE(executeAsUid(1001000, [&]() {
1158         ASSERT_FALSE(mIoOveruseMonitor->getIoOveruseStats(&actual).ok())
1159                 << "Should fail on missing I/O overuse stats";
1160     }));
1161 
1162     ASSERT_NO_FATAL_FAILURE(executeAsUid(1102001, [&]() {
1163         ASSERT_FALSE(mIoOveruseMonitor->getIoOveruseStats(&actual).ok())
1164                 << "Should fail on missing package information";
1165     }));
1166 }
1167 
TEST_F(IoOveruseMonitorTest,TestUpdateResourceOveruseConfigurations)1168 TEST_F(IoOveruseMonitorTest, TestUpdateResourceOveruseConfigurations) {
1169     EXPECT_CALL(*mMockIoOveruseConfigs, update(_)).WillOnce(Return(Result<void>{}));
1170 
1171     ASSERT_RESULT_OK(mIoOveruseMonitor->updateResourceOveruseConfigurations({}));
1172 }
1173 
TEST_F(IoOveruseMonitorTest,TestFailsUpdateResourceOveruseConfigurations)1174 TEST_F(IoOveruseMonitorTest, TestFailsUpdateResourceOveruseConfigurations) {
1175     EXPECT_CALL(*mMockIoOveruseConfigs, update(_))
1176             .WillOnce([&]([[maybe_unused]] const std::vector<ResourceOveruseConfiguration>& configs)
1177                               -> Result<void> { return Error() << "Failed to update"; });
1178 
1179     ASSERT_FALSE(mIoOveruseMonitor->updateResourceOveruseConfigurations({}).ok());
1180 }
1181 
TEST_F(IoOveruseMonitorTest,TestRemoveUser)1182 TEST_F(IoOveruseMonitorTest, TestRemoveUser) {
1183     EXPECT_CALL(*mMockUidStatsCollector, deltaStats())
1184             .WillOnce(Return(
1185                     constructUidStats({{1001000, {/*fgWrBytes=*/70'000, /*bgWrBytes=*/20'000}},
1186                                        {1112345, {/*fgWrBytes=*/35'000, /*bgWrBytes=*/15'000}}})));
1187 
1188     std::vector<UserPackageIoUsageStats> todayIoUsageStats =
1189             {constructUserPackageIoUsageStats(
1190                      /*userId=*/11, "com.android.google.package",
1191                      /*writtenBytes=*/constructPerStateBytes(100'000, 85'000, 120'000),
1192                      /*forgivenWriteBytes=*/constructPerStateBytes(70'000, 60'000, 100'000),
1193                      /*totalOveruses=*/3),
1194              constructUserPackageIoUsageStats(
1195                      /*userId=*/12, "com.android.kitchensink",
1196                      /*writtenBytes=*/constructPerStateBytes(50'000, 40'000, 35'000),
1197                      /*forgivenWriteBytes=*/constructPerStateBytes(30'000, 30'000, 30'000),
1198                      /*totalOveruses=*/6)};
1199 
1200     ASSERT_RESULT_OK(mIoOveruseMonitor->onTodayIoUsageStatsFetched(todayIoUsageStats));
1201 
1202     ResourceStats actualResourceStats = {};
1203 
1204     time_t currentTime = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
1205     const auto [startTime, durationInSeconds] = calculateStartAndDuration(currentTime);
1206 
1207     ASSERT_RESULT_OK(mIoOveruseMonitor->onPeriodicCollection(currentTime, SystemState::NORMAL_MODE,
1208                                                              mMockUidStatsCollector, nullptr,
1209                                                              &actualResourceStats));
1210 
1211     std::vector<PackageIoOveruseStats> expectedIoOveruseStats =
1212             {constructPackageIoOveruseStats(
1213                      /*uid*=*/1001000, /*shouldNotify=*/false, /*isKillable=*/false,
1214                      /*remaining=*/constructPerStateBytes(10'000, 20'000, 100'000),
1215                      /*written=*/constructPerStateBytes(70'000, 20'000, 0),
1216                      /*forgiven=*/constructPerStateBytes(0, 0, 0),
1217                      /*totalOveruses=*/0, startTime, durationInSeconds),
1218              constructPackageIoOveruseStats(
1219                      /*uid*=*/1112345, /*shouldNotify=*/true, /*isKillable=*/true,
1220                      /*remaining=*/constructPerStateBytes(5'000, 0, 80'000),
1221                      /*written=*/constructPerStateBytes(135'000, 100'000, 120'000),
1222                      /*forgiven=*/constructPerStateBytes(70'000, 90'000, 100'000),
1223                      /*totalOveruses=*/4, startTime, durationInSeconds)};
1224 
1225     EXPECT_THAT(actualResourceStats.resourceOveruseStats->packageIoOveruseStats,
1226                 UnorderedElementsAreArray(expectedIoOveruseStats))
1227             << "Expected: " << toString(expectedIoOveruseStats) << "\nActual: "
1228             << toString(actualResourceStats.resourceOveruseStats->packageIoOveruseStats);
1229 
1230     mIoOveruseMonitor->removeStatsForUser(/*userId=*/11);
1231     mIoOveruseMonitor->removeStatsForUser(/*userId=*/12);
1232 
1233     EXPECT_CALL(*mMockUidStatsCollector, deltaStats())
1234             .WillOnce(Return(
1235                     constructUidStats({{1112345, {/*fgWrBytes=*/70'000, /*bgWrBytes=*/40'000}},
1236                                        {1245678, {/*fgWrBytes=*/30'000, /*bgWrBytes=*/10'000}}})));
1237 
1238     ASSERT_RESULT_OK(mIoOveruseMonitor->onPeriodicCollection(currentTime, SystemState::GARAGE_MODE,
1239                                                              mMockUidStatsCollector, nullptr,
1240                                                              &actualResourceStats));
1241 
1242     expectedIoOveruseStats = {constructPackageIoOveruseStats(
1243                                       /*uid*=*/1112345, /*shouldNotify=*/true, /*isKillable=*/true,
1244                                       /*remaining=*/constructPerStateBytes(70'000, 30'000, 0),
1245                                       /*written=*/constructPerStateBytes(0, 0, 110'000),
1246                                       /*forgiven=*/constructPerStateBytes(0, 0, 100'000),
1247                                       /*totalOveruses=*/1, startTime, durationInSeconds),
1248                               constructPackageIoOveruseStats(
1249                                       /*uid*=*/1245678, /*shouldNotify=*/true, /*isKillable=*/true,
1250                                       /*remaining=*/constructPerStateBytes(30'000, 15'000, 0),
1251                                       /*written=*/constructPerStateBytes(0, 0, 40'000),
1252                                       /*forgiven=*/constructPerStateBytes(0, 0, 40'000),
1253                                       /*totalOveruses=*/4, startTime, durationInSeconds)};
1254     EXPECT_THAT(actualResourceStats.resourceOveruseStats->packageIoOveruseStats,
1255                 UnorderedElementsAreArray(expectedIoOveruseStats))
1256             << "Expected: " << toString(expectedIoOveruseStats) << "\nActual: "
1257             << toString(actualResourceStats.resourceOveruseStats->packageIoOveruseStats);
1258 }
1259 
1260 }  // namespace watchdog
1261 }  // namespace automotive
1262 }  // namespace android
1263