Chromium Code Reviews| Index: components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerJobService.java |
| diff --git a/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerJobService.java b/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerJobService.java |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..4fc2b8f49d61d963c632d301ded8da2148d2fa59 |
| --- /dev/null |
| +++ b/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerJobService.java |
| @@ -0,0 +1,151 @@ |
| +// Copyright 2017 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +package org.chromium.components.background_task_scheduler; |
| + |
| +import android.annotation.TargetApi; |
| +import android.app.job.JobInfo; |
| +import android.app.job.JobParameters; |
| +import android.app.job.JobScheduler; |
| +import android.content.ComponentName; |
| +import android.content.Context; |
| +import android.os.Build; |
| +import android.os.Bundle; |
| +import android.os.PersistableBundle; |
| + |
| +import org.chromium.base.Log; |
| +import org.chromium.base.ThreadUtils; |
| +import org.chromium.base.VisibleForTesting; |
| + |
| +/** |
| + * An implementation of {@link BackgroundTaskSchedulerDelegate} that uses the system |
| + * {@link JobScheduler} to schedule jobs. |
| + */ |
| +@TargetApi(Build.VERSION_CODES.LOLLIPOP_MR1) |
| +class BackgroundTaskSchedulerJobService implements BackgroundTaskSchedulerDelegate { |
| + private static final String TAG = "BkgrdTaskSchedulerJS"; |
| + |
| + private static final String BACKGROUND_TASK_CLASS_KEY = "_background_task_class"; |
| + @VisibleForTesting |
| + static final String BACKGROUND_TASK_EXTRAS_KEY = "_background_task_extras"; |
| + |
| + static BackgroundTask getBackgroundTaskFromJobParameters(JobParameters jobParameters) { |
| + String backgroundTaskClassName = getBackgroundTaskClassFromJobParameters(jobParameters); |
| + return BackgroundTaskScheduler.getBackgroundTaskFromClassName(backgroundTaskClassName); |
| + } |
| + |
| + private static String getBackgroundTaskClassFromJobParameters(JobParameters jobParameters) { |
| + PersistableBundle extras = jobParameters.getExtras(); |
| + if (extras == null) return null; |
| + return extras.getString(BACKGROUND_TASK_CLASS_KEY); |
| + } |
| + |
| + /** |
| + * Retrieves the {@link TaskParameters} from the {@link JobParameters}, which are passed as |
|
David Trainor- moved to gerrit
2017/02/24 07:19:49
Mention that only persistable data is transmitted
nyquist
2017/02/24 23:41:12
Done.
|
| + * one of the keys. |
| + * |
| + * @param jobParameters the {@link JobParameters} to extract the {@link TaskParameters} from. |
| + * @return the {@link TaskParameters} for the current job. |
| + */ |
| + static TaskParameters getTaskParametersFromJobParameters(JobParameters jobParameters) { |
| + TaskParameters.Builder builder = TaskParameters.create(jobParameters.getJobId()); |
| + |
| + PersistableBundle jobExtras = jobParameters.getExtras(); |
| + PersistableBundle persistableTaskExtras = |
| + jobExtras.getPersistableBundle(BACKGROUND_TASK_EXTRAS_KEY); |
| + |
| + Bundle taskExtras = new Bundle(); |
| + taskExtras.putAll(persistableTaskExtras); |
| + builder.addExtras(taskExtras); |
| + |
| + return builder.build(); |
| + } |
| + |
| + @VisibleForTesting |
| + static JobInfo createJobInfoFromTaskInfo(Context context, TaskInfo taskInfo) { |
| + PersistableBundle jobExtras = new PersistableBundle(); |
| + jobExtras.putString(BACKGROUND_TASK_CLASS_KEY, taskInfo.getBackgroundTaskClass().getName()); |
| + |
| + PersistableBundle persistableBundle = getTaskExtrasAsPersistableBundle(taskInfo); |
| + jobExtras.putPersistableBundle(BACKGROUND_TASK_EXTRAS_KEY, persistableBundle); |
| + |
| + JobInfo.Builder builder = |
| + new JobInfo |
| + .Builder(taskInfo.getTaskId(), |
| + new ComponentName(context, BackgroundTaskJobService.class)) |
| + .setExtras(jobExtras) |
| + .setPersisted(taskInfo.isPersisted()) |
| + .setRequiresCharging(taskInfo.requiresCharging()) |
| + .setRequiredNetworkType(getJobInfoNetworkTypeFromTaskNetworkType( |
| + taskInfo.getRequiredNetworkType())); |
| + |
| + if (taskInfo.isPeriodic()) { |
| + builder = getPeriodicJobInfo(builder, taskInfo); |
| + } else { |
| + builder = getOneOffJobInfo(builder, taskInfo); |
| + } |
| + |
| + return builder.build(); |
| + } |
| + |
| + private static JobInfo.Builder getOneOffJobInfo(JobInfo.Builder builder, TaskInfo taskInfo) { |
| + TaskInfo.OneOffInfo oneOffInfo = taskInfo.getOneOffInfo(); |
| + if (oneOffInfo.hasWindowStartTimeConstraint()) { |
| + builder = builder.setMinimumLatency(oneOffInfo.getWindowStartTimeMs()); |
| + } |
| + return builder.setOverrideDeadline(oneOffInfo.getWindowEndTimeMs()); |
| + } |
| + |
| + private static JobInfo.Builder getPeriodicJobInfo(JobInfo.Builder builder, TaskInfo taskInfo) { |
| + TaskInfo.PeriodicInfo periodicInfo = taskInfo.getPeriodicInfo(); |
| + if (periodicInfo.hasFlex()) { |
| + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { |
| + return builder.setPeriodic(periodicInfo.getIntervalMs(), periodicInfo.getFlexMs()); |
| + } |
| + return builder.setPeriodic(periodicInfo.getIntervalMs()); |
| + } |
| + return builder.setPeriodic(periodicInfo.getIntervalMs()); |
| + } |
| + |
| + private static int getJobInfoNetworkTypeFromTaskNetworkType( |
| + @TaskInfo.NetworkType int networkType) { |
| + // The values are hard coded to represent the same as the network type from JobService. |
| + return networkType; |
| + } |
| + |
| + private static PersistableBundle getTaskExtrasAsPersistableBundle(TaskInfo taskInfo) { |
| + Bundle taskExtras = taskInfo.getExtras(); |
| + BundleToPersistableBundleConverter.Result convertedData = |
| + BundleToPersistableBundleConverter.convert(taskExtras); |
| + if (convertedData.hasErrors()) { |
| + Log.w(TAG, "Failed converting extras to PersistableBundle: " |
| + + convertedData.getFailedKeysErrorString()); |
| + } |
| + return convertedData.getPersistableBundle(); |
| + } |
| + |
| + @Override |
| + public boolean schedule(Context context, TaskInfo taskInfo) { |
| + ThreadUtils.assertOnUiThread(); |
| + JobInfo jobInfo = createJobInfoFromTaskInfo(context, taskInfo); |
| + |
| + JobScheduler jobScheduler = |
| + (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE); |
| + |
| + if (taskInfo.shouldUpdateCurrent()) { |
| + jobScheduler.cancel(taskInfo.getTaskId()); |
| + } |
| + |
| + int result = jobScheduler.schedule(jobInfo); |
| + return result == JobScheduler.RESULT_SUCCESS; |
| + } |
| + |
| + @Override |
| + public void cancel(Context context, int taskId) { |
| + ThreadUtils.assertOnUiThread(); |
| + JobScheduler jobScheduler = |
| + (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE); |
| + jobScheduler.cancel(taskId); |
| + } |
| +} |