Index: components/background_task_scheduler/README.md |
diff --git a/components/background_task_scheduler/README.md b/components/background_task_scheduler/README.md |
new file mode 100644 |
index 0000000000000000000000000000000000000000..c48720d51da763635ed4f85e66309881fc9d29e1 |
--- /dev/null |
+++ b/components/background_task_scheduler/README.md |
@@ -0,0 +1,163 @@ |
+# Quick Start Guide to using BackgroundTaskScheduler |
+ |
+## Background |
+ |
+In Android M+ it is encouraged to use `JobScheduler` for all background jobs, |
+instead of using things like `IntentService` or polling using alarms. Using the |
+system API is beneficial as it has a full view of what goes on in the system and |
+can schedule jobs accordingly. |
+ |
+However, this functionality was introduced in Android L, and |
+the API has been very stable since Android M. This means that we also need a |
+similar framework for older versions of Android, which is provided by |
+Google Play services. We prefer system APIs, since they do not require including |
+external libraries which bloats the APK size of Chrome and adds unnecessary |
+complexity. The GcmNetworkManager is only used when the system API is not |
+available. |
+ |
+The `background_task_scheduler` component provides a new framework for use |
+within chromium to schedule and execute background jobs using the frameworks |
+available on a given version of Android. |
+The public API of the framework is similar to that of the Android |
+`JobScheduler`, but it is backed by either the system `JobScheduler` API or by |
+GcmNetworkManager. What service is used to back the framework remains unknown to |
+callers of the API. |
+ |
+## What is a task |
+ |
+A task is defined as a class that implements the `BackgroundTask` interface, |
+which looks like this: |
+ |
+```java |
+interface BackgroundTask { |
+ interface TaskFinishedCallback { |
+ void taskFinished(boolean needsReschedule); |
+ } |
+ |
+ boolean onStartTask(Context context, |
+ TaskParameters taskParameters, |
+ TaskFinishedCallback callback); |
+ boolean onStopTask(Context context, |
+ TaskParameters taskParameters); |
+} |
+``` |
+ |
+**Any class implementing this interface must have a public constructor which takes |
+no arguments.** |
+ |
+A task must also have a unique ID, and it must be listed in `TaskIds` to ensure |
+there is no overlap between different tasks. |
+ |
+## How to schedule a task |
+ |
+A task is scheduled by creating an object containing information about the task, |
+such as when to run it, whether it requires battery, and other similar |
+constraints. This object is called `TaskInfo` and has a builder you can use |
+to set all the relevant fields. |
+ |
+There are two main types of tasks; one-off tasks and periodic tasks. One-off |
+tasks are only executed once, whereas periodic tasks are executed once per |
+a defined interval. |
+ |
+As an example for how to create a one-off task that executes in 200 minutes, |
+you can do the following: |
+ |
+```java |
+TaskInfo.createOneOffTask(TaskIds.YOUR_FEATURE, |
+ MyBackgroundTask.class, |
+ TimeUnit.MINUTES.toMillis(200)).build(); |
+``` |
+ |
+For a periodic task that executes every 200 minutes, you can call: |
+ |
+```java |
+TaskInfo.createPeriodicTask(TaskIds.YOUR_FEATURE, |
+ MyBackgroundTask.class, |
+ TimeUnit.MINUTES.toMillis(200)).build(); |
+``` |
+ |
+Typically you will also set other required parameters such as what type of |
+network conditions are necessary and whether the task requires the device to |
+be charging. They can be set on the builder like this: |
+ |
+```java |
+TaskInfo.createOneOffTask(TaskIds.YOUR_FEATURE, |
+ MyBackgroundTask.class, |
+ TimeUnit.MINUTES.toMillis(100) |
+ TimeUnit.MINUTES.toMillis(200)) |
+ .setRequiresCharging(true) |
+ .setRequiredNetworkType(TaskInfo.NETWORK_TYPE_UNMETERED) |
+ .build(); |
+``` |
+ |
+When the task is ready for scheduling, you use the |
+`BackgroundTaskSchedulerFactory` to get the current instance of the |
+`BackgroundTaskScheduler` and use it to schedule the job. |
+ |
+```java |
+BackgroundTaskScheduleFactory.getScheduler().schedule(myTaskInfo); |
+``` |
+ |
+If you ever need to cancel a task, you can do that by calling `cancel`, and |
+passing in the task ID: |
+ |
+```java |
+BackgroundTaskScheduleFactory.getScheduler().cancel(TaskIds.YOUR_FEATURE); |
+``` |
+ |
+## Passing task arguments |
+ |
+A `TaskInfo` supports passing in arguments through a `Bundle`, but only values |
+that can be part of an Android `BaseBundle` are allowed. You can pass them in |
+using the `TaskInfo.Builder`: |
+ |
+```java |
+Bundle myBundle = new Bundle(); |
+myBundle.putString("foo", "bar"); |
+myBundle.putLong("number", 1337L); |
+ |
+TaskInfo.createOneOffTask(TaskIds.YOUR_FEATURE, |
+ MyBackgroundTask.class, |
+ TimeUnit.MINUTES.toMillis(100) |
+ TimeUnit.MINUTES.toMillis(200)) |
+ .setExtras(myBundle) |
+ .build(); |
+``` |
+ |
+These arguments will be readable for the task through the `TaskParameters` |
+object that is passed to both `onStartTask(...)` and `onStopTask(...)`, by |
+doing the following: |
+ |
+```java |
+boolean onStartTask(Context context, |
+ TaskParameters taskParameters, |
+ TaskFinishedCallback callback) { |
+ Bundle myExtras = taskParameters.getExtras(); |
+ // Use |myExtras|. |
+ ... |
+} |
+``` |
+ |
+## Background processing |
+ |
+Even though the `BackgroundTaskScheduler` provides functionality for invoking |
+code while the application is in the background, the `BackgroundTask` instance |
+is still invoked on the application main thread. |
+ |
+This means that unless the operation is extremely quick, processing must happen |
+asynchronously, and the call to `onStartJob(...)` must return before the task |
+has finished processing. In that case, `onStartJob(...)` must return true, and |
+instead invoke the `TaskFinishedCallback` when the processing is finished, which |
+typically happens on a different `Thread`, `Handler` or using an `AsyncTask`. |
+ |
+If the task finishes while still being on the main thread, `onStartJob(...)` |
+should return false, indicating that no further processsing is required. |
+ |
+If at any time the constraints given through the `TaskInfo` object does not |
+hold anymore, or if the system deems it necessary, `onStopTask(...)` will be |
+invoked, requiring all activity to cease immediately. The task can return true |
+if the task needs to be rescheduled since it was canceled, or false otherwise. |
+ |
+**The system will hold a wakelock from the time `onStartTask(...)` is invoked |
+until either the task itself invokes the `TaskFinishedCallback`, or |
+`onStopTask(...)` is invoked.** |