Loading apex/jobscheduler/framework/java/android/app/job/JobInfo.java +60 −49 Original line number Diff line number Diff line Loading @@ -207,62 +207,65 @@ public class JobInfo implements Parcelable { public static final int DEFAULT_BACKOFF_POLICY = BACKOFF_POLICY_EXPONENTIAL; /** * Default of {@link #getPriority}. * Default of {@link #getBias}. * @hide */ public static final int PRIORITY_DEFAULT = 0; public static final int BIAS_DEFAULT = 0; /** * Value of {@link #getPriority} for expedited syncs. * Value of {@link #getBias} for expedited syncs. * @hide */ public static final int PRIORITY_SYNC_EXPEDITED = 10; public static final int BIAS_SYNC_EXPEDITED = 10; /** * Value of {@link #getPriority} for first time initialization syncs. * Value of {@link #getBias} for first time initialization syncs. * @hide */ public static final int PRIORITY_SYNC_INITIALIZATION = 20; public static final int BIAS_SYNC_INITIALIZATION = 20; /** * Value of {@link #getPriority} for a BFGS app (overrides the supplied * JobInfo priority if it is smaller). * Value of {@link #getBias} for a BFGS app (overrides the supplied * JobInfo bias if it is smaller). * @hide */ public static final int PRIORITY_BOUND_FOREGROUND_SERVICE = 30; public static final int BIAS_BOUND_FOREGROUND_SERVICE = 30; /** @hide For backward compatibility. */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public static final int PRIORITY_FOREGROUND_APP = PRIORITY_BOUND_FOREGROUND_SERVICE; public static final int PRIORITY_FOREGROUND_APP = BIAS_BOUND_FOREGROUND_SERVICE; /** * Value of {@link #getPriority} for a FG service app (overrides the supplied * JobInfo priority if it is smaller). * Value of {@link #getBias} for a FG service app (overrides the supplied * JobInfo bias if it is smaller). * @hide */ public static final int BIAS_FOREGROUND_SERVICE = 35; /** @hide For backward compatibility. */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public static final int PRIORITY_FOREGROUND_SERVICE = 35; public static final int PRIORITY_FOREGROUND_SERVICE = BIAS_FOREGROUND_SERVICE; /** * Value of {@link #getPriority} for the current top app (overrides the supplied * JobInfo priority if it is smaller). * Value of {@link #getBias} for the current top app (overrides the supplied * JobInfo bias if it is smaller). * @hide */ public static final int PRIORITY_TOP_APP = 40; public static final int BIAS_TOP_APP = 40; /** * Adjustment of {@link #getPriority} if the app has often (50% or more of the time) * Adjustment of {@link #getBias} if the app has often (50% or more of the time) * been running jobs. * @hide */ public static final int PRIORITY_ADJ_OFTEN_RUNNING = -40; public static final int BIAS_ADJ_OFTEN_RUNNING = -40; /** * Adjustment of {@link #getPriority} if the app has always (90% or more of the time) * Adjustment of {@link #getBias} if the app has always (90% or more of the time) * been running jobs. * @hide */ public static final int PRIORITY_ADJ_ALWAYS_RUNNING = -80; public static final int BIAS_ADJ_ALWAYS_RUNNING = -80; /** * Indicates that the implementation of this job will be using Loading Loading @@ -355,7 +358,7 @@ public class JobInfo implements Parcelable { private final long flexMillis; private final long initialBackoffMillis; private final int backoffPolicy; private final int priority; private final int mBias; @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) private final int flags; Loading Loading @@ -403,8 +406,8 @@ public class JobInfo implements Parcelable { } /** @hide */ public int getPriority() { return priority; public int getBias() { return mBias; } /** @hide */ Loading Loading @@ -740,7 +743,7 @@ public class JobInfo implements Parcelable { if (backoffPolicy != j.backoffPolicy) { return false; } if (priority != j.priority) { if (mBias != j.mBias) { return false; } if (flags != j.flags) { Loading Loading @@ -787,7 +790,7 @@ public class JobInfo implements Parcelable { hashCode = 31 * hashCode + Long.hashCode(flexMillis); hashCode = 31 * hashCode + Long.hashCode(initialBackoffMillis); hashCode = 31 * hashCode + backoffPolicy; hashCode = 31 * hashCode + priority; hashCode = 31 * hashCode + mBias; hashCode = 31 * hashCode + flags; return hashCode; } Loading Loading @@ -826,7 +829,7 @@ public class JobInfo implements Parcelable { backoffPolicy = in.readInt(); hasEarlyConstraint = in.readInt() == 1; hasLateConstraint = in.readInt() == 1; priority = in.readInt(); mBias = in.readInt(); flags = in.readInt(); } Loading Loading @@ -857,7 +860,7 @@ public class JobInfo implements Parcelable { backoffPolicy = b.mBackoffPolicy; hasEarlyConstraint = b.mHasEarlyConstraint; hasLateConstraint = b.mHasLateConstraint; priority = b.mPriority; mBias = b.mBias; flags = b.mFlags; } Loading Loading @@ -902,7 +905,7 @@ public class JobInfo implements Parcelable { out.writeInt(backoffPolicy); out.writeInt(hasEarlyConstraint ? 1 : 0); out.writeInt(hasLateConstraint ? 1 : 0); out.writeInt(priority); out.writeInt(mBias); out.writeInt(this.flags); } Loading Loading @@ -1020,7 +1023,7 @@ public class JobInfo implements Parcelable { private Bundle mTransientExtras = Bundle.EMPTY; private ClipData mClipData; private int mClipGrantFlags; private int mPriority = PRIORITY_DEFAULT; private int mBias = BIAS_DEFAULT; private int mFlags; // Requirements. private int mConstraintFlags; Loading Loading @@ -1074,7 +1077,7 @@ public class JobInfo implements Parcelable { mTransientExtras = job.getTransientExtras(); mClipData = job.getClipData(); mClipGrantFlags = job.getClipGrantFlags(); mPriority = job.getPriority(); mBias = job.getBias(); mFlags = job.getFlags(); mConstraintFlags = job.getConstraintFlags(); mNetworkRequest = job.getRequiredNetwork(); Loading @@ -1099,10 +1102,18 @@ public class JobInfo implements Parcelable { mBackoffPolicy = job.getBackoffPolicy(); } /** @hide */ @NonNull public Builder setBias(int bias) { mBias = bias; return this; } /** @hide */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public Builder setPriority(int priority) { mPriority = priority; // No-op for invalid calls. This wasn't a supported API before Tiramisu, so anyone // calling this that isn't targeting T isn't guaranteed a behavior change. return this; } Loading Loading @@ -1829,27 +1840,27 @@ public class JobInfo implements Parcelable { } /** * Convert a priority integer into a human readable string for debugging. * Convert a bias integer into a human readable string for debugging. * @hide */ public static String getPriorityString(int priority) { switch (priority) { case PRIORITY_DEFAULT: return PRIORITY_DEFAULT + " [DEFAULT]"; case PRIORITY_SYNC_EXPEDITED: return PRIORITY_SYNC_EXPEDITED + " [SYNC_EXPEDITED]"; case PRIORITY_SYNC_INITIALIZATION: return PRIORITY_SYNC_INITIALIZATION + " [SYNC_INITIALIZATION]"; case PRIORITY_BOUND_FOREGROUND_SERVICE: return PRIORITY_BOUND_FOREGROUND_SERVICE + " [BFGS_APP]"; case PRIORITY_FOREGROUND_SERVICE: return PRIORITY_FOREGROUND_SERVICE + " [FGS_APP]"; case PRIORITY_TOP_APP: return PRIORITY_TOP_APP + " [TOP_APP]"; // PRIORITY_ADJ_* are adjustments and not used as real priorities. public static String getBiasString(int bias) { switch (bias) { case BIAS_DEFAULT: return BIAS_DEFAULT + " [DEFAULT]"; case BIAS_SYNC_EXPEDITED: return BIAS_SYNC_EXPEDITED + " [SYNC_EXPEDITED]"; case BIAS_SYNC_INITIALIZATION: return BIAS_SYNC_INITIALIZATION + " [SYNC_INITIALIZATION]"; case BIAS_BOUND_FOREGROUND_SERVICE: return BIAS_BOUND_FOREGROUND_SERVICE + " [BFGS_APP]"; case BIAS_FOREGROUND_SERVICE: return BIAS_FOREGROUND_SERVICE + " [FGS_APP]"; case BIAS_TOP_APP: return BIAS_TOP_APP + " [TOP_APP]"; // BIAS_ADJ_* are adjustments and not used as real priorities. // No need to convert to strings. } return priority + " [UNKNOWN]"; return bias + " [UNKNOWN]"; } } apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java +47 −51 Original line number Diff line number Diff line Loading @@ -86,7 +86,7 @@ class JobConcurrencyManager { /** * Set of possible execution types that a job can have. The actual type(s) of a job are based * on the {@link JobStatus#lastEvaluatedPriority}, which is typically evaluated right before * on the {@link JobStatus#lastEvaluatedBias}, which is typically evaluated right before * execution (when we're trying to determine which jobs to run next) and won't change after the * job has started executing. * Loading Loading @@ -527,9 +527,8 @@ class JobConcurrencyManager { /** * Takes jobs from pending queue and runs them on available contexts. * If no contexts are available, preempts lower priority jobs to * run higher priority ones. * Lock on mJobs before calling this function. * If no contexts are available, preempts lower bias jobs to run higher bias ones. * Lock on mLock before calling this function. */ @GuardedBy("mLock") void assignJobsToContextsLocked() { Loading Loading @@ -596,9 +595,9 @@ class JobConcurrencyManager { } // Find an available slot for nextPending. The context should be available OR // it should have lowest priority among all running jobs // it should have the lowest bias among all running jobs // (sharing the same Uid as nextPending) int minPriorityForPreemption = Integer.MAX_VALUE; int minBiasForPreemption = Integer.MAX_VALUE; int selectedContextId = -1; int allWorkTypes = getJobWorkTypes(nextPending); int workType = mWorkCountTracker.canJobStart(allWorkTypes); Loading Loading @@ -631,7 +630,7 @@ class JobConcurrencyManager { // Maybe stop the job if it has had its day in the sun. Don't let a different // app preempt jobs started for TOP apps though. final String reason = shouldStopJobReason[j]; if (job.lastEvaluatedPriority < JobInfo.PRIORITY_TOP_APP if (job.lastEvaluatedBias < JobInfo.BIAS_TOP_APP && reason != null && mWorkCountTracker.canJobStart(allWorkTypes, activeServices.get(j).getRunningJobWorkType()) != WORK_TYPE_NONE) { // Right now, the way the code is set up, we don't need to explicitly Loading @@ -643,19 +642,19 @@ class JobConcurrencyManager { continue; } final int jobPriority = mService.evaluateJobPriorityLocked(job); if (jobPriority >= nextPending.lastEvaluatedPriority) { final int jobBias = mService.evaluateJobBiasLocked(job); if (jobBias >= nextPending.lastEvaluatedBias) { continue; } if (minPriorityForPreemption > jobPriority) { if (minBiasForPreemption > jobBias) { // Step down the preemption threshold - wind up replacing // the lowest-priority running job minPriorityForPreemption = jobPriority; // the lowest-bias running job minBiasForPreemption = jobBias; selectedContextId = j; preemptReason = "higher priority job found"; preemptReason = "higher bias job found"; preemptReasonCode = JobParameters.STOP_REASON_PREEMPT; // In this case, we're just going to preempt a low priority job, we're not // In this case, we're just going to preempt a low bias job, we're not // actually starting a job, so don't set startingJob. } } Loading Loading @@ -749,7 +748,7 @@ class JobConcurrencyManager { continue; } pending.lastEvaluatedPriority = mService.evaluateJobPriorityLocked(pending); pending.lastEvaluatedBias = mService.evaluateJobBiasLocked(pending); if (updateCounter) { mWorkCountTracker.incrementPendingJobCount(getJobWorkTypes(pending)); Loading @@ -773,7 +772,7 @@ class JobConcurrencyManager { @GuardedBy("mLock") private boolean isPkgConcurrencyLimitedLocked(@NonNull JobStatus jobStatus) { if (jobStatus.lastEvaluatedPriority >= JobInfo.PRIORITY_TOP_APP) { if (jobStatus.lastEvaluatedBias >= JobInfo.BIAS_TOP_APP) { // Don't restrict top apps' concurrency. The work type limits will make sure // background jobs have slots to run if the system has resources. return false; Loading Loading @@ -866,9 +865,9 @@ class JobConcurrencyManager { // Preemption case needs special care. updateNonRunningPrioritiesLocked(pendingJobs, false); JobStatus highestPriorityJob = null; int highPriWorkType = workType; int highPriAllWorkTypes = workType; JobStatus highestBiasJob = null; int highBiasWorkType = workType; int highBiasAllWorkTypes = workType; JobStatus backupJob = null; int backupWorkType = WORK_TYPE_NONE; int backupAllWorkTypes = WORK_TYPE_NONE; Loading @@ -893,40 +892,39 @@ class JobConcurrencyManager { } // Only bypass the concurrent limit if we had preempted the job due to a higher // priority job. if (nextPending.lastEvaluatedPriority <= jobStatus.lastEvaluatedPriority // bias job. if (nextPending.lastEvaluatedBias <= jobStatus.lastEvaluatedBias && isPkgConcurrencyLimitedLocked(nextPending)) { continue; } if (highestPriorityJob == null || highestPriorityJob.lastEvaluatedPriority < nextPending.lastEvaluatedPriority) { highestPriorityJob = nextPending; if (highestBiasJob == null || highestBiasJob.lastEvaluatedBias < nextPending.lastEvaluatedBias) { highestBiasJob = nextPending; } else { continue; } // In this path, we pre-empted an existing job. We don't fully care about the // reserved slots. We should just run the highest priority job we can find, // reserved slots. We should just run the highest bias job we can find, // though it would be ideal to use an available WorkType slot instead of // overloading slots. highPriAllWorkTypes = getJobWorkTypes(nextPending); final int workAsType = mWorkCountTracker.canJobStart(highPriAllWorkTypes); highBiasAllWorkTypes = getJobWorkTypes(nextPending); final int workAsType = mWorkCountTracker.canJobStart(highBiasAllWorkTypes); if (workAsType == WORK_TYPE_NONE) { // Just use the preempted job's work type since this new one is technically // replacing it anyway. highPriWorkType = workType; highBiasWorkType = workType; } else { highPriWorkType = workAsType; highBiasWorkType = workAsType; } } if (highestPriorityJob != null) { if (highestBiasJob != null) { if (DEBUG) { Slog.d(TAG, "Running job " + jobStatus + " as preemption"); } mWorkCountTracker.stageJob(highPriWorkType, highPriAllWorkTypes); startJobLocked(worker, highestPriorityJob, highPriWorkType); mWorkCountTracker.stageJob(highBiasWorkType, highBiasAllWorkTypes); startJobLocked(worker, highestBiasJob, highBiasWorkType); } else { if (DEBUG) { Slog.d(TAG, "Couldn't find preemption job for uid " + worker.getPreferredUid()); Loading @@ -944,11 +942,10 @@ class JobConcurrencyManager { updateCounterConfigLocked(); updateNonRunningPrioritiesLocked(pendingJobs, false); // This slot is now free and we have pending jobs. Start the highest priority job we // find. JobStatus highestPriorityJob = null; int highPriWorkType = workType; int highPriAllWorkTypes = workType; // This slot is now free and we have pending jobs. Start the highest bias job we find. JobStatus highestBiasJob = null; int highBiasWorkType = workType; int highBiasAllWorkTypes = workType; for (int i = 0; i < pendingJobs.size(); i++) { final JobStatus nextPending = pendingJobs.get(i); Loading @@ -965,23 +962,22 @@ class JobConcurrencyManager { if (workAsType == WORK_TYPE_NONE) { continue; } if (highestPriorityJob == null || highestPriorityJob.lastEvaluatedPriority < nextPending.lastEvaluatedPriority) { highestPriorityJob = nextPending; highPriWorkType = workAsType; highPriAllWorkTypes = allWorkTypes; if (highestBiasJob == null || highestBiasJob.lastEvaluatedBias < nextPending.lastEvaluatedBias) { highestBiasJob = nextPending; highBiasWorkType = workAsType; highBiasAllWorkTypes = allWorkTypes; } } if (highestPriorityJob != null) { if (highestBiasJob != null) { // This slot is free, and we haven't yet hit the limit on // concurrent jobs... we can just throw the job in to here. if (DEBUG) { Slog.d(TAG, "About to run job: " + jobStatus); } mWorkCountTracker.stageJob(highPriWorkType, highPriAllWorkTypes); startJobLocked(worker, highestPriorityJob, highPriWorkType); mWorkCountTracker.stageJob(highBiasWorkType, highBiasAllWorkTypes); startJobLocked(worker, highestBiasJob, highBiasWorkType); } } Loading Loading @@ -1255,9 +1251,9 @@ class JobConcurrencyManager { int classification = 0; if (shouldRunAsFgUserJob(js)) { if (js.lastEvaluatedPriority >= JobInfo.PRIORITY_TOP_APP) { if (js.lastEvaluatedBias >= JobInfo.BIAS_TOP_APP) { classification |= WORK_TYPE_TOP; } else if (js.lastEvaluatedPriority >= JobInfo.PRIORITY_FOREGROUND_SERVICE) { } else if (js.lastEvaluatedBias >= JobInfo.BIAS_FOREGROUND_SERVICE) { classification |= WORK_TYPE_FGS; } else { classification |= WORK_TYPE_BG; Loading @@ -1267,7 +1263,7 @@ class JobConcurrencyManager { classification |= WORK_TYPE_EJ; } } else { if (js.lastEvaluatedPriority >= JobInfo.PRIORITY_FOREGROUND_SERVICE if (js.lastEvaluatedBias >= JobInfo.BIAS_FOREGROUND_SERVICE || js.shouldTreatAsExpeditedJob()) { classification |= WORK_TYPE_BGUSER_IMPORTANT; } Loading Loading @@ -1630,7 +1626,7 @@ class JobConcurrencyManager { for (int i = 0; i < mNumActuallyReservedSlots.size(); ++i) { int wt = mNumActuallyReservedSlots.keyAt(i); if (assignWorkType == WORK_TYPE_NONE || wt < assignWorkType) { // Try to give this slot to the highest priority one within its limits. // Try to give this slot to the highest bias one within its limits. int total = mNumRunningJobs.get(wt) + mNumStartingJobs.get(wt) + mNumPendingJobs.get(wt); if (mNumActuallyReservedSlots.valueAt(i) < mConfigAbsoluteMaxSlots.get(wt) Loading apex/jobscheduler/service/java/com/android/server/job/JobPackageTracker.java +2 −2 Original line number Diff line number Diff line Loading @@ -481,7 +481,7 @@ public final class JobPackageTracker { final long now = sUptimeMillisClock.millis(); job.madeActive = now; rebatchIfNeeded(now); if (job.lastEvaluatedPriority >= JobInfo.PRIORITY_TOP_APP) { if (job.lastEvaluatedBias >= JobInfo.BIAS_TOP_APP) { mCurDataSet.incActiveTop(job.getSourceUid(), job.getSourcePackageName(), now); } else { mCurDataSet.incActive(job.getSourceUid(), job.getSourcePackageName(), now); Loading @@ -492,7 +492,7 @@ public final class JobPackageTracker { public void noteInactive(JobStatus job, int stopReason, String debugReason) { final long now = sUptimeMillisClock.millis(); if (job.lastEvaluatedPriority >= JobInfo.PRIORITY_TOP_APP) { if (job.lastEvaluatedBias >= JobInfo.BIAS_TOP_APP) { mCurDataSet.decActiveTop(job.getSourceUid(), job.getSourcePackageName(), now, stopReason); } else { Loading apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java +43 −44 File changed.Preview size limit exceeded, changes collapsed. Show changes apex/jobscheduler/service/java/com/android/server/job/JobStore.java +9 −5 Original line number Diff line number Diff line Loading @@ -530,7 +530,8 @@ public final class JobStore { } } /** Write out a tag with data comprising the required fields and priority of this job and /** * Write out a tag with data comprising the required fields and bias of this job and * its client. */ private void addAttributesToJobTag(XmlSerializer out, JobStatus jobStatus) Loading @@ -546,7 +547,7 @@ public final class JobStore { } out.attribute(null, "sourceUserId", String.valueOf(jobStatus.getSourceUserId())); out.attribute(null, "uid", Integer.toString(jobStatus.getUid())); out.attribute(null, "priority", String.valueOf(jobStatus.getPriority())); out.attribute(null, "bias", String.valueOf(jobStatus.getBias())); out.attribute(null, "flags", String.valueOf(jobStatus.getFlags())); if (jobStatus.getInternalFlags() != 0) { out.attribute(null, "internalFlags", String.valueOf(jobStatus.getInternalFlags())); Loading Loading @@ -819,15 +820,18 @@ public final class JobStore { long lastFailedRunTime; int internalFlags = 0; // Read out job identifier attributes and priority. // Read out job identifier attributes and bias. try { jobBuilder = buildBuilderFromXml(parser); jobBuilder.setPersisted(true); uid = Integer.parseInt(parser.getAttributeValue(null, "uid")); String val = parser.getAttributeValue(null, "priority"); String val = parser.getAttributeValue(null, "bias"); if (val == null) { val = parser.getAttributeValue(null, "priority"); } if (val != null) { jobBuilder.setPriority(Integer.parseInt(val)); jobBuilder.setBias(Integer.parseInt(val)); } val = parser.getAttributeValue(null, "flags"); if (val != null) { Loading Loading
apex/jobscheduler/framework/java/android/app/job/JobInfo.java +60 −49 Original line number Diff line number Diff line Loading @@ -207,62 +207,65 @@ public class JobInfo implements Parcelable { public static final int DEFAULT_BACKOFF_POLICY = BACKOFF_POLICY_EXPONENTIAL; /** * Default of {@link #getPriority}. * Default of {@link #getBias}. * @hide */ public static final int PRIORITY_DEFAULT = 0; public static final int BIAS_DEFAULT = 0; /** * Value of {@link #getPriority} for expedited syncs. * Value of {@link #getBias} for expedited syncs. * @hide */ public static final int PRIORITY_SYNC_EXPEDITED = 10; public static final int BIAS_SYNC_EXPEDITED = 10; /** * Value of {@link #getPriority} for first time initialization syncs. * Value of {@link #getBias} for first time initialization syncs. * @hide */ public static final int PRIORITY_SYNC_INITIALIZATION = 20; public static final int BIAS_SYNC_INITIALIZATION = 20; /** * Value of {@link #getPriority} for a BFGS app (overrides the supplied * JobInfo priority if it is smaller). * Value of {@link #getBias} for a BFGS app (overrides the supplied * JobInfo bias if it is smaller). * @hide */ public static final int PRIORITY_BOUND_FOREGROUND_SERVICE = 30; public static final int BIAS_BOUND_FOREGROUND_SERVICE = 30; /** @hide For backward compatibility. */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public static final int PRIORITY_FOREGROUND_APP = PRIORITY_BOUND_FOREGROUND_SERVICE; public static final int PRIORITY_FOREGROUND_APP = BIAS_BOUND_FOREGROUND_SERVICE; /** * Value of {@link #getPriority} for a FG service app (overrides the supplied * JobInfo priority if it is smaller). * Value of {@link #getBias} for a FG service app (overrides the supplied * JobInfo bias if it is smaller). * @hide */ public static final int BIAS_FOREGROUND_SERVICE = 35; /** @hide For backward compatibility. */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public static final int PRIORITY_FOREGROUND_SERVICE = 35; public static final int PRIORITY_FOREGROUND_SERVICE = BIAS_FOREGROUND_SERVICE; /** * Value of {@link #getPriority} for the current top app (overrides the supplied * JobInfo priority if it is smaller). * Value of {@link #getBias} for the current top app (overrides the supplied * JobInfo bias if it is smaller). * @hide */ public static final int PRIORITY_TOP_APP = 40; public static final int BIAS_TOP_APP = 40; /** * Adjustment of {@link #getPriority} if the app has often (50% or more of the time) * Adjustment of {@link #getBias} if the app has often (50% or more of the time) * been running jobs. * @hide */ public static final int PRIORITY_ADJ_OFTEN_RUNNING = -40; public static final int BIAS_ADJ_OFTEN_RUNNING = -40; /** * Adjustment of {@link #getPriority} if the app has always (90% or more of the time) * Adjustment of {@link #getBias} if the app has always (90% or more of the time) * been running jobs. * @hide */ public static final int PRIORITY_ADJ_ALWAYS_RUNNING = -80; public static final int BIAS_ADJ_ALWAYS_RUNNING = -80; /** * Indicates that the implementation of this job will be using Loading Loading @@ -355,7 +358,7 @@ public class JobInfo implements Parcelable { private final long flexMillis; private final long initialBackoffMillis; private final int backoffPolicy; private final int priority; private final int mBias; @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) private final int flags; Loading Loading @@ -403,8 +406,8 @@ public class JobInfo implements Parcelable { } /** @hide */ public int getPriority() { return priority; public int getBias() { return mBias; } /** @hide */ Loading Loading @@ -740,7 +743,7 @@ public class JobInfo implements Parcelable { if (backoffPolicy != j.backoffPolicy) { return false; } if (priority != j.priority) { if (mBias != j.mBias) { return false; } if (flags != j.flags) { Loading Loading @@ -787,7 +790,7 @@ public class JobInfo implements Parcelable { hashCode = 31 * hashCode + Long.hashCode(flexMillis); hashCode = 31 * hashCode + Long.hashCode(initialBackoffMillis); hashCode = 31 * hashCode + backoffPolicy; hashCode = 31 * hashCode + priority; hashCode = 31 * hashCode + mBias; hashCode = 31 * hashCode + flags; return hashCode; } Loading Loading @@ -826,7 +829,7 @@ public class JobInfo implements Parcelable { backoffPolicy = in.readInt(); hasEarlyConstraint = in.readInt() == 1; hasLateConstraint = in.readInt() == 1; priority = in.readInt(); mBias = in.readInt(); flags = in.readInt(); } Loading Loading @@ -857,7 +860,7 @@ public class JobInfo implements Parcelable { backoffPolicy = b.mBackoffPolicy; hasEarlyConstraint = b.mHasEarlyConstraint; hasLateConstraint = b.mHasLateConstraint; priority = b.mPriority; mBias = b.mBias; flags = b.mFlags; } Loading Loading @@ -902,7 +905,7 @@ public class JobInfo implements Parcelable { out.writeInt(backoffPolicy); out.writeInt(hasEarlyConstraint ? 1 : 0); out.writeInt(hasLateConstraint ? 1 : 0); out.writeInt(priority); out.writeInt(mBias); out.writeInt(this.flags); } Loading Loading @@ -1020,7 +1023,7 @@ public class JobInfo implements Parcelable { private Bundle mTransientExtras = Bundle.EMPTY; private ClipData mClipData; private int mClipGrantFlags; private int mPriority = PRIORITY_DEFAULT; private int mBias = BIAS_DEFAULT; private int mFlags; // Requirements. private int mConstraintFlags; Loading Loading @@ -1074,7 +1077,7 @@ public class JobInfo implements Parcelable { mTransientExtras = job.getTransientExtras(); mClipData = job.getClipData(); mClipGrantFlags = job.getClipGrantFlags(); mPriority = job.getPriority(); mBias = job.getBias(); mFlags = job.getFlags(); mConstraintFlags = job.getConstraintFlags(); mNetworkRequest = job.getRequiredNetwork(); Loading @@ -1099,10 +1102,18 @@ public class JobInfo implements Parcelable { mBackoffPolicy = job.getBackoffPolicy(); } /** @hide */ @NonNull public Builder setBias(int bias) { mBias = bias; return this; } /** @hide */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public Builder setPriority(int priority) { mPriority = priority; // No-op for invalid calls. This wasn't a supported API before Tiramisu, so anyone // calling this that isn't targeting T isn't guaranteed a behavior change. return this; } Loading Loading @@ -1829,27 +1840,27 @@ public class JobInfo implements Parcelable { } /** * Convert a priority integer into a human readable string for debugging. * Convert a bias integer into a human readable string for debugging. * @hide */ public static String getPriorityString(int priority) { switch (priority) { case PRIORITY_DEFAULT: return PRIORITY_DEFAULT + " [DEFAULT]"; case PRIORITY_SYNC_EXPEDITED: return PRIORITY_SYNC_EXPEDITED + " [SYNC_EXPEDITED]"; case PRIORITY_SYNC_INITIALIZATION: return PRIORITY_SYNC_INITIALIZATION + " [SYNC_INITIALIZATION]"; case PRIORITY_BOUND_FOREGROUND_SERVICE: return PRIORITY_BOUND_FOREGROUND_SERVICE + " [BFGS_APP]"; case PRIORITY_FOREGROUND_SERVICE: return PRIORITY_FOREGROUND_SERVICE + " [FGS_APP]"; case PRIORITY_TOP_APP: return PRIORITY_TOP_APP + " [TOP_APP]"; // PRIORITY_ADJ_* are adjustments and not used as real priorities. public static String getBiasString(int bias) { switch (bias) { case BIAS_DEFAULT: return BIAS_DEFAULT + " [DEFAULT]"; case BIAS_SYNC_EXPEDITED: return BIAS_SYNC_EXPEDITED + " [SYNC_EXPEDITED]"; case BIAS_SYNC_INITIALIZATION: return BIAS_SYNC_INITIALIZATION + " [SYNC_INITIALIZATION]"; case BIAS_BOUND_FOREGROUND_SERVICE: return BIAS_BOUND_FOREGROUND_SERVICE + " [BFGS_APP]"; case BIAS_FOREGROUND_SERVICE: return BIAS_FOREGROUND_SERVICE + " [FGS_APP]"; case BIAS_TOP_APP: return BIAS_TOP_APP + " [TOP_APP]"; // BIAS_ADJ_* are adjustments and not used as real priorities. // No need to convert to strings. } return priority + " [UNKNOWN]"; return bias + " [UNKNOWN]"; } }
apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java +47 −51 Original line number Diff line number Diff line Loading @@ -86,7 +86,7 @@ class JobConcurrencyManager { /** * Set of possible execution types that a job can have. The actual type(s) of a job are based * on the {@link JobStatus#lastEvaluatedPriority}, which is typically evaluated right before * on the {@link JobStatus#lastEvaluatedBias}, which is typically evaluated right before * execution (when we're trying to determine which jobs to run next) and won't change after the * job has started executing. * Loading Loading @@ -527,9 +527,8 @@ class JobConcurrencyManager { /** * Takes jobs from pending queue and runs them on available contexts. * If no contexts are available, preempts lower priority jobs to * run higher priority ones. * Lock on mJobs before calling this function. * If no contexts are available, preempts lower bias jobs to run higher bias ones. * Lock on mLock before calling this function. */ @GuardedBy("mLock") void assignJobsToContextsLocked() { Loading Loading @@ -596,9 +595,9 @@ class JobConcurrencyManager { } // Find an available slot for nextPending. The context should be available OR // it should have lowest priority among all running jobs // it should have the lowest bias among all running jobs // (sharing the same Uid as nextPending) int minPriorityForPreemption = Integer.MAX_VALUE; int minBiasForPreemption = Integer.MAX_VALUE; int selectedContextId = -1; int allWorkTypes = getJobWorkTypes(nextPending); int workType = mWorkCountTracker.canJobStart(allWorkTypes); Loading Loading @@ -631,7 +630,7 @@ class JobConcurrencyManager { // Maybe stop the job if it has had its day in the sun. Don't let a different // app preempt jobs started for TOP apps though. final String reason = shouldStopJobReason[j]; if (job.lastEvaluatedPriority < JobInfo.PRIORITY_TOP_APP if (job.lastEvaluatedBias < JobInfo.BIAS_TOP_APP && reason != null && mWorkCountTracker.canJobStart(allWorkTypes, activeServices.get(j).getRunningJobWorkType()) != WORK_TYPE_NONE) { // Right now, the way the code is set up, we don't need to explicitly Loading @@ -643,19 +642,19 @@ class JobConcurrencyManager { continue; } final int jobPriority = mService.evaluateJobPriorityLocked(job); if (jobPriority >= nextPending.lastEvaluatedPriority) { final int jobBias = mService.evaluateJobBiasLocked(job); if (jobBias >= nextPending.lastEvaluatedBias) { continue; } if (minPriorityForPreemption > jobPriority) { if (minBiasForPreemption > jobBias) { // Step down the preemption threshold - wind up replacing // the lowest-priority running job minPriorityForPreemption = jobPriority; // the lowest-bias running job minBiasForPreemption = jobBias; selectedContextId = j; preemptReason = "higher priority job found"; preemptReason = "higher bias job found"; preemptReasonCode = JobParameters.STOP_REASON_PREEMPT; // In this case, we're just going to preempt a low priority job, we're not // In this case, we're just going to preempt a low bias job, we're not // actually starting a job, so don't set startingJob. } } Loading Loading @@ -749,7 +748,7 @@ class JobConcurrencyManager { continue; } pending.lastEvaluatedPriority = mService.evaluateJobPriorityLocked(pending); pending.lastEvaluatedBias = mService.evaluateJobBiasLocked(pending); if (updateCounter) { mWorkCountTracker.incrementPendingJobCount(getJobWorkTypes(pending)); Loading @@ -773,7 +772,7 @@ class JobConcurrencyManager { @GuardedBy("mLock") private boolean isPkgConcurrencyLimitedLocked(@NonNull JobStatus jobStatus) { if (jobStatus.lastEvaluatedPriority >= JobInfo.PRIORITY_TOP_APP) { if (jobStatus.lastEvaluatedBias >= JobInfo.BIAS_TOP_APP) { // Don't restrict top apps' concurrency. The work type limits will make sure // background jobs have slots to run if the system has resources. return false; Loading Loading @@ -866,9 +865,9 @@ class JobConcurrencyManager { // Preemption case needs special care. updateNonRunningPrioritiesLocked(pendingJobs, false); JobStatus highestPriorityJob = null; int highPriWorkType = workType; int highPriAllWorkTypes = workType; JobStatus highestBiasJob = null; int highBiasWorkType = workType; int highBiasAllWorkTypes = workType; JobStatus backupJob = null; int backupWorkType = WORK_TYPE_NONE; int backupAllWorkTypes = WORK_TYPE_NONE; Loading @@ -893,40 +892,39 @@ class JobConcurrencyManager { } // Only bypass the concurrent limit if we had preempted the job due to a higher // priority job. if (nextPending.lastEvaluatedPriority <= jobStatus.lastEvaluatedPriority // bias job. if (nextPending.lastEvaluatedBias <= jobStatus.lastEvaluatedBias && isPkgConcurrencyLimitedLocked(nextPending)) { continue; } if (highestPriorityJob == null || highestPriorityJob.lastEvaluatedPriority < nextPending.lastEvaluatedPriority) { highestPriorityJob = nextPending; if (highestBiasJob == null || highestBiasJob.lastEvaluatedBias < nextPending.lastEvaluatedBias) { highestBiasJob = nextPending; } else { continue; } // In this path, we pre-empted an existing job. We don't fully care about the // reserved slots. We should just run the highest priority job we can find, // reserved slots. We should just run the highest bias job we can find, // though it would be ideal to use an available WorkType slot instead of // overloading slots. highPriAllWorkTypes = getJobWorkTypes(nextPending); final int workAsType = mWorkCountTracker.canJobStart(highPriAllWorkTypes); highBiasAllWorkTypes = getJobWorkTypes(nextPending); final int workAsType = mWorkCountTracker.canJobStart(highBiasAllWorkTypes); if (workAsType == WORK_TYPE_NONE) { // Just use the preempted job's work type since this new one is technically // replacing it anyway. highPriWorkType = workType; highBiasWorkType = workType; } else { highPriWorkType = workAsType; highBiasWorkType = workAsType; } } if (highestPriorityJob != null) { if (highestBiasJob != null) { if (DEBUG) { Slog.d(TAG, "Running job " + jobStatus + " as preemption"); } mWorkCountTracker.stageJob(highPriWorkType, highPriAllWorkTypes); startJobLocked(worker, highestPriorityJob, highPriWorkType); mWorkCountTracker.stageJob(highBiasWorkType, highBiasAllWorkTypes); startJobLocked(worker, highestBiasJob, highBiasWorkType); } else { if (DEBUG) { Slog.d(TAG, "Couldn't find preemption job for uid " + worker.getPreferredUid()); Loading @@ -944,11 +942,10 @@ class JobConcurrencyManager { updateCounterConfigLocked(); updateNonRunningPrioritiesLocked(pendingJobs, false); // This slot is now free and we have pending jobs. Start the highest priority job we // find. JobStatus highestPriorityJob = null; int highPriWorkType = workType; int highPriAllWorkTypes = workType; // This slot is now free and we have pending jobs. Start the highest bias job we find. JobStatus highestBiasJob = null; int highBiasWorkType = workType; int highBiasAllWorkTypes = workType; for (int i = 0; i < pendingJobs.size(); i++) { final JobStatus nextPending = pendingJobs.get(i); Loading @@ -965,23 +962,22 @@ class JobConcurrencyManager { if (workAsType == WORK_TYPE_NONE) { continue; } if (highestPriorityJob == null || highestPriorityJob.lastEvaluatedPriority < nextPending.lastEvaluatedPriority) { highestPriorityJob = nextPending; highPriWorkType = workAsType; highPriAllWorkTypes = allWorkTypes; if (highestBiasJob == null || highestBiasJob.lastEvaluatedBias < nextPending.lastEvaluatedBias) { highestBiasJob = nextPending; highBiasWorkType = workAsType; highBiasAllWorkTypes = allWorkTypes; } } if (highestPriorityJob != null) { if (highestBiasJob != null) { // This slot is free, and we haven't yet hit the limit on // concurrent jobs... we can just throw the job in to here. if (DEBUG) { Slog.d(TAG, "About to run job: " + jobStatus); } mWorkCountTracker.stageJob(highPriWorkType, highPriAllWorkTypes); startJobLocked(worker, highestPriorityJob, highPriWorkType); mWorkCountTracker.stageJob(highBiasWorkType, highBiasAllWorkTypes); startJobLocked(worker, highestBiasJob, highBiasWorkType); } } Loading Loading @@ -1255,9 +1251,9 @@ class JobConcurrencyManager { int classification = 0; if (shouldRunAsFgUserJob(js)) { if (js.lastEvaluatedPriority >= JobInfo.PRIORITY_TOP_APP) { if (js.lastEvaluatedBias >= JobInfo.BIAS_TOP_APP) { classification |= WORK_TYPE_TOP; } else if (js.lastEvaluatedPriority >= JobInfo.PRIORITY_FOREGROUND_SERVICE) { } else if (js.lastEvaluatedBias >= JobInfo.BIAS_FOREGROUND_SERVICE) { classification |= WORK_TYPE_FGS; } else { classification |= WORK_TYPE_BG; Loading @@ -1267,7 +1263,7 @@ class JobConcurrencyManager { classification |= WORK_TYPE_EJ; } } else { if (js.lastEvaluatedPriority >= JobInfo.PRIORITY_FOREGROUND_SERVICE if (js.lastEvaluatedBias >= JobInfo.BIAS_FOREGROUND_SERVICE || js.shouldTreatAsExpeditedJob()) { classification |= WORK_TYPE_BGUSER_IMPORTANT; } Loading Loading @@ -1630,7 +1626,7 @@ class JobConcurrencyManager { for (int i = 0; i < mNumActuallyReservedSlots.size(); ++i) { int wt = mNumActuallyReservedSlots.keyAt(i); if (assignWorkType == WORK_TYPE_NONE || wt < assignWorkType) { // Try to give this slot to the highest priority one within its limits. // Try to give this slot to the highest bias one within its limits. int total = mNumRunningJobs.get(wt) + mNumStartingJobs.get(wt) + mNumPendingJobs.get(wt); if (mNumActuallyReservedSlots.valueAt(i) < mConfigAbsoluteMaxSlots.get(wt) Loading
apex/jobscheduler/service/java/com/android/server/job/JobPackageTracker.java +2 −2 Original line number Diff line number Diff line Loading @@ -481,7 +481,7 @@ public final class JobPackageTracker { final long now = sUptimeMillisClock.millis(); job.madeActive = now; rebatchIfNeeded(now); if (job.lastEvaluatedPriority >= JobInfo.PRIORITY_TOP_APP) { if (job.lastEvaluatedBias >= JobInfo.BIAS_TOP_APP) { mCurDataSet.incActiveTop(job.getSourceUid(), job.getSourcePackageName(), now); } else { mCurDataSet.incActive(job.getSourceUid(), job.getSourcePackageName(), now); Loading @@ -492,7 +492,7 @@ public final class JobPackageTracker { public void noteInactive(JobStatus job, int stopReason, String debugReason) { final long now = sUptimeMillisClock.millis(); if (job.lastEvaluatedPriority >= JobInfo.PRIORITY_TOP_APP) { if (job.lastEvaluatedBias >= JobInfo.BIAS_TOP_APP) { mCurDataSet.decActiveTop(job.getSourceUid(), job.getSourcePackageName(), now, stopReason); } else { Loading
apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java +43 −44 File changed.Preview size limit exceeded, changes collapsed. Show changes
apex/jobscheduler/service/java/com/android/server/job/JobStore.java +9 −5 Original line number Diff line number Diff line Loading @@ -530,7 +530,8 @@ public final class JobStore { } } /** Write out a tag with data comprising the required fields and priority of this job and /** * Write out a tag with data comprising the required fields and bias of this job and * its client. */ private void addAttributesToJobTag(XmlSerializer out, JobStatus jobStatus) Loading @@ -546,7 +547,7 @@ public final class JobStore { } out.attribute(null, "sourceUserId", String.valueOf(jobStatus.getSourceUserId())); out.attribute(null, "uid", Integer.toString(jobStatus.getUid())); out.attribute(null, "priority", String.valueOf(jobStatus.getPriority())); out.attribute(null, "bias", String.valueOf(jobStatus.getBias())); out.attribute(null, "flags", String.valueOf(jobStatus.getFlags())); if (jobStatus.getInternalFlags() != 0) { out.attribute(null, "internalFlags", String.valueOf(jobStatus.getInternalFlags())); Loading Loading @@ -819,15 +820,18 @@ public final class JobStore { long lastFailedRunTime; int internalFlags = 0; // Read out job identifier attributes and priority. // Read out job identifier attributes and bias. try { jobBuilder = buildBuilderFromXml(parser); jobBuilder.setPersisted(true); uid = Integer.parseInt(parser.getAttributeValue(null, "uid")); String val = parser.getAttributeValue(null, "priority"); String val = parser.getAttributeValue(null, "bias"); if (val == null) { val = parser.getAttributeValue(null, "priority"); } if (val != null) { jobBuilder.setPriority(Integer.parseInt(val)); jobBuilder.setBias(Integer.parseInt(val)); } val = parser.getAttributeValue(null, "flags"); if (val != null) { Loading