1 # Quick Start Guide to using BackgroundTaskScheduler
5 This document describes how to schedule a background task in Android using
6 BackgroundTaskScheduler API. Although most of the examples are described in
7 Java, the exact same API is available in C++ as well.
11 In Android it is encouraged to use `JobScheduler` for all background jobs,
12 instead of using things like `IntentService` or polling using alarms. Using the
13 system API is beneficial as it has a full view of what goes on in the system and
14 can schedule jobs accordingly.
16 The `background_task_scheduler` component provides a framework for use within
17 Chromium to schedule and execute background jobs using the system API. The
18 API of the framework is similar to that of the Android `JobScheduler`.
22 A task is defined as a class that implements the `BackgroundTask` interface,
23 which looks like this:
26 interface BackgroundTask {
27 interface TaskFinishedCallback {
28 void taskFinished(boolean needsReschedule);
31 boolean onStartTask(Context context,
32 TaskParameters taskParameters,
33 TaskFinishedCallback callback);
34 boolean onStopTask(Context context,
35 TaskParameters taskParameters);
39 **Any class implementing this interface must have a public constructor which takes
42 A task must also have a unique ID, and it must be listed in `TaskIds` to ensure
43 there is no overlap between different tasks.
45 The connection between `TaskIds` and the corresponding `BackgroundTask` classes is done by injecting
46 a `BackgroundTaskFactory` class in `BackgroundTaskSchedulerFactory`. For the //chrome embedder
47 (which is the only one needing the association), the `ChromeBackgroundTaskFactory` [implementation]
48 (https://cs.chromium.org/chromium/src/chrome/android/java/src/org/chromium/chrome/browser
49 /background_task_scheduler/ChromeBackgroundTaskFactory.java) was created. Anyone that adds a new
50 task id to `TaskIds` should add a case in this class to.
52 ## How to schedule a task
54 A task is scheduled by creating an object containing information about the task,
55 such as when to run it, whether it requires battery, and other similar
56 constraints. This object is called `TaskInfo` and has a builder you can use
57 to set all the relevant fields.
59 There are three main types of tasks; one-off tasks, periodic tasks, and exact timing info tasks. One-off
60 tasks are only executed once, whereas periodic tasks are executed once per
61 a defined interval. The exact info tasks are triggered at the exact scheduled time.
63 There are two steps in the process of creating a TaskInfo:
65 1. the specific timing info is created; there are three objects available - `OneOffInfo`,
66 `PeriodicInfo`, and `ExactInfo`; each one of these objects has its own builder;
67 2. the task info is created using the `createTask` method; other parameters can be set afterwards.
69 As an example for how to create a one-off task that executes in 200 minutes,
70 you can do the following:
73 TaskInfo.TimingInfo oneOffInfo = TaskInfo.OneOffInfo.create()
74 .setWindowEndTimeMs(TimeUnit.MINUTES.toMillis(200)).build();
75 TaskInfo taskInfo = TaskInfo.createTask(TaskIds.YOUR_FEATURE,
79 For a periodic task that executes every 200 minutes, you can call:
82 TaskInfo.TimingInfo periodicInfo = TaskInfo.PeriodicInfo.create()
83 .setIntervalMs(TimeUnit.MINUTES.toMillis(200)).build();
84 TaskInfo taskInfo = TaskInfo.createTask(TaskIds.YOUR_FEATURE,
85 periodicInfo).build();
88 Typically you will also set other required parameters such as what type of
89 network conditions are necessary and whether the task requires the device to
90 be charging. They can be set on the builder like this:
93 TaskInfo.TimingInfo oneOffInfo = TaskInfo.OneOffInfo.create()
94 .setWindowStartTimeMs(TimeUnit.MINUTES.toMillis(100))
95 .setWindowEndTimeMs(TimeUnit.MINUTES.toMillis(200)).build();
96 TaskInfo taskInfo = TaskInfo.createTask(TaskIds.YOUR_FEATURE,
98 .setRequiresCharging(true)
99 .setRequiredNetworkType(
100 TaskInfo.NETWORK_TYPE_UNMETERED)
104 Note that the task will be run after `windowEndTimeMs` regardless of whether the
105 prerequisite conditions are met. To work around this, mark the `windowEndTimeMs`
106 to `Integer.MAX_VALUE`.
108 When the task is ready for scheduling, you use the
109 `BackgroundTaskSchedulerFactory` to get the current instance of the
110 `BackgroundTaskScheduler` and use it to schedule the job.
113 BackgroundTaskSchedulerFactory.getScheduler().schedule(myTaskInfo);
116 If you ever need to cancel a task, you can do that by calling `cancel`, and
117 passing in the task ID:
120 BackgroundTaskSchedulerFactory.getScheduler().cancel(TaskIds.YOUR_FEATURE);
123 ## Passing task arguments
125 A `TaskInfo` supports passing in arguments through a `Bundle`, but only values
126 that can be part of an Android `BaseBundle` are allowed. You can pass them in
127 using the `TaskInfo.Builder`:
130 Bundle myBundle = new Bundle();
131 myBundle.putString("foo", "bar");
132 myBundle.putLong("number", 1337L);
134 TaskInfo.TimingInfo oneOffInfo = TaskInfo.OneOffInfo.create()
135 .setWindowStartTimeMs(TimeUnit.MINUTES.toMillis(100))
136 .setWindowEndTimeMs(TimeUnit.MINUTES.toMillis(200)).build();
137 TaskInfo taskInfo = TaskInfo.createTask(TaskIds.YOUR_FEATURE,
143 These arguments will be readable for the task through the `TaskParameters`
144 object that is passed to both `onStartTask(...)` and `onStopTask(...)`, by
148 boolean onStartTask(Context context,
149 TaskParameters taskParameters,
150 TaskFinishedCallback callback) {
151 Bundle myExtras = taskParameters.getExtras();
156 For native tasks, the extras are packed into a std::string, It's the caller's
157 responsibility to pack and unpack the task extras correctly into the std::string.
158 We recommend using a proto for consistency.
160 ## Performing actions over TimingInfo objects
162 To perform actions over the `TimingInfo` objects, based on their implementation, the Visitor design
163 pattern was used. A public interface is exposed for this: `TimingInfoVisitor`. To use this
164 interface, someone should create a class that would look like this:
167 class ImplementedActionVisitor implements TaskInfo.TimingInfoVisitor {
169 public void visit(TaskInfo.OneOffInfo oneOffInfo) { ... }
172 public void visit(TaskInfo.PeriodicInfo periodicInfo) { ... }
176 To use this visitor, someone would make the following calls:
179 ImplementedActionVisitor visitor = new ImplementedActionVisitor();
180 myTimingInfo.accept(visitor);
183 ## Loading Native parts
185 Some of the tasks running in the background require native parts of the browser
186 to be initialized. In order to simplify implementation of such tasks, we provide
187 a base `NativeBackgroundTask`
188 [implementation](https://cs.chromium.org/chromium/src/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/NativeBackgroundTask.java)
189 in the browser layer. It requires extending classes to implement 4 methods:
191 * `onStartTaskBeforeNativeLoaded(...)` where the background task can decide
192 whether conditions are correct to proceed with native initialization;
193 * `onStartTaskWithNative(...)` where the background task can be sure that
194 native initialization was completed, therefore it can depend on that part of
196 * `onStopTaskBeforeNativeLoaded(...)` which is delivered to the background task
197 just like `onStopTask(...)` and the native parts of the browser are not
199 * `onStopTaskWithNative(...)` which is delivered to the background task just
200 like `onStopTask(...)` and the native parts of the browser are loaded.
202 While in a normal execution, both `onStart...` methods are called, only one of
203 the stopping methods will be triggered, depending on whether the native parts of
204 the browser are loaded at the time the underlying scheduler decides to stop the
207 ## Launching Browser process
209 After the advent of servicfication in chrome, we have the option of launching a
210 background task in a reduced service manager only mode without the need to
211 launch the full browser process. In order to enable this, you have to override
212 `NativeBackgroundTask#supportsMinimalBrowser` and return true or false
213 depending on whether you want to launch service-manager only mode or full
216 ## Background processing
218 Even though the `BackgroundTaskScheduler` provides functionality for invoking
219 code while the application is in the background, the `BackgroundTask` instance
220 is still invoked on the application's main thread.
222 This means that unless the operation is extremely quick, processing must happen
223 asynchronously, and the call to `onStartTask*(...)` must return before the task
224 has finished processing. In that case, the method should return once the
225 asychronous processing has begun, and invoke the `TaskFinishedCallback` when the
226 processing is finished, which typically happens on a different `Thread`,
227 `Handler`, or by using an `AsyncTask`.
229 If at any time the constraints given through the `TaskInfo` object do not hold
230 anymore, or if the system deems it necessary, `onStopTask*(...)` will be
231 invoked, requiring all activity to cease immediately. The task can return true
232 if the task needs to be rescheduled since it was canceled, or false otherwise.
233 Note that onStopTask*() is not invoked if the task itself invokes
234 `TaskFinishedCallback` or if the task is cancelled by the caller.
236 **The system will hold a wakelock from the time
237 `onStartTaskBeforeNativeLoaded(...)` is invoked until either the task itself
238 invokes the `TaskFinishedCallback`, or `onStopTask*(...)` is invoked.**