.schedule(); final JobProxy.Common common = new JobProxy.Common(context(), TestLogger.INSTANCE, jobId); final JobRequest request = common.getPendingRequest(true, true); assertThat(request).isNotNull();
JobProxy.Common common = new JobProxy.Common(getApplicationContext(), CAT, jobId); JobRequest request = common.getPendingRequest(true, true); if (request == null) { return Result.FAILURE; Job.Result result = common.executeJobRequest(request, transientBundle); if (Job.Result.SUCCESS == result) { return Result.SUCCESS;
@Test public void verifyPendingRequestNullWhenMarkedStated() { final int jobId = DummyJobs.createBuilder(DummyJobs.SuccessJob.class) .setPeriodic(TimeUnit.MINUTES.toMillis(15)) .build() .schedule(); final JobProxy.Common common = new JobProxy.Common(context(), TestLogger.INSTANCE, jobId); assertThat(common.getPendingRequest(true, false)).isNotNull(); assertThat(common.getPendingRequest(true, false)).isNotNull(); JobRequest request = common.getPendingRequest(true, false); assertThat(request).isNotNull(); common.markStarting(request); assertThat(common.getPendingRequest(true, false)).isNull(); }
JobProxy.Common.cleanUpOrphanedJob(mContext, request.getJobId());
JobUtil.timeToString(request.getFlexMs())); } else if (request.getJobApi().supportsExecutionWindow()) { timeWindow = String.format(Locale.US, "start %s, end %s", JobUtil.timeToString(getStartMs(request)), JobUtil.timeToString(getEndMs(request))); } else { timeWindow = "delay " + JobUtil.timeToString(getAverageDelayMs(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); } } });
/*package*/ static void cleanUpOrphanedJob(Context context, int jobId) { /* * That's necessary if the database was deleted and jobs (especially the JobScheduler) are still around. * Then if a new job is being scheduled, it's possible that the new job has the ID of the old one. Here * we make sure, that no job is left in the system. */ for (JobApi jobApi : JobApi.values()) { if (jobApi.isSupported(context)) { try { jobApi.getProxy(context).cancel(jobId); } catch (Exception ignored) { // GCM API could crash if it's disabled, ignore crashes at this point and continue } } } }
public static long getAverageDelayMsSupportFlex(JobRequest request) { return checkedAdd(getStartMsSupportFlex(request), (getEndMsSupportFlex(request) - getStartMsSupportFlex(request)) / 2); }
/*package*/ static void runJob(@Nullable Intent intent, @NonNull Service service, @NonNull JobCat cat) { if (intent == null) { cat.i("Delivered intent is null"); return; } int jobId = intent.getIntExtra(PlatformAlarmReceiver.EXTRA_JOB_ID, -1); Bundle transientExtras = intent.getBundleExtra(PlatformAlarmReceiver.EXTRA_TRANSIENT_EXTRAS); final JobProxy.Common common = new JobProxy.Common(service, cat, jobId); // create the JobManager. Seeing sometimes exceptions, that it wasn't created, yet. final JobRequest request = common.getPendingRequest(true, true); if (request != null) { common.executeJobRequest(request, transientExtras); } } }
public static long getEndMs(JobRequest request, boolean shiftEnd) { long endMs; if (request.getFailureCount() > 0) { endMs = request.getBackoffOffset(); } else { endMs = request.getEndMs(); } if (shiftEnd && request.requirementsEnforced() && request.hasRequirements()) { // move the end backwards if the API is smart with the requirements endMs = checkedMultiply(endMs, 100); } return endMs; }
@Override public int onRunTask(TaskParams taskParams) { int jobId = Integer.parseInt(taskParams.getTag()); JobProxy.Common common = new JobProxy.Common(this, CAT, jobId); JobRequest request = common.getPendingRequest(true, true); if (request == null) { return GcmNetworkManager.RESULT_FAILURE; } Job.Result result = common.executeJobRequest(request, taskParams.getExtras()); if (Job.Result.SUCCESS.equals(result)) { return GcmNetworkManager.RESULT_SUCCESS; } else { return GcmNetworkManager.RESULT_FAILURE; } }
private static long checkedAdd(long a, long b) { long result = a + b; return checkNoOverflow(result, (a ^ b) < 0 | (a ^ result) >= 0); }
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)); }
public static long getAverageDelayMs(JobRequest request) { return checkedAdd(getStartMs(request), (getEndMs(request) - getStartMs(request)) / 2); }
@Override public void run() { try { PlatformAlarmService.runJob(intent, PlatformAlarmServiceExact.this, CAT); } finally { // call here, our own wake lock could be acquired too late JobProxy.Common.completeWakefulIntent(intent); stopSelfIfNecessary(startId); } } });
@SuppressWarnings("SameParameterValue") private static long checkedMultiply(long a, long b) { int leadingZeros = Long.numberOfLeadingZeros(a) + Long.numberOfLeadingZeros(~a) + Long.numberOfLeadingZeros(b) + Long.numberOfLeadingZeros(~b); if (leadingZeros > Long.SIZE + 1) { return a * b; } long result = a * b; result = checkNoOverflow(result, leadingZeros >= Long.SIZE); result = checkNoOverflow(result, a >= 0 | b != Long.MIN_VALUE); result = checkNoOverflow(result, a == 0 || result / a == b); return result; }
protected long getTriggerAtMillis(JobRequest request) { if (JobConfig.isForceRtc()) { return JobConfig.getClock().currentTimeMillis() + Common.getAverageDelayMs(request); } else { return JobConfig.getClock().elapsedRealtime() + Common.getAverageDelayMs(request); } }
/** * Cancel either the pending {@link JobRequest} or the running {@link Job}. * * @param jobId The unique ID of the {@link JobRequest} or running {@link Job}. * @return {@code true} if a request or job were found and canceled. */ public boolean cancel(int jobId) { // call both methods boolean result = cancelInner(getJobRequest(jobId, true)) | cancelInner(getJob(jobId)); JobProxy.Common.cleanUpOrphanedJob(mContext, jobId); // do this as well, just in case return result; }
JobUtil.timeToString(request.getFlexMs())); } else if (request.getJobApi().supportsExecutionWindow()) { timeWindow = String.format(Locale.US, "start %s, end %s", JobUtil.timeToString(getStartMs(request)), JobUtil.timeToString(getEndMs(request))); } else { timeWindow = "delay " + JobUtil.timeToString(getAverageDelayMs(request));
JobProxy.Common.cleanUpOrphanedJob(mContext, request.getJobId());