diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java index 819f253e0c19a..07a99084e9d5d 100644 --- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java +++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java @@ -746,7 +746,13 @@ public class JobSchedulerService extends com.android.server.SystemService final Constants mConstants; final ConstantsObserver mConstantsObserver; - static final Comparator mEnqueueTimeComparator = (o1, o2) -> { + private static final Comparator sPendingJobComparator = (o1, o2) -> { + // Jobs with an override state set (via adb) should be put first as tests/developers + // expect the jobs to run immediately. + if (o1.overrideState != o2.overrideState) { + // Higher override state (OVERRIDE_FULL) should be before lower state (OVERRIDE_SOFT) + return o2.overrideState - o1.overrideState; + } if (o1.enqueueTime < o2.enqueueTime) { return -1; } @@ -1097,7 +1103,7 @@ public class JobSchedulerService extends com.android.server.SystemService // This is a new job, we can just immediately put it on the pending // list and try to run it. mJobPackageTracker.notePending(jobStatus); - addOrderedItem(mPendingJobs, jobStatus, mEnqueueTimeComparator); + addOrderedItem(mPendingJobs, jobStatus, sPendingJobComparator); maybeRunPendingJobsLocked(); } else { evaluateControllerStatesLocked(jobStatus); @@ -1858,7 +1864,7 @@ public class JobSchedulerService extends com.android.server.SystemService // state is such that all ready jobs should be run immediately. if (runNow != null && isReadyToBeExecutedLocked(runNow)) { mJobPackageTracker.notePending(runNow); - addOrderedItem(mPendingJobs, runNow, mEnqueueTimeComparator); + addOrderedItem(mPendingJobs, runNow, sPendingJobComparator); } else { queueReadyJobsForExecutionLocked(); } @@ -2030,7 +2036,7 @@ public class JobSchedulerService extends com.android.server.SystemService noteJobsPending(newReadyJobs); mPendingJobs.addAll(newReadyJobs); if (mPendingJobs.size() > 1) { - mPendingJobs.sort(mEnqueueTimeComparator); + mPendingJobs.sort(sPendingJobComparator); } newReadyJobs.clear(); @@ -2107,7 +2113,7 @@ public class JobSchedulerService extends com.android.server.SystemService noteJobsPending(runnableJobs); mPendingJobs.addAll(runnableJobs); if (mPendingJobs.size() > 1) { - mPendingJobs.sort(mEnqueueTimeComparator); + mPendingJobs.sort(sPendingJobComparator); } } else { if (DEBUG) { @@ -2813,11 +2819,9 @@ public class JobSchedulerService extends com.android.server.SystemService } // Shell command infrastructure: run the given job immediately - int executeRunCommand(String pkgName, int userId, int jobId, boolean force) { - if (DEBUG) { - Slog.v(TAG, "executeRunCommand(): " + pkgName + "/" + userId - + " " + jobId + " f=" + force); - } + int executeRunCommand(String pkgName, int userId, int jobId, boolean satisfied, boolean force) { + Slog.d(TAG, "executeRunCommand(): " + pkgName + "/" + userId + + " " + jobId + " s=" + satisfied + " f=" + force); try { final int uid = AppGlobals.getPackageManager().getPackageUid(pkgName, 0, @@ -2832,7 +2836,8 @@ public class JobSchedulerService extends com.android.server.SystemService return JobSchedulerShellCommand.CMD_ERR_NO_JOB; } - js.overrideState = (force) ? JobStatus.OVERRIDE_FULL : JobStatus.OVERRIDE_SOFT; + js.overrideState = (force) ? JobStatus.OVERRIDE_FULL + : (satisfied ? JobStatus.OVERRIDE_SORTING : JobStatus.OVERRIDE_SOFT); // Re-evaluate constraints after the override is set in case one of the overridden // constraints was preventing another constraint from thinking it needed to update. @@ -2841,7 +2846,7 @@ public class JobSchedulerService extends com.android.server.SystemService } if (!js.isConstraintsSatisfied()) { - js.overrideState = 0; + js.overrideState = JobStatus.OVERRIDE_NONE; return JobSchedulerShellCommand.CMD_ERR_CONSTRAINTS; } diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerShellCommand.java b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerShellCommand.java index 957170890a8f3..1e7206287566b 100644 --- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerShellCommand.java +++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerShellCommand.java @@ -136,6 +136,7 @@ public final class JobSchedulerShellCommand extends BasicShellCommandHandler { checkPermission("force scheduled jobs"); boolean force = false; + boolean satisfied = false; int userId = UserHandle.USER_SYSTEM; String opt; @@ -146,6 +147,11 @@ public final class JobSchedulerShellCommand extends BasicShellCommandHandler { force = true; break; + case "-s": + case "--satisfied": + satisfied = true; + break; + case "-u": case "--user": userId = Integer.parseInt(getNextArgRequired()); @@ -157,12 +163,17 @@ public final class JobSchedulerShellCommand extends BasicShellCommandHandler { } } + if (force && satisfied) { + pw.println("Cannot specify both --force and --satisfied"); + return -1; + } + final String pkgName = getNextArgRequired(); final int jobId = Integer.parseInt(getNextArgRequired()); final long ident = Binder.clearCallingIdentity(); try { - int ret = mInternal.executeRunCommand(pkgName, userId, jobId, force); + int ret = mInternal.executeRunCommand(pkgName, userId, jobId, satisfied, force); if (printError(ret, pkgName, userId, jobId)) { return ret; } @@ -424,11 +435,18 @@ public final class JobSchedulerShellCommand extends BasicShellCommandHandler { pw.println("Job scheduler (jobscheduler) commands:"); pw.println(" help"); pw.println(" Print this help text."); - pw.println(" run [-f | --force] [-u | --user USER_ID] PACKAGE JOB_ID"); - pw.println(" Trigger immediate execution of a specific scheduled job."); + pw.println(" run [-f | --force] [-s | --satisfied] [-u | --user USER_ID] PACKAGE JOB_ID"); + pw.println(" Trigger immediate execution of a specific scheduled job. For historical"); + pw.println(" reasons, some constraints, such as battery, are ignored when this"); + pw.println(" command is called. If you don't want any constraints to be ignored,"); + pw.println(" include the -s flag."); pw.println(" Options:"); pw.println(" -f or --force: run the job even if technical constraints such as"); - pw.println(" connectivity are not currently met"); + pw.println(" connectivity are not currently met. This is incompatible with -f "); + pw.println(" and so an error will be reported if both are given."); + pw.println(" -s or --satisfied: run the job only if all constraints are met."); + pw.println(" This is incompatible with -f and so an error will be reported"); + pw.println(" if both are given."); pw.println(" -u or --user: specify which user's job is to be run; the default is"); pw.println(" the primary or system user"); pw.println(" timeout [-u | --user USER_ID] [PACKAGE] [JOB_ID]"); 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 81dbc873fa576..d7c6ddbb0c63e 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 @@ -131,10 +131,14 @@ public final class JobStatus { // TODO(b/129954980) private static final boolean STATS_LOG_ENABLED = false; + // No override. + public static final int OVERRIDE_NONE = 0; + // Override to improve sorting order. Does not affect constraint evaluation. + public static final int OVERRIDE_SORTING = 1; // Soft override: ignore constraints like time that don't affect API availability - public static final int OVERRIDE_SOFT = 1; + public static final int OVERRIDE_SOFT = 2; // Full override: ignore all constraints including API-affecting like connectivity - public static final int OVERRIDE_FULL = 2; + public static final int OVERRIDE_FULL = 3; /** If not specified, trigger update delay is 10 seconds. */ public static final long DEFAULT_TRIGGER_UPDATE_DELAY = 10*1000; @@ -304,7 +308,7 @@ public final class JobStatus { public int nextPendingWorkId = 1; // Used by shell commands - public int overrideState = 0; + public int overrideState = JobStatus.OVERRIDE_NONE; // When this job was enqueued, for ordering. (in elapsedRealtimeMillis) public long enqueueTime;