Merge "Avoid using stale sessions for cleanup alarm." into sc-dev

This commit is contained in:
Kweku Adams
2021-05-06 21:58:52 +00:00
committed by Android (Google) Code Review
2 changed files with 50 additions and 21 deletions

View File

@@ -1502,13 +1502,14 @@ public final class QuotaController extends StateController {
/** Schedule a cleanup alarm if necessary and there isn't already one scheduled. */ /** Schedule a cleanup alarm if necessary and there isn't already one scheduled. */
@VisibleForTesting @VisibleForTesting
void maybeScheduleCleanupAlarmLocked() { void maybeScheduleCleanupAlarmLocked() {
if (mNextCleanupTimeElapsed > sElapsedRealtimeClock.millis()) { final long nowElapsed = sElapsedRealtimeClock.millis();
if (mNextCleanupTimeElapsed > nowElapsed) {
// There's already an alarm scheduled. Just stick with that one. There's no way we'll // There's already an alarm scheduled. Just stick with that one. There's no way we'll
// end up scheduling an earlier alarm. // end up scheduling an earlier alarm.
if (DEBUG) { if (DEBUG) {
Slog.v(TAG, "Not scheduling cleanup since there's already one at " Slog.v(TAG, "Not scheduling cleanup since there's already one at "
+ mNextCleanupTimeElapsed + " (in " + (mNextCleanupTimeElapsed + mNextCleanupTimeElapsed
- sElapsedRealtimeClock.millis()) + "ms)"); + " (in " + (mNextCleanupTimeElapsed - nowElapsed) + "ms)");
} }
return; return;
} }
@@ -1530,7 +1531,7 @@ public final class QuotaController extends StateController {
if (nextCleanupElapsed - mNextCleanupTimeElapsed <= 10 * MINUTE_IN_MILLIS) { if (nextCleanupElapsed - mNextCleanupTimeElapsed <= 10 * MINUTE_IN_MILLIS) {
// No need to clean up too often. Delay the alarm if the next cleanup would be too soon // No need to clean up too often. Delay the alarm if the next cleanup would be too soon
// after it. // after it.
nextCleanupElapsed += 10 * MINUTE_IN_MILLIS; nextCleanupElapsed = mNextCleanupTimeElapsed + 10 * MINUTE_IN_MILLIS;
} }
mNextCleanupTimeElapsed = nextCleanupElapsed; mNextCleanupTimeElapsed = nextCleanupElapsed;
mAlarmManager.set(AlarmManager.ELAPSED_REALTIME, nextCleanupElapsed, ALARM_TAG_CLEANUP, mAlarmManager.set(AlarmManager.ELAPSED_REALTIME, nextCleanupElapsed, ALARM_TAG_CLEANUP,
@@ -2478,30 +2479,60 @@ public final class QuotaController extends StateController {
} }
} }
private final class DeleteTimingSessionsFunctor implements Consumer<List<TimingSession>> { private static final class TimingSessionTooOldPredicate implements Predicate<TimingSession> {
private final Predicate<TimingSession> mTooOld = new Predicate<TimingSession>() { private long mNowElapsed;
public boolean test(TimingSession ts) {
return ts.endTimeElapsed <= sElapsedRealtimeClock.millis() - MAX_PERIOD_MS; private void updateNow() {
} mNowElapsed = sElapsedRealtimeClock.millis();
}; }
@Override @Override
public void accept(List<TimingSession> sessions) { public boolean test(TimingSession ts) {
if (sessions != null) { return ts.endTimeElapsed <= mNowElapsed - MAX_PERIOD_MS;
// Remove everything older than MAX_PERIOD_MS time ago.
sessions.removeIf(mTooOld);
}
} }
} }
private final DeleteTimingSessionsFunctor mDeleteOldSessionsFunctor = private final TimingSessionTooOldPredicate mTimingSessionTooOld =
new DeleteTimingSessionsFunctor(); new TimingSessionTooOldPredicate();
private final Consumer<List<TimingSession>> mDeleteOldSessionsFunctor = sessions -> {
if (sessions != null) {
// Remove everything older than MAX_PERIOD_MS time ago.
sessions.removeIf(mTimingSessionTooOld);
}
};
@VisibleForTesting @VisibleForTesting
void deleteObsoleteSessionsLocked() { void deleteObsoleteSessionsLocked() {
mTimingSessionTooOld.updateNow();
// Regular sessions
mTimingSessions.forEach(mDeleteOldSessionsFunctor); mTimingSessions.forEach(mDeleteOldSessionsFunctor);
// Don't delete EJ timing sessions here. They'll be removed in
// getRemainingEJExecutionTimeLocked(). // EJ sessions
for (int uIdx = 0; uIdx < mEJTimingSessions.numMaps(); ++uIdx) {
final int userId = mEJTimingSessions.keyAt(uIdx);
for (int pIdx = 0; pIdx < mEJTimingSessions.numElementsForKey(userId); ++pIdx) {
final String packageName = mEJTimingSessions.keyAt(uIdx, pIdx);
final ShrinkableDebits debits = getEJDebitsLocked(userId, packageName);
final List<TimingSession> sessions = mEJTimingSessions.get(userId, packageName);
if (sessions == null) {
continue;
}
while (sessions.size() > 0) {
final TimingSession ts = sessions.get(0);
if (mTimingSessionTooOld.test(ts)) {
// Stale sessions may still be factored into tally. Remove them.
final long duration = ts.endTimeElapsed - ts.startTimeElapsed;
debits.transactLocked(-duration);
sessions.remove(0);
} else {
break;
}
}
}
}
} }
private class QcHandler extends Handler { private class QcHandler extends Handler {

View File

@@ -68,7 +68,6 @@ import android.content.ComponentName;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.pm.ApplicationInfo; import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageInfo; import android.content.pm.PackageInfo;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal; import android.content.pm.PackageManagerInternal;
@@ -475,7 +474,6 @@ public class QuotaControllerTest {
expectedRegular.add(thr); expectedRegular.add(thr);
expectedRegular.add(two); expectedRegular.add(two);
expectedRegular.add(one); expectedRegular.add(one);
expectedEJ.add(fiv); // EJ list should be unaffected
expectedEJ.add(fou); expectedEJ.add(fou);
expectedEJ.add(one); expectedEJ.add(one);
mQuotaController.saveTimingSession(0, "com.android.test", fiv, false); mQuotaController.saveTimingSession(0, "com.android.test", fiv, false);