| Index: components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerGcmNetworkManager.java
|
| diff --git a/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerGcmNetworkManager.java b/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerGcmNetworkManager.java
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..bcc46bcc722254486ae96e8bdc9960092d6663fb
|
| --- /dev/null
|
| +++ b/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerGcmNetworkManager.java
|
| @@ -0,0 +1,182 @@
|
| +// 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.content.Context;
|
| +import android.os.Bundle;
|
| +import android.support.annotation.NonNull;
|
| +
|
| +import com.google.android.gms.common.ConnectionResult;
|
| +import com.google.android.gms.common.GoogleApiAvailability;
|
| +import com.google.android.gms.gcm.GcmNetworkManager;
|
| +import com.google.android.gms.gcm.OneoffTask;
|
| +import com.google.android.gms.gcm.PeriodicTask;
|
| +import com.google.android.gms.gcm.Task;
|
| +import com.google.android.gms.gcm.TaskParams;
|
| +
|
| +import org.chromium.base.Log;
|
| +import org.chromium.base.ThreadUtils;
|
| +import org.chromium.base.VisibleForTesting;
|
| +
|
| +import java.util.concurrent.TimeUnit;
|
| +
|
| +/**
|
| + * An implementation of {@link BackgroundTaskSchedulerDelegate} that uses the Play Services
|
| + * {@link GcmNetworkManager} to schedule jobs.
|
| + */
|
| +class BackgroundTaskSchedulerGcmNetworkManager implements BackgroundTaskSchedulerDelegate {
|
| + private static final String TAG = "BkgrdTaskSchedGcmNM";
|
| +
|
| + @VisibleForTesting
|
| + static final String BACKGROUND_TASK_CLASS_KEY = "_background_task_class";
|
| + @VisibleForTesting
|
| + static final String BACKGROUND_TASK_EXTRAS_KEY = "_background_task_extras";
|
| +
|
| + static BackgroundTask getBackgroundTaskFromTaskParams(@NonNull TaskParams taskParams) {
|
| + String backgroundTaskClassName = getBackgroundTaskClassFromTaskParams(taskParams);
|
| + return BackgroundTaskScheduler.getBackgroundTaskFromClassName(backgroundTaskClassName);
|
| + }
|
| +
|
| + private static String getBackgroundTaskClassFromTaskParams(@NonNull TaskParams taskParams) {
|
| + Bundle extras = taskParams.getExtras();
|
| + if (extras == null) return null;
|
| + return extras.getString(BACKGROUND_TASK_CLASS_KEY);
|
| + }
|
| +
|
| + /**
|
| + * Retrieves the {@link TaskParameters} from the {@link TaskParams}, 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 taskParams the {@link TaskParams} to extract the {@link TaskParameters} from.
|
| + * @return the {@link TaskParameters} for the current job.
|
| + */
|
| + static TaskParameters getTaskParametersFromTaskParams(@NonNull TaskParams taskParams) {
|
| + int taskId;
|
| + try {
|
| + taskId = Integer.parseInt(taskParams.getTag());
|
| + } catch (NumberFormatException e) {
|
| + Log.e(TAG, "Cound not parse task ID from task tag: " + taskParams.getTag());
|
| + return null;
|
| + }
|
| +
|
| + TaskParameters.Builder builder = TaskParameters.create(taskId);
|
| +
|
| + Bundle extras = taskParams.getExtras();
|
| + Bundle taskExtras = extras.getBundle(BACKGROUND_TASK_EXTRAS_KEY);
|
| + builder.addExtras(taskExtras);
|
| +
|
| + return builder.build();
|
| + }
|
| +
|
| + @VisibleForTesting
|
| + static Task createTaskFromTaskInfo(@NonNull TaskInfo taskInfo) {
|
| + Bundle taskExtras = new Bundle();
|
| + taskExtras.putString(
|
| + BACKGROUND_TASK_CLASS_KEY, taskInfo.getBackgroundTaskClass().getName());
|
| + taskExtras.putBundle(BACKGROUND_TASK_EXTRAS_KEY, taskInfo.getExtras());
|
| +
|
| + Task.Builder builder;
|
| + if (taskInfo.isPeriodic()) {
|
| + builder = getPeriodicTaskBuilder(taskInfo.getPeriodicInfo());
|
| + } else {
|
| + builder = getOneOffTaskBuilder(taskInfo.getOneOffInfo());
|
| + }
|
| +
|
| + builder.setExtras(taskExtras)
|
| + .setPersisted(taskInfo.isPersisted())
|
| + .setRequiredNetwork(getGcmNetworkManagerNetworkTypeFromTypeFromTaskNetworkType(
|
| + taskInfo.getRequiredNetworkType()))
|
| + .setRequiresCharging(taskInfo.requiresCharging())
|
| + .setService(BackgroundTaskGcmTaskService.class)
|
| + .setTag(taskIdToTaskTag(taskInfo.getTaskId()))
|
| + .setUpdateCurrent(taskInfo.shouldUpdateCurrent());
|
| +
|
| + return builder.build();
|
| + }
|
| +
|
| + private static Task.Builder getPeriodicTaskBuilder(TaskInfo.PeriodicInfo periodicInfo) {
|
| + PeriodicTask.Builder builder = new PeriodicTask.Builder();
|
| + builder.setPeriod(TimeUnit.MILLISECONDS.toSeconds(periodicInfo.getIntervalMs()));
|
| + if (periodicInfo.hasFlex()) {
|
| + builder.setFlex(TimeUnit.MILLISECONDS.toSeconds(periodicInfo.getFlexMs()));
|
| + }
|
| + return builder;
|
| + }
|
| +
|
| + private static Task.Builder getOneOffTaskBuilder(TaskInfo.OneOffInfo oneOffInfo) {
|
| + OneoffTask.Builder builder = new OneoffTask.Builder();
|
| + long windowStartSeconds = oneOffInfo.hasWindowStartTimeConstraint()
|
| + ? TimeUnit.MILLISECONDS.toSeconds(oneOffInfo.getWindowStartTimeMs())
|
| + : 0;
|
| + builder.setExecutionWindow(windowStartSeconds,
|
| + TimeUnit.MILLISECONDS.toSeconds(oneOffInfo.getWindowEndTimeMs()));
|
| + return builder;
|
| + }
|
| +
|
| + private static int getGcmNetworkManagerNetworkTypeFromTypeFromTaskNetworkType(
|
| + @TaskInfo.NetworkType int networkType) {
|
| + switch (networkType) {
|
| + // This is correct: GcmNM ANY means no network is guaranteed.
|
| + case TaskInfo.NETWORK_TYPE_NONE:
|
| + return Task.NETWORK_STATE_ANY;
|
| + case TaskInfo.NETWORK_TYPE_ANY:
|
| + return Task.NETWORK_STATE_CONNECTED;
|
| + case TaskInfo.NETWORK_TYPE_UNMETERED:
|
| + return Task.NETWORK_STATE_UNMETERED;
|
| + default:
|
| + assert false;
|
| + }
|
| + return Task.NETWORK_STATE_ANY;
|
| + }
|
| +
|
| + @Override
|
| + public boolean schedule(Context context, @NonNull TaskInfo taskInfo) {
|
| + ThreadUtils.assertOnUiThread();
|
| + if (!BackgroundTaskScheduler.hasParameterlessPublicConstructor(
|
| + taskInfo.getBackgroundTaskClass())) {
|
| + Log.e(TAG,
|
| + "BackgroundTask " + taskInfo.getBackgroundTaskClass()
|
| + + " has no parameterless public constructor.");
|
| + return false;
|
| + }
|
| +
|
| + GcmNetworkManager gcmNetworkManager = getGcmNetworkManager(context);
|
| + if (gcmNetworkManager == null) {
|
| + Log.e(TAG, "GcmNetworkManager is not available.");
|
| + return false;
|
| + }
|
| +
|
| + Task task = createTaskFromTaskInfo(taskInfo);
|
| +
|
| + gcmNetworkManager.schedule(task);
|
| + return true;
|
| + }
|
| +
|
| + @Override
|
| + public void cancel(Context context, int taskId) {
|
| + ThreadUtils.assertOnUiThread();
|
| +
|
| + GcmNetworkManager gcmNetworkManager = getGcmNetworkManager(context);
|
| + if (gcmNetworkManager == null) {
|
| + Log.e(TAG, "GcmNetworkManager is not available.");
|
| + return;
|
| + }
|
| +
|
| + gcmNetworkManager.cancelTask(taskIdToTaskTag(taskId), BackgroundTaskGcmTaskService.class);
|
| + }
|
| +
|
| + private GcmNetworkManager getGcmNetworkManager(Context context) {
|
| + if (GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(context)
|
| + == ConnectionResult.SUCCESS) {
|
| + return GcmNetworkManager.getInstance(context);
|
| + }
|
| + return null;
|
| + }
|
| +
|
| + private static String taskIdToTaskTag(int taskId) {
|
| + return Integer.toString(taskId);
|
| + }
|
| +}
|
|
|