Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(32)

Unified Diff: components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerGcmNetworkManager.java

Issue 2779753002: [Android] Adding scheduling through GcmNetworkManager (Closed)
Patch Set: Ensuring task is called on UI thread Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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);
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698