diff options
| -rw-r--r-- | api/current.txt | 4 | ||||
| -rw-r--r-- | api/system-current.txt | 4 | ||||
| -rw-r--r-- | api/test-current.txt | 4 | ||||
| -rw-r--r-- | core/java/android/app/job/JobInfo.java | 35 | ||||
| -rw-r--r-- | services/core/java/com/android/server/job/JobSchedulerService.java | 5 | ||||
| -rw-r--r-- | services/core/java/com/android/server/job/JobStore.java | 15 | ||||
| -rw-r--r-- | services/core/java/com/android/server/job/controllers/JobStatus.java | 2 |
7 files changed, 60 insertions, 9 deletions
diff --git a/api/current.txt b/api/current.txt index 42e72e33f487..693d9f4223a8 100644 --- a/api/current.txt +++ b/api/current.txt @@ -6166,6 +6166,7 @@ package android.app.job { method public int describeContents(); method public int getBackoffPolicy(); method public android.os.PersistableBundle getExtras(); + method public long getFlexMillis(); method public int getId(); method public long getInitialBackoffMillis(); method public long getIntervalMillis(); @@ -6183,6 +6184,8 @@ package android.app.job { field public static final android.os.Parcelable.Creator<android.app.job.JobInfo> CREATOR; 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 long MIN_FLEX_MILLIS = 300000L; // 0x493e0L + field public static final long MIN_PERIOD_MILLIS = 3600000L; // 0x36ee80L 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 @@ -6196,6 +6199,7 @@ package android.app.job { 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 setPeriodic(long, long); 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); diff --git a/api/system-current.txt b/api/system-current.txt index b34a7f4806af..d4a97b650fa2 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -6381,6 +6381,7 @@ package android.app.job { method public int describeContents(); method public int getBackoffPolicy(); method public android.os.PersistableBundle getExtras(); + method public long getFlexMillis(); method public int getId(); method public long getInitialBackoffMillis(); method public long getIntervalMillis(); @@ -6398,6 +6399,8 @@ package android.app.job { field public static final android.os.Parcelable.Creator<android.app.job.JobInfo> CREATOR; 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 long MIN_FLEX_MILLIS = 300000L; // 0x493e0L + field public static final long MIN_PERIOD_MILLIS = 3600000L; // 0x36ee80L 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 @@ -6411,6 +6414,7 @@ package android.app.job { 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 setPeriodic(long, long); 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); diff --git a/api/test-current.txt b/api/test-current.txt index bcab75bf5d37..2f24953ce7da 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -6168,6 +6168,7 @@ package android.app.job { method public int describeContents(); method public int getBackoffPolicy(); method public android.os.PersistableBundle getExtras(); + method public long getFlexMillis(); method public int getId(); method public long getInitialBackoffMillis(); method public long getIntervalMillis(); @@ -6185,6 +6186,8 @@ package android.app.job { field public static final android.os.Parcelable.Creator<android.app.job.JobInfo> CREATOR; 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 long MIN_FLEX_MILLIS = 300000L; // 0x493e0L + field public static final long MIN_PERIOD_MILLIS = 3600000L; // 0x36ee80L 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 @@ -6198,6 +6201,7 @@ package android.app.job { 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 setPeriodic(long, long); 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); diff --git a/core/java/android/app/job/JobInfo.java b/core/java/android/app/job/JobInfo.java index 0d9e7787a236..b899710c4feb 100644 --- a/core/java/android/app/job/JobInfo.java +++ b/core/java/android/app/job/JobInfo.java @@ -64,6 +64,11 @@ public class JobInfo implements Parcelable { */ public static final int BACKOFF_POLICY_EXPONENTIAL = 1; + /* Minimum interval for a periodic job, in milliseconds. */ + public static final long MIN_PERIOD_MILLIS = 60 * 60 * 1000L; // 60 minutes + /* Minimum flex for a periodic job, in milliseconds. */ + public static final long MIN_FLEX_MILLIS = 5 * 60 * 1000L; // 5 minutes + /** * Default type of backoff. * @hide @@ -83,6 +88,7 @@ public class JobInfo implements Parcelable { private final boolean isPeriodic; private final boolean isPersisted; private final long intervalMillis; + private final long flexMillis; private final long initialBackoffMillis; private final int backoffPolicy; @@ -165,7 +171,17 @@ public class JobInfo implements Parcelable { * job does not recur periodically. */ public long getIntervalMillis() { - return intervalMillis; + return intervalMillis >= MIN_PERIOD_MILLIS ? intervalMillis : MIN_PERIOD_MILLIS; + } + + /** + * Flex time for this job. Only valid if this is a periodic job. + */ + public long getFlexMillis() { + long interval = getIntervalMillis(); + long percentClamp = 5 * interval / 100; + long clampedFlex = Math.max(flexMillis, Math.max(percentClamp, MIN_FLEX_MILLIS)); + return clampedFlex <= interval ? clampedFlex : interval; } /** @@ -216,6 +232,7 @@ public class JobInfo implements Parcelable { isPeriodic = in.readInt() == 1; isPersisted = in.readInt() == 1; intervalMillis = in.readLong(); + flexMillis = in.readLong(); initialBackoffMillis = in.readLong(); backoffPolicy = in.readInt(); hasEarlyConstraint = in.readInt() == 1; @@ -234,6 +251,7 @@ public class JobInfo implements Parcelable { isPeriodic = b.mIsPeriodic; isPersisted = b.mIsPersisted; intervalMillis = b.mIntervalMillis; + flexMillis = b.mFlexMillis; initialBackoffMillis = b.mInitialBackoffMillis; backoffPolicy = b.mBackoffPolicy; hasEarlyConstraint = b.mHasEarlyConstraint; @@ -258,6 +276,7 @@ public class JobInfo implements Parcelable { out.writeInt(isPeriodic ? 1 : 0); out.writeInt(isPersisted ? 1 : 0); out.writeLong(intervalMillis); + out.writeLong(flexMillis); out.writeLong(initialBackoffMillis); out.writeInt(backoffPolicy); out.writeInt(hasEarlyConstraint ? 1 : 0); @@ -299,6 +318,7 @@ public class JobInfo implements Parcelable { private boolean mHasEarlyConstraint; private boolean mHasLateConstraint; private long mIntervalMillis; + private long mFlexMillis; // Back-off parameters. private long mInitialBackoffMillis = DEFAULT_INITIAL_BACKOFF_MILLIS; private int mBackoffPolicy = DEFAULT_BACKOFF_POLICY; @@ -373,8 +393,21 @@ public class JobInfo implements Parcelable { * @param intervalMillis Millisecond interval for which this job will repeat. */ public Builder setPeriodic(long intervalMillis) { + return setPeriodic(intervalMillis, intervalMillis); + } + + /** + * Specify that this job should recur with the provided interval and flex. The job can + * execute at any time in a window of flex length at the end of the period. + * @param intervalMillis Millisecond interval for which this job will repeat. + * @param flexMillis Millisecond flex for this job. Flex is clamped to be at least + * {@link #MIN_FLEX_MILLIS} or 5 percent of the period, whichever is + * higher. + */ + public Builder setPeriodic(long intervalMillis, long flexMillis) { mIsPeriodic = true; mIntervalMillis = intervalMillis; + mFlexMillis = flexMillis; mHasEarlyConstraint = mHasLateConstraint = true; return this; } diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java index 4eabe3684e4f..3530d80577c7 100644 --- a/services/core/java/com/android/server/job/JobSchedulerService.java +++ b/services/core/java/com/android/server/job/JobSchedulerService.java @@ -613,9 +613,10 @@ public class JobSchedulerService extends com.android.server.SystemService if (periodicToReschedule.hasDeadlineConstraint()) { runEarly = Math.max(periodicToReschedule.getLatestRunTimeElapsed() - elapsedNow, 0L); } - long newEarliestRunTimeElapsed = elapsedNow + runEarly; + long flex = periodicToReschedule.getJob().getFlexMillis(); long period = periodicToReschedule.getJob().getIntervalMillis(); - long newLatestRuntimeElapsed = newEarliestRunTimeElapsed + period; + long newLatestRuntimeElapsed = elapsedNow + runEarly + period; + long newEarliestRunTimeElapsed = newLatestRuntimeElapsed - flex; if (DEBUG) { Slog.v(TAG, "Rescheduling executed periodic. New execution window [" + diff --git a/services/core/java/com/android/server/job/JobStore.java b/services/core/java/com/android/server/job/JobStore.java index 472e8f6ff06c..b8aa9dd7d156 100644 --- a/services/core/java/com/android/server/job/JobStore.java +++ b/services/core/java/com/android/server/job/JobStore.java @@ -397,6 +397,7 @@ public class JobStore { if (jobStatus.getJob().isPeriodic()) { out.startTag(null, XML_TAG_PERIODIC); out.attribute(null, "period", Long.toString(job.getIntervalMillis())); + out.attribute(null, "flex", Long.toString(job.getFlexMillis())); } else { out.startTag(null, XML_TAG_ONEOFF); } @@ -594,13 +595,17 @@ public class JobStore { String val = parser.getAttributeValue(null, "period"); final long periodMillis = Long.valueOf(val); jobBuilder.setPeriodic(periodMillis); - // As a sanity check, cap the recreated run time to be no later than 2 periods + val = parser.getAttributeValue(null, "flex"); + final long flexMillis = (val != null) ? Long.valueOf(val) : periodMillis; + // As a sanity check, cap the recreated run time to be no later than flex+period // from now. This is the latest the periodic could be pushed out. This could - // happen if the periodic ran early (at the start of its period), and then the + // happen if the periodic ran early (at flex time before period), and then the // device rebooted. - if (elapsedRuntimes.second > elapsedNow + 2 * periodMillis) { - final long clampedEarlyRuntimeElapsed = elapsedNow + periodMillis; - final long clampedLateRuntimeElapsed = elapsedNow + 2 * periodMillis; + if (elapsedRuntimes.second > elapsedNow + periodMillis + flexMillis) { + final long clampedLateRuntimeElapsed = elapsedNow + flexMillis + + periodMillis; + final long clampedEarlyRuntimeElapsed = clampedLateRuntimeElapsed + - flexMillis; Slog.w(TAG, String.format("Periodic job for uid='%d' persisted run-time is" + " too big [%s, %s]. Clamping to [%s,%s]", diff --git a/services/core/java/com/android/server/job/controllers/JobStatus.java b/services/core/java/com/android/server/job/controllers/JobStatus.java index c02611f4fdce..060a93ef8ed9 100644 --- a/services/core/java/com/android/server/job/controllers/JobStatus.java +++ b/services/core/java/com/android/server/job/controllers/JobStatus.java @@ -96,8 +96,8 @@ public class JobStatus { final long elapsedNow = SystemClock.elapsedRealtime(); if (job.isPeriodic()) { - earliestRunTimeElapsedMillis = elapsedNow; latestRunTimeElapsedMillis = elapsedNow + job.getIntervalMillis(); + earliestRunTimeElapsedMillis = latestRunTimeElapsedMillis - job.getFlexMillis(); } else { earliestRunTimeElapsedMillis = job.hasEarlyConstraint() ? elapsedNow + job.getMinLatencyMillis() : NO_EARLIEST_RUNTIME; |