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

Commit 900c67fc authored by Matthew Williams's avatar Matthew Williams
Browse files

Add job persistance as a setter in the API

Bug: 15936795
Change-Id: I11e5a722bab5838dc151670256ed09dfaa7fdaa7
parent 244911f9
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -5492,6 +5492,7 @@ package android.app.job {
    method public int getNetworkCapabilities();
    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);
@@ -5508,6 +5509,7 @@ 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);
+25 −6
Original line number Diff line number Diff line
@@ -64,7 +64,6 @@ public class JobInfo implements Parcelable {
    }

    private final int jobId;
    // TODO: Change this to use PersistableBundle when that lands in master.
    private final PersistableBundle extras;
    private final ComponentName service;
    private final boolean requireCharging;
@@ -75,6 +74,7 @@ public class JobInfo implements Parcelable {
    private final long minLatencyMillis;
    private final long maxExecutionDelayMillis;
    private final boolean isPeriodic;
    private final boolean isPersisted;
    private final long intervalMillis;
    private final long initialBackoffMillis;
    private final int backoffPolicy;
@@ -144,6 +144,13 @@ public class JobInfo implements Parcelable {
        return isPeriodic;
    }

    /**
     * @return Whether or not this job should be persisted across device reboots.
     */
    public boolean isPersisted() {
        return isPersisted;
    }

    /**
     * Set to the interval between occurrences of this job. This value is <b>not</b> set if the
     * job does not recur periodically.
@@ -197,6 +204,7 @@ public class JobInfo implements Parcelable {
        minLatencyMillis = in.readLong();
        maxExecutionDelayMillis = in.readLong();
        isPeriodic = in.readInt() == 1;
        isPersisted = in.readInt() == 1;
        intervalMillis = in.readLong();
        initialBackoffMillis = in.readLong();
        backoffPolicy = in.readInt();
@@ -214,6 +222,7 @@ public class JobInfo implements Parcelable {
        minLatencyMillis = b.mMinLatencyMillis;
        maxExecutionDelayMillis = b.mMaxExecutionDelayMillis;
        isPeriodic = b.mIsPeriodic;
        isPersisted = b.mIsPersisted;
        intervalMillis = b.mIntervalMillis;
        initialBackoffMillis = b.mInitialBackoffMillis;
        backoffPolicy = b.mBackoffPolicy;
@@ -237,6 +246,7 @@ public class JobInfo implements Parcelable {
        out.writeLong(minLatencyMillis);
        out.writeLong(maxExecutionDelayMillis);
        out.writeInt(isPeriodic ? 1 : 0);
        out.writeInt(isPersisted ? 1 : 0);
        out.writeLong(intervalMillis);
        out.writeLong(initialBackoffMillis);
        out.writeInt(backoffPolicy);
@@ -265,6 +275,7 @@ public class JobInfo implements Parcelable {
        private boolean mRequiresCharging;
        private boolean mRequiresDeviceIdle;
        private int mNetworkCapabilities;
        private boolean mIsPersisted;
        // One-off parameters.
        private long mMinLatencyMillis;
        private long mMaxExecutionDelayMillis;
@@ -342,11 +353,6 @@ public class JobInfo implements Parcelable {
         * Specify that this job should recur with the provided interval, not more than once per
         * period. You have no control over when within this interval this job will be executed,
         * only the guarantee that it will be executed at most once within this interval.
         * A periodic job will be repeated until the phone is turned off, however it will only be
         * persisted beyond boot if the client app has declared the
         * {@link android.Manifest.permission#RECEIVE_BOOT_COMPLETED} permission. You can schedule
         * periodic jobs without this permission, they simply will cease to exist after the phone
         * restarts.
         * Setting this function on the builder with {@link #setMinimumLatency(long)} or
         * {@link #setOverrideDeadline(long)} will result in an error.
         * @param intervalMillis Millisecond interval for which this job will repeat.
@@ -406,6 +412,19 @@ public class JobInfo implements Parcelable {
            return this;
        }

        /**
         * Set whether or not to persist this job across device reboots. This will only have an
         * effect if your application holds the permission
         * {@link android.Manifest.permission#RECEIVE_BOOT_COMPLETED}. Otherwise an exception will
         * be thrown.
         * @param isPersisted True to indicate that the job will be written to disk and loaded at
         *                    boot.
         */
        public Builder setIsPersisted(boolean isPersisted) {
            mIsPersisted = isPersisted;
            return this;
        }

        /**
         * @return The job object to hand to the JobScheduler. This object is immutable.
         */
+9 −6
Original line number Diff line number Diff line
@@ -140,12 +140,10 @@ public class JobSchedulerService extends com.android.server.SystemService
     * This cancels the job if it's already been scheduled, and replaces it with the one provided.
     * @param job JobInfo object containing execution parameters
     * @param uId The package identifier of the application this job is for.
     * @param canPersistJob Whether or not the client has the appropriate permissions for
     *                       persisting this job.
     * @return Result of this operation. See <code>JobScheduler#RESULT_*</code> return codes.
     */
    public int schedule(JobInfo job, int uId, boolean canPersistJob) {
        JobStatus jobStatus = new JobStatus(job, uId, canPersistJob);
    public int schedule(JobInfo job, int uId) {
        JobStatus jobStatus = new JobStatus(job, uId);
        cancelJob(uId, job.getId());
        startTrackingJob(jobStatus);
        return JobScheduler.RESULT_SUCCESS;
@@ -668,11 +666,16 @@ public class JobSchedulerService extends com.android.server.SystemService
            final int uid = Binder.getCallingUid();

            enforceValidJobRequest(uid, job);
            final boolean canPersist = canPersistJobs(pid, uid);
            if (job.isPersisted()) {
                if (!canPersistJobs(pid, uid)) {
                    throw new IllegalArgumentException("Error: requested job be persisted without"
                            + " holding RECEIVE_BOOT_COMPLETED permission.");
                }
            }

            long ident = Binder.clearCallingIdentity();
            try {
                return JobSchedulerService.this.schedule(job, uid, canPersist);
                return JobSchedulerService.this.schedule(job, uid);
            } finally {
                Binder.restoreCallingIdentity(ident);
            }
+6 −2
Original line number Diff line number Diff line
@@ -160,7 +160,9 @@ public class JobStore {
            }
            return false;
        }
        if (jobStatus.isPersisted()) {
            maybeWriteStatusToDiskAsync();
        }
        return removed;
    }

@@ -429,7 +431,8 @@ public class JobStore {
            }
        }

        private List<JobStatus> readJobMapImpl(FileInputStream fis) throws XmlPullParserException, IOException {
        private List<JobStatus> readJobMapImpl(FileInputStream fis)
                throws XmlPullParserException, IOException {
            XmlPullParser parser = Xml.newPullParser();
            parser.setInput(fis, null);

@@ -498,6 +501,7 @@ public class JobStore {
            // Read out job identifier attributes.
            try {
                jobBuilder = buildBuilderFromXml(parser);
                jobBuilder.setIsPersisted(true);
                uid = Integer.valueOf(parser.getAttributeValue(null, "uid"));
            } catch (NumberFormatException e) {
                Slog.e(TAG, "Error parsing job's required fields, skipping");
+9 −12
Original line number Diff line number Diff line
@@ -43,9 +43,6 @@ public class JobStatus {
    final JobInfo job;
    final int uId;

    /** At reschedule time we need to know whether to update job on disk. */
    final boolean persisted;

    // Constraints.
    final AtomicBoolean chargingConstraintSatisfied = new AtomicBoolean();
    final AtomicBoolean timeDelayConstraintSatisfied = new AtomicBoolean();
@@ -72,16 +69,15 @@ public class JobStatus {
        return uId;
    }

    private JobStatus(JobInfo job, int uId, boolean persisted, int numFailures) {
    private JobStatus(JobInfo job, int uId, int numFailures) {
        this.job = job;
        this.uId = uId;
        this.numFailures = numFailures;
        this.persisted = persisted;
    }

    /** Create a newly scheduled job. */
    public JobStatus(JobInfo job, int uId, boolean persisted) {
        this(job, uId, persisted, 0);
    public JobStatus(JobInfo job, int uId) {
        this(job, uId, 0);

        final long elapsedNow = SystemClock.elapsedRealtime();

@@ -105,7 +101,7 @@ public class JobStatus {
     */
    public JobStatus(JobInfo job, int uId, long earliestRunTimeElapsedMillis,
                      long latestRunTimeElapsedMillis) {
        this(job, uId, true, 0);
        this(job, uId, 0);

        this.earliestRunTimeElapsedMillis = earliestRunTimeElapsedMillis;
        this.latestRunTimeElapsedMillis = latestRunTimeElapsedMillis;
@@ -114,7 +110,7 @@ public class JobStatus {
    /** Create a new job to be rescheduled with the provided parameters. */
    public JobStatus(JobStatus rescheduling, long newEarliestRuntimeElapsedMillis,
                      long newLatestRuntimeElapsedMillis, int backoffAttempt) {
        this(rescheduling.job, rescheduling.getUid(), rescheduling.isPersisted(), backoffAttempt);
        this(rescheduling.job, rescheduling.getUid(), backoffAttempt);

        earliestRunTimeElapsedMillis = newEarliestRuntimeElapsedMillis;
        latestRunTimeElapsedMillis = newLatestRuntimeElapsedMillis;
@@ -172,6 +168,10 @@ public class JobStatus {
        return job.isRequireDeviceIdle();
    }

    public boolean isPersisted() {
        return job.isPersisted();
    }

    public long getEarliestRunTime() {
        return earliestRunTimeElapsedMillis;
    }
@@ -180,9 +180,6 @@ public class JobStatus {
        return latestRunTimeElapsedMillis;
    }

    public boolean isPersisted() {
        return persisted;
    }
    /**
     * @return Whether or not this job is ready to run, based on its requirements.
     */
Loading