summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Jeff Sharkey <jsharkey@android.com> 2017-10-24 16:55:04 -0600
committer Jeff Sharkey <jsharkey@android.com> 2017-10-25 11:23:22 -0600
commit76a0241effeb80cb3bdd15be3efbfa84b6172d6e (patch)
treeaed7982e38122ed7f8e6b9d1dff2a60e07e31733
parentdb4b619a2fbd2746425916806391d9b20bd8bfca (diff)
Provide explicit Network via JobParameters.
On devices with multiple active networks, or rapidly switching between networks, we need an API to tell jobs explicitly which network to use. (For example, the default route could meet all job criteria, but we could have changed the default network by the time we spun up the JobService.) This also paves the way for us choosing to run jobs over non-default networks. Test: verified via DownloadManager Bug: 64133169 Change-Id: Ic8d654707e39236c8da85a5e172161ac39e5f0b3
-rw-r--r--api/current.txt2
-rw-r--r--api/system-current.txt2
-rw-r--r--api/test-current.txt2
-rw-r--r--core/java/android/app/job/JobInfo.java21
-rw-r--r--core/java/android/app/job/JobParameters.java38
-rw-r--r--services/core/java/com/android/server/job/JobServiceContext.java2
-rw-r--r--services/core/java/com/android/server/job/controllers/ConnectivityController.java5
-rw-r--r--services/core/java/com/android/server/job/controllers/JobStatus.java5
8 files changed, 66 insertions, 11 deletions
diff --git a/api/current.txt b/api/current.txt
index 8b3c74088df5..eca3a8bebc1a 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -6899,6 +6899,7 @@ package android.app.job {
method public int getClipGrantFlags();
method public android.os.PersistableBundle getExtras();
method public int getJobId();
+ method public android.net.Network getNetwork();
method public android.os.Bundle getTransientExtras();
method public java.lang.String[] getTriggeredContentAuthorities();
method public android.net.Uri[] getTriggeredContentUris();
@@ -52072,7 +52073,6 @@ package android.widget {
method public android.graphics.Typeface getTypeface();
method public android.text.style.URLSpan[] getUrls();
method public boolean hasSelection();
- method public void invalidate(int, int, int, int);
method public boolean isAllCaps();
method public boolean isCursorVisible();
method public boolean isElegantTextHeight();
diff --git a/api/system-current.txt b/api/system-current.txt
index ee23b6d92b71..6d828e3ca5f1 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -7341,6 +7341,7 @@ package android.app.job {
method public int getClipGrantFlags();
method public android.os.PersistableBundle getExtras();
method public int getJobId();
+ method public android.net.Network getNetwork();
method public android.os.Bundle getTransientExtras();
method public java.lang.String[] getTriggeredContentAuthorities();
method public android.net.Uri[] getTriggeredContentUris();
@@ -56176,7 +56177,6 @@ package android.widget {
method public android.graphics.Typeface getTypeface();
method public android.text.style.URLSpan[] getUrls();
method public boolean hasSelection();
- method public void invalidate(int, int, int, int);
method public boolean isAllCaps();
method public boolean isCursorVisible();
method public boolean isElegantTextHeight();
diff --git a/api/test-current.txt b/api/test-current.txt
index 9a241add0bdb..954cb4852372 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -6970,6 +6970,7 @@ package android.app.job {
method public int getClipGrantFlags();
method public android.os.PersistableBundle getExtras();
method public int getJobId();
+ method public android.net.Network getNetwork();
method public android.os.Bundle getTransientExtras();
method public java.lang.String[] getTriggeredContentAuthorities();
method public android.net.Uri[] getTriggeredContentUris();
@@ -52680,7 +52681,6 @@ package android.widget {
method public android.graphics.Typeface getTypeface();
method public android.text.style.URLSpan[] getUrls();
method public boolean hasSelection();
- method public void invalidate(int, int, int, int);
method public boolean isAllCaps();
method public boolean isCursorVisible();
method public boolean isElegantTextHeight();
diff --git a/core/java/android/app/job/JobInfo.java b/core/java/android/app/job/JobInfo.java
index 1434c9baadf3..1cde73a0af61 100644
--- a/core/java/android/app/job/JobInfo.java
+++ b/core/java/android/app/job/JobInfo.java
@@ -909,12 +909,21 @@ public class JobInfo implements Parcelable {
}
/**
- * 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
- * {@link #setOverrideDeadline(long)} to change this behaviour.
+ * 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 {@link #setOverrideDeadline(long)} to change this
+ * behaviour.
+ * <p class="note">
+ * Note: When your job executes in
+ * {@link JobService#onStartJob(JobParameters)}, be sure to use the
+ * specific network returned by {@link JobParameters#getNetwork()},
+ * otherwise you'll use the default network which may not meet this
+ * constraint.
+ *
+ * @see JobParameters#getNetwork()
*/
public Builder setRequiredNetworkType(@NetworkType int networkType) {
mNetworkType = networkType;
diff --git a/core/java/android/app/job/JobParameters.java b/core/java/android/app/job/JobParameters.java
index a6f6be22809c..5053dc6fdf05 100644
--- a/core/java/android/app/job/JobParameters.java
+++ b/core/java/android/app/job/JobParameters.java
@@ -20,6 +20,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.job.IJobCallback;
import android.content.ClipData;
+import android.net.Network;
import android.net.Uri;
import android.os.Bundle;
import android.os.IBinder;
@@ -66,6 +67,7 @@ public class JobParameters implements Parcelable {
private final boolean overrideDeadlineExpired;
private final Uri[] mTriggeredContentUris;
private final String[] mTriggeredContentAuthorities;
+ private final Network network;
private int stopReason; // Default value of stopReason is REASON_CANCELED
@@ -73,7 +75,7 @@ public class JobParameters implements Parcelable {
public JobParameters(IBinder callback, int jobId, PersistableBundle extras,
Bundle transientExtras, ClipData clipData, int clipGrantFlags,
boolean overrideDeadlineExpired, Uri[] triggeredContentUris,
- String[] triggeredContentAuthorities) {
+ String[] triggeredContentAuthorities, Network network) {
this.jobId = jobId;
this.extras = extras;
this.transientExtras = transientExtras;
@@ -83,6 +85,7 @@ public class JobParameters implements Parcelable {
this.overrideDeadlineExpired = overrideDeadlineExpired;
this.mTriggeredContentUris = triggeredContentUris;
this.mTriggeredContentAuthorities = triggeredContentAuthorities;
+ this.network = network;
}
/**
@@ -171,6 +174,28 @@ public class JobParameters implements Parcelable {
}
/**
+ * Return the network that should be used to perform any network requests
+ * for this job.
+ * <p>
+ * Devices may have multiple active network connections simultaneously, or
+ * they may not have a default network route at all. To correctly handle all
+ * situations like this, your job should always use the network returned by
+ * this method instead of implicitly using the default network route.
+ * <p>
+ * Note that the system may relax the constraints you originally requested,
+ * such as allowing a {@link JobInfo#NETWORK_TYPE_UNMETERED} job to run over
+ * a metered network when there is a surplus of metered data available.
+ *
+ * @return the network that should be used to perform any network requests
+ * for this job, or {@code null} if this job didn't set any required
+ * network type.
+ * @see JobInfo.Builder#setRequiredNetworkType(int)
+ */
+ public @Nullable Network getNetwork() {
+ return network;
+ }
+
+ /**
* Dequeue the next pending {@link JobWorkItem} from these JobParameters associated with their
* currently running job. Calling this method when there is no more work available and all
* previously dequeued work has been completed will result in the system taking care of
@@ -257,6 +282,11 @@ public class JobParameters implements Parcelable {
overrideDeadlineExpired = in.readInt() == 1;
mTriggeredContentUris = in.createTypedArray(Uri.CREATOR);
mTriggeredContentAuthorities = in.createStringArray();
+ if (in.readInt() != 0) {
+ network = Network.CREATOR.createFromParcel(in);
+ } else {
+ network = null;
+ }
stopReason = in.readInt();
}
@@ -286,6 +316,12 @@ public class JobParameters implements Parcelable {
dest.writeInt(overrideDeadlineExpired ? 1 : 0);
dest.writeTypedArray(mTriggeredContentUris, flags);
dest.writeStringArray(mTriggeredContentAuthorities);
+ if (network != null) {
+ dest.writeInt(1);
+ network.writeToParcel(dest, flags);
+ } else {
+ dest.writeInt(0);
+ }
dest.writeInt(stopReason);
}
diff --git a/services/core/java/com/android/server/job/JobServiceContext.java b/services/core/java/com/android/server/job/JobServiceContext.java
index d3fd3a992a31..ae01c433fc8d 100644
--- a/services/core/java/com/android/server/job/JobServiceContext.java
+++ b/services/core/java/com/android/server/job/JobServiceContext.java
@@ -216,7 +216,7 @@ public final class JobServiceContext implements ServiceConnection {
final JobInfo ji = job.getJob();
mParams = new JobParameters(mRunningCallback, job.getJobId(), ji.getExtras(),
ji.getTransientExtras(), ji.getClipData(), ji.getClipGrantFlags(),
- isDeadlineExpired, triggeredUris, triggeredAuthorities);
+ isDeadlineExpired, triggeredUris, triggeredAuthorities, job.network);
mExecutionStartTimeElapsed = SystemClock.elapsedRealtime();
// Once we'e begun executing a job, we by definition no longer care whether
diff --git a/services/core/java/com/android/server/job/controllers/ConnectivityController.java b/services/core/java/com/android/server/job/controllers/ConnectivityController.java
index 78367fe97a54..c928c07be983 100644
--- a/services/core/java/com/android/server/job/controllers/ConnectivityController.java
+++ b/services/core/java/com/android/server/job/controllers/ConnectivityController.java
@@ -125,6 +125,11 @@ public final class ConnectivityController extends StateController implements
changed |= jobStatus.setUnmeteredConstraintSatisfied(unmetered);
changed |= jobStatus.setNotRoamingConstraintSatisfied(notRoaming);
+ // Pass along the evaluated network for job to use; prevents race
+ // conditions as default routes change over time, and opens the door to
+ // using non-default routes.
+ jobStatus.network = network;
+
// Track system-uid connected/validated as a general reportable proxy for the
// overall state of connectivity constraint satisfiability.
if (jobUid == Process.SYSTEM_UID) {
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 23caa8cfa701..1a27c0afb5ea 100644
--- a/services/core/java/com/android/server/job/controllers/JobStatus.java
+++ b/services/core/java/com/android/server/job/controllers/JobStatus.java
@@ -22,6 +22,7 @@ import android.app.job.JobInfo;
import android.app.job.JobWorkItem;
import android.content.ClipData;
import android.content.ComponentName;
+import android.net.Network;
import android.net.Uri;
import android.os.RemoteException;
import android.os.SystemClock;
@@ -167,6 +168,7 @@ public final class JobStatus {
// These are filled in by controllers when preparing for execution.
public ArraySet<Uri> changedUris;
public ArraySet<String> changedAuthorities;
+ public Network network;
public int lastEvaluatedPriority;
@@ -1101,6 +1103,9 @@ public final class JobStatus {
}
}
}
+ if (network != null) {
+ pw.print(prefix); pw.print("Network: "); pw.println(network);
+ }
if (pendingWork != null && pendingWork.size() > 0) {
pw.print(prefix); pw.println("Pending work:");
for (int i = 0; i < pendingWork.size(); i++) {