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

Commit 09e1810c authored by Kweku Adams's avatar Kweku Adams
Browse files

Make sure all jobs are sorted by override state.

Override state is only set via adb, which means its used for testing job
execution. Make sure we put jobs under test at the front of the queue to
avoid issues with execution delay.

Bug: 141645789
Bug: 223437753
Test: atest FrameworksServicesTests:PendingJobQueueTest
Change-Id: Icc4788117c46ada49c030f82f26affbd56e6ef69
parent b0ea1d0b
Loading
Loading
Loading
Loading
+20 −10
Original line number Diff line number Diff line
@@ -54,6 +54,13 @@ class PendingJobQueue {
                } else if (t2 == AppJobQueue.NO_NEXT_TIMESTAMP) {
                    return -1;
                }
                final int o1 = ajq1.peekNextOverrideState();
                final int o2 = ajq2.peekNextOverrideState();
                if (o1 != o2) {
                    // Higher override state (OVERRIDE_FULL) should be before lower state
                    // (OVERRIDE_SOFT)
                    return Integer.compare(o2, o1);
                }
                return Long.compare(t1, t2);
            });

@@ -185,6 +192,7 @@ class PendingJobQueue {

    private static final class AppJobQueue {
        static final long NO_NEXT_TIMESTAMP = -1L;
        static final int NO_NEXT_OVERRIDE_STATE = -1;

        private static class AdjustedJobStatus {
            public long adjustedEnqueueTime;
@@ -207,7 +215,7 @@ class PendingJobQueue {
            if (job1.overrideState != job2.overrideState) {
                // Higher override state (OVERRIDE_FULL) should be before lower state
                // (OVERRIDE_SOFT)
                return job2.overrideState - job1.overrideState;
                return Integer.compare(job2.overrideState, job1.overrideState);
            }

            final boolean job1EJ = job1.isRequestedExpeditedJob();
@@ -223,18 +231,15 @@ class PendingJobQueue {
            if (job1Priority != job2Priority) {
                // Use the priority set by an app for intra-app job ordering. Higher
                // priority should be before lower priority.
                return job2Priority - job1Priority;
                return Integer.compare(job2Priority, job1Priority);
            }

            if (job1.lastEvaluatedBias != job2.lastEvaluatedBias) {
                // Higher bias should go first.
                return job2.lastEvaluatedBias - job1.lastEvaluatedBias;
                return Integer.compare(job2.lastEvaluatedBias, job1.lastEvaluatedBias);
            }

            if (job1.enqueueTime < job2.enqueueTime) {
                return -1;
            }
            return job1.enqueueTime > job2.enqueueTime ? 1 : 0;
            return Long.compare(job1.enqueueTime, job2.enqueueTime);
        };

        private static final Pools.Pool<AdjustedJobStatus> mAdjustedJobStatusPool =
@@ -344,9 +349,14 @@ class PendingJobQueue {
            if (mCurIndex >= mJobs.size()) {
                return null;
            }
            JobStatus next = mJobs.get(mCurIndex).job;
            mCurIndex++;
            return next;
            return mJobs.get(mCurIndex++).job;
        }

        int peekNextOverrideState() {
            if (mCurIndex >= mJobs.size()) {
                return NO_NEXT_OVERRIDE_STATE;
            }
            return mJobs.get(mCurIndex).job.overrideState;
        }

        long peekNextTimestamp() {
+14 −18
Original line number Diff line number Diff line
@@ -28,7 +28,6 @@ import android.platform.test.annotations.LargeTest;
import android.util.Log;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
import android.util.SparseIntArray;
import android.util.SparseLongArray;

import com.android.server.job.controllers.JobStatus;
@@ -371,38 +370,34 @@ public class PendingJobQueueTest {

    private void checkPendingJobInvariants(PendingJobQueue jobQueue) {
        final SparseBooleanArray regJobSeen = new SparseBooleanArray();
        final SparseIntArray lastOverrideStateSeen = new SparseIntArray();
        // Latest priority enqueue times seen for each priority for each app.
        final SparseArray<SparseLongArray> latestPriorityRegEnqueueTimesPerUid =
                new SparseArray<>();
        final SparseArray<SparseLongArray> latestPriorityEjEnqueueTimesPerUid = new SparseArray<>();
        final int noEntry = -1;
        int prevOverrideState = noEntry;

        JobStatus job;
        jobQueue.resetIterator();
        while ((job = jobQueue.next()) != null) {
            final int uid = job.getSourceUid();

            // Invariant #1: All jobs (for a UID) are sorted by override state
            // Invariant #1: All jobs are sorted by override state
            // Invariant #2: All jobs (for a UID) are sorted by priority order
            // Invariant #3: Jobs (for a UID) with the same priority are sorted by enqueue time.
            // Invariant #4: EJs (for a UID) should be before regular jobs

            final int prevOverrideState = lastOverrideStateSeen.get(uid, noEntry);
            lastOverrideStateSeen.put(uid, job.overrideState);
            if (prevOverrideState == noEntry) {
                // First job for UID
                continue;
            }

            // Invariant 1
            if (prevOverrideState != job.overrideState) {
                if (prevOverrideState != noEntry) {
                    assertTrue(prevOverrideState > job.overrideState);
                // Override state can make ordering weird. Clear the other cached states for this
                // UID to avoid confusion in the other checks.
                latestPriorityEjEnqueueTimesPerUid.remove(uid);
                latestPriorityRegEnqueueTimesPerUid.remove(uid);
                regJobSeen.delete(uid);
                }
                // Override state can make ordering weird. Clear the other cached states
                // to avoid confusion in the other checks.
                latestPriorityEjEnqueueTimesPerUid.clear();
                latestPriorityRegEnqueueTimesPerUid.clear();
                regJobSeen.clear();
                prevOverrideState = job.overrideState;
            }

            final int priority = job.getEffectivePriority();
@@ -423,8 +418,9 @@ public class PendingJobQueueTest {
                final long lastSeenPriorityEnqueueTime =
                        latestPriorityEnqueueTimes.get(priority, noEntry);
                if (lastSeenPriorityEnqueueTime != noEntry) {
                    assertTrue("Jobs with same priority not sorted by enqueue time: "
                                    + lastSeenPriorityEnqueueTime + " vs " + job.enqueueTime,
                    assertTrue("Jobs with same priority for uid " + uid
                                    + " not sorted by enqueue time: "
                                    + lastSeenPriorityEnqueueTime + " before " + job.enqueueTime,
                            lastSeenPriorityEnqueueTime <= job.enqueueTime);
                }
            } else {