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

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

Implement API review feedback for JobScheduler

BUG: 17005336

Took the opportunity to clean up some back-off logic

Change-Id: Ibc8ae34d1d44dd064ba071e4cbad17872f7e38cf
parent acb570cd
Loading
Loading
Loading
Loading
+10 −14
Original line number Diff line number Diff line
@@ -5643,19 +5643,21 @@ package android.app.job {
    method public long getIntervalMillis();
    method public long getMaxExecutionDelayMillis();
    method public long getMinLatencyMillis();
    method public int getNetworkCapabilities();
    method public int getNetworkType();
    method public android.content.ComponentName getService();
    method public boolean isPeriodic();
    method public boolean isPersisted();
    method public boolean isRequireCharging();
    method public boolean isRequireDeviceIdle();
    method public void writeToParcel(android.os.Parcel, int);
    field public static final int BACKOFF_POLICY_EXPONENTIAL = 1; // 0x1
    field public static final int BACKOFF_POLICY_LINEAR = 0; // 0x0
    field public static final android.os.Parcelable.Creator CREATOR;
  }
  public static abstract interface JobInfo.BackoffPolicy {
    field public static final int EXPONENTIAL = 1; // 0x1
    field public static final int LINEAR = 0; // 0x0
    field public static final long DEFAULT_INITIAL_BACKOFF_MILLIS = 30000L; // 0x7530L
    field public static final long MAX_BACKOFF_DELAY_MILLIS = 18000000L; // 0x112a880L
    field public static final int NETWORK_TYPE_ANY = 1; // 0x1
    field public static final int NETWORK_TYPE_NONE = 0; // 0x0
    field public static final int NETWORK_TYPE_UNMETERED = 2; // 0x2
  }
  public static final class JobInfo.Builder {
@@ -5663,21 +5665,15 @@ package android.app.job {
    method public android.app.job.JobInfo build();
    method public android.app.job.JobInfo.Builder setBackoffCriteria(long, int);
    method public android.app.job.JobInfo.Builder setExtras(android.os.PersistableBundle);
    method public android.app.job.JobInfo.Builder setIsPersisted(boolean);
    method public android.app.job.JobInfo.Builder setMinimumLatency(long);
    method public android.app.job.JobInfo.Builder setOverrideDeadline(long);
    method public android.app.job.JobInfo.Builder setPeriodic(long);
    method public android.app.job.JobInfo.Builder setRequiredNetworkCapabilities(int);
    method public android.app.job.JobInfo.Builder setPersisted(boolean);
    method public android.app.job.JobInfo.Builder setRequiredNetworkType(int);
    method public android.app.job.JobInfo.Builder setRequiresCharging(boolean);
    method public android.app.job.JobInfo.Builder setRequiresDeviceIdle(boolean);
  }
  public static abstract interface JobInfo.NetworkType {
    field public static final int ANY = 1; // 0x1
    field public static final int NONE = 0; // 0x0
    field public static final int UNMETERED = 2; // 0x2
  }
  public class JobParameters implements android.os.Parcelable {
    method public int describeContents();
    method public android.os.PersistableBundle getExtras();
+1 −1
Original line number Diff line number Diff line
@@ -27,6 +27,6 @@ import android.app.job.JobParameters;
oneway interface IJobService {
    /** Begin execution of application's job. */
    void startJob(in JobParameters jobParams);
    /** Stop execution of application's task. */
    /** Stop execution of application's job. */
    void stopJob(in JobParameters jobParams);
}
+52 −44
Original line number Diff line number Diff line
@@ -17,7 +17,6 @@
package android.app.job;

import android.content.ComponentName;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.PersistableBundle;
@@ -31,40 +30,45 @@ import android.os.PersistableBundle;
 * accomplish. Doing otherwise with throw an exception in your app.
 */
public class JobInfo implements Parcelable {
    public interface NetworkType {
    /** Default. */
        public final int NONE = 0;
    public static final int NETWORK_TYPE_NONE = 0;
    /** This job requires network connectivity. */
        public final int ANY = 1;
    public static final int NETWORK_TYPE_ANY = 1;
    /** This job requires network connectivity that is unmetered. */
        public final int UNMETERED = 2;
    }
    public static final int NETWORK_TYPE_UNMETERED = 2;

    /**
     * Amount of backoff a job has initially by default, in milliseconds.
     * @hide.
     */
    public static final long DEFAULT_INITIAL_BACKOFF_MILLIS = 5000L;
    public static final long DEFAULT_INITIAL_BACKOFF_MILLIS = 30000L;  // 30 seconds.

    /**
     * Default type of backoff.
     * @hide
     * Maximum backoff we allow for a job, in milliseconds.
     */
    public static final int DEFAULT_BACKOFF_POLICY = BackoffPolicy.EXPONENTIAL;
    public static final long MAX_BACKOFF_DELAY_MILLIS = 5 * 60 * 60 * 1000;  // 5 hours.

    /**
     * Maximum backoff we allow for a job, in milliseconds.
     * @hide
     * Linearly back-off a failed job. See
     * {@link android.app.job.JobInfo.Builder#setBackoffCriteria(long, int)}
     * retry_time(current_time, num_failures) =
     *     current_time + initial_backoff_millis * num_failures, num_failures >= 1
     */
    public static final long MAX_BACKOFF_DELAY_MILLIS = 24 * 60 * 60 * 1000;  // 24 hours.
    public static final int BACKOFF_POLICY_LINEAR = 0;

    /**
     * Linear: retry_time(failure_time, t) = failure_time + initial_retry_delay * t, t >= 1
     * Expon: retry_time(failure_time, t) = failure_time + initial_retry_delay ^ t, t >= 1
     * Exponentially back-off a failed job. See
     * {@link android.app.job.JobInfo.Builder#setBackoffCriteria(long, int)}
     *
     * retry_time(current_time, num_failures) =
     *     current_time + initial_backoff_millis * 2 ^ (num_failures - 1), num_failures >= 1
     */
    public interface BackoffPolicy {
        public final int LINEAR = 0;
        public final int EXPONENTIAL = 1;
    }
    public static final int BACKOFF_POLICY_EXPONENTIAL = 1;

    /**
     * Default type of backoff.
     * @hide
     */
    public static final int DEFAULT_BACKOFF_POLICY = BACKOFF_POLICY_EXPONENTIAL;

    private final int jobId;
    private final PersistableBundle extras;
@@ -73,7 +77,7 @@ public class JobInfo implements Parcelable {
    private final boolean requireDeviceIdle;
    private final boolean hasEarlyConstraint;
    private final boolean hasLateConstraint;
    private final int networkCapabilities;
    private final int networkType;
    private final long minLatencyMillis;
    private final long maxExecutionDelayMillis;
    private final boolean isPeriodic;
@@ -118,10 +122,12 @@ public class JobInfo implements Parcelable {
    }

    /**
     * See {@link android.app.job.JobInfo.NetworkType} for a description of this value.
     * One of {@link android.app.job.JobInfo#NETWORK_TYPE_ANY},
     * {@link android.app.job.JobInfo#NETWORK_TYPE_NONE}, or
     * {@link android.app.job.JobInfo#NETWORK_TYPE_UNMETERED}.
     */
    public int getNetworkCapabilities() {
        return networkCapabilities;
    public int getNetworkType() {
        return networkType;
    }

    /**
@@ -172,8 +178,9 @@ public class JobInfo implements Parcelable {
    }

    /**
     * See {@link android.app.job.JobInfo.BackoffPolicy} for an explanation of the values this field
     * can take. This defaults to exponential.
     * One of either {@link android.app.job.JobInfo#BACKOFF_POLICY_EXPONENTIAL}, or
     * {@link android.app.job.JobInfo#BACKOFF_POLICY_LINEAR}, depending on which criteria you set
     * when creating this job.
     */
    public int getBackoffPolicy() {
        return backoffPolicy;
@@ -203,7 +210,7 @@ public class JobInfo implements Parcelable {
        service = in.readParcelable(null);
        requireCharging = in.readInt() == 1;
        requireDeviceIdle = in.readInt() == 1;
        networkCapabilities = in.readInt();
        networkType = in.readInt();
        minLatencyMillis = in.readLong();
        maxExecutionDelayMillis = in.readLong();
        isPeriodic = in.readInt() == 1;
@@ -221,7 +228,7 @@ public class JobInfo implements Parcelable {
        service = b.mJobService;
        requireCharging = b.mRequiresCharging;
        requireDeviceIdle = b.mRequiresDeviceIdle;
        networkCapabilities = b.mNetworkCapabilities;
        networkType = b.mNetworkType;
        minLatencyMillis = b.mMinLatencyMillis;
        maxExecutionDelayMillis = b.mMaxExecutionDelayMillis;
        isPeriodic = b.mIsPeriodic;
@@ -245,7 +252,7 @@ public class JobInfo implements Parcelable {
        out.writeParcelable(service, flags);
        out.writeInt(requireCharging ? 1 : 0);
        out.writeInt(requireDeviceIdle ? 1 : 0);
        out.writeInt(networkCapabilities);
        out.writeInt(networkType);
        out.writeLong(minLatencyMillis);
        out.writeLong(maxExecutionDelayMillis);
        out.writeInt(isPeriodic ? 1 : 0);
@@ -282,7 +289,7 @@ public class JobInfo implements Parcelable {
        // Requirements.
        private boolean mRequiresCharging;
        private boolean mRequiresDeviceIdle;
        private int mNetworkCapabilities;
        private int mNetworkType;
        private boolean mIsPersisted;
        // One-off parameters.
        private long mMinLatencyMillis;
@@ -320,15 +327,15 @@ public class JobInfo implements Parcelable {
        }

        /**
         * Set some description of the kind of network capabilities you would like to have. This
         * will be a parameter defined in {@link android.app.job.JobInfo.NetworkType}.
         * Not calling this function means the network is not necessary.
         * Set some description of the kind of network type your job needs to have.
         * Not calling this function means the network is not necessary, as the default is
         * {@link #NETWORK_TYPE_NONE}.
         * Bear in mind that calling this function defines network as a strict requirement for your
         * job if the network requested is not available your job will never run. See
         * job. If the network requested is not available your job will never run. See
         * {@link #setOverrideDeadline(long)} to change this behaviour.
         */
        public Builder setRequiredNetworkCapabilities(int networkCapabilities) {
            mNetworkCapabilities = networkCapabilities;
        public Builder setRequiredNetworkType(int networkType) {
            mNetworkType = networkType;
            return this;
        }

@@ -401,8 +408,8 @@ public class JobInfo implements Parcelable {

        /**
         * Set up the back-off/retry policy.
         * This defaults to some respectable values: {5 seconds, Exponential}. We cap back-off at
         * 1hr.
         * This defaults to some respectable values: {30 seconds, Exponential}. We cap back-off at
         * 5hrs.
         * Note that trying to set a backoff criteria for a job with
         * {@link #setRequiresDeviceIdle(boolean)} will throw an exception when you call build().
         * This is because back-off typically does not make sense for these types of jobs. See
@@ -411,7 +418,8 @@ public class JobInfo implements Parcelable {
         * mode.
         * @param initialBackoffMillis Millisecond time interval to wait initially when job has
         *                             failed.
         * @param backoffPolicy is one of {@link BackoffPolicy}
         * @param backoffPolicy is one of {@link #BACKOFF_POLICY_LINEAR} or
         * {@link #BACKOFF_POLICY_EXPONENTIAL}
         */
        public Builder setBackoffCriteria(long initialBackoffMillis, int backoffPolicy) {
            mBackoffPolicySet = true;
@@ -428,7 +436,7 @@ public class JobInfo implements Parcelable {
         * @param isPersisted True to indicate that the job will be written to disk and loaded at
         *                    boot.
         */
        public Builder setIsPersisted(boolean isPersisted) {
        public Builder setPersisted(boolean isPersisted) {
            mIsPersisted = isPersisted;
            return this;
        }
@@ -439,7 +447,7 @@ public class JobInfo implements Parcelable {
        public JobInfo build() {
            // Allow jobs with no constraints - What am I, a database?
            if (!mHasEarlyConstraint && !mHasLateConstraint && !mRequiresCharging &&
                    !mRequiresDeviceIdle && mNetworkCapabilities == NetworkType.NONE) {
                    !mRequiresDeviceIdle && mNetworkType == NETWORK_TYPE_NONE) {
                throw new IllegalArgumentException("You're trying to build a job with no " +
                        "constraints, this is not allowed.");
            }
+3 −6
Original line number Diff line number Diff line
@@ -17,9 +17,6 @@
package android.app.job;

import android.app.Service;
import android.app.job.IJobCallback;
import android.app.job.IJobService;
import android.app.job.IJobService.Stub;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
@@ -218,7 +215,7 @@ public abstract class JobService extends Service {
     *
     * <p>This will happen if the requirements specified at schedule time are no longer met. For
     * example you may have requested WiFi with
     * {@link android.app.job.JobInfo.Builder#setRequiredNetworkCapabilities(int)}, yet while your
     * {@link android.app.job.JobInfo.Builder#setRequiredNetworkType(int)}, yet while your
     * job was executing the user toggled WiFi. Another example is if you had specified
     * {@link android.app.job.JobInfo.Builder#setRequiresDeviceIdle(boolean)}, and the phone left its
     * idle maintenance window. You are solely responsible for the behaviour of your application
@@ -248,8 +245,8 @@ public abstract class JobService extends Service {
     *
     * @param params Parameters specifying system-provided info about this job, this was given to
     *               your application in {@link #onStartJob(JobParameters)}.
     * @param needsReschedule True if this job is complete, false if you want the JobManager to
     *                        reschedule you.
     * @param needsReschedule True if this job should be rescheduled according to the back-off
     *                        criteria specified at schedule-time. False otherwise.
     */
    public final void jobFinished(JobParameters params, boolean needsReschedule) {
        ensureHandler();
+1 −3
Original line number Diff line number Diff line
@@ -20,10 +20,8 @@ import android.app.job.JobInfo;
import android.app.job.JobParameters;
import android.app.job.JobScheduler;
import android.app.job.JobService;
import android.app.job.JobInfo.NetworkType;
import android.content.ComponentName;
import android.content.Context;
import android.util.Slog;

public class FullBackupJob extends JobService {
    private static final String TAG = "FullBackupJob";
@@ -40,7 +38,7 @@ public class FullBackupJob extends JobService {
        JobScheduler js = (JobScheduler) ctx.getSystemService(Context.JOB_SCHEDULER_SERVICE);
        JobInfo.Builder builder = new JobInfo.Builder(JOB_ID, sIdleService)
                .setRequiresDeviceIdle(true)
                .setRequiredNetworkCapabilities(NetworkType.UNMETERED)
                .setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
                .setRequiresCharging(true);
        if (minDelay > 0) {
            builder.setMinimumLatency(minDelay);
Loading