101ac45b6ff2334925c8d24b5278b44e5e30f5622Matthew Williamspackage com.android.server.job;
23d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams
33d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams
43d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williamsimport android.content.ComponentName;
53d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williamsimport android.content.Context;
67060b04f6d92351b67222e636ab378a0273bf3e7Christopher Tateimport android.app.job.JobInfo;
77060b04f6d92351b67222e636ab378a0273bf3e7Christopher Tateimport android.app.job.JobInfo.Builder;
83d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williamsimport android.os.PersistableBundle;
9fa8e5084eed63ab8d92c71fcff656690a30293c3Matthew Williamsimport android.os.SystemClock;
103d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williamsimport android.test.AndroidTestCase;
113d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williamsimport android.test.RenamingDelegatingContext;
123d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williamsimport android.util.Log;
133d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams
142f36fd6fc94b62b8ccd03cdcea89826d05414f93Christopher Tateimport com.android.server.job.JobStore.JobSet;
157060b04f6d92351b67222e636ab378a0273bf3e7Christopher Tateimport com.android.server.job.controllers.JobStatus;
163d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams
1701ac45b6ff2334925c8d24b5278b44e5e30f5622Matthew Williamsimport java.util.Iterator;
183d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams
193d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams/**
203d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams * Test reading and writing correctly from file.
213d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams */
2201ac45b6ff2334925c8d24b5278b44e5e30f5622Matthew Williamspublic class JobStoreTest extends AndroidTestCase {
233d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams    private static final String TAG = "TaskStoreTest";
243d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams    private static final String TEST_PREFIX = "_test_";
2501ac45b6ff2334925c8d24b5278b44e5e30f5622Matthew Williams
263d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams    private static final int SOME_UID = 34234;
273d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams    private ComponentName mComponent;
2801ac45b6ff2334925c8d24b5278b44e5e30f5622Matthew Williams    private static final long IO_WAIT = 1000L;
293d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams
307060b04f6d92351b67222e636ab378a0273bf3e7Christopher Tate    JobStore mTaskStoreUnderTest;
313d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams    Context mTestContext;
323d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams
333d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams    @Override
343d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams    public void setUp() throws Exception {
353d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams        mTestContext = new RenamingDelegatingContext(getContext(), TEST_PREFIX);
363d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams        Log.d(TAG, "Saving tasks to '" + mTestContext.getFilesDir() + "'");
3701ac45b6ff2334925c8d24b5278b44e5e30f5622Matthew Williams        mTaskStoreUnderTest =
3801ac45b6ff2334925c8d24b5278b44e5e30f5622Matthew Williams                JobStore.initAndGetForTesting(mTestContext, mTestContext.getFilesDir());
393d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams        mComponent = new ComponentName(getContext().getPackageName(), StubClass.class.getName());
403d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams    }
413d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams
423d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams    @Override
433d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams    public void tearDown() throws Exception {
443d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams        mTaskStoreUnderTest.clear();
453d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams    }
463d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams
473d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams    public void testMaybeWriteStatusToDisk() throws Exception {
483d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams        int taskId = 5;
493d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams        long runByMillis = 20000L; // 20s
503d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams        long runFromMillis = 2000L; // 2s
513d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams        long initialBackoff = 10000L; // 10s
523d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams
537060b04f6d92351b67222e636ab378a0273bf3e7Christopher Tate        final JobInfo task = new Builder(taskId, mComponent)
543d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams                .setRequiresCharging(true)
55d1c06753d045ad10e00e7aba53ee2adba0712cccMatthew Williams                .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
56d1c06753d045ad10e00e7aba53ee2adba0712cccMatthew Williams                .setBackoffCriteria(initialBackoff, JobInfo.BACKOFF_POLICY_EXPONENTIAL)
573d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams                .setOverrideDeadline(runByMillis)
583d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams                .setMinimumLatency(runFromMillis)
59d1c06753d045ad10e00e7aba53ee2adba0712cccMatthew Williams                .setPersisted(true)
603d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams                .build();
611085ff6ee531931ef7f55cbadbc83616f619b292Dianne Hackborn        final JobStatus ts = JobStatus.createFromJobInfo(task, SOME_UID, null, -1, null);
623d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams        mTaskStoreUnderTest.add(ts);
633d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams        Thread.sleep(IO_WAIT);
643d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams        // Manually load tasks from xml file.
652f36fd6fc94b62b8ccd03cdcea89826d05414f93Christopher Tate        final JobSet jobStatusSet = new JobSet();
6601ac45b6ff2334925c8d24b5278b44e5e30f5622Matthew Williams        mTaskStoreUnderTest.readJobMapFromDisk(jobStatusSet);
6701ac45b6ff2334925c8d24b5278b44e5e30f5622Matthew Williams
6801ac45b6ff2334925c8d24b5278b44e5e30f5622Matthew Williams        assertEquals("Didn't get expected number of persisted tasks.", 1, jobStatusSet.size());
692f36fd6fc94b62b8ccd03cdcea89826d05414f93Christopher Tate        final JobStatus loadedTaskStatus = jobStatusSet.getAllJobs().get(0);
7001ac45b6ff2334925c8d24b5278b44e5e30f5622Matthew Williams        assertTasksEqual(task, loadedTaskStatus.getJob());
7148a30db75dd0eedf8e065c89825b2af86a381b62Matthew Williams        assertTrue("JobStore#contains invalid.", mTaskStoreUnderTest.containsJob(ts));
7201ac45b6ff2334925c8d24b5278b44e5e30f5622Matthew Williams        assertEquals("Different uids.", SOME_UID, loadedTaskStatus.getUid());
7301ac45b6ff2334925c8d24b5278b44e5e30f5622Matthew Williams        compareTimestampsSubjectToIoLatency("Early run-times not the same after read.",
7401ac45b6ff2334925c8d24b5278b44e5e30f5622Matthew Williams                ts.getEarliestRunTime(), loadedTaskStatus.getEarliestRunTime());
7501ac45b6ff2334925c8d24b5278b44e5e30f5622Matthew Williams        compareTimestampsSubjectToIoLatency("Late run-times not the same after read.",
7601ac45b6ff2334925c8d24b5278b44e5e30f5622Matthew Williams                ts.getLatestRunTimeElapsed(), loadedTaskStatus.getLatestRunTimeElapsed());
773d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams
783d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams    }
793d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams
803d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams    public void testWritingTwoFilesToDisk() throws Exception {
817060b04f6d92351b67222e636ab378a0273bf3e7Christopher Tate        final JobInfo task1 = new Builder(8, mComponent)
823d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams                .setRequiresDeviceIdle(true)
833d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams                .setPeriodic(10000L)
843d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams                .setRequiresCharging(true)
85d1c06753d045ad10e00e7aba53ee2adba0712cccMatthew Williams                .setPersisted(true)
863d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams                .build();
877060b04f6d92351b67222e636ab378a0273bf3e7Christopher Tate        final JobInfo task2 = new Builder(12, mComponent)
883d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams                .setMinimumLatency(5000L)
89d1c06753d045ad10e00e7aba53ee2adba0712cccMatthew Williams                .setBackoffCriteria(15000L, JobInfo.BACKOFF_POLICY_LINEAR)
903d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams                .setOverrideDeadline(30000L)
91d1c06753d045ad10e00e7aba53ee2adba0712cccMatthew Williams                .setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
92d1c06753d045ad10e00e7aba53ee2adba0712cccMatthew Williams                .setPersisted(true)
933d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams                .build();
941085ff6ee531931ef7f55cbadbc83616f619b292Dianne Hackborn        final JobStatus taskStatus1 = JobStatus.createFromJobInfo(task1, SOME_UID, null, -1, null);
951085ff6ee531931ef7f55cbadbc83616f619b292Dianne Hackborn        final JobStatus taskStatus2 = JobStatus.createFromJobInfo(task2, SOME_UID, null, -1, null);
963d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams        mTaskStoreUnderTest.add(taskStatus1);
973d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams        mTaskStoreUnderTest.add(taskStatus2);
983d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams        Thread.sleep(IO_WAIT);
9901ac45b6ff2334925c8d24b5278b44e5e30f5622Matthew Williams
1002f36fd6fc94b62b8ccd03cdcea89826d05414f93Christopher Tate        final JobSet jobStatusSet = new JobSet();
10101ac45b6ff2334925c8d24b5278b44e5e30f5622Matthew Williams        mTaskStoreUnderTest.readJobMapFromDisk(jobStatusSet);
10201ac45b6ff2334925c8d24b5278b44e5e30f5622Matthew Williams        assertEquals("Incorrect # of persisted tasks.", 2, jobStatusSet.size());
1032f36fd6fc94b62b8ccd03cdcea89826d05414f93Christopher Tate        Iterator<JobStatus> it = jobStatusSet.getAllJobs().iterator();
10401ac45b6ff2334925c8d24b5278b44e5e30f5622Matthew Williams        JobStatus loaded1 = it.next();
10501ac45b6ff2334925c8d24b5278b44e5e30f5622Matthew Williams        JobStatus loaded2 = it.next();
106fa8e5084eed63ab8d92c71fcff656690a30293c3Matthew Williams
107fa8e5084eed63ab8d92c71fcff656690a30293c3Matthew Williams        // Reverse them so we know which comparison to make.
108fa8e5084eed63ab8d92c71fcff656690a30293c3Matthew Williams        if (loaded1.getJobId() != 8) {
109fa8e5084eed63ab8d92c71fcff656690a30293c3Matthew Williams            JobStatus tmp = loaded1;
110fa8e5084eed63ab8d92c71fcff656690a30293c3Matthew Williams            loaded1 = loaded2;
111fa8e5084eed63ab8d92c71fcff656690a30293c3Matthew Williams            loaded2 = tmp;
112fa8e5084eed63ab8d92c71fcff656690a30293c3Matthew Williams        }
113fa8e5084eed63ab8d92c71fcff656690a30293c3Matthew Williams
11401ac45b6ff2334925c8d24b5278b44e5e30f5622Matthew Williams        assertTasksEqual(task1, loaded1.getJob());
11501ac45b6ff2334925c8d24b5278b44e5e30f5622Matthew Williams        assertTasksEqual(task2, loaded2.getJob());
11648a30db75dd0eedf8e065c89825b2af86a381b62Matthew Williams        assertTrue("JobStore#contains invalid.", mTaskStoreUnderTest.containsJob(taskStatus1));
11748a30db75dd0eedf8e065c89825b2af86a381b62Matthew Williams        assertTrue("JobStore#contains invalid.", mTaskStoreUnderTest.containsJob(taskStatus2));
11801ac45b6ff2334925c8d24b5278b44e5e30f5622Matthew Williams        // Check that the loaded task has the correct runtimes.
11901ac45b6ff2334925c8d24b5278b44e5e30f5622Matthew Williams        compareTimestampsSubjectToIoLatency("Early run-times not the same after read.",
12001ac45b6ff2334925c8d24b5278b44e5e30f5622Matthew Williams                taskStatus1.getEarliestRunTime(), loaded1.getEarliestRunTime());
12101ac45b6ff2334925c8d24b5278b44e5e30f5622Matthew Williams        compareTimestampsSubjectToIoLatency("Late run-times not the same after read.",
12201ac45b6ff2334925c8d24b5278b44e5e30f5622Matthew Williams                taskStatus1.getLatestRunTimeElapsed(), loaded1.getLatestRunTimeElapsed());
12301ac45b6ff2334925c8d24b5278b44e5e30f5622Matthew Williams        compareTimestampsSubjectToIoLatency("Early run-times not the same after read.",
12401ac45b6ff2334925c8d24b5278b44e5e30f5622Matthew Williams                taskStatus2.getEarliestRunTime(), loaded2.getEarliestRunTime());
12501ac45b6ff2334925c8d24b5278b44e5e30f5622Matthew Williams        compareTimestampsSubjectToIoLatency("Late run-times not the same after read.",
12601ac45b6ff2334925c8d24b5278b44e5e30f5622Matthew Williams                taskStatus2.getLatestRunTimeElapsed(), loaded2.getLatestRunTimeElapsed());
1273d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams
1283d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams    }
1293d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams
1303d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams    public void testWritingTaskWithExtras() throws Exception {
1317060b04f6d92351b67222e636ab378a0273bf3e7Christopher Tate        JobInfo.Builder b = new Builder(8, mComponent)
1323d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams                .setRequiresDeviceIdle(true)
1333d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams                .setPeriodic(10000L)
134900c67fc51fc2672458dd1c9641250f2ecc01a31Matthew Williams                .setRequiresCharging(true)
135d1c06753d045ad10e00e7aba53ee2adba0712cccMatthew Williams                .setPersisted(true);
1363d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams
1373d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams        PersistableBundle extras = new PersistableBundle();
1383d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams        extras.putDouble("hello", 3.2);
1393d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams        extras.putString("hi", "there");
1403d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams        extras.putInt("into", 3);
1413d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams        b.setExtras(extras);
1427060b04f6d92351b67222e636ab378a0273bf3e7Christopher Tate        final JobInfo task = b.build();
1431085ff6ee531931ef7f55cbadbc83616f619b292Dianne Hackborn        JobStatus taskStatus = JobStatus.createFromJobInfo(task, SOME_UID, null, -1, null);
1443d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams
1453d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams        mTaskStoreUnderTest.add(taskStatus);
1463d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams        Thread.sleep(IO_WAIT);
1473d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams
1482f36fd6fc94b62b8ccd03cdcea89826d05414f93Christopher Tate        final JobSet jobStatusSet = new JobSet();
14901ac45b6ff2334925c8d24b5278b44e5e30f5622Matthew Williams        mTaskStoreUnderTest.readJobMapFromDisk(jobStatusSet);
15001ac45b6ff2334925c8d24b5278b44e5e30f5622Matthew Williams        assertEquals("Incorrect # of persisted tasks.", 1, jobStatusSet.size());
1512f36fd6fc94b62b8ccd03cdcea89826d05414f93Christopher Tate        JobStatus loaded = jobStatusSet.getAllJobs().iterator().next();
15201ac45b6ff2334925c8d24b5278b44e5e30f5622Matthew Williams        assertTasksEqual(task, loaded.getJob());
1533d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams    }
1548e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge    public void testWritingTaskWithSourcePackage() throws Exception {
1558e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge        JobInfo.Builder b = new Builder(8, mComponent)
1568e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge                .setRequiresDeviceIdle(true)
1578e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge                .setPeriodic(10000L)
1588e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge                .setRequiresCharging(true)
1598e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge                .setPersisted(true);
160b0001f6fb1383d9824c2733896b0b348e7f77240Dianne Hackborn        JobStatus taskStatus = JobStatus.createFromJobInfo(b.build(), SOME_UID,
1611085ff6ee531931ef7f55cbadbc83616f619b292Dianne Hackborn                "com.google.android.gms", 0, null);
1628e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge
1638e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge        mTaskStoreUnderTest.add(taskStatus);
1648e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge        Thread.sleep(IO_WAIT);
1658e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge
1662f36fd6fc94b62b8ccd03cdcea89826d05414f93Christopher Tate        final JobSet jobStatusSet = new JobSet();
1678e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge        mTaskStoreUnderTest.readJobMapFromDisk(jobStatusSet);
1688e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge        assertEquals("Incorrect # of persisted tasks.", 1, jobStatusSet.size());
1692f36fd6fc94b62b8ccd03cdcea89826d05414f93Christopher Tate        JobStatus loaded = jobStatusSet.getAllJobs().iterator().next();
1708e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge        assertEquals("Source package not equal.", loaded.getSourcePackageName(),
1718e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge                taskStatus.getSourcePackageName());
1728e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge        assertEquals("Source user not equal.", loaded.getSourceUserId(),
1738e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge                taskStatus.getSourceUserId());
1748e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge    }
1758e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge
1768e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge    public void testWritingTaskWithFlex() throws Exception {
1778e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge        JobInfo.Builder b = new Builder(8, mComponent)
1788e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge                .setRequiresDeviceIdle(true)
1798e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge                .setPeriodic(5*60*60*1000, 1*60*60*1000)
1808e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge                .setRequiresCharging(true)
1818e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge                .setPersisted(true);
1821085ff6ee531931ef7f55cbadbc83616f619b292Dianne Hackborn        JobStatus taskStatus = JobStatus.createFromJobInfo(b.build(), SOME_UID, null, -1, null);
1838e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge
1848e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge        mTaskStoreUnderTest.add(taskStatus);
1858e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge        Thread.sleep(IO_WAIT);
1868e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge
1872f36fd6fc94b62b8ccd03cdcea89826d05414f93Christopher Tate        final JobSet jobStatusSet = new JobSet();
1888e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge        mTaskStoreUnderTest.readJobMapFromDisk(jobStatusSet);
1898e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge        assertEquals("Incorrect # of persisted tasks.", 1, jobStatusSet.size());
1902f36fd6fc94b62b8ccd03cdcea89826d05414f93Christopher Tate        JobStatus loaded = jobStatusSet.getAllJobs().iterator().next();
1918e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge        assertEquals("Period not equal.", loaded.getJob().getIntervalMillis(),
1928e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge                taskStatus.getJob().getIntervalMillis());
1938e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge        assertEquals("Flex not equal.", loaded.getJob().getFlexMillis(),
1948e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge                taskStatus.getJob().getFlexMillis());
1958e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge    }
1963d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams
197fa8e5084eed63ab8d92c71fcff656690a30293c3Matthew Williams    public void testMassivePeriodClampedOnRead() throws Exception {
1988e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge        final long ONE_HOUR = 60*60*1000L; // flex
1998e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge        final long TWO_HOURS = 2 * ONE_HOUR; // period
200fa8e5084eed63ab8d92c71fcff656690a30293c3Matthew Williams        JobInfo.Builder b = new Builder(8, mComponent)
2018e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge                .setPeriodic(TWO_HOURS, ONE_HOUR)
202fa8e5084eed63ab8d92c71fcff656690a30293c3Matthew Williams                .setPersisted(true);
203fa8e5084eed63ab8d92c71fcff656690a30293c3Matthew Williams        final long invalidLateRuntimeElapsedMillis =
2048e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge                SystemClock.elapsedRealtime() + (TWO_HOURS * ONE_HOUR) + TWO_HOURS;  // > period+flex
205fa8e5084eed63ab8d92c71fcff656690a30293c3Matthew Williams        final long invalidEarlyRuntimeElapsedMillis =
2068e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge                invalidLateRuntimeElapsedMillis - TWO_HOURS;  // Early is (late - period).
207b0001f6fb1383d9824c2733896b0b348e7f77240Dianne Hackborn        final JobStatus js = new JobStatus(b.build(), SOME_UID, "somePackage",
2081085ff6ee531931ef7f55cbadbc83616f619b292Dianne Hackborn                0 /* sourceUserId */, "someTag",
209fa8e5084eed63ab8d92c71fcff656690a30293c3Matthew Williams                invalidEarlyRuntimeElapsedMillis, invalidLateRuntimeElapsedMillis);
210fa8e5084eed63ab8d92c71fcff656690a30293c3Matthew Williams
211fa8e5084eed63ab8d92c71fcff656690a30293c3Matthew Williams        mTaskStoreUnderTest.add(js);
212fa8e5084eed63ab8d92c71fcff656690a30293c3Matthew Williams        Thread.sleep(IO_WAIT);
213fa8e5084eed63ab8d92c71fcff656690a30293c3Matthew Williams
2142f36fd6fc94b62b8ccd03cdcea89826d05414f93Christopher Tate        final JobSet jobStatusSet = new JobSet();
215fa8e5084eed63ab8d92c71fcff656690a30293c3Matthew Williams        mTaskStoreUnderTest.readJobMapFromDisk(jobStatusSet);
216fa8e5084eed63ab8d92c71fcff656690a30293c3Matthew Williams        assertEquals("Incorrect # of persisted tasks.", 1, jobStatusSet.size());
2172f36fd6fc94b62b8ccd03cdcea89826d05414f93Christopher Tate        JobStatus loaded = jobStatusSet.getAllJobs().iterator().next();
218fa8e5084eed63ab8d92c71fcff656690a30293c3Matthew Williams
219fa8e5084eed63ab8d92c71fcff656690a30293c3Matthew Williams        // Assert early runtime was clamped to be under now + period. We can do <= here b/c we'll
220fa8e5084eed63ab8d92c71fcff656690a30293c3Matthew Williams        // call SystemClock.elapsedRealtime after doing the disk i/o.
221fa8e5084eed63ab8d92c71fcff656690a30293c3Matthew Williams        final long newNowElapsed = SystemClock.elapsedRealtime();
222fa8e5084eed63ab8d92c71fcff656690a30293c3Matthew Williams        assertTrue("Early runtime wasn't correctly clamped.",
2238e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge                loaded.getEarliestRunTime() <= newNowElapsed + TWO_HOURS);
2248e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge        // Assert late runtime was clamped to be now + period + flex.
225fa8e5084eed63ab8d92c71fcff656690a30293c3Matthew Williams        assertTrue("Early runtime wasn't correctly clamped.",
2268e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge                loaded.getEarliestRunTime() <= newNowElapsed + TWO_HOURS + ONE_HOUR);
2275db09084c8e4efc6311754243c39962fc8e7a766Shreyas Basarge    }
2285db09084c8e4efc6311754243c39962fc8e7a766Shreyas Basarge
2295db09084c8e4efc6311754243c39962fc8e7a766Shreyas Basarge    public void testPriorityPersisted() throws Exception {
2305db09084c8e4efc6311754243c39962fc8e7a766Shreyas Basarge        JobInfo.Builder b = new Builder(92, mComponent)
2315db09084c8e4efc6311754243c39962fc8e7a766Shreyas Basarge                .setOverrideDeadline(5000)
2325db09084c8e4efc6311754243c39962fc8e7a766Shreyas Basarge                .setPriority(42)
2335db09084c8e4efc6311754243c39962fc8e7a766Shreyas Basarge                .setPersisted(true);
2341085ff6ee531931ef7f55cbadbc83616f619b292Dianne Hackborn        final JobStatus js = JobStatus.createFromJobInfo(b.build(), SOME_UID, null, -1, null);
2355db09084c8e4efc6311754243c39962fc8e7a766Shreyas Basarge        mTaskStoreUnderTest.add(js);
2365db09084c8e4efc6311754243c39962fc8e7a766Shreyas Basarge        Thread.sleep(IO_WAIT);
2372f36fd6fc94b62b8ccd03cdcea89826d05414f93Christopher Tate        final JobSet jobStatusSet = new JobSet();
2385db09084c8e4efc6311754243c39962fc8e7a766Shreyas Basarge        mTaskStoreUnderTest.readJobMapFromDisk(jobStatusSet);
2392f36fd6fc94b62b8ccd03cdcea89826d05414f93Christopher Tate        JobStatus loaded = jobStatusSet.getAllJobs().iterator().next();
2405db09084c8e4efc6311754243c39962fc8e7a766Shreyas Basarge        assertEquals("Priority not correctly persisted.", 42, loaded.getPriority());
241fa8e5084eed63ab8d92c71fcff656690a30293c3Matthew Williams    }
242fa8e5084eed63ab8d92c71fcff656690a30293c3Matthew Williams
2433d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams    /**
2447ef490fab68ee93f92eb5728cc4d3cb691315412Shreyas Basarge     * Test that non persisted job is not written to disk.
2457ef490fab68ee93f92eb5728cc4d3cb691315412Shreyas Basarge     */
2467ef490fab68ee93f92eb5728cc4d3cb691315412Shreyas Basarge    public void testNonPersistedTaskIsNotPersisted() throws Exception {
2477ef490fab68ee93f92eb5728cc4d3cb691315412Shreyas Basarge        JobInfo.Builder b = new Builder(42, mComponent)
2487ef490fab68ee93f92eb5728cc4d3cb691315412Shreyas Basarge                .setOverrideDeadline(10000)
2497ef490fab68ee93f92eb5728cc4d3cb691315412Shreyas Basarge                .setPersisted(false);
2501085ff6ee531931ef7f55cbadbc83616f619b292Dianne Hackborn        JobStatus jsNonPersisted = JobStatus.createFromJobInfo(b.build(), SOME_UID, null, -1, null);
2517ef490fab68ee93f92eb5728cc4d3cb691315412Shreyas Basarge        mTaskStoreUnderTest.add(jsNonPersisted);
2527ef490fab68ee93f92eb5728cc4d3cb691315412Shreyas Basarge        b = new Builder(43, mComponent)
2537ef490fab68ee93f92eb5728cc4d3cb691315412Shreyas Basarge                .setOverrideDeadline(10000)
2547ef490fab68ee93f92eb5728cc4d3cb691315412Shreyas Basarge                .setPersisted(true);
2551085ff6ee531931ef7f55cbadbc83616f619b292Dianne Hackborn        JobStatus jsPersisted = JobStatus.createFromJobInfo(b.build(), SOME_UID, null, -1, null);
2567ef490fab68ee93f92eb5728cc4d3cb691315412Shreyas Basarge        mTaskStoreUnderTest.add(jsPersisted);
2577ef490fab68ee93f92eb5728cc4d3cb691315412Shreyas Basarge        Thread.sleep(IO_WAIT);
2582f36fd6fc94b62b8ccd03cdcea89826d05414f93Christopher Tate        final JobSet jobStatusSet = new JobSet();
2597ef490fab68ee93f92eb5728cc4d3cb691315412Shreyas Basarge        mTaskStoreUnderTest.readJobMapFromDisk(jobStatusSet);
2607ef490fab68ee93f92eb5728cc4d3cb691315412Shreyas Basarge        assertEquals("Job count is incorrect.", 1, jobStatusSet.size());
2612f36fd6fc94b62b8ccd03cdcea89826d05414f93Christopher Tate        JobStatus jobStatus = jobStatusSet.getAllJobs().iterator().next();
2627ef490fab68ee93f92eb5728cc4d3cb691315412Shreyas Basarge        assertEquals("Wrong job persisted.", 43, jobStatus.getJobId());
2637ef490fab68ee93f92eb5728cc4d3cb691315412Shreyas Basarge    }
2647ef490fab68ee93f92eb5728cc4d3cb691315412Shreyas Basarge
2657ef490fab68ee93f92eb5728cc4d3cb691315412Shreyas Basarge    /**
2663d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams     * Helper function to throw an error if the provided task and TaskStatus objects are not equal.
2673d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams     */
2687060b04f6d92351b67222e636ab378a0273bf3e7Christopher Tate    private void assertTasksEqual(JobInfo first, JobInfo second) {
2693d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams        assertEquals("Different task ids.", first.getId(), second.getId());
2703d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams        assertEquals("Different components.", first.getService(), second.getService());
2713d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams        assertEquals("Different periodic status.", first.isPeriodic(), second.isPeriodic());
2723d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams        assertEquals("Different period.", first.getIntervalMillis(), second.getIntervalMillis());
2733d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams        assertEquals("Different inital backoff.", first.getInitialBackoffMillis(),
2743d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams                second.getInitialBackoffMillis());
2753d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams        assertEquals("Different backoff policy.", first.getBackoffPolicy(),
2763d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams                second.getBackoffPolicy());
2773d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams
2783d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams        assertEquals("Invalid charging constraint.", first.isRequireCharging(),
2793d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams                second.isRequireCharging());
280a06ec6a9435f9555142e700f54cf20278bc1982fDianne Hackborn        assertEquals("Invalid battery not low constraint.", first.isRequireBatteryNotLow(),
281a06ec6a9435f9555142e700f54cf20278bc1982fDianne Hackborn                second.isRequireBatteryNotLow());
2823d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams        assertEquals("Invalid idle constraint.", first.isRequireDeviceIdle(),
2833d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams                second.isRequireDeviceIdle());
2843d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams        assertEquals("Invalid unmetered constraint.",
285d1c06753d045ad10e00e7aba53ee2adba0712cccMatthew Williams                first.getNetworkType() == JobInfo.NETWORK_TYPE_UNMETERED,
286d1c06753d045ad10e00e7aba53ee2adba0712cccMatthew Williams                second.getNetworkType() == JobInfo.NETWORK_TYPE_UNMETERED);
2873d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams        assertEquals("Invalid connectivity constraint.",
288d1c06753d045ad10e00e7aba53ee2adba0712cccMatthew Williams                first.getNetworkType() == JobInfo.NETWORK_TYPE_ANY,
289d1c06753d045ad10e00e7aba53ee2adba0712cccMatthew Williams                second.getNetworkType() == JobInfo.NETWORK_TYPE_ANY);
2903d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams        assertEquals("Invalid deadline constraint.",
2913d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams                first.hasLateConstraint(),
2923d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams                second.hasLateConstraint());
2933d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams        assertEquals("Invalid delay constraint.",
2943d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams                first.hasEarlyConstraint(),
2953d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams                second.hasEarlyConstraint());
2963d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams        assertEquals("Extras don't match",
2973d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams                first.getExtras().toString(), second.getExtras().toString());
298ba60473a6539d16bef8720d79b5559512303bddfDianne Hackborn        assertEquals("Transient xtras don't match",
299ba60473a6539d16bef8720d79b5559512303bddfDianne Hackborn                first.getTransientExtras().toString(), second.getTransientExtras().toString());
3003d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams    }
3013d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams
3023d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams    /**
3033d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams     * When comparing timestamps before and after DB read/writes (to make sure we're saving/loading
3043d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams     * the correct values), there is some latency involved that terrorises a naive assertEquals().
3053d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams     * We define a <code>DELTA_MILLIS</code> as a function variable here to make this comparision
3063d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams     * more reasonable.
3073d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams     */
3083d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams    private void compareTimestampsSubjectToIoLatency(String error, long ts1, long ts2) {
3093d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams        final long DELTA_MILLIS = 700L;  // We allow up to 700ms of latency for IO read/writes.
3103d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams        assertTrue(error, Math.abs(ts1 - ts2) < DELTA_MILLIS + IO_WAIT);
3113d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams    }
3123d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams
3133d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams    private static class StubClass {}
3143d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams
31501ac45b6ff2334925c8d24b5278b44e5e30f5622Matthew Williams}
316