public abstract class

WorkManager

extends java.lang.Object

 java.lang.Object

↳androidx.work.WorkManager

Subclasses:

WorkManagerImpl

Gradle dependencies

compile group: 'androidx.work', name: 'work-runtime', version: '2.8.0-alpha02'

  • groupId: androidx.work
  • artifactId: work-runtime
  • version: 2.8.0-alpha02

Artifact androidx.work:work-runtime:2.8.0-alpha02 it located at Google repository (https://maven.google.com/)

Overview

WorkManager the recommended library for persistent work. Scheduled work is is guaranteed to execute sometime after its Constraints are met. WorkManager allows observation of work status and the ability to create complex chains of work.

WorkManager uses an underlying job dispatching service when available based on the following criteria:

  • Uses JobScheduler for API 23+
  • Uses a custom AlarmManager + BroadcastReceiver implementation for API 14-22

All work must be done in a ListenableWorker class. A simple implementation, Worker, is recommended as the starting point for most developers. With the optional dependencies, you can also use CoroutineWorker or RxWorker. All background work is given a maximum of ten minutes to finish its execution. After this time has expired, the worker will be signalled to stop.

There are two types of work supported by WorkManager: OneTimeWorkRequest and PeriodicWorkRequest. You can enqueue requests using WorkManager as follows:

 WorkManager workManager = WorkManager.getInstance(Context);
 workManager.enqueue(new OneTimeWorkRequest.Builder(FooWorker.class).build());
 
A WorkRequest has an associated id that can be used for lookups and observation as follows:
 WorkRequest request = new OneTimeWorkRequest.Builder(FooWorker.class).build();
 workManager.enqueue(request);
 LiveData status = workManager.getWorkInfoByIdLiveData(request.getId());
 status.observe(...);
 
You can also use the id for cancellation:
 WorkRequest request = new OneTimeWorkRequest.Builder(FooWorker.class).build();
 workManager.enqueue(request);
 workManager.cancelWorkById(request.getId());
 
You can chain work as follows:
 WorkRequest request1 = new OneTimeWorkRequest.Builder(FooWorker.class).build();
 WorkRequest request2 = new OneTimeWorkRequest.Builder(BarWorker.class).build();
 WorkRequest request3 = new OneTimeWorkRequest.Builder(BazWorker.class).build();
 workManager.beginWith(request1, request2).then(request3).enqueue();
 
Each call to WorkManager.beginWith(OneTimeWorkRequest) or WorkManager.beginWith(List) returns a WorkContinuation upon which you can call WorkContinuation.then(OneTimeWorkRequest) or WorkContinuation.then(List) to chain further work. This allows for creation of complex chains of work. For example, to create a chain like this:
            A
            |
      +----------+
      |          |
      B          C
      |
   +----+
   |    |
   D    E             
you would enqueue them as follows:
 WorkContinuation continuation = workManager.beginWith(A);
 continuation.then(B).then(D, E).enqueue();  // A is implicitly enqueued here
 continuation.then(C).enqueue();
 
Work is eligible for execution when all of its prerequisites are complete. If any of its prerequisites fail or are cancelled, the work will never run.

WorkRequests can accept Constraints, inputs (see Data), and backoff criteria. WorkRequests can be tagged with human-readable Strings (see WorkRequest.Builder.addTag(String)), and chains of work can be given a uniquely-identifiable name (see WorkManager.beginUniqueWork(String, ExistingWorkPolicy, OneTimeWorkRequest)).

Initializing WorkManager

By default, WorkManager auto-initializes itself using a built-in ContentProvider. ContentProviders are created and run before the Application object, so this allows the WorkManager singleton to be setup before your code can run in most cases. This is suitable for most developers. However, you can provide a custom Configuration by using Configuration.Provider or WorkManager.

Renaming and Removing ListenableWorker Classes

Exercise caution in renaming classes derived from ListenableWorkers. WorkManager stores the class name in its internal database when the WorkRequest is enqueued so it can later create an instance of that worker when constraints are met. Unless otherwise specified in the WorkManager Configuration, this is done in the default WorkerFactory which tries to reflectively create the ListenableWorker object. Therefore, renaming or removing these classes is dangerous - if there is pending work with the given class, it will fail permanently if the class cannot be found. If you are using a custom WorkerFactory, make sure you properly handle cases where the class is not found so that your code does not crash.

In case it is desirable to rename a class, implement a custom WorkerFactory that instantiates the right ListenableWorker for the old class name.

Summary

Constructors
protectedWorkManager()

Methods
public abstract WorkContinuationbeginUniqueWork(java.lang.String uniqueWorkName, ExistingWorkPolicy existingWorkPolicy, java.util.List<OneTimeWorkRequest> work)

This method allows you to begin unique chains of work for situations where you only want one chain with a given name to be active at a time.

public final WorkContinuationbeginUniqueWork(java.lang.String uniqueWorkName, ExistingWorkPolicy existingWorkPolicy, OneTimeWorkRequest work)

This method allows you to begin unique chains of work for situations where you only want one chain with a given name to be active at a time.

public abstract WorkContinuationbeginWith(java.util.List<OneTimeWorkRequest> work)

Begins a chain with one or more OneTimeWorkRequests, which can be enqueued together in the future using WorkContinuation.enqueue().

public final WorkContinuationbeginWith(OneTimeWorkRequest work)

Begins a chain with one or more OneTimeWorkRequests, which can be enqueued together in the future using WorkContinuation.enqueue().

public abstract OperationcancelAllWork()

Cancels all unfinished work.

public abstract OperationcancelAllWorkByTag(java.lang.String tag)

Cancels all unfinished work with the given tag.

public abstract OperationcancelUniqueWork(java.lang.String uniqueWorkName)

Cancels all unfinished work in the work chain with the given name.

public abstract OperationcancelWorkById(java.util.UUID id)

Cancels work with the given id if it isn't finished.

public abstract PendingIntentcreateCancelPendingIntent(java.util.UUID id)

Creates a PendingIntent which can be used to cancel a WorkRequest with the given id.

public abstract Operationenqueue(java.util.List<WorkRequest> requests)

Enqueues one or more items for background processing.

public final Operationenqueue(WorkRequest workRequest)

Enqueues one item for background processing.

public abstract OperationenqueueUniquePeriodicWork(java.lang.String uniqueWorkName, ExistingPeriodicWorkPolicy existingPeriodicWorkPolicy, PeriodicWorkRequest periodicWork)

This method allows you to enqueue a uniquely-named PeriodicWorkRequest, where only one PeriodicWorkRequest of a particular name can be active at a time.

public abstract OperationenqueueUniqueWork(java.lang.String uniqueWorkName, ExistingWorkPolicy existingWorkPolicy, java.util.List<OneTimeWorkRequest> work)

This method allows you to enqueue work requests to a uniquely-named WorkContinuation, where only one continuation of a particular name can be active at a time.

public OperationenqueueUniqueWork(java.lang.String uniqueWorkName, ExistingWorkPolicy existingWorkPolicy, OneTimeWorkRequest work)

This method allows you to enqueue work requests to a uniquely-named WorkContinuation, where only one continuation of a particular name can be active at a time.

public abstract ConfigurationgetConfiguration()

Provides the Configuration instance that WorkManager was initialized with.

public static WorkManagergetInstance()

Retrieves the default singleton instance of WorkManager.

public static WorkManagergetInstance(Context context)

Retrieves the default singleton instance of WorkManager.

public abstract <any>getLastCancelAllTimeMillis()

Gets a of the last time all work was cancelled.

public abstract LiveData<java.lang.Long>getLastCancelAllTimeMillisLiveData()

Gets a LiveData of the last time all work was cancelled.

public abstract <any>getWorkInfoById(java.util.UUID id)

Gets a of the WorkInfo for a given work id.

public abstract LiveData<WorkInfo>getWorkInfoByIdLiveData(java.util.UUID id)

Gets a LiveData of the WorkInfo for a given work id.

public abstract <any>getWorkInfos(WorkQuery workQuery)

Gets the of the java.util.List of WorkInfo for all work referenced by the WorkQuery specification.

public abstract <any>getWorkInfosByTag(java.lang.String tag)

Gets a of the WorkInfo for all work for a given tag.

public abstract LiveData<java.util.List>getWorkInfosByTagLiveData(java.lang.String tag)

Gets a LiveData of the WorkInfo for all work for a given tag.

public abstract <any>getWorkInfosForUniqueWork(java.lang.String uniqueWorkName)

Gets a of the WorkInfo for all work in a work chain with a given unique name.

public abstract LiveData<java.util.List>getWorkInfosForUniqueWorkLiveData(java.lang.String uniqueWorkName)

Gets a LiveData of the WorkInfo for all work in a work chain with a given unique name.

public abstract LiveData<java.util.List>getWorkInfosLiveData(WorkQuery workQuery)

Gets the LiveData of the java.util.List of WorkInfo for all work referenced by the WorkQuery specification.

public static voidinitialize(Context context, Configuration configuration)

Used to do a one-time initialization of the WorkManager singleton with a custom Configuration.

public static booleanisInitialized()

Provides a way to check if WorkManager is initialized in this process.

public abstract OperationpruneWork()

Prunes all eligible finished work from the internal database.

from java.lang.Objectclone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait

Constructors

protected WorkManager()

Methods

public static WorkManager getInstance()

Deprecated: Call WorkManager.getInstance(Context) instead.

Retrieves the default singleton instance of WorkManager.

Returns:

The singleton instance of WorkManager; this may be null in unusual circumstances where you have disabled automatic initialization and have failed to manually call WorkManager.initialize(Context, Configuration).

public static WorkManager getInstance(Context context)

Retrieves the default singleton instance of WorkManager.

Parameters:

context: A for on-demand initialization.

Returns:

The singleton instance of WorkManager; this may be null in unusual circumstances where you have disabled automatic initialization and have failed to manually call WorkManager.initialize(Context, Configuration).

public static void initialize(Context context, Configuration configuration)

Used to do a one-time initialization of the WorkManager singleton with a custom Configuration. By default, this method should not be called because WorkManager is automatically initialized. To initialize WorkManager yourself, please follow these steps:

  • Disable androidx.work.WorkManagerInitializer in your manifest.
  • Invoke this method in Application#onCreate or a ContentProvider. Note that this method must be invoked in one of these two places or you risk getting a NullPointerException in WorkManager.getInstance(Context).

This method throws an java.lang.IllegalStateException when attempting to initialize in direct boot mode.

This method throws an exception if it is called multiple times.

Parameters:

context: A object for configuration purposes. Internally, this class will call , so you may safely pass in any Context without risking a memory leak.
configuration: The Configuration for used to set up WorkManager.

See also: for on-demand initialization.

public static boolean isInitialized()

Provides a way to check if WorkManager is initialized in this process.

Returns:

true if WorkManager has been initialized in this process.

public abstract Configuration getConfiguration()

Provides the Configuration instance that WorkManager was initialized with.

Returns:

The Configuration instance that WorkManager was initialized with.

public final Operation enqueue(WorkRequest workRequest)

Enqueues one item for background processing.

Parameters:

workRequest: The WorkRequest to enqueue

Returns:

An Operation that can be used to determine when the enqueue has completed

public abstract Operation enqueue(java.util.List<WorkRequest> requests)

Enqueues one or more items for background processing.

Parameters:

requests: One or more WorkRequest to enqueue

Returns:

An Operation that can be used to determine when the enqueue has completed

public final WorkContinuation beginWith(OneTimeWorkRequest work)

Begins a chain with one or more OneTimeWorkRequests, which can be enqueued together in the future using WorkContinuation.enqueue().

If any work in the chain fails or is cancelled, all of its dependent work inherits that state and will never run.

Parameters:

work: One or more OneTimeWorkRequest to start a chain of work

Returns:

A WorkContinuation that allows for further chaining of dependent OneTimeWorkRequest

public abstract WorkContinuation beginWith(java.util.List<OneTimeWorkRequest> work)

Begins a chain with one or more OneTimeWorkRequests, which can be enqueued together in the future using WorkContinuation.enqueue().

If any work in the chain fails or is cancelled, all of its dependent work inherits that state and will never run.

Parameters:

work: One or more OneTimeWorkRequest to start a chain of work

Returns:

A WorkContinuation that allows for further chaining of dependent OneTimeWorkRequest

public final WorkContinuation beginUniqueWork(java.lang.String uniqueWorkName, ExistingWorkPolicy existingWorkPolicy, OneTimeWorkRequest work)

This method allows you to begin unique chains of work for situations where you only want one chain with a given name to be active at a time. For example, you may only want one sync operation to be active. If there is one pending, you can choose to let it run or replace it with your new work.

The uniqueWorkName uniquely identifies this set of work.

If this method determines that new work should be enqueued and run, all records of previous work with uniqueWorkName will be pruned. If this method determines that new work should NOT be run, then the entire chain will be considered a no-op.

If any work in the chain fails or is cancelled, all of its dependent work inherits that state and will never run. This is particularly important if you are using APPEND as your ExistingWorkPolicy.

Parameters:

uniqueWorkName: A unique name which for this chain of work
existingWorkPolicy: An ExistingWorkPolicy
work: The OneTimeWorkRequest to enqueue. REPLACE ensures that if there is pending work labelled with uniqueWorkName, it will be cancelled and the new work will run. KEEP will run the new sequence of work only if there is no pending work labelled with uniqueWorkName. APPEND will create a new sequence of work if there is no existing work with uniqueWorkName; otherwise, work will be added as a child of all leaf nodes labelled with uniqueWorkName.

Returns:

A WorkContinuation that allows further chaining

public abstract WorkContinuation beginUniqueWork(java.lang.String uniqueWorkName, ExistingWorkPolicy existingWorkPolicy, java.util.List<OneTimeWorkRequest> work)

This method allows you to begin unique chains of work for situations where you only want one chain with a given name to be active at a time. For example, you may only want one sync operation to be active. If there is one pending, you can choose to let it run or replace it with your new work.

The uniqueWorkName uniquely identifies this set of work.

If this method determines that new work should be enqueued and run, all records of previous work with uniqueWorkName will be pruned. If this method determines that new work should NOT be run, then the entire chain will be considered a no-op.

If any work in the chain fails or is cancelled, all of its dependent work inherits that state and will never run. This is particularly important if you are using APPEND as your ExistingWorkPolicy.

Parameters:

uniqueWorkName: A unique name which for this chain of work
existingWorkPolicy: An ExistingWorkPolicy; see below for more information
work: One or more OneTimeWorkRequest to enqueue. REPLACE ensures that if there is pending work labelled with uniqueWorkName, it will be cancelled and the new work will run. KEEP will run the new sequence of work only if there is no pending work labelled with uniqueWorkName. APPEND will create a new sequence of work if there is no existing work with uniqueWorkName; otherwise, work will be added as a child of all leaf nodes labelled with uniqueWorkName.

Returns:

A WorkContinuation that allows further chaining

public Operation enqueueUniqueWork(java.lang.String uniqueWorkName, ExistingWorkPolicy existingWorkPolicy, OneTimeWorkRequest work)

This method allows you to enqueue work requests to a uniquely-named WorkContinuation, where only one continuation of a particular name can be active at a time. For example, you may only want one sync operation to be active. If there is one pending, you can choose to let it run or replace it with your new work.

The uniqueWorkName uniquely identifies this WorkContinuation.

Parameters:

uniqueWorkName: A unique name which for this operation
existingWorkPolicy: An ExistingWorkPolicy; see below for more information
work: The OneTimeWorkRequests to enqueue. REPLACE ensures that if there is pending work labelled with uniqueWorkName, it will be cancelled and the new work will run. KEEP will run the new OneTimeWorkRequests only if there is no pending work labelled with uniqueWorkName. APPEND will append the OneTimeWorkRequests as leaf nodes labelled with uniqueWorkName.

Returns:

An Operation that can be used to determine when the enqueue has completed

public abstract Operation enqueueUniqueWork(java.lang.String uniqueWorkName, ExistingWorkPolicy existingWorkPolicy, java.util.List<OneTimeWorkRequest> work)

This method allows you to enqueue work requests to a uniquely-named WorkContinuation, where only one continuation of a particular name can be active at a time. For example, you may only want one sync operation to be active. If there is one pending, you can choose to let it run or replace it with your new work.

The uniqueWorkName uniquely identifies this WorkContinuation.

Parameters:

uniqueWorkName: A unique name which for this operation
existingWorkPolicy: An ExistingWorkPolicy
work: OneTimeWorkRequests to enqueue. REPLACE ensures that if there is pending work labelled with uniqueWorkName, it will be cancelled and the new work will run. KEEP will run the new OneTimeWorkRequests only if there is no pending work labelled with uniqueWorkName. APPEND will append the OneTimeWorkRequests as leaf nodes labelled with uniqueWorkName.

Returns:

An Operation that can be used to determine when the enqueue has completed

public abstract Operation enqueueUniquePeriodicWork(java.lang.String uniqueWorkName, ExistingPeriodicWorkPolicy existingPeriodicWorkPolicy, PeriodicWorkRequest periodicWork)

This method allows you to enqueue a uniquely-named PeriodicWorkRequest, where only one PeriodicWorkRequest of a particular name can be active at a time. For example, you may only want one sync operation to be active. If there is one pending, you can choose to let it run or replace it with your new work.

The uniqueWorkName uniquely identifies this PeriodicWorkRequest.

Parameters:

uniqueWorkName: A unique name which for this operation
existingPeriodicWorkPolicy: An ExistingPeriodicWorkPolicy
periodicWork: A PeriodicWorkRequest to enqueue. REPLACE ensures that if there is pending work labelled with uniqueWorkName, it will be cancelled and the new work will run. KEEP will run the new PeriodicWorkRequest only if there is no pending work labelled with uniqueWorkName.

Returns:

An Operation that can be used to determine when the enqueue has completed

public abstract Operation cancelWorkById(java.util.UUID id)

Cancels work with the given id if it isn't finished. Note that cancellation is a best-effort policy and work that is already executing may continue to run. Upon cancellation, ListenableWorker.onStopped() will be invoked for any affected workers.

Parameters:

id: The id of the work

Returns:

An Operation that can be used to determine when the cancelWorkById has completed

public abstract Operation cancelAllWorkByTag(java.lang.String tag)

Cancels all unfinished work with the given tag. Note that cancellation is a best-effort policy and work that is already executing may continue to run. Upon cancellation, ListenableWorker.onStopped() will be invoked for any affected workers.

Parameters:

tag: The tag used to identify the work

Returns:

An Operation that can be used to determine when the cancelAllWorkByTag has completed

public abstract Operation cancelUniqueWork(java.lang.String uniqueWorkName)

Cancels all unfinished work in the work chain with the given name. Note that cancellation is a best-effort policy and work that is already executing may continue to run. Upon cancellation, ListenableWorker.onStopped() will be invoked for any affected workers.

Parameters:

uniqueWorkName: The unique name used to identify the chain of work

Returns:

An Operation that can be used to determine when the cancelUniqueWork has completed

public abstract Operation cancelAllWork()

Cancels all unfinished work. Use this method with extreme caution! By invoking it, you will potentially affect other modules or libraries in your codebase. It is strongly recommended that you use one of the other cancellation methods at your disposal.

Upon cancellation, ListenableWorker.onStopped() will be invoked for any affected workers.

Returns:

An Operation that can be used to determine when the cancelAllWork has completed

public abstract PendingIntent createCancelPendingIntent(java.util.UUID id)

Creates a PendingIntent which can be used to cancel a WorkRequest with the given id.

Parameters:

id: The WorkRequest id.

Returns:

The PendingIntent that can be used to cancel the WorkRequest.

public abstract Operation pruneWork()

Prunes all eligible finished work from the internal database. Eligible work must be finished (WorkInfo.State.SUCCEEDED, WorkInfo.State.FAILED, or WorkInfo.State.CANCELLED), with zero unfinished dependents.

Use this method with caution; by invoking it, you (and any modules and libraries in your codebase) will no longer be able to observe the WorkInfo of the pruned work. You do not normally need to call this method - WorkManager takes care to auto-prune its work after a sane period of time. This method also ignores the WorkRequest.Builder.keepResultsForAtLeast(long, TimeUnit) policy.

Returns:

An Operation that can be used to determine when the pruneWork has completed

public abstract LiveData<java.lang.Long> getLastCancelAllTimeMillisLiveData()

Gets a LiveData of the last time all work was cancelled. This method is intended for use by library and module developers who have dependent data in their own repository that must be updated or deleted in case someone cancels their work without their prior knowledge.

Returns:

A LiveData of the timestamp (System#getCurrentTimeMillis()) when WorkManager.cancelAllWork() was last invoked; this timestamp may be 0L if this never occurred

public abstract <any> getLastCancelAllTimeMillis()

Gets a of the last time all work was cancelled. This method is intended for use by library and module developers who have dependent data in their own repository that must be updated or deleted in case someone cancels their work without their prior knowledge.

Returns:

A of the timestamp (System#getCurrentTimeMillis()) when WorkManager.cancelAllWork() was last invoked; this timestamp may be 0L if this never occurred

public abstract LiveData<WorkInfo> getWorkInfoByIdLiveData(java.util.UUID id)

Gets a LiveData of the WorkInfo for a given work id.

Parameters:

id: The id of the work

Returns:

A LiveData of the WorkInfo associated with id; note that this WorkInfo may be null if id is not known to WorkManager.

public abstract <any> getWorkInfoById(java.util.UUID id)

Gets a of the WorkInfo for a given work id.

Parameters:

id: The id of the work

Returns:

A of the WorkInfo associated with id; note that this WorkInfo may be null if id is not known to WorkManager

public abstract LiveData<java.util.List> getWorkInfosByTagLiveData(java.lang.String tag)

Gets a LiveData of the WorkInfo for all work for a given tag.

Parameters:

tag: The tag of the work

Returns:

A LiveData list of WorkInfo for work tagged with tag

public abstract <any> getWorkInfosByTag(java.lang.String tag)

Gets a of the WorkInfo for all work for a given tag.

Parameters:

tag: The tag of the work

Returns:

A list of WorkInfo for work tagged with tag

public abstract LiveData<java.util.List> getWorkInfosForUniqueWorkLiveData(java.lang.String uniqueWorkName)

Gets a LiveData of the WorkInfo for all work in a work chain with a given unique name.

Parameters:

uniqueWorkName: The unique name used to identify the chain of work

Returns:

A LiveData of the WorkInfo for work in the chain named uniqueWorkName

public abstract <any> getWorkInfosForUniqueWork(java.lang.String uniqueWorkName)

Gets a of the WorkInfo for all work in a work chain with a given unique name.

Parameters:

uniqueWorkName: The unique name used to identify the chain of work

Returns:

A of the WorkInfo for work in the chain named uniqueWorkName

public abstract LiveData<java.util.List> getWorkInfosLiveData(WorkQuery workQuery)

Gets the LiveData of the java.util.List of WorkInfo for all work referenced by the WorkQuery specification.

Parameters:

workQuery: The work query specification

Returns:

A LiveData of the java.util.List of WorkInfo for work referenced by this WorkQuery.

public abstract <any> getWorkInfos(WorkQuery workQuery)

Gets the of the java.util.List of WorkInfo for all work referenced by the WorkQuery specification.

Parameters:

workQuery: The work query specification

Returns:

A of the java.util.List of WorkInfo for work referenced by this WorkQuery.

Source

/*
 * Copyright 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package androidx.work;

import android.annotation.SuppressLint;
import android.app.PendingIntent;
import android.content.Context;

import androidx.annotation.NonNull;
import androidx.annotation.RestrictTo;
import androidx.lifecycle.LiveData;
import androidx.work.impl.WorkManagerImpl;

import com.google.common.util.concurrent.ListenableFuture;

import java.util.Collections;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * WorkManager the recommended library for persistent work.
 * Scheduled work is is guaranteed to execute sometime after its {@link Constraints} are met.
 * WorkManager allows observation of work status and the ability to create complex chains of work.
 * <p>
 * WorkManager uses an underlying job dispatching service when available based on the following
 * criteria:
 * <p><ul>
 * <li>Uses JobScheduler for API 23+
 * <li>Uses a custom AlarmManager + BroadcastReceiver implementation for API 14-22</ul>
 * <p>
 * All work must be done in a {@link ListenableWorker} class.  A simple implementation,
 * {@link Worker}, is recommended as the starting point for most developers.  With the optional
 * dependencies, you can also use {@code CoroutineWorker} or {@code RxWorker}.  All background work
 * is given a maximum of ten minutes to finish its execution.  After this time has expired, the
 * worker will be signalled to stop.
 * <p>
 * There are two types of work supported by WorkManager: {@link OneTimeWorkRequest} and
 * {@link PeriodicWorkRequest}.  You can enqueue requests using WorkManager as follows:
 *
 * <pre class="prettyprint">
 * WorkManager workManager = WorkManager.getInstance(Context);
 * workManager.enqueue(new OneTimeWorkRequest.Builder(FooWorker.class).build());
 * </pre>
 *
 * A {@link WorkRequest} has an associated id that can be used for lookups and observation as
 * follows:
 *
 * <pre class="prettyprint">
 * WorkRequest request = new OneTimeWorkRequest.Builder(FooWorker.class).build();
 * workManager.enqueue(request);
 * LiveData<WorkInfo> status = workManager.getWorkInfoByIdLiveData(request.getId());
 * status.observe(...);
 * </pre>
 *
 * You can also use the id for cancellation:
 *
 * <pre class="prettyprint">
 * WorkRequest request = new OneTimeWorkRequest.Builder(FooWorker.class).build();
 * workManager.enqueue(request);
 * workManager.cancelWorkById(request.getId());
 * </pre>
 *
 * You can chain work as follows:
 *
 * <pre class="prettyprint">
 * WorkRequest request1 = new OneTimeWorkRequest.Builder(FooWorker.class).build();
 * WorkRequest request2 = new OneTimeWorkRequest.Builder(BarWorker.class).build();
 * WorkRequest request3 = new OneTimeWorkRequest.Builder(BazWorker.class).build();
 * workManager.beginWith(request1, request2).then(request3).enqueue();
 * </pre>
 *
 * Each call to {@link #beginWith(OneTimeWorkRequest)} or {@link #beginWith(List)} returns a
 * {@link WorkContinuation} upon which you can call
 * {@link WorkContinuation#then(OneTimeWorkRequest)} or {@link WorkContinuation#then(List)} to
 * chain further work.  This allows for creation of complex chains of work.  For example, to create
 * a chain like this:
 *
 * <pre>
 *            A
 *            |
 *      +----------+
 *      |          |
 *      B          C
 *      |
 *   +----+
 *   |    |
 *   D    E             </pre>
 *
 * you would enqueue them as follows:
 *
 * <pre class="prettyprint">
 * WorkContinuation continuation = workManager.beginWith(A);
 * continuation.then(B).then(D, E).enqueue();  // A is implicitly enqueued here
 * continuation.then(C).enqueue();
 * </pre>
 *
 * Work is eligible for execution when all of its prerequisites are complete.  If any of its
 * prerequisites fail or are cancelled, the work will never run.
 * <p>
 * WorkRequests can accept {@link Constraints}, inputs (see {@link Data}), and backoff criteria.
 * WorkRequests can be tagged with human-readable Strings
 * (see {@link WorkRequest.Builder#addTag(String)}), and chains of work can be given a
 * uniquely-identifiable name (see
 * {@link #beginUniqueWork(String, ExistingWorkPolicy, OneTimeWorkRequest)}).
 * <p>
 * <a name="initializing"></a>
 * <b>Initializing WorkManager</b>
 * <p>
 * By default, WorkManager auto-initializes itself using a built-in {@code ContentProvider}.
 * ContentProviders are created and run before the {@code Application} object, so this allows the
 * WorkManager singleton to be setup before your code can run in most cases.  This is suitable for
 * most developers.  However, you can provide a custom {@link Configuration} by using
 * {@link Configuration.Provider} or
 * {@link WorkManager#initialize(android.content.Context, androidx.work.Configuration)}.
 * <p>
 * <a name="worker_class_names"></a>
 * <b>Renaming and Removing ListenableWorker Classes</b>
 * <p>
 * Exercise caution in renaming classes derived from {@link ListenableWorker}s.  WorkManager stores
 * the class name in its internal database when the {@link WorkRequest} is enqueued so it can later
 * create an instance of that worker when constraints are met.  Unless otherwise specified in the
 * WorkManager {@link Configuration}, this is done in the default {@link WorkerFactory} which tries
 * to reflectively create the ListenableWorker object.  Therefore, renaming or removing these
 * classes is dangerous - if there is pending work with the given class, it will fail permanently
 * if the class cannot be found.  If you are using a custom WorkerFactory, make sure you properly
 * handle cases where the class is not found so that your code does not crash.
 * <p>
 * In case it is desirable to rename a class, implement a custom WorkerFactory that instantiates the
 * right ListenableWorker for the old class name.
 * */
// Suppressing Metalava checks for added abstract methods in WorkManager.
// WorkManager cannot be extended, because the constructor is marked @Restricted
@SuppressLint("AddedAbstractMethod")
public abstract class WorkManager {

    /**
     * Retrieves the {@code default} singleton instance of {@link WorkManager}.
     *
     * @return The singleton instance of {@link WorkManager}; this may be {@code null} in unusual
     *         circumstances where you have disabled automatic initialization and have failed to
     *         manually call {@link #initialize(Context, Configuration)}.
     * @throws IllegalStateException If WorkManager is not initialized properly as per the exception
     *                               message.
     * @deprecated Call {@link WorkManager#getInstance(Context)} instead.
     */
    @Deprecated
    public static @NonNull WorkManager getInstance() {
        WorkManager workManager = WorkManagerImpl.getInstance();
        if (workManager == null) {
            throw new IllegalStateException("WorkManager is not initialized properly.  The most "
                    + "likely cause is that you disabled WorkManagerInitializer in your manifest "
                    + "but forgot to call WorkManager#initialize in your Application#onCreate or a "
                    + "ContentProvider.");
        } else {
            return workManager;
        }
    }

    /**
     * Retrieves the {@code default} singleton instance of {@link WorkManager}.
     *
     * @param context A {@link Context} for on-demand initialization.
     * @return The singleton instance of {@link WorkManager}; this may be {@code null} in unusual
     *         circumstances where you have disabled automatic initialization and have failed to
     *         manually call {@link #initialize(Context, Configuration)}.
     * @throws IllegalStateException If WorkManager is not initialized properly
     */
    public static @NonNull WorkManager getInstance(@NonNull Context context) {
        return WorkManagerImpl.getInstance(context);
    }

    /**
     * Used to do a one-time initialization of the {@link WorkManager} singleton with a custom
     * {@link Configuration}.  By default, this method should not be called because WorkManager is
     * automatically initialized.  To initialize WorkManager yourself, please follow these steps:
     * <p><ul>
     * <li>Disable {@code androidx.work.WorkManagerInitializer} in your manifest.
     * <li>Invoke this method in {@code Application#onCreate} or a {@code ContentProvider}. Note
     * that this method <b>must</b> be invoked in one of these two places or you risk getting a
     * {@code NullPointerException} in {@link #getInstance(Context)}.
     * </ul></p>
     * <p>
     * This method throws an {@link IllegalStateException} when attempting to initialize in
     * direct boot mode.
     * <p>
     * This method throws an exception if it is called multiple times.
     *
     * @param context A {@link Context} object for configuration purposes. Internally, this class
     *                will call {@link Context#getApplicationContext()}, so you may safely pass in
     *                any Context without risking a memory leak.
     * @param configuration The {@link Configuration} for used to set up WorkManager.
     * @see Configuration.Provider for on-demand initialization.
     */
    public static void initialize(@NonNull Context context, @NonNull Configuration configuration) {
        WorkManagerImpl.initialize(context, configuration);
    }

    /**
     * Provides a way to check if {@link WorkManager} is initialized in this process.
     *
     * @return {@code true} if {@link WorkManager} has been initialized in this process.
     */
    public static boolean isInitialized() {
        return WorkManagerImpl.isInitialized();
    }

    /**
     * Provides the {@link Configuration} instance that {@link WorkManager} was initialized with.
     *
     * @return The {@link Configuration} instance that {@link WorkManager} was initialized with.
     */
    @NonNull
    public abstract Configuration getConfiguration();

    /**
     * Enqueues one item for background processing.
     *
     * @param workRequest The {@link WorkRequest} to enqueue
     * @return An {@link Operation} that can be used to determine when the enqueue has completed
     */
    @NonNull
    public final Operation enqueue(@NonNull WorkRequest workRequest) {
        return enqueue(Collections.singletonList(workRequest));
    }

    /**
     * Enqueues one or more items for background processing.
     *
     * @param requests One or more {@link WorkRequest} to enqueue
     * @return An {@link Operation} that can be used to determine when the enqueue has completed
     */
    @NonNull
    public abstract Operation enqueue(@NonNull List<? extends WorkRequest> requests);

    /**
     * Begins a chain with one or more {@link OneTimeWorkRequest}s, which can be enqueued together
     * in the future using {@link WorkContinuation#enqueue()}.
     * <p>
     * If any work in the chain fails or is cancelled, all of its dependent work inherits that state
     * and will never run.
     *
     * @param work One or more {@link OneTimeWorkRequest} to start a chain of work
     * @return A {@link WorkContinuation} that allows for further chaining of dependent
     *         {@link OneTimeWorkRequest}
     */
    public final @NonNull WorkContinuation beginWith(@NonNull OneTimeWorkRequest work) {
        return beginWith(Collections.singletonList(work));
    }

    /**
     * Begins a chain with one or more {@link OneTimeWorkRequest}s, which can be enqueued together
     * in the future using {@link WorkContinuation#enqueue()}.
     * <p>
     * If any work in the chain fails or is cancelled, all of its dependent work inherits that state
     * and will never run.
     *
     * @param work One or more {@link OneTimeWorkRequest} to start a chain of work
     * @return A {@link WorkContinuation} that allows for further chaining of dependent
     *         {@link OneTimeWorkRequest}
     */
    public abstract @NonNull WorkContinuation beginWith(@NonNull List<OneTimeWorkRequest> work);

    /**
     * This method allows you to begin unique chains of work for situations where you only want one
     * chain with a given name to be active at a time.  For example, you may only want one sync
     * operation to be active.  If there is one pending, you can choose to let it run or replace it
     * with your new work.
     * <p>
     * The {@code uniqueWorkName} uniquely identifies this set of work.
     * <p>
     * If this method determines that new work should be enqueued and run, all records of previous
     * work with {@code uniqueWorkName} will be pruned.  If this method determines that new work
     * should NOT be run, then the entire chain will be considered a no-op.
     * <p>
     * If any work in the chain fails or is cancelled, all of its dependent work inherits that state
     * and will never run.  This is particularly important if you are using {@code APPEND} as your
     * {@link ExistingWorkPolicy}.
     *
     * @param uniqueWorkName A unique name which for this chain of work
     * @param existingWorkPolicy An {@link ExistingWorkPolicy}
     * @param work The {@link OneTimeWorkRequest} to enqueue. {@code REPLACE} ensures that if there
     *             is pending work labelled with {@code uniqueWorkName}, it will be cancelled and
     *             the new work will run. {@code KEEP} will run the new sequence of work only if
     *             there is no pending work labelled with {@code uniqueWorkName}.  {@code APPEND}
     *             will create a new sequence of work if there is no existing work with
     *             {@code uniqueWorkName}; otherwise, {@code work} will be added as a child of all
     *             leaf nodes labelled with {@code uniqueWorkName}.
     * @return A {@link WorkContinuation} that allows further chaining
     */
    public final @NonNull WorkContinuation beginUniqueWork(
            @NonNull String uniqueWorkName,
            @NonNull ExistingWorkPolicy existingWorkPolicy,
            @NonNull OneTimeWorkRequest work) {
        return beginUniqueWork(uniqueWorkName, existingWorkPolicy, Collections.singletonList(work));
    }

    /**
     * This method allows you to begin unique chains of work for situations where you only want one
     * chain with a given name to be active at a time.  For example, you may only want one sync
     * operation to be active.  If there is one pending, you can choose to let it run or replace it
     * with your new work.
     * <p>
     * The {@code uniqueWorkName} uniquely identifies this set of work.
     * <p>
     * If this method determines that new work should be enqueued and run, all records of previous
     * work with {@code uniqueWorkName} will be pruned.  If this method determines that new work
     * should NOT be run, then the entire chain will be considered a no-op.
     * <p>
     * If any work in the chain fails or is cancelled, all of its dependent work inherits that state
     * and will never run.  This is particularly important if you are using {@code APPEND} as your
     * {@link ExistingWorkPolicy}.
     *
     * @param uniqueWorkName A unique name which for this chain of work
     * @param existingWorkPolicy An {@link ExistingWorkPolicy}; see below for more information
     * @param work One or more {@link OneTimeWorkRequest} to enqueue. {@code REPLACE} ensures that
     *             if there is pending work labelled with {@code uniqueWorkName}, it will be
     *             cancelled and the new work will run. {@code KEEP} will run the new sequence of
     *             work only if there is no pending work labelled with {@code uniqueWorkName}.
     *             {@code APPEND} will create a new sequence of work if there is no
     *             existing work with {@code uniqueWorkName}; otherwise, {@code work} will be added
     *             as a child of all leaf nodes labelled with {@code uniqueWorkName}.
     * @return A {@link WorkContinuation} that allows further chaining
     */
    public abstract @NonNull WorkContinuation beginUniqueWork(
            @NonNull String uniqueWorkName,
            @NonNull ExistingWorkPolicy existingWorkPolicy,
            @NonNull List<OneTimeWorkRequest> work);


    /**
     * This method allows you to enqueue {@code work} requests to a uniquely-named
     * {@link WorkContinuation}, where only one continuation of a particular name can be active at
     * a time. For example, you may only want one sync operation to be active. If there is one
     * pending, you can choose to let it run or replace it with your new work.
     * <p>
     * The {@code uniqueWorkName} uniquely identifies this {@link WorkContinuation}.
     *
     * @param uniqueWorkName A unique name which for this operation
     * @param existingWorkPolicy An {@link ExistingWorkPolicy}; see below for more information
     * @param work The {@link OneTimeWorkRequest}s to enqueue. {@code REPLACE} ensures that if there
     *             is pending work labelled with {@code uniqueWorkName}, it will be cancelled and
     *             the new work will run. {@code KEEP} will run the new OneTimeWorkRequests only if
     *             there is no pending work labelled with {@code uniqueWorkName}.  {@code APPEND}
     *             will append the OneTimeWorkRequests as leaf nodes labelled with
     *             {@code uniqueWorkName}.
     * @return An {@link Operation} that can be used to determine when the enqueue has completed
     */
    @NonNull
    public Operation enqueueUniqueWork(
            @NonNull String uniqueWorkName,
            @NonNull ExistingWorkPolicy existingWorkPolicy,
            @NonNull OneTimeWorkRequest work) {
        return enqueueUniqueWork(
                uniqueWorkName,
                existingWorkPolicy,
                Collections.singletonList(work));
    }

    /**
     * This method allows you to enqueue {@code work} requests to a uniquely-named
     * {@link WorkContinuation}, where only one continuation of a particular name can be active at
     * a time. For example, you may only want one sync operation to be active. If there is one
     * pending, you can choose to let it run or replace it with your new work.
     * <p>
     * The {@code uniqueWorkName} uniquely identifies this {@link WorkContinuation}.
     *
     * @param uniqueWorkName A unique name which for this operation
     * @param existingWorkPolicy An {@link ExistingWorkPolicy}
     * @param work {@link OneTimeWorkRequest}s to enqueue. {@code REPLACE} ensures
     *                     that if there is pending work labelled with {@code uniqueWorkName}, it
     *                     will be cancelled and the new work will run. {@code KEEP} will run the
     *                     new OneTimeWorkRequests only if there is no pending work labelled with
     *                     {@code uniqueWorkName}. {@code APPEND} will append the
     *                     OneTimeWorkRequests as leaf nodes labelled with {@code uniqueWorkName}.
     * @return An {@link Operation} that can be used to determine when the enqueue has completed
     */
    @NonNull
    public abstract Operation enqueueUniqueWork(
            @NonNull String uniqueWorkName,
            @NonNull ExistingWorkPolicy existingWorkPolicy,
            @NonNull List<OneTimeWorkRequest> work);

    /**
     * This method allows you to enqueue a uniquely-named {@link PeriodicWorkRequest}, where only
     * one PeriodicWorkRequest of a particular name can be active at a time.  For example, you may
     * only want one sync operation to be active.  If there is one pending, you can choose to let it
     * run or replace it with your new work.
     * <p>
     * The {@code uniqueWorkName} uniquely identifies this PeriodicWorkRequest.
     *
     * @param uniqueWorkName A unique name which for this operation
     * @param existingPeriodicWorkPolicy An {@link ExistingPeriodicWorkPolicy}
     * @param periodicWork A {@link PeriodicWorkRequest} to enqueue. {@code REPLACE} ensures that if
     *                     there is pending work labelled with {@code uniqueWorkName}, it will be
     *                     cancelled and the new work will run. {@code KEEP} will run the new
     *                     PeriodicWorkRequest only if there is no pending work labelled with
     *                     {@code uniqueWorkName}.
     * @return An {@link Operation} that can be used to determine when the enqueue has completed
     */
    @NonNull
    public abstract Operation enqueueUniquePeriodicWork(
            @NonNull String uniqueWorkName,
            @NonNull ExistingPeriodicWorkPolicy existingPeriodicWorkPolicy,
            @NonNull PeriodicWorkRequest periodicWork);

    /**
     * Cancels work with the given id if it isn't finished.  Note that cancellation is a best-effort
     * policy and work that is already executing may continue to run.  Upon cancellation,
     * {@link ListenableWorker#onStopped()} will be invoked for any affected workers.
     *
     * @param id The id of the work
     * @return An {@link Operation} that can be used to determine when the cancelWorkById has
     * completed
     */
    public abstract @NonNull Operation cancelWorkById(@NonNull UUID id);

    /**
     * Cancels all unfinished work with the given tag.  Note that cancellation is a best-effort
     * policy and work that is already executing may continue to run.  Upon cancellation,
     * {@link ListenableWorker#onStopped()} will be invoked for any affected workers.
     *
     * @param tag The tag used to identify the work
     * @return An {@link Operation} that can be used to determine when the cancelAllWorkByTag has
     * completed
     */
    public abstract @NonNull Operation cancelAllWorkByTag(@NonNull String tag);

    /**
     * Cancels all unfinished work in the work chain with the given name.  Note that cancellation is
     * a best-effort policy and work that is already executing may continue to run.  Upon
     * cancellation, {@link ListenableWorker#onStopped()} will be invoked for any affected workers.
     *
     * @param uniqueWorkName The unique name used to identify the chain of work
     * @return An {@link Operation} that can be used to determine when the cancelUniqueWork has
     * completed
     */
    public abstract @NonNull Operation cancelUniqueWork(@NonNull String uniqueWorkName);

    /**
     * Cancels all unfinished work.  <b>Use this method with extreme caution!</b>  By invoking it,
     * you will potentially affect other modules or libraries in your codebase.  It is strongly
     * recommended that you use one of the other cancellation methods at your disposal.
     * <p>
     * Upon cancellation, {@link ListenableWorker#onStopped()} will be invoked for any affected
     * workers.
     *
     * @return An {@link Operation} that can be used to determine when the cancelAllWork has
     * completed
     */
    public abstract @NonNull Operation cancelAllWork();

    /**
     * Creates a {@link PendingIntent} which can be used to cancel a {@link WorkRequest} with the
     * given {@code id}.
     *
     * @param id      The {@link WorkRequest} id.
     * @return The {@link PendingIntent} that can be used to cancel the {@link WorkRequest}.
     */
    public abstract @NonNull PendingIntent createCancelPendingIntent(@NonNull UUID id);

    /**
     * Prunes all eligible finished work from the internal database.  Eligible work must be finished
     * ({@link WorkInfo.State#SUCCEEDED}, {@link WorkInfo.State#FAILED}, or
     * {@link WorkInfo.State#CANCELLED}), with zero unfinished dependents.
     * <p>
     * <b>Use this method with caution</b>; by invoking it, you (and any modules and libraries in
     * your codebase) will no longer be able to observe the {@link WorkInfo} of the pruned work.
     * You do not normally need to call this method - WorkManager takes care to auto-prune its work
     * after a sane period of time.  This method also ignores the
     * {@link OneTimeWorkRequest.Builder#keepResultsForAtLeast(long, TimeUnit)} policy.
     *
     * @return An {@link Operation} that can be used to determine when the pruneWork has
     * completed
     */
    public abstract @NonNull Operation pruneWork();

    /**
     * Gets a {@link LiveData} of the last time all work was cancelled.  This method is intended for
     * use by library and module developers who have dependent data in their own repository that
     * must be updated or deleted in case someone cancels their work without their prior knowledge.
     *
     * @return A {@link LiveData} of the timestamp ({@code System#getCurrentTimeMillis()}) when
     *         {@link #cancelAllWork()} was last invoked; this timestamp may be {@code 0L} if this
     *         never occurred
     */
    public abstract @NonNull LiveData<Long> getLastCancelAllTimeMillisLiveData();

    /**
     * Gets a {@link ListenableFuture} of the last time all work was cancelled.  This method is
     * intended for use by library and module developers who have dependent data in their own
     * repository that must be updated or deleted in case someone cancels their work without
     * their prior knowledge.
     *
     * @return A {@link ListenableFuture} of the timestamp ({@code System#getCurrentTimeMillis()})
     *         when {@link #cancelAllWork()} was last invoked; this timestamp may be {@code 0L} if
     *         this never occurred
     */
    public abstract @NonNull ListenableFuture<Long> getLastCancelAllTimeMillis();

    /**
     * Gets a {@link LiveData} of the {@link WorkInfo} for a given work id.
     *
     * @param id The id of the work
     * @return A {@link LiveData} of the {@link WorkInfo} associated with {@code id}; note that
     *         this {@link WorkInfo} may be {@code null} if {@code id} is not known to
     *         WorkManager.
     */
    public abstract @NonNull LiveData<WorkInfo> getWorkInfoByIdLiveData(@NonNull UUID id);

    /**
     * Gets a {@link ListenableFuture} of the {@link WorkInfo} for a given work id.
     *
     * @param id The id of the work
     * @return A {@link ListenableFuture} of the {@link WorkInfo} associated with {@code id};
     * note that this {@link WorkInfo} may be {@code null} if {@code id} is not known to
     * WorkManager
     */
    public abstract @NonNull ListenableFuture<WorkInfo> getWorkInfoById(@NonNull UUID id);

    /**
     * Gets a {@link LiveData} of the {@link WorkInfo} for all work for a given tag.
     *
     * @param tag The tag of the work
     * @return A {@link LiveData} list of {@link WorkInfo} for work tagged with {@code tag}
     */
    public abstract @NonNull LiveData<List<WorkInfo>> getWorkInfosByTagLiveData(
            @NonNull String tag);

    /**
     * Gets a {@link ListenableFuture} of the {@link WorkInfo} for all work for a given tag.
     *
     * @param tag The tag of the work
     * @return A {@link ListenableFuture} list of {@link WorkInfo} for work tagged with
     * {@code tag}
     */
    public abstract @NonNull ListenableFuture<List<WorkInfo>> getWorkInfosByTag(
            @NonNull String tag);

    /**
     * Gets a {@link LiveData} of the {@link WorkInfo} for all work in a work chain with a given
     * unique name.
     *
     * @param uniqueWorkName The unique name used to identify the chain of work
     * @return A {@link LiveData} of the {@link WorkInfo} for work in the chain named
     *         {@code uniqueWorkName}
     */
    public abstract @NonNull LiveData<List<WorkInfo>> getWorkInfosForUniqueWorkLiveData(
            @NonNull String uniqueWorkName);

    /**
     * Gets a {@link ListenableFuture} of the {@link WorkInfo} for all work in a work chain
     * with a given unique name.
     *
     * @param uniqueWorkName The unique name used to identify the chain of work
     * @return A {@link ListenableFuture} of the {@link WorkInfo} for work in the chain named
     *         {@code uniqueWorkName}
     */
    public abstract @NonNull ListenableFuture<List<WorkInfo>> getWorkInfosForUniqueWork(
            @NonNull String uniqueWorkName);

    /**
     * Gets the {@link LiveData} of the {@link List} of {@link WorkInfo} for all work
     * referenced by the {@link WorkQuery} specification.
     *
     * @param workQuery The work query specification
     * @return A {@link LiveData} of the {@link List} of {@link WorkInfo} for work
     * referenced by this {@link WorkQuery}.
     */
    public abstract @NonNull LiveData<List<WorkInfo>> getWorkInfosLiveData(
            @NonNull WorkQuery workQuery);

    /**
     * Gets the {@link ListenableFuture} of the {@link List} of {@link WorkInfo} for all work
     * referenced by the {@link WorkQuery} specification.
     *
     * @param workQuery The work query specification
     * @return A {@link ListenableFuture} of the {@link List} of {@link WorkInfo} for work
     * referenced by this {@link WorkQuery}.
     */
    public abstract @NonNull ListenableFuture<List<WorkInfo>> getWorkInfos(
            @NonNull WorkQuery workQuery);

    /**
     * @hide
     */
    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
    protected WorkManager() {
    }
}