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