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         mMockIoOveruseConfigs.clear();
231         mMockPackageInfoResolver.clear();
232         mMockUidStatsCollector.clear();
233         mIoOveruseMonitor.clear();
234         mIoOveruseMonitorPeer.clear();
235         mMockDeathRegistrationWrapper.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     auto currentTime = std::chrono::time_point_cast<std::chrono::milliseconds>(
368             std::chrono::system_clock::now());
369     const auto [startTime, durationInSeconds] = calculateStartAndDuration(currentTime);
370 
371     ASSERT_RESULT_OK(mIoOveruseMonitor->onPeriodicCollection(currentTime, SystemState::NORMAL_MODE,
372                                                              mMockUidStatsCollector, nullptr,
373                                                              &actualResourceStats));
374 
375     std::vector<PackageIoOveruseStats> expectedIoOveruseStats =
376             {constructPackageIoOveruseStats(/*uid=*/1001000, /*shouldNotify=*/false,
377                                             /*isKillable=*/false, /*remaining=*/
378                                             constructPerStateBytes(10'000, 20'000, 100'000),
379                                             /*written=*/constructPerStateBytes(70'000, 20'000, 0),
380                                             /*forgiven=*/constructPerStateBytes(0, 0, 0),
381                                             /*totalOveruses=*/0, startTime, durationInSeconds),
382              constructPackageIoOveruseStats(/*uid=*/1112345, /*shouldNotify=*/false,
383                                             /*isKillable=*/true, /*remaining=*/
384                                             constructPerStateBytes(35'000, 15'000, 100'000),
385                                             /*written=*/constructPerStateBytes(35'000, 15'000, 0),
386                                             /*forgiven=*/constructPerStateBytes(0, 0, 0),
387                                             /*totalOveruses=*/0, startTime, durationInSeconds),
388              // Exceeds threshold.
389              constructPackageIoOveruseStats(/*uid=*/1212345, /*shouldNotify=*/true,
390                                             /*isKillable=*/true,
391                                             /*remaining=*/
392                                             constructPerStateBytes(0, 10'000, 100'000),
393                                             /*written=*/constructPerStateBytes(70'000, 20'000, 0),
394                                             /*forgiven=*/constructPerStateBytes(70'000, 0, 0),
395                                             /*totalOveruses=*/1, startTime, durationInSeconds)};
396 
397     EXPECT_THAT(actualResourceStats.resourceOveruseStats->packageIoOveruseStats,
398                 UnorderedElementsAreArray(expectedIoOveruseStats))
399             << "Expected: " << toString(expectedIoOveruseStats) << "\nActual: "
400             << toString(actualResourceStats.resourceOveruseStats->packageIoOveruseStats);
401 
402     // Sync IoOveruseMonitor with the today's I/O usage stats.
403     ASSERT_RESULT_OK(mIoOveruseMonitor->onTodayIoUsageStatsFetched(/*userPackageIoUsageStats=*/{}));
404 
405     ResourceOveruseStats actualOverusingNativeStats;
406     // Package "com.android.google.package" for user 11 changed uid from 1112345 to 1113999.
407     EXPECT_CALL(*mMockUidStatsCollector, deltaStats())
408             .WillOnce(Return(
409                     constructUidStats({{1001000, {/*fgWrBytes=*/30'000, /*bgWrBytes=*/0}},
410                                        {1113999, {/*fgWrBytes=*/25'000, /*bgWrBytes=*/10'000}},
411                                        {1212345, {/*fgWrBytes=*/20'000, /*bgWrBytes=*/30'000}}})));
412 
413     actualResourceStats.resourceOveruseStats->packageIoOveruseStats.clear();
414     EXPECT_CALL(*mockResourceOveruseListener, onOveruse(_))
415             .WillOnce(DoAll(SaveArg<0>(&actualOverusingNativeStats),
416                             Return(ByMove(ScopedAStatus::ok()))));
417 
418     ASSERT_RESULT_OK(mIoOveruseMonitor->onPeriodicCollection(currentTime, SystemState::NORMAL_MODE,
419                                                              mMockUidStatsCollector, nullptr,
420                                                              &actualResourceStats));
421 
422     const auto expectedOverusingNativeStats = constructResourceOveruseStats(
423             constructIoOveruseStats(/*isKillable=*/false,
424                                     /*remaining=*/constructPerStateBytes(0, 20'000, 100'000),
425                                     /*written=*/constructPerStateBytes(100'000, 20'000, 0),
426                                     /*totalOveruses=*/1, startTime, durationInSeconds));
427     EXPECT_THAT(actualOverusingNativeStats, Eq(expectedOverusingNativeStats))
428             << "Expected: " << expectedOverusingNativeStats.toString()
429             << "\nActual: " << actualOverusingNativeStats.toString();
430 
431     expectedIoOveruseStats =
432             {constructPackageIoOveruseStats(/*uid=*/1001000, /*shouldNotify=*/true,
433                                             /*isKillable=*/false, /*remaining=*/
434                                             constructPerStateBytes(0, 20'000, 100'000),
435                                             /*written=*/constructPerStateBytes(100'000, 20'000, 0),
436                                             /*forgiven=*/constructPerStateBytes(80'000, 0, 0),
437                                             /*totalOveruses=*/1, startTime, durationInSeconds),
438              // Exceeds warn threshold percentage.
439              constructPackageIoOveruseStats(/*uid=*/1113999, /*shouldNotify=*/true,
440                                             /*isKillable=*/true, /*remaining=*/
441                                             constructPerStateBytes(10'000, 5'000, 100'000),
442                                             /*written=*/constructPerStateBytes(60'000, 25'000, 0),
443                                             /*forgiven=*/constructPerStateBytes(0, 0, 0),
444                                             /*totalOveruses=*/0, startTime, durationInSeconds),
445              /*
446               * Exceeds threshold.
447               * The package was forgiven on previous overuse so the remaining bytes should only
448               * reflect the bytes written after the forgiven bytes.
449               */
450              constructPackageIoOveruseStats(/*uid=*/1212345, /*shouldNotify=*/true,
451                                             /*isKillable=*/true, /*remaining=*/
452                                             constructPerStateBytes(50'000, 0, 100'000),
453                                             /*written=*/constructPerStateBytes(90'000, 50'000, 0),
454                                             /*forgiven=*/constructPerStateBytes(70'000, 30'000, 0),
455                                             /*totalOveruses=*/2, startTime, durationInSeconds)};
456     EXPECT_THAT(actualResourceStats.resourceOveruseStats->packageIoOveruseStats,
457                 UnorderedElementsAreArray(expectedIoOveruseStats))
458             << "Expected: " << toString(expectedIoOveruseStats) << "\nActual: "
459             << toString(actualResourceStats.resourceOveruseStats->packageIoOveruseStats);
460 
461     /*
462      * Current date changed so the daily I/O usage stats should be reset and the latest I/O overuse
463      * stats should not aggregate with the previous day's stats.
464      */
465     EXPECT_CALL(*mMockUidStatsCollector, deltaStats())
466             .WillOnce(Return(
467                     constructUidStats({{1001000, {/*fgWrBytes=*/78'000, /*bgWrBytes=*/38'000}},
468                                        {1113999, {/*fgWrBytes=*/55'000, /*bgWrBytes=*/23'000}},
469                                        {1212345, {/*fgWrBytes=*/55'000, /*bgWrBytes=*/23'000}}})));
470     actualResourceStats.resourceOveruseStats->packageIoOveruseStats.clear();
471 
472     currentTime += std::chrono::hours(24);  // Change collection time to next day.
473     ASSERT_RESULT_OK(mIoOveruseMonitor->onPeriodicCollection(currentTime, SystemState::NORMAL_MODE,
474                                                              mMockUidStatsCollector, nullptr,
475                                                              &actualResourceStats));
476 
477     const auto [nextDayStartTime, nextDayDuration] = calculateStartAndDuration(currentTime);
478     expectedIoOveruseStats =
479             {constructPackageIoOveruseStats(/*uid=*/1001000, /*shouldNotify=*/false,
480                                             /*isKillable=*/false, /*remaining=*/
481                                             constructPerStateBytes(2'000, 2'000, 100'000),
482                                             /*written=*/constructPerStateBytes(78'000, 38'000, 0),
483                                             /*forgiven=*/constructPerStateBytes(0, 0, 0),
484                                             /*totalOveruses=*/0, nextDayStartTime, nextDayDuration),
485              constructPackageIoOveruseStats(/*uid=*/1113999, /*shouldNotify=*/false,
486                                             /*isKillable=*/true, /*remaining=*/
487                                             constructPerStateBytes(15'000, 7'000, 100'000),
488                                             /*written=*/constructPerStateBytes(55'000, 23'000, 0),
489                                             /*forgiven=*/constructPerStateBytes(0, 0, 0),
490                                             /*totalOveruses=*/0, nextDayStartTime, nextDayDuration),
491              constructPackageIoOveruseStats(/*uid=*/1212345, /*shouldNotify=*/false,
492                                             /*isKillable=*/true, /*remaining=*/
493                                             constructPerStateBytes(15'000, 7'000, 100'000),
494                                             /*written=*/constructPerStateBytes(55'000, 23'000, 0),
495                                             /*forgiven=*/constructPerStateBytes(0, 0, 0),
496                                             /*totalOveruses=*/0, nextDayStartTime,
497                                             nextDayDuration)};
498 
499     EXPECT_THAT(actualResourceStats.resourceOveruseStats->packageIoOveruseStats,
500                 UnorderedElementsAreArray(expectedIoOveruseStats))
501             << "Expected: " << toString(expectedIoOveruseStats) << "\nActual: "
502             << toString(actualResourceStats.resourceOveruseStats->packageIoOveruseStats);
503 }
504 
TEST_F(IoOveruseMonitorTest,TestOnPeriodicCollectionWithGarageMode)505 TEST_F(IoOveruseMonitorTest, TestOnPeriodicCollectionWithGarageMode) {
506     std::shared_ptr<MockResourceOveruseListener> mockResourceOveruseListener =
507             SharedRefBase::make<MockResourceOveruseListener>();
508     ASSERT_NO_FATAL_FAILURE(executeAsUid(1001000, [&]() {
509         ASSERT_RESULT_OK(mIoOveruseMonitor->addIoOveruseListener(mockResourceOveruseListener));
510     }));
511 
512     EXPECT_CALL(*mMockWatchdogServiceHelper, requestTodayIoUsageStats())
513             .WillOnce(Return(ByMove(ScopedAStatus::ok())));
514 
515     /*
516      * Package "system.daemon" (UID: 1001000) exceeds warn threshold percentage of 80% but no
517      * warning is issued as it is a native UID.
518      */
519     EXPECT_CALL(*mMockUidStatsCollector, deltaStats())
520             .WillOnce(Return(
521                     constructUidStats({{1001000, {/*fgWrBytes=*/70'000, /*bgWrBytes=*/60'000}},
522                                        {1112345, {/*fgWrBytes=*/35'000, /*bgWrBytes=*/15'000}},
523                                        {1212345, {/*fgWrBytes=*/90'000, /*bgWrBytes=*/20'000}}})));
524 
525     ResourceOveruseStats actualOverusingNativeStats;
526     EXPECT_CALL(*mockResourceOveruseListener, onOveruse(_))
527             .WillOnce(DoAll(SaveArg<0>(&actualOverusingNativeStats),
528                             Return(ByMove(ScopedAStatus::ok()))));
529 
530     ResourceStats actualResourceStats = {};
531 
532     auto currentTime = std::chrono::time_point_cast<std::chrono::milliseconds>(
533             std::chrono::system_clock::now());
534     const auto [startTime, durationInSeconds] = calculateStartAndDuration(currentTime);
535 
536     ASSERT_RESULT_OK(mIoOveruseMonitor->onPeriodicCollection(currentTime, SystemState::GARAGE_MODE,
537                                                              mMockUidStatsCollector, nullptr,
538                                                              &actualResourceStats));
539 
540     const auto expectedOverusingNativeStats = constructResourceOveruseStats(
541             constructIoOveruseStats(/*isKillable=*/false,
542                                     /*remaining=*/constructPerStateBytes(80'000, 40'000, 0),
543                                     /*written=*/constructPerStateBytes(0, 0, 130'000),
544                                     /*totalOveruses=*/1, startTime, durationInSeconds));
545     EXPECT_THAT(actualOverusingNativeStats, Eq(expectedOverusingNativeStats))
546             << "Expected: " << expectedOverusingNativeStats.toString()
547             << "\nActual: " << actualOverusingNativeStats.toString();
548 
549     const std::vector<PackageIoOveruseStats> expectedIoOveruseStats =
550             {constructPackageIoOveruseStats(/*uid=*/1001000, /*shouldNotify=*/true,
551                                             /*isKillable=*/false, /*remaining=*/
552                                             constructPerStateBytes(80'000, 40'000, 0),
553                                             /*written=*/constructPerStateBytes(0, 0, 130'000),
554                                             /*forgiven=*/constructPerStateBytes(0, 0, 100'000),
555                                             /*totalOveruses=*/1, startTime, durationInSeconds),
556              constructPackageIoOveruseStats(/*uid=*/1112345, /*shouldNotify=*/false,
557                                             /*isKillable=*/true, /*remaining=*/
558                                             constructPerStateBytes(70'000, 30'000, 50'000),
559                                             /*written=*/constructPerStateBytes(0, 0, 50'000),
560                                             /*forgiven=*/constructPerStateBytes(0, 0, 0),
561                                             /*totalOveruses=*/0, startTime, durationInSeconds),
562              // Exceeds threshold.
563              constructPackageIoOveruseStats(/*uid=*/1212345, /*shouldNotify=*/true,
564                                             /*isKillable=*/true,
565                                             /*remaining=*/
566                                             constructPerStateBytes(70'000, 30'000, 0),
567                                             /*written=*/constructPerStateBytes(0, 0, 110'000),
568                                             /*forgiven=*/constructPerStateBytes(0, 0, 100'000),
569                                             /*totalOveruses=*/1, startTime, durationInSeconds)};
570     EXPECT_THAT(actualResourceStats.resourceOveruseStats->packageIoOveruseStats,
571                 UnorderedElementsAreArray(expectedIoOveruseStats))
572             << "Expected: " << toString(expectedIoOveruseStats) << "\nActual: "
573             << toString(actualResourceStats.resourceOveruseStats->packageIoOveruseStats);
574 }
575 
TEST_F(IoOveruseMonitorTest,TestOnPeriodicCollectionWithZeroWriteBytes)576 TEST_F(IoOveruseMonitorTest, TestOnPeriodicCollectionWithZeroWriteBytes) {
577     EXPECT_CALL(*mMockWatchdogServiceHelper, requestTodayIoUsageStats())
578             .WillOnce(Return(ByMove(ScopedAStatus::ok())));
579 
580     EXPECT_CALL(*mMockUidStatsCollector, deltaStats())
581             .WillOnce(Return(constructUidStats({{1001000, {/*fgWrBytes=*/0, /*bgWrBytes=*/0}},
582                                                 {1112345, {/*fgWrBytes=*/0, /*bgWrBytes=*/0}},
583                                                 {1212345, {/*fgWrBytes=*/0, /*bgWrBytes=*/0}}})));
584 
585     EXPECT_CALL(*mMockPackageInfoResolver, getPackageInfosForUids(_)).Times(0);
586     EXPECT_CALL(*mMockIoOveruseConfigs, fetchThreshold(_)).Times(0);
587     EXPECT_CALL(*mMockIoOveruseConfigs, isSafeToKill(_)).Times(0);
588 
589     ResourceStats actualResourceStats = {};
590 
591     ASSERT_RESULT_OK(
592             mIoOveruseMonitor
593                     ->onPeriodicCollection(std::chrono::time_point_cast<std::chrono::milliseconds>(
594                                                    std::chrono::system_clock::now()),
595                                            SystemState::NORMAL_MODE, mMockUidStatsCollector,
596                                            nullptr, &actualResourceStats));
597 
598     EXPECT_TRUE(actualResourceStats.resourceOveruseStats->packageIoOveruseStats.empty())
599             << "I/O overuse stats list is not empty";
600 }
601 
TEST_F(IoOveruseMonitorTest,TestOnPeriodicCollectionWithExtremeOveruse)602 TEST_F(IoOveruseMonitorTest, TestOnPeriodicCollectionWithExtremeOveruse) {
603     EXPECT_CALL(*mMockWatchdogServiceHelper, requestTodayIoUsageStats())
604             .WillOnce(Return(ByMove(ScopedAStatus::ok())));
605 
606     EXPECT_CALL(*mMockUidStatsCollector, deltaStats())
607             .WillOnce(Return(
608                     constructUidStats({{1001000, {/*fgWrBytes=*/190'000, /*bgWrBytes=*/42'000}},
609                                        {1212345, {/*fgWrBytes=*/90'000, /*bgWrBytes=*/90'000}}})));
610 
611     auto currentTime = std::chrono::time_point_cast<std::chrono::milliseconds>(
612             std::chrono::system_clock::now());
613     const auto [startTime, durationInSeconds] = calculateStartAndDuration(currentTime);
614 
615     ResourceStats actualResourceStats = {};
616 
617     ASSERT_RESULT_OK(mIoOveruseMonitor->onPeriodicCollection(currentTime, SystemState::NORMAL_MODE,
618                                                              mMockUidStatsCollector, nullptr,
619                                                              &actualResourceStats));
620 
621     std::vector<PackageIoOveruseStats> expectedPackageIoOveruseStats =
622             {constructPackageIoOveruseStats(/*uid=*/1001000, /*shouldNotify=*/true,
623                                             /*isKillable=*/false, /*remaining=*/
624                                             constructPerStateBytes(0, 0, 100'000),
625                                             /*written=*/constructPerStateBytes(190'000, 42'000, 0),
626                                             /*forgiven=*/constructPerStateBytes(160'000, 40'000, 0),
627                                             /*totalOveruses=*/3, startTime, durationInSeconds),
628              constructPackageIoOveruseStats(/*uid=*/1212345, /*shouldNotify=*/true,
629                                             /*isKillable=*/true, /*remaining=*/
630                                             constructPerStateBytes(0, 0, 100'000),
631                                             /*written=*/constructPerStateBytes(90'000, 90'000, 0),
632                                             /*forgiven=*/constructPerStateBytes(70'000, 90'000, 0),
633                                             /*totalOveruses=*/4, startTime, durationInSeconds)};
634     EXPECT_THAT(actualResourceStats.resourceOveruseStats->packageIoOveruseStats,
635                 UnorderedElementsAreArray(expectedPackageIoOveruseStats))
636             << "Expected: " << toString(expectedPackageIoOveruseStats) << "\nActual: "
637             << toString(actualResourceStats.resourceOveruseStats->packageIoOveruseStats);
638 }
639 
TEST_F(IoOveruseMonitorTest,TestOnPeriodicCollectionWithExtremeOveruseInGarageMode)640 TEST_F(IoOveruseMonitorTest, TestOnPeriodicCollectionWithExtremeOveruseInGarageMode) {
641     EXPECT_CALL(*mMockWatchdogServiceHelper, requestTodayIoUsageStats())
642             .WillOnce(Return(ByMove(ScopedAStatus::ok())));
643 
644     EXPECT_CALL(*mMockUidStatsCollector, deltaStats())
645             .WillOnce(Return(
646                     constructUidStats({{1001000, {/*fgWrBytes=*/190'000, /*bgWrBytes=*/42'000}},
647                                        {1212345, {/*fgWrBytes=*/90'000, /*bgWrBytes=*/90'000}}})));
648 
649     auto currentTime = std::chrono::time_point_cast<std::chrono::milliseconds>(
650             std::chrono::system_clock::now());
651     const auto [startTime, durationInSeconds] = calculateStartAndDuration(currentTime);
652 
653     ResourceStats actualResourceStats = {};
654 
655     ASSERT_RESULT_OK(mIoOveruseMonitor->onPeriodicCollection(currentTime, SystemState::GARAGE_MODE,
656                                                              mMockUidStatsCollector, nullptr,
657                                                              &actualResourceStats));
658 
659     std::vector<PackageIoOveruseStats> expectedPackageIoOveruseStats =
660             {constructPackageIoOveruseStats(/*uid=*/1001000, /*shouldNotify=*/true,
661                                             /*isKillable=*/false, /*remaining=*/
662                                             constructPerStateBytes(80'000, 40'000, 0),
663                                             /*written=*/constructPerStateBytes(0, 0, 232'000),
664                                             /*forgiven=*/constructPerStateBytes(0, 0, 200'000),
665                                             /*totalOveruses=*/2, startTime, durationInSeconds),
666              constructPackageIoOveruseStats(/*uid=*/1212345, /*shouldNotify=*/true,
667                                             /*isKillable=*/true, /*remaining=*/
668                                             constructPerStateBytes(70'000, 30'000, 0),
669                                             /*written=*/constructPerStateBytes(0, 0, 180'000),
670                                             /*forgiven=*/constructPerStateBytes(0, 0, 100'000),
671                                             /*totalOveruses=*/1, startTime, durationInSeconds)};
672     EXPECT_THAT(actualResourceStats.resourceOveruseStats->packageIoOveruseStats,
673                 UnorderedElementsAreArray(expectedPackageIoOveruseStats))
674             << "Expected: " << toString(expectedPackageIoOveruseStats) << "\nActual: "
675             << toString(actualResourceStats.resourceOveruseStats->packageIoOveruseStats);
676 }
677 
TEST_F(IoOveruseMonitorTest,TestOnPeriodicCollectionWithSmallWrittenBytes)678 TEST_F(IoOveruseMonitorTest, TestOnPeriodicCollectionWithSmallWrittenBytes) {
679     EXPECT_CALL(*mMockWatchdogServiceHelper, requestTodayIoUsageStats())
680             .WillOnce(Return(ByMove(ScopedAStatus::ok())));
681 
682     /*
683      * UID 1212345 current written bytes < |KTestMinSyncWrittenBytes| so the UID's stats are not
684      * synced.
685      */
686     EXPECT_CALL(*mMockUidStatsCollector, deltaStats())
687             .WillOnce(Return(
688                     constructUidStats({{1001000, {/*fgWrBytes=*/59'200, /*bgWrBytes=*/0}},
689                                        {1112345, {/*fgWrBytes=*/0, /*bgWrBytes=*/25'200}},
690                                        {1212345, {/*fgWrBytes=*/300, /*bgWrBytes=*/600}},
691                                        {1312345, {/*fgWrBytes=*/51'200, /*bgWrBytes=*/0}}})));
692 
693     ResourceStats actualResourceStats = {};
694 
695     auto currentTime = std::chrono::time_point_cast<std::chrono::milliseconds>(
696             std::chrono::system_clock::now());
697     const auto [startTime, durationInSeconds] = calculateStartAndDuration(currentTime);
698 
699     ASSERT_RESULT_OK(mIoOveruseMonitor->onPeriodicCollection(currentTime, SystemState::NORMAL_MODE,
700                                                              mMockUidStatsCollector, nullptr,
701                                                              &actualResourceStats));
702 
703     std::vector<PackageIoOveruseStats> expectedIoOveruseStats =
704             {constructPackageIoOveruseStats(/*uid=*/1001000, /*shouldNotify=*/false,
705                                             /*isKillable=*/false, /*remaining=*/
706                                             constructPerStateBytes(20'800, 40'000, 100'000),
707                                             /*written=*/
708                                             constructPerStateBytes(59'200, 0, 0),
709                                             /*forgiven=*/constructPerStateBytes(0, 0, 0),
710                                             /*totalOveruses=*/0, startTime, durationInSeconds),
711              constructPackageIoOveruseStats(/*uid=*/1112345, /*shouldNotify=*/true,
712                                             /*isKillable=*/true, /*remaining=*/
713                                             constructPerStateBytes(70'000, 4'800, 100'000),
714                                             /*written=*/constructPerStateBytes(0, 25'200, 0),
715                                             /*forgiven=*/constructPerStateBytes(0, 0, 0),
716                                             /*totalOveruses=*/0, startTime, durationInSeconds),
717              constructPackageIoOveruseStats(/*uid=*/1312345, /*shouldNotify=*/false,
718                                             /*isKillable=*/true, /*remaining=*/
719                                             constructPerStateBytes(18'800, 30'000, 100'000),
720                                             /*written=*/constructPerStateBytes(51'200, 0, 0),
721                                             /*forgiven=*/constructPerStateBytes(0, 0, 0),
722                                             /*totalOveruses=*/0, startTime, durationInSeconds)};
723 
724     EXPECT_THAT(actualResourceStats.resourceOveruseStats->packageIoOveruseStats,
725                 UnorderedElementsAreArray(expectedIoOveruseStats))
726             << "Expected: " << toString(expectedIoOveruseStats) << "\nActual: "
727             << toString(actualResourceStats.resourceOveruseStats->packageIoOveruseStats);
728 
729     ASSERT_RESULT_OK(mIoOveruseMonitor->onTodayIoUsageStatsFetched(/*userPackageIoUsageStats=*/{}));
730 
731     /*
732      * UID 1001000 current written bytes is < |kTestMinSyncWrittenBytes| but exceeds warn threshold
733      * but not killable so the UID's stats are not synced.
734      * UID 1112345 current written bytes is < |kTestMinSyncWrittenBytes| but exceeds threshold so
735      * the UID's stats are synced.
736      * UID 1212345 current written bytes is < |kTestMinSyncWrittenBytes| but total written bytes
737      * since last synced > |kTestMinSyncWrittenBytes| so the UID's stats are synced.
738      * UID 1312345 current written bytes is < |kTestMinSyncWrittenBytes| but exceeds warn threshold
739      * and killable so the UID's stat are synced.
740      */
741     EXPECT_CALL(*mMockUidStatsCollector, deltaStats())
742             .WillOnce(Return(constructUidStats(
743                     {{1001000, {/*fgWrBytes=*/KTestMinSyncWrittenBytes - 100, /*bgWrBytes=*/0}},
744                      {1112345, {/*fgWrBytes=*/0, /*bgWrBytes=*/KTestMinSyncWrittenBytes - 100}},
745                      {1212345, {/*fgWrBytes=*/KTestMinSyncWrittenBytes - 300, /*bgWrBytes=*/0}},
746                      {1312345, {/*fgWrBytes=*/KTestMinSyncWrittenBytes - 100, /*bgWrBytes=*/0}}})));
747 
748     ASSERT_RESULT_OK(mIoOveruseMonitor->onPeriodicCollection(currentTime, SystemState::NORMAL_MODE,
749                                                              mMockUidStatsCollector, nullptr,
750                                                              &actualResourceStats));
751 
752     expectedIoOveruseStats =
753             {constructPackageIoOveruseStats(/*uid=*/1112345, /*shouldNotify=*/true,
754                                             /*isKillable=*/true, /*remaining=*/
755                                             constructPerStateBytes(70'000, 0, 100'000),
756                                             /*written=*/constructPerStateBytes(0, 30'100, 0),
757                                             /*forgiven=*/
758                                             constructPerStateBytes(0, 30'000, 0),
759                                             /*totalOveruses=*/1, startTime, durationInSeconds),
760              constructPackageIoOveruseStats(/*uid=*/1212345, /*shouldNotify=*/false,
761                                             /*isKillable=*/true, /*remaining=*/
762                                             constructPerStateBytes(65'000, 29'400, 100'000),
763                                             /*written=*/constructPerStateBytes(5'000, 600, 0),
764                                             /*forgiven=*/constructPerStateBytes(0, 0, 0),
765                                             /*totalOveruses=*/0, startTime, durationInSeconds),
766              constructPackageIoOveruseStats(/*uid=*/1312345, /*shouldNotify=*/true,
767                                             /*isKillable=*/true, /*remaining=*/
768                                             constructPerStateBytes(13'900, 30'000, 100'000),
769                                             /*written=*/constructPerStateBytes(56'100, 0, 0),
770                                             /*forgiven=*/constructPerStateBytes(0, 0, 0),
771                                             /*totalOveruses=*/0, startTime, durationInSeconds)};
772     EXPECT_THAT(actualResourceStats.resourceOveruseStats->packageIoOveruseStats,
773                 UnorderedElementsAreArray(expectedIoOveruseStats))
774             << "Expected: " << toString(expectedIoOveruseStats) << "\nActual: "
775             << toString(actualResourceStats.resourceOveruseStats->packageIoOveruseStats);
776 }
777 
TEST_F(IoOveruseMonitorTest,TestOnPeriodicCollectionWithNoPackageInfo)778 TEST_F(IoOveruseMonitorTest, TestOnPeriodicCollectionWithNoPackageInfo) {
779     EXPECT_CALL(*mMockWatchdogServiceHelper, requestTodayIoUsageStats())
780             .WillOnce(Return(ByMove(ScopedAStatus::ok())));
781 
782     EXPECT_CALL(*mMockUidStatsCollector, deltaStats())
783             .WillOnce(Return(
784                     constructUidStats({{2301000, {/*fgWrBytes=*/70'000, /*bgWrBytes=*/20'000}},
785                                        {2412345, {/*fgWrBytes=*/35'000, /*bgWrBytes=*/15'000}},
786                                        {2512345, {/*fgWrBytes=*/70'000, /*bgWrBytes=*/20'000}}})));
787 
788     EXPECT_CALL(*mMockIoOveruseConfigs, fetchThreshold(_)).Times(0);
789     EXPECT_CALL(*mMockIoOveruseConfigs, isSafeToKill(_)).Times(0);
790 
791     ResourceStats actualResourceStats = {};
792 
793     ASSERT_RESULT_OK(
794             mIoOveruseMonitor
795                     ->onPeriodicCollection(std::chrono::time_point_cast<std::chrono::milliseconds>(
796                                                    std::chrono::system_clock::now()),
797                                            SystemState::NORMAL_MODE, mMockUidStatsCollector,
798                                            nullptr, &actualResourceStats));
799 
800     EXPECT_TRUE(actualResourceStats.resourceOveruseStats->packageIoOveruseStats.empty())
801             << "I/O overuse stats list is not empty";
802 }
803 
804 // TODO(262605181): Create a test where the syncing is done when the carwatchdog
805 // service is registered.
806 
TEST_F(IoOveruseMonitorTest,TestOnPeriodicCollectionWithPrevBootStats)807 TEST_F(IoOveruseMonitorTest, TestOnPeriodicCollectionWithPrevBootStats) {
808     EXPECT_CALL(*mMockWatchdogServiceHelper, requestTodayIoUsageStats())
809             .WillOnce(Return(ByMove(ScopedAStatus::ok())));
810 
811     EXPECT_CALL(*mMockUidStatsCollector, deltaStats())
812             .WillOnce(Return(
813                     constructUidStats({{1001000, {/*fgWrBytes=*/70'000, /*bgWrBytes=*/20'000}},
814                                        {1112345, {/*fgWrBytes=*/35'000, /*bgWrBytes=*/15'000}}})));
815 
816     ResourceStats actualResourceStats = {};
817 
818     auto currentTime = std::chrono::time_point_cast<std::chrono::milliseconds>(
819             std::chrono::system_clock::now());
820     const auto [startTime, durationInSeconds] = calculateStartAndDuration(currentTime);
821 
822     ASSERT_RESULT_OK(mIoOveruseMonitor->onPeriodicCollection(currentTime, SystemState::NORMAL_MODE,
823                                                              mMockUidStatsCollector, nullptr,
824                                                              &actualResourceStats));
825 
826     std::vector<PackageIoOveruseStats> expectedIoOveruseStats =
827             {constructPackageIoOveruseStats(
828                      /*uid*=*/1001000, /*shouldNotify=*/false, /*isKillable=*/false,
829                      /*remaining=*/constructPerStateBytes(10'000, 20'000, 100'000),
830                      /*written=*/constructPerStateBytes(70'000, 20'000, 0),
831                      /*forgiven=*/constructPerStateBytes(0, 0, 0),
832                      /*totalOveruses=*/0, startTime, durationInSeconds),
833              constructPackageIoOveruseStats(
834                      /*uid*=*/1112345, /*shouldNotify=*/false, /*isKillable=*/true,
835                      /*remaining=*/constructPerStateBytes(35'000, 15'000, 100'000),
836                      /*written=*/constructPerStateBytes(35'000, 15'000, 0),
837                      /*forgiven=*/constructPerStateBytes(0, 0, 0),
838                      /*totalOveruses=*/0, startTime, durationInSeconds)};
839 
840     EXPECT_THAT(actualResourceStats.resourceOveruseStats->packageIoOveruseStats,
841                 UnorderedElementsAreArray(expectedIoOveruseStats))
842             << "Expected: " << toString(expectedIoOveruseStats) << "\nActual: "
843             << toString(actualResourceStats.resourceOveruseStats->packageIoOveruseStats);
844 
845     std::vector<UserPackageIoUsageStats> todayIoUsageStats =
846             {constructUserPackageIoUsageStats(
847                      /*userId=*/11, "com.android.google.package",
848                      /*writtenBytes=*/constructPerStateBytes(100'000, 85'000, 120'000),
849                      /*forgivenWriteBytes=*/constructPerStateBytes(70'000, 60'000, 100'000),
850                      /*totalOveruses=*/3),
851              constructUserPackageIoUsageStats(
852                      /*userId=*/12, "com.android.kitchensink",
853                      /*writtenBytes=*/constructPerStateBytes(50'000, 40'000, 35'000),
854                      /*forgivenWriteBytes=*/constructPerStateBytes(30'000, 30'000, 30'000),
855                      /*totalOveruses=*/6)};
856 
857     // Sync today's I/O usage stats
858     ASSERT_RESULT_OK(mIoOveruseMonitor->onTodayIoUsageStatsFetched(todayIoUsageStats));
859 
860     EXPECT_CALL(*mMockUidStatsCollector, deltaStats())
861             .WillOnce(Return(
862                     constructUidStats({{1112345, {/*fgWrBytes=*/70'000, /*bgWrBytes=*/40'000}},
863                                        {1245678, {/*fgWrBytes=*/30'000, /*bgWrBytes=*/10'000}}})));
864 
865     ASSERT_RESULT_OK(mIoOveruseMonitor->onPeriodicCollection(currentTime, SystemState::GARAGE_MODE,
866                                                              mMockUidStatsCollector, nullptr,
867                                                              &actualResourceStats));
868 
869     expectedIoOveruseStats = {constructPackageIoOveruseStats(
870                                       /*uid*=*/1112345, /*shouldNotify=*/true, /*isKillable=*/true,
871                                       /*remaining=*/constructPerStateBytes(5'000, 0, 0),
872                                       /*written=*/constructPerStateBytes(135'000, 100'000, 230'000),
873                                       /*forgiven=*/constructPerStateBytes(70'000, 90'000, 200'000),
874                                       /*totalOveruses=*/5, startTime, durationInSeconds),
875                               constructPackageIoOveruseStats(
876                                       /*uid*=*/1245678, /*shouldNotify=*/true, /*isKillable=*/true,
877                                       /*remaining=*/constructPerStateBytes(10'000, 5'000, 0),
878                                       /*written=*/constructPerStateBytes(50'000, 40'000, 75'000),
879                                       /*forgiven=*/constructPerStateBytes(30'000, 30'000, 70'000),
880                                       /*totalOveruses=*/10, startTime, durationInSeconds)};
881 
882     EXPECT_THAT(actualResourceStats.resourceOveruseStats->packageIoOveruseStats,
883                 UnorderedElementsAreArray(expectedIoOveruseStats))
884             << "Expected: " << toString(expectedIoOveruseStats) << "\nActual: "
885             << toString(actualResourceStats.resourceOveruseStats->packageIoOveruseStats);
886 }
887 
TEST_F(IoOveruseMonitorTest,TestOnPeriodicCollectionWithErrorFetchingPrevBootStats)888 TEST_F(IoOveruseMonitorTest, TestOnPeriodicCollectionWithErrorFetchingPrevBootStats) {
889     EXPECT_CALL(*mMockWatchdogServiceHelper, requestTodayIoUsageStats())
890             .WillOnce(Return(ByMove(ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_STATE,
891                                                                                 "Illegal state"))));
892 
893     EXPECT_CALL(*mMockUidStatsCollector, deltaStats())
894             .WillOnce(Return(
895                     constructUidStats({{1112345, {/*fgWrBytes=*/15'000, /*bgWrBytes=*/15'000}}})));
896 
897     auto currentTime = std::chrono::time_point_cast<std::chrono::milliseconds>(
898             std::chrono::system_clock::now());
899     const auto [startTime, durationInSeconds] = calculateStartAndDuration(currentTime);
900     ResourceStats actualResourceStats = {};
901 
902     ASSERT_RESULT_OK(mIoOveruseMonitor->onPeriodicCollection(currentTime, SystemState::NORMAL_MODE,
903                                                              mMockUidStatsCollector, nullptr,
904                                                              &actualResourceStats));
905 
906     std::vector<UserPackageIoUsageStats> todayIoUsageStats = {constructUserPackageIoUsageStats(
907             /*userId=*/11, "com.android.google.package",
908             /*writtenBytes=*/constructPerStateBytes(100'000, 85'000, 120'000),
909             /*forgivenWriteBytes=*/constructPerStateBytes(70'000, 60'000, 100'000),
910             /*totalOveruses=*/3)};
911     ASSERT_RESULT_OK(mIoOveruseMonitor->onTodayIoUsageStatsFetched(todayIoUsageStats));
912 
913     EXPECT_CALL(*mMockUidStatsCollector, deltaStats())
914             .WillOnce(Return(
915                     constructUidStats({{1112345, {/*fgWrBytes=*/20'000, /*bgWrBytes=*/40'000}}})));
916 
917     ASSERT_RESULT_OK(mIoOveruseMonitor->onPeriodicCollection(currentTime, SystemState::NORMAL_MODE,
918                                                              mMockUidStatsCollector, nullptr,
919                                                              &actualResourceStats));
920 
921     std::vector<PackageIoOveruseStats> expectedIoOveruseStats = {constructPackageIoOveruseStats(
922             /*uid*=*/1112345, /*shouldNotify=*/true, /*isKillable=*/true,
923             /*remaining=*/constructPerStateBytes(5'000, 0, 80'000),
924             /*written=*/constructPerStateBytes(135'000, 140'000, 120'000),
925             /*forgiven=*/constructPerStateBytes(70'000, 120'000, 100'000),
926             /*totalOveruses=*/5, startTime, durationInSeconds)};
927     EXPECT_THAT(actualResourceStats.resourceOveruseStats->packageIoOveruseStats,
928                 UnorderedElementsAreArray(expectedIoOveruseStats))
929             << "Expected: " << toString(expectedIoOveruseStats) << "\nActual: "
930             << toString(actualResourceStats.resourceOveruseStats->packageIoOveruseStats);
931 }
932 
TEST_F(IoOveruseMonitorTest,TestOnPeriodicMonitor)933 TEST_F(IoOveruseMonitorTest, TestOnPeriodicMonitor) {
934     IoOveruseConfigsInterface::IoOveruseAlertThresholdSet alertThresholds =
935             {toIoOveruseAlertThreshold(
936                      /*durationInSeconds=*/10, /*writtenBytesPerSecond=*/15'360),
937              toIoOveruseAlertThreshold(
938                      /*durationInSeconds=*/17, /*writtenBytesPerSecond=*/10'240),
939              toIoOveruseAlertThreshold(
940                      /*durationInSeconds=*/23, /*writtenBytesPerSecond=*/7'168)};
941     ON_CALL(*mMockIoOveruseConfigs, systemWideAlertThresholds())
942             .WillByDefault(ReturnRef(alertThresholds));
943 
944     time_t time = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
945     const auto nextCollectionTime = [&]() -> time_t {
946         time += kTestMonitorInterval.count();
947         return time;
948     };
949     bool isAlertReceived = false;
950     const auto alertHandler = [&]() { isAlertReceived = true; };
951 
952     // 1st polling is ignored
953     sp<MockProcDiskStatsCollector> mockProcDiskStatsCollector =
954             sp<MockProcDiskStatsCollector>::make();
955     EXPECT_CALL(*mockProcDiskStatsCollector, deltaSystemWideDiskStats()).Times(0);
956 
957     ASSERT_RESULT_OK(mIoOveruseMonitor->onPeriodicMonitor(nextCollectionTime(),
958                                                           mockProcDiskStatsCollector,
959                                                           alertHandler));
960     EXPECT_FALSE(isAlertReceived) << "Triggered spurious alert because first polling is ignored";
961 
962     // 2nd polling - guarded by the heuristic to handle spurious alerting on partially filled buffer
963     EXPECT_CALL(*mockProcDiskStatsCollector, deltaSystemWideDiskStats())
964             .WillOnce([]() -> DiskStats { return DiskStats{.numKibWritten = 70}; });
965 
966     ASSERT_RESULT_OK(mIoOveruseMonitor->onPeriodicMonitor(nextCollectionTime(),
967                                                           mockProcDiskStatsCollector,
968                                                           alertHandler));
969     EXPECT_FALSE(isAlertReceived) << "Triggered spurious alert when not exceeding the threshold";
970 
971     // 3rd polling exceeds first threshold
972     EXPECT_CALL(*mockProcDiskStatsCollector, deltaSystemWideDiskStats())
973             .WillOnce([]() -> DiskStats { return DiskStats{.numKibWritten = 90}; });
974 
975     ASSERT_RESULT_OK(mIoOveruseMonitor->onPeriodicMonitor(nextCollectionTime(),
976                                                           mockProcDiskStatsCollector,
977                                                           alertHandler));
978     EXPECT_TRUE(isAlertReceived) << "Failed to trigger alert when exceeding the threshold";
979 
980     isAlertReceived = false;
981 
982     // 4th polling - guarded by the heuristic to handle spurious alerting on partially filled buffer
983     EXPECT_CALL(*mockProcDiskStatsCollector, deltaSystemWideDiskStats())
984             .WillOnce([]() -> DiskStats { return DiskStats{.numKibWritten = 10}; });
985 
986     ASSERT_RESULT_OK(mIoOveruseMonitor->onPeriodicMonitor(nextCollectionTime(),
987                                                           mockProcDiskStatsCollector,
988                                                           alertHandler));
989     EXPECT_FALSE(isAlertReceived) << "Triggered spurious alert when not exceeding the threshold";
990 
991     // 5th polling exceeds second threshold
992     EXPECT_CALL(*mockProcDiskStatsCollector, deltaSystemWideDiskStats())
993             .WillOnce([]() -> DiskStats { return DiskStats{.numKibWritten = 80}; });
994 
995     ASSERT_RESULT_OK(mIoOveruseMonitor->onPeriodicMonitor(nextCollectionTime(),
996                                                           mockProcDiskStatsCollector,
997                                                           alertHandler));
998     EXPECT_TRUE(isAlertReceived) << "Failed to trigger alert when exceeding the threshold";
999 
1000     isAlertReceived = false;
1001 
1002     // 6th polling exceeds third threshold
1003     EXPECT_CALL(*mockProcDiskStatsCollector, deltaSystemWideDiskStats())
1004             .WillOnce([]() -> DiskStats { return DiskStats{.numKibWritten = 10}; });
1005 
1006     ASSERT_RESULT_OK(mIoOveruseMonitor->onPeriodicMonitor(nextCollectionTime(),
1007                                                           mockProcDiskStatsCollector,
1008                                                           alertHandler));
1009     EXPECT_TRUE(isAlertReceived) << "Failed to trigger alert when exceeding the threshold";
1010 }
1011 
TEST_F(IoOveruseMonitorTest,TestRegisterResourceOveruseListener)1012 TEST_F(IoOveruseMonitorTest, TestRegisterResourceOveruseListener) {
1013     std::shared_ptr<MockResourceOveruseListener> mockResourceOveruseListener =
1014             SharedRefBase::make<MockResourceOveruseListener>();
1015 
1016     expectLinkToDeath(mockResourceOveruseListener->asBinder().get(),
1017                       std::move(ScopedAStatus::ok()));
1018 
1019     ASSERT_RESULT_OK(mIoOveruseMonitor->addIoOveruseListener(mockResourceOveruseListener));
1020 
1021     ASSERT_RESULT_OK(mIoOveruseMonitor->addIoOveruseListener(mockResourceOveruseListener));
1022 }
1023 
TEST_F(IoOveruseMonitorTest,TestErrorsRegisterResourceOveruseListenerOnLinkToDeathError)1024 TEST_F(IoOveruseMonitorTest, TestErrorsRegisterResourceOveruseListenerOnLinkToDeathError) {
1025     std::shared_ptr<MockResourceOveruseListener> mockResourceOveruseListener =
1026             SharedRefBase::make<MockResourceOveruseListener>();
1027 
1028     ASSERT_NO_FATAL_FAILURE(
1029             expectLinkToDeath(mockResourceOveruseListener->asBinder().get(),
1030                               std::move(ScopedAStatus::fromExceptionCode(EX_TRANSACTION_FAILED))));
1031 
1032     ASSERT_FALSE(mIoOveruseMonitor->addIoOveruseListener(mockResourceOveruseListener).ok());
1033 }
1034 
TEST_F(IoOveruseMonitorTest,TestDuplicateRemoveIoOveruseListener)1035 TEST_F(IoOveruseMonitorTest, TestDuplicateRemoveIoOveruseListener) {
1036     std::shared_ptr<MockResourceOveruseListener> mockResourceOveruseListener =
1037             SharedRefBase::make<MockResourceOveruseListener>();
1038 
1039     ASSERT_RESULT_OK(mIoOveruseMonitor->addIoOveruseListener(mockResourceOveruseListener));
1040 
1041     expectUnlinkToDeath(mockResourceOveruseListener->asBinder().get(),
1042                         std::move(ScopedAStatus::ok()));
1043 
1044     ASSERT_RESULT_OK(mIoOveruseMonitor->removeIoOveruseListener(mockResourceOveruseListener));
1045 
1046     ASSERT_FALSE(mIoOveruseMonitor->removeIoOveruseListener(mockResourceOveruseListener).ok())
1047             << "Should error on duplicate unregister";
1048 }
1049 
TEST_F(IoOveruseMonitorTest,TestRemoveIoOveruseListenerOnUnlinkToDeathError)1050 TEST_F(IoOveruseMonitorTest, TestRemoveIoOveruseListenerOnUnlinkToDeathError) {
1051     std::shared_ptr<MockResourceOveruseListener> mockResourceOveruseListener =
1052             SharedRefBase::make<MockResourceOveruseListener>();
1053 
1054     ASSERT_RESULT_OK(mIoOveruseMonitor->addIoOveruseListener(mockResourceOveruseListener));
1055 
1056     expectUnlinkToDeath(mockResourceOveruseListener->asBinder().get(),
1057                         std::move(ScopedAStatus::fromExceptionCode(EX_TRANSACTION_FAILED)));
1058 
1059     ASSERT_RESULT_OK(mIoOveruseMonitor->removeIoOveruseListener(mockResourceOveruseListener));
1060 }
1061 
TEST_F(IoOveruseMonitorTest,TestRemoveDeadIoOveruseListener)1062 TEST_F(IoOveruseMonitorTest, TestRemoveDeadIoOveruseListener) {
1063     std::shared_ptr<MockResourceOveruseListener> mockResourceOveruseListener =
1064             SharedRefBase::make<MockResourceOveruseListener>();
1065 
1066     ASSERT_RESULT_OK(mIoOveruseMonitor->addIoOveruseListener(mockResourceOveruseListener));
1067 
1068     AIBinder* binder = mockResourceOveruseListener->asBinder().get();
1069     mIoOveruseMonitor->handleBinderDeath(static_cast<void*>(binder));
1070 
1071     ASSERT_NO_FATAL_FAILURE(expectNoUnlinkToDeath(binder));
1072 
1073     ASSERT_FALSE(mIoOveruseMonitor->removeIoOveruseListener(mockResourceOveruseListener).ok())
1074             << "Should error on removing dead listener";
1075 }
1076 
TEST_F(IoOveruseMonitorTest,TestGetIoOveruseStats)1077 TEST_F(IoOveruseMonitorTest, TestGetIoOveruseStats) {
1078     EXPECT_CALL(*mMockWatchdogServiceHelper, requestTodayIoUsageStats())
1079             .WillOnce(Return(ByMove(ScopedAStatus::ok())));
1080     EXPECT_CALL(*mMockUidStatsCollector, deltaStats())
1081             .WillOnce(Return(
1082                     constructUidStats({{1001000, {/*fgWrBytes=*/90'000, /*bgWrBytes=*/20'000}}})));
1083 
1084     auto currentTime = std::chrono::time_point_cast<std::chrono::milliseconds>(
1085             std::chrono::system_clock::now());
1086     const auto [startTime, durationInSeconds] = calculateStartAndDuration(currentTime);
1087     ResourceStats resourceStats = {};
1088 
1089     ASSERT_RESULT_OK(mIoOveruseMonitor->onPeriodicCollection(currentTime, SystemState::NORMAL_MODE,
1090                                                              mMockUidStatsCollector, nullptr,
1091                                                              &resourceStats));
1092 
1093     const auto expected =
1094             constructIoOveruseStats(/*isKillable=*/false,
1095                                     /*remaining=*/
1096                                     constructPerStateBytes(70'000, 20'000, 100'000),
1097                                     /*written=*/
1098                                     constructPerStateBytes(90'000, 20'000, 0),
1099                                     /*totalOveruses=*/1, startTime, durationInSeconds);
1100     IoOveruseStats actual;
1101     ASSERT_NO_FATAL_FAILURE(executeAsUid(1001000, [&]() {
1102         ASSERT_RESULT_OK(mIoOveruseMonitor->getIoOveruseStats(&actual));
1103     }));
1104     EXPECT_THAT(actual, expected) << "Expected: " << expected.toString()
1105                                   << "\nActual: " << actual.toString();
1106 }
1107 
TEST_F(IoOveruseMonitorTest,TestResetIoOveruseStats)1108 TEST_F(IoOveruseMonitorTest, TestResetIoOveruseStats) {
1109     EXPECT_CALL(*mMockWatchdogServiceHelper, requestTodayIoUsageStats())
1110             .WillOnce(Return(ByMove(ScopedAStatus::ok())));
1111     EXPECT_CALL(*mMockUidStatsCollector, deltaStats())
1112             .WillOnce(Return(
1113                     constructUidStats({{1001000, {/*fgWrBytes=*/90'000, /*bgWrBytes=*/20'000}}})));
1114 
1115     ResourceStats resourceStats = {};
1116 
1117     ASSERT_RESULT_OK(
1118             mIoOveruseMonitor
1119                     ->onPeriodicCollection(std::chrono::time_point_cast<std::chrono::milliseconds>(
1120                                                    std::chrono::system_clock::now()),
1121                                            SystemState::NORMAL_MODE, mMockUidStatsCollector,
1122                                            nullptr, &resourceStats));
1123 
1124     IoOveruseStats actual;
1125     ASSERT_NO_FATAL_FAILURE(executeAsUid(1001000, [&]() {
1126         ASSERT_RESULT_OK(mIoOveruseMonitor->getIoOveruseStats(&actual));
1127     }));
1128 
1129     EXPECT_NE(actual.totalOveruses, 0);
1130     EXPECT_NE(actual.writtenBytes.foregroundBytes, 0);
1131     EXPECT_NE(actual.writtenBytes.backgroundBytes, 0);
1132 
1133     std::vector<std::string> packageNames = {"system.daemon"};
1134     EXPECT_CALL(*mMockWatchdogServiceHelper, resetResourceOveruseStats(packageNames))
1135             .WillOnce(Return(ByMove(ScopedAStatus::ok())));
1136 
1137     ASSERT_RESULT_OK(mIoOveruseMonitor->resetIoOveruseStats(packageNames));
1138 
1139     ASSERT_NO_FATAL_FAILURE(executeAsUid(1001000, [&]() {
1140         ASSERT_RESULT_OK(mIoOveruseMonitor->getIoOveruseStats(&actual));
1141     }));
1142 
1143     EXPECT_EQ(actual.totalOveruses, 0);
1144     EXPECT_EQ(actual.writtenBytes.foregroundBytes, 0);
1145     EXPECT_EQ(actual.writtenBytes.backgroundBytes, 0);
1146 }
1147 
TEST_F(IoOveruseMonitorTest,TestErrorsResetIoOveruseStatsOnWatchdogServiceHelperError)1148 TEST_F(IoOveruseMonitorTest, TestErrorsResetIoOveruseStatsOnWatchdogServiceHelperError) {
1149     std::vector<std::string> packageNames = {"system.daemon"};
1150     EXPECT_CALL(*mMockWatchdogServiceHelper, resetResourceOveruseStats(packageNames))
1151             .WillOnce(Return(ByMove(ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE))));
1152 
1153     ASSERT_FALSE(mIoOveruseMonitor->resetIoOveruseStats(packageNames).ok())
1154             << "Must return error when WatchdogServiceHelper fails to reset stats";
1155 }
1156 
TEST_F(IoOveruseMonitorTest,TestErrorsGetIoOveruseStatsOnNoStats)1157 TEST_F(IoOveruseMonitorTest, TestErrorsGetIoOveruseStatsOnNoStats) {
1158     ON_CALL(*mMockPackageInfoResolver, getPackageInfosForUids(_))
1159             .WillByDefault([]() -> std::unordered_map<uid_t, PackageInfo> {
1160                 return {{1001000,
1161                          constructPackageInfo(/*packageName=*/"system.daemon", /*uid=*/1001000,
1162                                               UidType::NATIVE)}};
1163             });
1164     IoOveruseStats actual;
1165     ASSERT_NO_FATAL_FAILURE(executeAsUid(1001000, [&]() {
1166         ASSERT_FALSE(mIoOveruseMonitor->getIoOveruseStats(&actual).ok())
1167                 << "Should fail on missing I/O overuse stats";
1168     }));
1169 
1170     ASSERT_NO_FATAL_FAILURE(executeAsUid(1102001, [&]() {
1171         ASSERT_FALSE(mIoOveruseMonitor->getIoOveruseStats(&actual).ok())
1172                 << "Should fail on missing package information";
1173     }));
1174 }
1175 
TEST_F(IoOveruseMonitorTest,TestUpdateResourceOveruseConfigurations)1176 TEST_F(IoOveruseMonitorTest, TestUpdateResourceOveruseConfigurations) {
1177     EXPECT_CALL(*mMockIoOveruseConfigs, update(_)).WillOnce(Return(Result<void>{}));
1178 
1179     ASSERT_RESULT_OK(mIoOveruseMonitor->updateResourceOveruseConfigurations({}));
1180 }
1181 
TEST_F(IoOveruseMonitorTest,TestFailsUpdateResourceOveruseConfigurations)1182 TEST_F(IoOveruseMonitorTest, TestFailsUpdateResourceOveruseConfigurations) {
1183     EXPECT_CALL(*mMockIoOveruseConfigs, update(_))
1184             .WillOnce([&]([[maybe_unused]] const std::vector<ResourceOveruseConfiguration>& configs)
1185                               -> Result<void> { return Error() << "Failed to update"; });
1186 
1187     ASSERT_FALSE(mIoOveruseMonitor->updateResourceOveruseConfigurations({}).ok());
1188 }
1189 
TEST_F(IoOveruseMonitorTest,TestRemoveUser)1190 TEST_F(IoOveruseMonitorTest, TestRemoveUser) {
1191     EXPECT_CALL(*mMockUidStatsCollector, deltaStats())
1192             .WillOnce(Return(
1193                     constructUidStats({{1001000, {/*fgWrBytes=*/70'000, /*bgWrBytes=*/20'000}},
1194                                        {1112345, {/*fgWrBytes=*/35'000, /*bgWrBytes=*/15'000}}})));
1195 
1196     std::vector<UserPackageIoUsageStats> todayIoUsageStats =
1197             {constructUserPackageIoUsageStats(
1198                      /*userId=*/11, "com.android.google.package",
1199                      /*writtenBytes=*/constructPerStateBytes(100'000, 85'000, 120'000),
1200                      /*forgivenWriteBytes=*/constructPerStateBytes(70'000, 60'000, 100'000),
1201                      /*totalOveruses=*/3),
1202              constructUserPackageIoUsageStats(
1203                      /*userId=*/12, "com.android.kitchensink",
1204                      /*writtenBytes=*/constructPerStateBytes(50'000, 40'000, 35'000),
1205                      /*forgivenWriteBytes=*/constructPerStateBytes(30'000, 30'000, 30'000),
1206                      /*totalOveruses=*/6)};
1207 
1208     ASSERT_RESULT_OK(mIoOveruseMonitor->onTodayIoUsageStatsFetched(todayIoUsageStats));
1209 
1210     ResourceStats actualResourceStats = {};
1211 
1212     auto currentTime = std::chrono::time_point_cast<std::chrono::milliseconds>(
1213             std::chrono::system_clock::now());
1214     const auto [startTime, durationInSeconds] = calculateStartAndDuration(currentTime);
1215 
1216     ASSERT_RESULT_OK(mIoOveruseMonitor->onPeriodicCollection(currentTime, SystemState::NORMAL_MODE,
1217                                                              mMockUidStatsCollector, nullptr,
1218                                                              &actualResourceStats));
1219 
1220     std::vector<PackageIoOveruseStats> expectedIoOveruseStats =
1221             {constructPackageIoOveruseStats(
1222                      /*uid*=*/1001000, /*shouldNotify=*/false, /*isKillable=*/false,
1223                      /*remaining=*/constructPerStateBytes(10'000, 20'000, 100'000),
1224                      /*written=*/constructPerStateBytes(70'000, 20'000, 0),
1225                      /*forgiven=*/constructPerStateBytes(0, 0, 0),
1226                      /*totalOveruses=*/0, startTime, durationInSeconds),
1227              constructPackageIoOveruseStats(
1228                      /*uid*=*/1112345, /*shouldNotify=*/true, /*isKillable=*/true,
1229                      /*remaining=*/constructPerStateBytes(5'000, 0, 80'000),
1230                      /*written=*/constructPerStateBytes(135'000, 100'000, 120'000),
1231                      /*forgiven=*/constructPerStateBytes(70'000, 90'000, 100'000),
1232                      /*totalOveruses=*/4, startTime, durationInSeconds)};
1233 
1234     EXPECT_THAT(actualResourceStats.resourceOveruseStats->packageIoOveruseStats,
1235                 UnorderedElementsAreArray(expectedIoOveruseStats))
1236             << "Expected: " << toString(expectedIoOveruseStats) << "\nActual: "
1237             << toString(actualResourceStats.resourceOveruseStats->packageIoOveruseStats);
1238 
1239     mIoOveruseMonitor->removeStatsForUser(/*userId=*/11);
1240     mIoOveruseMonitor->removeStatsForUser(/*userId=*/12);
1241 
1242     EXPECT_CALL(*mMockUidStatsCollector, deltaStats())
1243             .WillOnce(Return(
1244                     constructUidStats({{1112345, {/*fgWrBytes=*/70'000, /*bgWrBytes=*/40'000}},
1245                                        {1245678, {/*fgWrBytes=*/30'000, /*bgWrBytes=*/10'000}}})));
1246 
1247     ASSERT_RESULT_OK(mIoOveruseMonitor->onPeriodicCollection(currentTime, SystemState::GARAGE_MODE,
1248                                                              mMockUidStatsCollector, nullptr,
1249                                                              &actualResourceStats));
1250 
1251     expectedIoOveruseStats = {constructPackageIoOveruseStats(
1252                                       /*uid*=*/1112345, /*shouldNotify=*/true, /*isKillable=*/true,
1253                                       /*remaining=*/constructPerStateBytes(70'000, 30'000, 0),
1254                                       /*written=*/constructPerStateBytes(0, 0, 110'000),
1255                                       /*forgiven=*/constructPerStateBytes(0, 0, 100'000),
1256                                       /*totalOveruses=*/1, startTime, durationInSeconds),
1257                               constructPackageIoOveruseStats(
1258                                       /*uid*=*/1245678, /*shouldNotify=*/true, /*isKillable=*/true,
1259                                       /*remaining=*/constructPerStateBytes(30'000, 15'000, 0),
1260                                       /*written=*/constructPerStateBytes(0, 0, 40'000),
1261                                       /*forgiven=*/constructPerStateBytes(0, 0, 40'000),
1262                                       /*totalOveruses=*/4, startTime, durationInSeconds)};
1263     EXPECT_THAT(actualResourceStats.resourceOveruseStats->packageIoOveruseStats,
1264                 UnorderedElementsAreArray(expectedIoOveruseStats))
1265             << "Expected: " << toString(expectedIoOveruseStats) << "\nActual: "
1266             << toString(actualResourceStats.resourceOveruseStats->packageIoOveruseStats);
1267 }
1268 
1269 }  // namespace watchdog
1270 }  // namespace automotive
1271 }  // namespace android
1272