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; 1301ac45b6ff2334925c8d24b5278b44e5e30f5622Matthew Williamsimport android.util.ArraySet; 143d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams 152f36fd6fc94b62b8ccd03cdcea89826d05414f93Christopher Tateimport com.android.server.job.JobStore.JobSet; 167060b04f6d92351b67222e636ab378a0273bf3e7Christopher Tateimport com.android.server.job.controllers.JobStatus; 173d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams 1801ac45b6ff2334925c8d24b5278b44e5e30f5622Matthew Williamsimport java.util.Iterator; 193d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams 203d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams/** 213d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams * Test reading and writing correctly from file. 223d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams */ 2301ac45b6ff2334925c8d24b5278b44e5e30f5622Matthew Williamspublic class JobStoreTest extends AndroidTestCase { 243d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams private static final String TAG = "TaskStoreTest"; 253d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams private static final String TEST_PREFIX = "_test_"; 2601ac45b6ff2334925c8d24b5278b44e5e30f5622Matthew Williams 273d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams private static final int SOME_UID = 34234; 283d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams private ComponentName mComponent; 2901ac45b6ff2334925c8d24b5278b44e5e30f5622Matthew Williams private static final long IO_WAIT = 1000L; 303d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams 317060b04f6d92351b67222e636ab378a0273bf3e7Christopher Tate JobStore mTaskStoreUnderTest; 323d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams Context mTestContext; 333d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams 343d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams @Override 353d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams public void setUp() throws Exception { 363d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams mTestContext = new RenamingDelegatingContext(getContext(), TEST_PREFIX); 373d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams Log.d(TAG, "Saving tasks to '" + mTestContext.getFilesDir() + "'"); 3801ac45b6ff2334925c8d24b5278b44e5e30f5622Matthew Williams mTaskStoreUnderTest = 3901ac45b6ff2334925c8d24b5278b44e5e30f5622Matthew Williams JobStore.initAndGetForTesting(mTestContext, mTestContext.getFilesDir()); 403d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams mComponent = new ComponentName(getContext().getPackageName(), StubClass.class.getName()); 413d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams } 423d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams 433d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams @Override 443d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams public void tearDown() throws Exception { 453d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams mTaskStoreUnderTest.clear(); 463d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams } 473d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams 483d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams public void testMaybeWriteStatusToDisk() throws Exception { 493d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams int taskId = 5; 503d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams long runByMillis = 20000L; // 20s 513d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams long runFromMillis = 2000L; // 2s 523d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams long initialBackoff = 10000L; // 10s 533d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams 547060b04f6d92351b67222e636ab378a0273bf3e7Christopher Tate final JobInfo task = new Builder(taskId, mComponent) 553d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams .setRequiresCharging(true) 56d1c06753d045ad10e00e7aba53ee2adba0712cccMatthew Williams .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY) 57d1c06753d045ad10e00e7aba53ee2adba0712cccMatthew Williams .setBackoffCriteria(initialBackoff, JobInfo.BACKOFF_POLICY_EXPONENTIAL) 583d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams .setOverrideDeadline(runByMillis) 593d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams .setMinimumLatency(runFromMillis) 60d1c06753d045ad10e00e7aba53ee2adba0712cccMatthew Williams .setPersisted(true) 613d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams .build(); 621085ff6ee531931ef7f55cbadbc83616f619b292Dianne Hackborn final JobStatus ts = JobStatus.createFromJobInfo(task, SOME_UID, null, -1, null); 633d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams mTaskStoreUnderTest.add(ts); 643d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams Thread.sleep(IO_WAIT); 653d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams // Manually load tasks from xml file. 662f36fd6fc94b62b8ccd03cdcea89826d05414f93Christopher Tate final JobSet jobStatusSet = new JobSet(); 6701ac45b6ff2334925c8d24b5278b44e5e30f5622Matthew Williams mTaskStoreUnderTest.readJobMapFromDisk(jobStatusSet); 6801ac45b6ff2334925c8d24b5278b44e5e30f5622Matthew Williams 6901ac45b6ff2334925c8d24b5278b44e5e30f5622Matthew Williams assertEquals("Didn't get expected number of persisted tasks.", 1, jobStatusSet.size()); 702f36fd6fc94b62b8ccd03cdcea89826d05414f93Christopher Tate final JobStatus loadedTaskStatus = jobStatusSet.getAllJobs().get(0); 7101ac45b6ff2334925c8d24b5278b44e5e30f5622Matthew Williams assertTasksEqual(task, loadedTaskStatus.getJob()); 7248a30db75dd0eedf8e065c89825b2af86a381b62Matthew Williams assertTrue("JobStore#contains invalid.", mTaskStoreUnderTest.containsJob(ts)); 7301ac45b6ff2334925c8d24b5278b44e5e30f5622Matthew Williams assertEquals("Different uids.", SOME_UID, loadedTaskStatus.getUid()); 7401ac45b6ff2334925c8d24b5278b44e5e30f5622Matthew Williams compareTimestampsSubjectToIoLatency("Early run-times not the same after read.", 7501ac45b6ff2334925c8d24b5278b44e5e30f5622Matthew Williams ts.getEarliestRunTime(), loadedTaskStatus.getEarliestRunTime()); 7601ac45b6ff2334925c8d24b5278b44e5e30f5622Matthew Williams compareTimestampsSubjectToIoLatency("Late run-times not the same after read.", 7701ac45b6ff2334925c8d24b5278b44e5e30f5622Matthew Williams ts.getLatestRunTimeElapsed(), loadedTaskStatus.getLatestRunTimeElapsed()); 783d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams 793d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams } 803d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams 813d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams public void testWritingTwoFilesToDisk() throws Exception { 827060b04f6d92351b67222e636ab378a0273bf3e7Christopher Tate final JobInfo task1 = new Builder(8, mComponent) 833d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams .setRequiresDeviceIdle(true) 843d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams .setPeriodic(10000L) 853d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams .setRequiresCharging(true) 86d1c06753d045ad10e00e7aba53ee2adba0712cccMatthew Williams .setPersisted(true) 873d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams .build(); 887060b04f6d92351b67222e636ab378a0273bf3e7Christopher Tate final JobInfo task2 = new Builder(12, mComponent) 893d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams .setMinimumLatency(5000L) 90d1c06753d045ad10e00e7aba53ee2adba0712cccMatthew Williams .setBackoffCriteria(15000L, JobInfo.BACKOFF_POLICY_LINEAR) 913d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams .setOverrideDeadline(30000L) 92d1c06753d045ad10e00e7aba53ee2adba0712cccMatthew Williams .setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED) 93d1c06753d045ad10e00e7aba53ee2adba0712cccMatthew Williams .setPersisted(true) 943d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams .build(); 951085ff6ee531931ef7f55cbadbc83616f619b292Dianne Hackborn final JobStatus taskStatus1 = JobStatus.createFromJobInfo(task1, SOME_UID, null, -1, null); 961085ff6ee531931ef7f55cbadbc83616f619b292Dianne Hackborn final JobStatus taskStatus2 = JobStatus.createFromJobInfo(task2, SOME_UID, null, -1, null); 973d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams mTaskStoreUnderTest.add(taskStatus1); 983d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams mTaskStoreUnderTest.add(taskStatus2); 993d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams Thread.sleep(IO_WAIT); 10001ac45b6ff2334925c8d24b5278b44e5e30f5622Matthew Williams 1012f36fd6fc94b62b8ccd03cdcea89826d05414f93Christopher Tate final JobSet jobStatusSet = new JobSet(); 10201ac45b6ff2334925c8d24b5278b44e5e30f5622Matthew Williams mTaskStoreUnderTest.readJobMapFromDisk(jobStatusSet); 10301ac45b6ff2334925c8d24b5278b44e5e30f5622Matthew Williams assertEquals("Incorrect # of persisted tasks.", 2, jobStatusSet.size()); 1042f36fd6fc94b62b8ccd03cdcea89826d05414f93Christopher Tate Iterator<JobStatus> it = jobStatusSet.getAllJobs().iterator(); 10501ac45b6ff2334925c8d24b5278b44e5e30f5622Matthew Williams JobStatus loaded1 = it.next(); 10601ac45b6ff2334925c8d24b5278b44e5e30f5622Matthew Williams JobStatus loaded2 = it.next(); 107fa8e5084eed63ab8d92c71fcff656690a30293c3Matthew Williams 108fa8e5084eed63ab8d92c71fcff656690a30293c3Matthew Williams // Reverse them so we know which comparison to make. 109fa8e5084eed63ab8d92c71fcff656690a30293c3Matthew Williams if (loaded1.getJobId() != 8) { 110fa8e5084eed63ab8d92c71fcff656690a30293c3Matthew Williams JobStatus tmp = loaded1; 111fa8e5084eed63ab8d92c71fcff656690a30293c3Matthew Williams loaded1 = loaded2; 112fa8e5084eed63ab8d92c71fcff656690a30293c3Matthew Williams loaded2 = tmp; 113fa8e5084eed63ab8d92c71fcff656690a30293c3Matthew Williams } 114fa8e5084eed63ab8d92c71fcff656690a30293c3Matthew Williams 11501ac45b6ff2334925c8d24b5278b44e5e30f5622Matthew Williams assertTasksEqual(task1, loaded1.getJob()); 11601ac45b6ff2334925c8d24b5278b44e5e30f5622Matthew Williams assertTasksEqual(task2, loaded2.getJob()); 11748a30db75dd0eedf8e065c89825b2af86a381b62Matthew Williams assertTrue("JobStore#contains invalid.", mTaskStoreUnderTest.containsJob(taskStatus1)); 11848a30db75dd0eedf8e065c89825b2af86a381b62Matthew Williams assertTrue("JobStore#contains invalid.", mTaskStoreUnderTest.containsJob(taskStatus2)); 11901ac45b6ff2334925c8d24b5278b44e5e30f5622Matthew Williams // Check that the loaded task has the correct runtimes. 12001ac45b6ff2334925c8d24b5278b44e5e30f5622Matthew Williams compareTimestampsSubjectToIoLatency("Early run-times not the same after read.", 12101ac45b6ff2334925c8d24b5278b44e5e30f5622Matthew Williams taskStatus1.getEarliestRunTime(), loaded1.getEarliestRunTime()); 12201ac45b6ff2334925c8d24b5278b44e5e30f5622Matthew Williams compareTimestampsSubjectToIoLatency("Late run-times not the same after read.", 12301ac45b6ff2334925c8d24b5278b44e5e30f5622Matthew Williams taskStatus1.getLatestRunTimeElapsed(), loaded1.getLatestRunTimeElapsed()); 12401ac45b6ff2334925c8d24b5278b44e5e30f5622Matthew Williams compareTimestampsSubjectToIoLatency("Early run-times not the same after read.", 12501ac45b6ff2334925c8d24b5278b44e5e30f5622Matthew Williams taskStatus2.getEarliestRunTime(), loaded2.getEarliestRunTime()); 12601ac45b6ff2334925c8d24b5278b44e5e30f5622Matthew Williams compareTimestampsSubjectToIoLatency("Late run-times not the same after read.", 12701ac45b6ff2334925c8d24b5278b44e5e30f5622Matthew Williams taskStatus2.getLatestRunTimeElapsed(), loaded2.getLatestRunTimeElapsed()); 1283d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams 1293d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams } 1303d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams 1313d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams public void testWritingTaskWithExtras() throws Exception { 1327060b04f6d92351b67222e636ab378a0273bf3e7Christopher Tate JobInfo.Builder b = new Builder(8, mComponent) 1333d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams .setRequiresDeviceIdle(true) 1343d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams .setPeriodic(10000L) 135900c67fc51fc2672458dd1c9641250f2ecc01a31Matthew Williams .setRequiresCharging(true) 136d1c06753d045ad10e00e7aba53ee2adba0712cccMatthew Williams .setPersisted(true); 1373d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams 1383d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams PersistableBundle extras = new PersistableBundle(); 1393d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams extras.putDouble("hello", 3.2); 1403d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams extras.putString("hi", "there"); 1413d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams extras.putInt("into", 3); 1423d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams b.setExtras(extras); 1437060b04f6d92351b67222e636ab378a0273bf3e7Christopher Tate final JobInfo task = b.build(); 1441085ff6ee531931ef7f55cbadbc83616f619b292Dianne Hackborn JobStatus taskStatus = JobStatus.createFromJobInfo(task, SOME_UID, null, -1, null); 1453d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams 1463d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams mTaskStoreUnderTest.add(taskStatus); 1473d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams Thread.sleep(IO_WAIT); 1483d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams 1492f36fd6fc94b62b8ccd03cdcea89826d05414f93Christopher Tate final JobSet jobStatusSet = new JobSet(); 15001ac45b6ff2334925c8d24b5278b44e5e30f5622Matthew Williams mTaskStoreUnderTest.readJobMapFromDisk(jobStatusSet); 15101ac45b6ff2334925c8d24b5278b44e5e30f5622Matthew Williams assertEquals("Incorrect # of persisted tasks.", 1, jobStatusSet.size()); 1522f36fd6fc94b62b8ccd03cdcea89826d05414f93Christopher Tate JobStatus loaded = jobStatusSet.getAllJobs().iterator().next(); 15301ac45b6ff2334925c8d24b5278b44e5e30f5622Matthew Williams assertTasksEqual(task, loaded.getJob()); 1543d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams } 1558e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge public void testWritingTaskWithSourcePackage() throws Exception { 1568e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge JobInfo.Builder b = new Builder(8, mComponent) 1578e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge .setRequiresDeviceIdle(true) 1588e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge .setPeriodic(10000L) 1598e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge .setRequiresCharging(true) 1608e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge .setPersisted(true); 161b0001f6fb1383d9824c2733896b0b348e7f77240Dianne Hackborn JobStatus taskStatus = JobStatus.createFromJobInfo(b.build(), SOME_UID, 1621085ff6ee531931ef7f55cbadbc83616f619b292Dianne Hackborn "com.google.android.gms", 0, null); 1638e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge 1648e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge mTaskStoreUnderTest.add(taskStatus); 1658e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge Thread.sleep(IO_WAIT); 1668e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge 1672f36fd6fc94b62b8ccd03cdcea89826d05414f93Christopher Tate final JobSet jobStatusSet = new JobSet(); 1688e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge mTaskStoreUnderTest.readJobMapFromDisk(jobStatusSet); 1698e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge assertEquals("Incorrect # of persisted tasks.", 1, jobStatusSet.size()); 1702f36fd6fc94b62b8ccd03cdcea89826d05414f93Christopher Tate JobStatus loaded = jobStatusSet.getAllJobs().iterator().next(); 1718e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge assertEquals("Source package not equal.", loaded.getSourcePackageName(), 1728e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge taskStatus.getSourcePackageName()); 1738e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge assertEquals("Source user not equal.", loaded.getSourceUserId(), 1748e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge taskStatus.getSourceUserId()); 1758e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge } 1768e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge 1778e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge public void testWritingTaskWithFlex() throws Exception { 1788e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge JobInfo.Builder b = new Builder(8, mComponent) 1798e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge .setRequiresDeviceIdle(true) 1808e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge .setPeriodic(5*60*60*1000, 1*60*60*1000) 1818e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge .setRequiresCharging(true) 1828e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge .setPersisted(true); 1831085ff6ee531931ef7f55cbadbc83616f619b292Dianne Hackborn JobStatus taskStatus = JobStatus.createFromJobInfo(b.build(), SOME_UID, null, -1, null); 1848e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge 1858e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge mTaskStoreUnderTest.add(taskStatus); 1868e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge Thread.sleep(IO_WAIT); 1878e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge 1882f36fd6fc94b62b8ccd03cdcea89826d05414f93Christopher Tate final JobSet jobStatusSet = new JobSet(); 1898e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge mTaskStoreUnderTest.readJobMapFromDisk(jobStatusSet); 1908e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge assertEquals("Incorrect # of persisted tasks.", 1, jobStatusSet.size()); 1912f36fd6fc94b62b8ccd03cdcea89826d05414f93Christopher Tate JobStatus loaded = jobStatusSet.getAllJobs().iterator().next(); 1928e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge assertEquals("Period not equal.", loaded.getJob().getIntervalMillis(), 1938e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge taskStatus.getJob().getIntervalMillis()); 1948e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge assertEquals("Flex not equal.", loaded.getJob().getFlexMillis(), 1958e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge taskStatus.getJob().getFlexMillis()); 1968e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge } 1973d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams 198fa8e5084eed63ab8d92c71fcff656690a30293c3Matthew Williams public void testMassivePeriodClampedOnRead() throws Exception { 1998e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge final long ONE_HOUR = 60*60*1000L; // flex 2008e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge final long TWO_HOURS = 2 * ONE_HOUR; // period 201fa8e5084eed63ab8d92c71fcff656690a30293c3Matthew Williams JobInfo.Builder b = new Builder(8, mComponent) 2028e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge .setPeriodic(TWO_HOURS, ONE_HOUR) 203fa8e5084eed63ab8d92c71fcff656690a30293c3Matthew Williams .setPersisted(true); 204fa8e5084eed63ab8d92c71fcff656690a30293c3Matthew Williams final long invalidLateRuntimeElapsedMillis = 2058e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge SystemClock.elapsedRealtime() + (TWO_HOURS * ONE_HOUR) + TWO_HOURS; // > period+flex 206fa8e5084eed63ab8d92c71fcff656690a30293c3Matthew Williams final long invalidEarlyRuntimeElapsedMillis = 2078e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge invalidLateRuntimeElapsedMillis - TWO_HOURS; // Early is (late - period). 208b0001f6fb1383d9824c2733896b0b348e7f77240Dianne Hackborn final JobStatus js = new JobStatus(b.build(), SOME_UID, "somePackage", 2091085ff6ee531931ef7f55cbadbc83616f619b292Dianne Hackborn 0 /* sourceUserId */, "someTag", 210fa8e5084eed63ab8d92c71fcff656690a30293c3Matthew Williams invalidEarlyRuntimeElapsedMillis, invalidLateRuntimeElapsedMillis); 211fa8e5084eed63ab8d92c71fcff656690a30293c3Matthew Williams 212fa8e5084eed63ab8d92c71fcff656690a30293c3Matthew Williams mTaskStoreUnderTest.add(js); 213fa8e5084eed63ab8d92c71fcff656690a30293c3Matthew Williams Thread.sleep(IO_WAIT); 214fa8e5084eed63ab8d92c71fcff656690a30293c3Matthew Williams 2152f36fd6fc94b62b8ccd03cdcea89826d05414f93Christopher Tate final JobSet jobStatusSet = new JobSet(); 216fa8e5084eed63ab8d92c71fcff656690a30293c3Matthew Williams mTaskStoreUnderTest.readJobMapFromDisk(jobStatusSet); 217fa8e5084eed63ab8d92c71fcff656690a30293c3Matthew Williams assertEquals("Incorrect # of persisted tasks.", 1, jobStatusSet.size()); 2182f36fd6fc94b62b8ccd03cdcea89826d05414f93Christopher Tate JobStatus loaded = jobStatusSet.getAllJobs().iterator().next(); 219fa8e5084eed63ab8d92c71fcff656690a30293c3Matthew Williams 220fa8e5084eed63ab8d92c71fcff656690a30293c3Matthew Williams // Assert early runtime was clamped to be under now + period. We can do <= here b/c we'll 221fa8e5084eed63ab8d92c71fcff656690a30293c3Matthew Williams // call SystemClock.elapsedRealtime after doing the disk i/o. 222fa8e5084eed63ab8d92c71fcff656690a30293c3Matthew Williams final long newNowElapsed = SystemClock.elapsedRealtime(); 223fa8e5084eed63ab8d92c71fcff656690a30293c3Matthew Williams assertTrue("Early runtime wasn't correctly clamped.", 2248e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge loaded.getEarliestRunTime() <= newNowElapsed + TWO_HOURS); 2258e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge // Assert late runtime was clamped to be now + period + flex. 226fa8e5084eed63ab8d92c71fcff656690a30293c3Matthew Williams assertTrue("Early runtime wasn't correctly clamped.", 2278e64e2e6a4d2964b6a4147f5cccd03de934c86cdShreyas Basarge loaded.getEarliestRunTime() <= newNowElapsed + TWO_HOURS + ONE_HOUR); 2285db09084c8e4efc6311754243c39962fc8e7a766Shreyas Basarge } 2295db09084c8e4efc6311754243c39962fc8e7a766Shreyas Basarge 2305db09084c8e4efc6311754243c39962fc8e7a766Shreyas Basarge public void testPriorityPersisted() throws Exception { 2315db09084c8e4efc6311754243c39962fc8e7a766Shreyas Basarge JobInfo.Builder b = new Builder(92, mComponent) 2325db09084c8e4efc6311754243c39962fc8e7a766Shreyas Basarge .setOverrideDeadline(5000) 2335db09084c8e4efc6311754243c39962fc8e7a766Shreyas Basarge .setPriority(42) 2345db09084c8e4efc6311754243c39962fc8e7a766Shreyas Basarge .setPersisted(true); 2351085ff6ee531931ef7f55cbadbc83616f619b292Dianne Hackborn final JobStatus js = JobStatus.createFromJobInfo(b.build(), SOME_UID, null, -1, null); 2365db09084c8e4efc6311754243c39962fc8e7a766Shreyas Basarge mTaskStoreUnderTest.add(js); 2375db09084c8e4efc6311754243c39962fc8e7a766Shreyas Basarge Thread.sleep(IO_WAIT); 2382f36fd6fc94b62b8ccd03cdcea89826d05414f93Christopher Tate final JobSet jobStatusSet = new JobSet(); 2395db09084c8e4efc6311754243c39962fc8e7a766Shreyas Basarge mTaskStoreUnderTest.readJobMapFromDisk(jobStatusSet); 2402f36fd6fc94b62b8ccd03cdcea89826d05414f93Christopher Tate JobStatus loaded = jobStatusSet.getAllJobs().iterator().next(); 2415db09084c8e4efc6311754243c39962fc8e7a766Shreyas Basarge assertEquals("Priority not correctly persisted.", 42, loaded.getPriority()); 242fa8e5084eed63ab8d92c71fcff656690a30293c3Matthew Williams } 243fa8e5084eed63ab8d92c71fcff656690a30293c3Matthew Williams 2443d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams /** 2457ef490fab68ee93f92eb5728cc4d3cb691315412Shreyas Basarge * Test that non persisted job is not written to disk. 2467ef490fab68ee93f92eb5728cc4d3cb691315412Shreyas Basarge */ 2477ef490fab68ee93f92eb5728cc4d3cb691315412Shreyas Basarge public void testNonPersistedTaskIsNotPersisted() throws Exception { 2487ef490fab68ee93f92eb5728cc4d3cb691315412Shreyas Basarge JobInfo.Builder b = new Builder(42, mComponent) 2497ef490fab68ee93f92eb5728cc4d3cb691315412Shreyas Basarge .setOverrideDeadline(10000) 2507ef490fab68ee93f92eb5728cc4d3cb691315412Shreyas Basarge .setPersisted(false); 2511085ff6ee531931ef7f55cbadbc83616f619b292Dianne Hackborn JobStatus jsNonPersisted = JobStatus.createFromJobInfo(b.build(), SOME_UID, null, -1, null); 2527ef490fab68ee93f92eb5728cc4d3cb691315412Shreyas Basarge mTaskStoreUnderTest.add(jsNonPersisted); 2537ef490fab68ee93f92eb5728cc4d3cb691315412Shreyas Basarge b = new Builder(43, mComponent) 2547ef490fab68ee93f92eb5728cc4d3cb691315412Shreyas Basarge .setOverrideDeadline(10000) 2557ef490fab68ee93f92eb5728cc4d3cb691315412Shreyas Basarge .setPersisted(true); 2561085ff6ee531931ef7f55cbadbc83616f619b292Dianne Hackborn JobStatus jsPersisted = JobStatus.createFromJobInfo(b.build(), SOME_UID, null, -1, null); 2577ef490fab68ee93f92eb5728cc4d3cb691315412Shreyas Basarge mTaskStoreUnderTest.add(jsPersisted); 2587ef490fab68ee93f92eb5728cc4d3cb691315412Shreyas Basarge Thread.sleep(IO_WAIT); 2592f36fd6fc94b62b8ccd03cdcea89826d05414f93Christopher Tate final JobSet jobStatusSet = new JobSet(); 2607ef490fab68ee93f92eb5728cc4d3cb691315412Shreyas Basarge mTaskStoreUnderTest.readJobMapFromDisk(jobStatusSet); 2617ef490fab68ee93f92eb5728cc4d3cb691315412Shreyas Basarge assertEquals("Job count is incorrect.", 1, jobStatusSet.size()); 2622f36fd6fc94b62b8ccd03cdcea89826d05414f93Christopher Tate JobStatus jobStatus = jobStatusSet.getAllJobs().iterator().next(); 2637ef490fab68ee93f92eb5728cc4d3cb691315412Shreyas Basarge assertEquals("Wrong job persisted.", 43, jobStatus.getJobId()); 2647ef490fab68ee93f92eb5728cc4d3cb691315412Shreyas Basarge } 2657ef490fab68ee93f92eb5728cc4d3cb691315412Shreyas Basarge 2667ef490fab68ee93f92eb5728cc4d3cb691315412Shreyas Basarge /** 2673d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams * Helper function to throw an error if the provided task and TaskStatus objects are not equal. 2683d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams */ 2697060b04f6d92351b67222e636ab378a0273bf3e7Christopher Tate private void assertTasksEqual(JobInfo first, JobInfo second) { 2703d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams assertEquals("Different task ids.", first.getId(), second.getId()); 2713d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams assertEquals("Different components.", first.getService(), second.getService()); 2723d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams assertEquals("Different periodic status.", first.isPeriodic(), second.isPeriodic()); 2733d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams assertEquals("Different period.", first.getIntervalMillis(), second.getIntervalMillis()); 2743d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams assertEquals("Different inital backoff.", first.getInitialBackoffMillis(), 2753d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams second.getInitialBackoffMillis()); 2763d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams assertEquals("Different backoff policy.", first.getBackoffPolicy(), 2773d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams second.getBackoffPolicy()); 2783d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams 2793d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams assertEquals("Invalid charging constraint.", first.isRequireCharging(), 2803d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams second.isRequireCharging()); 2813d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams assertEquals("Invalid idle constraint.", first.isRequireDeviceIdle(), 2823d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams second.isRequireDeviceIdle()); 2833d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams assertEquals("Invalid unmetered constraint.", 284d1c06753d045ad10e00e7aba53ee2adba0712cccMatthew Williams first.getNetworkType() == JobInfo.NETWORK_TYPE_UNMETERED, 285d1c06753d045ad10e00e7aba53ee2adba0712cccMatthew Williams second.getNetworkType() == JobInfo.NETWORK_TYPE_UNMETERED); 2863d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams assertEquals("Invalid connectivity constraint.", 287d1c06753d045ad10e00e7aba53ee2adba0712cccMatthew Williams first.getNetworkType() == JobInfo.NETWORK_TYPE_ANY, 288d1c06753d045ad10e00e7aba53ee2adba0712cccMatthew Williams second.getNetworkType() == JobInfo.NETWORK_TYPE_ANY); 2893d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams assertEquals("Invalid deadline constraint.", 2903d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams first.hasLateConstraint(), 2913d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams second.hasLateConstraint()); 2923d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams assertEquals("Invalid delay constraint.", 2933d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams first.hasEarlyConstraint(), 2943d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams second.hasEarlyConstraint()); 2953d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams assertEquals("Extras don't match", 2963d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams first.getExtras().toString(), second.getExtras().toString()); 2973d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams } 2983d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams 2993d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams /** 3003d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams * When comparing timestamps before and after DB read/writes (to make sure we're saving/loading 3013d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams * the correct values), there is some latency involved that terrorises a naive assertEquals(). 3023d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams * We define a <code>DELTA_MILLIS</code> as a function variable here to make this comparision 3033d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams * more reasonable. 3043d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams */ 3053d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams private void compareTimestampsSubjectToIoLatency(String error, long ts1, long ts2) { 3063d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams final long DELTA_MILLIS = 700L; // We allow up to 700ms of latency for IO read/writes. 3073d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams assertTrue(error, Math.abs(ts1 - ts2) < DELTA_MILLIS + IO_WAIT); 3083d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams } 3093d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams 3103d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams private static class StubClass {} 3113d86fd2bb9db6067c49634bc4c6cdb4d5235ad36Matthew Williams 31201ac45b6ff2334925c8d24b5278b44e5e30f5622Matthew Williams} 313