Chromium Code Reviews| 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..a065668ba2e2996a081988a74d63b362e9b01f40 |
| --- /dev/null |
| +++ b/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerGcmNetworkManager.java |
| @@ -0,0 +1,184 @@ |
| +// 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) |
| + // TODO(fgorski): Check what is the default for JobScheduler. TaskInfo may need to |
|
fgorski
2017/04/11 19:42:11
This is about how we have the defaults set...
We m
nyquist
2017/04/18 21:58:28
Yeah, would be great to look into this before we a
fgorski
2017/04/20 05:54:15
JobInfo or Builder documentation does not mention
nyquist
2017/04/25 20:44:15
sgtm
|
| + // be fixed. |
| + .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); |
| + } |
| +} |