RescheduleReceiver does not do nothing for 8s anymore.

- RescheduleReceiver tells WorkManagerImpl about the PendingResult after
a call to goAsync().
- Once ForceStopRunnable is done, it calls
WorkManagerImpl#onForceStopCompleted. This calls PendingResult#finish()
if one exists.

Test: Updated unit tests.
Change-Id: I671494023457166824e1e2f787722fe801442637
diff --git a/work/workmanager/src/androidTest/java/androidx/work/impl/utils/ForceStopRunnableTest.java b/work/workmanager/src/androidTest/java/androidx/work/impl/utils/ForceStopRunnableTest.java
index c706e40..3d6b4c0 100644
--- a/work/workmanager/src/androidTest/java/androidx/work/impl/utils/ForceStopRunnableTest.java
+++ b/work/workmanager/src/androidTest/java/androidx/work/impl/utils/ForceStopRunnableTest.java
@@ -79,6 +79,7 @@
         when(runnable.isForceStopped()).thenReturn(true);
         runnable.run();
         verify(mWorkManager, times(1)).rescheduleEligibleWork();
+        verify(mWorkManager, times(1)).onForceStopRunnableCompleted();
     }
 
     @Test
@@ -88,6 +89,7 @@
         when(runnable.isForceStopped()).thenReturn(false);
         runnable.run();
         verify(mWorkManager, times(0)).rescheduleEligibleWork();
+        verify(mWorkManager, times(1)).onForceStopRunnableCompleted();
     }
 
     @Test
diff --git a/work/workmanager/src/main/java/androidx/work/impl/WorkManagerImpl.java b/work/workmanager/src/main/java/androidx/work/impl/WorkManagerImpl.java
index 6e97b53..763a454 100644
--- a/work/workmanager/src/main/java/androidx/work/impl/WorkManagerImpl.java
+++ b/work/workmanager/src/main/java/androidx/work/impl/WorkManagerImpl.java
@@ -18,6 +18,7 @@
 
 import android.arch.core.util.Function;
 import android.arch.lifecycle.LiveData;
+import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.os.Build;
 import android.os.Looper;
@@ -74,6 +75,8 @@
     private List<Scheduler> mSchedulers;
     private Processor mProcessor;
     private Preferences mPreferences;
+    private boolean mForceStopRunnableCompleted;
+    private BroadcastReceiver.PendingResult mRescheduleReceiverResult;
 
     private static WorkManagerImpl sDelegatedInstance = null;
     private static WorkManagerImpl sDefaultInstance = null;
@@ -174,6 +177,7 @@
                 getSchedulers(),
                 configuration.getExecutor());
         mPreferences = new Preferences(mContext);
+        mForceStopRunnableCompleted = false;
 
         // Checks for app force stops.
         mTaskExecutor.executeOnBackgroundThread(new ForceStopRunnable(context, this));
@@ -527,6 +531,42 @@
         Schedulers.schedule(getConfiguration(), getWorkDatabase(), getSchedulers());
     }
 
+    /**
+     * A way for {@link ForceStopRunnable} to tell {@link WorkManagerImpl} that it has completed.
+     *
+     * @hide
+     */
+    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+    public void onForceStopRunnableCompleted() {
+        synchronized (sLock) {
+            mForceStopRunnableCompleted = true;
+            if (mRescheduleReceiverResult != null) {
+                mRescheduleReceiverResult.finish();
+                mRescheduleReceiverResult = null;
+            }
+        }
+    }
+
+    /**
+     * This method is invoked by
+     * {@link androidx.work.impl.background.systemalarm.RescheduleReceiver}
+     * after a call to {@link BroadcastReceiver#goAsync()}. Once {@link ForceStopRunnable} is done,
+     * we can safely call {@link BroadcastReceiver.PendingResult#finish()}.
+     *
+     * @hide
+     */
+    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+    public void setReschedulePendingResult(
+            @NonNull BroadcastReceiver.PendingResult rescheduleReceiverResult) {
+        synchronized (sLock) {
+            mRescheduleReceiverResult = rescheduleReceiverResult;
+            if (mForceStopRunnableCompleted) {
+                mRescheduleReceiverResult.finish();
+                mRescheduleReceiverResult = null;
+            }
+        }
+    }
+
     private void assertBackgroundThread(String errorMessage) {
         if (Looper.getMainLooper().getThread() == Thread.currentThread()) {
             throw new IllegalStateException(errorMessage);
diff --git a/work/workmanager/src/main/java/androidx/work/impl/background/systemalarm/RescheduleReceiver.java b/work/workmanager/src/main/java/androidx/work/impl/background/systemalarm/RescheduleReceiver.java
index 248c761..b8adec2 100644
--- a/work/workmanager/src/main/java/androidx/work/impl/background/systemalarm/RescheduleReceiver.java
+++ b/work/workmanager/src/main/java/androidx/work/impl/background/systemalarm/RescheduleReceiver.java
@@ -20,15 +20,10 @@
 import android.content.Context;
 import android.content.Intent;
 import android.os.Build;
-import android.os.Handler;
-import android.os.Looper;
 import android.util.Log;
 
-import androidx.work.WorkManager;
 import androidx.work.impl.WorkManagerImpl;
 
-import java.util.concurrent.TimeUnit;
-
 /**
  * Reschedules alarms on BOOT_COMPLETED and other similar scenarios.
  */
@@ -39,25 +34,15 @@
     @Override
     public void onReceive(Context context, Intent intent) {
         if (Build.VERSION.SDK_INT >= WorkManagerImpl.MIN_JOB_SCHEDULER_API_LEVEL) {
-            if (WorkManager.getInstance() == null) {
+            WorkManagerImpl workManager = WorkManagerImpl.getInstance();
+            if (workManager == null) {
                 // WorkManager has not already been initialized.
                 Log.e(TAG,
                         "Cannot reschedule jobs. WorkManager needs to be initialized via a "
                                 + "ContentProvider#onCreate() or an Application#onCreate().");
             } else {
-                // This helps set up rescheduling of Jobs with JobScheduler. We are doing nothing
-                // for 8 seconds, to give ForceStopRunnable a chance to reschedule. Using 8 seconds
-                // instead of 10 seconds, because the OS starts the ANR timer before the call to
-                // onReceive().
-                Handler handler = new Handler(Looper.getMainLooper());
                 final PendingResult pendingResult = goAsync();
-                handler.postDelayed(new Runnable() {
-                    @Override
-                    public void run() {
-                        pendingResult.finish();
-                    }
-                }, TimeUnit.SECONDS.toMillis(8));
-
+                workManager.setReschedulePendingResult(pendingResult);
             }
         } else {
             Intent reschedule = CommandHandler.createRescheduleIntent(context);
diff --git a/work/workmanager/src/main/java/androidx/work/impl/utils/ForceStopRunnable.java b/work/workmanager/src/main/java/androidx/work/impl/utils/ForceStopRunnable.java
index fbcaa42..c01e4fd 100644
--- a/work/workmanager/src/main/java/androidx/work/impl/utils/ForceStopRunnable.java
+++ b/work/workmanager/src/main/java/androidx/work/impl/utils/ForceStopRunnable.java
@@ -73,6 +73,7 @@
             Log.d(TAG, "Application was force-stopped, rescheduling.");
             mWorkManager.rescheduleEligibleWork();
         }
+        mWorkManager.onForceStopRunnableCompleted();
     }
 
     /**