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