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