diff options
10 files changed, 99 insertions, 100 deletions
diff --git a/api/current.txt b/api/current.txt index a592b0e..58bde97 100644 --- a/api/current.txt +++ b/api/current.txt @@ -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(); diff --git a/core/java/android/app/job/IJobService.aidl b/core/java/android/app/job/IJobService.aidl index 63f8b81..7f55d29 100644 --- a/core/java/android/app/job/IJobService.aidl +++ b/core/java/android/app/job/IJobService.aidl @@ -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); } diff --git a/core/java/android/app/job/JobInfo.java b/core/java/android/app/job/JobInfo.java index e4ed470e..0d9e778 100644 --- a/core/java/android/app/job/JobInfo.java +++ b/core/java/android/app/job/JobInfo.java @@ -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; - /** This job requires network connectivity. */ - public final int ANY = 1; - /** This job requires network connectivity that is unmetered. */ - public final int UNMETERED = 2; - } + /** Default. */ + public static final int NETWORK_TYPE_NONE = 0; + /** This job requires network connectivity. */ + public static final int NETWORK_TYPE_ANY = 1; + /** This job requires network connectivity that is unmetered. */ + 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."); } diff --git a/core/java/android/app/job/JobService.java b/core/java/android/app/job/JobService.java index eea0268..940a530 100644 --- a/core/java/android/app/job/JobService.java +++ b/core/java/android/app/job/JobService.java @@ -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(); diff --git a/services/backup/java/com/android/server/backup/FullBackupJob.java b/services/backup/java/com/android/server/backup/FullBackupJob.java index deb2293..601f15e 100644 --- a/services/backup/java/com/android/server/backup/FullBackupJob.java +++ b/services/backup/java/com/android/server/backup/FullBackupJob.java @@ -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); diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java index 60f880c..379ec94 100644 --- a/services/core/java/com/android/server/job/JobSchedulerService.java +++ b/services/core/java/com/android/server/job/JobSchedulerService.java @@ -407,26 +407,26 @@ public class JobSchedulerService extends com.android.server.SystemService final JobInfo job = failureToReschedule.getJob(); final long initialBackoffMillis = job.getInitialBackoffMillis(); - final int backoffAttempt = failureToReschedule.getNumFailures() + 1; - long newEarliestRuntimeElapsed = elapsedNowMillis; + final int backoffAttempts = failureToReschedule.getNumFailures() + 1; + long delayMillis; switch (job.getBackoffPolicy()) { - case JobInfo.BackoffPolicy.LINEAR: - newEarliestRuntimeElapsed += initialBackoffMillis * backoffAttempt; + case JobInfo.BACKOFF_POLICY_LINEAR: + delayMillis = initialBackoffMillis * backoffAttempts; break; default: if (DEBUG) { Slog.v(TAG, "Unrecognised back-off policy, defaulting to exponential."); } - case JobInfo.BackoffPolicy.EXPONENTIAL: - newEarliestRuntimeElapsed += - Math.pow(initialBackoffMillis * 0.001, backoffAttempt) * 1000; + case JobInfo.BACKOFF_POLICY_EXPONENTIAL: + delayMillis = + (long) Math.scalb(initialBackoffMillis, backoffAttempts - 1); break; } - newEarliestRuntimeElapsed = - Math.min(newEarliestRuntimeElapsed, JobInfo.MAX_BACKOFF_DELAY_MILLIS); - return new JobStatus(failureToReschedule, newEarliestRuntimeElapsed, - JobStatus.NO_LATEST_RUNTIME, backoffAttempt); + delayMillis = + Math.min(delayMillis, JobInfo.MAX_BACKOFF_DELAY_MILLIS); + return new JobStatus(failureToReschedule, elapsedNowMillis + delayMillis, + JobStatus.NO_LATEST_RUNTIME, backoffAttempts); } /** diff --git a/services/core/java/com/android/server/job/JobStore.java b/services/core/java/com/android/server/job/JobStore.java index 46f557f..df12e1a 100644 --- a/services/core/java/com/android/server/job/JobStore.java +++ b/services/core/java/com/android/server/job/JobStore.java @@ -515,7 +515,7 @@ public class JobStore { // Read out job identifier attributes. try { jobBuilder = buildBuilderFromXml(parser); - jobBuilder.setIsPersisted(true); + jobBuilder.setPersisted(true); uid = Integer.valueOf(parser.getAttributeValue(null, "uid")); } catch (NumberFormatException e) { Slog.e(TAG, "Error parsing job's required fields, skipping"); @@ -622,11 +622,11 @@ public class JobStore { private void buildConstraintsFromXml(JobInfo.Builder jobBuilder, XmlPullParser parser) { String val = parser.getAttributeValue(null, "unmetered"); if (val != null) { - jobBuilder.setRequiredNetworkCapabilities(JobInfo.NetworkType.UNMETERED); + jobBuilder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED); } val = parser.getAttributeValue(null, "connectivity"); if (val != null) { - jobBuilder.setRequiredNetworkCapabilities(JobInfo.NetworkType.ANY); + jobBuilder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY); } val = parser.getAttributeValue(null, "idle"); if (val != null) { 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 a257ea0..6f5d3c2 100644 --- a/services/core/java/com/android/server/job/controllers/JobStatus.java +++ b/services/core/java/com/android/server/job/controllers/JobStatus.java @@ -159,11 +159,11 @@ public class JobStatus { } public boolean hasConnectivityConstraint() { - return job.getNetworkCapabilities() == JobInfo.NetworkType.ANY; + return job.getNetworkType() == JobInfo.NETWORK_TYPE_ANY; } public boolean hasUnmeteredConstraint() { - return job.getNetworkCapabilities() == JobInfo.NetworkType.UNMETERED; + return job.getNetworkType() == JobInfo.NETWORK_TYPE_UNMETERED; } public boolean hasChargingConstraint() { @@ -219,7 +219,7 @@ public class JobStatus { + ",u" + getUserId() + ",R=(" + formatRunTime(earliestRunTimeElapsedMillis, NO_EARLIEST_RUNTIME) + "," + formatRunTime(latestRunTimeElapsedMillis, NO_LATEST_RUNTIME) + ")" - + ",N=" + job.getNetworkCapabilities() + ",C=" + job.isRequireCharging() + + ",N=" + job.getNetworkType() + ",C=" + job.isRequireCharging() + ",I=" + job.isRequireDeviceIdle() + ",F=" + numFailures + ",P=" + job.isPersisted() + (isReady() ? "(READY)" : "") diff --git a/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java b/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java index 2b693a3..402f0dd 100644 --- a/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java +++ b/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java @@ -51,11 +51,11 @@ public class JobStoreTest extends AndroidTestCase { final JobInfo task = new Builder(taskId, mComponent) .setRequiresCharging(true) - .setRequiredNetworkCapabilities(JobInfo.NetworkType.ANY) - .setBackoffCriteria(initialBackoff, JobInfo.BackoffPolicy.EXPONENTIAL) + .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY) + .setBackoffCriteria(initialBackoff, JobInfo.BACKOFF_POLICY_EXPONENTIAL) .setOverrideDeadline(runByMillis) .setMinimumLatency(runFromMillis) - .setIsPersisted(true) + .setPersisted(true) .build(); final JobStatus ts = new JobStatus(task, SOME_UID); mTaskStoreUnderTest.add(ts); @@ -80,14 +80,14 @@ public class JobStoreTest extends AndroidTestCase { .setRequiresDeviceIdle(true) .setPeriodic(10000L) .setRequiresCharging(true) - .setIsPersisted(true) + .setPersisted(true) .build(); final JobInfo task2 = new Builder(12, mComponent) .setMinimumLatency(5000L) - .setBackoffCriteria(15000L, JobInfo.BackoffPolicy.LINEAR) + .setBackoffCriteria(15000L, JobInfo.BACKOFF_POLICY_LINEAR) .setOverrideDeadline(30000L) - .setRequiredNetworkCapabilities(JobInfo.NetworkType.UNMETERED) - .setIsPersisted(true) + .setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED) + .setPersisted(true) .build(); final JobStatus taskStatus1 = new JobStatus(task1, SOME_UID); final JobStatus taskStatus2 = new JobStatus(task2, SOME_UID); @@ -121,7 +121,7 @@ public class JobStoreTest extends AndroidTestCase { .setRequiresDeviceIdle(true) .setPeriodic(10000L) .setRequiresCharging(true) - .setIsPersisted(true); + .setPersisted(true); PersistableBundle extras = new PersistableBundle(); extras.putDouble("hello", 3.2); @@ -159,11 +159,11 @@ public class JobStoreTest extends AndroidTestCase { assertEquals("Invalid idle constraint.", first.isRequireDeviceIdle(), second.isRequireDeviceIdle()); assertEquals("Invalid unmetered constraint.", - first.getNetworkCapabilities() == JobInfo.NetworkType.UNMETERED, - second.getNetworkCapabilities() == JobInfo.NetworkType.UNMETERED); + first.getNetworkType() == JobInfo.NETWORK_TYPE_UNMETERED, + second.getNetworkType() == JobInfo.NETWORK_TYPE_UNMETERED); assertEquals("Invalid connectivity constraint.", - first.getNetworkCapabilities() == JobInfo.NetworkType.ANY, - second.getNetworkCapabilities() == JobInfo.NetworkType.ANY); + first.getNetworkType() == JobInfo.NETWORK_TYPE_ANY, + second.getNetworkType() == JobInfo.NETWORK_TYPE_ANY); assertEquals("Invalid deadline constraint.", first.hasLateConstraint(), second.hasLateConstraint()); diff --git a/tests/JobSchedulerTestApp/src/com/android/demo/jobSchedulerApp/MainActivity.java b/tests/JobSchedulerTestApp/src/com/android/demo/jobSchedulerApp/MainActivity.java index 6e5484e..b9a2a7e 100644 --- a/tests/JobSchedulerTestApp/src/com/android/demo/jobSchedulerApp/MainActivity.java +++ b/tests/JobSchedulerTestApp/src/com/android/demo/jobSchedulerApp/MainActivity.java @@ -143,13 +143,13 @@ public class MainActivity extends Activity { boolean requiresUnmetered = mWiFiConnectivityRadioButton.isChecked(); boolean requiresAnyConnectivity = mAnyConnectivityRadioButton.isChecked(); if (requiresUnmetered) { - builder.setRequiredNetworkCapabilities(JobInfo.NetworkType.UNMETERED); + builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED); } else if (requiresAnyConnectivity) { - builder.setRequiredNetworkCapabilities(JobInfo.NetworkType.ANY); + builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY); } builder.setRequiresDeviceIdle(mRequiresIdleCheckbox.isChecked()); builder.setRequiresCharging(mRequiresChargingCheckBox.isChecked()); - builder.setIsPersisted(mIsPersistedCheckbox.isChecked()); + builder.setPersisted(mIsPersistedCheckbox.isChecked()); mTestService.scheduleJob(builder.build()); } |