jobscheduler/src/main/java/me/tatarka/support/internal/job/JobSchedulerService.java
private JobStatus reschedulePeriodicJob(JobStatus job) {
        final long elapsedNow = SystemClock.elapsedRealtime();
        // Compute how much of the period is remaining.
        long runEarly = Math.max(job.getLatestRunTimeElapsed() - elapsedNow, 0);
        long newEarliestRunTimeElapsed = elapsedNow + runEarly;
        long period = job.getJob().getIntervalMillis();
        long newLatestRuntimeElapsed = newEarliestRunTimeElapsed + period;
        return new JobStatus(job, newEarliestRunTimeElapsed,
                newLatestRuntimeElapsed, 0 /* backoffAttempt */);
    }
private JobStatus reschedulePeriodicJob(JobStatus job) {
        final long elapsedNow = SystemClock.elapsedRealtime();
        // Compute how much of the period is remaining.
        long runEarly = Math.max(job.getLatestRunTimeElapsed() - elapsedNow, 0);
        long newEarliestRunTimeElapsed = elapsedNow + runEarly;
        long period = job.getJob().getIntervalMillis();
        long newLatestRuntimeElapsed = newEarliestRunTimeElapsed + period;
        return new JobStatus(job, newEarliestRunTimeElapsed,
                newLatestRuntimeElapsed, 0 /* backoffAttempt */);
    }
Called after a periodic has executed so we can to re-add it. We take the last execution time
of the job to be the time of completion (i.e. the time at which this function is called).
This could be inaccurate b/c the job can run for as long as
{@link com.android.server.job.JobServiceContext#EXECUTING_TIMESLICE_MILLIS}, but will lead
to underscheduling at least, rather than if we had taken the last execution time to be the
start of the execution.
@return A new job representing the execution criteria for this instantiation of the
recurring job.