Merge "Fix QC alarm spamming." into rvc-dev am: 7a97fd74d4 am: 7f53da43bd am: 6ac36921c6
Change-Id: I76081530de61935ae9033a85cc3d7d792a4ec22b
This commit is contained in:
@@ -241,10 +241,11 @@ public final class QuotaController extends StateController {
|
||||
+ "bgJobCountInMaxPeriod=" + bgJobCountInMaxPeriod + ", "
|
||||
+ "sessionCountInWindow=" + sessionCountInWindow + ", "
|
||||
+ "inQuotaTime=" + inQuotaTimeElapsed + ", "
|
||||
+ "jobCountExpirationTime=" + jobRateLimitExpirationTimeElapsed + ", "
|
||||
+ "jobCountInRateLimitingWindow=" + jobCountInRateLimitingWindow + ", "
|
||||
+ "sessionCountExpirationTime=" + sessionRateLimitExpirationTimeElapsed + ", "
|
||||
+ "sessionCountInRateLimitingWindow=" + sessionCountInRateLimitingWindow;
|
||||
+ "rateLimitJobCountExpirationTime=" + jobRateLimitExpirationTimeElapsed + ", "
|
||||
+ "rateLimitJobCountWindow=" + jobCountInRateLimitingWindow + ", "
|
||||
+ "rateLimitSessionCountExpirationTime="
|
||||
+ sessionRateLimitExpirationTimeElapsed + ", "
|
||||
+ "rateLimitSessionCountWindow=" + sessionCountInRateLimitingWindow;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -863,12 +864,19 @@ public final class QuotaController extends StateController {
|
||||
stats.executionTimeInMaxPeriodMs = 0;
|
||||
stats.bgJobCountInMaxPeriod = 0;
|
||||
stats.sessionCountInWindow = 0;
|
||||
stats.inQuotaTimeElapsed = 0;
|
||||
if (stats.jobCountLimit == 0 || stats.sessionCountLimit == 0) {
|
||||
// App won't be in quota until configuration changes.
|
||||
stats.inQuotaTimeElapsed = Long.MAX_VALUE;
|
||||
} else {
|
||||
stats.inQuotaTimeElapsed = 0;
|
||||
}
|
||||
|
||||
Timer timer = mPkgTimers.get(userId, packageName);
|
||||
final long nowElapsed = sElapsedRealtimeClock.millis();
|
||||
stats.expirationTimeElapsed = nowElapsed + MAX_PERIOD_MS;
|
||||
if (timer != null && timer.isActive()) {
|
||||
// Exclude active sessions from the session count so that new jobs aren't prevented
|
||||
// from starting due to an app hitting the session limit.
|
||||
stats.executionTimeInWindowMs =
|
||||
stats.executionTimeInMaxPeriodMs = timer.getCurrentDuration(nowElapsed);
|
||||
stats.bgJobCountInWindow = stats.bgJobCountInMaxPeriod = timer.getBgJobCount();
|
||||
@@ -883,6 +891,10 @@ public final class QuotaController extends StateController {
|
||||
stats.inQuotaTimeElapsed = Math.max(stats.inQuotaTimeElapsed,
|
||||
nowElapsed - mMaxExecutionTimeIntoQuotaMs + MAX_PERIOD_MS);
|
||||
}
|
||||
if (stats.bgJobCountInWindow >= stats.jobCountLimit) {
|
||||
stats.inQuotaTimeElapsed = Math.max(stats.inQuotaTimeElapsed,
|
||||
nowElapsed + stats.windowSizeMs);
|
||||
}
|
||||
}
|
||||
|
||||
List<TimingSession> sessions = mTimingSessions.get(userId, packageName);
|
||||
@@ -1303,6 +1315,13 @@ public final class QuotaController extends StateController {
|
||||
inQuotaTimeElapsed = Math.max(inQuotaTimeElapsed,
|
||||
stats.sessionRateLimitExpirationTimeElapsed);
|
||||
}
|
||||
if (inQuotaTimeElapsed <= sElapsedRealtimeClock.millis()) {
|
||||
final long nowElapsed = sElapsedRealtimeClock.millis();
|
||||
Slog.wtf(TAG,
|
||||
"In quota time is " + (nowElapsed - inQuotaTimeElapsed) + "ms old. Now="
|
||||
+ nowElapsed + ", inQuotaTime=" + inQuotaTimeElapsed + ": " + stats);
|
||||
inQuotaTimeElapsed = nowElapsed + 5 * MINUTE_IN_MILLIS;
|
||||
}
|
||||
mInQuotaAlarmListener.addAlarmLocked(userId, packageName, inQuotaTimeElapsed);
|
||||
}
|
||||
|
||||
@@ -1916,8 +1935,8 @@ public final class QuotaController extends StateController {
|
||||
@GuardedBy("mLock")
|
||||
private void setNextAlarmLocked(long earliestTriggerElapsed) {
|
||||
if (mAlarmQueue.size() > 0) {
|
||||
final long nextTriggerTimeElapsed = Math.max(earliestTriggerElapsed,
|
||||
mAlarmQueue.peek().second);
|
||||
final Pair<Package, Long> alarm = mAlarmQueue.peek();
|
||||
final long nextTriggerTimeElapsed = Math.max(earliestTriggerElapsed, alarm.second);
|
||||
// Only schedule the alarm if one of the following is true:
|
||||
// 1. There isn't one currently scheduled
|
||||
// 2. The new alarm is significantly earlier than the previous alarm. If it's
|
||||
@@ -1928,7 +1947,8 @@ public final class QuotaController extends StateController {
|
||||
|| nextTriggerTimeElapsed < mTriggerTimeElapsed - 3 * MINUTE_IN_MILLIS
|
||||
|| mTriggerTimeElapsed < nextTriggerTimeElapsed) {
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "Scheduling start alarm at " + nextTriggerTimeElapsed);
|
||||
Slog.d(TAG, "Scheduling start alarm at " + nextTriggerTimeElapsed
|
||||
+ " for app " + alarm.first);
|
||||
}
|
||||
mAlarmManager.set(AlarmManager.ELAPSED_REALTIME, nextTriggerTimeElapsed,
|
||||
ALARM_TAG_QUOTA_CHECK, this, mHandler);
|
||||
|
||||
@@ -408,7 +408,12 @@ public class CountQuotaTracker extends QuotaTracker {
|
||||
void updateExecutionStatsLocked(final int userId, @NonNull final String packageName,
|
||||
@Nullable final String tag, @NonNull ExecutionStats stats) {
|
||||
stats.countInWindow = 0;
|
||||
stats.inQuotaTimeElapsed = 0;
|
||||
if (stats.countLimit == 0) {
|
||||
// UPTC won't be in quota until configuration changes.
|
||||
stats.inQuotaTimeElapsed = Long.MAX_VALUE;
|
||||
} else {
|
||||
stats.inQuotaTimeElapsed = 0;
|
||||
}
|
||||
|
||||
// This can be used to determine when an app will have enough quota to transition from
|
||||
// out-of-quota to in-quota.
|
||||
|
||||
@@ -620,6 +620,77 @@ public class QuotaControllerTest {
|
||||
assertEquals(expectedStats, inputStats);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateExecutionStatsLocked_WithTimer() {
|
||||
final long now = sElapsedRealtimeClock.millis();
|
||||
setProcessState(ActivityManager.PROCESS_STATE_SERVICE);
|
||||
|
||||
ExecutionStats expectedStats = new ExecutionStats();
|
||||
ExecutionStats inputStats = new ExecutionStats();
|
||||
inputStats.windowSizeMs = expectedStats.windowSizeMs = 24 * HOUR_IN_MILLIS;
|
||||
inputStats.jobCountLimit = expectedStats.jobCountLimit = mQcConstants.MAX_JOB_COUNT_RARE;
|
||||
inputStats.sessionCountLimit = expectedStats.sessionCountLimit =
|
||||
mQcConstants.MAX_SESSION_COUNT_RARE;
|
||||
// Active timer isn't counted as session yet.
|
||||
expectedStats.sessionCountInWindow = 0;
|
||||
// Timer only, under quota.
|
||||
for (int i = 1; i < mQcConstants.MAX_JOB_COUNT_RARE; ++i) {
|
||||
JobStatus jobStatus = createJobStatus("testUpdateExecutionStatsLocked_WithTimer", i);
|
||||
setStandbyBucket(RARE_INDEX, jobStatus); // 24 hour window
|
||||
mQuotaController.maybeStartTrackingJobLocked(jobStatus, null);
|
||||
mQuotaController.prepareForExecutionLocked(jobStatus);
|
||||
advanceElapsedClock(7000);
|
||||
|
||||
expectedStats.expirationTimeElapsed = sElapsedRealtimeClock.millis();
|
||||
expectedStats.executionTimeInWindowMs = expectedStats.executionTimeInMaxPeriodMs =
|
||||
7000 * i;
|
||||
expectedStats.bgJobCountInWindow = expectedStats.bgJobCountInMaxPeriod = i;
|
||||
mQuotaController.updateExecutionStatsLocked(SOURCE_USER_ID, SOURCE_PACKAGE, inputStats);
|
||||
assertEquals(expectedStats, inputStats);
|
||||
assertTrue(mQuotaController.isWithinQuotaLocked(SOURCE_USER_ID, SOURCE_PACKAGE,
|
||||
RARE_INDEX));
|
||||
}
|
||||
|
||||
// Add old session. Make sure values are combined correctly.
|
||||
mQuotaController.saveTimingSession(SOURCE_USER_ID, SOURCE_PACKAGE,
|
||||
createTimingSession(sElapsedRealtimeClock.millis() - (6 * HOUR_IN_MILLIS),
|
||||
10 * MINUTE_IN_MILLIS, 5));
|
||||
expectedStats.sessionCountInWindow = 1;
|
||||
|
||||
expectedStats.expirationTimeElapsed = sElapsedRealtimeClock.millis() + 18 * HOUR_IN_MILLIS;
|
||||
expectedStats.executionTimeInWindowMs += 10 * MINUTE_IN_MILLIS;
|
||||
expectedStats.executionTimeInMaxPeriodMs += 10 * MINUTE_IN_MILLIS;
|
||||
expectedStats.bgJobCountInWindow += 5;
|
||||
expectedStats.bgJobCountInMaxPeriod += 5;
|
||||
// Active timer is under quota, so out of quota due to old session.
|
||||
expectedStats.inQuotaTimeElapsed =
|
||||
sElapsedRealtimeClock.millis() + 18 * HOUR_IN_MILLIS + 10 * MINUTE_IN_MILLIS;
|
||||
mQuotaController.updateExecutionStatsLocked(SOURCE_USER_ID, SOURCE_PACKAGE, inputStats);
|
||||
assertEquals(expectedStats, inputStats);
|
||||
assertFalse(
|
||||
mQuotaController.isWithinQuotaLocked(SOURCE_USER_ID, SOURCE_PACKAGE, RARE_INDEX));
|
||||
|
||||
// Quota should be exceeded due to activity in active timer.
|
||||
JobStatus jobStatus = createJobStatus("testUpdateExecutionStatsLocked_WithTimer", 0);
|
||||
setStandbyBucket(RARE_INDEX, jobStatus); // 24 hour window
|
||||
mQuotaController.maybeStartTrackingJobLocked(jobStatus, null);
|
||||
mQuotaController.prepareForExecutionLocked(jobStatus);
|
||||
advanceElapsedClock(10000);
|
||||
|
||||
expectedStats.executionTimeInWindowMs += 10000;
|
||||
expectedStats.executionTimeInMaxPeriodMs += 10000;
|
||||
expectedStats.bgJobCountInWindow++;
|
||||
expectedStats.bgJobCountInMaxPeriod++;
|
||||
// Out of quota due to activity in active timer, so in quota time should be when enough
|
||||
// time has passed since active timer.
|
||||
expectedStats.inQuotaTimeElapsed =
|
||||
sElapsedRealtimeClock.millis() + expectedStats.windowSizeMs;
|
||||
mQuotaController.updateExecutionStatsLocked(SOURCE_USER_ID, SOURCE_PACKAGE, inputStats);
|
||||
assertEquals(expectedStats, inputStats);
|
||||
assertFalse(
|
||||
mQuotaController.isWithinQuotaLocked(SOURCE_USER_ID, SOURCE_PACKAGE, RARE_INDEX));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that getExecutionStatsLocked returns the correct stats.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user