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

Commit 62bbd4f6 authored by Kweku Adams's avatar Kweku Adams
Browse files

Disallow EJs that time out from running in Doze or battery saver.

If an EJ has used its minimum runtime guarantee before, then we
shouldn't let it run in Doze or battery saver again. The restriction
will persist across reschedules.

Bug: 171305774
Test: atest frameworks/base/services/tests/servicestests/src/com/android/server/job
Test: atest frameworks/base/services/tests/mockingservicestests/src/com/android/server/job
Test: atest CtsJobSchedulerTestCases
Change-Id: Id63ea89062b6269e87518123df5d65441f3a7923
parent 1fd830ff
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -25,7 +25,9 @@ import com.android.server.job.controllers.JobStatus;
public interface JobCompletedListener {
    /**
     * Callback for when a job is completed.
     *
     * @param stopReason      The stop reason provided to JobParameters.
     * @param needsReschedule Whether the implementing class should reschedule this job.
     */
    void onJobCompletedLocked(JobStatus jobStatus, boolean needsReschedule);
    void onJobCompletedLocked(JobStatus jobStatus, int stopReason, boolean needsReschedule);
}
+8 −2
Original line number Diff line number Diff line
@@ -1745,11 +1745,12 @@ public class JobSchedulerService extends com.android.server.SystemService
     * A job just finished executing. We fetch the
     * {@link com.android.server.job.controllers.JobStatus} from the store and depending on
     * whether we want to reschedule we re-add it to the controllers.
     *
     * @param jobStatus       Completed job.
     * @param needsReschedule Whether the implementing class should reschedule this job.
     */
    @Override
    public void onJobCompletedLocked(JobStatus jobStatus, boolean needsReschedule) {
    public void onJobCompletedLocked(JobStatus jobStatus, int stopReason, boolean needsReschedule) {
        if (DEBUG) {
            Slog.d(TAG, "Completed " + jobStatus + ", reschedule=" + needsReschedule);
        }
@@ -1767,6 +1768,11 @@ public class JobSchedulerService extends com.android.server.SystemService
        // we stop it.
        final JobStatus rescheduledJob = needsReschedule
                ? getRescheduleJobForFailureLocked(jobStatus) : null;
        if (rescheduledJob != null
                && (stopReason == JobParameters.REASON_TIMEOUT
                || stopReason == JobParameters.REASON_PREEMPT)) {
            rescheduledJob.disallowRunInBatterySaverAndDoze();
        }

        // Do not write back immediately if this is a periodic job. The job may get lost if system
        // shuts down before it is added back.
+7 −6
Original line number Diff line number Diff line
@@ -379,8 +379,8 @@ public final class JobServiceContext implements ServiceConnection {
    }

    boolean isWithinExecutionGuaranteeTime() {
        return mExecutionStartTimeElapsed + mMinExecutionGuaranteeMillis
                < sElapsedRealtimeClock.millis();
        return sElapsedRealtimeClock.millis()
                < mExecutionStartTimeElapsed + mMinExecutionGuaranteeMillis;
    }

    @GuardedBy("mLock")
@@ -848,11 +848,12 @@ public final class JobServiceContext implements ServiceConnection {
        }
        applyStoppedReasonLocked(reason);
        completedJob = mRunningJob;
        mJobPackageTracker.noteInactive(completedJob, mParams.getStopReason(), reason);
        final int stopReason = mParams.getStopReason();
        mJobPackageTracker.noteInactive(completedJob, stopReason, reason);
        FrameworkStatsLog.write_non_chained(FrameworkStatsLog.SCHEDULED_JOB_STATE_CHANGED,
                completedJob.getSourceUid(), null, completedJob.getBatteryName(),
                FrameworkStatsLog.SCHEDULED_JOB_STATE_CHANGED__STATE__FINISHED,
                mParams.getStopReason(), completedJob.getStandbyBucket(), completedJob.getJobId(),
                stopReason, completedJob.getStandbyBucket(), completedJob.getJobId(),
                completedJob.hasChargingConstraint(),
                completedJob.hasBatteryNotLowConstraint(),
                completedJob.hasStorageNotLowConstraint(),
@@ -863,7 +864,7 @@ public final class JobServiceContext implements ServiceConnection {
                completedJob.hasContentTriggerConstraint());
        try {
            mBatteryStats.noteJobFinish(mRunningJob.getBatteryName(), mRunningJob.getSourceUid(),
                    mParams.getStopReason());
                    stopReason);
        } catch (RemoteException e) {
            // Whatever.
        }
@@ -882,7 +883,7 @@ public final class JobServiceContext implements ServiceConnection {
        service = null;
        mAvailable = true;
        removeOpTimeOutLocked();
        mCompletedListener.onJobCompletedLocked(completedJob, reschedule);
        mCompletedListener.onJobCompletedLocked(completedJob, stopReason, reschedule);
        mJobConcurrencyManager.onJobCompletedLocked(this, completedJob, workType);
    }

+1 −1
Original line number Diff line number Diff line
@@ -954,7 +954,7 @@ public final class JobStore {
                    appBucket, sourceTag,
                    elapsedRuntimes.first, elapsedRuntimes.second,
                    lastSuccessfulRunTime, lastFailedRunTime,
                    (rtcIsGood) ? null : rtcRuntimes, internalFlags);
                    (rtcIsGood) ? null : rtcRuntimes, internalFlags, /* dynamicConstraints */ 0);
            return js;
        }

+8 −11
Original line number Diff line number Diff line
@@ -64,7 +64,7 @@ public final class DeviceIdleJobsController extends StateController {
     * when the app is temp whitelisted or in the foreground.
     */
    private final ArraySet<JobStatus> mAllowInIdleJobs;
    private final SparseBooleanArray mForegroundUids;
    private final SparseBooleanArray mForegroundUids = new SparseBooleanArray();
    private final DeviceIdleUpdateFunctor mDeviceIdleUpdateFunctor;
    private final DeviceIdleJobsDelayHandler mHandler;
    private final PowerManager mPowerManager;
@@ -77,7 +77,6 @@ public final class DeviceIdleJobsController extends StateController {
    private int[] mDeviceIdleWhitelistAppIds;
    private int[] mPowerSaveTempWhitelistAppIds;

    // onReceive
    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
@@ -120,6 +119,10 @@ public final class DeviceIdleJobsController extends StateController {
        }
    };

    /** Criteria for whether or not we should a job's rush evaluation when the device exits Doze. */
    private final Predicate<JobStatus> mShouldRushEvaluation = (jobStatus) ->
            jobStatus.isRequestedExpeditedJob() || mForegroundUids.get(jobStatus.getSourceUid());

    public DeviceIdleJobsController(JobSchedulerService service) {
        super(service);

@@ -133,7 +136,6 @@ public final class DeviceIdleJobsController extends StateController {
                mLocalDeviceIdleController.getPowerSaveTempWhitelistAppIds();
        mDeviceIdleUpdateFunctor = new DeviceIdleUpdateFunctor();
        mAllowInIdleJobs = new ArraySet<>();
        mForegroundUids = new SparseBooleanArray();
        final IntentFilter filter = new IntentFilter();
        filter.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
        filter.addAction(PowerManager.ACTION_LIGHT_DEVICE_IDLE_MODE_CHANGED);
@@ -156,14 +158,9 @@ public final class DeviceIdleJobsController extends StateController {
                mHandler.removeMessages(PROCESS_BACKGROUND_JOBS);
                mService.getJobStore().forEachJob(mDeviceIdleUpdateFunctor);
            } else {
                // When coming out of doze, process all foreground uids immediately, while others
                // will be processed after a delay of 3 seconds.
                for (int i = 0; i < mForegroundUids.size(); i++) {
                    if (mForegroundUids.valueAt(i)) {
                        mService.getJobStore().forEachJobForSourceUid(
                                mForegroundUids.keyAt(i), mDeviceIdleUpdateFunctor);
                    }
                }
                // When coming out of doze, process all foreground uids and EJs immediately,
                // while others will be processed after a delay of 3 seconds.
                mService.getJobStore().forEachJob(mShouldRushEvaluation, mDeviceIdleUpdateFunctor);
                mHandler.sendEmptyMessageDelayed(PROCESS_BACKGROUND_JOBS, BACKGROUND_JOBS_DELAY);
            }
        }
Loading