1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.app.job; 18 19 import static android.app.job.JobInfo.NETWORK_BYTES_UNKNOWN; 20 21 import android.annotation.BytesLong; 22 import android.annotation.Nullable; 23 import android.compat.annotation.UnsupportedAppUsage; 24 import android.content.Intent; 25 import android.os.Build; 26 import android.os.Parcel; 27 import android.os.Parcelable; 28 29 /** 30 * A unit of work that can be enqueued for a job using 31 * {@link JobScheduler#enqueue JobScheduler.enqueue}. See 32 * {@link JobParameters#dequeueWork() JobParameters.dequeueWork} for more details. 33 */ 34 final public class JobWorkItem implements Parcelable { 35 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 36 final Intent mIntent; 37 private final long mNetworkDownloadBytes; 38 private final long mNetworkUploadBytes; 39 private final long mMinimumChunkBytes; 40 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 41 int mDeliveryCount; 42 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 43 int mWorkId; 44 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 45 Object mGrants; 46 47 /** 48 * Create a new piece of work, which can be submitted to 49 * {@link JobScheduler#enqueue JobScheduler.enqueue}. 50 * 51 * @param intent The general Intent describing this work. 52 */ JobWorkItem(Intent intent)53 public JobWorkItem(Intent intent) { 54 this(intent, NETWORK_BYTES_UNKNOWN, NETWORK_BYTES_UNKNOWN); 55 } 56 57 /** 58 * Create a new piece of work, which can be submitted to 59 * {@link JobScheduler#enqueue JobScheduler.enqueue}. 60 * <p> 61 * See {@link JobInfo.Builder#setEstimatedNetworkBytes(long, long)} for 62 * details about how to estimate network traffic. 63 * 64 * @param intent The general Intent describing this work. 65 * @param downloadBytes The estimated size of network traffic that will be 66 * downloaded by this job work item, in bytes. 67 * @param uploadBytes The estimated size of network traffic that will be 68 * uploaded by this job work item, in bytes. 69 */ JobWorkItem(Intent intent, @BytesLong long downloadBytes, @BytesLong long uploadBytes)70 public JobWorkItem(Intent intent, @BytesLong long downloadBytes, @BytesLong long uploadBytes) { 71 this(intent, downloadBytes, uploadBytes, NETWORK_BYTES_UNKNOWN); 72 } 73 74 /** 75 * Create a new piece of work, which can be submitted to 76 * {@link JobScheduler#enqueue JobScheduler.enqueue}. 77 * <p> 78 * See {@link JobInfo.Builder#setEstimatedNetworkBytes(long, long)} for 79 * details about how to estimate network traffic. 80 * 81 * @param intent The general Intent describing this work. 82 * @param downloadBytes The estimated size of network traffic that will be 83 * downloaded by this job work item, in bytes. 84 * @param uploadBytes The estimated size of network traffic that will be 85 * uploaded by this job work item, in bytes. 86 * @param minimumChunkBytes The smallest piece of data that cannot be easily paused and 87 * resumed, in bytes. 88 */ JobWorkItem(@ullable Intent intent, @BytesLong long downloadBytes, @BytesLong long uploadBytes, @BytesLong long minimumChunkBytes)89 public JobWorkItem(@Nullable Intent intent, @BytesLong long downloadBytes, 90 @BytesLong long uploadBytes, @BytesLong long minimumChunkBytes) { 91 if (minimumChunkBytes != NETWORK_BYTES_UNKNOWN && minimumChunkBytes <= 0) { 92 throw new IllegalArgumentException("Minimum chunk size must be positive"); 93 } 94 final long estimatedTransfer; 95 if (uploadBytes == NETWORK_BYTES_UNKNOWN) { 96 estimatedTransfer = downloadBytes; 97 } else { 98 estimatedTransfer = uploadBytes 99 + (downloadBytes == NETWORK_BYTES_UNKNOWN ? 0 : downloadBytes); 100 } 101 if (minimumChunkBytes != NETWORK_BYTES_UNKNOWN && estimatedTransfer != NETWORK_BYTES_UNKNOWN 102 && minimumChunkBytes > estimatedTransfer) { 103 throw new IllegalArgumentException( 104 "Minimum chunk size can't be greater than estimated network usage"); 105 } 106 mIntent = intent; 107 mNetworkDownloadBytes = downloadBytes; 108 mNetworkUploadBytes = uploadBytes; 109 mMinimumChunkBytes = minimumChunkBytes; 110 } 111 112 /** 113 * Return the Intent associated with this work. 114 */ getIntent()115 public Intent getIntent() { 116 return mIntent; 117 } 118 119 /** 120 * Return the estimated size of download traffic that will be performed by 121 * this job, in bytes. 122 * 123 * @return Estimated size of download traffic, or 124 * {@link JobInfo#NETWORK_BYTES_UNKNOWN} when unknown. 125 */ getEstimatedNetworkDownloadBytes()126 public @BytesLong long getEstimatedNetworkDownloadBytes() { 127 return mNetworkDownloadBytes; 128 } 129 130 /** 131 * Return the estimated size of upload traffic that will be performed by 132 * this job work item, in bytes. 133 * 134 * @return Estimated size of upload traffic, or 135 * {@link JobInfo#NETWORK_BYTES_UNKNOWN} when unknown. 136 */ getEstimatedNetworkUploadBytes()137 public @BytesLong long getEstimatedNetworkUploadBytes() { 138 return mNetworkUploadBytes; 139 } 140 141 /** 142 * Return the smallest piece of data that cannot be easily paused and resumed, in bytes. 143 * 144 * @return Smallest piece of data that cannot be easily paused and resumed, or 145 * {@link JobInfo#NETWORK_BYTES_UNKNOWN} when unknown. 146 */ getMinimumNetworkChunkBytes()147 public @BytesLong long getMinimumNetworkChunkBytes() { 148 return mMinimumChunkBytes; 149 } 150 151 /** 152 * Return the count of the number of times this work item has been delivered 153 * to the job. The value will be > 1 if it has been redelivered because the job 154 * was stopped or crashed while it had previously been delivered but before the 155 * job had called {@link JobParameters#completeWork JobParameters.completeWork} for it. 156 */ getDeliveryCount()157 public int getDeliveryCount() { 158 return mDeliveryCount; 159 } 160 161 /** 162 * @hide 163 */ bumpDeliveryCount()164 public void bumpDeliveryCount() { 165 mDeliveryCount++; 166 } 167 168 /** 169 * @hide 170 */ setWorkId(int id)171 public void setWorkId(int id) { 172 mWorkId = id; 173 } 174 175 /** 176 * @hide 177 */ getWorkId()178 public int getWorkId() { 179 return mWorkId; 180 } 181 182 /** 183 * @hide 184 */ setGrants(Object grants)185 public void setGrants(Object grants) { 186 mGrants = grants; 187 } 188 189 /** 190 * @hide 191 */ getGrants()192 public Object getGrants() { 193 return mGrants; 194 } 195 toString()196 public String toString() { 197 StringBuilder sb = new StringBuilder(64); 198 sb.append("JobWorkItem{id="); 199 sb.append(mWorkId); 200 sb.append(" intent="); 201 sb.append(mIntent); 202 if (mNetworkDownloadBytes != NETWORK_BYTES_UNKNOWN) { 203 sb.append(" downloadBytes="); 204 sb.append(mNetworkDownloadBytes); 205 } 206 if (mNetworkUploadBytes != NETWORK_BYTES_UNKNOWN) { 207 sb.append(" uploadBytes="); 208 sb.append(mNetworkUploadBytes); 209 } 210 if (mMinimumChunkBytes != NETWORK_BYTES_UNKNOWN) { 211 sb.append(" minimumChunkBytes="); 212 sb.append(mMinimumChunkBytes); 213 } 214 if (mDeliveryCount != 0) { 215 sb.append(" dcount="); 216 sb.append(mDeliveryCount); 217 } 218 sb.append("}"); 219 return sb.toString(); 220 } 221 222 /** 223 * @hide 224 */ enforceValidity()225 public void enforceValidity() { 226 final long estimatedTransfer; 227 if (mNetworkUploadBytes == NETWORK_BYTES_UNKNOWN) { 228 estimatedTransfer = mNetworkDownloadBytes; 229 } else { 230 estimatedTransfer = mNetworkUploadBytes 231 + (mNetworkDownloadBytes == NETWORK_BYTES_UNKNOWN ? 0 : mNetworkDownloadBytes); 232 } 233 if (mMinimumChunkBytes != NETWORK_BYTES_UNKNOWN 234 && estimatedTransfer != NETWORK_BYTES_UNKNOWN 235 && mMinimumChunkBytes > estimatedTransfer) { 236 throw new IllegalArgumentException( 237 "Minimum chunk size can't be greater than estimated network usage"); 238 } 239 if (mMinimumChunkBytes != NETWORK_BYTES_UNKNOWN && mMinimumChunkBytes <= 0) { 240 throw new IllegalArgumentException("Minimum chunk size must be positive"); 241 } 242 } 243 describeContents()244 public int describeContents() { 245 return 0; 246 } 247 writeToParcel(Parcel out, int flags)248 public void writeToParcel(Parcel out, int flags) { 249 if (mIntent != null) { 250 out.writeInt(1); 251 mIntent.writeToParcel(out, 0); 252 } else { 253 out.writeInt(0); 254 } 255 out.writeLong(mNetworkDownloadBytes); 256 out.writeLong(mNetworkUploadBytes); 257 out.writeLong(mMinimumChunkBytes); 258 out.writeInt(mDeliveryCount); 259 out.writeInt(mWorkId); 260 } 261 262 public static final @android.annotation.NonNull Parcelable.Creator<JobWorkItem> CREATOR 263 = new Parcelable.Creator<JobWorkItem>() { 264 public JobWorkItem createFromParcel(Parcel in) { 265 return new JobWorkItem(in); 266 } 267 268 public JobWorkItem[] newArray(int size) { 269 return new JobWorkItem[size]; 270 } 271 }; 272 273 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) JobWorkItem(Parcel in)274 JobWorkItem(Parcel in) { 275 if (in.readInt() != 0) { 276 mIntent = Intent.CREATOR.createFromParcel(in); 277 } else { 278 mIntent = null; 279 } 280 mNetworkDownloadBytes = in.readLong(); 281 mNetworkUploadBytes = in.readLong(); 282 mMinimumChunkBytes = in.readLong(); 283 mDeliveryCount = in.readInt(); 284 mWorkId = in.readInt(); 285 } 286 } 287