@Override protected void onHandleWork(@NonNull Intent intent) { /* * Delay this slightly. This avoids a race condition if the app was launched by the * AlarmManager. Then the alarm was already removed, but the JobRequest might still * be available in the storage. We still catch this case, because we never execute * a job with the same ID twice. Nonetheless, add the delay to save resources. */ try { CAT.d("Reschedule service started"); SystemClock.sleep(JobConfig.getJobReschedulePause()); JobManager manager; try { manager = JobManager.create(this); } catch (Exception e) { return; } Set<JobRequest> requests = manager.getAllJobRequests(null, true, true); int rescheduledCount = rescheduleJobs(manager, requests); CAT.d("Reschedule %d jobs of %d jobs", rescheduledCount, requests.size()); } finally { if (latch != null) { // latch can be null, if the service was restarted after a process death latch.countDown(); } } }
@Override public boolean onStopJob(JobParameters params) { Job job = JobManager.create(this).getJob(params.getJobId()); if (job != null) { job.cancel(); CAT.d("Called onStopJob for %s", job); } else { CAT.d("Called onStopJob, job %d not found", params.getJobId()); } // do not reschedule return false; }
private void logScheduled(JobRequest request) { mCat.d("Scheduled alarm, %s, delay %s (from now), exact %b, reschedule count %d", request, JobUtil.timeToString(Common.getAverageDelayMs(request)), request.isExact(), Common.getRescheduleCount(request)); }
@Override protected void plantOneOffInexact(JobRequest request, AlarmManager alarmManager, PendingIntent pendingIntent) { long currentTime = System.currentTimeMillis(); long startMs = currentTime + Common.getStartMs(request); long lengthMs = Common.getEndMs(request) - Common.getStartMs(request); alarmManager.setWindow(AlarmManager.RTC, startMs, lengthMs, pendingIntent); mCat.d("Schedule alarm, %s, start %s, end %s", request, JobUtil.timeToString(Common.getStartMs(request)), JobUtil.timeToString(Common.getEndMs(request))); }
@Override public void run() { try { final int jobId = params.getJobId(); final JobProxy.Common common = new JobProxy.Common(PlatformJobService.this, CAT, jobId); // don't mark starting! final JobRequest request = common.getPendingRequest(true, false); if (request == null) { return; } if (request.isTransient()) { if (TransientBundleCompat.startWithTransientBundle(PlatformJobService.this, request)) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { // should only happen during testing if an API is disabled CAT.d("PendingIntent for transient bundle is not null although running on O, using compat mode, request %s", request); } return; } else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { CAT.d("PendingIntent for transient job %s expired", request); return; } } common.markStarting(request); common.executeJobRequest(request, getTransientBundle(params)); } finally { // do not reschedule jobFinished(params, false); } } });
@Override protected void plantOneOffFlexSupport(JobRequest request, AlarmManager alarmManager, PendingIntent pendingIntent) { long currentTime = System.currentTimeMillis(); long startMs = currentTime + Common.getStartMsSupportFlex(request); long lengthMs = Common.getEndMsSupportFlex(request) - Common.getStartMsSupportFlex(request); alarmManager.setWindow(AlarmManager.RTC, startMs, lengthMs, pendingIntent); mCat.d("Scheduled repeating alarm (flex support), %s, start %s, end %s, flex %s", request, JobUtil.timeToString(Common.getStartMsSupportFlex(request)), JobUtil.timeToString(Common.getEndMsSupportFlex(request)), JobUtil.timeToString(request.getFlexMs())); } }
protected void plantOneOffFlexSupport(JobRequest request, AlarmManager alarmManager, PendingIntent pendingIntent) { long triggerAtMs = JobConfig.getClock().currentTimeMillis() + Common.getAverageDelayMsSupportFlex(request); alarmManager.set(AlarmManager.RTC, triggerAtMs, pendingIntent); mCat.d("Scheduled repeating alarm (flex support), %s, interval %s, flex %s", request, JobUtil.timeToString(request.getIntervalMs()), JobUtil.timeToString(request.getFlexMs())); }
@Override public void plantPeriodic(JobRequest request) { PendingIntent pendingIntent = getPendingIntent(request, true); AlarmManager alarmManager = getAlarmManager(); if (alarmManager != null) { alarmManager.setRepeating(getType(true), getTriggerAtMillis(request), request.getIntervalMs(), pendingIntent); } mCat.d("Scheduled repeating alarm, %s, interval %s", request, JobUtil.timeToString(request.getIntervalMs())); }
transientBundle = TransientBundleHolder.getBundle(jobId); if (transientBundle == null) { CAT.d("Transient bundle is gone for request %s", request); return Result.FAILURE;
@Test public void testSingleCustomLoggerAddAfter() { JobCat cat = new JobCat("Tag"); TestLogger printer = new TestLogger(); assertThat(JobConfig.addLogger(printer)).isTrue(); cat.d("hello"); cat.w("world"); assertThat(printer.mMessages).containsExactly("hello", "world"); }
@Test public void test100Loggers() { JobCat cat1 = new JobCat("Tag1"); List<TestLogger> printers = new ArrayList<>(); for (int i = 0; i < 100; i++) { TestLogger printer = new TestLogger(); assertThat(JobConfig.addLogger(printer)).isTrue(); printers.add(printer); } JobCat cat2 = new JobCat("Tag2"); cat1.d("hello"); cat2.w("world"); for (TestLogger printer : printers) { assertThat(printer.mTags).containsExactly("Tag1", "Tag2"); assertThat(printer.mMessages).containsExactly("hello", "world"); } TestLogger removedPrinter = printers.remove(50); JobConfig.removeLogger(removedPrinter); cat1.d("third"); for (TestLogger printer : printers) { assertThat(printer.mTags).containsExactly("Tag1", "Tag2", "Tag1"); assertThat(printer.mMessages).containsExactly("hello", "world", "third"); } assertThat(removedPrinter.mTags).containsExactly("Tag1", "Tag2"); assertThat(removedPrinter.mMessages).containsExactly("hello", "world"); }
@Test public void testSingleCustomLoggerAddBefore() { TestLogger printer = new TestLogger(); assertThat(JobConfig.addLogger(printer)).isTrue(); JobCat cat = new JobCat("Tag"); cat.d("hello"); cat.w("world"); assertThat(printer.mMessages).contains("hello", "world"); }
@Override public void plantPeriodic(JobRequest request) { long intervalMs = request.getIntervalMs(); long flexMs = request.getFlexMs(); JobInfo jobInfo = createBuilderPeriodic(createBaseBuilder(request, true), intervalMs, flexMs).build(); int scheduleResult = schedule(jobInfo); if (scheduleResult == ERROR_BOOT_PERMISSION) { jobInfo = createBuilderPeriodic(createBaseBuilder(request, false), intervalMs, flexMs).build(); scheduleResult = schedule(jobInfo); } mCat.d("Schedule periodic jobInfo %s, %s, interval %s, flex %s", scheduleResultToString(scheduleResult), request, JobUtil.timeToString(intervalMs), JobUtil.timeToString(flexMs)); }
@Override public void plantPeriodicFlexSupport(JobRequest request) { long startMs = Common.getStartMsSupportFlex(request); long endMs = Common.getEndMsSupportFlex(request); JobInfo jobInfo = createBuilderOneOff(createBaseBuilder(request, true), startMs, endMs).build(); int scheduleResult = schedule(jobInfo); if (scheduleResult == ERROR_BOOT_PERMISSION) { jobInfo = createBuilderOneOff(createBaseBuilder(request, false), startMs, endMs).build(); scheduleResult = schedule(jobInfo); } mCat.d("Schedule periodic (flex support) jobInfo %s, %s, start %s, end %s, flex %s", scheduleResultToString(scheduleResult), request, JobUtil.timeToString(startMs), JobUtil.timeToString(endMs), JobUtil.timeToString(request.getFlexMs())); }
@Override public void plantOneOff(JobRequest request) { long startMs = Common.getStartMs(request); long endMs = Common.getEndMs(request, true); JobInfo jobInfo = createBuilderOneOff(createBaseBuilder(request, true), startMs, endMs).build(); int scheduleResult = schedule(jobInfo); if (scheduleResult == ERROR_BOOT_PERMISSION) { jobInfo = createBuilderOneOff(createBaseBuilder(request, false), startMs, endMs).build(); scheduleResult = schedule(jobInfo); } mCat.d("Schedule one-off jobInfo %s, %s, start %s, end %s (from now), reschedule count %d", scheduleResultToString(scheduleResult), request, JobUtil.timeToString(startMs), JobUtil.timeToString(Common.getEndMs(request, false)), Common.getRescheduleCount(request)); }
@Override public boolean onStopJob(JobParameters params) { Job job = JobManager.create(this).getJob(params.getJobId()); if (job != null) { job.cancel(); CAT.d("Called onStopJob for %s", job); } else { CAT.d("Called onStopJob, job %d not found", params.getJobId()); } // do not reschedule return false; }
@Override protected void plantOneOffFlexSupport(JobRequest request, AlarmManager alarmManager, PendingIntent pendingIntent) { long currentTime = System.currentTimeMillis(); long startMs = currentTime + Common.getStartMsSupportFlex(request); long lengthMs = Common.getEndMsSupportFlex(request) - Common.getStartMsSupportFlex(request); alarmManager.setWindow(AlarmManager.RTC, startMs, lengthMs, pendingIntent); mCat.d("Scheduled repeating alarm (flex support), %s, start %s, end %s, flex %s", request, JobUtil.timeToString(Common.getStartMsSupportFlex(request)), JobUtil.timeToString(Common.getEndMsSupportFlex(request)), JobUtil.timeToString(request.getFlexMs())); } }
@Override public void plantPeriodic(JobRequest request) { PendingIntent pendingIntent = getPendingIntent(request, true); AlarmManager alarmManager = getAlarmManager(); if (alarmManager != null) { alarmManager.setRepeating(getType(true), getTriggerAtMillis(request), request.getIntervalMs(), pendingIntent); } mCat.d("Scheduled repeating alarm, %s, interval %s", request, JobUtil.timeToString(request.getIntervalMs())); }