summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Kweku Adams <kwekua@google.com> 2024-02-08 06:56:53 +0000
committer Kweku Adams <kwekua@google.com> 2024-02-08 15:52:34 +0000
commit0f72d99536872904bdfc101e01dd0aa41cdea6e4 (patch)
treedb2197bf608bb1dc36bf02798f2e4bc0eafb8276
parente7143188377ea9a5967d73538311874e7414f557 (diff)
Apply flex policy to jobs with short deadlines.
Apply flex policy to all jobs with deadlines and adjust other factors to accomodate increased scope: 1. Don't exclude jobs with short deadlines from flex policy. 2. Use the standard flex fallback duration for the policy, unless the job's own deadline results in a later end time. In that case, use the job's deadline instead. 3. Exclude jobs from the TOP app from score calculation so that apps aren't penalized for doing work while in the TOP state. 4. Cache job score to avoid recalculating if buckets haven't changed. 5. Address comments from previous change. 6. Adjust scores and max values to avoid extreme delays. Bug: 236261941 Test: atest frameworks/base/services/tests/mockingservicestests/src/com/android/server/job Test: CtsJobSchedulerTestCases:FlexibilityConstraintTest Change-Id: I2dd85732eddc4aace3ab81a914d781fb25d9c6f6
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/controllers/FlexibilityController.java81
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java9
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/job/controllers/FlexibilityControllerTest.java109
3 files changed, 119 insertions, 80 deletions
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/FlexibilityController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/FlexibilityController.java
index 6883d18cd937..aec464d0e820 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/FlexibilityController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/FlexibilityController.java
@@ -241,6 +241,8 @@ public final class FlexibilityController extends StateController {
private static final long MAX_TIME_WINDOW_MS = 24 * HOUR_IN_MILLIS;
private final JobScoreBucket[] mScoreBuckets = new JobScoreBucket[NUM_SCORE_BUCKETS];
private int mScoreBucketIndex = 0;
+ private long mCachedScoreExpirationTimeElapsed;
+ private int mCachedScore;
public void addScore(int add, long nowElapsed) {
JobScoreBucket bucket = mScoreBuckets[mScoreBucketIndex];
@@ -248,10 +250,17 @@ public final class FlexibilityController extends StateController {
bucket = new JobScoreBucket();
bucket.startTimeElapsed = nowElapsed;
mScoreBuckets[mScoreBucketIndex] = bucket;
+ // Brand new bucket, there's nothing to remove from the score,
+ // so just update the expiration time if needed.
+ mCachedScoreExpirationTimeElapsed = Math.min(mCachedScoreExpirationTimeElapsed,
+ nowElapsed + MAX_TIME_WINDOW_MS);
} else if (bucket.startTimeElapsed < nowElapsed - MAX_TIME_WINDOW_MS) {
// The bucket is too old.
bucket.reset();
bucket.startTimeElapsed = nowElapsed;
+ // Force a recalculation of the cached score instead of just updating the cached
+ // value and time in case there are multiple stale buckets.
+ mCachedScoreExpirationTimeElapsed = nowElapsed;
} else if (bucket.startTimeElapsed
< nowElapsed - MAX_TIME_WINDOW_MS / NUM_SCORE_BUCKETS) {
// The current bucket's duration has completed. Move on to the next bucket.
@@ -261,16 +270,26 @@ public final class FlexibilityController extends StateController {
}
bucket.score += add;
+ mCachedScore += add;
}
public int getScore(long nowElapsed) {
+ if (nowElapsed < mCachedScoreExpirationTimeElapsed) {
+ return mCachedScore;
+ }
int score = 0;
final long earliestElapsed = nowElapsed - MAX_TIME_WINDOW_MS;
+ long earliestValidBucketTimeElapsed = Long.MAX_VALUE;
for (JobScoreBucket bucket : mScoreBuckets) {
if (bucket != null && bucket.startTimeElapsed >= earliestElapsed) {
score += bucket.score;
+ if (earliestValidBucketTimeElapsed > bucket.startTimeElapsed) {
+ earliestValidBucketTimeElapsed = bucket.startTimeElapsed;
+ }
}
}
+ mCachedScore = score;
+ mCachedScoreExpirationTimeElapsed = earliestValidBucketTimeElapsed + MAX_TIME_WINDOW_MS;
return score;
}
@@ -378,10 +397,16 @@ public final class FlexibilityController extends StateController {
@Override
public void prepareForExecutionLocked(JobStatus jobStatus) {
+ if (jobStatus.lastEvaluatedBias == JobInfo.BIAS_TOP_APP) {
+ // Don't include jobs for the TOP app in the score calculation.
+ return;
+ }
// Use the job's requested priority to determine its score since that is what the developer
// selected and it will be stable across job runs.
- final int score = mFallbackFlexibilityDeadlineScores
- .get(jobStatus.getJob().getPriority(), jobStatus.getJob().getPriority() / 100);
+ final int priority = jobStatus.getJob().getPriority();
+ final int score = mFallbackFlexibilityDeadlineScores.get(priority,
+ FcConfig.DEFAULT_FALLBACK_FLEXIBILITY_DEADLINE_SCORES
+ .get(priority, priority / 100));
JobScoreTracker jobScoreTracker =
mJobScoreTrackers.get(jobStatus.getSourceUid(), jobStatus.getSourcePackageName());
if (jobScoreTracker == null) {
@@ -394,6 +419,10 @@ public final class FlexibilityController extends StateController {
@Override
public void unprepareFromExecutionLocked(JobStatus jobStatus) {
+ if (jobStatus.lastEvaluatedBias == JobInfo.BIAS_TOP_APP) {
+ // Jobs for the TOP app are excluded from the score calculation.
+ return;
+ }
// The job didn't actually start. Undo the score increase.
JobScoreTracker jobScoreTracker =
mJobScoreTrackers.get(jobStatus.getSourceUid(), jobStatus.getSourcePackageName());
@@ -401,8 +430,10 @@ public final class FlexibilityController extends StateController {
Slog.e(TAG, "Unprepared a job that didn't result in a score change");
return;
}
- final int score = mFallbackFlexibilityDeadlineScores
- .get(jobStatus.getJob().getPriority(), jobStatus.getJob().getPriority() / 100);
+ final int priority = jobStatus.getJob().getPriority();
+ final int score = mFallbackFlexibilityDeadlineScores.get(priority,
+ FcConfig.DEFAULT_FALLBACK_FLEXIBILITY_DEADLINE_SCORES
+ .get(priority, priority / 100));
jobScoreTracker.addScore(-score, sElapsedRealtimeClock.millis());
}
@@ -649,21 +680,24 @@ public final class FlexibilityController extends StateController {
(long) Math.scalb(mRescheduledJobDeadline, js.getNumPreviousAttempts() - 2),
mMaxRescheduledDeadline);
}
+
+ // Intentionally use the effective priority here. If a job's priority was effectively
+ // lowered, it will be less likely to run quickly given other policies in JobScheduler.
+ // Thus, there's no need to further delay the job based on flex policy.
+ final int jobPriority = js.getEffectivePriority();
+ final int jobScore =
+ getScoreLocked(js.getSourceUid(), js.getSourcePackageName(), nowElapsed);
+ // Set an upper limit on the fallback deadline so that the delay doesn't become extreme.
+ final long fallbackDurationMs = Math.min(3 * mFallbackFlexibilityDeadlineMs,
+ mFallbackFlexibilityDeadlines.get(jobPriority, mFallbackFlexibilityDeadlineMs)
+ + mFallbackFlexibilityAdditionalScoreTimeFactors
+ .get(jobPriority, MINUTE_IN_MILLIS) * jobScore);
+ final long fallbackDeadlineMs = earliest + fallbackDurationMs;
+
if (js.getLatestRunTimeElapsed() == JobStatus.NO_LATEST_RUNTIME) {
- // Intentionally use the effective priority here. If a job's priority was effectively
- // lowered, it will be less likely to run quickly given other policies in JobScheduler.
- // Thus, there's no need to further delay the job based on flex policy.
- final int jobPriority = js.getEffectivePriority();
- final int jobScore =
- getScoreLocked(js.getSourceUid(), js.getSourcePackageName(), nowElapsed);
- // Set an upper limit on the fallback deadline so that the delay doesn't become extreme.
- final long fallbackDeadlineMs = Math.min(3 * mFallbackFlexibilityDeadlineMs,
- mFallbackFlexibilityDeadlines.get(jobPriority, mFallbackFlexibilityDeadlineMs)
- + mFallbackFlexibilityAdditionalScoreTimeFactors
- .get(jobPriority, MINUTE_IN_MILLIS) * jobScore);
- return earliest + fallbackDeadlineMs;
+ return fallbackDeadlineMs;
}
- return js.getLatestRunTimeElapsed();
+ return Math.max(fallbackDeadlineMs, js.getLatestRunTimeElapsed());
}
@VisibleForTesting
@@ -976,7 +1010,8 @@ public final class FlexibilityController extends StateController {
// Something has gone horribly wrong. This has only occurred on incorrectly
// configured tests, but add a check here for safety.
Slog.wtf(TAG, "Got invalid latest when scheduling alarm."
- + " Prefetch=" + js.getJob().isPrefetch());
+ + " prefetch=" + js.getJob().isPrefetch()
+ + " periodic=" + js.getJob().isPeriodic());
// Since things have gone wrong, the safest and most reliable thing to do is
// stop applying flex policy to the job.
mFlexibilityTracker.setNumDroppedFlexibleConstraints(js,
@@ -991,7 +1026,7 @@ public final class FlexibilityController extends StateController {
if (DEBUG) {
Slog.d(TAG, "scheduleDropNumConstraintsAlarm: "
- + js.getSourcePackageName() + " " + js.getSourceUserId()
+ + js.toShortString()
+ " numApplied: " + js.getNumAppliedFlexibleConstraints()
+ " numRequired: " + js.getNumRequiredFlexibleConstraints()
+ " numSatisfied: " + Integer.bitCount(
@@ -1199,11 +1234,11 @@ public final class FlexibilityController extends StateController {
DEFAULT_FALLBACK_FLEXIBILITY_DEADLINE_ADDITIONAL_SCORE_TIME_FACTORS
.put(PRIORITY_MAX, 0);
DEFAULT_FALLBACK_FLEXIBILITY_DEADLINE_ADDITIONAL_SCORE_TIME_FACTORS
- .put(PRIORITY_HIGH, 4 * MINUTE_IN_MILLIS);
+ .put(PRIORITY_HIGH, 3 * MINUTE_IN_MILLIS);
DEFAULT_FALLBACK_FLEXIBILITY_DEADLINE_ADDITIONAL_SCORE_TIME_FACTORS
- .put(PRIORITY_DEFAULT, 3 * MINUTE_IN_MILLIS);
+ .put(PRIORITY_DEFAULT, 2 * MINUTE_IN_MILLIS);
DEFAULT_FALLBACK_FLEXIBILITY_DEADLINE_ADDITIONAL_SCORE_TIME_FACTORS
- .put(PRIORITY_LOW, 2 * MINUTE_IN_MILLIS);
+ .put(PRIORITY_LOW, 1 * MINUTE_IN_MILLIS);
DEFAULT_FALLBACK_FLEXIBILITY_DEADLINE_ADDITIONAL_SCORE_TIME_FACTORS
.put(PRIORITY_MIN, 1 * MINUTE_IN_MILLIS);
DEFAULT_PERCENTS_TO_DROP_FLEXIBLE_CONSTRAINTS
@@ -1220,7 +1255,7 @@ public final class FlexibilityController extends StateController {
private static final long DEFAULT_MIN_TIME_BETWEEN_FLEXIBILITY_ALARMS_MS = MINUTE_IN_MILLIS;
private static final long DEFAULT_RESCHEDULED_JOB_DEADLINE_MS = HOUR_IN_MILLIS;
- private static final long DEFAULT_MAX_RESCHEDULED_DEADLINE_MS = 5 * DAY_IN_MILLIS;
+ private static final long DEFAULT_MAX_RESCHEDULED_DEADLINE_MS = DAY_IN_MILLIS;
@VisibleForTesting
static final long DEFAULT_UNSEEN_CONSTRAINT_GRACE_PERIOD_MS = 3 * DAY_IN_MILLIS;
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
index a3a686fdc5c8..a0b9c5fb7a60 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
@@ -16,8 +16,6 @@
package com.android.server.job.controllers;
-import static android.text.format.DateUtils.HOUR_IN_MILLIS;
-
import static com.android.server.job.JobSchedulerService.ACTIVE_INDEX;
import static com.android.server.job.JobSchedulerService.EXEMPTED_INDEX;
import static com.android.server.job.JobSchedulerService.NEVER_INDEX;
@@ -430,9 +428,6 @@ public final class JobStatus {
*/
public static final int INTERNAL_FLAG_DEMOTED_BY_SYSTEM_UIJ = 1 << 2;
- /** Minimum difference between start and end time to have flexible constraint */
- @VisibleForTesting
- static final long MIN_WINDOW_FOR_FLEXIBILITY_MS = HOUR_IN_MILLIS;
/**
* Versatile, persistable flags for a job that's updated within the system server,
* as opposed to {@link JobInfo#flags} that's set by callers.
@@ -708,14 +703,10 @@ public final class JobStatus {
final boolean lacksSomeFlexibleConstraints =
((~requiredConstraints) & SYSTEM_WIDE_FLEXIBLE_CONSTRAINTS) != 0
|| mCanApplyTransportAffinities;
- final boolean satisfiesMinWindowException =
- (latestRunTimeElapsedMillis - earliestRunTimeElapsedMillis)
- >= MIN_WINDOW_FOR_FLEXIBILITY_MS;
// The first time a job is rescheduled it will not be subject to flexible constraints.
// Otherwise, every consecutive reschedule increases a jobs' flexibility deadline.
if (!isRequestedExpeditedJob() && !job.isUserInitiated()
- && satisfiesMinWindowException
&& (numFailures + numSystemStops) != 1
&& lacksSomeFlexibleConstraints) {
requiredConstraints |= CONSTRAINT_FLEXIBLE;
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/controllers/FlexibilityControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/job/controllers/FlexibilityControllerTest.java
index 28471b37d2a0..6bcd778c234b 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/controllers/FlexibilityControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/controllers/FlexibilityControllerTest.java
@@ -49,7 +49,6 @@ import static com.android.server.job.controllers.JobStatus.CONSTRAINT_CONNECTIVI
import static com.android.server.job.controllers.JobStatus.CONSTRAINT_CONTENT_TRIGGER;
import static com.android.server.job.controllers.JobStatus.CONSTRAINT_FLEXIBLE;
import static com.android.server.job.controllers.JobStatus.CONSTRAINT_IDLE;
-import static com.android.server.job.controllers.JobStatus.MIN_WINDOW_FOR_FLEXIBILITY_MS;
import static com.android.server.job.controllers.JobStatus.NO_LATEST_RUNTIME;
import static org.junit.Assert.assertArrayEquals;
@@ -410,10 +409,12 @@ public class FlexibilityControllerTest {
@Test
public void testOnConstantsUpdated_PercentsToDropConstraints() {
+ final long fallbackDuration = 12 * HOUR_IN_MILLIS;
JobInfo.Builder jb = createJob(0)
- .setOverrideDeadline(MIN_WINDOW_FOR_FLEXIBILITY_MS);
+ .setOverrideDeadline(HOUR_IN_MILLIS);
JobStatus js = createJobStatus("testPercentsToDropConstraintsConfig", jb);
- assertEquals(FROZEN_TIME + MIN_WINDOW_FOR_FLEXIBILITY_MS / 10 * 5,
+ // Even though the override deadline is 1 hour, the fallback duration is still used.
+ assertEquals(FROZEN_TIME + fallbackDuration / 10 * 5,
mFlexibilityController.getNextConstraintDropTimeElapsedLocked(js));
setDeviceConfigString(KEY_PERCENTS_TO_DROP_FLEXIBLE_CONSTRAINTS,
"500=1|2|3|4"
@@ -441,13 +442,13 @@ public class FlexibilityControllerTest {
mFlexibilityController.mFcConfig.PERCENTS_TO_DROP_FLEXIBLE_CONSTRAINTS
.get(JobInfo.PRIORITY_MIN),
new int[]{54, 55, 56, 57});
- assertEquals(FROZEN_TIME + MIN_WINDOW_FOR_FLEXIBILITY_MS / 10,
+ assertEquals(FROZEN_TIME + fallbackDuration / 10,
mFlexibilityController.getNextConstraintDropTimeElapsedLocked(js));
js.setNumDroppedFlexibleConstraints(1);
- assertEquals(FROZEN_TIME + MIN_WINDOW_FOR_FLEXIBILITY_MS / 10 * 2,
+ assertEquals(FROZEN_TIME + fallbackDuration / 10 * 2,
mFlexibilityController.getNextConstraintDropTimeElapsedLocked(js));
js.setNumDroppedFlexibleConstraints(2);
- assertEquals(FROZEN_TIME + MIN_WINDOW_FOR_FLEXIBILITY_MS / 10 * 3,
+ assertEquals(FROZEN_TIME + fallbackDuration / 10 * 3,
mFlexibilityController.getNextConstraintDropTimeElapsedLocked(js));
}
@@ -504,37 +505,38 @@ public class FlexibilityControllerTest {
@Test
public void testGetNextConstraintDropTimeElapsedLocked() {
+ final long fallbackDuration = 50 * HOUR_IN_MILLIS;
setDeviceConfigLong(KEY_FALLBACK_FLEXIBILITY_DEADLINE, 200 * HOUR_IN_MILLIS);
setDeviceConfigString(KEY_FALLBACK_FLEXIBILITY_DEADLINES,
"500=" + HOUR_IN_MILLIS
+ ",400=" + 25 * HOUR_IN_MILLIS
- + ",300=" + 50 * HOUR_IN_MILLIS
+ + ",300=" + fallbackDuration
+ ",200=" + 100 * HOUR_IN_MILLIS
+ ",100=" + 200 * HOUR_IN_MILLIS);
long nextTimeToDropNumConstraints;
// no delay, deadline
- JobInfo.Builder jb = createJob(0).setOverrideDeadline(MIN_WINDOW_FOR_FLEXIBILITY_MS);
+ JobInfo.Builder jb = createJob(0).setOverrideDeadline(HOUR_IN_MILLIS);
JobStatus js = createJobStatus("time", jb);
assertEquals(JobStatus.NO_EARLIEST_RUNTIME, js.getEarliestRunTime());
- assertEquals(MIN_WINDOW_FOR_FLEXIBILITY_MS + FROZEN_TIME, js.getLatestRunTimeElapsed());
+ assertEquals(HOUR_IN_MILLIS + FROZEN_TIME, js.getLatestRunTimeElapsed());
assertEquals(FROZEN_TIME, js.enqueueTime);
nextTimeToDropNumConstraints = mFlexibilityController
.getNextConstraintDropTimeElapsedLocked(js);
- assertEquals(FROZEN_TIME + MIN_WINDOW_FOR_FLEXIBILITY_MS / 10 * 5,
+ assertEquals(FROZEN_TIME + fallbackDuration / 10 * 5,
nextTimeToDropNumConstraints);
js.setNumDroppedFlexibleConstraints(1);
nextTimeToDropNumConstraints = mFlexibilityController
.getNextConstraintDropTimeElapsedLocked(js);
- assertEquals(FROZEN_TIME + MIN_WINDOW_FOR_FLEXIBILITY_MS / 10 * 6,
+ assertEquals(FROZEN_TIME + fallbackDuration / 10 * 6,
nextTimeToDropNumConstraints);
js.setNumDroppedFlexibleConstraints(2);
nextTimeToDropNumConstraints = mFlexibilityController
.getNextConstraintDropTimeElapsedLocked(js);
- assertEquals(FROZEN_TIME + MIN_WINDOW_FOR_FLEXIBILITY_MS / 10 * 7,
+ assertEquals(FROZEN_TIME + fallbackDuration / 10 * 7,
nextTimeToDropNumConstraints);
// delay, no deadline
@@ -574,81 +576,83 @@ public class FlexibilityControllerTest {
// delay, deadline
jb = createJob(0)
- .setOverrideDeadline(2 * MIN_WINDOW_FOR_FLEXIBILITY_MS)
- .setMinimumLatency(MIN_WINDOW_FOR_FLEXIBILITY_MS);
+ .setOverrideDeadline(2 * HOUR_IN_MILLIS)
+ .setMinimumLatency(HOUR_IN_MILLIS);
js = createJobStatus("time", jb);
- final long windowStart = FROZEN_TIME + MIN_WINDOW_FOR_FLEXIBILITY_MS;
+ final long windowStart = FROZEN_TIME + HOUR_IN_MILLIS;
nextTimeToDropNumConstraints = mFlexibilityController
.getNextConstraintDropTimeElapsedLocked(js);
- assertEquals(windowStart + MIN_WINDOW_FOR_FLEXIBILITY_MS / 10 * 5,
+ assertEquals(windowStart + fallbackDuration / 10 * 5,
nextTimeToDropNumConstraints);
js.setNumDroppedFlexibleConstraints(1);
nextTimeToDropNumConstraints = mFlexibilityController
.getNextConstraintDropTimeElapsedLocked(js);
- assertEquals(windowStart + MIN_WINDOW_FOR_FLEXIBILITY_MS / 10 * 6,
+ assertEquals(windowStart + fallbackDuration / 10 * 6,
nextTimeToDropNumConstraints);
js.setNumDroppedFlexibleConstraints(2);
nextTimeToDropNumConstraints = mFlexibilityController
.getNextConstraintDropTimeElapsedLocked(js);
- assertEquals(windowStart + MIN_WINDOW_FOR_FLEXIBILITY_MS / 10 * 7,
+ assertEquals(windowStart + fallbackDuration / 10 * 7,
nextTimeToDropNumConstraints);
}
@Test
public void testCurPercent() {
+ final long fallbackDuration = 10 * HOUR_IN_MILLIS;
+ setDeviceConfigString(KEY_FALLBACK_FLEXIBILITY_DEADLINES, "300=" + fallbackDuration);
long deadline = 100 * MINUTE_IN_MILLIS;
long nowElapsed = FROZEN_TIME;
JobInfo.Builder jb = createJob(0).setOverrideDeadline(deadline);
JobStatus js = createJobStatus("time", jb);
assertEquals(FROZEN_TIME, mFlexibilityController.getLifeCycleBeginningElapsedLocked(js));
- assertEquals(deadline + FROZEN_TIME,
+ assertEquals(FROZEN_TIME + fallbackDuration,
mFlexibilityController.getLifeCycleEndElapsedLocked(js, nowElapsed, FROZEN_TIME));
- nowElapsed = FROZEN_TIME + 60 * MINUTE_IN_MILLIS;
+ nowElapsed = FROZEN_TIME + 6 * HOUR_IN_MILLIS;
JobSchedulerService.sElapsedRealtimeClock =
Clock.fixed(Instant.ofEpochMilli(nowElapsed), ZoneOffset.UTC);
assertEquals(60, mFlexibilityController.getCurPercentOfLifecycleLocked(js, nowElapsed));
- nowElapsed = FROZEN_TIME + 130 * MINUTE_IN_MILLIS;
+ nowElapsed = FROZEN_TIME + 13 * HOUR_IN_MILLIS;
JobSchedulerService.sElapsedRealtimeClock =
Clock.fixed(Instant.ofEpochMilli(nowElapsed), ZoneOffset.UTC);
assertEquals(100, mFlexibilityController.getCurPercentOfLifecycleLocked(js, nowElapsed));
- nowElapsed = FROZEN_TIME + 95 * MINUTE_IN_MILLIS;
+ nowElapsed = FROZEN_TIME + 9 * HOUR_IN_MILLIS;
JobSchedulerService.sElapsedRealtimeClock =
Clock.fixed(Instant.ofEpochMilli(nowElapsed), ZoneOffset.UTC);
- assertEquals(95, mFlexibilityController.getCurPercentOfLifecycleLocked(js, nowElapsed));
+ assertEquals(90, mFlexibilityController.getCurPercentOfLifecycleLocked(js, nowElapsed));
nowElapsed = FROZEN_TIME;
JobSchedulerService.sElapsedRealtimeClock =
Clock.fixed(Instant.ofEpochMilli(nowElapsed), ZoneOffset.UTC);
- long delay = MINUTE_IN_MILLIS;
- deadline = 101 * MINUTE_IN_MILLIS;
+ long delay = HOUR_IN_MILLIS;
+ deadline = HOUR_IN_MILLIS + 100 * MINUTE_IN_MILLIS;
jb = createJob(0).setOverrideDeadline(deadline).setMinimumLatency(delay);
js = createJobStatus("time", jb);
assertEquals(FROZEN_TIME + delay,
mFlexibilityController.getLifeCycleBeginningElapsedLocked(js));
- assertEquals(deadline + FROZEN_TIME,
+ assertEquals(FROZEN_TIME + delay + fallbackDuration,
mFlexibilityController.getLifeCycleEndElapsedLocked(js, nowElapsed,
FROZEN_TIME + delay));
- nowElapsed = FROZEN_TIME + delay + 60 * MINUTE_IN_MILLIS;
+ nowElapsed = FROZEN_TIME + delay + 6 * HOUR_IN_MILLIS;
JobSchedulerService.sElapsedRealtimeClock =
Clock.fixed(Instant.ofEpochMilli(nowElapsed), ZoneOffset.UTC);
assertEquals(60, mFlexibilityController.getCurPercentOfLifecycleLocked(js, nowElapsed));
- nowElapsed = FROZEN_TIME + 130 * MINUTE_IN_MILLIS;
+ nowElapsed = FROZEN_TIME + 13 * HOUR_IN_MILLIS;
JobSchedulerService.sElapsedRealtimeClock =
Clock.fixed(Instant.ofEpochMilli(nowElapsed), ZoneOffset.UTC);
assertEquals(100, mFlexibilityController.getCurPercentOfLifecycleLocked(js, nowElapsed));
- nowElapsed = FROZEN_TIME + delay + 95 * MINUTE_IN_MILLIS;
+ nowElapsed = FROZEN_TIME + delay + 9 * HOUR_IN_MILLIS;
JobSchedulerService.sElapsedRealtimeClock =
Clock.fixed(Instant.ofEpochMilli(nowElapsed), ZoneOffset.UTC);
- assertEquals(95, mFlexibilityController.getCurPercentOfLifecycleLocked(js, nowElapsed));
+ assertEquals(90, mFlexibilityController.getCurPercentOfLifecycleLocked(js, nowElapsed));
}
@Test
@@ -786,26 +790,27 @@ public class FlexibilityControllerTest {
// deadline
JobInfo.Builder jb = createJob(0).setOverrideDeadline(HOUR_IN_MILLIS);
JobStatus js = createJobStatus("time", jb);
- assertEquals(HOUR_IN_MILLIS + FROZEN_TIME,
- mFlexibilityController.getLifeCycleEndElapsedLocked(js, nowElapsed, 0));
+ assertEquals(3 * HOUR_IN_MILLIS + js.enqueueTime,
+ mFlexibilityController
+ .getLifeCycleEndElapsedLocked(js, nowElapsed, js.enqueueTime));
// no deadline
- assertEquals(FROZEN_TIME + 2 * HOUR_IN_MILLIS,
+ assertEquals(js.enqueueTime + 2 * HOUR_IN_MILLIS,
mFlexibilityController.getLifeCycleEndElapsedLocked(
createJobStatus("time", createJob(0).setPriority(JobInfo.PRIORITY_HIGH)),
- nowElapsed, 100L));
- assertEquals(FROZEN_TIME + 3 * HOUR_IN_MILLIS,
+ nowElapsed, js.enqueueTime));
+ assertEquals(js.enqueueTime + 3 * HOUR_IN_MILLIS,
mFlexibilityController.getLifeCycleEndElapsedLocked(
createJobStatus("time", createJob(0).setPriority(JobInfo.PRIORITY_DEFAULT)),
- nowElapsed, 100L));
- assertEquals(FROZEN_TIME + 4 * HOUR_IN_MILLIS,
+ nowElapsed, js.enqueueTime));
+ assertEquals(js.enqueueTime + 4 * HOUR_IN_MILLIS,
mFlexibilityController.getLifeCycleEndElapsedLocked(
createJobStatus("time", createJob(0).setPriority(JobInfo.PRIORITY_LOW)),
- nowElapsed, 100L));
- assertEquals(FROZEN_TIME + 5 * HOUR_IN_MILLIS,
+ nowElapsed, js.enqueueTime));
+ assertEquals(js.enqueueTime + 5 * HOUR_IN_MILLIS,
mFlexibilityController.getLifeCycleEndElapsedLocked(
createJobStatus("time", createJob(0).setPriority(JobInfo.PRIORITY_MIN)),
- nowElapsed, 100L));
+ nowElapsed, js.enqueueTime));
}
@Test
@@ -871,14 +876,16 @@ public class FlexibilityControllerTest {
mFlexibilityController.prepareForExecutionLocked(jsLow);
mFlexibilityController.prepareForExecutionLocked(jsMin);
- // deadline
- JobInfo.Builder jb = createJob(0).setOverrideDeadline(HOUR_IN_MILLIS);
- JobStatus js = createJobStatus("testGetLifeCycleEndElapsedLocked_ScoreAddition", jb);
- assertEquals(HOUR_IN_MILLIS + FROZEN_TIME,
- mFlexibilityController.getLifeCycleEndElapsedLocked(js, nowElapsed, 0));
+ final long longDeadlineMs = 14 * 24 * HOUR_IN_MILLIS;
+ JobInfo.Builder jbWithLongDeadline = createJob(0).setOverrideDeadline(longDeadlineMs);
+ JobStatus jsWithLongDeadline = createJobStatus(
+ "testGetLifeCycleEndElapsedLocked_ScoreAddition", jbWithLongDeadline);
+ JobInfo.Builder jbWithShortDeadline =
+ createJob(0).setOverrideDeadline(15 * MINUTE_IN_MILLIS);
+ JobStatus jsWithShortDeadline = createJobStatus(
+ "testGetLifeCycleEndElapsedLocked_ScoreAddition", jbWithShortDeadline);
final long earliestMs = 123L;
- // no deadline
assertEquals(earliestMs + HOUR_IN_MILLIS + 5 * 15 * MINUTE_IN_MILLIS,
mFlexibilityController.getLifeCycleEndElapsedLocked(
createJobStatus("testGetLifeCycleEndElapsedLocked_ScoreAddition",
@@ -894,6 +901,9 @@ public class FlexibilityControllerTest {
createJobStatus("testGetLifeCycleEndElapsedLocked_ScoreAddition",
createJob(0).setPriority(JobInfo.PRIORITY_DEFAULT)),
nowElapsed, earliestMs));
+ assertEquals(earliestMs + HOUR_IN_MILLIS + 3 * 15 * MINUTE_IN_MILLIS,
+ mFlexibilityController.getLifeCycleEndElapsedLocked(
+ jsWithShortDeadline, nowElapsed, earliestMs));
assertEquals(earliestMs + HOUR_IN_MILLIS + 2 * 15 * MINUTE_IN_MILLIS,
mFlexibilityController.getLifeCycleEndElapsedLocked(
createJobStatus("testGetLifeCycleEndElapsedLocked_ScoreAddition",
@@ -904,6 +914,9 @@ public class FlexibilityControllerTest {
createJobStatus("testGetLifeCycleEndElapsedLocked_ScoreAddition",
createJob(0).setPriority(JobInfo.PRIORITY_MIN)),
nowElapsed, earliestMs));
+ assertEquals(jsWithLongDeadline.enqueueTime + longDeadlineMs,
+ mFlexibilityController.getLifeCycleEndElapsedLocked(
+ jsWithLongDeadline, nowElapsed, earliestMs));
}
@Test
@@ -1033,8 +1046,8 @@ public class FlexibilityControllerTest {
JobInfo.Builder jb = createJob(0);
jb.setMinimumLatency(1);
jb.setOverrideDeadline(2);
- JobStatus js = createJobStatus("Disable Flexible When Job Has Short Window", jb);
- assertFalse(js.hasFlexibilityConstraint());
+ JobStatus js = createJobStatus("testExceptions_ShortWindow", jb);
+ assertTrue(js.hasFlexibilityConstraint());
}
@Test