1 /* 2 * Copyright (C) 2014 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; 18 19 import android.annotation.NonNull; 20 import android.annotation.TargetApi; 21 import android.app.Notification; 22 import android.app.job.JobInfo; 23 import android.app.job.JobParameters; 24 import android.app.job.JobScheduler; 25 import android.app.job.JobService; 26 import android.app.job.JobWorkItem; 27 import android.content.ClipData; 28 import android.content.Context; 29 import android.content.Intent; 30 import android.content.pm.PackageManager; 31 import android.net.Uri; 32 import android.os.Process; 33 import android.util.Log; 34 35 import junit.framework.Assert; 36 37 import java.util.ArrayList; 38 import java.util.List; 39 import java.util.concurrent.CountDownLatch; 40 import java.util.concurrent.TimeUnit; 41 42 /** 43 * Handles callback from the framework {@link android.app.job.JobScheduler}. The behaviour of this 44 * class is configured through the static 45 * {@link TestEnvironment}. 46 */ 47 @TargetApi(21) 48 public class MockJobService extends JobService { 49 private static final String TAG = "MockJobService"; 50 51 /** Wait this long before timing out the test. */ 52 private static final long DEFAULT_TIMEOUT_MILLIS = 30000L; // 30 seconds. 53 54 private JobParameters mParams; 55 56 ArrayList<JobWorkItem> mReceivedWork = new ArrayList<>(); 57 58 ArrayList<JobWorkItem> mPendingCompletions = new ArrayList<>(); 59 60 private boolean mWaitingForStop; 61 62 private long mEstimatedDownloadBytes = JobInfo.NETWORK_BYTES_UNKNOWN; 63 private long mEstimatedUploadBytes = JobInfo.NETWORK_BYTES_UNKNOWN; 64 private long mTransferredDownloadBytes = JobInfo.NETWORK_BYTES_UNKNOWN; 65 private long mTransferredUploadBytes = JobInfo.NETWORK_BYTES_UNKNOWN; 66 67 @Override onDestroy()68 public void onDestroy() { 69 super.onDestroy(); 70 Log.i(TAG, "Destroying test service"); 71 if (TestEnvironment.getTestEnvironment().getExpectedWork() != null) { 72 TestEnvironment.getTestEnvironment().notifyExecution(this, mParams, 0, 0, mReceivedWork, 73 null); 74 } 75 } 76 77 @Override onCreate()78 public void onCreate() { 79 super.onCreate(); 80 Log.i(TAG, "Created test service."); 81 } 82 83 @Override onStartJob(JobParameters params)84 public boolean onStartJob(JobParameters params) { 85 Log.i(TAG, "Test job executing: " + params.getJobId()); 86 mParams = params; 87 TestEnvironment.getTestEnvironment().addEvent( 88 new TestEnvironment.Event( 89 TestEnvironment.Event.EVENT_START_JOB, params.getJobId())); 90 91 final Notification notificationToPost = 92 TestEnvironment.getTestEnvironment().getJobStartNotification(); 93 if (notificationToPost != null) { 94 setNotification(params, 95 TestEnvironment.getTestEnvironment().getJobStartNotificationId(), 96 notificationToPost, 97 TestEnvironment.getTestEnvironment().getJobStartNotificationEndPolicy()); 98 } 99 int permCheckRead = PackageManager.PERMISSION_DENIED; 100 int permCheckWrite = PackageManager.PERMISSION_DENIED; 101 ClipData clip = params.getClipData(); 102 if (clip != null) { 103 permCheckRead = checkUriPermission(clip.getItemAt(0).getUri(), Process.myPid(), 104 Process.myUid(), Intent.FLAG_GRANT_READ_URI_PERMISSION); 105 permCheckWrite = checkUriPermission(clip.getItemAt(0).getUri(), Process.myPid(), 106 Process.myUid(), Intent.FLAG_GRANT_WRITE_URI_PERMISSION); 107 } 108 109 TestWorkItem[] expectedWork = TestEnvironment.getTestEnvironment().getExpectedWork(); 110 if (expectedWork != null) { 111 try { 112 if (!TestEnvironment.getTestEnvironment().awaitDoWork()) { 113 TestEnvironment.getTestEnvironment().notifyExecution(this, 114 params, permCheckRead, 115 permCheckWrite, null, "Spent too long waiting to start executing work"); 116 return false; 117 } 118 } catch (InterruptedException e) { 119 TestEnvironment.getTestEnvironment().notifyExecution(this, 120 params, permCheckRead, 121 permCheckWrite, null, "Failed waiting for work: " + e); 122 return false; 123 } 124 JobWorkItem work; 125 int index = 0; 126 while ((work = params.dequeueWork()) != null) { 127 final Intent intent = work.getIntent(); 128 Log.i(TAG, "Received work #" + index + ": " + intent); 129 mReceivedWork.add(work); 130 131 int flags = 0; 132 133 if (index < expectedWork.length) { 134 TestWorkItem expected = expectedWork[index]; 135 int grantFlags = intent == null ? 0 : intent.getFlags(); 136 if (expected.requireUrisGranted != null) { 137 for (int ui = 0; ui < expected.requireUrisGranted.length; ui++) { 138 if ((grantFlags & Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) { 139 if (checkUriPermission(expected.requireUrisGranted[ui], 140 Process.myPid(), Process.myUid(), 141 Intent.FLAG_GRANT_READ_URI_PERMISSION) 142 != PackageManager.PERMISSION_GRANTED) { 143 TestEnvironment.getTestEnvironment().notifyExecution(this, 144 params, 145 permCheckRead, permCheckWrite, null, 146 "Expected read permission but not granted: " 147 + expected.requireUrisGranted[ui] 148 + " @ #" + index); 149 return false; 150 } 151 } 152 if ((grantFlags & Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) { 153 if (checkUriPermission(expected.requireUrisGranted[ui], 154 Process.myPid(), Process.myUid(), 155 Intent.FLAG_GRANT_WRITE_URI_PERMISSION) 156 != PackageManager.PERMISSION_GRANTED) { 157 TestEnvironment.getTestEnvironment().notifyExecution(this, 158 params, 159 permCheckRead, permCheckWrite, null, 160 "Expected write permission but not granted: " 161 + expected.requireUrisGranted[ui] 162 + " @ #" + index); 163 return false; 164 } 165 } 166 } 167 } 168 if (expected.requireUrisNotGranted != null) { 169 // XXX note no delay here, current impl will have fully revoked the 170 // permission by the time we return from completing the last work. 171 for (int ui = 0; ui < expected.requireUrisNotGranted.length; ui++) { 172 if ((grantFlags & Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) { 173 if (checkUriPermission(expected.requireUrisNotGranted[ui], 174 Process.myPid(), Process.myUid(), 175 Intent.FLAG_GRANT_READ_URI_PERMISSION) 176 != PackageManager.PERMISSION_DENIED) { 177 TestEnvironment.getTestEnvironment().notifyExecution(this, 178 params, 179 permCheckRead, permCheckWrite, null, 180 "Not expected read permission but granted: " 181 + expected.requireUrisNotGranted[ui] 182 + " @ #" + index); 183 return false; 184 } 185 } 186 if ((grantFlags & Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) { 187 if (checkUriPermission(expected.requireUrisNotGranted[ui], 188 Process.myPid(), Process.myUid(), 189 Intent.FLAG_GRANT_WRITE_URI_PERMISSION) 190 != PackageManager.PERMISSION_DENIED) { 191 TestEnvironment.getTestEnvironment().notifyExecution(this, 192 params, 193 permCheckRead, permCheckWrite, null, 194 "Not expected write permission but granted: " 195 + expected.requireUrisNotGranted[ui] 196 + " @ #" + index); 197 return false; 198 } 199 } 200 } 201 } 202 203 flags = expected.flags; 204 205 if ((flags & TestWorkItem.FLAG_WAIT_FOR_STOP) != 0) { 206 Log.i(TAG, "Now waiting to stop"); 207 mWaitingForStop = true; 208 TestEnvironment.getTestEnvironment().notifyWaitingForStop(); 209 return true; 210 } 211 212 if ((flags & TestWorkItem.FLAG_COMPLETE_NEXT) != 0) { 213 if (!processNextPendingCompletion()) { 214 TestEnvironment.getTestEnvironment().notifyExecution(this, params, 215 0, 0, null, 216 "Expected to complete next pending work but there was none: " 217 + " @ #" + index); 218 return false; 219 } 220 } 221 } 222 223 if ((flags & TestWorkItem.FLAG_DELAY_COMPLETE_PUSH_BACK) != 0) { 224 mPendingCompletions.add(work); 225 } else if ((flags & TestWorkItem.FLAG_DELAY_COMPLETE_PUSH_TOP) != 0) { 226 mPendingCompletions.add(0, work); 227 } else { 228 mParams.completeWork(work); 229 } 230 231 if (index < expectedWork.length) { 232 TestWorkItem expected = expectedWork[index]; 233 if (expected.subitems != null) { 234 final TestWorkItem[] sub = expected.subitems; 235 final JobInfo ji = expected.jobInfo; 236 final JobScheduler js = (JobScheduler) getSystemService( 237 Context.JOB_SCHEDULER_SERVICE); 238 for (int subi = 0; subi < sub.length; subi++) { 239 js.enqueue(ji, new JobWorkItem(sub[subi].intent)); 240 } 241 } 242 } 243 244 index++; 245 } 246 247 if (processNextPendingCompletion()) { 248 // We had some pending completions, clean them all out... 249 while (processNextPendingCompletion()) { 250 } 251 // ...and we need to do a final dequeue to complete the job, which should not 252 // return any remaining work. 253 if ((work = params.dequeueWork()) != null) { 254 TestEnvironment.getTestEnvironment().notifyExecution(this, params, 255 0, 0, null, 256 "Expected no remaining work after dequeue pending, but got: " + work); 257 } 258 } 259 260 Log.i(TAG, "Done with all work at #" + index); 261 // We don't notifyExecution here because we want to make sure the job properly 262 // stops itself. 263 return true; 264 } else { 265 boolean continueAfterStart 266 = TestEnvironment.getTestEnvironment().handleContinueAfterStart(); 267 try { 268 if (!TestEnvironment.getTestEnvironment().awaitDoJob()) { 269 TestEnvironment.getTestEnvironment().notifyExecution(this, 270 params, permCheckRead, 271 permCheckWrite, null, "Spent too long waiting to start job"); 272 return false; 273 } 274 } catch (InterruptedException e) { 275 TestEnvironment.getTestEnvironment().notifyExecution(this, params, permCheckRead, 276 permCheckWrite, null, "Failed waiting to start job: " + e); 277 return false; 278 } 279 TestEnvironment.getTestEnvironment().notifyExecution(this, params, permCheckRead, 280 permCheckWrite, null, null); 281 return continueAfterStart; 282 } 283 } 284 285 @Override onNetworkChanged(JobParameters params)286 public void onNetworkChanged(JobParameters params) { 287 TestEnvironment.getTestEnvironment().notifyNetworkChanged(params); 288 } 289 processNextPendingCompletion()290 boolean processNextPendingCompletion() { 291 if (mPendingCompletions.size() <= 0) { 292 return false; 293 } 294 295 JobWorkItem next = mPendingCompletions.remove(0); 296 mParams.completeWork(next); 297 return true; 298 } 299 300 @Override onStopJob(JobParameters params)301 public boolean onStopJob(JobParameters params) { 302 Log.i(TAG, "Received stop callback"); 303 TestEnvironment.getTestEnvironment().notifyStopped(params); 304 return mWaitingForStop || TestEnvironment.getTestEnvironment().requestReschedule(); 305 } 306 307 @Override getTransferredDownloadBytes(@onNull JobParameters params)308 public long getTransferredDownloadBytes(@NonNull JobParameters params) { 309 return mTransferredDownloadBytes; 310 } 311 312 @Override getTransferredUploadBytes(@onNull JobParameters params)313 public long getTransferredUploadBytes(@NonNull JobParameters params) { 314 return mTransferredUploadBytes; 315 } 316 317 @Override getTransferredDownloadBytes(@onNull JobParameters params, @NonNull JobWorkItem item)318 public long getTransferredDownloadBytes(@NonNull JobParameters params, 319 @NonNull JobWorkItem item) { 320 return mTransferredDownloadBytes; 321 } 322 323 @Override getTransferredUploadBytes(@onNull JobParameters params, @NonNull JobWorkItem item)324 public long getTransferredUploadBytes(@NonNull JobParameters params, 325 @NonNull JobWorkItem item) { 326 return mTransferredUploadBytes; 327 } 328 setEstimatedNetworkBytesForTest(long downloadBytes, long uploadBytes)329 private void setEstimatedNetworkBytesForTest(long downloadBytes, long uploadBytes) { 330 mEstimatedDownloadBytes = downloadBytes; 331 mEstimatedUploadBytes = uploadBytes; 332 updateEstimatedNetworkBytes(mParams, downloadBytes, uploadBytes); 333 } 334 setTransferredBytesForTest(long downloadBytes, long uploadBytes)335 private void setTransferredBytesForTest(long downloadBytes, long uploadBytes) { 336 mTransferredDownloadBytes = downloadBytes; 337 mTransferredUploadBytes = uploadBytes; 338 updateTransferredNetworkBytes(mParams, downloadBytes, uploadBytes); 339 } 340 341 public static final class TestWorkItem { 342 /** 343 * Stop processing work for now, waiting for the service to be stopped. 344 */ 345 public static final int FLAG_WAIT_FOR_STOP = 1<<0; 346 /** 347 * Don't complete this work now, instead push it on the back of the stack of 348 * pending completions. 349 */ 350 public static final int FLAG_DELAY_COMPLETE_PUSH_BACK = 1<<1; 351 /** 352 * Don't complete this work now, instead insert to the top of the stack of 353 * pending completions. 354 */ 355 public static final int FLAG_DELAY_COMPLETE_PUSH_TOP = 1<<2; 356 /** 357 * Complete next pending completion on the stack before completing this one. 358 */ 359 public static final int FLAG_COMPLETE_NEXT = 1<<3; 360 361 public final Intent intent; 362 public final JobInfo jobInfo; 363 public final int flags; 364 public final int deliveryCount; 365 public final TestWorkItem[] subitems; 366 public final Uri[] requireUrisGranted; 367 public final Uri[] requireUrisNotGranted; 368 TestWorkItem(Intent _intent)369 public TestWorkItem(Intent _intent) { 370 intent = _intent; 371 jobInfo = null; 372 flags = 0; 373 deliveryCount = 1; 374 subitems = null; 375 requireUrisGranted = null; 376 requireUrisNotGranted = null; 377 } 378 TestWorkItem(Intent _intent, int _flags)379 public TestWorkItem(Intent _intent, int _flags) { 380 intent = _intent; 381 jobInfo = null; 382 flags = _flags; 383 deliveryCount = 1; 384 subitems = null; 385 requireUrisGranted = null; 386 requireUrisNotGranted = null; 387 } 388 TestWorkItem(Intent _intent, int _flags, int _deliveryCount)389 public TestWorkItem(Intent _intent, int _flags, int _deliveryCount) { 390 intent = _intent; 391 jobInfo = null; 392 flags = _flags; 393 deliveryCount = _deliveryCount; 394 subitems = null; 395 requireUrisGranted = null; 396 requireUrisNotGranted = null; 397 } 398 TestWorkItem(Intent _intent, JobInfo _jobInfo, TestWorkItem[] _subitems)399 public TestWorkItem(Intent _intent, JobInfo _jobInfo, TestWorkItem[] _subitems) { 400 intent = _intent; 401 jobInfo = _jobInfo; 402 flags = 0; 403 deliveryCount = 1; 404 subitems = _subitems; 405 requireUrisGranted = null; 406 requireUrisNotGranted = null; 407 } 408 TestWorkItem(Intent _intent, Uri[] _requireUrisGranted, Uri[] _requireUrisNotGranted)409 public TestWorkItem(Intent _intent, Uri[] _requireUrisGranted, 410 Uri[] _requireUrisNotGranted) { 411 intent = _intent; 412 jobInfo = null; 413 flags = 0; 414 deliveryCount = 1; 415 subitems = null; 416 requireUrisGranted = _requireUrisGranted; 417 requireUrisNotGranted = _requireUrisNotGranted; 418 } 419 420 @Override toString()421 public String toString() { 422 return "TestWorkItem { " + intent + " dc=" + deliveryCount + " }"; 423 } 424 } 425 426 /** 427 * Configures the expected behaviour for each test. This object is shared across consecutive 428 * tests, so to clear state each test is responsible for calling 429 * {@link TestEnvironment#setUp()}. 430 */ 431 public static final class TestEnvironment { 432 433 private static TestEnvironment kTestEnvironment; 434 //public static final int INVALID_JOB_ID = -1; 435 436 private CountDownLatch mLatch; 437 private CountDownLatch mWaitingForStopLatch; 438 private CountDownLatch mDoJobLatch; 439 private CountDownLatch mStoppedLatch; 440 private CountDownLatch mDoWorkLatch; 441 private CountDownLatch mNetworkChangeLatch; 442 private TestWorkItem[] mExpectedWork; 443 private boolean mContinueAfterStart; 444 private boolean mRequestReschedule; 445 private JobParameters mExecutedJobParameters; 446 private JobParameters mNetworkChangedJobParameters; 447 private MockJobService mExecutedJobService; 448 private int mExecutedPermCheckRead; 449 private int mExecutedPermCheckWrite; 450 private ArrayList<JobWorkItem> mExecutedReceivedWork; 451 private String mExecutedErrorMessage; 452 private JobParameters mStopJobParameters; 453 private List<Event> mExecutedEvents = new ArrayList<>(); 454 private int mJobStartNotificationId; 455 private Notification mJobStartNotification; 456 private int mJobStartNotificationEndPolicy; 457 getTestEnvironment()458 public static TestEnvironment getTestEnvironment() { 459 if (kTestEnvironment == null) { 460 kTestEnvironment = new TestEnvironment(); 461 } 462 return kTestEnvironment; 463 } 464 getExpectedWork()465 public TestWorkItem[] getExpectedWork() { 466 return mExpectedWork; 467 } 468 getJobStartNotification()469 private Notification getJobStartNotification() { 470 return mJobStartNotification; 471 } 472 getJobStartNotificationEndPolicy()473 private int getJobStartNotificationEndPolicy() { 474 return mJobStartNotificationEndPolicy; 475 } 476 getJobStartNotificationId()477 private int getJobStartNotificationId() { 478 return mJobStartNotificationId; 479 } 480 getLastStartJobParameters()481 public JobParameters getLastStartJobParameters() { 482 return mExecutedJobParameters; 483 } 484 getLastStopJobParameters()485 public JobParameters getLastStopJobParameters() { 486 return mStopJobParameters; 487 } 488 getLastNetworkChangedJobParameters()489 public JobParameters getLastNetworkChangedJobParameters() { 490 return mNetworkChangedJobParameters; 491 } 492 getLastPermCheckRead()493 public int getLastPermCheckRead() { 494 return mExecutedPermCheckRead; 495 } 496 getLastPermCheckWrite()497 public int getLastPermCheckWrite() { 498 return mExecutedPermCheckWrite; 499 } 500 getLastReceivedWork()501 public ArrayList<JobWorkItem> getLastReceivedWork() { 502 return mExecutedReceivedWork; 503 } 504 getLastErrorMessage()505 public String getLastErrorMessage() { 506 return mExecutedErrorMessage; 507 } 508 509 /** 510 * Block the test thread, waiting on the JobScheduler to execute some previously scheduled 511 * job on this service. 512 */ awaitExecution()513 public boolean awaitExecution() throws InterruptedException { 514 return awaitExecution(DEFAULT_TIMEOUT_MILLIS); 515 } 516 awaitExecution(long timeoutMillis)517 public boolean awaitExecution(long timeoutMillis) throws InterruptedException { 518 final boolean executed = mLatch.await(timeoutMillis, TimeUnit.MILLISECONDS); 519 if (getLastErrorMessage() != null) { 520 Assert.fail(getLastErrorMessage()); 521 } 522 return executed; 523 } 524 525 /** 526 * Block the test thread, expecting to timeout but still listening to ensure that no jobs 527 * land in the interim. 528 * @return True if the latch timed out waiting on an execution. 529 */ awaitTimeout()530 public boolean awaitTimeout() throws InterruptedException { 531 return awaitTimeout(DEFAULT_TIMEOUT_MILLIS); 532 } 533 awaitTimeout(long timeoutMillis)534 public boolean awaitTimeout(long timeoutMillis) throws InterruptedException { 535 return !mLatch.await(timeoutMillis, TimeUnit.MILLISECONDS); 536 } 537 awaitWaitingForStop()538 public boolean awaitWaitingForStop() throws InterruptedException { 539 return mWaitingForStopLatch.await(DEFAULT_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); 540 } 541 awaitDoWork()542 public boolean awaitDoWork() throws InterruptedException { 543 return mDoWorkLatch.await(DEFAULT_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); 544 } 545 awaitDoJob()546 public boolean awaitDoJob() throws InterruptedException { 547 if (mDoJobLatch == null) { 548 return true; 549 } 550 return mDoJobLatch.await(DEFAULT_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); 551 } 552 awaitNetworkChange()553 public boolean awaitNetworkChange() throws InterruptedException { 554 return mNetworkChangeLatch.await(DEFAULT_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); 555 } 556 awaitStopped()557 public boolean awaitStopped() throws InterruptedException { 558 return mStoppedLatch.await(DEFAULT_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); 559 } 560 notifyExecution(MockJobService jobService, JobParameters params, int permCheckRead, int permCheckWrite, ArrayList<JobWorkItem> receivedWork, String errorMsg)561 private void notifyExecution(MockJobService jobService, JobParameters params, 562 int permCheckRead, int permCheckWrite, 563 ArrayList<JobWorkItem> receivedWork, String errorMsg) { 564 mExecutedJobService = jobService; 565 mExecutedJobParameters = params; 566 mExecutedPermCheckRead = permCheckRead; 567 mExecutedPermCheckWrite = permCheckWrite; 568 mExecutedReceivedWork = receivedWork; 569 mExecutedErrorMessage = errorMsg; 570 if (mLatch != null) { 571 mLatch.countDown(); 572 } 573 } 574 notifyNetworkChanged(JobParameters params)575 private void notifyNetworkChanged(JobParameters params) { 576 mNetworkChangedJobParameters = params; 577 if (mNetworkChangeLatch != null) { 578 mNetworkChangeLatch.countDown(); 579 } 580 } 581 notifyWaitingForStop()582 private void notifyWaitingForStop() { 583 mWaitingForStopLatch.countDown(); 584 } 585 notifyStopped(JobParameters params)586 private void notifyStopped(JobParameters params) { 587 mStopJobParameters = params; 588 if (mStoppedLatch != null) { 589 mStoppedLatch.countDown(); 590 } 591 } 592 setEstimatedNetworkBytes(long downloadBytes, long uploadBytes)593 public void setEstimatedNetworkBytes(long downloadBytes, long uploadBytes) { 594 mExecutedJobService.setEstimatedNetworkBytesForTest(downloadBytes, uploadBytes); 595 } 596 setTransferredNetworkBytes(long downloadBytes, long uploadBytes)597 public void setTransferredNetworkBytes(long downloadBytes, long uploadBytes) { 598 mExecutedJobService.setTransferredBytesForTest(downloadBytes, uploadBytes); 599 } 600 setExpectedExecutions(int numExecutions)601 public void setExpectedExecutions(int numExecutions) { 602 // For no executions expected, set count to 1 so we can still block for the timeout. 603 if (numExecutions == 0) { 604 mLatch = new CountDownLatch(1); 605 } else { 606 mLatch = new CountDownLatch(numExecutions); 607 } 608 mWaitingForStopLatch = null; 609 mDoJobLatch = null; 610 mStoppedLatch = null; 611 mDoWorkLatch = null; 612 mNetworkChangeLatch = null; 613 mExpectedWork = null; 614 mContinueAfterStart = false; 615 mRequestReschedule = false; 616 mExecutedEvents.clear(); 617 mJobStartNotification = null; 618 } 619 setExpectedWaitForStop()620 public void setExpectedWaitForStop() { 621 mWaitingForStopLatch = new CountDownLatch(1); 622 } 623 setExpectedWork(TestWorkItem[] work)624 public void setExpectedWork(TestWorkItem[] work) { 625 mExpectedWork = work; 626 mDoWorkLatch = new CountDownLatch(1); 627 } 628 setExpectedStopped()629 public void setExpectedStopped() { 630 mStoppedLatch = new CountDownLatch(1); 631 } 632 setExpectedNetworkChange()633 public void setExpectedNetworkChange() { 634 mNetworkChangeLatch = new CountDownLatch(1); 635 } 636 setNotificationAtStart(int notificationId, @NonNull Notification notification, @JobEndNotificationPolicy int jobEndNotificationPolicy)637 public void setNotificationAtStart(int notificationId, 638 @NonNull Notification notification, 639 @JobEndNotificationPolicy int jobEndNotificationPolicy) { 640 mJobStartNotificationId = notificationId; 641 mJobStartNotification = notification; 642 mJobStartNotificationEndPolicy = jobEndNotificationPolicy; 643 } 644 readyToWork()645 public void readyToWork() { 646 mDoWorkLatch.countDown(); 647 } 648 setExpectedWaitForRun()649 public void setExpectedWaitForRun() { 650 mDoJobLatch = new CountDownLatch(1); 651 } 652 readyToRun()653 public void readyToRun() { 654 mDoJobLatch.countDown(); 655 } 656 setContinueAfterStart()657 public void setContinueAfterStart() { 658 mContinueAfterStart = true; 659 } 660 handleContinueAfterStart()661 public boolean handleContinueAfterStart() { 662 boolean res = mContinueAfterStart; 663 mContinueAfterStart = false; 664 return res; 665 } 666 setRequestReschedule()667 public void setRequestReschedule() { 668 mRequestReschedule = true; 669 } 670 requestReschedule()671 boolean requestReschedule() { 672 return mRequestReschedule; 673 } 674 675 /** Called in each testCase#setup */ setUp()676 public void setUp() { 677 mLatch = null; 678 mExecutedJobParameters = null; 679 mExecutedJobService = null; 680 mStopJobParameters = null; 681 } 682 addEvent(Event event)683 void addEvent(Event event) { 684 mExecutedEvents.add(event); 685 } 686 getExecutedEvents()687 public List<Event> getExecutedEvents() { 688 return mExecutedEvents; 689 } 690 691 public static class Event { 692 public static final int EVENT_START_JOB = 0; 693 694 public int event; 695 public int jobId; 696 Event(int event, int jobId)697 public Event(int event, int jobId) { 698 this.event = event; 699 this.jobId = jobId; 700 } 701 702 @Override equals(Object other)703 public boolean equals(Object other) { 704 if (this == other) { 705 return true; 706 } 707 if (other instanceof Event) { 708 Event otherEvent = (Event) other; 709 return otherEvent.event == event && otherEvent.jobId == jobId; 710 } 711 return false; 712 } 713 714 @Override hashCode()715 public int hashCode() { 716 return event + 31 * jobId; 717 } 718 719 @Override toString()720 public String toString() { 721 return "Event{" + event + ", " + jobId + "}"; 722 } 723 } 724 } 725 } 726