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

Commit 13785e6c authored by Kweku Adams's avatar Kweku Adams Committed by Android (Google) Code Review
Browse files

Merge "Apply thermal throttling to long-running jobs."

parents bccd5364 1c99942d
Loading
Loading
Loading
Loading
+50 −0
Original line number Diff line number Diff line
@@ -542,6 +542,30 @@ class JobConcurrencyManager {
        return mRunningJobs.contains(job);
    }

    /**
     * Return {@code true} if the specified job has been executing for longer than the minimum
     * execution guarantee.
     */
    @GuardedBy("mLock")
    boolean isJobLongRunningLocked(@NonNull JobStatus job) {
        if (!mRunningJobs.contains(job)) {
            return false;
        }

        for (int i = mActiveServices.size() - 1; i >= 0; --i) {
            final JobServiceContext jsc = mActiveServices.get(i);
            final JobStatus jobStatus = jsc.getRunningJobLocked();

            if (jobStatus == job) {
                return !jsc.isWithinExecutionGuaranteeTime();
            }
        }

        Slog.wtf(TAG, "Couldn't find long running job on a context");
        mRunningJobs.remove(job);
        return false;
    }

    /**
     * Returns true if a job that is "similar" to the provided job is currently running.
     * "Similar" in this context means any job that the {@link JobStore} would consider equivalent
@@ -989,6 +1013,26 @@ class JobConcurrencyManager {
        }
    }

    /**
     * Stops any jobs that have run for more than their minimum execution guarantee and are
     * restricted by the given {@link JobRestriction}.
     */
    @GuardedBy("mLock")
    void maybeStopLongRunningJobsLocked(@NonNull JobRestriction restriction) {
        for (int i = mActiveServices.size() - 1; i >= 0; --i) {
            final JobServiceContext jsc = mActiveServices.get(i);
            final JobStatus jobStatus = jsc.getRunningJobLocked();

            if (jobStatus != null && !jsc.isWithinExecutionGuaranteeTime()
                    && restriction.isJobRestricted(jobStatus)) {
                jsc.cancelExecutingJobLocked(restriction.getReason(),
                        restriction.getInternalReason(),
                        JobParameters.getInternalReasonCodeDescription(
                                restriction.getInternalReason()));
            }
        }
    }

    @GuardedBy("mLock")
    void stopNonReadyActiveJobsLocked() {
        for (int i = 0; i < mActiveServices.size(); i++) {
@@ -1349,6 +1393,12 @@ class JobConcurrencyManager {
        if (mPowerManager.isDeviceIdleMode()) {
            return "deep doze";
        }
        final JobRestriction jobRestriction;
        if ((jobRestriction = mService.checkIfRestricted(js)) != null) {
            return "restriction:"
                    + JobParameters.getInternalReasonCodeDescription(
                            jobRestriction.getInternalReason());
        }

        // Update config in case memory usage has changed significantly.
        updateCounterConfigLocked();
+17 −0
Original line number Diff line number Diff line
@@ -1772,6 +1772,12 @@ public class JobSchedulerService extends com.android.server.SystemService
        return mConcurrencyManager.isJobRunningLocked(job);
    }

    /** @see JobConcurrencyManager#isJobLongRunningLocked(JobStatus) */
    @GuardedBy("mLock")
    public boolean isLongRunningLocked(JobStatus job) {
        return mConcurrencyManager.isJobLongRunningLocked(job);
    }

    private void noteJobPending(JobStatus job) {
        mJobPackageTracker.notePending(job);
    }
@@ -2049,6 +2055,17 @@ public class JobSchedulerService extends com.android.server.SystemService
        }
    }

    @Override
    public void onRestrictionStateChanged(@NonNull JobRestriction restriction,
            boolean stopLongRunningJobs) {
        mHandler.obtainMessage(MSG_CHECK_JOB).sendToTarget();
        if (stopLongRunningJobs) {
            synchronized (mLock) {
                mConcurrencyManager.maybeStopLongRunningJobsLocked(restriction);
            }
        }
    }

    @Override
    public void onRunJobNow(JobStatus jobStatus) {
        if (jobStatus == null) {
+2 −2
Original line number Diff line number Diff line
@@ -736,10 +736,10 @@ public final class JobServiceContext implements ServiceConnection {
    @GuardedBy("mLock")
    private void doCancelLocked(@JobParameters.StopReason int stopReasonCode,
            int internalStopReasonCode, @Nullable String debugReason) {
        if (mVerb == VERB_FINISHED) {
        if (mVerb == VERB_FINISHED || mVerb == VERB_STOPPING) {
            if (DEBUG) {
                Slog.d(TAG,
                        "Trying to process cancel for torn-down context, ignoring.");
                        "Too late to process cancel for context (verb=" + mVerb + "), ignoring.");
            }
            return;
        }
+11 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import android.annotation.Nullable;
import android.util.ArraySet;

import com.android.server.job.controllers.JobStatus;
import com.android.server.job.restrictions.JobRestriction;

import java.util.List;

@@ -36,6 +37,16 @@ public interface StateChangedListener {
     */
    void onControllerStateChanged(@Nullable ArraySet<JobStatus> changedJobs);

    /**
     * Called by a {@link com.android.server.job.restrictions.JobRestriction} to notify the
     * JobScheduler that it should check on the state of all jobs.
     *
     * @param stopLongRunningJobs Whether to stop any jobs that have run for more than their minimum
     *                            execution guarantee and are restricted by the changed restriction
     */
    void onRestrictionStateChanged(@NonNull JobRestriction restriction,
            boolean stopLongRunningJobs);

    /**
     * Called by the controller to notify the JobManager that regardless of the state of the task,
     * it must be run immediately.
+10 −6
Original line number Diff line number Diff line
@@ -73,9 +73,10 @@ public class ThermalStatusRestriction extends JobRestriction {
                                // bucket (thus resulting in us beginning to enforce the tightest
                                // restrictions).
                                || (mThermalStatus < UPPER_THRESHOLD && status > UPPER_THRESHOLD);
                final boolean increased = mThermalStatus < status;
                mThermalStatus = status;
                if (significantChange) {
                    mService.onControllerStateChanged(null);
                    mService.onRestrictionStateChanged(ThermalStatusRestriction.this, increased);
                }
            }
        });
@@ -89,16 +90,19 @@ public class ThermalStatusRestriction extends JobRestriction {
        final int priority = job.getEffectivePriority();
        if (mThermalStatus >= HIGHER_PRIORITY_THRESHOLD) {
            // For moderate throttling, only let expedited jobs and high priority regular jobs that
            // are already running run.
            // haven't been running for long run.
            return !job.shouldTreatAsExpeditedJob()
                    && !(priority == JobInfo.PRIORITY_HIGH
                    && mService.isCurrentlyRunningLocked(job));
                        && mService.isCurrentlyRunningLocked(job)
                        && !mService.isLongRunningLocked(job));
        }
        if (mThermalStatus >= LOW_PRIORITY_THRESHOLD) {
            // For light throttling, throttle all min priority jobs and all low priority jobs that
            // aren't already running.
            return (priority == JobInfo.PRIORITY_LOW && !mService.isCurrentlyRunningLocked(job))
                    || priority == JobInfo.PRIORITY_MIN;
            // aren't already running or have been running for long enough.
            return priority == JobInfo.PRIORITY_MIN
                    || (priority == JobInfo.PRIORITY_LOW
                        && (!mService.isCurrentlyRunningLocked(job)
                            || mService.isLongRunningLocked(job)));
        }
        return false;
    }
Loading