Adding checks for bad periodic job scheduling.
1. There are cases where a periodic job is scheduled in a past time
period. Without any other constraints, the job could be run much too
frequently and spam the system. Adding these checks makes sure the jobs
are scheduled with sane values.
2. Adding an upper limit on the job period to avoid overflow cases.
3. Changing int to long to avoid overflow.
Bug: 133654009
Test: atest com.android.server.job.JobSchedulerServiceTest
Test: atest com.android.server.job.controllers.QuotaControllerTest
Test: atest com.android.server.job.controllers.TimeControllerTest
Test: atest CtsJobSchedulerTestCases
Change-Id: I97616efb6c37b7201eb926d16c0d9be450bf2ba4
diff --git a/services/core/java/com/android/server/job/controllers/JobStatus.java b/services/core/java/com/android/server/job/controllers/JobStatus.java
index fd20e11..eb5d472 100644
--- a/services/core/java/com/android/server/job/controllers/JobStatus.java
+++ b/services/core/java/com/android/server/job/controllers/JobStatus.java
@@ -511,8 +511,13 @@
final long elapsedNow = sElapsedRealtimeClock.millis();
final long earliestRunTimeElapsedMillis, latestRunTimeElapsedMillis;
if (job.isPeriodic()) {
- latestRunTimeElapsedMillis = elapsedNow + job.getIntervalMillis();
- earliestRunTimeElapsedMillis = latestRunTimeElapsedMillis - job.getFlexMillis();
+ // Make sure period is in the interval [min_possible_period, max_possible_period].
+ final long period = Math.max(JobInfo.getMinPeriodMillis(),
+ Math.min(JobSchedulerService.MAX_ALLOWED_PERIOD_MS, job.getIntervalMillis()));
+ latestRunTimeElapsedMillis = elapsedNow + period;
+ earliestRunTimeElapsedMillis = latestRunTimeElapsedMillis
+ // Make sure flex is in the interval [min_possible_flex, period].
+ - Math.max(JobInfo.getMinFlexMillis(), Math.min(period, job.getFlexMillis()));
} else {
earliestRunTimeElapsedMillis = job.hasEarlyConstraint() ?
elapsedNow + job.getMinLatencyMillis() : NO_EARLIEST_RUNTIME;
@@ -1631,6 +1636,9 @@
formatRunTime(pw, earliestRunTimeElapsedMillis, NO_EARLIEST_RUNTIME, elapsedRealtimeMillis);
pw.print(", latest=");
formatRunTime(pw, latestRunTimeElapsedMillis, NO_LATEST_RUNTIME, elapsedRealtimeMillis);
+ pw.print(", original latest=");
+ formatRunTime(pw, mOriginalLatestRunTimeElapsedMillis,
+ NO_LATEST_RUNTIME, elapsedRealtimeMillis);
pw.println();
if (numFailures != 0) {
pw.print(prefix); pw.print("Num failures: "); pw.println(numFailures);