Merge "Partially undo "Try to avoid overlapping job execution."" into tm-dev am: 55e09c9efa am: b2ad53ae11
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/18355274 Change-Id: I7f9f36b43a3e1c533ad045784a00347e85da633e Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -1777,10 +1777,7 @@ public class JobInfo implements Parcelable {
|
||||
* {@link Build.VERSION_CODES#S}, but starting from Android version
|
||||
* {@link Build.VERSION_CODES#TIRAMISU}, expedited jobs for the foreground app are
|
||||
* guaranteed to be started before {@link JobScheduler#schedule(JobInfo)} returns (assuming
|
||||
* all requested constraints are satisfied), similar to foreground services. However, this
|
||||
* start guarantee means there is a higher chance of overlapping executions, as noted in
|
||||
* {@link JobService}, so be sure to handle that properly if you intend to reschedule the
|
||||
* job while it's actively running.
|
||||
* all requested constraints are satisfied), similar to foreground services.
|
||||
*
|
||||
* @see JobInfo#isExpedited()
|
||||
*/
|
||||
|
||||
@@ -107,9 +107,7 @@ public abstract class JobScheduler {
|
||||
/**
|
||||
* Schedule a job to be executed. Will replace any currently scheduled job with the same
|
||||
* ID with the new information in the {@link JobInfo}. If a job with the given ID is currently
|
||||
* running, it will be stopped. Note that in some cases, the newly scheduled job may be started
|
||||
* before the previously running job has been fully stopped. See {@link JobService} for
|
||||
* additional details.
|
||||
* running, it will be stopped.
|
||||
*
|
||||
* <p class="caution"><strong>Note:</strong> Scheduling a job can have a high cost, even if it's
|
||||
* rescheduling the same job and the job didn't execute, especially on platform versions before
|
||||
|
||||
@@ -32,16 +32,11 @@ import android.os.IBinder;
|
||||
* {@link #onStopJob(android.app.job.JobParameters)}, which is meant to inform you that the
|
||||
* scheduling requirements are no longer being met.</p>
|
||||
*
|
||||
* As a subclass of {@link Service}, there will only be one active instance of any JobService
|
||||
* <p>As a subclass of {@link Service}, there will only be one active instance of any JobService
|
||||
* subclasses, regardless of job ID. This means that if you schedule multiple jobs with different
|
||||
* job IDs but using the same JobService class, that JobService may receive multiple calls to
|
||||
* {@link #onStartJob(JobParameters)} and {@link #onStopJob(JobParameters)}, with each call being
|
||||
* for the separate jobs.
|
||||
*
|
||||
* <p class="note">Note that if you cancel and reschedule an already executing job,
|
||||
* there may be a small period of time where {@link #onStartJob(JobParameters)} has been called for
|
||||
* the newly scheduled job instance before {@link #onStopJob(JobParameters)} has been called or
|
||||
* fully processed for the old job.</p>
|
||||
* for the separate jobs.</p>
|
||||
*/
|
||||
public abstract class JobService extends Service {
|
||||
private static final String TAG = "JobService";
|
||||
|
||||
@@ -717,17 +717,9 @@ class JobConcurrencyManager {
|
||||
|
||||
final boolean isTopEj = nextPending.shouldTreatAsExpeditedJob()
|
||||
&& nextPending.lastEvaluatedBias == JobInfo.BIAS_TOP_APP;
|
||||
// Avoid overlapping job execution as much as possible.
|
||||
if (!isTopEj && isSimilarJobRunningLocked(nextPending)) {
|
||||
if (DEBUG) {
|
||||
Slog.w(TAG, "Delaying execution of job because of similarly running one: "
|
||||
+ nextPending);
|
||||
}
|
||||
// It would be nice to let the JobService running the other similar job know about
|
||||
// this new job so that it doesn't unbind from the JobService and we can call
|
||||
// onStartJob as soon as the older job finishes.
|
||||
// TODO: optimize the job reschedule flow to reduce service binding churn
|
||||
continue;
|
||||
if (DEBUG && isSimilarJobRunningLocked(nextPending)) {
|
||||
Slog.w(TAG, "Already running similar " + (isTopEj ? "TOP-EJ" : "job")
|
||||
+ " to: " + nextPending);
|
||||
}
|
||||
|
||||
// Find an available slot for nextPending. The context should be one of the following:
|
||||
@@ -1206,13 +1198,8 @@ class JobConcurrencyManager {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Avoid overlapping job execution as much as possible.
|
||||
if (isSimilarJobRunningLocked(nextPending)) {
|
||||
if (DEBUG) {
|
||||
Slog.w(TAG, "Avoiding execution of job because of similarly running one: "
|
||||
+ nextPending);
|
||||
}
|
||||
continue;
|
||||
if (DEBUG && isSimilarJobRunningLocked(nextPending)) {
|
||||
Slog.w(TAG, "Already running similar job to: " + nextPending);
|
||||
}
|
||||
|
||||
if (worker.getPreferredUid() != nextPending.getUid()) {
|
||||
@@ -1298,13 +1285,8 @@ class JobConcurrencyManager {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Avoid overlapping job execution as much as possible.
|
||||
if (isSimilarJobRunningLocked(nextPending)) {
|
||||
if (DEBUG) {
|
||||
Slog.w(TAG, "Avoiding execution of job because of similarly running one: "
|
||||
+ nextPending);
|
||||
}
|
||||
continue;
|
||||
if (DEBUG && isSimilarJobRunningLocked(nextPending)) {
|
||||
Slog.w(TAG, "Already running similar job to: " + nextPending);
|
||||
}
|
||||
|
||||
if (isPkgConcurrencyLimitedLocked(nextPending)) {
|
||||
|
||||
@@ -1208,22 +1208,12 @@ public class JobSchedulerService extends com.android.server.SystemService
|
||||
// This may throw a SecurityException.
|
||||
jobStatus.prepareLocked();
|
||||
|
||||
final boolean canExecuteImmediately;
|
||||
if (toCancel != null) {
|
||||
// Implicitly replaces the existing job record with the new instance
|
||||
final boolean wasJobExecuting = cancelJobImplLocked(toCancel, jobStatus,
|
||||
JobParameters.STOP_REASON_CANCELLED_BY_APP,
|
||||
JobParameters.INTERNAL_STOP_REASON_CANCELED,
|
||||
"job rescheduled by app");
|
||||
// Avoid overlapping job executions. Don't push for immediate execution if an old
|
||||
// job with the same ID was running, but let TOP EJs start immediately.
|
||||
canExecuteImmediately = !wasJobExecuting
|
||||
|| (jobStatus.isRequestedExpeditedJob()
|
||||
&& mUidBiasOverride.get(jobStatus.getSourceUid(), JobInfo.BIAS_DEFAULT)
|
||||
== JobInfo.BIAS_TOP_APP);
|
||||
cancelJobImplLocked(toCancel, jobStatus, JobParameters.STOP_REASON_CANCELLED_BY_APP,
|
||||
JobParameters.INTERNAL_STOP_REASON_CANCELED, "job rescheduled by app");
|
||||
} else {
|
||||
startTrackingJobLocked(jobStatus, null);
|
||||
canExecuteImmediately = true;
|
||||
}
|
||||
|
||||
if (work != null) {
|
||||
@@ -1266,12 +1256,7 @@ public class JobSchedulerService extends com.android.server.SystemService
|
||||
// list and try to run it.
|
||||
mJobPackageTracker.notePending(jobStatus);
|
||||
mPendingJobQueue.add(jobStatus);
|
||||
if (canExecuteImmediately) {
|
||||
// Don't ask the JobConcurrencyManager to try to run the job immediately. The
|
||||
// JobServiceContext will ask the JobConcurrencyManager for another job once
|
||||
// it finishes cleaning up the old job.
|
||||
maybeRunPendingJobsLocked();
|
||||
}
|
||||
maybeRunPendingJobsLocked();
|
||||
} else {
|
||||
evaluateControllerStatesLocked(jobStatus);
|
||||
}
|
||||
@@ -1392,10 +1377,8 @@ public class JobSchedulerService extends com.android.server.SystemService
|
||||
* is null, the cancelled job is removed outright from the system. If
|
||||
* {@code incomingJob} is non-null, it replaces {@code cancelled} in the store of
|
||||
* currently scheduled jobs.
|
||||
*
|
||||
* @return true if the cancelled job was running
|
||||
*/
|
||||
private boolean cancelJobImplLocked(JobStatus cancelled, JobStatus incomingJob,
|
||||
private void cancelJobImplLocked(JobStatus cancelled, JobStatus incomingJob,
|
||||
@JobParameters.StopReason int reason, int internalReasonCode, String debugReason) {
|
||||
if (DEBUG) Slog.d(TAG, "CANCEL: " + cancelled.toShortString());
|
||||
cancelled.unprepareLocked();
|
||||
@@ -1406,7 +1389,7 @@ public class JobSchedulerService extends com.android.server.SystemService
|
||||
}
|
||||
mChangedJobList.remove(cancelled);
|
||||
// Cancel if running.
|
||||
boolean wasRunning = mConcurrencyManager.stopJobOnServiceContextLocked(
|
||||
mConcurrencyManager.stopJobOnServiceContextLocked(
|
||||
cancelled, reason, internalReasonCode, debugReason);
|
||||
// If this is a replacement, bring in the new version of the job
|
||||
if (incomingJob != null) {
|
||||
@@ -1414,7 +1397,6 @@ public class JobSchedulerService extends com.android.server.SystemService
|
||||
startTrackingJobLocked(incomingJob, cancelled);
|
||||
}
|
||||
reportActiveLocked();
|
||||
return wasRunning;
|
||||
}
|
||||
|
||||
void updateUidState(int uid, int procState) {
|
||||
|
||||
Reference in New Issue
Block a user