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

Commit 94e56d3d authored by Kweku Adams's avatar Kweku Adams Committed by Automerger Merge Worker
Browse files

Merge "Partially undo "Try to avoid overlapping job execution."" into tm-dev am: 55e09c9e

parents 37402fdd 55e09c9e
Loading
Loading
Loading
Loading
+1 −4
Original line number Diff line number Diff line
@@ -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()
         */
+1 −3
Original line number Diff line number Diff line
@@ -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
+2 −7
Original line number Diff line number Diff line
@@ -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";
+7 −25
Original line number Diff line number Diff line
@@ -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)) {
+5 −23
Original line number Diff line number Diff line
@@ -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();
                }
            } 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) {