| /* |
| * Copyright (C) 2017 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package android.jobscheduler.cts; |
| |
| import android.annotation.TargetApi; |
| import android.app.job.JobInfo; |
| import android.app.job.JobWorkItem; |
| import android.content.ContentProviderClient; |
| import android.content.Intent; |
| import android.jobscheduler.MockJobService.TestWorkItem; |
| import android.net.Uri; |
| |
| import java.util.ArrayList; |
| |
| /** |
| * Schedules jobs with the {@link android.app.job.JobScheduler} by enqueue work in to |
| * them and processing it. |
| */ |
| @TargetApi(26) |
| public class EnqueueJobWorkTest extends ConstraintTest { |
| private static final String TAG = "ClipDataJobTest"; |
| |
| /** Unique identifier for the job scheduled by this suite of tests. */ |
| public static final int ENQUEUE_WORK_JOB_ID = EnqueueJobWorkTest.class.hashCode(); |
| |
| private JobInfo.Builder mBuilder; |
| private ContentProviderClient mProvider; |
| |
| @Override |
| public void setUp() throws Exception { |
| super.setUp(); |
| |
| mBuilder = new JobInfo.Builder(ENQUEUE_WORK_JOB_ID, kJobServiceComponent); |
| mProvider = getContext().getContentResolver().acquireContentProviderClient(mFirstUri); |
| } |
| |
| @Override |
| public void tearDown() throws Exception { |
| super.tearDown(); |
| mProvider.close(); |
| mJobScheduler.cancel(ENQUEUE_WORK_JOB_ID); |
| } |
| |
| private boolean intentEquals(Intent i1, Intent i2) { |
| if (i1 == i2) { |
| return true; |
| } |
| if (i1 == null || i2 == null) { |
| return false; |
| } |
| return i1.filterEquals(i2); |
| } |
| |
| private void compareWork(TestWorkItem[] expected, ArrayList<Intent> received) { |
| if (received == null) { |
| fail("Didn't receive any expected work."); |
| } |
| ArrayList<TestWorkItem> expectedArray = new ArrayList<>(); |
| for (int i = 0; i < expected.length; i++) { |
| expectedArray.add(expected[i]); |
| } |
| for (int i = 0; i < received.size(); i++) { |
| Intent work = received.get(i); |
| if (i < expected.length && expected[i].subitems != null) { |
| TestWorkItem[] sub = expected[i].subitems; |
| for (int j = 0; j < sub.length; j++) { |
| expectedArray.add(sub[j]); |
| } |
| } |
| if (i >= expectedArray.size()) { |
| fail("Received more than " + expected.length + " work items, first extra is " |
| + work); |
| } |
| if (!intentEquals(work, expectedArray.get(i).intent)) { |
| fail("Received work #" + i + " " + work + " but expected " + expected[i]); |
| } |
| } |
| if (received.size() < expected.length) { |
| fail("Received only " + received.size() + " work items, but expected " |
| + expected.length); |
| } |
| } |
| |
| /** |
| * Test basic enqueueing of work. |
| */ |
| public void testEnqueueOneWork() throws Exception { |
| Intent work1 = new Intent("work1"); |
| TestWorkItem[] work = new TestWorkItem[] { new TestWorkItem(work1) }; |
| kTestEnvironment.setExpectedExecutions(1); |
| kTestEnvironment.setExpectedWork(work); |
| mJobScheduler.enqueue(mBuilder.setOverrideDeadline(0).build(), new JobWorkItem(work1)); |
| kTestEnvironment.readyToWork(); |
| assertTrue("Job with work enqueued did not fire.", |
| kTestEnvironment.awaitExecution()); |
| compareWork(work, kTestEnvironment.getLastReceivedWork()); |
| if (kTestEnvironment.getLastErrorMessage() != null) { |
| fail(kTestEnvironment.getLastErrorMessage()); |
| } |
| } |
| |
| /** |
| * Test basic enqueueing batches of work. |
| */ |
| public void testEnqueueMultipleWork() throws Exception { |
| Intent work1 = new Intent("work1"); |
| Intent work2 = new Intent("work2"); |
| Intent work3 = new Intent("work3"); |
| Intent work4 = new Intent("work4"); |
| Intent work5 = new Intent("work5"); |
| Intent work6 = new Intent("work6"); |
| Intent work7 = new Intent("work7"); |
| Intent work8 = new Intent("work8"); |
| TestWorkItem[] work = new TestWorkItem[] { |
| new TestWorkItem(work1), new TestWorkItem(work2), new TestWorkItem(work3), |
| new TestWorkItem(work4), new TestWorkItem(work5), new TestWorkItem(work6), |
| new TestWorkItem(work7), new TestWorkItem(work8) }; |
| kTestEnvironment.setExpectedExecutions(1); |
| kTestEnvironment.setExpectedWork(work); |
| JobInfo ji = mBuilder.setOverrideDeadline(0).build(); |
| mJobScheduler.enqueue(ji, new JobWorkItem(work1)); |
| mJobScheduler.enqueue(ji, new JobWorkItem(work2)); |
| mJobScheduler.enqueue(ji, new JobWorkItem(work3)); |
| mJobScheduler.enqueue(ji, new JobWorkItem(work4)); |
| mJobScheduler.enqueue(ji, new JobWorkItem(work5)); |
| mJobScheduler.enqueue(ji, new JobWorkItem(work6)); |
| mJobScheduler.enqueue(ji, new JobWorkItem(work7)); |
| mJobScheduler.enqueue(ji, new JobWorkItem(work8)); |
| kTestEnvironment.readyToWork(); |
| assertTrue("Job with work enqueued did not fire.", |
| kTestEnvironment.awaitExecution()); |
| compareWork(work, kTestEnvironment.getLastReceivedWork()); |
| } |
| |
| /** |
| * Test basic enqueueing batches of work, with new work coming in while processing existing |
| * work. |
| */ |
| public void testEnqueueMultipleSubWork() throws Exception { |
| Intent work1 = new Intent("work1"); |
| Intent work2 = new Intent("work2"); |
| Intent work3 = new Intent("work3"); |
| Intent work4 = new Intent("work4"); |
| Intent work5 = new Intent("work5"); |
| Intent work6 = new Intent("work6"); |
| Intent work7 = new Intent("work7"); |
| Intent work8 = new Intent("work8"); |
| JobInfo ji = mBuilder.setOverrideDeadline(0).build(); |
| TestWorkItem[] work = new TestWorkItem[]{ |
| new TestWorkItem(work1), new TestWorkItem(work2), new TestWorkItem(work3), |
| new TestWorkItem(work4, ji, new TestWorkItem[] { |
| new TestWorkItem(work5), new TestWorkItem(work6), |
| new TestWorkItem(work7), new TestWorkItem(work8)}) |
| }; |
| kTestEnvironment.setExpectedExecutions(1); |
| kTestEnvironment.setExpectedWork(work); |
| mJobScheduler.enqueue(ji, new JobWorkItem(work1)); |
| mJobScheduler.enqueue(ji, new JobWorkItem(work2)); |
| mJobScheduler.enqueue(ji, new JobWorkItem(work3)); |
| mJobScheduler.enqueue(ji, new JobWorkItem(work4)); |
| kTestEnvironment.readyToWork(); |
| assertTrue("Job with work enqueued did not fire.", |
| kTestEnvironment.awaitExecution()); |
| compareWork(work, kTestEnvironment.getLastReceivedWork()); |
| } |
| |
| /** |
| * Test basic enqueueing batches of work. |
| */ |
| public void testEnqueueMultipleUriGrantWork() throws Exception { |
| // Start out with storage low, so job is enqueued but not executed yet. |
| setStorageState(true); |
| |
| // We need to get a permission grant so that we can grant it to ourself. |
| mProvider.call("grant", MY_PACKAGE, mFirstUriBundle); |
| mProvider.call("grant", MY_PACKAGE, mSecondUriBundle); |
| assertHasUriPermission(mFirstUri, Intent.FLAG_GRANT_READ_URI_PERMISSION |
| | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); |
| assertHasUriPermission(mSecondUri, Intent.FLAG_GRANT_READ_URI_PERMISSION |
| | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); |
| |
| Intent work1 = new Intent("work1"); |
| work1.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION |
| | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); |
| work1.setData(mFirstUri); |
| work1.setClipData(mSecondClipData); |
| |
| Intent work2 = new Intent("work2"); |
| work2.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION |
| | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); |
| work2.setData(mFirstUri); |
| |
| TestWorkItem[] work = new TestWorkItem[] { |
| new TestWorkItem(work1, new Uri[] { mFirstUri, mSecondUri}, new Uri[0]), |
| new TestWorkItem(work2, new Uri[] { mFirstUri }, new Uri[] { mSecondUri}) }; |
| kTestEnvironment.setExpectedExecutions(1); |
| kTestEnvironment.setExpectedWork(work); |
| JobInfo ji = mBuilder.setOverrideDeadline(0).setRequiresStorageNotLow(true).build(); |
| mJobScheduler.enqueue(ji, new JobWorkItem(work1)); |
| mJobScheduler.enqueue(ji, new JobWorkItem(work2)); |
| |
| // Remove the explicit grant, we should still have a grant due to the job. |
| mProvider.call("revoke", MY_PACKAGE, mFirstUriBundle); |
| mProvider.call("revoke", MY_PACKAGE, mSecondUriBundle); |
| assertHasUriPermission(mFirstUri, Intent.FLAG_GRANT_READ_URI_PERMISSION |
| | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); |
| assertHasUriPermission(mSecondUri, Intent.FLAG_GRANT_READ_URI_PERMISSION |
| | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); |
| |
| kTestEnvironment.readyToWork(); |
| |
| // Now allow the job to run. |
| setStorageState(false); |
| |
| assertTrue("Job with work enqueued did not fire.", |
| kTestEnvironment.awaitExecution()); |
| compareWork(work, kTestEnvironment.getLastReceivedWork()); |
| |
| // And wait for everything to be cleaned up. |
| waitPermissionRevoke(mFirstUri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, 5000); |
| waitPermissionRevoke(mSecondUri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, 5000); |
| } |
| } |