| 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..cf86dda2bc0c4cb72d8e0c89dc4cbd902943057e
|
| --- /dev/null
|
| +++ b/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerJobService.java
|
| @@ -0,0 +1,159 @@
|
| +// 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
|
| + * one of the keys. Only values valid for {@link android.os.BaseBundle} are supported, and other
|
| + * values are stripped at the time when the task is scheduled.
|
| + *
|
| + * @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();
|
| + if (!BackgroundTaskScheduler.hasParameterlessPublicConstructor(
|
| + taskInfo.getBackgroundTaskClass())) {
|
| + Log.e(TAG, "BackgroundTask " + taskInfo.getBackgroundTaskClass()
|
| + + " has no parameterless public constructor.");
|
| + return false;
|
| + }
|
| +
|
| + 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);
|
| + }
|
| +}
|
|
|