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