1 /* 2 * Copyright (C) 2020 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.jobscheduler.cts; 18 19 import android.app.job.JobInfo; 20 import android.app.job.JobScheduler; 21 import android.app.job.JobWorkItem; 22 import android.content.Intent; 23 import android.jobscheduler.MockJobService; 24 import android.os.PersistableBundle; 25 26 import java.util.List; 27 28 /** 29 * Tests related to created and reading JobWorkItem objects. 30 */ 31 public class JobWorkItemTest extends BaseJobSchedulerTest { 32 private static final int JOB_ID = JobWorkItemTest.class.hashCode(); 33 private static final Intent TEST_INTENT = new Intent("some.random.action"); 34 testAllInfoGivenToJob()35 public void testAllInfoGivenToJob() throws Exception { 36 final JobInfo jobInfo = new JobInfo.Builder(JOB_ID, kJobServiceComponent) 37 .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY) 38 .build(); 39 final PersistableBundle pb = new PersistableBundle(); 40 pb.putInt("random_key", 42); 41 final JobWorkItem expectedJwi = new JobWorkItem.Builder() 42 .setIntent(TEST_INTENT) 43 .setExtras(pb) 44 .setEstimatedNetworkBytes(30, 20) 45 .setMinimumNetworkChunkBytes(5) 46 .build(); 47 // JobWorkItem hasn't been scheduled yet. Delivery count should be 0. 48 assertEquals(0, expectedJwi.getDeliveryCount()); 49 50 try (NetworkingHelper networkingHelper = 51 new NetworkingHelper(getInstrumentation(), getContext())) { 52 networkingHelper.setAllNetworksEnabled(true); 53 kTestEnvironment.setExpectedExecutions(1); 54 kTestEnvironment.setExpectedWork(new MockJobService.TestWorkItem[]{ 55 new MockJobService.TestWorkItem(TEST_INTENT)}); 56 kTestEnvironment.readyToWork(); 57 mJobScheduler.enqueue(jobInfo, expectedJwi); 58 runSatisfiedJob(JOB_ID); 59 assertTrue("Job didn't fire immediately", kTestEnvironment.awaitExecution()); 60 } 61 62 List<JobWorkItem> executedJwis = kTestEnvironment.getLastReceivedWork(); 63 assertEquals(1, executedJwis.size()); 64 final JobWorkItem actualJwi = executedJwis.get(0); 65 assertEquals(1, actualJwi.getDeliveryCount()); 66 final Intent actualIntent = actualJwi.getIntent(); 67 assertNotNull(actualIntent); 68 assertEquals(TEST_INTENT.getAction(), actualIntent.getAction()); 69 final PersistableBundle extras = actualJwi.getExtras(); 70 assertNotNull(extras); 71 assertEquals(1, extras.keySet().size()); 72 assertEquals(42, extras.getInt("random_key")); 73 assertEquals(30, actualJwi.getEstimatedNetworkDownloadBytes()); 74 assertEquals(20, actualJwi.getEstimatedNetworkUploadBytes()); 75 assertEquals(5, actualJwi.getMinimumNetworkChunkBytes()); 76 } 77 testIntentOnlyItem_builder()78 public void testIntentOnlyItem_builder() { 79 JobWorkItem jwi = new JobWorkItem.Builder().setIntent(TEST_INTENT).build(); 80 81 assertEquals(TEST_INTENT, jwi.getIntent()); 82 assertEquals(JobInfo.NETWORK_BYTES_UNKNOWN, jwi.getEstimatedNetworkDownloadBytes()); 83 assertEquals(JobInfo.NETWORK_BYTES_UNKNOWN, jwi.getEstimatedNetworkUploadBytes()); 84 assertEquals(JobInfo.NETWORK_BYTES_UNKNOWN, jwi.getMinimumNetworkChunkBytes()); 85 // JobWorkItem hasn't been scheduled yet. Delivery count should be 0. 86 assertEquals(0, jwi.getDeliveryCount()); 87 assertTrue(jwi.getExtras().isEmpty()); 88 } 89 testIntentOnlyItem_ctor()90 public void testIntentOnlyItem_ctor() { 91 JobWorkItem jwi = new JobWorkItem(TEST_INTENT); 92 93 assertEquals(TEST_INTENT, jwi.getIntent()); 94 assertEquals(JobInfo.NETWORK_BYTES_UNKNOWN, jwi.getEstimatedNetworkDownloadBytes()); 95 assertEquals(JobInfo.NETWORK_BYTES_UNKNOWN, jwi.getEstimatedNetworkUploadBytes()); 96 assertEquals(JobInfo.NETWORK_BYTES_UNKNOWN, jwi.getMinimumNetworkChunkBytes()); 97 // JobWorkItem hasn't been scheduled yet. Delivery count should be 0. 98 assertEquals(0, jwi.getDeliveryCount()); 99 assertTrue(jwi.getExtras().isEmpty()); 100 } 101 testItemWithEstimatedBytes_builder()102 public void testItemWithEstimatedBytes_builder() { 103 try { 104 new JobWorkItem.Builder().setEstimatedNetworkBytes(-10, 20).build(); 105 fail("Successfully created JobWorkItem with negative download bytes value"); 106 } catch (IllegalArgumentException expected) { 107 // Success 108 } 109 110 try { 111 new JobWorkItem.Builder().setEstimatedNetworkBytes(10, -20).build(); 112 fail("Successfully created JobWorkItem with negative upload bytes value"); 113 } catch (IllegalArgumentException expected) { 114 // Success 115 } 116 117 JobWorkItem jwi = new JobWorkItem.Builder().setEstimatedNetworkBytes(10, 20).build(); 118 assertNull(jwi.getIntent()); 119 assertEquals(10, jwi.getEstimatedNetworkDownloadBytes()); 120 assertEquals(20, jwi.getEstimatedNetworkUploadBytes()); 121 // JobWorkItem hasn't been scheduled yet. Delivery count should be 0. 122 assertEquals(0, jwi.getDeliveryCount()); 123 assertTrue(jwi.getExtras().isEmpty()); 124 } 125 testItemWithEstimatedBytes_ctor()126 public void testItemWithEstimatedBytes_ctor() { 127 try { 128 new JobWorkItem(TEST_INTENT, -10, 20); 129 fail("Successfully created JobWorkItem with negative download bytes value"); 130 } catch (IllegalArgumentException expected) { 131 // Success 132 } 133 134 try { 135 new JobWorkItem(TEST_INTENT, 10, -20); 136 fail("Successfully created JobWorkItem with negative upload bytes value"); 137 } catch (IllegalArgumentException expected) { 138 // Success 139 } 140 141 JobWorkItem jwi = new JobWorkItem(TEST_INTENT, 10, 20); 142 143 assertEquals(TEST_INTENT, jwi.getIntent()); 144 assertEquals(10, jwi.getEstimatedNetworkDownloadBytes()); 145 assertEquals(20, jwi.getEstimatedNetworkUploadBytes()); 146 // JobWorkItem hasn't been scheduled yet. Delivery count should be 0. 147 assertEquals(0, jwi.getDeliveryCount()); 148 assertTrue(jwi.getExtras().isEmpty()); 149 } 150 testItemWithMinimumChunkBytes_builder()151 public void testItemWithMinimumChunkBytes_builder() { 152 JobWorkItem jwi = new JobWorkItem.Builder().setMinimumNetworkChunkBytes(3).build(); 153 154 assertNull(jwi.getIntent()); 155 assertEquals(JobInfo.NETWORK_BYTES_UNKNOWN, jwi.getEstimatedNetworkDownloadBytes()); 156 assertEquals(JobInfo.NETWORK_BYTES_UNKNOWN, jwi.getEstimatedNetworkUploadBytes()); 157 assertEquals(3, jwi.getMinimumNetworkChunkBytes()); 158 // JobWorkItem hasn't been scheduled yet. Delivery count should be 0. 159 assertEquals(0, jwi.getDeliveryCount()); 160 assertTrue(jwi.getExtras().isEmpty()); 161 162 try { 163 new JobWorkItem.Builder().setMinimumNetworkChunkBytes(-3).build(); 164 fail("Successfully created JobWorkItem with negative minimum chunk value"); 165 } catch (IllegalArgumentException expected) { 166 // Success 167 } 168 try { 169 new JobWorkItem.Builder().setMinimumNetworkChunkBytes(0).build(); 170 fail("Successfully created JobWorkItem with 0 minimum chunk value"); 171 } catch (IllegalArgumentException expected) { 172 // Success 173 } 174 try { 175 new JobWorkItem.Builder() 176 .setEstimatedNetworkBytes(10, 20) 177 .setMinimumNetworkChunkBytes(50) 178 .build(); 179 fail("Successfully created JobWorkItem with minimum chunk value too large"); 180 } catch (IllegalArgumentException expected) { 181 // Success 182 } 183 try { 184 new JobWorkItem.Builder() 185 .setEstimatedNetworkBytes(JobInfo.NETWORK_BYTES_UNKNOWN, 20) 186 .setMinimumNetworkChunkBytes(25) 187 .build(); 188 fail("Successfully created JobWorkItem with minimum chunk value too large"); 189 } catch (IllegalArgumentException expected) { 190 // Success 191 } 192 try { 193 new JobWorkItem.Builder() 194 .setEstimatedNetworkBytes(10, JobInfo.NETWORK_BYTES_UNKNOWN) 195 .setMinimumNetworkChunkBytes(15) 196 .build(); 197 fail("Successfully created JobWorkItem with minimum chunk value too large"); 198 } catch (IllegalArgumentException expected) { 199 // Success 200 } 201 } 202 testItemWithMinimumChunkBytes_ctor()203 public void testItemWithMinimumChunkBytes_ctor() { 204 JobWorkItem jwi = new JobWorkItem(TEST_INTENT, 10, 20, 3); 205 206 assertEquals(TEST_INTENT, jwi.getIntent()); 207 assertEquals(10, jwi.getEstimatedNetworkDownloadBytes()); 208 assertEquals(20, jwi.getEstimatedNetworkUploadBytes()); 209 assertEquals(3, jwi.getMinimumNetworkChunkBytes()); 210 // JobWorkItem hasn't been scheduled yet. Delivery count should be 0. 211 assertEquals(0, jwi.getDeliveryCount()); 212 assertTrue(jwi.getExtras().isEmpty()); 213 214 try { 215 new JobWorkItem(TEST_INTENT, 10, 20, -3); 216 fail("Successfully created JobWorkItem with negative minimum chunk value"); 217 } catch (IllegalArgumentException expected) { 218 // Success 219 } 220 try { 221 new JobWorkItem(TEST_INTENT, 10, 20, 0); 222 fail("Successfully created JobWorkItem with 0 minimum chunk value"); 223 } catch (IllegalArgumentException expected) { 224 // Success 225 } 226 try { 227 new JobWorkItem(TEST_INTENT, 10, 20, 50); 228 fail("Successfully created JobWorkItem with minimum chunk value too large"); 229 } catch (IllegalArgumentException expected) { 230 // Success 231 } 232 try { 233 new JobWorkItem(TEST_INTENT, JobInfo.NETWORK_BYTES_UNKNOWN, 20, 25); 234 fail("Successfully created JobWorkItem with minimum chunk value too large"); 235 } catch (IllegalArgumentException expected) { 236 // Success 237 } 238 try { 239 new JobWorkItem(TEST_INTENT, 10, JobInfo.NETWORK_BYTES_UNKNOWN, 15); 240 fail("Successfully created JobWorkItem with minimum chunk value too large"); 241 } catch (IllegalArgumentException expected) { 242 // Success 243 } 244 } 245 testItemWithPersistableBundle()246 public void testItemWithPersistableBundle() { 247 final PersistableBundle pb = new PersistableBundle(); 248 pb.putInt("random_key", 42); 249 JobWorkItem jwi = new JobWorkItem.Builder().setExtras(pb).build(); 250 251 assertNull(jwi.getIntent()); 252 assertEquals(JobInfo.NETWORK_BYTES_UNKNOWN, jwi.getEstimatedNetworkDownloadBytes()); 253 assertEquals(JobInfo.NETWORK_BYTES_UNKNOWN, jwi.getEstimatedNetworkUploadBytes()); 254 assertEquals(JobInfo.NETWORK_BYTES_UNKNOWN, jwi.getMinimumNetworkChunkBytes()); 255 // JobWorkItem hasn't been scheduled yet. Delivery count should be 0. 256 assertEquals(0, jwi.getDeliveryCount()); 257 final PersistableBundle extras = jwi.getExtras(); 258 assertNotNull(extras); 259 assertEquals(1, extras.keySet().size()); 260 assertEquals(42, extras.getInt("random_key")); 261 262 try { 263 new JobWorkItem.Builder().setExtras(null).build(); 264 fail("Successfully created null extras"); 265 } catch (Exception expected) { 266 // Success 267 } 268 } 269 testDeliveryCountBumped()270 public void testDeliveryCountBumped() throws Exception { 271 JobInfo jobInfo = new JobInfo.Builder(JOB_ID, kJobServiceComponent).build(); 272 JobWorkItem jwi = new JobWorkItem(TEST_INTENT); 273 // JobWorkItem hasn't been scheduled yet. Delivery count should be 0. 274 assertEquals(0, jwi.getDeliveryCount()); 275 276 kTestEnvironment.setExpectedExecutions(1); 277 kTestEnvironment.setExpectedWork(new MockJobService.TestWorkItem[]{ 278 new MockJobService.TestWorkItem(TEST_INTENT)}); 279 kTestEnvironment.readyToWork(); 280 mJobScheduler.enqueue(jobInfo, jwi); 281 runSatisfiedJob(JOB_ID); 282 assertTrue("Job didn't fire immediately", kTestEnvironment.awaitExecution()); 283 284 List<JobWorkItem> executedJWIs = kTestEnvironment.getLastReceivedWork(); 285 assertEquals(1, executedJWIs.size()); 286 assertEquals(1, executedJWIs.get(0).getDeliveryCount()); 287 } 288 testPersisted_withIntent()289 public void testPersisted_withIntent() { 290 JobWorkItem jwi = new JobWorkItem.Builder().setIntent(TEST_INTENT).build(); 291 JobInfo jobInfo = new JobInfo.Builder(JOB_ID, kJobServiceComponent) 292 .setPersisted(true) 293 .build(); 294 try { 295 mJobScheduler.enqueue(jobInfo, jwi); 296 fail("Successfully enqueued persisted JWI with intent"); 297 } catch (IllegalArgumentException expected) { 298 // Success 299 } 300 } 301 testPersisted_withPersistableBundle()302 public void testPersisted_withPersistableBundle() { 303 final PersistableBundle pb = new PersistableBundle(); 304 pb.putInt("random_key", 42); 305 JobWorkItem jwi = new JobWorkItem.Builder().setExtras(pb).build(); 306 JobInfo jobInfo = new JobInfo.Builder(JOB_ID, kJobServiceComponent) 307 .setPersisted(true) 308 .build(); 309 310 assertEquals(JobScheduler.RESULT_SUCCESS, mJobScheduler.enqueue(jobInfo, jwi)); 311 } 312 testScheduleItemWithNetworkInfoAndNoNetworkConstraint_download()313 public void testScheduleItemWithNetworkInfoAndNoNetworkConstraint_download() { 314 JobWorkItem jwi = new JobWorkItem(TEST_INTENT, 10, JobInfo.NETWORK_BYTES_UNKNOWN); 315 JobInfo jobInfo = new JobInfo.Builder(JOB_ID, kJobServiceComponent).build(); 316 try { 317 mJobScheduler.enqueue(jobInfo, jwi); 318 fail("Successfully scheduled JobWorkItem with network implication" 319 + " and job with no network constraint"); 320 } catch (IllegalArgumentException expected) { 321 // Success 322 } 323 } 324 testScheduleItemWithNetworkInfoAndNoNetworkConstraint_upload()325 public void testScheduleItemWithNetworkInfoAndNoNetworkConstraint_upload() { 326 JobWorkItem jwi = new JobWorkItem(TEST_INTENT, JobInfo.NETWORK_BYTES_UNKNOWN, 10); 327 JobInfo jobInfo = new JobInfo.Builder(JOB_ID, kJobServiceComponent).build(); 328 try { 329 mJobScheduler.enqueue(jobInfo, jwi); 330 fail("Successfully scheduled JobWorkItem with network implication" 331 + " and job with no network constraint"); 332 } catch (IllegalArgumentException expected) { 333 // Success 334 } 335 } 336 testScheduleItemWithNetworkInfoAndNoNetworkConstraint_minimumChunk()337 public void testScheduleItemWithNetworkInfoAndNoNetworkConstraint_minimumChunk() { 338 JobWorkItem jwi = new JobWorkItem(TEST_INTENT, 339 JobInfo.NETWORK_BYTES_UNKNOWN, JobInfo.NETWORK_BYTES_UNKNOWN, 10); 340 JobInfo jobInfo = new JobInfo.Builder(JOB_ID, kJobServiceComponent).build(); 341 try { 342 mJobScheduler.enqueue(jobInfo, jwi); 343 fail("Successfully scheduled JobWorkItem with network implication" 344 + " and job with no network constraint"); 345 } catch (IllegalArgumentException expected) { 346 // Success 347 } 348 } 349 testScheduleItemWithNetworkInfoAndNoNetworkConstraint()350 public void testScheduleItemWithNetworkInfoAndNoNetworkConstraint() { 351 JobWorkItem jwi = new JobWorkItem(TEST_INTENT, 10, 10, 10); 352 JobInfo jobInfo = new JobInfo.Builder(JOB_ID, kJobServiceComponent) 353 .setRequiredNetworkType(JobInfo.NETWORK_TYPE_NONE) 354 .build(); 355 try { 356 mJobScheduler.enqueue(jobInfo, jwi); 357 fail("Successfully scheduled JobWorkItem with network implication" 358 + " and job with no network constraint"); 359 } catch (IllegalArgumentException expected) { 360 // Success 361 } 362 } 363 testScheduleItemWithNetworkInfoAndNetworkConstraint()364 public void testScheduleItemWithNetworkInfoAndNetworkConstraint() { 365 JobWorkItem jwi = new JobWorkItem(TEST_INTENT, 366 JobInfo.NETWORK_BYTES_UNKNOWN, JobInfo.NETWORK_BYTES_UNKNOWN, 10); 367 JobInfo jobInfo = new JobInfo.Builder(JOB_ID, kJobServiceComponent) 368 .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY) 369 .build(); 370 assertEquals(JobScheduler.RESULT_SUCCESS, mJobScheduler.enqueue(jobInfo, jwi)); 371 } 372 } 373