Index: components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskGcmTaskService.java |
diff --git a/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskGcmTaskService.java b/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskGcmTaskService.java |
new file mode 100644 |
index 0000000000000000000000000000000000000000..2e9a425f19425f7da2c5b8f25cf0e721b9738d0e |
--- /dev/null |
+++ b/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskGcmTaskService.java |
@@ -0,0 +1,128 @@ |
+// 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 com.google.android.gms.gcm.GcmNetworkManager; |
+import com.google.android.gms.gcm.GcmTaskService; |
+import com.google.android.gms.gcm.TaskParams; |
+ |
+import org.chromium.base.ContextUtils; |
+import org.chromium.base.Log; |
+import org.chromium.base.ThreadUtils; |
+ |
+import java.util.concurrent.CountDownLatch; |
+import java.util.concurrent.TimeUnit; |
+import java.util.concurrent.atomic.AtomicBoolean; |
+ |
+/** Delegates calls out to various tasks that need to run in the background. */ |
+public class BackgroundTaskGcmTaskService extends GcmTaskService { |
+ private static final String TAG = "BkgrdTaskGcmTS"; |
+ |
+ /** Class that waits for the processing to be done. */ |
+ private static class Waiter { |
+ // Wakelock is only held for 3 minutes by default for GcmTaskService. |
+ private static final long MAX_TIMEOUT_SECONDS = 179; |
+ private final CountDownLatch mLatch; |
+ private long mWaiterTimeoutSeconds; |
+ private boolean mIsRescheduleNeeded; |
+ private boolean mHasTaskTimedOut; |
+ |
+ public Waiter(long waiterTimeoutSeconds) { |
+ mLatch = new CountDownLatch(1); |
+ mWaiterTimeoutSeconds = Math.min(waiterTimeoutSeconds, MAX_TIMEOUT_SECONDS); |
+ } |
+ |
+ /** Start waiting for the processing to finish. */ |
+ public void startWaiting() { |
+ try { |
+ mHasTaskTimedOut = !mLatch.await(mWaiterTimeoutSeconds, TimeUnit.SECONDS); |
+ } catch (InterruptedException e) { |
+ Log.d(TAG, "Waiter interrupted while waiting."); |
+ } |
+ } |
+ |
+ /** Called to finish waiting. */ |
+ public void onWaitDone(boolean needsRescheduling) { |
+ mIsRescheduleNeeded = needsRescheduling; |
+ mLatch.countDown(); |
+ } |
+ |
+ /** @return Whether last task timed out. */ |
+ public boolean hasTaskTimedOut() { |
+ return mHasTaskTimedOut; |
+ } |
+ |
+ /** @return Whether task needs to be rescheduled. */ |
+ public boolean isRescheduleNeeded() { |
+ return mIsRescheduleNeeded; |
+ } |
+ } |
+ |
+ private static class TaskFinishedCallbackGcmTaskService |
+ implements BackgroundTask.TaskFinishedCallback { |
+ private final Waiter mWaiter; |
+ |
+ public TaskFinishedCallbackGcmTaskService(Waiter waiter) { |
+ mWaiter = waiter; |
+ } |
+ |
+ @Override |
+ public void taskFinished(final boolean needsReschedule) { |
+ ThreadUtils.runOnUiThreadBlocking(new Runnable() { |
+ @Override |
+ public void run() { |
+ mWaiter.onWaitDone(needsReschedule); |
+ } |
+ }); |
+ } |
+ } |
+ |
+ @Override |
+ public int onRunTask(TaskParams params) { |
+ final BackgroundTask backgroundTask = |
+ BackgroundTaskSchedulerGcmNetworkManager.getBackgroundTaskFromTaskParams(params); |
+ if (backgroundTask == null) { |
+ Log.w(TAG, "Failed to start task. Could not instantiate class."); |
+ return GcmNetworkManager.RESULT_FAILURE; |
+ } |
+ |
+ final TaskParameters taskParams = |
+ BackgroundTaskSchedulerGcmNetworkManager.getTaskParametersFromTaskParams(params); |
+ final Waiter waiter = new Waiter(Waiter.MAX_TIMEOUT_SECONDS); |
+ |
+ final AtomicBoolean taskNeedsBackgroundProcessing = new AtomicBoolean(); |
+ ThreadUtils.runOnUiThreadBlocking(new Runnable() { |
+ @Override |
+ public void run() { |
+ taskNeedsBackgroundProcessing.set( |
+ backgroundTask.onStartTask(ContextUtils.getApplicationContext(), taskParams, |
+ new TaskFinishedCallbackGcmTaskService(waiter))); |
+ } |
+ }); |
+ |
+ if (!taskNeedsBackgroundProcessing.get()) return GcmNetworkManager.RESULT_SUCCESS; |
+ |
+ waiter.startWaiting(); |
+ |
+ if (waiter.isRescheduleNeeded()) return GcmNetworkManager.RESULT_RESCHEDULE; |
+ if (!waiter.hasTaskTimedOut()) return GcmNetworkManager.RESULT_SUCCESS; |
+ |
+ final AtomicBoolean taskNeedsRescheduling = new AtomicBoolean(); |
+ ThreadUtils.runOnUiThreadBlocking(new Runnable() { |
+ @Override |
+ public void run() { |
+ taskNeedsRescheduling.set(backgroundTask.onStopTask( |
+ ContextUtils.getApplicationContext(), taskParams)); |
+ } |
+ }); |
+ |
+ if (taskNeedsRescheduling.get()) return GcmNetworkManager.RESULT_RESCHEDULE; |
+ |
+ return GcmNetworkManager.RESULT_SUCCESS; |
+ } |
+ |
+ @Override |
+ public void onInitializeTasks() {} |
+} |