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();
}
/**