Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b5480ac5 authored by alexbianchi's avatar alexbianchi Committed by Alex Bianchi
Browse files

Decrease number of sElapsedRealtimeClock.millis() calls in Flexibility Controller

Getting the current elapsed time is system intensive. Currently
flexibility controller gets the elapsed time within for loops and in
functions that are called at the same time. By passing in nowElapsed we
can decrease the amount of times we call sElapsedRealtimeClock.millis().

Bug: 243166228

Test: atest frameworks/base/services/tests/mockingservicestests/src/com/android/server/job
Test: atest frameworks/base/services/tests/servicestests/src/com/android/server/job
Test: atest CtsJobSchedulerTestCases
Change-Id: I8bed88b97306af0fc7d0beadb43cb252ad0d5afe
parent a61c60e9
Loading
Loading
Loading
Loading
+5 −4
Original line number Diff line number Diff line
@@ -176,12 +176,13 @@ public final class BatteryController extends RestrictingController {
            Slog.d(TAG, "maybeReportNewChargingStateLocked: "
                    + powerConnected + "/" + stablePower + "/" + batteryNotLow);
        }
        final long nowElapsed = sElapsedRealtimeClock.millis();

        mFlexibilityController.setConstraintSatisfied(
                JobStatus.CONSTRAINT_CHARGING, mService.isBatteryCharging());
        mFlexibilityController
            .setConstraintSatisfied(JobStatus.CONSTRAINT_BATTERY_NOT_LOW, batteryNotLow);
                JobStatus.CONSTRAINT_CHARGING, mService.isBatteryCharging(), nowElapsed);
        mFlexibilityController.setConstraintSatisfied(
                        JobStatus.CONSTRAINT_BATTERY_NOT_LOW, batteryNotLow, nowElapsed);

        final long nowElapsed = sElapsedRealtimeClock.millis();
        for (int i = mTrackedTasks.size() - 1; i >= 0; i--) {
            final JobStatus ts = mTrackedTasks.valueAt(i);
            if (ts.hasChargingConstraint()) {
+19 −22
Original line number Diff line number Diff line
@@ -137,9 +137,9 @@ public final class FlexibilityController extends StateController {
            new PrefetchController.PrefetchChangedListener() {
                @Override
                public void onPrefetchCacheUpdated(ArraySet<JobStatus> jobs, int userId,
                        String pkgName, long prevEstimatedLaunchTime, long newEstimatedLaunchTime) {
                        String pkgName, long prevEstimatedLaunchTime,
                        long newEstimatedLaunchTime, long nowElapsed) {
                    synchronized (mLock) {
                        final long nowElapsed = sElapsedRealtimeClock.millis();
                        final long prefetchThreshold =
                                mPrefetchController.getLaunchTimeThresholdMs();
                        boolean jobWasInPrefetchWindow  = prevEstimatedLaunchTime
@@ -158,8 +158,8 @@ public final class FlexibilityController extends StateController {
                            if (!js.hasFlexibilityConstraint()) {
                                continue;
                            }
                            mFlexibilityTracker.resetJobNumDroppedConstraints(js);
                            mFlexibilityAlarmQueue.scheduleDropNumConstraintsAlarm(js);
                            mFlexibilityTracker.resetJobNumDroppedConstraints(js, nowElapsed);
                            mFlexibilityAlarmQueue.scheduleDropNumConstraintsAlarm(js, nowElapsed);
                        }
                    }
                }
@@ -191,7 +191,7 @@ public final class FlexibilityController extends StateController {
            js.setTrackingController(JobStatus.TRACKING_FLEXIBILITY);
            final long nowElapsed = sElapsedRealtimeClock.millis();
            js.setFlexibilityConstraintSatisfied(nowElapsed, isFlexibilitySatisfiedLocked(js));
            mFlexibilityAlarmQueue.scheduleDropNumConstraintsAlarm(js);
            mFlexibilityAlarmQueue.scheduleDropNumConstraintsAlarm(js, nowElapsed);
        }
    }

@@ -239,7 +239,7 @@ public final class FlexibilityController extends StateController {
     * Changes flexibility constraint satisfaction for affected jobs.
     */
    @VisibleForTesting
    void setConstraintSatisfied(int constraint, boolean state) {
    void setConstraintSatisfied(int constraint, boolean state, long nowElapsed) {
        synchronized (mLock) {
            final boolean old = (mSatisfiedFlexibleConstraints & constraint) != 0;
            if (old == state) {
@@ -255,8 +255,6 @@ public final class FlexibilityController extends StateController {
            // The rest did not have a change in state and are still satisfied or unsatisfied.
            final int numConstraintsToUpdate = Math.max(curSatisfied, prevSatisfied);

            final long nowElapsed = sElapsedRealtimeClock.millis();

            // In order to get the range of all potentially satisfied jobs, we start at the number
            // of satisfied system-wide constraints and iterate to the max number of potentially
            // satisfied constraints, determined by how many job-specific constraints exist.
@@ -329,10 +327,9 @@ public final class FlexibilityController extends StateController {

    @VisibleForTesting
    @GuardedBy("mLock")
    int getCurPercentOfLifecycleLocked(JobStatus js) {
    int getCurPercentOfLifecycleLocked(JobStatus js, long nowElapsed) {
        final long earliest = getLifeCycleBeginningElapsedLocked(js);
        final long latest = getLifeCycleEndElapsedLocked(js, earliest);
        final long nowElapsed = sElapsedRealtimeClock.millis();
        if (latest == NO_LIFECYCLE_END || earliest >= nowElapsed) {
            return 0;
        }
@@ -414,8 +411,8 @@ public final class FlexibilityController extends StateController {
                                .getJobsByNumRequiredConstraints(j);
                        for (int i = 0; i < jobs.size(); i++) {
                            JobStatus js = jobs.valueAt(i);
                            mFlexibilityTracker.resetJobNumDroppedConstraints(js);
                            mFlexibilityAlarmQueue.scheduleDropNumConstraintsAlarm(js);
                            mFlexibilityTracker.resetJobNumDroppedConstraints(js, nowElapsed);
                            mFlexibilityAlarmQueue.scheduleDropNumConstraintsAlarm(js, nowElapsed);
                            if (js.setFlexibilityConstraintSatisfied(
                                    nowElapsed, isFlexibilitySatisfiedLocked(js))) {
                                changedJobs.add(js);
@@ -479,8 +476,8 @@ public final class FlexibilityController extends StateController {
            mTrackedJobs.get(js.getNumRequiredFlexibleConstraints() - 1).remove(js);
        }

        public void resetJobNumDroppedConstraints(JobStatus js) {
            final int curPercent = getCurPercentOfLifecycleLocked(js);
        public void resetJobNumDroppedConstraints(JobStatus js, long nowElapsed) {
            final int curPercent = getCurPercentOfLifecycleLocked(js, nowElapsed);
            int toDrop = 0;
            final int jsMaxFlexibleConstraints = NUM_SYSTEM_WIDE_FLEXIBLE_CONSTRAINTS
                    + (js.getPreferUnmetered() ? 1 : 0);
@@ -489,7 +486,8 @@ public final class FlexibilityController extends StateController {
                    toDrop++;
                }
            }
            adjustJobsRequiredConstraints(js, js.getNumDroppedFlexibleConstraints() - toDrop);
            adjustJobsRequiredConstraints(
                    js, js.getNumDroppedFlexibleConstraints() - toDrop, nowElapsed);
        }

        /** Returns all tracked jobs. */
@@ -502,13 +500,12 @@ public final class FlexibilityController extends StateController {
         * Returns false if the job status's number of flexible constraints is now 0.
         * Jobs with 0 required flexible constraints are removed from the tracker.
         */
        public boolean adjustJobsRequiredConstraints(JobStatus js, int n) {
        public boolean adjustJobsRequiredConstraints(JobStatus js, int n, long nowElapsed) {
            if (n == 0) {
                return false;
            }
            remove(js);
            js.adjustNumRequiredFlexibleConstraints(n);
            final long nowElapsed = sElapsedRealtimeClock.millis();
            js.setFlexibilityConstraintSatisfied(nowElapsed, isFlexibilitySatisfiedLocked(js));
            if (js.getNumRequiredFlexibleConstraints() <= 0) {
                maybeStopTrackingJobLocked(js, null, false);
@@ -553,7 +550,7 @@ public final class FlexibilityController extends StateController {
            return js.getSourceUserId() == userId;
        }

        public void scheduleDropNumConstraintsAlarm(JobStatus js) {
        public void scheduleDropNumConstraintsAlarm(JobStatus js, long nowElapsed) {
            long nextTimeElapsed;
            synchronized (mLock) {
                final long earliest = getLifeCycleBeginningElapsedLocked(js);
@@ -567,7 +564,7 @@ public final class FlexibilityController extends StateController {

                if (latest - nextTimeElapsed < mDeadlineProximityLimitMs) {
                    mFlexibilityTracker.adjustJobsRequiredConstraints(
                            js, -js.getNumRequiredFlexibleConstraints());
                            js, -js.getNumRequiredFlexibleConstraints(), nowElapsed);
                    return;
                }
                addAlarm(js, nextTimeElapsed);
@@ -578,21 +575,21 @@ public final class FlexibilityController extends StateController {
        protected void processExpiredAlarms(@NonNull ArraySet<JobStatus> expired) {
            synchronized (mLock) {
                ArraySet<JobStatus> changedJobs = new ArraySet<>();
                final long nowElapsed = sElapsedRealtimeClock.millis();
                for (int i = 0; i < expired.size(); i++) {
                    JobStatus js = expired.valueAt(i);
                    boolean wasFlexibilitySatisfied = js.isConstraintSatisfied(CONSTRAINT_FLEXIBLE);

                    final long earliest = getLifeCycleBeginningElapsedLocked(js);
                    final long latest = getLifeCycleEndElapsedLocked(js, earliest);
                    final long nowElapsed = sElapsedRealtimeClock.millis();

                    if (latest - nowElapsed < mDeadlineProximityLimitMs) {
                        mFlexibilityTracker.adjustJobsRequiredConstraints(js,
                                -js.getNumRequiredFlexibleConstraints());
                                -js.getNumRequiredFlexibleConstraints(), nowElapsed);
                    } else {
                        long nextTimeElapsed =
                                getNextConstraintDropTimeElapsedLocked(js, earliest, latest);
                        if (mFlexibilityTracker.adjustJobsRequiredConstraints(js, -1)
                        if (mFlexibilityTracker.adjustJobsRequiredConstraints(js, -1,  nowElapsed)
                                && nextTimeElapsed != NO_LIFECYCLE_END) {
                            mFlexibilityAlarmQueue.addAlarm(js, nextTimeElapsed);
                        }
+2 −1
Original line number Diff line number Diff line
@@ -95,9 +95,10 @@ public final class IdleController extends RestrictingController implements Idlen
     */
    @Override
    public void reportNewIdleState(boolean isIdle) {
        mFlexibilityController.setConstraintSatisfied(JobStatus.CONSTRAINT_IDLE, isIdle);
        synchronized (mLock) {
            final long nowElapsed = sElapsedRealtimeClock.millis();
            mFlexibilityController.setConstraintSatisfied(
                    JobStatus.CONSTRAINT_IDLE, isIdle, nowElapsed);
            for (int i = mTrackedTasks.size()-1; i >= 0; i--) {
                mTrackedTasks.valueAt(i).setIdleConstraintSatisfied(nowElapsed, isIdle);
            }
+4 −3
Original line number Diff line number Diff line
@@ -105,7 +105,7 @@ public class PrefetchController extends StateController {
    public interface PrefetchChangedListener {
        /** Callback to inform listeners when estimated launch times change. */
        void onPrefetchCacheUpdated(ArraySet<JobStatus> jobs, int userId, String pkgName,
                long prevEstimatedLaunchTime, long newEstimatedLaunchTime);
                long prevEstimatedLaunchTime, long newEstimatedLaunchTime, long nowElapsed);
    }

    @SuppressWarnings("FieldCanBeLocal")
@@ -308,8 +308,9 @@ public class PrefetchController extends StateController {
                    final long nowElapsed = sElapsedRealtimeClock.millis();
                    updateThresholdAlarmLocked(userId, pkgName, now, nowElapsed);
                    for (int i = 0; i < mPrefetchChangedListeners.size(); i++) {
                        mPrefetchChangedListeners.valueAt(i).onPrefetchCacheUpdated(jobs,
                                userId, pkgName, prevEstimatedLaunchTime, newEstimatedLaunchTime);
                        mPrefetchChangedListeners.valueAt(i).onPrefetchCacheUpdated(
                                jobs, userId, pkgName, prevEstimatedLaunchTime,
                                newEstimatedLaunchTime, nowElapsed);
                    }
                    if (maybeUpdateConstraintForPkgLocked(now, nowElapsed, userId, pkgName)) {
                        mStateChangedListener.onControllerStateChanged(jobs);
+63 −43
Original line number Diff line number Diff line
@@ -209,7 +209,8 @@ public class FlexibilityControllerTest {
    public void testOnConstantsUpdated_DeadlineProximity() {
        JobStatus js = createJobStatus("testDeadlineProximityConfig", createJob(0));
        setDeviceConfigLong(KEY_DEADLINE_PROXIMITY_LIMIT, Long.MAX_VALUE);
        mFlexibilityController.mFlexibilityAlarmQueue.scheduleDropNumConstraintsAlarm(js);
        mFlexibilityController.mFlexibilityAlarmQueue
                .scheduleDropNumConstraintsAlarm(js, FROZEN_TIME);
        assertEquals(0, js.getNumRequiredFlexibleConstraints());
    }

@@ -336,26 +337,31 @@ public class FlexibilityControllerTest {
    @Test
    public void testCurPercent() {
        long deadline = 1000;
        long nowElapsed;
        JobInfo.Builder jb = createJob(0).setOverrideDeadline(deadline);
        JobStatus js = createJobStatus("time", jb);

        assertEquals(FROZEN_TIME, mFlexibilityController.getLifeCycleBeginningElapsedLocked(js));
        assertEquals(deadline + FROZEN_TIME,
                mFlexibilityController.getLifeCycleEndElapsedLocked(js, FROZEN_TIME));
        nowElapsed = 600 + FROZEN_TIME;
        JobSchedulerService.sElapsedRealtimeClock =
                Clock.fixed(Instant.ofEpochMilli(600 + FROZEN_TIME), ZoneOffset.UTC);
        assertEquals(60, mFlexibilityController.getCurPercentOfLifecycleLocked(js));
                Clock.fixed(Instant.ofEpochMilli(nowElapsed), ZoneOffset.UTC);
        assertEquals(60, mFlexibilityController.getCurPercentOfLifecycleLocked(js, nowElapsed));

        nowElapsed = 1400;
        JobSchedulerService.sElapsedRealtimeClock =
                Clock.fixed(Instant.ofEpochMilli(1400), ZoneOffset.UTC);
        assertEquals(100, mFlexibilityController.getCurPercentOfLifecycleLocked(js));
                Clock.fixed(Instant.ofEpochMilli(nowElapsed), ZoneOffset.UTC);
        assertEquals(100, mFlexibilityController.getCurPercentOfLifecycleLocked(js, nowElapsed));

        nowElapsed = 950 + FROZEN_TIME;
        JobSchedulerService.sElapsedRealtimeClock =
                Clock.fixed(Instant.ofEpochMilli(950 + FROZEN_TIME), ZoneOffset.UTC);
        assertEquals(95, mFlexibilityController.getCurPercentOfLifecycleLocked(js));
                Clock.fixed(Instant.ofEpochMilli(nowElapsed), ZoneOffset.UTC);
        assertEquals(95, mFlexibilityController.getCurPercentOfLifecycleLocked(js, nowElapsed));

        nowElapsed = FROZEN_TIME;
        JobSchedulerService.sElapsedRealtimeClock =
                Clock.fixed(Instant.ofEpochMilli(FROZEN_TIME), ZoneOffset.UTC);
                Clock.fixed(Instant.ofEpochMilli(nowElapsed), ZoneOffset.UTC);
        long delay = 100;
        deadline = 1100;
        jb = createJob(0).setOverrideDeadline(deadline).setMinimumLatency(delay);
@@ -366,18 +372,21 @@ public class FlexibilityControllerTest {
        assertEquals(deadline + FROZEN_TIME,
                mFlexibilityController.getLifeCycleEndElapsedLocked(js, FROZEN_TIME + delay));

        nowElapsed = 600 + FROZEN_TIME + delay;
        JobSchedulerService.sElapsedRealtimeClock =
                Clock.fixed(Instant.ofEpochMilli(600 + FROZEN_TIME + delay), ZoneOffset.UTC);
                Clock.fixed(Instant.ofEpochMilli(nowElapsed), ZoneOffset.UTC);

        assertEquals(60, mFlexibilityController.getCurPercentOfLifecycleLocked(js));
        assertEquals(60, mFlexibilityController.getCurPercentOfLifecycleLocked(js, nowElapsed));

        nowElapsed = 1400;
        JobSchedulerService.sElapsedRealtimeClock =
                Clock.fixed(Instant.ofEpochMilli(1400), ZoneOffset.UTC);
        assertEquals(100, mFlexibilityController.getCurPercentOfLifecycleLocked(js));
                Clock.fixed(Instant.ofEpochMilli(nowElapsed), ZoneOffset.UTC);
        assertEquals(100, mFlexibilityController.getCurPercentOfLifecycleLocked(js, nowElapsed));

        nowElapsed = 950 + FROZEN_TIME + delay;
        JobSchedulerService.sElapsedRealtimeClock =
                Clock.fixed(Instant.ofEpochMilli(950 + FROZEN_TIME + delay), ZoneOffset.UTC);
        assertEquals(95, mFlexibilityController.getCurPercentOfLifecycleLocked(js));
                Clock.fixed(Instant.ofEpochMilli(nowElapsed), ZoneOffset.UTC);
        assertEquals(95, mFlexibilityController.getCurPercentOfLifecycleLocked(js, nowElapsed));
    }

    @Test
@@ -491,19 +500,19 @@ public class FlexibilityControllerTest {
            assertEquals(3, trackedJobs.get(2).size());
            assertEquals(0, trackedJobs.get(3).size());

            flexTracker.adjustJobsRequiredConstraints(jobs[0], -1);
            flexTracker.adjustJobsRequiredConstraints(jobs[0], -1, FROZEN_TIME);
            assertEquals(0, trackedJobs.get(0).size());
            assertEquals(1, trackedJobs.get(1).size());
            assertEquals(2, trackedJobs.get(2).size());
            assertEquals(0, trackedJobs.get(3).size());

            flexTracker.adjustJobsRequiredConstraints(jobs[0], -1);
            flexTracker.adjustJobsRequiredConstraints(jobs[0], -1, FROZEN_TIME);
            assertEquals(1, trackedJobs.get(0).size());
            assertEquals(0, trackedJobs.get(1).size());
            assertEquals(2, trackedJobs.get(2).size());
            assertEquals(0, trackedJobs.get(3).size());

            flexTracker.adjustJobsRequiredConstraints(jobs[0], -1);
            flexTracker.adjustJobsRequiredConstraints(jobs[0], -1, FROZEN_TIME);
            assertEquals(0, trackedJobs.get(0).size());
            assertEquals(0, trackedJobs.get(1).size());
            assertEquals(2, trackedJobs.get(2).size());
@@ -515,24 +524,25 @@ public class FlexibilityControllerTest {
            assertEquals(1, trackedJobs.get(2).size());
            assertEquals(0, trackedJobs.get(3).size());

            flexTracker.resetJobNumDroppedConstraints(jobs[0]);
            flexTracker.resetJobNumDroppedConstraints(jobs[0], FROZEN_TIME);
            assertEquals(0, trackedJobs.get(0).size());
            assertEquals(0, trackedJobs.get(1).size());
            assertEquals(2, trackedJobs.get(2).size());
            assertEquals(0, trackedJobs.get(3).size());

            flexTracker.adjustJobsRequiredConstraints(jobs[0], -2);
            flexTracker.adjustJobsRequiredConstraints(jobs[0], -2, FROZEN_TIME);

            assertEquals(1, trackedJobs.get(0).size());
            assertEquals(0, trackedJobs.get(1).size());
            assertEquals(1, trackedJobs.get(2).size());
            assertEquals(0, trackedJobs.get(3).size());

            final long nowElapsed = ((DEFAULT_FALLBACK_FLEXIBILITY_DEADLINE_MS / 2)
                    + HOUR_IN_MILLIS);
            JobSchedulerService.sElapsedRealtimeClock =
                    Clock.fixed(Instant.ofEpochMilli((DEFAULT_FALLBACK_FLEXIBILITY_DEADLINE_MS / 2)
                            + HOUR_IN_MILLIS), ZoneOffset.UTC);
                    Clock.fixed(Instant.ofEpochMilli(nowElapsed), ZoneOffset.UTC);

            flexTracker.resetJobNumDroppedConstraints(jobs[0]);
            flexTracker.resetJobNumDroppedConstraints(jobs[0], nowElapsed);
            assertEquals(0, trackedJobs.get(0).size());
            assertEquals(1, trackedJobs.get(1).size());
            assertEquals(1, trackedJobs.get(2).size());
@@ -615,13 +625,13 @@ public class FlexibilityControllerTest {

    @Test
    public void testSetConstraintSatisfied_Constraints() {
        mFlexibilityController.setConstraintSatisfied(CONSTRAINT_IDLE, false);
        mFlexibilityController.setConstraintSatisfied(CONSTRAINT_IDLE, false, FROZEN_TIME);
        assertFalse(mFlexibilityController.isConstraintSatisfied(CONSTRAINT_IDLE));

        mFlexibilityController.setConstraintSatisfied(CONSTRAINT_IDLE, true);
        mFlexibilityController.setConstraintSatisfied(CONSTRAINT_IDLE, true, FROZEN_TIME);
        assertTrue(mFlexibilityController.isConstraintSatisfied(CONSTRAINT_IDLE));

        mFlexibilityController.setConstraintSatisfied(CONSTRAINT_IDLE, false);
        mFlexibilityController.setConstraintSatisfied(CONSTRAINT_IDLE, false, FROZEN_TIME);
        assertFalse(mFlexibilityController.isConstraintSatisfied(CONSTRAINT_IDLE));
    }

@@ -651,20 +661,21 @@ public class FlexibilityControllerTest {
                        createJobStatus(String.valueOf(i), jb), null);
            }
        }
        mFlexibilityController.setConstraintSatisfied(CONSTRAINT_CHARGING, false);
        mFlexibilityController.setConstraintSatisfied(CONSTRAINT_IDLE, false);
        mFlexibilityController.setConstraintSatisfied(CONSTRAINT_BATTERY_NOT_LOW, false);
        mFlexibilityController.setConstraintSatisfied(CONSTRAINT_CHARGING, false, FROZEN_TIME);
        mFlexibilityController.setConstraintSatisfied(CONSTRAINT_IDLE, false, FROZEN_TIME);
        mFlexibilityController.setConstraintSatisfied(
                CONSTRAINT_BATTERY_NOT_LOW, false, FROZEN_TIME);

        assertEquals(0, mFlexibilityController.mSatisfiedFlexibleConstraints);

        for (int i = 0; i < constraintCombinations.length; i++) {
            constraints = constraintCombinations[i];
            mFlexibilityController.setConstraintSatisfied(CONSTRAINT_CHARGING,
                    (constraints & CONSTRAINT_CHARGING) != 0);
                    (constraints & CONSTRAINT_CHARGING) != 0, FROZEN_TIME);
            mFlexibilityController.setConstraintSatisfied(CONSTRAINT_IDLE,
                    (constraints & CONSTRAINT_IDLE) != 0);
                    (constraints & CONSTRAINT_IDLE) != 0, FROZEN_TIME);
            mFlexibilityController.setConstraintSatisfied(CONSTRAINT_BATTERY_NOT_LOW,
                    (constraints & CONSTRAINT_BATTERY_NOT_LOW) != 0);
                    (constraints & CONSTRAINT_BATTERY_NOT_LOW) != 0, FROZEN_TIME);

            assertEquals(constraints, mFlexibilityController.mSatisfiedFlexibleConstraints);
            synchronized (mFlexibilityController.mLock) {
@@ -679,6 +690,7 @@ public class FlexibilityControllerTest {
        JobInfo.Builder jb = createJob(22).setOverrideDeadline(100L);
        JobStatus js = createJobStatus("testResetJobNumDroppedConstraints", jb);
        js.adjustNumRequiredFlexibleConstraints(3);
        long nowElapsed;

        mFlexibilityController.mFlexibilityTracker.add(js);

@@ -687,45 +699,51 @@ public class FlexibilityControllerTest {
        assertEquals(1, mFlexibilityController
                .mFlexibilityTracker.getJobsByNumRequiredConstraints(3).size());


        nowElapsed = 155L;
        JobSchedulerService.sElapsedRealtimeClock =
                Clock.fixed(Instant.ofEpochMilli(155L), ZoneOffset.UTC);
                Clock.fixed(Instant.ofEpochMilli(nowElapsed), ZoneOffset.UTC);

        mFlexibilityController.mFlexibilityTracker.adjustJobsRequiredConstraints(js, -1);
        mFlexibilityController.mFlexibilityTracker
                .adjustJobsRequiredConstraints(js, -1, nowElapsed);

        assertEquals(2, js.getNumRequiredFlexibleConstraints());
        assertEquals(1, js.getNumDroppedFlexibleConstraints());
        assertEquals(1, mFlexibilityController
                .mFlexibilityTracker.getJobsByNumRequiredConstraints(2).size());

        mFlexibilityController.mFlexibilityTracker.resetJobNumDroppedConstraints(js);
        mFlexibilityController.mFlexibilityTracker.resetJobNumDroppedConstraints(js, nowElapsed);

        assertEquals(2, js.getNumRequiredFlexibleConstraints());
        assertEquals(1, js.getNumDroppedFlexibleConstraints());
        assertEquals(1, mFlexibilityController
                .mFlexibilityTracker.getJobsByNumRequiredConstraints(2).size());

        nowElapsed = 140L;
        JobSchedulerService.sElapsedRealtimeClock =
                Clock.fixed(Instant.ofEpochMilli(140L), ZoneOffset.UTC);
                Clock.fixed(Instant.ofEpochMilli(nowElapsed), ZoneOffset.UTC);

        mFlexibilityController.mFlexibilityTracker.resetJobNumDroppedConstraints(js);
        mFlexibilityController.mFlexibilityTracker.resetJobNumDroppedConstraints(js, nowElapsed);

        assertEquals(3, js.getNumRequiredFlexibleConstraints());
        assertEquals(0, js.getNumDroppedFlexibleConstraints());
        assertEquals(1, mFlexibilityController
                .mFlexibilityTracker.getJobsByNumRequiredConstraints(3).size());

        nowElapsed = 175L;
        JobSchedulerService.sElapsedRealtimeClock =
                Clock.fixed(Instant.ofEpochMilli(175), ZoneOffset.UTC);
                Clock.fixed(Instant.ofEpochMilli(nowElapsed), ZoneOffset.UTC);

        mFlexibilityController.mFlexibilityTracker.resetJobNumDroppedConstraints(js);
        mFlexibilityController.mFlexibilityTracker.resetJobNumDroppedConstraints(js, nowElapsed);

        assertEquals(0, js.getNumRequiredFlexibleConstraints());
        assertEquals(3, js.getNumDroppedFlexibleConstraints());

        nowElapsed = 165L;
        JobSchedulerService.sElapsedRealtimeClock =
                Clock.fixed(Instant.ofEpochMilli(165L), ZoneOffset.UTC);
                Clock.fixed(Instant.ofEpochMilli(nowElapsed), ZoneOffset.UTC);

        mFlexibilityController.mFlexibilityTracker.resetJobNumDroppedConstraints(js);
        mFlexibilityController.mFlexibilityTracker.resetJobNumDroppedConstraints(js, nowElapsed);

        assertEquals(1, js.getNumRequiredFlexibleConstraints());
        assertEquals(2, js.getNumDroppedFlexibleConstraints());
@@ -745,12 +763,14 @@ public class FlexibilityControllerTest {

        mFlexibilityController.maybeStartTrackingJobLocked(js, null);

        final long nowElapsed = 150L;
        JobSchedulerService.sElapsedRealtimeClock =
                Clock.fixed(Instant.ofEpochMilli(150L), ZoneOffset.UTC);
                Clock.fixed(Instant.ofEpochMilli(nowElapsed), ZoneOffset.UTC);

        mFlexibilityController.mPrefetchChangedListener.onPrefetchCacheUpdated(
                jobs, js.getUserId(), js.getSourcePackageName(), Long.MAX_VALUE,
                1150L + mFlexibilityController.mConstants.PREFETCH_FORCE_BATCH_RELAX_THRESHOLD_MS);
                1150L + mFlexibilityController.mConstants.PREFETCH_FORCE_BATCH_RELAX_THRESHOLD_MS,
                nowElapsed);

        assertEquals(150L,
                (long) mFlexibilityController.mPrefetchLifeCycleStart
@@ -758,7 +778,7 @@ public class FlexibilityControllerTest {
        assertEquals(150L, mFlexibilityController.getLifeCycleBeginningElapsedLocked(js));
        assertEquals(1150L,
                mFlexibilityController.getLifeCycleEndElapsedLocked(js, 150L));
        assertEquals(0, mFlexibilityController.getCurPercentOfLifecycleLocked(js));
        assertEquals(0, mFlexibilityController.getCurPercentOfLifecycleLocked(js, FROZEN_TIME));
        assertEquals(650L, mFlexibilityController
                .getNextConstraintDropTimeElapsedLocked(js));
        assertEquals(3, js.getNumRequiredFlexibleConstraints());
Loading