From b1d6448ec4f9af79776cc2e9eb951b659212b0bb Mon Sep 17 00:00:00 2001 From: Christopher Tate Date: Wed, 15 Mar 2017 12:01:22 -0700 Subject: [PATCH] Correctly check expired jobs against active ones If a job was run before its deadline, and then the deadline landed while the job was still running, b/c of the 'deadline trumps all' it would be considered eligible to run again as soon as the previous iteration completed. Fix this by checking against the state of the active queue. Bug 36253320 Test: CTS: job scheduler TimingConstraintsTest Change-Id: I4f0c1012091bf88776cfe725d7b59f6dcf602c02 --- .../server/job/JobSchedulerService.java | 24 +++++++++++++++---- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java index b316a3bd06393..940f621a47d16 100644 --- a/services/core/java/com/android/server/job/JobSchedulerService.java +++ b/services/core/java/com/android/server/job/JobSchedulerService.java @@ -1106,8 +1106,7 @@ public final class JobSchedulerService extends com.android.server.SystemService JobStatus runNow = (JobStatus) message.obj; // runNow can be null, which is a controller's way of indicating that its // state is such that all ready jobs should be run immediately. - if (runNow != null && !mPendingJobs.contains(runNow) - && mJobs.containsJob(runNow)) { + if (runNow != null && isReadyToBeExecutedLocked(runNow)) { mJobPackageTracker.notePending(runNow); mPendingJobs.add(runNow); } @@ -1310,12 +1309,27 @@ public final class JobSchedulerService extends com.android.server.SystemService * - The component is enabled and runnable. */ private boolean isReadyToBeExecutedLocked(JobStatus job) { + final boolean jobExists = mJobs.containsJob(job); final boolean jobReady = job.isReady(); final boolean jobPending = mPendingJobs.contains(job); final boolean jobActive = isCurrentlyActiveLocked(job); final int userId = job.getUserId(); final boolean userStarted = ArrayUtils.contains(mStartedUsers, userId); + + if (DEBUG) { + Slog.v(TAG, "isReadyToBeExecutedLocked: " + job.toShortString() + + " exists=" + jobExists + + " ready=" + jobReady + " pending=" + jobPending + + " active=" + jobActive + " userStarted=" + userStarted); + } + + // Short circuit: don't do the expensive PM check unless we really think + // we might need to run this job now. + if (!jobExists || !userStarted || !jobReady || jobPending || jobActive) { + return false; + } + final boolean componentPresent; try { componentPresent = (AppGlobals.getPackageManager().getServiceInfo( @@ -1327,11 +1341,11 @@ public final class JobSchedulerService extends com.android.server.SystemService if (DEBUG) { Slog.v(TAG, "isReadyToBeExecutedLocked: " + job.toShortString() - + " ready=" + jobReady + " pending=" + jobPending - + " active=" + jobActive + " userStarted=" + userStarted + " componentPresent=" + componentPresent); } - return userStarted && componentPresent && jobReady && !jobPending && !jobActive; + + // Everything else checked out so far, so this is the final yes/no check + return componentPresent; } /**