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

Commit bafeeb98 authored by Matthew Williams's avatar Matthew Williams
Browse files

JobScheduler needs to flush queue on charging

Also make it illegal to schedule a job with no constraints.
BUG: 16877705
Change-Id: Iae57286bc4f73163a7e3c9d2d531623fd50f1f72
parent de3af82c
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -434,6 +434,12 @@ public class JobInfo implements Parcelable {
         * @return The job object to hand to the JobScheduler. This object is immutable.
         */
        public JobInfo build() {
            // Allow tasks with no constraints. What am I, a database?
            if (!mHasEarlyConstraint && !mHasLateConstraint && !mRequiresCharging &&
                    !mRequiresDeviceIdle && mNetworkCapabilities == NetworkType.NONE) {
                throw new IllegalArgumentException("You're trying to build a job with no " +
                        "constraints, this is not allowed.");
            }
            mExtras = new PersistableBundle(mExtras);  // Make our own copy.
            // Check that a deadline was not set on a periodic job.
            if (mIsPeriodic && (mMaxExecutionDelayMillis != 0L)) {
+7 −1
Original line number Diff line number Diff line
@@ -22,7 +22,13 @@ import android.content.Context;

/**
 * Class for scheduling various types of jobs with the scheduling framework on the device.
 *
 * See {@link android.app.job.JobInfo} for more description of the types of jobs that can be run
 * and how to construct them.
 * The framework will be intelligent about when you receive your callbacks, and attempt to batch
 * and defer them as much as possible. Typically if you don't specify a deadline on your job, it
 * can be run at any moment depending on the current state of the JobScheduler's internal queue,
 * however it might be deferred as long as until the next time the device is connected to a power
 * source.
 * <p>You do not
 * instantiate this class directly; instead, retrieve it through
 * {@link android.content.Context#getSystemService
+4 −1
Original line number Diff line number Diff line
@@ -162,6 +162,7 @@ public class JobSchedulerService extends com.android.server.SystemService
        JobStatus jobStatus = new JobStatus(job, uId);
        cancelJob(uId, job.getId());
        startTrackingJob(jobStatus);
        mHandler.obtainMessage(MSG_CHECK_JOB).sendToTarget();
        return JobScheduler.RESULT_SUCCESS;
    }

@@ -507,7 +508,9 @@ public class JobSchedulerService extends com.android.server.SystemService
                case MSG_JOB_EXPIRED:
                    synchronized (mJobs) {
                        JobStatus runNow = (JobStatus) message.obj;
                        if (!mPendingJobs.contains(runNow)) {
                        // runNow can be null, which is a controller's way of indicating that its
                        // state is such that all ready jobs should be run immediately.
                        if (runNow != null && !mPendingJobs.contains(runNow)) {
                            mPendingJobs.add(runNow);
                        }
                    }
+2 −1
Original line number Diff line number Diff line
@@ -33,7 +33,8 @@ public interface StateChangedListener {
    /**
     * Called by the controller to notify the JobManager that regardless of the state of the task,
     * it must be run immediately.
     * @param jobStatus The state of the task which is to be run immediately.
     * @param jobStatus The state of the task which is to be run immediately. <strong>null
     *                  indicates to the scheduler that any ready jobs should be flushed.</strong>
     */
    public void onRunJobNow(JobStatus jobStatus);
}
+23 −8
Original line number Diff line number Diff line
@@ -84,15 +84,15 @@ public class BatteryController extends StateController {

    @Override
    public void maybeStartTrackingJob(JobStatus taskStatus) {
        if (taskStatus.hasChargingConstraint()) {
        final boolean isOnStablePower = mChargeTracker.isOnStablePower();
        if (taskStatus.hasChargingConstraint()) {
            synchronized (mTrackedTasks) {
                mTrackedTasks.add(taskStatus);
                taskStatus.chargingConstraintSatisfied.set(isOnStablePower);
            }
            if (isOnStablePower) {
                mStateChangedListener.onControllerStateChanged();
        }
        if (isOnStablePower) {
            mChargeTracker.setStableChargingAlarm();
        }
    }

@@ -119,9 +119,15 @@ public class BatteryController extends StateController {
                }
            }
        }
        // Let the scheduler know that state has changed. This may or may not result in an
        // execution.
        if (reportChange) {
            mStateChangedListener.onControllerStateChanged();
        }
        // Also tell the scheduler that any ready jobs should be flushed.
        if (stablePower) {
            mStateChangedListener.onRunJobNow(null);
        }
    }

    public class ChargingTracker extends BroadcastReceiver {
@@ -196,9 +202,7 @@ public class BatteryController extends StateController {
                }
                // Set up an alarm for ACTION_CHARGING_STABLE - we don't want to kick off tasks
                // here if the user unplugs the phone immediately.
                mAlarm.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
                        SystemClock.elapsedRealtime() + STABLE_CHARGING_THRESHOLD_MILLIS,
                        mStableChargingTriggerIntent);
                setStableChargingAlarm();
                mCharging = true;
            } else if (Intent.ACTION_POWER_DISCONNECTED.equals(action)) {
                if (DEBUG) {
@@ -211,7 +215,7 @@ public class BatteryController extends StateController {
            }else if (ACTION_CHARGING_STABLE.equals(action)) {
                // Here's where we actually do the notify for a task being ready.
                if (DEBUG) {
                    Slog.d(TAG, "Battery connected fired @ " + SystemClock.elapsedRealtime()
                    Slog.d(TAG, "Stable charging fired @ " + SystemClock.elapsedRealtime()
                            + " charging: " + mCharging);
                }
                if (mCharging) {  // Should never receive this intent if mCharging is false.
@@ -219,6 +223,17 @@ public class BatteryController extends StateController {
                }
            }
        }

        void setStableChargingAlarm() {
            final long alarmTriggerElapsed =
                    SystemClock.elapsedRealtime() + STABLE_CHARGING_THRESHOLD_MILLIS;
            if (DEBUG) {
                Slog.d(TAG, "Setting stable alarm to go off in " +
                        (STABLE_CHARGING_THRESHOLD_MILLIS / 1000) + "s");
            }
            mAlarm.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, alarmTriggerElapsed,
                    mStableChargingTriggerIntent);
        }
    }

    @Override