Builder(@NonNull ValidationEnforcer validator, JobParameters job) { this.validator = validator; tag = job.getTag(); serviceClassName = job.getService(); trigger = job.getTrigger(); recurring = job.isRecurring(); lifetime = job.getLifetime(); constraints = job.getConstraints(); extras = job.getExtras(); retryStrategy = job.getRetryStrategy(); }
/** * Recurring content URI triggered jobs need to be rescheduled when execution is finished. * * <p>GooglePlay does not support recurring content URI triggered jobs. * * <p>{@link JobService#RESULT_FAIL_RETRY} needs to be sent or current triggered URIs will be * lost. */ private static boolean needsToBeRescheduled(JobParameters job, int result) { return job.isRecurring() && job.getTrigger() instanceof ContentUriTrigger && result != JobService.RESULT_FAIL_RETRY; }
public synchronized void recordResult(JobParameters j, int result) { for (JobHistory jh : this) { if (jh.job.getTag().equals(j.getTag()) && jh.job.getService().equals(j.getService())) { jh.recordResult(result); return; } } JobHistory jh = new JobHistory(j); jh.recordResult(result); add(jh); }
public Bundle writeToBundle(JobParameters job, Bundle b) { b.putString(REQUEST_PARAM_TAG, job.getTag()); b.putBoolean(REQUEST_PARAM_UPDATE_CURRENT, job.shouldReplaceCurrent()); boolean persisted = job.getLifetime() == Lifetime.FOREVER; b.putBoolean(REQUEST_PARAM_PERSISTED, persisted); b.putString(REQUEST_PARAM_SERVICE, GooglePlayReceiver.class.getName()); writeTriggerToBundle(job, b); writeConstraintsToBundle(job, b); writeRetryStrategyToBundle(job, b); // Embed the job spec into the extras (under a prefix). Bundle userExtras = job.getExtras(); if (userExtras == null) { userExtras = new Bundle(); } b.putBundle(REQUEST_PARAM_EXTRAS, jobCoder.encode(job, userExtras)); return b; }
@Override public int cancel(@NonNull String tag) { synchronized (mStore) { final Iterator<JobHistory> it = mStore.iterator(); while (it.hasNext()) { JobParameters j = it.next().job; if (tag == null || tag.equals(j.getTag())) { it.remove(); break; } } return mDriver.cancel(tag); } }
@Override public boolean onStartJob(@NonNull JobParameters job) { Log.i(JobFormActivity.TAG, "onStartJob called"); Bundle extras = job.getExtras(); assert extras != null; int result = extras.getInt("return"); CentralContainer.getStore(getApplicationContext()).recordResult(job, result); return false; // No more work to do }
private View createViewForJob(JobParameters job) { TableLayout tableLayout = new TableLayout(this); addRow(tableLayout, "TAG = " + job.getTag()); addRow(tableLayout, "SERVICE = " + job.getService()); if (job.getTriggerReason() != null && job.getTrigger() instanceof JobTrigger.ContentUriTrigger) { ContentUriTrigger trigger = (ContentUriTrigger) job.getTrigger(); addRow(tableLayout, "OBSERVED URIs = "); for (ObservedUri uri : trigger.getUris()) { addRow( tableLayout, "URI = " + uri.getUri() + ", flags = " + Integer.toBinaryString(uri.getFlags())); } addRow(tableLayout, "TRIGGERED URIs = "); for (Uri uri : job.getTriggerReason().getTriggeredContentUris()) { addRow(tableLayout, uri.toString()); } } ScrollView scrollView = new ScrollView(this); scrollView.addView(tableLayout); return scrollView; }
@Override public View getView(final int position, View convertView, ViewGroup parent) { final Context ctx = getContext(); TextView textView = new TextView(parent.getContext()); JobParameters job = getItem(position).job; List<Uri> uris = job.getTriggerReason() != null ? job.getTriggerReason().getTriggeredContentUris() : Collections.<Uri>emptyList(); textView.setText(String.format(Locale.US, CELL_FORMAT, job.getTag(), job.getService(), uris)); textView.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { Intent i = new Intent(ctx, JobDetailActivity.class); i.putExtra("pos", position); ctx.startActivity(i); } }); return textView; }
private static void writeTriggerToBundle(JobParameters job, Bundle b) { final JobTrigger trigger = job.getTrigger(); if (trigger == Trigger.NOW) { writeImmediateTriggerToBundle(b); } else if (trigger instanceof JobTrigger.ExecutionWindowTrigger) { writeExecutionWindowTriggerToBundle(job, b, (JobTrigger.ExecutionWindowTrigger) trigger); } else if (trigger instanceof JobTrigger.ContentUriTrigger) { writeContentUriTriggerToBundle(b, (JobTrigger.ContentUriTrigger) trigger); } else { throw new IllegalArgumentException("Unknown trigger: " + trigger.getClass()); } }
private static void writeConstraintsToBundle(JobParameters job, Bundle b) { int c = Constraint.compact(job.getConstraints()); b.putBoolean( REQUEST_PARAM_REQUIRES_CHARGING, (c & Constraint.DEVICE_CHARGING) == Constraint.DEVICE_CHARGING); b.putBoolean( REQUEST_PARAM_REQUIRES_IDLE, (c & Constraint.DEVICE_IDLE) == Constraint.DEVICE_IDLE); b.putInt(REQUEST_PARAM_REQUIRED_NETWORK, convertConstraintsToLegacyNetConstant(c)); }
private static void writeExecutionWindowTriggerToBundle( JobParameters job, Bundle b, JobTrigger.ExecutionWindowTrigger trigger) { b.putInt(REQUEST_PARAM_TRIGGER_TYPE, BundleProtocol.TRIGGER_TYPE_EXECUTION_WINDOW); if (job.isRecurring()) { b.putLong(REQUEST_PARAM_TRIGGER_WINDOW_PERIOD, trigger.getWindowEnd()); b.putLong( REQUEST_PARAM_TRIGGER_WINDOW_FLEX, trigger.getWindowEnd() - trigger.getWindowStart()); } else { b.putLong(REQUEST_PARAM_TRIGGER_WINDOW_START, trigger.getWindowStart()); b.putLong(REQUEST_PARAM_TRIGGER_WINDOW_END, trigger.getWindowEnd()); } }
private static void writeRetryStrategyToBundle(JobParameters job, Bundle b) { RetryStrategy strategy = job.getRetryStrategy(); Bundle rb = new Bundle(); rb.putInt( REQUEST_PARAM_RETRY_STRATEGY_POLICY, convertRetryPolicyToLegacyVersion(strategy.getPolicy())); rb.putInt(REQUEST_PARAM_RETRY_STRATEGY_INITIAL_BACKOFF_SECONDS, strategy.getInitialBackoff()); rb.putInt(REQUEST_PARAM_RETRY_STRATEGY_MAXIMUM_BACKOFF_SECONDS, strategy.getMaximumBackoff()); b.putBundle(REQUEST_PARAM_RETRY_STRATEGY, rb); }
/** * Records that the provided {@code job} has been started, then arranges for {@link * #onStartJob(JobParameters)} to be called on the main thread (via {@link * #callOnStartJobImpl(JobParameters)}. */ @WorkerThread private void handleStartJobRequestImpl(final JobParameters job, IJobCallback callback) { synchronized (runningJobs) { if (runningJobs.containsKey(job.getTag())) { Log.w( TAG, String.format(Locale.US, "Job with tag = %s was already running.", job.getTag())); return; } runningJobs.put(job.getTag(), new JobCallback(job, callback, SystemClock.elapsedRealtime())); } // onStartJob needs to be called on the main thread mainHandler.post(UnitOfWork.callOnStartJob(this, job)); }
final Bundle extras = jobParameters.getExtras(); if (LOCAL_LOGV) { Log.v(TAG, "onStartJob(" + jobParameters + ", extras=" + extras + ")"); } else if (shouldRun(jobParameters)) { startService(new Intent(this, SmsBackupService.class) .setAction(jobParameters.getTag()) .putExtras(extras)); jobs.put(jobParameters.getTag(), jobParameters); return true; } else {
/** * Called when the scheduling engine has decided to interrupt the execution of a running job, most * likely because the runtime constraints associated with the job are no longer satisfied. The job * must stop execution. * * @return true if the job should be retried */ @Override public boolean onStopJob(JobParameters jobParameters) { if (LOCAL_LOGV) { Log.v(TAG, "onStopJob(" + jobParameters + ", extras=" + jobParameters.getExtras() + ")"); } App.post(new CancelEvent(SYSTEM)); return false; }
@Override public int schedule(@NonNull Job job) { Log.i("TrackingBackend", "beginning schedule loop"); synchronized (mStore) { final Iterator<JobHistory> it = mStore.iterator(); while (it.hasNext()) { JobParameters j = it.next().job; if (j.getTag().equals(job.getTag()) && j.getService().equals(job.getService())) { it.remove(); } } mStore.add(new JobHistory(job)); } Log.i("TrackingBackend", "ending schedule loop"); return mDriver.schedule(job); }
@NonNull Bundle encode(@NonNull JobParameters jobParameters, @NonNull Bundle data) { if (data == null) { throw new IllegalArgumentException("Unexpected null Bundle provided"); } Bundle userExtras = jobParameters.getExtras(); if (userExtras != null) { data.putAll(userExtras); } data.putInt(prefix + BundleProtocol.PACKED_PARAM_LIFETIME, jobParameters.getLifetime()); data.putBoolean(prefix + BundleProtocol.PACKED_PARAM_RECURRING, jobParameters.isRecurring()); data.putBoolean( prefix + BundleProtocol.PACKED_PARAM_REPLACE_CURRENT, jobParameters.shouldReplaceCurrent()); data.putString(prefix + BundleProtocol.PACKED_PARAM_TAG, jobParameters.getTag()); data.putString(prefix + BundleProtocol.PACKED_PARAM_SERVICE, jobParameters.getService()); data.putInt( prefix + BundleProtocol.PACKED_PARAM_CONSTRAINTS, compact(jobParameters.getConstraints())); encodeTrigger(jobParameters.getTrigger(), data); encodeRetryStrategy(jobParameters.getRetryStrategy(), data); return data; }
@WorkerThread private void handleStopJobRequestImpl(final JobParameters job, final boolean needToSendResult) { synchronized (runningJobs) { JobCallback jobCallback = runningJobs.remove(job.getTag()); if (jobCallback == null) { if (Log.isLoggable(TAG, Log.DEBUG)) { Log.d(TAG, "Provided job has already been executed."); } return; } // onStopJob needs to be called on the main thread mainHandler.post( UnitOfWork.callOnStopJob( this, jobCallback, /* needToSendResult= */ needToSendResult, /* terminatingResult= */ RESULT_SUCCESS)); } }
@Override public Void call() { try { InstanceID instanceID = InstanceID.getInstance(getApplicationContext()); String senderId = job.getExtras().getString(KEY_GCM_SENDER_ID); String token = instanceID.getToken(senderId, GoogleCloudMessaging.INSTANCE_ID_SCOPE, null); ParseInstallation installation = ParseInstallation.getCurrentInstallation(); installation.setDeviceToken(token); //even though this is FCM, calling it gcm will work on the backend installation.setPushType(PUSH_TYPE); installation.save(); PLog.d(ParseGCM.TAG, "GCM registration success"); } catch (Exception e) { PLog.e(ParseGCM.TAG, "GCM registration failed", e); jobFinished(job, true); } return null; } });