Merge "Allow apps to specify minimum chunk size."

This commit is contained in:
TreeHugger Robot
2021-07-14 00:25:34 +00:00
committed by Android (Google) Code Review
7 changed files with 259 additions and 18 deletions

View File

@@ -324,6 +324,7 @@ public class JobInfo implements Parcelable {
private final NetworkRequest networkRequest;
private final long networkDownloadBytes;
private final long networkUploadBytes;
private final long minimumNetworkChunkBytes;
private final long minLatencyMillis;
private final long maxExecutionDelayMillis;
private final boolean isPeriodic;
@@ -514,6 +515,17 @@ public class JobInfo implements Parcelable {
return networkUploadBytes;
}
/**
* Return the smallest piece of data that cannot be easily paused and resumed, in bytes.
*
* @return Smallest piece of data that cannot be easily paused and resumed, or
* {@link #NETWORK_BYTES_UNKNOWN} when unknown.
* @see Builder#setMinimumNetworkChunkBytes(long)
*/
public @BytesLong long getMinimumNetworkChunkBytes() {
return minimumNetworkChunkBytes;
}
/**
* Set for a job that does not recur periodically, to specify a delay after which the job
* will be eligible for execution. This value is not set if the job recurs periodically.
@@ -679,6 +691,9 @@ public class JobInfo implements Parcelable {
if (networkUploadBytes != j.networkUploadBytes) {
return false;
}
if (minimumNetworkChunkBytes != j.minimumNetworkChunkBytes) {
return false;
}
if (minLatencyMillis != j.minLatencyMillis) {
return false;
}
@@ -741,6 +756,7 @@ public class JobInfo implements Parcelable {
}
hashCode = 31 * hashCode + Long.hashCode(networkDownloadBytes);
hashCode = 31 * hashCode + Long.hashCode(networkUploadBytes);
hashCode = 31 * hashCode + Long.hashCode(minimumNetworkChunkBytes);
hashCode = 31 * hashCode + Long.hashCode(minLatencyMillis);
hashCode = 31 * hashCode + Long.hashCode(maxExecutionDelayMillis);
hashCode = 31 * hashCode + Boolean.hashCode(isPeriodic);
@@ -777,6 +793,7 @@ public class JobInfo implements Parcelable {
}
networkDownloadBytes = in.readLong();
networkUploadBytes = in.readLong();
minimumNetworkChunkBytes = in.readLong();
minLatencyMillis = in.readLong();
maxExecutionDelayMillis = in.readLong();
isPeriodic = in.readInt() == 1;
@@ -807,6 +824,7 @@ public class JobInfo implements Parcelable {
networkRequest = b.mNetworkRequest;
networkDownloadBytes = b.mNetworkDownloadBytes;
networkUploadBytes = b.mNetworkUploadBytes;
minimumNetworkChunkBytes = b.mMinimumNetworkChunkBytes;
minLatencyMillis = b.mMinLatencyMillis;
maxExecutionDelayMillis = b.mMaxExecutionDelayMillis;
isPeriodic = b.mIsPeriodic;
@@ -851,6 +869,7 @@ public class JobInfo implements Parcelable {
}
out.writeLong(networkDownloadBytes);
out.writeLong(networkUploadBytes);
out.writeLong(minimumNetworkChunkBytes);
out.writeLong(minLatencyMillis);
out.writeLong(maxExecutionDelayMillis);
out.writeInt(isPeriodic ? 1 : 0);
@@ -986,6 +1005,7 @@ public class JobInfo implements Parcelable {
private NetworkRequest mNetworkRequest;
private long mNetworkDownloadBytes = NETWORK_BYTES_UNKNOWN;
private long mNetworkUploadBytes = NETWORK_BYTES_UNKNOWN;
private long mMinimumNetworkChunkBytes = NETWORK_BYTES_UNKNOWN;
private ArrayList<TriggerContentUri> mTriggerContentUris;
private long mTriggerContentUpdateDelay = -1;
private long mTriggerContentMaxDelay = -1;
@@ -1038,6 +1058,7 @@ public class JobInfo implements Parcelable {
mNetworkRequest = job.getRequiredNetwork();
mNetworkDownloadBytes = job.getEstimatedNetworkDownloadBytes();
mNetworkUploadBytes = job.getEstimatedNetworkUploadBytes();
mMinimumNetworkChunkBytes = job.getMinimumNetworkChunkBytes();
mTriggerContentUris = job.getTriggerContentUris() != null
? new ArrayList<>(Arrays.asList(job.getTriggerContentUris())) : null;
mTriggerContentUpdateDelay = job.getTriggerContentUpdateDelay();
@@ -1255,6 +1276,39 @@ public class JobInfo implements Parcelable {
return this;
}
/**
* Set the minimum size of non-resumable network traffic this job requires, in bytes. When
* the upload or download can be easily paused and resumed, use this to set the smallest
* size that must be transmitted between start and stop events to be considered successful.
* If the transfer cannot be paused and resumed, then this should be the sum of the values
* provided to {@link JobInfo.Builder#setEstimatedNetworkBytes(long, long)}.
*
* <p>
* Apps are encouraged to provide values that are as accurate as possible since JobScheduler
* will try to run the job at a time when at least the minimum chunk can be transmitted to
* reduce the amount of repetitive data that's transferred. Jobs that cannot provide
* reasonable estimates should use the sentinel value {@link JobInfo#NETWORK_BYTES_UNKNOWN}.
*
* <p>
* The values provided here only reflect the minimum non-resumable traffic that will be
* performed by the base job; if you're using {@link JobWorkItem} then
* you also need to define the network traffic used by each work item
* when constructing them.
*
* @param chunkSizeBytes The smallest piece of data that cannot be easily paused and
* resumed, in bytes.
* @see JobInfo#getMinimumNetworkChunkBytes()
* @see JobWorkItem#JobWorkItem(android.content.Intent, long, long, long)
*/
@NonNull
public Builder setMinimumNetworkChunkBytes(@BytesLong long chunkSizeBytes) {
if (chunkSizeBytes != NETWORK_BYTES_UNKNOWN && chunkSizeBytes <= 0) {
throw new IllegalArgumentException("Minimum chunk size must be positive");
}
mMinimumNetworkChunkBytes = chunkSizeBytes;
return this;
}
/**
* Specify that to run this job, the device must be charging (or be a
* non-battery-powered device connected to permanent power, such as Android TV
@@ -1647,12 +1701,29 @@ public class JobInfo implements Parcelable {
/**
* @hide
*/
public void enforceValidity() {
// Check that network estimates require network type
if ((networkDownloadBytes > 0 || networkUploadBytes > 0) && networkRequest == null) {
public final void enforceValidity() {
// Check that network estimates require network type and are reasonable values.
if ((networkDownloadBytes > 0 || networkUploadBytes > 0 || minimumNetworkChunkBytes > 0)
&& networkRequest == null) {
throw new IllegalArgumentException(
"Can't provide estimated network usage without requiring a network");
}
final long estimatedTransfer;
if (networkUploadBytes == NETWORK_BYTES_UNKNOWN) {
estimatedTransfer = networkDownloadBytes;
} else {
estimatedTransfer = networkUploadBytes
+ (networkDownloadBytes == NETWORK_BYTES_UNKNOWN ? 0 : networkDownloadBytes);
}
if (minimumNetworkChunkBytes != NETWORK_BYTES_UNKNOWN
&& estimatedTransfer != NETWORK_BYTES_UNKNOWN
&& minimumNetworkChunkBytes > estimatedTransfer) {
throw new IllegalArgumentException(
"Minimum chunk size can't be greater than estimated network usage");
}
if (minimumNetworkChunkBytes != NETWORK_BYTES_UNKNOWN && minimumNetworkChunkBytes <= 0) {
throw new IllegalArgumentException("Minimum chunk size must be positive");
}
// Check that a deadline was not set on a periodic job.
if (isPeriodic) {

View File

@@ -19,6 +19,7 @@ package android.app.job;
import static android.app.job.JobInfo.NETWORK_BYTES_UNKNOWN;
import android.annotation.BytesLong;
import android.annotation.Nullable;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Intent;
import android.os.Build;
@@ -33,8 +34,9 @@ import android.os.Parcelable;
final public class JobWorkItem implements Parcelable {
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
final Intent mIntent;
final long mNetworkDownloadBytes;
final long mNetworkUploadBytes;
private final long mNetworkDownloadBytes;
private final long mNetworkUploadBytes;
private final long mMinimumChunkBytes;
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
int mDeliveryCount;
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
@@ -49,9 +51,7 @@ final public class JobWorkItem implements Parcelable {
* @param intent The general Intent describing this work.
*/
public JobWorkItem(Intent intent) {
mIntent = intent;
mNetworkDownloadBytes = NETWORK_BYTES_UNKNOWN;
mNetworkUploadBytes = NETWORK_BYTES_UNKNOWN;
this(intent, NETWORK_BYTES_UNKNOWN, NETWORK_BYTES_UNKNOWN);
}
/**
@@ -68,9 +68,45 @@ final public class JobWorkItem implements Parcelable {
* uploaded by this job work item, in bytes.
*/
public JobWorkItem(Intent intent, @BytesLong long downloadBytes, @BytesLong long uploadBytes) {
this(intent, downloadBytes, uploadBytes, NETWORK_BYTES_UNKNOWN);
}
/**
* Create a new piece of work, which can be submitted to
* {@link JobScheduler#enqueue JobScheduler.enqueue}.
* <p>
* See {@link JobInfo.Builder#setEstimatedNetworkBytes(long, long)} for
* details about how to estimate network traffic.
*
* @param intent The general Intent describing this work.
* @param downloadBytes The estimated size of network traffic that will be
* downloaded by this job work item, in bytes.
* @param uploadBytes The estimated size of network traffic that will be
* uploaded by this job work item, in bytes.
* @param minimumChunkBytes The smallest piece of data that cannot be easily paused and
* resumed, in bytes.
*/
public JobWorkItem(@Nullable Intent intent, @BytesLong long downloadBytes,
@BytesLong long uploadBytes, @BytesLong long minimumChunkBytes) {
if (minimumChunkBytes != NETWORK_BYTES_UNKNOWN && minimumChunkBytes <= 0) {
throw new IllegalArgumentException("Minimum chunk size must be positive");
}
final long estimatedTransfer;
if (uploadBytes == NETWORK_BYTES_UNKNOWN) {
estimatedTransfer = downloadBytes;
} else {
estimatedTransfer = uploadBytes
+ (downloadBytes == NETWORK_BYTES_UNKNOWN ? 0 : downloadBytes);
}
if (minimumChunkBytes != NETWORK_BYTES_UNKNOWN && estimatedTransfer != NETWORK_BYTES_UNKNOWN
&& minimumChunkBytes > estimatedTransfer) {
throw new IllegalArgumentException(
"Minimum chunk size can't be greater than estimated network usage");
}
mIntent = intent;
mNetworkDownloadBytes = downloadBytes;
mNetworkUploadBytes = uploadBytes;
mMinimumChunkBytes = minimumChunkBytes;
}
/**
@@ -102,6 +138,16 @@ final public class JobWorkItem implements Parcelable {
return mNetworkUploadBytes;
}
/**
* Return the smallest piece of data that cannot be easily paused and resumed, in bytes.
*
* @return Smallest piece of data that cannot be easily paused and resumed, or
* {@link JobInfo#NETWORK_BYTES_UNKNOWN} when unknown.
*/
public @BytesLong long getMinimumNetworkChunkBytes() {
return mMinimumChunkBytes;
}
/**
* Return the count of the number of times this work item has been delivered
* to the job. The value will be > 1 if it has been redelivered because the job
@@ -161,6 +207,10 @@ final public class JobWorkItem implements Parcelable {
sb.append(" uploadBytes=");
sb.append(mNetworkUploadBytes);
}
if (mMinimumChunkBytes != NETWORK_BYTES_UNKNOWN) {
sb.append(" minimumChunkBytes=");
sb.append(mMinimumChunkBytes);
}
if (mDeliveryCount != 0) {
sb.append(" dcount=");
sb.append(mDeliveryCount);
@@ -169,6 +219,28 @@ final public class JobWorkItem implements Parcelable {
return sb.toString();
}
/**
* @hide
*/
public void enforceValidity() {
final long estimatedTransfer;
if (mNetworkUploadBytes == NETWORK_BYTES_UNKNOWN) {
estimatedTransfer = mNetworkDownloadBytes;
} else {
estimatedTransfer = mNetworkUploadBytes
+ (mNetworkDownloadBytes == NETWORK_BYTES_UNKNOWN ? 0 : mNetworkDownloadBytes);
}
if (mMinimumChunkBytes != NETWORK_BYTES_UNKNOWN
&& estimatedTransfer != NETWORK_BYTES_UNKNOWN
&& mMinimumChunkBytes > estimatedTransfer) {
throw new IllegalArgumentException(
"Minimum chunk size can't be greater than estimated network usage");
}
if (mMinimumChunkBytes != NETWORK_BYTES_UNKNOWN && mMinimumChunkBytes <= 0) {
throw new IllegalArgumentException("Minimum chunk size must be positive");
}
}
public int describeContents() {
return 0;
}
@@ -182,6 +254,7 @@ final public class JobWorkItem implements Parcelable {
}
out.writeLong(mNetworkDownloadBytes);
out.writeLong(mNetworkUploadBytes);
out.writeLong(mMinimumChunkBytes);
out.writeInt(mDeliveryCount);
out.writeInt(mWorkId);
}
@@ -206,6 +279,7 @@ final public class JobWorkItem implements Parcelable {
}
mNetworkDownloadBytes = in.readLong();
mNetworkUploadBytes = in.readLong();
mMinimumChunkBytes = in.readLong();
mDeliveryCount = in.readInt();
mWorkId = in.readInt();
}

View File

@@ -2806,6 +2806,7 @@ public class JobSchedulerService extends com.android.server.SystemService
throw new NullPointerException("work is null");
}
work.enforceValidity();
validateJobFlags(job, uid);
final long ident = Binder.clearCallingIdentity();

View File

@@ -549,6 +549,47 @@ public final class ConnectivityController extends RestrictingController implemen
*/
private boolean isInsane(JobStatus jobStatus, Network network,
NetworkCapabilities capabilities, Constants constants) {
// Use the maximum possible time since it gives us an upper bound, even though the job
// could end up stopping earlier.
final long maxJobExecutionTimeMs = mService.getMaxJobExecutionTimeMs(jobStatus);
final long minimumChunkBytes = jobStatus.getMinimumNetworkChunkBytes();
if (minimumChunkBytes != JobInfo.NETWORK_BYTES_UNKNOWN) {
final long bandwidthDown = capabilities.getLinkDownstreamBandwidthKbps();
// If we don't know the bandwidth, all we can do is hope the job finishes the minimum
// chunk in time.
if (bandwidthDown > 0) {
// Divide by 8 to convert bits to bytes.
final long estimatedMillis = ((minimumChunkBytes * DateUtils.SECOND_IN_MILLIS)
/ (DataUnit.KIBIBYTES.toBytes(bandwidthDown) / 8));
if (estimatedMillis > maxJobExecutionTimeMs) {
// If we'd never finish the minimum chunk before the timeout, we'd be insane!
Slog.w(TAG, "Minimum chunk " + minimumChunkBytes + " bytes over "
+ bandwidthDown + " kbps network would take "
+ estimatedMillis + "ms and job has "
+ maxJobExecutionTimeMs + "ms to run; that's insane!");
return true;
}
}
final long bandwidthUp = capabilities.getLinkUpstreamBandwidthKbps();
// If we don't know the bandwidth, all we can do is hope the job finishes in time.
if (bandwidthUp > 0) {
// Divide by 8 to convert bits to bytes.
final long estimatedMillis = ((minimumChunkBytes * DateUtils.SECOND_IN_MILLIS)
/ (DataUnit.KIBIBYTES.toBytes(bandwidthUp) / 8));
if (estimatedMillis > maxJobExecutionTimeMs) {
// If we'd never finish the minimum chunk before the timeout, we'd be insane!
Slog.w(TAG, "Minimum chunk " + minimumChunkBytes + " bytes over " + bandwidthUp
+ " kbps network would take " + estimatedMillis + "ms and job has "
+ maxJobExecutionTimeMs + "ms to run; that's insane!");
return true;
}
}
return false;
}
// Minimum chunk size isn't defined. Check using the estimated upload/download sizes.
if (capabilities.hasCapability(NET_CAPABILITY_NOT_METERED)
&& mChargingTracker.isCharging()) {
// We're charging and on an unmetered network. We don't have to be as conservative about
@@ -557,9 +598,6 @@ public final class ConnectivityController extends RestrictingController implemen
return false;
}
// Use the maximum possible time since it gives us an upper bound, even though the job
// could end up stopping earlier.
final long maxJobExecutionTimeMs = mService.getMaxJobExecutionTimeMs(jobStatus);
final long downloadBytes = jobStatus.getEstimatedNetworkDownloadBytes();
if (downloadBytes != JobInfo.NETWORK_BYTES_UNKNOWN) {

View File

@@ -391,6 +391,7 @@ public final class JobStatus {
private long mTotalNetworkDownloadBytes = JobInfo.NETWORK_BYTES_UNKNOWN;
private long mTotalNetworkUploadBytes = JobInfo.NETWORK_BYTES_UNKNOWN;
private long mMinimumNetworkChunkBytes = JobInfo.NETWORK_BYTES_UNKNOWN;
/////// Booleans that track if a job is ready to run. They should be updated whenever dependent
/////// states change.
@@ -531,7 +532,7 @@ public final class JobStatus {
mInternalFlags = internalFlags;
updateEstimatedNetworkBytesLocked();
updateNetworkBytesLocked();
if (job.getRequiredNetwork() != null) {
// Later, when we check if a given network satisfies the required
@@ -664,7 +665,7 @@ public final class JobStatus {
sourcePackageName, sourceUserId, toShortString()));
}
pendingWork.add(work);
updateEstimatedNetworkBytesLocked();
updateNetworkBytesLocked();
}
public JobWorkItem dequeueWorkLocked() {
@@ -677,7 +678,7 @@ public final class JobStatus {
executingWork.add(work);
work.bumpDeliveryCount();
}
updateEstimatedNetworkBytesLocked();
updateNetworkBytesLocked();
return work;
}
return null;
@@ -736,7 +737,7 @@ public final class JobStatus {
pendingWork = null;
executingWork = null;
incomingJob.nextPendingWorkId = nextPendingWorkId;
incomingJob.updateEstimatedNetworkBytesLocked();
incomingJob.updateNetworkBytesLocked();
} else {
// We are completely stopping the job... need to clean up work.
ungrantWorkList(pendingWork);
@@ -744,7 +745,7 @@ public final class JobStatus {
ungrantWorkList(executingWork);
executingWork = null;
}
updateEstimatedNetworkBytesLocked();
updateNetworkBytesLocked();
}
public void prepareLocked() {
@@ -944,9 +945,10 @@ public final class JobStatus {
}
}
private void updateEstimatedNetworkBytesLocked() {
private void updateNetworkBytesLocked() {
mTotalNetworkDownloadBytes = job.getEstimatedNetworkDownloadBytes();
mTotalNetworkUploadBytes = job.getEstimatedNetworkUploadBytes();
mMinimumNetworkChunkBytes = job.getMinimumNetworkChunkBytes();
if (pendingWork != null) {
for (int i = 0; i < pendingWork.size(); i++) {
@@ -968,6 +970,12 @@ public final class JobStatus {
mTotalNetworkUploadBytes += uploadBytes;
}
}
final long chunkBytes = pendingWork.get(i).getMinimumNetworkChunkBytes();
if (mMinimumNetworkChunkBytes == JobInfo.NETWORK_BYTES_UNKNOWN) {
mMinimumNetworkChunkBytes = chunkBytes;
} else if (chunkBytes != JobInfo.NETWORK_BYTES_UNKNOWN) {
mMinimumNetworkChunkBytes = Math.min(mMinimumNetworkChunkBytes, chunkBytes);
}
}
}
}
@@ -980,6 +988,10 @@ public final class JobStatus {
return mTotalNetworkUploadBytes;
}
public long getMinimumNetworkChunkBytes() {
return mMinimumNetworkChunkBytes;
}
/** Does this job have any sort of networking constraint? */
public boolean hasConnectivityConstraint() {
// No need to check mDynamicConstraints since connectivity will only be in that list if
@@ -1942,6 +1954,10 @@ public final class JobStatus {
pw.print("Network upload bytes: ");
pw.println(mTotalNetworkUploadBytes);
}
if (mMinimumNetworkChunkBytes != JobInfo.NETWORK_BYTES_UNKNOWN) {
pw.print("Minimum network chunk bytes: ");
pw.println(mMinimumNetworkChunkBytes);
}
if (job.getMinLatencyMillis() != 0) {
pw.print("Minimum latency: ");
TimeUtils.formatDuration(job.getMinLatencyMillis(), pw);

View File

@@ -7937,6 +7937,7 @@ package android.app.job {
method public static final long getMinFlexMillis();
method public long getMinLatencyMillis();
method public static final long getMinPeriodMillis();
method public long getMinimumNetworkChunkBytes();
method @Deprecated public int getNetworkType();
method @Nullable public android.net.NetworkRequest getRequiredNetwork();
method @NonNull public android.content.ComponentName getService();
@@ -7979,6 +7980,7 @@ package android.app.job {
method public android.app.job.JobInfo.Builder setExtras(@NonNull android.os.PersistableBundle);
method @Deprecated public android.app.job.JobInfo.Builder setImportantWhileForeground(boolean);
method public android.app.job.JobInfo.Builder setMinimumLatency(long);
method @NonNull public android.app.job.JobInfo.Builder setMinimumNetworkChunkBytes(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);
@@ -8071,11 +8073,13 @@ package android.app.job {
public final class JobWorkItem implements android.os.Parcelable {
ctor public JobWorkItem(android.content.Intent);
ctor public JobWorkItem(android.content.Intent, long, long);
ctor public JobWorkItem(@Nullable android.content.Intent, long, long, long);
method public int describeContents();
method public int getDeliveryCount();
method public long getEstimatedNetworkDownloadBytes();
method public long getEstimatedNetworkUploadBytes();
method public android.content.Intent getIntent();
method public long getMinimumNetworkChunkBytes();
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.app.job.JobWorkItem> CREATOR;
}

View File

@@ -152,6 +152,11 @@ public class ConnectivityControllerTest {
.setEstimatedNetworkBytes(DataUnit.MEBIBYTES.toBytes(1),
DataUnit.MEBIBYTES.toBytes(1))
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY);
final JobInfo.Builder jobWithMinChunk = createJob()
.setEstimatedNetworkBytes(DataUnit.MEBIBYTES.toBytes(1),
DataUnit.MEBIBYTES.toBytes(1))
.setMinimumNetworkChunkBytes(DataUnit.KIBIBYTES.toBytes(100))
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY);
final ArgumentCaptor<BroadcastReceiver> chargingCaptor =
ArgumentCaptor.forClass(BroadcastReceiver.class);
@@ -170,18 +175,51 @@ public class ConnectivityControllerTest {
assertFalse(controller.isSatisfied(createJobStatus(job), net,
createCapabilitiesBuilder().setLinkUpstreamBandwidthKbps(1)
.setLinkDownstreamBandwidthKbps(1).build(), mConstants));
assertFalse(controller.isSatisfied(createJobStatus(jobWithMinChunk), net,
createCapabilitiesBuilder().setLinkUpstreamBandwidthKbps(1)
.setLinkDownstreamBandwidthKbps(1).build(), mConstants));
// Slow downstream
assertFalse(controller.isSatisfied(createJobStatus(job), net,
createCapabilitiesBuilder().setLinkUpstreamBandwidthKbps(1024)
.setLinkDownstreamBandwidthKbps(1).build(), mConstants));
assertFalse(controller.isSatisfied(createJobStatus(jobWithMinChunk), net,
createCapabilitiesBuilder().setLinkUpstreamBandwidthKbps(1024)
.setLinkDownstreamBandwidthKbps(1).build(), mConstants));
// Slow upstream
assertFalse(controller.isSatisfied(createJobStatus(job), net,
createCapabilitiesBuilder().setLinkUpstreamBandwidthKbps(1)
.setLinkDownstreamBandwidthKbps(1024).build(), mConstants));
assertFalse(controller.isSatisfied(createJobStatus(jobWithMinChunk), net,
createCapabilitiesBuilder().setLinkUpstreamBandwidthKbps(1)
.setLinkDownstreamBandwidthKbps(1024).build(), mConstants));
// Medium network is fine for min chunk
assertFalse(controller.isSatisfied(createJobStatus(job), net,
createCapabilitiesBuilder().setLinkUpstreamBandwidthKbps(5)
.setLinkDownstreamBandwidthKbps(5).build(), mConstants));
assertTrue(controller.isSatisfied(createJobStatus(jobWithMinChunk), net,
createCapabilitiesBuilder().setLinkUpstreamBandwidthKbps(5)
.setLinkDownstreamBandwidthKbps(5).build(), mConstants));
// Medium downstream
assertFalse(controller.isSatisfied(createJobStatus(job), net,
createCapabilitiesBuilder().setLinkUpstreamBandwidthKbps(1024)
.setLinkDownstreamBandwidthKbps(5).build(), mConstants));
assertTrue(controller.isSatisfied(createJobStatus(jobWithMinChunk), net,
createCapabilitiesBuilder().setLinkUpstreamBandwidthKbps(1024)
.setLinkDownstreamBandwidthKbps(5).build(), mConstants));
// Medium upstream
assertFalse(controller.isSatisfied(createJobStatus(job), net,
createCapabilitiesBuilder().setLinkUpstreamBandwidthKbps(5)
.setLinkDownstreamBandwidthKbps(1024).build(), mConstants));
assertTrue(controller.isSatisfied(createJobStatus(jobWithMinChunk), net,
createCapabilitiesBuilder().setLinkUpstreamBandwidthKbps(5)
.setLinkDownstreamBandwidthKbps(1024).build(), mConstants));
// Fast network looks great
assertTrue(controller.isSatisfied(createJobStatus(job), net,
createCapabilitiesBuilder().setLinkUpstreamBandwidthKbps(1024)
.setLinkDownstreamBandwidthKbps(1024).build(), mConstants));
assertTrue(controller.isSatisfied(createJobStatus(jobWithMinChunk), net,
createCapabilitiesBuilder().setLinkUpstreamBandwidthKbps(1024)
.setLinkDownstreamBandwidthKbps(1024).build(), mConstants));
// Slow network still good given time
assertTrue(controller.isSatisfied(createJobStatus(job), net,
createCapabilitiesBuilder().setLinkUpstreamBandwidthKbps(130)
@@ -241,7 +279,6 @@ public class ConnectivityControllerTest {
final ConnectivityController controller = new ConnectivityController(mService);
when(mService.getMaxJobExecutionTimeMs(any())).thenReturn(10 * 60_000L);
// Suspended networks aren't usable.
assertFalse(controller.isSatisfied(createJobStatus(job), net,
createCapabilitiesBuilder().removeCapability(NET_CAPABILITY_NOT_SUSPENDED)