OLD | NEW |
(Empty) | |
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 package org.chromium.components.background_task_scheduler; |
| 6 |
| 7 import com.google.android.gms.gcm.GcmNetworkManager; |
| 8 import com.google.android.gms.gcm.GcmTaskService; |
| 9 import com.google.android.gms.gcm.TaskParams; |
| 10 |
| 11 import org.chromium.base.ContextUtils; |
| 12 import org.chromium.base.Log; |
| 13 import org.chromium.base.ThreadUtils; |
| 14 |
| 15 import java.util.concurrent.CountDownLatch; |
| 16 import java.util.concurrent.TimeUnit; |
| 17 import java.util.concurrent.atomic.AtomicBoolean; |
| 18 |
| 19 /** Delegates calls out to various tasks that need to run in the background. */ |
| 20 public class BackgroundTaskGcmTaskService extends GcmTaskService { |
| 21 private static final String TAG = "BkgrdTaskGcmTS"; |
| 22 |
| 23 /** Class that waits for the processing to be done. */ |
| 24 private static class Waiter { |
| 25 // Wakelock is only held for 3 minutes by default for GcmTaskService. |
| 26 private static final long MAX_TIMEOUT_SECONDS = 179; |
| 27 private final CountDownLatch mLatch; |
| 28 private long mWaiterTimeoutSeconds; |
| 29 private boolean mIsRescheduleNeeded; |
| 30 private boolean mHasTaskTimedOut; |
| 31 |
| 32 public Waiter(long waiterTimeoutSeconds) { |
| 33 mLatch = new CountDownLatch(1); |
| 34 mWaiterTimeoutSeconds = Math.min(waiterTimeoutSeconds, MAX_TIMEOUT_S
ECONDS); |
| 35 } |
| 36 |
| 37 /** Start waiting for the processing to finish. */ |
| 38 public void startWaiting() { |
| 39 try { |
| 40 mHasTaskTimedOut = !mLatch.await(mWaiterTimeoutSeconds, TimeUnit
.SECONDS); |
| 41 } catch (InterruptedException e) { |
| 42 Log.d(TAG, "Waiter interrupted while waiting."); |
| 43 } |
| 44 } |
| 45 |
| 46 /** Called to finish waiting. */ |
| 47 public void onWaitDone(boolean needsRescheduling) { |
| 48 mIsRescheduleNeeded = needsRescheduling; |
| 49 mLatch.countDown(); |
| 50 } |
| 51 |
| 52 /** @return Whether last task timed out. */ |
| 53 public boolean hasTaskTimedOut() { |
| 54 return mHasTaskTimedOut; |
| 55 } |
| 56 |
| 57 /** @return Whether task needs to be rescheduled. */ |
| 58 public boolean isRescheduleNeeded() { |
| 59 return mIsRescheduleNeeded; |
| 60 } |
| 61 } |
| 62 |
| 63 private static class TaskFinishedCallbackGcmTaskService |
| 64 implements BackgroundTask.TaskFinishedCallback { |
| 65 private final Waiter mWaiter; |
| 66 |
| 67 public TaskFinishedCallbackGcmTaskService(Waiter waiter) { |
| 68 mWaiter = waiter; |
| 69 } |
| 70 |
| 71 @Override |
| 72 public void taskFinished(final boolean needsReschedule) { |
| 73 ThreadUtils.runOnUiThreadBlocking(new Runnable() { |
| 74 @Override |
| 75 public void run() { |
| 76 mWaiter.onWaitDone(needsReschedule); |
| 77 } |
| 78 }); |
| 79 } |
| 80 } |
| 81 |
| 82 @Override |
| 83 public int onRunTask(TaskParams params) { |
| 84 final BackgroundTask backgroundTask = |
| 85 BackgroundTaskSchedulerGcmNetworkManager.getBackgroundTaskFromTa
skParams(params); |
| 86 if (backgroundTask == null) { |
| 87 Log.w(TAG, "Failed to start task. Could not instantiate class."); |
| 88 return GcmNetworkManager.RESULT_FAILURE; |
| 89 } |
| 90 |
| 91 final TaskParameters taskParams = |
| 92 BackgroundTaskSchedulerGcmNetworkManager.getTaskParametersFromTa
skParams(params); |
| 93 final Waiter waiter = new Waiter(Waiter.MAX_TIMEOUT_SECONDS); |
| 94 |
| 95 final AtomicBoolean taskNeedsBackgroundProcessing = new AtomicBoolean(); |
| 96 ThreadUtils.runOnUiThreadBlocking(new Runnable() { |
| 97 @Override |
| 98 public void run() { |
| 99 taskNeedsBackgroundProcessing.set( |
| 100 backgroundTask.onStartTask(ContextUtils.getApplicationCo
ntext(), taskParams, |
| 101 new TaskFinishedCallbackGcmTaskService(waiter)))
; |
| 102 } |
| 103 }); |
| 104 |
| 105 if (!taskNeedsBackgroundProcessing.get()) return GcmNetworkManager.RESUL
T_SUCCESS; |
| 106 |
| 107 waiter.startWaiting(); |
| 108 |
| 109 if (waiter.isRescheduleNeeded()) return GcmNetworkManager.RESULT_RESCHED
ULE; |
| 110 if (!waiter.hasTaskTimedOut()) return GcmNetworkManager.RESULT_SUCCESS; |
| 111 |
| 112 final AtomicBoolean taskNeedsRescheduling = new AtomicBoolean(); |
| 113 ThreadUtils.runOnUiThreadBlocking(new Runnable() { |
| 114 @Override |
| 115 public void run() { |
| 116 taskNeedsRescheduling.set(backgroundTask.onStopTask( |
| 117 ContextUtils.getApplicationContext(), taskParams)); |
| 118 } |
| 119 }); |
| 120 |
| 121 if (taskNeedsRescheduling.get()) return GcmNetworkManager.RESULT_RESCHED
ULE; |
| 122 |
| 123 return GcmNetworkManager.RESULT_SUCCESS; |
| 124 } |
| 125 |
| 126 @Override |
| 127 public void onInitializeTasks() {} |
| 128 } |
OLD | NEW |