aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorandroid-build-team Robot <android-build-team-robot@google.com>2018-06-10 19:02:31 +0000
committerandroid-build-team Robot <android-build-team-robot@google.com>2018-06-10 19:02:31 +0000
commitae78fb8a99ef9b253681ce60ac5f3be0b9c77c0f (patch)
treecf8c59fcb5503ff0bb68838949efeaa2c145b766
parente5abe2d3eaf16febb29c11708b431f90e2e81289 (diff)
parentf0a0a39e63da4265934e8bead2ddc619465371cd (diff)
downloadsupport-android-cts-9.0_r19.tar.gz
Snap for 4832339 from f0a0a39e63da4265934e8bead2ddc619465371cd to pi-releaseandroid-wear-9.0.0_r9android-wear-9.0.0_r8android-wear-9.0.0_r7android-wear-9.0.0_r6android-wear-9.0.0_r5android-wear-9.0.0_r4android-wear-9.0.0_r34android-wear-9.0.0_r33android-wear-9.0.0_r32android-wear-9.0.0_r31android-wear-9.0.0_r30android-wear-9.0.0_r3android-wear-9.0.0_r29android-wear-9.0.0_r28android-wear-9.0.0_r27android-wear-9.0.0_r26android-wear-9.0.0_r25android-wear-9.0.0_r24android-wear-9.0.0_r23android-wear-9.0.0_r22android-wear-9.0.0_r21android-wear-9.0.0_r20android-wear-9.0.0_r2android-wear-9.0.0_r19android-wear-9.0.0_r18android-wear-9.0.0_r17android-wear-9.0.0_r16android-wear-9.0.0_r15android-wear-9.0.0_r14android-wear-9.0.0_r13android-wear-9.0.0_r12android-wear-9.0.0_r11android-wear-9.0.0_r10android-wear-9.0.0_r1android-vts-9.0_r9android-vts-9.0_r8android-vts-9.0_r7android-vts-9.0_r6android-vts-9.0_r5android-vts-9.0_r4android-vts-9.0_r19android-vts-9.0_r18android-vts-9.0_r17android-vts-9.0_r16android-vts-9.0_r15android-vts-9.0_r14android-vts-9.0_r13android-vts-9.0_r12android-vts-9.0_r11android-vts-9.0_r10android-security-9.0.0_r76android-security-9.0.0_r75android-security-9.0.0_r74android-security-9.0.0_r73android-security-9.0.0_r72android-security-9.0.0_r71android-security-9.0.0_r70android-security-9.0.0_r69android-security-9.0.0_r68android-security-9.0.0_r67android-security-9.0.0_r66android-security-9.0.0_r65android-security-9.0.0_r64android-security-9.0.0_r63android-security-9.0.0_r62android-cts-9.0_r9android-cts-9.0_r8android-cts-9.0_r7android-cts-9.0_r6android-cts-9.0_r5android-cts-9.0_r4android-cts-9.0_r3android-cts-9.0_r20android-cts-9.0_r2android-cts-9.0_r19android-cts-9.0_r18android-cts-9.0_r17android-cts-9.0_r16android-cts-9.0_r15android-cts-9.0_r14android-cts-9.0_r13android-cts-9.0_r12android-cts-9.0_r11android-cts-9.0_r10android-cts-9.0_r1android-9.0.0_r9android-9.0.0_r8android-9.0.0_r7android-9.0.0_r61android-9.0.0_r60android-9.0.0_r6android-9.0.0_r59android-9.0.0_r58android-9.0.0_r57android-9.0.0_r56android-9.0.0_r55android-9.0.0_r54android-9.0.0_r53android-9.0.0_r52android-9.0.0_r51android-9.0.0_r50android-9.0.0_r5android-9.0.0_r49android-9.0.0_r48android-9.0.0_r3android-9.0.0_r2android-9.0.0_r18android-9.0.0_r17android-9.0.0_r10android-9.0.0_r1security-pi-releasepie-vts-releasepie-security-releasepie-s2-releasepie-release-2pie-releasepie-r2-s2-releasepie-r2-s1-releasepie-r2-releasepie-cts-release
Change-Id: If085d5207d41cfdc6d1a3bbcf62106ae510dad29
-rw-r--r--buildSrc/src/main/kotlin/androidx/build/PublishDocsRules.kt19
-rw-r--r--work/workmanager-firebase/src/main/java/androidx/work/impl/background/firebase/FirebaseDelayedJobAlarmReceiver.java4
-rw-r--r--work/workmanager/src/androidTest/java/androidx/work/WorkDatabaseMigrationTest.java49
-rw-r--r--work/workmanager/src/androidTest/java/androidx/work/WorkSpecDaoTest.java14
-rw-r--r--work/workmanager/src/androidTest/java/androidx/work/impl/ProcessorTest.java3
-rw-r--r--work/workmanager/src/androidTest/java/androidx/work/impl/WorkContinuationImplTest.java14
-rw-r--r--work/workmanager/src/androidTest/java/androidx/work/impl/WorkManagerImplLargeExecutorTest.java82
-rw-r--r--work/workmanager/src/androidTest/java/androidx/work/impl/WorkManagerImplTest.java78
-rw-r--r--work/workmanager/src/androidTest/java/androidx/work/impl/WorkerWrapperTest.java84
-rw-r--r--work/workmanager/src/androidTest/java/androidx/work/impl/background/systemalarm/SystemAlarmDispatcherTest.java5
-rw-r--r--work/workmanager/src/androidTest/java/androidx/work/impl/workers/ConstraintTrackingWorkerTest.java17
-rw-r--r--work/workmanager/src/androidTest/java/androidx/work/worker/CheckLimitsWorker.java56
-rw-r--r--work/workmanager/src/main/java/androidx/work/Configuration.java56
-rw-r--r--work/workmanager/src/main/java/androidx/work/SynchronousWorkManager.java15
-rw-r--r--work/workmanager/src/main/java/androidx/work/WorkManager.java14
-rw-r--r--work/workmanager/src/main/java/androidx/work/WorkRequest.java1
-rw-r--r--work/workmanager/src/main/java/androidx/work/impl/Processor.java17
-rw-r--r--work/workmanager/src/main/java/androidx/work/impl/Schedulers.java6
-rw-r--r--work/workmanager/src/main/java/androidx/work/impl/WorkDatabaseMigrations.java17
-rw-r--r--work/workmanager/src/main/java/androidx/work/impl/WorkManagerImpl.java18
-rw-r--r--work/workmanager/src/main/java/androidx/work/impl/WorkerWrapper.java10
-rw-r--r--work/workmanager/src/main/java/androidx/work/impl/background/systemalarm/ConstraintsCommandHandler.java7
-rw-r--r--work/workmanager/src/main/java/androidx/work/impl/model/SystemIdInfo.java3
-rw-r--r--work/workmanager/src/main/java/androidx/work/impl/model/SystemIdInfoDao.java4
-rw-r--r--work/workmanager/src/main/java/androidx/work/impl/model/WorkSpecDao.java18
-rw-r--r--work/workmanager/src/main/java/androidx/work/impl/utils/CancelWorkRunnable.java5
-rw-r--r--work/workmanager/src/main/java/androidx/work/impl/utils/EnqueueRunnable.java5
-rw-r--r--work/workmanager/src/main/java/androidx/work/impl/utils/PruneWorkRunnable.java47
-rw-r--r--work/workmanager/src/schemas/androidx.work.impl.WorkDatabase/2.json6
29 files changed, 547 insertions, 127 deletions
diff --git a/buildSrc/src/main/kotlin/androidx/build/PublishDocsRules.kt b/buildSrc/src/main/kotlin/androidx/build/PublishDocsRules.kt
index a40d6d938b0..62e8c5b8bc5 100644
--- a/buildSrc/src/main/kotlin/androidx/build/PublishDocsRules.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/PublishDocsRules.kt
@@ -24,7 +24,7 @@ import androidx.build.Strategy.Prebuilts
import androidx.build.Strategy.Ignore
val RELEASE_RULE = docsRules("public") {
- val defaultVersion = "1.0.0-alpha1"
+ val defaultVersion = "1.0.0-alpha3"
prebuilts(LibraryGroups.ANNOTATION, defaultVersion)
prebuilts(LibraryGroups.APPCOMPAT, defaultVersion)
prebuilts(LibraryGroups.ASYNCLAYOUTINFLATER, defaultVersion)
@@ -33,9 +33,7 @@ val RELEASE_RULE = docsRules("public") {
.addStubs("car/car-stubs/android.car.jar")
prebuilts(LibraryGroups.CARDVIEW, defaultVersion)
prebuilts(LibraryGroups.COLLECTION, defaultVersion)
- // misses prebuilts, because it was released under different name in alpha1
- tipOfTree(LibraryGroups.CONTENTPAGER)
-
+ prebuilts(LibraryGroups.CONTENTPAGER, defaultVersion)
prebuilts(LibraryGroups.COORDINATORLAYOUT, defaultVersion)
prebuilts(LibraryGroups.CORE, defaultVersion)
prebuilts(LibraryGroups.CURSORADAPTER, defaultVersion)
@@ -57,7 +55,6 @@ val RELEASE_RULE = docsRules("public") {
prebuilts(LibraryGroups.MEDIAROUTER, defaultVersion)
prebuilts(LibraryGroups.PALETTE, defaultVersion)
prebuilts(LibraryGroups.PERCENTLAYOUT, defaultVersion)
- ignore(LibraryGroups.PREFERENCE, "preference-ktx")
prebuilts(LibraryGroups.PREFERENCE, defaultVersion)
prebuilts(LibraryGroups.PRINT, defaultVersion)
prebuilts(LibraryGroups.RECOMMENDATION, defaultVersion)
@@ -76,17 +73,11 @@ val RELEASE_RULE = docsRules("public") {
val flatfootVersion = "2.0.0-alpha1"
prebuilts(LibraryGroups.ROOM, flatfootVersion)
prebuilts(LibraryGroups.PERSISTENCE, flatfootVersion)
- // lifecycle-viewmodel-ktx / lifecycle-process / lifecycle-service miss their prebuilts
- tipOfTree(LibraryGroups.LIFECYCLE, "lifecycle-viewmodel-ktx")
- tipOfTree(LibraryGroups.LIFECYCLE, "lifecycle-process")
- tipOfTree(LibraryGroups.LIFECYCLE, "lifecycle-service")
prebuilts(LibraryGroups.LIFECYCLE, flatfootVersion)
prebuilts(LibraryGroups.ARCH_CORE, flatfootVersion)
- prebuilts(LibraryGroups.PAGING, "paging-rxjava2", "1.0.0-alpha1")
- prebuilts(LibraryGroups.PAGING, "2.0.0-alpha1")
- // navigation & workmanager don't have prebuilts currently
- tipOfTree(LibraryGroups.NAVIGATION)
- tipOfTree(LibraryGroups.WORKMANAGER)
+ prebuilts(LibraryGroups.PAGING, flatfootVersion)
+ prebuilts(LibraryGroups.NAVIGATION, "1.0.0-alpha01")
+ prebuilts(LibraryGroups.WORKMANAGER, "1.0.0-alpha02")
default(Ignore)
}
diff --git a/work/workmanager-firebase/src/main/java/androidx/work/impl/background/firebase/FirebaseDelayedJobAlarmReceiver.java b/work/workmanager-firebase/src/main/java/androidx/work/impl/background/firebase/FirebaseDelayedJobAlarmReceiver.java
index f17fde4dbb0..5e549d25093 100644
--- a/work/workmanager-firebase/src/main/java/androidx/work/impl/background/firebase/FirebaseDelayedJobAlarmReceiver.java
+++ b/work/workmanager-firebase/src/main/java/androidx/work/impl/background/firebase/FirebaseDelayedJobAlarmReceiver.java
@@ -21,6 +21,7 @@ import android.content.Intent;
import android.support.annotation.RestrictTo;
import android.util.Log;
+import androidx.work.Configuration;
import androidx.work.impl.Schedulers;
import androidx.work.impl.WorkDatabase;
import androidx.work.impl.WorkManagerImpl;
@@ -41,6 +42,7 @@ public class FirebaseDelayedJobAlarmReceiver extends BroadcastReceiver {
final PendingResult pendingResult = goAsync();
final String workSpecId = intent.getStringExtra(WORKSPEC_ID_KEY);
final WorkManagerImpl workManagerImpl = WorkManagerImpl.getInstance();
+ final Configuration configuration = workManagerImpl.getConfiguration();
final WorkDatabase database = workManagerImpl.getWorkDatabase();
// TODO (rahulrav@) Use WorkManager's task executor here instead.
new Thread(new Runnable() {
@@ -48,7 +50,7 @@ public class FirebaseDelayedJobAlarmReceiver extends BroadcastReceiver {
public void run() {
WorkSpec workSpec = database.workSpecDao().getWorkSpec(workSpecId);
if (workSpec != null) {
- Schedulers.schedule(database, workManagerImpl.getSchedulers());
+ Schedulers.schedule(configuration, database, workManagerImpl.getSchedulers());
} else {
Log.e(TAG, "WorkSpec not found! Cannot schedule!");
}
diff --git a/work/workmanager/src/androidTest/java/androidx/work/WorkDatabaseMigrationTest.java b/work/workmanager/src/androidTest/java/androidx/work/WorkDatabaseMigrationTest.java
index 1c1893f2cf4..c1311173b1c 100644
--- a/work/workmanager/src/androidTest/java/androidx/work/WorkDatabaseMigrationTest.java
+++ b/work/workmanager/src/androidTest/java/androidx/work/WorkDatabaseMigrationTest.java
@@ -16,12 +16,15 @@
package androidx.work;
+import static android.database.sqlite.SQLiteDatabase.CONFLICT_FAIL;
+
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import android.arch.persistence.db.SupportSQLiteDatabase;
import android.arch.persistence.db.framework.FrameworkSQLiteOpenHelperFactory;
import android.arch.persistence.room.testing.MigrationTestHelper;
+import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteException;
import android.support.test.InstrumentationRegistry;
@@ -30,6 +33,9 @@ import android.support.test.runner.AndroidJUnit4;
import androidx.work.impl.WorkDatabase;
import androidx.work.impl.WorkDatabaseMigrations;
+import androidx.work.impl.model.WorkSpec;
+import androidx.work.impl.model.WorkTypeConverters;
+import androidx.work.worker.TestWorker;
import org.junit.Before;
import org.junit.Rule;
@@ -53,12 +59,12 @@ public class WorkDatabaseMigrationTest {
// Queries
private static final String INSERT_ALARM_INFO = "INSERT INTO alarmInfo VALUES (?, ?)";
- private static final String INSERT_SYSTEM_ID_INFO = "INSERT INTO systemIdInfo VALUES (?, ?)";
- private static final String CHECK_SYSTEM_ID_INFO = "SELECT * FROM systemIdInfo";
+ private static final String INSERT_SYSTEM_ID_INFO = "INSERT INTO SystemIdInfo VALUES (?, ?)";
+ private static final String CHECK_SYSTEM_ID_INFO = "SELECT * FROM SystemIdInfo";
private static final String CHECK_ALARM_INFO = "SELECT * FROM alarmInfo";
private static final String CHECK_TABLE_NAME = "SELECT * FROM %s";
private static final String TABLE_ALARM_INFO = "alarmInfo";
- private static final String TABLE_SYSTEM_ID_INFO = "systemIdInfo";
+ private static final String TABLE_SYSTEM_ID_INFO = "SystemIdInfo";
private static final String TABLE_WORKSPEC = "WorkSpec";
private static final String TABLE_WORKTAG = "WorkTag";
private static final String TABLE_WORKNAME = "WorkName";
@@ -86,6 +92,33 @@ public class WorkDatabaseMigrationTest {
SupportSQLiteDatabase database =
mMigrationTestHelper.createDatabase(TEST_DATABASE, OLD_VERSION);
+ String workSpecId0 = UUID.randomUUID().toString();
+ ContentValues contentValues = new ContentValues();
+ contentValues.put("id", workSpecId0);
+ contentValues.put("state", WorkTypeConverters.StateIds.ENQUEUED);
+ contentValues.put("worker_class_name", TestWorker.class.getName());
+ contentValues.put("input_merger_class_name", OverwritingInputMerger.class.getName());
+ contentValues.put("input", Data.toByteArray(Data.EMPTY));
+ contentValues.put("output", Data.toByteArray(Data.EMPTY));
+ contentValues.put("initial_delay", 0L);
+ contentValues.put("interval_duration", 0L);
+ contentValues.put("flex_duration", 0L);
+ contentValues.put("required_network_type", false);
+ contentValues.put("requires_charging", false);
+ contentValues.put("requires_device_idle", false);
+ contentValues.put("requires_battery_not_low", false);
+ contentValues.put("requires_storage_not_low", false);
+ contentValues.put("content_uri_triggers",
+ WorkTypeConverters.contentUriTriggersToByteArray(new ContentUriTriggers()));
+ contentValues.put("run_attempt_count", 0);
+ contentValues.put("backoff_policy",
+ WorkTypeConverters.backoffPolicyToInt(BackoffPolicy.EXPONENTIAL));
+ contentValues.put("backoff_delay_duration", WorkRequest.DEFAULT_BACKOFF_DELAY_MILLIS);
+ contentValues.put("period_start_time", 0L);
+ contentValues.put("minimum_retention_duration", 0L);
+ contentValues.put("schedule_requested_at", WorkSpec.SCHEDULE_NOT_REQUESTED_YET);
+ database.insert("workspec", CONFLICT_FAIL, contentValues);
+
String workSpecId1 = UUID.randomUUID().toString();
String workSpecId2 = UUID.randomUUID().toString();
@@ -101,6 +134,14 @@ public class WorkDatabaseMigrationTest {
VALIDATE_DROPPED_TABLES,
WorkDatabaseMigrations.MIGRATION_1_2);
+ Cursor tagCursor = database.query("SELECT * FROM worktag");
+ assertThat(tagCursor.getCount(), is(1));
+ tagCursor.moveToFirst();
+ assertThat(tagCursor.getString(tagCursor.getColumnIndex("tag")),
+ is(TestWorker.class.getName()));
+ assertThat(tagCursor.getString(tagCursor.getColumnIndex("work_spec_id")), is(workSpecId0));
+ tagCursor.close();
+
Cursor cursor = database.query(CHECK_SYSTEM_ID_INFO);
assertThat(cursor.getCount(), is(2));
cursor.moveToFirst();
@@ -127,7 +168,7 @@ public class WorkDatabaseMigrationTest {
String workSpecId1 = UUID.randomUUID().toString();
String workSpecId2 = UUID.randomUUID().toString();
- // insert systemIdInfo
+ // insert SystemIdInfo
database.execSQL(INSERT_SYSTEM_ID_INFO, new Object[]{workSpecId1, 1});
database.execSQL(INSERT_SYSTEM_ID_INFO, new Object[]{workSpecId2, 2});
diff --git a/work/workmanager/src/androidTest/java/androidx/work/WorkSpecDaoTest.java b/work/workmanager/src/androidTest/java/androidx/work/WorkSpecDaoTest.java
index da5a8e019e9..6dd23cbfa81 100644
--- a/work/workmanager/src/androidTest/java/androidx/work/WorkSpecDaoTest.java
+++ b/work/workmanager/src/androidTest/java/androidx/work/WorkSpecDaoTest.java
@@ -19,6 +19,7 @@ package androidx.work;
import static androidx.work.State.BLOCKED;
import static androidx.work.State.FAILED;
import static androidx.work.State.SUCCEEDED;
+import static androidx.work.impl.Scheduler.MAX_SCHEDULER_LIMIT;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
@@ -70,7 +71,9 @@ public class WorkSpecDaoTest extends DatabaseTest {
WorkSpecDao workSpecDao = mDatabase.workSpecDao();
// Treat the scheduled request as previously scheduled
workSpecDao.markWorkSpecScheduled(scheduled.getStringId(), System.currentTimeMillis());
- List<WorkSpec> eligibleWorkSpecs = workSpecDao.getEligibleWorkForScheduling();
+ List<WorkSpec> eligibleWorkSpecs =
+ workSpecDao.getEligibleWorkForScheduling(MAX_SCHEDULER_LIMIT);
+
assertThat(eligibleWorkSpecs.size(), equalTo(2));
assertThat(eligibleWorkSpecs,
containsInAnyOrder(work.getWorkSpec(), enqueued.getWorkSpec()));
@@ -100,7 +103,8 @@ public class WorkSpecDaoTest extends DatabaseTest {
insertWork(succeeded);
insertWork(failed);
- List<WorkSpec> eligibleWorkSpecs = workSpecDao.getEligibleWorkForScheduling();
+ List<WorkSpec> eligibleWorkSpecs =
+ workSpecDao.getEligibleWorkForScheduling(MAX_SCHEDULER_LIMIT);
assertThat(eligibleWorkSpecs, notNullValue());
assertThat(eligibleWorkSpecs.size(), is(1));
assertThat(eligibleWorkSpecs, containsInAnyOrder(enqueued.getWorkSpec()));
@@ -131,7 +135,8 @@ public class WorkSpecDaoTest extends DatabaseTest {
insertWork(succeeded);
insertWork(failed);
- List<WorkSpec> eligibleWorkSpecs = workSpecDao.getEligibleWorkForScheduling();
+ List<WorkSpec> eligibleWorkSpecs =
+ workSpecDao.getEligibleWorkForScheduling(MAX_SCHEDULER_LIMIT);
assertThat(eligibleWorkSpecs, notNullValue());
assertThat(eligibleWorkSpecs.size(), is(0));
}
@@ -171,7 +176,8 @@ public class WorkSpecDaoTest extends DatabaseTest {
workSpecDao.resetScheduledState();
- List<WorkSpec> eligibleWorkSpecs = workSpecDao.getEligibleWorkForScheduling();
+ List<WorkSpec> eligibleWorkSpecs =
+ workSpecDao.getEligibleWorkForScheduling(MAX_SCHEDULER_LIMIT);
assertThat(eligibleWorkSpecs.size(), is(1));
// Not using contains in any order as the scheduleRequestedAt changes post reset.
assertThat(eligibleWorkSpecs.get(0).id, is(enqueued.getStringId()));
diff --git a/work/workmanager/src/androidTest/java/androidx/work/impl/ProcessorTest.java b/work/workmanager/src/androidTest/java/androidx/work/impl/ProcessorTest.java
index cfaa1f38571..1e178b1d471 100644
--- a/work/workmanager/src/androidTest/java/androidx/work/impl/ProcessorTest.java
+++ b/work/workmanager/src/androidTest/java/androidx/work/impl/ProcessorTest.java
@@ -25,6 +25,7 @@ import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
+import androidx.work.Configuration;
import androidx.work.DatabaseTest;
import androidx.work.OneTimeWorkRequest;
import androidx.work.worker.InfiniteTestWorker;
@@ -43,8 +44,10 @@ public class ProcessorTest extends DatabaseTest {
@Before
public void setUp() {
Context appContext = InstrumentationRegistry.getTargetContext().getApplicationContext();
+ Configuration configuration = new Configuration.Builder().build();
mProcessor = new Processor(
appContext,
+ configuration,
mDatabase,
Collections.singletonList(mock(Scheduler.class)),
Executors.newSingleThreadScheduledExecutor()) {
diff --git a/work/workmanager/src/androidTest/java/androidx/work/impl/WorkContinuationImplTest.java b/work/workmanager/src/androidTest/java/androidx/work/impl/WorkContinuationImplTest.java
index 778320853f7..f4a3a7b09be 100644
--- a/work/workmanager/src/androidTest/java/androidx/work/impl/WorkContinuationImplTest.java
+++ b/work/workmanager/src/androidTest/java/androidx/work/impl/WorkContinuationImplTest.java
@@ -72,6 +72,7 @@ import java.util.concurrent.Executors;
@SmallTest
public class WorkContinuationImplTest extends WorkManagerTest {
+ private Configuration mConfiguration;
private WorkDatabase mDatabase;
private WorkManagerImpl mWorkManagerImpl;
private Scheduler mScheduler;
@@ -103,11 +104,11 @@ public class WorkContinuationImplTest extends WorkManagerTest {
mScheduler = mock(Scheduler.class);
Context context = InstrumentationRegistry.getTargetContext();
- Configuration configuration = new Configuration.Builder()
+ mConfiguration = new Configuration.Builder()
.setExecutor(Executors.newSingleThreadExecutor())
.build();
- mWorkManagerImpl = spy(new WorkManagerImpl(context, configuration));
+ mWorkManagerImpl = spy(new WorkManagerImpl(context, mConfiguration));
when(mWorkManagerImpl.getSchedulers()).thenReturn(Collections.singletonList(mScheduler));
WorkManagerImpl.setDelegate(mWorkManagerImpl);
mDatabase = mWorkManagerImpl.getWorkDatabase();
@@ -306,7 +307,8 @@ public class WorkContinuationImplTest extends WorkManagerTest {
// TODO(sumir): I can't seem to get this kicked off automatically, so I'm running it myself.
// Figure out what's going on here.
- new WorkerWrapper.Builder(InstrumentationRegistry.getTargetContext(), mDatabase, joinId)
+ Context context = InstrumentationRegistry.getTargetContext();
+ new WorkerWrapper.Builder(context, mConfiguration, mDatabase, joinId)
.build()
.run();
@@ -514,6 +516,7 @@ public class WorkContinuationImplTest extends WorkManagerTest {
}
private static void verifyScheduled(Scheduler scheduler, WorkContinuationImpl continuation) {
+ Configuration configuration = continuation.getWorkManagerImpl().getConfiguration();
ArgumentCaptor<WorkSpec> captor = ArgumentCaptor.forClass(WorkSpec.class);
verify(scheduler, times(1)).schedule(captor.capture());
List<WorkSpec> workSpecs = captor.getAllValues();
@@ -521,7 +524,10 @@ public class WorkContinuationImplTest extends WorkManagerTest {
WorkDatabase workDatabase = continuation.getWorkManagerImpl().getWorkDatabase();
List<WorkSpec> eligibleWorkSpecs =
- workDatabase.workSpecDao().getEligibleWorkForScheduling();
+ workDatabase
+ .workSpecDao()
+ .getEligibleWorkForScheduling(
+ configuration.getMaxSchedulerLimit());
Set<String> capturedIds = new HashSet<>();
for (WorkSpec workSpec : workSpecs) {
diff --git a/work/workmanager/src/androidTest/java/androidx/work/impl/WorkManagerImplLargeExecutorTest.java b/work/workmanager/src/androidTest/java/androidx/work/impl/WorkManagerImplLargeExecutorTest.java
index 51e98e5728d..72ebe944b00 100644
--- a/work/workmanager/src/androidTest/java/androidx/work/impl/WorkManagerImplLargeExecutorTest.java
+++ b/work/workmanager/src/androidTest/java/androidx/work/impl/WorkManagerImplLargeExecutorTest.java
@@ -16,25 +16,33 @@
package androidx.work.impl;
+import static androidx.work.worker.CheckLimitsWorker.KEY_EXCEEDS_SCHEDULER_LIMIT;
+import static androidx.work.worker.CheckLimitsWorker.KEY_LIMIT_TO_ENFORCE;
+
+import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.lessThanOrEqualTo;
import static java.util.concurrent.TimeUnit.SECONDS;
import android.arch.core.executor.ArchTaskExecutor;
import android.arch.core.executor.TaskExecutor;
+import android.arch.lifecycle.Observer;
import android.content.Context;
import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.LargeTest;
import android.support.test.filters.SdkSuppress;
import android.support.test.runner.AndroidJUnit4;
import androidx.work.Configuration;
+import androidx.work.Data;
import androidx.work.OneTimeWorkRequest;
-import androidx.work.impl.model.WorkSpec;
+import androidx.work.TestLifecycleOwner;
+import androidx.work.WorkContinuation;
+import androidx.work.WorkStatus;
import androidx.work.impl.utils.taskexecutor.InstantTaskExecutorRule;
-import androidx.work.worker.TestWorker;
+import androidx.work.worker.CheckLimitsWorker;
import org.junit.After;
import org.junit.Before;
@@ -42,16 +50,23 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.util.ArrayList;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
+import java.util.UUID;
import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
@RunWith(AndroidJUnit4.class)
public class WorkManagerImplLargeExecutorTest {
private static final int NUM_WORKERS = 500;
+ private static final int TEST_TIMEOUT_SECONDS = 30;
// ThreadPoolExecutor parameters.
private static final int MIN_POOL_SIZE = 0;
@@ -61,6 +76,7 @@ public class WorkManagerImplLargeExecutorTest {
private static final long KEEP_ALIVE_TIME = 2L;
private WorkManagerImpl mWorkManagerImpl;
+ private TestLifecycleOwner mLifecycleOwner;
@Rule
public InstantTaskExecutorRule mRule = new InstantTaskExecutorRule();
@@ -90,8 +106,10 @@ public class WorkManagerImplLargeExecutorTest {
MIN_POOL_SIZE, MAX_POOL_SIZE, KEEP_ALIVE_TIME, SECONDS, queue);
Configuration configuration = new Configuration.Builder()
.setExecutor(executor)
+ .setMaxSchedulerLimit(50)
.build();
- mWorkManagerImpl = new WorkManagerImpl(context, configuration);
+ mWorkManagerImpl = new WorkManagerImpl(context, configuration, true);
+ mLifecycleOwner = new TestLifecycleOwner();
WorkManagerImpl.setDelegate(mWorkManagerImpl);
}
@@ -104,15 +122,57 @@ public class WorkManagerImplLargeExecutorTest {
@Test
@LargeTest
@SdkSuppress(maxSdkVersion = 22)
- public void testSchedulerLimits() {
+ public void testSchedulerLimits() throws InterruptedException {
+ List<OneTimeWorkRequest> workRequests = new ArrayList<>(NUM_WORKERS);
+ final Set<UUID> completed = new HashSet<>(NUM_WORKERS);
+ final int schedulerLimit = mWorkManagerImpl
+ .getConfiguration()
+ .getMaxSchedulerLimit();
+
+ final Data input = new Data.Builder()
+ .putInt(KEY_LIMIT_TO_ENFORCE, schedulerLimit)
+ .build();
+
for (int i = 0; i < NUM_WORKERS; i++) {
- mWorkManagerImpl.enqueue(OneTimeWorkRequest.from(TestWorker.class));
- List<WorkSpec> eligibleWorkSpecs = mWorkManagerImpl.getWorkDatabase()
- .workSpecDao()
- .getEligibleWorkForScheduling();
+ OneTimeWorkRequest request = new OneTimeWorkRequest.Builder(CheckLimitsWorker.class)
+ .setInputData(input)
+ .build();
- int size = eligibleWorkSpecs != null ? eligibleWorkSpecs.size() : 0;
- assertThat(size, lessThanOrEqualTo(Scheduler.MAX_SCHEDULER_LIMIT));
+ workRequests.add(request);
}
+
+
+ final CountDownLatch latch = new CountDownLatch(NUM_WORKERS);
+ WorkContinuation continuation = mWorkManagerImpl.beginWith(workRequests);
+
+ continuation.getStatuses()
+ .observe(mLifecycleOwner, new Observer<List<WorkStatus>>() {
+ @Override
+ public void onChanged(@Nullable List<WorkStatus> workStatuses) {
+ if (workStatuses == null || workStatuses.isEmpty()) {
+ return;
+ }
+
+ for (WorkStatus workStatus: workStatuses) {
+ if (workStatus.getState().isFinished()) {
+
+ Data output = workStatus.getOutputData();
+
+ boolean exceededLimits = output.getBoolean(
+ KEY_EXCEEDS_SCHEDULER_LIMIT, true);
+
+ assertThat(exceededLimits, is(false));
+ if (!completed.contains(workStatus.getId())) {
+ completed.add(workStatus.getId());
+ latch.countDown();
+ }
+ }
+ }
+ }
+ });
+
+ continuation.enqueue();
+ latch.await(TEST_TIMEOUT_SECONDS, TimeUnit.SECONDS);
+ assertThat(latch.getCount(), is(0L));
}
}
diff --git a/work/workmanager/src/androidTest/java/androidx/work/impl/WorkManagerImplTest.java b/work/workmanager/src/androidTest/java/androidx/work/impl/WorkManagerImplTest.java
index 71686008903..3e01164c251 100644
--- a/work/workmanager/src/androidTest/java/androidx/work/impl/WorkManagerImplTest.java
+++ b/work/workmanager/src/androidTest/java/androidx/work/impl/WorkManagerImplTest.java
@@ -171,6 +171,18 @@ public class WorkManagerImplTest {
@Test
@SmallTest
+ public void testEnqueue_AddsImplicitTags() {
+ OneTimeWorkRequest work = new OneTimeWorkRequest.Builder(TestWorker.class).build();
+ mWorkManagerImpl.synchronous().enqueueSync(work);
+
+ WorkTagDao workTagDao = mDatabase.workTagDao();
+ List<String> tags = workTagDao.getTagsForWorkSpecId(work.getStringId());
+ assertThat(tags, is(notNullValue()));
+ assertThat(tags, contains(TestWorker.class.getName()));
+ }
+
+ @Test
+ @SmallTest
public void testEnqueue_insertMultipleWork() {
OneTimeWorkRequest work1 = new OneTimeWorkRequest.Builder(TestWorker.class).build();
OneTimeWorkRequest work2 = new OneTimeWorkRequest.Builder(TestWorker.class).build();
@@ -841,12 +853,12 @@ public class WorkManagerImplTest {
work0.getId(),
ENQUEUED,
Data.EMPTY,
- Collections.<String>emptyList());
+ Collections.singletonList(TestWorker.class.getName()));
WorkStatus workStatus1 = new WorkStatus(
work1.getId(),
ENQUEUED,
Data.EMPTY,
- Collections.<String>emptyList());
+ Collections.singletonList(TestWorker.class.getName()));
assertThat(captor.getValue(), containsInAnyOrder(workStatus0, workStatus1));
WorkSpecDao workSpecDao = mDatabase.workSpecDao();
@@ -860,7 +872,7 @@ public class WorkManagerImplTest {
work0.getId(),
RUNNING,
Data.EMPTY,
- Collections.<String>emptyList());
+ Collections.singletonList(TestWorker.class.getName()));
assertThat(captor.getValue(), containsInAnyOrder(workStatus0, workStatus1));
clearInvocations(mockObserver);
@@ -874,7 +886,7 @@ public class WorkManagerImplTest {
work1.getId(),
RUNNING,
Data.EMPTY,
- Collections.<String>emptyList());
+ Collections.singletonList(TestWorker.class.getName()));
assertThat(captor.getValue(), containsInAnyOrder(workStatus0, workStatus1));
liveData.removeObservers(testLifecycleOwner);
@@ -907,17 +919,17 @@ public class WorkManagerImplTest {
work0.getId(),
RUNNING,
Data.EMPTY,
- Arrays.asList(firstTag, secondTag));
+ Arrays.asList(TestWorker.class.getName(), firstTag, secondTag));
WorkStatus workStatus1 = new WorkStatus(
work1.getId(),
BLOCKED,
Data.EMPTY,
- Collections.singletonList(firstTag));
+ Arrays.asList(TestWorker.class.getName(), firstTag));
WorkStatus workStatus2 = new WorkStatus(
work2.getId(),
SUCCEEDED,
Data.EMPTY,
- Collections.singletonList(secondTag));
+ Arrays.asList(TestWorker.class.getName(), secondTag));
List<WorkStatus> workStatuses = mWorkManagerImpl.getStatusesByTagSync(firstTag);
assertThat(workStatuses, containsInAnyOrder(workStatus0, workStatus1));
@@ -969,12 +981,12 @@ public class WorkManagerImplTest {
work0.getId(),
RUNNING,
Data.EMPTY,
- Arrays.asList(firstTag, secondTag));
+ Arrays.asList(TestWorker.class.getName(), firstTag, secondTag));
WorkStatus workStatus1 = new WorkStatus(
work1.getId(),
BLOCKED,
Data.EMPTY,
- Collections.singletonList(firstTag));
+ Arrays.asList(TestWorker.class.getName(), firstTag));
assertThat(captor.getValue(), containsInAnyOrder(workStatus0, workStatus1));
workSpecDao.setState(ENQUEUED, work0.getStringId());
@@ -987,7 +999,7 @@ public class WorkManagerImplTest {
work0.getId(),
ENQUEUED,
Data.EMPTY,
- Arrays.asList(firstTag, secondTag));
+ Arrays.asList(TestWorker.class.getName(), firstTag, secondTag));
assertThat(captor.getValue(), containsInAnyOrder(workStatus0, workStatus1));
liveData.removeObservers(testLifecycleOwner);
@@ -1015,17 +1027,17 @@ public class WorkManagerImplTest {
work0.getId(),
RUNNING,
Data.EMPTY,
- Collections.<String>emptyList());
+ Collections.singletonList(InfiniteTestWorker.class.getName()));
WorkStatus workStatus1 = new WorkStatus(
work1.getId(),
BLOCKED,
Data.EMPTY,
- Collections.<String>emptyList());
+ Collections.singletonList(InfiniteTestWorker.class.getName()));
WorkStatus workStatus2 = new WorkStatus(
work2.getId(),
BLOCKED,
Data.EMPTY,
- Collections.<String>emptyList());
+ Collections.singletonList(InfiniteTestWorker.class.getName()));
List<WorkStatus> workStatuses = mWorkManagerImpl.getStatusesForUniqueWorkSync(uniqueName);
assertThat(workStatuses, containsInAnyOrder(workStatus0, workStatus1, workStatus2));
@@ -1069,17 +1081,17 @@ public class WorkManagerImplTest {
work0.getId(),
RUNNING,
Data.EMPTY,
- Collections.<String>emptyList());
+ Collections.singletonList(InfiniteTestWorker.class.getName()));
WorkStatus workStatus1 = new WorkStatus(
work1.getId(),
BLOCKED,
Data.EMPTY,
- Collections.<String>emptyList());
+ Collections.singletonList(InfiniteTestWorker.class.getName()));
WorkStatus workStatus2 = new WorkStatus(
work2.getId(),
BLOCKED,
Data.EMPTY,
- Collections.<String>emptyList());
+ Collections.singletonList(InfiniteTestWorker.class.getName()));
assertThat(captor.getValue(), containsInAnyOrder(workStatus0, workStatus1, workStatus2));
workSpecDao.setState(ENQUEUED, work0.getStringId());
@@ -1092,7 +1104,7 @@ public class WorkManagerImplTest {
work0.getId(),
ENQUEUED,
Data.EMPTY,
- Collections.<String>emptyList());
+ Collections.singletonList(InfiniteTestWorker.class.getName()));
assertThat(captor.getValue(), containsInAnyOrder(workStatus0, workStatus1, workStatus2));
liveData.removeObservers(testLifecycleOwner);
@@ -1333,6 +1345,38 @@ public class WorkManagerImplTest {
@Test
@SmallTest
+ public void pruneFinishedWork() {
+ OneTimeWorkRequest enqueuedWork = new OneTimeWorkRequest.Builder(TestWorker.class).build();
+ OneTimeWorkRequest finishedWork =
+ new OneTimeWorkRequest.Builder(TestWorker.class).setInitialState(SUCCEEDED).build();
+ OneTimeWorkRequest finishedWorkWithUnfinishedDependent =
+ new OneTimeWorkRequest.Builder(TestWorker.class).setInitialState(SUCCEEDED).build();
+ OneTimeWorkRequest finishedWorkWithLongKeepForAtLeast =
+ new OneTimeWorkRequest.Builder(TestWorker.class)
+ .setInitialState(SUCCEEDED)
+ .keepResultsForAtLeast(999, TimeUnit.DAYS)
+ .build();
+
+ insertWorkSpecAndTags(enqueuedWork);
+ insertWorkSpecAndTags(finishedWork);
+ insertWorkSpecAndTags(finishedWorkWithUnfinishedDependent);
+ insertWorkSpecAndTags(finishedWorkWithLongKeepForAtLeast);
+
+ insertDependency(enqueuedWork, finishedWorkWithUnfinishedDependent);
+
+ mWorkManagerImpl.synchronous().pruneWorkSync();
+
+ WorkSpecDao workSpecDao = mDatabase.workSpecDao();
+ assertThat(workSpecDao.getWorkSpec(enqueuedWork.getStringId()), is(notNullValue()));
+ assertThat(workSpecDao.getWorkSpec(finishedWork.getStringId()), is(nullValue()));
+ assertThat(workSpecDao.getWorkSpec(finishedWorkWithUnfinishedDependent.getStringId()),
+ is(notNullValue()));
+ assertThat(workSpecDao.getWorkSpec(finishedWorkWithLongKeepForAtLeast.getStringId()),
+ is(nullValue()));
+ }
+
+ @Test
+ @SmallTest
public void testSynchronousCancelAndGetStatus() {
OneTimeWorkRequest work = new OneTimeWorkRequest.Builder(TestWorker.class).build();
insertWorkSpecAndTags(work);
diff --git a/work/workmanager/src/androidTest/java/androidx/work/impl/WorkerWrapperTest.java b/work/workmanager/src/androidTest/java/androidx/work/impl/WorkerWrapperTest.java
index 4a50d10965b..739fcf7b626 100644
--- a/work/workmanager/src/androidTest/java/androidx/work/impl/WorkerWrapperTest.java
+++ b/work/workmanager/src/androidTest/java/androidx/work/impl/WorkerWrapperTest.java
@@ -44,6 +44,7 @@ import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
import androidx.work.ArrayCreatingInputMerger;
+import androidx.work.Configuration;
import androidx.work.Data;
import androidx.work.DatabaseTest;
import androidx.work.OneTimeWorkRequest;
@@ -78,6 +79,7 @@ import java.util.concurrent.TimeUnit;
@RunWith(AndroidJUnit4.class)
public class WorkerWrapperTest extends DatabaseTest {
+ private Configuration mConfiguration;
private WorkSpecDao mWorkSpecDao;
private DependencyDao mDependencyDao;
private Context mContext;
@@ -90,6 +92,7 @@ public class WorkerWrapperTest extends DatabaseTest {
@Before
public void setUp() {
mContext = InstrumentationRegistry.getTargetContext();
+ mConfiguration = new Configuration.Builder().build();
mWorkSpecDao = spy(mDatabase.workSpecDao());
mDependencyDao = mDatabase.dependencyDao();
mMockListener = mock(ExecutionListener.class);
@@ -101,7 +104,7 @@ public class WorkerWrapperTest extends DatabaseTest {
public void testSuccess() {
OneTimeWorkRequest work = new OneTimeWorkRequest.Builder(TestWorker.class).build();
insertWork(work);
- new WorkerWrapper.Builder(mContext, mDatabase, work.getStringId())
+ new WorkerWrapper.Builder(mContext, mConfiguration, mDatabase, work.getStringId())
.withListener(mMockListener)
.build()
.run();
@@ -114,7 +117,7 @@ public class WorkerWrapperTest extends DatabaseTest {
public void testRunAttemptCountIncremented_successfulExecution() {
OneTimeWorkRequest work = new OneTimeWorkRequest.Builder(TestWorker.class).build();
insertWork(work);
- new WorkerWrapper.Builder(mContext, mDatabase, work.getStringId())
+ new WorkerWrapper.Builder(mContext, mConfiguration, mDatabase, work.getStringId())
.withSchedulers(Collections.singletonList(mMockScheduler))
.withListener(mMockListener)
.build()
@@ -128,7 +131,7 @@ public class WorkerWrapperTest extends DatabaseTest {
public void testRunAttemptCountIncremented_failedExecution() {
OneTimeWorkRequest work = new OneTimeWorkRequest.Builder(FailureWorker.class).build();
insertWork(work);
- new WorkerWrapper.Builder(mContext, mDatabase, work.getStringId())
+ new WorkerWrapper.Builder(mContext, mConfiguration, mDatabase, work.getStringId())
.withSchedulers(Collections.singletonList(mMockScheduler))
.withListener(mMockListener)
.build()
@@ -141,7 +144,7 @@ public class WorkerWrapperTest extends DatabaseTest {
@SmallTest
public void testPermanentErrorWithInvalidWorkSpecId() {
final String invalidWorkSpecId = "INVALID_ID";
- new WorkerWrapper.Builder(mContext, mDatabase, invalidWorkSpecId)
+ new WorkerWrapper.Builder(mContext, mConfiguration, mDatabase, invalidWorkSpecId)
.withListener(mMockListener)
.build()
.run();
@@ -155,7 +158,7 @@ public class WorkerWrapperTest extends DatabaseTest {
.setInitialState(RUNNING)
.build();
insertWork(work);
- new WorkerWrapper.Builder(mContext, mDatabase, work.getStringId())
+ new WorkerWrapper.Builder(mContext, mConfiguration, mDatabase, work.getStringId())
.withListener(mMockListener)
.build()
.run();
@@ -169,7 +172,7 @@ public class WorkerWrapperTest extends DatabaseTest {
.setInitialState(CANCELLED)
.build();
insertWork(work);
- new WorkerWrapper.Builder(mContext, mDatabase, work.getStringId())
+ new WorkerWrapper.Builder(mContext, mConfiguration, mDatabase, work.getStringId())
.withListener(mMockListener)
.build()
.run();
@@ -183,7 +186,7 @@ public class WorkerWrapperTest extends DatabaseTest {
OneTimeWorkRequest work = new OneTimeWorkRequest.Builder(TestWorker.class).build();
getWorkSpec(work).workerClassName = "INVALID_CLASS_NAME";
insertWork(work);
- new WorkerWrapper.Builder(mContext, mDatabase, work.getStringId())
+ new WorkerWrapper.Builder(mContext, mConfiguration, mDatabase, work.getStringId())
.withListener(mMockListener)
.build()
.run();
@@ -197,7 +200,7 @@ public class WorkerWrapperTest extends DatabaseTest {
OneTimeWorkRequest work = new OneTimeWorkRequest.Builder(TestWorker.class).build();
getWorkSpec(work).inputMergerClassName = "INVALID_CLASS_NAME";
insertWork(work);
- new WorkerWrapper.Builder(mContext, mDatabase, work.getStringId())
+ new WorkerWrapper.Builder(mContext, mConfiguration, mDatabase, work.getStringId())
.withSchedulers(Collections.singletonList(mMockScheduler))
.withListener(mMockListener)
.build()
@@ -211,7 +214,7 @@ public class WorkerWrapperTest extends DatabaseTest {
public void testFailed() {
OneTimeWorkRequest work = new OneTimeWorkRequest.Builder(FailureWorker.class).build();
insertWork(work);
- new WorkerWrapper.Builder(mContext, mDatabase, work.getStringId())
+ new WorkerWrapper.Builder(mContext, mConfiguration, mDatabase, work.getStringId())
.withListener(mMockListener)
.build()
.run();
@@ -224,7 +227,8 @@ public class WorkerWrapperTest extends DatabaseTest {
public void testRunning() throws InterruptedException {
OneTimeWorkRequest work = new OneTimeWorkRequest.Builder(SleepTestWorker.class).build();
insertWork(work);
- WorkerWrapper wrapper = new WorkerWrapper.Builder(mContext, mDatabase, work.getStringId())
+ WorkerWrapper wrapper = new WorkerWrapper.Builder(mContext, mConfiguration, mDatabase,
+ work.getStringId())
.withListener(mMockListener)
.build();
Executors.newSingleThreadExecutor().submit(wrapper);
@@ -241,7 +245,7 @@ public class WorkerWrapperTest extends DatabaseTest {
.setInitialState(RUNNING)
.build();
insertWork(work);
- new WorkerWrapper.Builder(mContext, mDatabase, work.getStringId())
+ new WorkerWrapper.Builder(mContext, mConfiguration, mDatabase, work.getStringId())
.withListener(mMockListener)
.build()
.run();
@@ -271,7 +275,8 @@ public class WorkerWrapperTest extends DatabaseTest {
assertThat(mWorkSpecDao.getState(work.getStringId()), is(BLOCKED));
assertThat(mDependencyDao.hasCompletedAllPrerequisites(work.getStringId()), is(false));
- new WorkerWrapper.Builder(mContext, mDatabase, prerequisiteWork.getStringId())
+ new WorkerWrapper.Builder(mContext, mConfiguration, mDatabase,
+ prerequisiteWork.getStringId())
.withListener(mMockListener)
.withSchedulers(Collections.singletonList(mMockScheduler))
.build()
@@ -306,7 +311,8 @@ public class WorkerWrapperTest extends DatabaseTest {
mDatabase.endTransaction();
}
- new WorkerWrapper.Builder(mContext, mDatabase, prerequisiteWork.getStringId())
+ new WorkerWrapper.Builder(mContext, mConfiguration, mDatabase,
+ prerequisiteWork.getStringId())
.withSchedulers(Collections.singletonList(mMockScheduler))
.build().run();
@@ -349,17 +355,19 @@ public class WorkerWrapperTest extends DatabaseTest {
}
// Run the prerequisites.
- new WorkerWrapper.Builder(mContext, mDatabase, prerequisiteWork1.getStringId())
+ new WorkerWrapper.Builder(mContext, mConfiguration, mDatabase,
+ prerequisiteWork1.getStringId())
.withSchedulers(Collections.singletonList(mMockScheduler))
.build().run();
- new WorkerWrapper.Builder(mContext, mDatabase, prerequisiteWork2.getStringId())
+ new WorkerWrapper.Builder(mContext, mConfiguration, mDatabase,
+ prerequisiteWork2.getStringId())
.withSchedulers(Collections.singletonList(mMockScheduler))
.build().run();
// Create and run the dependent work.
WorkerWrapper workerWrapper =
- new WorkerWrapper.Builder(mContext, mDatabase, work.getStringId())
+ new WorkerWrapper.Builder(mContext, mConfiguration, mDatabase, work.getStringId())
.withSchedulers(Collections.singletonList(mMockScheduler))
.build();
workerWrapper.run();
@@ -392,7 +400,8 @@ public class WorkerWrapperTest extends DatabaseTest {
long beforeUnblockedTime = System.currentTimeMillis();
- new WorkerWrapper.Builder(mContext, mDatabase, prerequisiteWork.getStringId())
+ new WorkerWrapper.Builder(mContext, mConfiguration, mDatabase,
+ prerequisiteWork.getStringId())
.withListener(mMockListener)
.withSchedulers(Collections.singletonList(mMockScheduler))
.build()
@@ -429,7 +438,8 @@ public class WorkerWrapperTest extends DatabaseTest {
mDatabase.endTransaction();
}
- new WorkerWrapper.Builder(mContext, mDatabase, prerequisiteWork.getStringId())
+ new WorkerWrapper.Builder(mContext, mConfiguration, mDatabase,
+ prerequisiteWork.getStringId())
.build()
.run();
@@ -452,7 +462,7 @@ public class WorkerWrapperTest extends DatabaseTest {
insertWork(periodicWork);
- new WorkerWrapper.Builder(mContext, mDatabase, periodicWork.getStringId())
+ new WorkerWrapper.Builder(mContext, mConfiguration, mDatabase, periodicWork.getStringId())
.withListener(mMockListener)
.build()
.run();
@@ -475,7 +485,7 @@ public class WorkerWrapperTest extends DatabaseTest {
insertWork(periodicWork);
- new WorkerWrapper.Builder(mContext, mDatabase, periodicWork.getStringId())
+ new WorkerWrapper.Builder(mContext, mConfiguration, mDatabase, periodicWork.getStringId())
.withListener(mMockListener)
.build()
.run();
@@ -495,7 +505,7 @@ public class WorkerWrapperTest extends DatabaseTest {
final String periodicWorkId = periodicWork.getStringId();
insertWork(periodicWork);
- new WorkerWrapper.Builder(mContext, mDatabase, periodicWorkId)
+ new WorkerWrapper.Builder(mContext, mConfiguration, mDatabase, periodicWorkId)
.withListener(mMockListener)
.build()
.run();
@@ -517,7 +527,7 @@ public class WorkerWrapperTest extends DatabaseTest {
final String periodicWorkId = periodicWork.getStringId();
insertWork(periodicWork);
- new WorkerWrapper.Builder(mContext, mDatabase, periodicWorkId)
+ new WorkerWrapper.Builder(mContext, mConfiguration, mDatabase, periodicWorkId)
.withListener(mMockListener)
.build()
.run();
@@ -539,7 +549,7 @@ public class WorkerWrapperTest extends DatabaseTest {
final String periodicWorkId = periodicWork.getStringId();
insertWork(periodicWork);
- new WorkerWrapper.Builder(mContext, mDatabase, periodicWorkId)
+ new WorkerWrapper.Builder(mContext, mConfiguration, mDatabase, periodicWorkId)
.withListener(mMockListener)
.build()
.run();
@@ -557,7 +567,7 @@ public class WorkerWrapperTest extends DatabaseTest {
insertWork(work);
Scheduler mockScheduler = mock(Scheduler.class);
- new WorkerWrapper.Builder(mContext, mDatabase, work.getStringId())
+ new WorkerWrapper.Builder(mContext, mConfiguration, mDatabase, work.getStringId())
.withSchedulers(Collections.singletonList(mockScheduler))
.build()
.run();
@@ -629,8 +639,8 @@ public class WorkerWrapperTest extends DatabaseTest {
OneTimeWorkRequest work =
new OneTimeWorkRequest.Builder(TestWorker.class).build();
Extras.RuntimeExtras runtimeExtras = new Extras.RuntimeExtras();
- runtimeExtras.triggeredContentAuthorities = new String[] { "tca1", "tca2", "tca3" };
- runtimeExtras.triggeredContentUris = new Uri[] { Uri.parse("tcu1"), Uri.parse("tcu2") };
+ runtimeExtras.triggeredContentAuthorities = new String[]{"tca1", "tca2", "tca3"};
+ runtimeExtras.triggeredContentUris = new Uri[]{Uri.parse("tcu1"), Uri.parse("tcu2")};
Worker worker = WorkerWrapper.workerFromWorkSpec(
mContext,
@@ -653,7 +663,7 @@ public class WorkerWrapperTest extends DatabaseTest {
OneTimeWorkRequest unscheduled = new OneTimeWorkRequest.Builder(TestWorker.class).build();
insertWork(unscheduled);
- new WorkerWrapper.Builder(mContext, mDatabase, work.getStringId())
+ new WorkerWrapper.Builder(mContext, mConfiguration, mDatabase, work.getStringId())
.withSchedulers(Collections.singletonList(mMockScheduler))
.withListener(mMockListener)
.build()
@@ -673,7 +683,7 @@ public class WorkerWrapperTest extends DatabaseTest {
OneTimeWorkRequest unscheduled = new OneTimeWorkRequest.Builder(TestWorker.class).build();
insertWork(unscheduled);
- new WorkerWrapper.Builder(mContext, mDatabase, work.getStringId())
+ new WorkerWrapper.Builder(mContext, mConfiguration, mDatabase, work.getStringId())
.withSchedulers(Collections.singletonList(mMockScheduler))
.withListener(mMockListener)
.build()
@@ -691,7 +701,7 @@ public class WorkerWrapperTest extends DatabaseTest {
insertWork(work);
WorkerWrapper workerWrapper =
- new WorkerWrapper.Builder(mContext, mDatabase, work.getStringId())
+ new WorkerWrapper.Builder(mContext, mConfiguration, mDatabase, work.getStringId())
.withSchedulers(Collections.singletonList(mMockScheduler))
.withListener(mMockListener)
.build();
@@ -717,7 +727,7 @@ public class WorkerWrapperTest extends DatabaseTest {
assertThat(worker.isStopped(), is(false));
WorkerWrapper workerWrapper =
- new WorkerWrapper.Builder(mContext, mDatabase, work.getStringId())
+ new WorkerWrapper.Builder(mContext, mConfiguration, mDatabase, work.getStringId())
.withSchedulers(Collections.singletonList(mMockScheduler))
.withListener(mMockListener)
.withWorker(worker)
@@ -744,7 +754,7 @@ public class WorkerWrapperTest extends DatabaseTest {
assertThat(worker.isStopped(), is(false));
WorkerWrapper workerWrapper =
- new WorkerWrapper.Builder(mContext, mDatabase, work.getStringId())
+ new WorkerWrapper.Builder(mContext, mConfiguration, mDatabase, work.getStringId())
.withSchedulers(Collections.singletonList(mMockScheduler))
.withListener(mMockListener)
.withWorker(worker)
@@ -761,7 +771,7 @@ public class WorkerWrapperTest extends DatabaseTest {
OneTimeWorkRequest work = new OneTimeWorkRequest.Builder(ExceptionWorker.class).build();
insertWork(work);
- new WorkerWrapper.Builder(mContext, mDatabase, work.getStringId())
+ new WorkerWrapper.Builder(mContext, mConfiguration, mDatabase, work.getStringId())
.withSchedulers(Collections.singletonList(mMockScheduler))
.withListener(mMockListener)
.build()
@@ -777,7 +787,7 @@ public class WorkerWrapperTest extends DatabaseTest {
insertWork(work);
WorkerWrapper workerWrapper =
- new WorkerWrapper.Builder(mContext, mDatabase, work.getStringId())
+ new WorkerWrapper.Builder(mContext, mConfiguration, mDatabase, work.getStringId())
.withSchedulers(Collections.singletonList(mMockScheduler))
.withListener(mMockListener)
.build();
@@ -797,10 +807,10 @@ public class WorkerWrapperTest extends DatabaseTest {
insertWork(work);
WorkerWrapper workerWrapper =
- new WorkerWrapper.Builder(mContext, mDatabase, work.getStringId())
- .withSchedulers(Collections.singletonList(mMockScheduler))
- .withListener(mMockListener)
- .build();
+ new WorkerWrapper.Builder(mContext, mConfiguration, mDatabase, work.getStringId())
+ .withSchedulers(Collections.singletonList(mMockScheduler))
+ .withListener(mMockListener)
+ .build();
Executors.newSingleThreadExecutor().submit(workerWrapper);
Thread.sleep(1000L);
diff --git a/work/workmanager/src/androidTest/java/androidx/work/impl/background/systemalarm/SystemAlarmDispatcherTest.java b/work/workmanager/src/androidTest/java/androidx/work/impl/background/systemalarm/SystemAlarmDispatcherTest.java
index 5e36dfd0c77..cfe2cef7db5 100644
--- a/work/workmanager/src/androidTest/java/androidx/work/impl/background/systemalarm/SystemAlarmDispatcherTest.java
+++ b/work/workmanager/src/androidTest/java/androidx/work/impl/background/systemalarm/SystemAlarmDispatcherTest.java
@@ -34,6 +34,7 @@ import android.support.test.filters.LargeTest;
import android.support.test.filters.MediumTest;
import android.support.test.runner.AndroidJUnit4;
+import androidx.work.Configuration;
import androidx.work.Constraints;
import androidx.work.DatabaseTest;
import androidx.work.OneTimeWorkRequest;
@@ -81,6 +82,7 @@ public class SystemAlarmDispatcherTest extends DatabaseTest {
private Context mContext;
private Scheduler mScheduler;
private WorkManagerImpl mWorkManager;
+ private Configuration mConfiguration;
private ExecutorService mExecutorService;
private Processor mProcessor;
private Processor mSpyProcessor;
@@ -108,10 +110,13 @@ public class SystemAlarmDispatcherTest extends DatabaseTest {
}
};
+ mConfiguration = new Configuration.Builder().build();
when(mWorkManager.getWorkDatabase()).thenReturn(mDatabase);
+ when(mWorkManager.getConfiguration()).thenReturn(mConfiguration);
mExecutorService = Executors.newSingleThreadExecutor();
mProcessor = new Processor(
mContext,
+ mConfiguration,
mDatabase,
Collections.singletonList(mScheduler),
// simulate real world use-case
diff --git a/work/workmanager/src/androidTest/java/androidx/work/impl/workers/ConstraintTrackingWorkerTest.java b/work/workmanager/src/androidTest/java/androidx/work/impl/workers/ConstraintTrackingWorkerTest.java
index a86df660418..6f136bf0b6e 100644
--- a/work/workmanager/src/androidTest/java/androidx/work/impl/workers/ConstraintTrackingWorkerTest.java
+++ b/work/workmanager/src/androidTest/java/androidx/work/impl/workers/ConstraintTrackingWorkerTest.java
@@ -31,6 +31,7 @@ import android.support.test.filters.SdkSuppress;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
+import androidx.work.Configuration;
import androidx.work.Constraints;
import androidx.work.Data;
import androidx.work.DatabaseTest;
@@ -76,6 +77,7 @@ public class ConstraintTrackingWorkerTest extends DatabaseTest implements Execut
private ExecutorService mExecutorService;
private WorkManagerImpl mWorkManagerImpl;
+ private Configuration mConfiguration;
private Scheduler mScheduler;
private Trackers mTracker;
private BatteryChargingTracker mBatteryChargingTracker;
@@ -89,10 +91,12 @@ public class ConstraintTrackingWorkerTest extends DatabaseTest implements Execut
mHandler = new Handler(Looper.getMainLooper());
mExecutorService = Executors.newSingleThreadScheduledExecutor();
mLatch = new CountDownLatch(1);
+ mConfiguration = new Configuration.Builder().build();
mWorkManagerImpl = mock(WorkManagerImpl.class);
mScheduler = mock(Scheduler.class);
when(mWorkManagerImpl.getWorkDatabase()).thenReturn(mDatabase);
+ when(mWorkManagerImpl.getConfiguration()).thenReturn(mConfiguration);
mBatteryChargingTracker = spy(new BatteryChargingTracker(mContext));
mBatteryNotLowTracker = spy(new BatteryNotLowTracker(mContext));
@@ -149,7 +153,8 @@ public class ConstraintTrackingWorkerTest extends DatabaseTest implements Execut
ConstraintTrackingWorker spyWorker = spy(worker);
when(spyWorker.getWorkDatabase()).thenReturn(mDatabase);
- WorkerWrapper.Builder builder = new WorkerWrapper.Builder(mContext, mDatabase, workSpecId);
+ WorkerWrapper.Builder builder =
+ new WorkerWrapper.Builder(mContext, mConfiguration, mDatabase, workSpecId);
builder.withWorker(spyWorker)
.withListener(this)
.withSchedulers(Collections.singletonList(mScheduler));
@@ -194,7 +199,8 @@ public class ConstraintTrackingWorkerTest extends DatabaseTest implements Execut
ConstraintTrackingWorker spyWorker = spy(worker);
when(spyWorker.getWorkDatabase()).thenReturn(mDatabase);
- WorkerWrapper.Builder builder = new WorkerWrapper.Builder(mContext, mDatabase, workSpecId);
+ WorkerWrapper.Builder builder =
+ new WorkerWrapper.Builder(mContext, mConfiguration, mDatabase, workSpecId);
builder.withWorker(spyWorker)
.withListener(this)
.withSchedulers(Collections.singletonList(mScheduler));
@@ -237,8 +243,8 @@ public class ConstraintTrackingWorkerTest extends DatabaseTest implements Execut
ConstraintTrackingWorker spyWorker = spy(worker);
when(spyWorker.getWorkDatabase()).thenReturn(mDatabase);
-
- WorkerWrapper.Builder builder = new WorkerWrapper.Builder(mContext, mDatabase, workSpecId);
+ WorkerWrapper.Builder builder =
+ new WorkerWrapper.Builder(mContext, mConfiguration, mDatabase, workSpecId);
builder.withWorker(spyWorker)
.withListener(this)
.withSchedulers(Collections.singletonList(mScheduler));
@@ -290,7 +296,8 @@ public class ConstraintTrackingWorkerTest extends DatabaseTest implements Execut
ConstraintTrackingWorker spyWorker = spy(worker);
when(spyWorker.getWorkDatabase()).thenReturn(mDatabase);
- WorkerWrapper.Builder builder = new WorkerWrapper.Builder(mContext, mDatabase, workSpecId);
+ WorkerWrapper.Builder builder =
+ new WorkerWrapper.Builder(mContext, mConfiguration, mDatabase, workSpecId);
builder.withWorker(spyWorker)
.withListener(this)
.withSchedulers(Collections.singletonList(mScheduler));
diff --git a/work/workmanager/src/androidTest/java/androidx/work/worker/CheckLimitsWorker.java b/work/workmanager/src/androidTest/java/androidx/work/worker/CheckLimitsWorker.java
new file mode 100644
index 00000000000..11763641ed8
--- /dev/null
+++ b/work/workmanager/src/androidTest/java/androidx/work/worker/CheckLimitsWorker.java
@@ -0,0 +1,56 @@
+/*
+ * 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.worker;
+
+import static androidx.work.Worker.Result.SUCCESS;
+
+import android.support.annotation.NonNull;
+
+import androidx.work.Data;
+import androidx.work.Worker;
+import androidx.work.impl.Scheduler;
+import androidx.work.impl.WorkManagerImpl;
+import androidx.work.impl.model.WorkSpec;
+
+import java.util.List;
+
+public class CheckLimitsWorker extends Worker {
+ /* The limit to enforce */
+ public static final String KEY_LIMIT_TO_ENFORCE = "limit";
+
+ /* The output key which tells us if we exceeded the scheduler limits. */
+ public static final String KEY_EXCEEDS_SCHEDULER_LIMIT = "exceed_scheduler_limit";
+
+ @NonNull
+ @Override
+ public Result doWork() {
+ Data input = getInputData();
+ int limitToEnforce = input.getInt(KEY_LIMIT_TO_ENFORCE, Scheduler.MAX_SCHEDULER_LIMIT);
+ WorkManagerImpl workManager = WorkManagerImpl.getInstance();
+ List<WorkSpec> eligibleWorkSpecs = workManager.getWorkDatabase()
+ .workSpecDao()
+ .getEligibleWorkForScheduling(limitToEnforce);
+ int size = eligibleWorkSpecs != null ? eligibleWorkSpecs.size() : 0;
+ boolean exceedsLimits = size > limitToEnforce;
+ Data output = new Data.Builder()
+ .putBoolean(KEY_EXCEEDS_SCHEDULER_LIMIT, exceedsLimits)
+ .build();
+
+ setOutputData(output);
+ return SUCCESS;
+ }
+}
diff --git a/work/workmanager/src/main/java/androidx/work/Configuration.java b/work/workmanager/src/main/java/androidx/work/Configuration.java
index 4fe1470424f..77f5ffa9b44 100644
--- a/work/workmanager/src/main/java/androidx/work/Configuration.java
+++ b/work/workmanager/src/main/java/androidx/work/Configuration.java
@@ -16,7 +16,11 @@
package androidx.work;
+import static androidx.work.impl.Scheduler.MAX_SCHEDULER_LIMIT;
+
+import android.os.Build;
import android.support.annotation.NonNull;
+import android.support.annotation.RestrictTo;
import androidx.work.impl.utils.IdGenerator;
@@ -28,9 +32,16 @@ import java.util.concurrent.Executors;
*/
public final class Configuration {
+ /**
+ * The minimum number of system requests which can be enqueued by {@link WorkManager}
+ * when using {@link android.app.job.JobScheduler} or {@link android.app.AlarmManager}.
+ */
+ public static final int MIN_SCHEDULER_LIMIT = 20;
+
private final Executor mExecutor;
private final int mMinJobSchedulerId;
private final int mMaxJobSchedulerId;
+ private final int mMaxSchedulerLimit;
private Configuration(@NonNull Configuration.Builder builder) {
if (builder.mExecutor == null) {
@@ -40,6 +51,7 @@ public final class Configuration {
}
mMinJobSchedulerId = builder.mMinJobSchedulerId;
mMaxJobSchedulerId = builder.mMaxJobSchedulerId;
+ mMaxSchedulerLimit = builder.mMaxSchedulerLimit;
}
/**
@@ -75,6 +87,22 @@ public final class Configuration {
return mMaxJobSchedulerId;
}
+ /**
+ * @return The maximum number of system requests which can be enqueued by {@link WorkManager}
+ * when using {@link android.app.job.JobScheduler} or {@link android.app.AlarmManager}.
+ *
+ * @hide
+ */
+ @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+ public int getMaxSchedulerLimit() {
+ // We double schedule jobs in SDK 23. So use half the number of max slots specified.
+ if (Build.VERSION.SDK_INT == 23) {
+ return mMaxSchedulerLimit / 2;
+ } else {
+ return mMaxSchedulerLimit;
+ }
+ }
+
private Executor createDefaultExecutor() {
return Executors.newFixedThreadPool(
// This value is the same as the core pool size for AsyncTask#THREAD_POOL_EXECUTOR.
@@ -88,6 +116,7 @@ public final class Configuration {
int mMinJobSchedulerId = IdGenerator.INITIAL_ID;
int mMaxJobSchedulerId = Integer.MAX_VALUE;
+ int mMaxSchedulerLimit = MIN_SCHEDULER_LIMIT;
Executor mExecutor;
/**
@@ -122,6 +151,33 @@ public final class Configuration {
}
/**
+ * Specifies the maximum number of system requests made by {@link WorkManager}
+ * when using {@link android.app.job.JobScheduler} or {@link android.app.AlarmManager}.
+ * When the application exceeds this limit {@link WorkManager} maintains an internal queue
+ * of {@link WorkRequest}s, and enqueues when slots become free.
+ *
+ * {@link WorkManager} requires a minimum of {@link Configuration#MIN_SCHEDULER_LIMIT}
+ * slots. The total number of slots also cannot exceed {@code 100} which is
+ * the {@link android.app.job.JobScheduler} limit.
+ *
+ * @param maxSchedulerLimit The total number of jobs which can be enqueued by
+ * {@link WorkManager} when using
+ * {@link android.app.job.JobScheduler}.
+ * @return This {@link Builder} instance
+ * @throws IllegalArgumentException when the number of jobs <
+ * {@link Configuration#MIN_SCHEDULER_LIMIT}
+ */
+ public Builder setMaxSchedulerLimit(int maxSchedulerLimit) {
+ if (maxSchedulerLimit < MIN_SCHEDULER_LIMIT) {
+ throw new IllegalArgumentException(
+ "WorkManager needs to be able to schedule at least 20 jobs in "
+ + "JobScheduler.");
+ }
+ mMaxSchedulerLimit = Math.min(maxSchedulerLimit, MAX_SCHEDULER_LIMIT);
+ return this;
+ }
+
+ /**
* Specifies a custom {@link Executor} for WorkManager.
*
* @param executor An {@link Executor} for processing work
diff --git a/work/workmanager/src/main/java/androidx/work/SynchronousWorkManager.java b/work/workmanager/src/main/java/androidx/work/SynchronousWorkManager.java
index f01e363152a..9f633d8e3e0 100644
--- a/work/workmanager/src/main/java/androidx/work/SynchronousWorkManager.java
+++ b/work/workmanager/src/main/java/androidx/work/SynchronousWorkManager.java
@@ -21,6 +21,7 @@ import android.support.annotation.WorkerThread;
import java.util.List;
import java.util.UUID;
+import java.util.concurrent.TimeUnit;
/**
* Blocking methods for {@link WorkManager} operations. These methods are expected to be called
@@ -129,6 +130,20 @@ public interface SynchronousWorkManager {
long getLastCancelAllTimeMillisSync();
/**
+ * Prunes all eligible finished work from the internal database in a synchronous fashion.
+ * Eligible work must be finished ({@link State#SUCCEEDED}, {@link State#FAILED}, or
+ * {@link 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 WorkStatus} 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.
+ */
+ @WorkerThread
+ void pruneWorkSync();
+
+ /**
* Gets the {@link WorkStatus} of a given work id in a synchronous fashion. This method is
* expected to be called from a background thread.
*
diff --git a/work/workmanager/src/main/java/androidx/work/WorkManager.java b/work/workmanager/src/main/java/androidx/work/WorkManager.java
index 83891dccef4..5960e50fcab 100644
--- a/work/workmanager/src/main/java/androidx/work/WorkManager.java
+++ b/work/workmanager/src/main/java/androidx/work/WorkManager.java
@@ -26,6 +26,7 @@ import androidx.work.impl.WorkManagerImpl;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
+import java.util.concurrent.TimeUnit;
/**
* WorkManager is a library used to enqueue work that is guaranteed to execute after its constraints
@@ -288,6 +289,19 @@ public abstract class WorkManager {
public abstract void cancelAllWork();
/**
+ * Prunes all eligible finished work from the internal database. Eligible work must be finished
+ * ({@link State#SUCCEEDED}, {@link State#FAILED}, or {@link 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 WorkStatus} 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.
+ */
+ public abstract void 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.
diff --git a/work/workmanager/src/main/java/androidx/work/WorkRequest.java b/work/workmanager/src/main/java/androidx/work/WorkRequest.java
index c1eae64b8e7..cfb72b8f759 100644
--- a/work/workmanager/src/main/java/androidx/work/WorkRequest.java
+++ b/work/workmanager/src/main/java/androidx/work/WorkRequest.java
@@ -121,6 +121,7 @@ public abstract class WorkRequest {
public Builder(@NonNull Class<? extends Worker> workerClass) {
mId = UUID.randomUUID();
mWorkSpec = new WorkSpec(mId.toString(), workerClass.getName());
+ addTag(workerClass.getName());
}
/**
diff --git a/work/workmanager/src/main/java/androidx/work/impl/Processor.java b/work/workmanager/src/main/java/androidx/work/impl/Processor.java
index 4092686fcee..86b7edf5f39 100644
--- a/work/workmanager/src/main/java/androidx/work/impl/Processor.java
+++ b/work/workmanager/src/main/java/androidx/work/impl/Processor.java
@@ -20,6 +20,8 @@ import android.support.annotation.NonNull;
import android.support.annotation.RestrictTo;
import android.util.Log;
+import androidx.work.Configuration;
+
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
@@ -38,8 +40,8 @@ public class Processor implements ExecutionListener {
private static final String TAG = "Processor";
private Context mAppContext;
+ private Configuration mConfiguration;
private WorkDatabase mWorkDatabase;
-
private Map<String, WorkerWrapper> mEnqueuedWorkMap;
private List<Scheduler> mSchedulers;
private Executor mExecutor;
@@ -50,10 +52,12 @@ public class Processor implements ExecutionListener {
public Processor(
Context appContext,
+ Configuration configuration,
WorkDatabase workDatabase,
List<Scheduler> schedulers,
Executor executor) {
mAppContext = appContext;
+ mConfiguration = configuration;
mWorkDatabase = workDatabase;
mEnqueuedWorkMap = new HashMap<>();
mSchedulers = schedulers;
@@ -87,11 +91,12 @@ public class Processor implements ExecutionListener {
return false;
}
- WorkerWrapper workWrapper = new WorkerWrapper.Builder(mAppContext, mWorkDatabase, id)
- .withListener(this)
- .withSchedulers(mSchedulers)
- .withRuntimeExtras(runtimeExtras)
- .build();
+ WorkerWrapper workWrapper =
+ new WorkerWrapper.Builder(mAppContext, mConfiguration, mWorkDatabase, id)
+ .withListener(this)
+ .withSchedulers(mSchedulers)
+ .withRuntimeExtras(runtimeExtras)
+ .build();
mEnqueuedWorkMap.put(id, workWrapper);
mExecutor.execute(workWrapper);
Log.d(TAG, String.format("%s: processing %s", getClass().getSimpleName(), id));
diff --git a/work/workmanager/src/main/java/androidx/work/impl/Schedulers.java b/work/workmanager/src/main/java/androidx/work/impl/Schedulers.java
index c6e5b816083..4944549d6fa 100644
--- a/work/workmanager/src/main/java/androidx/work/impl/Schedulers.java
+++ b/work/workmanager/src/main/java/androidx/work/impl/Schedulers.java
@@ -25,6 +25,7 @@ import android.support.annotation.RestrictTo;
import android.support.annotation.VisibleForTesting;
import android.util.Log;
+import androidx.work.Configuration;
import androidx.work.impl.background.systemalarm.SystemAlarmScheduler;
import androidx.work.impl.background.systemalarm.SystemAlarmService;
import androidx.work.impl.background.systemjob.SystemJobScheduler;
@@ -61,11 +62,14 @@ public class Schedulers {
* @param schedulers The {@link List} of {@link Scheduler}s to delegate to.
*/
public static void schedule(
+ @NonNull Configuration configuration,
@NonNull WorkDatabase workDatabase,
List<Scheduler> schedulers) {
WorkSpecDao workSpecDao = workDatabase.workSpecDao();
- List<WorkSpec> eligibleWorkSpecs = workSpecDao.getEligibleWorkForScheduling();
+ List<WorkSpec> eligibleWorkSpecs =
+ workSpecDao.getEligibleWorkForScheduling(
+ configuration.getMaxSchedulerLimit());
scheduleInternal(workDatabase, schedulers, eligibleWorkSpecs);
}
diff --git a/work/workmanager/src/main/java/androidx/work/impl/WorkDatabaseMigrations.java b/work/workmanager/src/main/java/androidx/work/impl/WorkDatabaseMigrations.java
index 0c3e3db484c..82a26ac58cd 100644
--- a/work/workmanager/src/main/java/androidx/work/impl/WorkDatabaseMigrations.java
+++ b/work/workmanager/src/main/java/androidx/work/impl/WorkDatabaseMigrations.java
@@ -38,7 +38,7 @@ public class WorkDatabaseMigrations {
private static final int VERSION_2 = 2;
private static final String CREATE_SYSTEM_ID_INFO =
- "CREATE TABLE IF NOT EXISTS `systemIdInfo` (`work_spec_id` TEXT NOT NULL, `system_id`"
+ "CREATE TABLE IF NOT EXISTS `SystemIdInfo` (`work_spec_id` TEXT NOT NULL, `system_id`"
+ " INTEGER NOT NULL, PRIMARY KEY(`work_spec_id`), FOREIGN KEY(`work_spec_id`)"
+ " REFERENCES `WorkSpec`(`id`) ON UPDATE CASCADE ON DELETE CASCADE )";
@@ -49,20 +49,20 @@ public class WorkDatabaseMigrations {
+ "CASCADE )";
private static final String MIGRATE_ALARM_INFO_TO_SYSTEM_ID_INFO =
- "INSERT INTO systemIdInfo(work_spec_id, system_id) "
+ "INSERT INTO SystemIdInfo(work_spec_id, system_id) "
+ "SELECT work_spec_id, alarm_id AS system_id FROM alarmInfo";
private static final String MIGRATE_SYSTEM_ID_INFO_TO_ALARM_INFO =
"INSERT INTO alarmInfo(work_spec_id, alarm_id) "
- + "SELECT work_spec_id, system_id AS alarm_id FROM systemIdInfo";
+ + "SELECT work_spec_id, system_id AS alarm_id FROM SystemIdInfo";
private static final String REMOVE_ALARM_INFO = "DROP TABLE IF EXISTS alarmInfo";
- private static final String REMOVE_SYSTEM_ID_INFO = "DROP TABLE IF EXISTS systemIdInfo";
-
+ private static final String REMOVE_SYSTEM_ID_INFO = "DROP TABLE IF EXISTS SystemIdInfo";
/**
* Removes the {@code alarmInfo} table and substitutes it for a more general
- * {@code systemIdInfo} table.
+ * {@code SystemIdInfo} table.
+ * Adds implicit work tags for all work (a tag with the worker class name).
*/
public static Migration MIGRATION_1_2 = new Migration(VERSION_1, VERSION_2) {
@Override
@@ -70,12 +70,14 @@ public class WorkDatabaseMigrations {
database.execSQL(CREATE_SYSTEM_ID_INFO);
database.execSQL(MIGRATE_ALARM_INFO_TO_SYSTEM_ID_INFO);
database.execSQL(REMOVE_ALARM_INFO);
+ database.execSQL("INSERT INTO worktag(tag, work_spec_id) "
+ + "SELECT worker_class_name AS tag, id AS work_spec_id FROM workspec");
}
};
/**
* Removes the {@code alarmInfo} table and substitutes it for a more general
- * {@code systemIdInfo} table.
+ * {@code SystemIdInfo} table.
*/
public static Migration MIGRATION_2_1 = new Migration(VERSION_2, VERSION_1) {
@Override
@@ -83,6 +85,7 @@ public class WorkDatabaseMigrations {
database.execSQL(CREATE_ALARM_INFO);
database.execSQL(MIGRATE_SYSTEM_ID_INFO_TO_ALARM_INFO);
database.execSQL(REMOVE_SYSTEM_ID_INFO);
+ // Don't remove implicit tags; they may have been added by the developer.
}
};
}
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 119325c412a..0dcdda349c6 100644
--- a/work/workmanager/src/main/java/androidx/work/impl/WorkManagerImpl.java
+++ b/work/workmanager/src/main/java/androidx/work/impl/WorkManagerImpl.java
@@ -43,6 +43,7 @@ import androidx.work.impl.utils.CancelWorkRunnable;
import androidx.work.impl.utils.ForceStopRunnable;
import androidx.work.impl.utils.LiveDataUtils;
import androidx.work.impl.utils.Preferences;
+import androidx.work.impl.utils.PruneWorkRunnable;
import androidx.work.impl.utils.StartWorkRunnable;
import androidx.work.impl.utils.StopWorkRunnable;
import androidx.work.impl.utils.taskexecutor.TaskExecutor;
@@ -166,6 +167,7 @@ public class WorkManagerImpl extends WorkManager implements SynchronousWorkManag
mTaskExecutor = WorkManagerTaskExecutor.getInstance();
mProcessor = new Processor(
context,
+ mConfiguration,
mWorkDatabase,
getSchedulers(),
configuration.getExecutor());
@@ -349,6 +351,7 @@ public class WorkManagerImpl extends WorkManager implements SynchronousWorkManag
}
@Override
+ @WorkerThread
public void cancelUniqueWorkSync(@NonNull String uniqueWorkName) {
assertBackgroundThread("Cannot cancelAllWorkByNameBlocking on main thread!");
CancelWorkRunnable.forName(uniqueWorkName, this).run();
@@ -360,6 +363,7 @@ public class WorkManagerImpl extends WorkManager implements SynchronousWorkManag
}
@Override
+ @WorkerThread
public void cancelAllWorkSync() {
assertBackgroundThread("Cannot cancelAllWorkSync on main thread!");
CancelWorkRunnable.forAll(this).run();
@@ -376,6 +380,18 @@ public class WorkManagerImpl extends WorkManager implements SynchronousWorkManag
}
@Override
+ public void pruneWork() {
+ mTaskExecutor.executeOnBackgroundThread(new PruneWorkRunnable(this));
+ }
+
+ @Override
+ @WorkerThread
+ public void pruneWorkSync() {
+ assertBackgroundThread("Cannot pruneWork on main thread!");
+ new PruneWorkRunnable(this).run();
+ }
+
+ @Override
public LiveData<WorkStatus> getStatusById(@NonNull UUID id) {
WorkSpecDao dao = mWorkDatabase.workSpecDao();
LiveData<List<WorkSpec.WorkStatusPojo>> inputLiveData =
@@ -500,7 +516,7 @@ public class WorkManagerImpl extends WorkManager implements SynchronousWorkManag
// Delegate to the WorkManager's schedulers.
// Using getters here so we can use from a mocked instance
// of WorkManagerImpl.
- Schedulers.schedule(getWorkDatabase(), getSchedulers());
+ Schedulers.schedule(getConfiguration(), getWorkDatabase(), getSchedulers());
}
private void assertBackgroundThread(String errorMessage) {
diff --git a/work/workmanager/src/main/java/androidx/work/impl/WorkerWrapper.java b/work/workmanager/src/main/java/androidx/work/impl/WorkerWrapper.java
index b6d4fc16cf7..0b8c44c83e7 100644
--- a/work/workmanager/src/main/java/androidx/work/impl/WorkerWrapper.java
+++ b/work/workmanager/src/main/java/androidx/work/impl/WorkerWrapper.java
@@ -30,6 +30,7 @@ import android.support.annotation.VisibleForTesting;
import android.support.annotation.WorkerThread;
import android.util.Log;
+import androidx.work.Configuration;
import androidx.work.Data;
import androidx.work.InputMerger;
import androidx.work.State;
@@ -63,6 +64,7 @@ public class WorkerWrapper implements Runnable {
private WorkSpec mWorkSpec;
Worker mWorker;
+ private Configuration mConfiguration;
private WorkDatabase mWorkDatabase;
private WorkSpecDao mWorkSpecDao;
private DependencyDao mDependencyDao;
@@ -78,6 +80,7 @@ public class WorkerWrapper implements Runnable {
mRuntimeExtras = builder.mRuntimeExtras;
mWorker = builder.mWorker;
+ mConfiguration = builder.mConfiguration;
mWorkDatabase = builder.mWorkDatabase;
mWorkSpecDao = mWorkDatabase.workSpecDao();
mDependencyDao = mWorkDatabase.dependencyDao();
@@ -300,7 +303,7 @@ public class WorkerWrapper implements Runnable {
notifyListener(false, false);
}
- Schedulers.schedule(mWorkDatabase, mSchedulers);
+ Schedulers.schedule(mConfiguration, mWorkDatabase, mSchedulers);
}
private void recursivelyFailWorkAndDependents(String workSpecId) {
@@ -370,7 +373,7 @@ public class WorkerWrapper implements Runnable {
}
// This takes of scheduling the dependent workers as they have been marked ENQUEUED.
- Schedulers.schedule(mWorkDatabase, mSchedulers);
+ Schedulers.schedule(mConfiguration, mWorkDatabase, mSchedulers);
}
static Worker workerFromWorkSpec(@NonNull Context context,
@@ -434,6 +437,7 @@ public class WorkerWrapper implements Runnable {
private Context mAppContext;
@Nullable
private Worker mWorker;
+ private Configuration mConfiguration;
private WorkDatabase mWorkDatabase;
private String mWorkSpecId;
private ExecutionListener mListener;
@@ -441,9 +445,11 @@ public class WorkerWrapper implements Runnable {
private Extras.RuntimeExtras mRuntimeExtras;
public Builder(@NonNull Context context,
+ @NonNull Configuration configuration,
@NonNull WorkDatabase database,
@NonNull String workSpecId) {
mAppContext = context.getApplicationContext();
+ mConfiguration = configuration;
mWorkDatabase = database;
mWorkSpecId = workSpecId;
}
diff --git a/work/workmanager/src/main/java/androidx/work/impl/background/systemalarm/ConstraintsCommandHandler.java b/work/workmanager/src/main/java/androidx/work/impl/background/systemalarm/ConstraintsCommandHandler.java
index 94cc2db75a7..6dbd752bea7 100644
--- a/work/workmanager/src/main/java/androidx/work/impl/background/systemalarm/ConstraintsCommandHandler.java
+++ b/work/workmanager/src/main/java/androidx/work/impl/background/systemalarm/ConstraintsCommandHandler.java
@@ -60,9 +60,14 @@ class ConstraintsCommandHandler {
@WorkerThread
void handleConstraintsChanged() {
+ int schedulerLimit = mDispatcher
+ .getWorkManager()
+ .getConfiguration()
+ .getMaxSchedulerLimit();
+
List<WorkSpec> candidates = mDispatcher.getWorkManager().getWorkDatabase()
.workSpecDao()
- .getEligibleWorkForScheduling();
+ .getEligibleWorkForScheduling(schedulerLimit);
// Filter candidates that are marked as SCHEDULE_NOT_REQUESTED_AT
List<WorkSpec> eligibleWorkSpecs = new ArrayList<>(candidates.size());
diff --git a/work/workmanager/src/main/java/androidx/work/impl/model/SystemIdInfo.java b/work/workmanager/src/main/java/androidx/work/impl/model/SystemIdInfo.java
index e869762592d..cd97958483e 100644
--- a/work/workmanager/src/main/java/androidx/work/impl/model/SystemIdInfo.java
+++ b/work/workmanager/src/main/java/androidx/work/impl/model/SystemIdInfo.java
@@ -28,8 +28,7 @@ import android.support.annotation.RestrictTo;
*
* @hide
*/
-@Entity(tableName = "systemIdInfo",
- foreignKeys = {
+@Entity(foreignKeys = {
@ForeignKey(
entity = WorkSpec.class,
parentColumns = "id",
diff --git a/work/workmanager/src/main/java/androidx/work/impl/model/SystemIdInfoDao.java b/work/workmanager/src/main/java/androidx/work/impl/model/SystemIdInfoDao.java
index bcee05b767d..383e51610c3 100644
--- a/work/workmanager/src/main/java/androidx/work/impl/model/SystemIdInfoDao.java
+++ b/work/workmanager/src/main/java/androidx/work/impl/model/SystemIdInfoDao.java
@@ -42,7 +42,7 @@ public interface SystemIdInfoDao {
* @return The instance of {@link SystemIdInfo} if exists.
*/
@Nullable
- @Query("SELECT * FROM systemIdInfo WHERE work_spec_id=:workSpecId")
+ @Query("SELECT * FROM SystemIdInfo WHERE work_spec_id=:workSpecId")
SystemIdInfo getSystemIdInfo(@NonNull String workSpecId);
/**
@@ -50,6 +50,6 @@ public interface SystemIdInfoDao {
*
* @param workSpecId The {@link WorkSpec} identifier.
*/
- @Query("DELETE FROM systemIdInfo where work_spec_id=:workSpecId")
+ @Query("DELETE FROM SystemIdInfo where work_spec_id=:workSpecId")
void removeSystemIdInfo(@NonNull String workSpecId);
}
diff --git a/work/workmanager/src/main/java/androidx/work/impl/model/WorkSpecDao.java b/work/workmanager/src/main/java/androidx/work/impl/model/WorkSpecDao.java
index 7d9775d380f..e15124fa8f5 100644
--- a/work/workmanager/src/main/java/androidx/work/impl/model/WorkSpecDao.java
+++ b/work/workmanager/src/main/java/androidx/work/impl/model/WorkSpecDao.java
@@ -29,7 +29,6 @@ import android.support.annotation.NonNull;
import androidx.work.Data;
import androidx.work.State;
-import androidx.work.impl.Scheduler;
import java.util.List;
@@ -285,10 +284,23 @@ public interface WorkSpecDao {
// We only want WorkSpecs which have not been previously scheduled.
+ " AND schedule_requested_at=" + WorkSpec.SCHEDULE_NOT_REQUESTED_YET
+ " LIMIT "
- + "(SELECT " + Scheduler.MAX_SCHEDULER_LIMIT + "-COUNT(*) FROM workspec WHERE"
+ + "(SELECT :schedulerLimit" + "-COUNT(*) FROM workspec WHERE"
+ " schedule_requested_at<>" + WorkSpec.SCHEDULE_NOT_REQUESTED_YET
+ " AND state NOT IN " + COMPLETED_STATES
+ ")"
)
- List<WorkSpec> getEligibleWorkForScheduling();
+ List<WorkSpec> getEligibleWorkForScheduling(int schedulerLimit);
+
+ /**
+ * Immediately prunes eligible work from the database meeting the following criteria:
+ * - Is finished (succeeded, failed, or cancelled)
+ * - Has zero unfinished dependents
+ */
+ @Query("DELETE FROM workspec WHERE "
+ + "state IN " + COMPLETED_STATES
+ + " AND (SELECT COUNT(*)=0 FROM dependency WHERE "
+ + " prerequisite_id=id AND "
+ + " work_spec_id NOT IN "
+ + " (SELECT id FROM workspec WHERE state IN " + COMPLETED_STATES + "))")
+ void pruneFinishedWorkWithZeroDependentsIgnoringKeepForAtLeast();
}
diff --git a/work/workmanager/src/main/java/androidx/work/impl/utils/CancelWorkRunnable.java b/work/workmanager/src/main/java/androidx/work/impl/utils/CancelWorkRunnable.java
index e117c95bc90..842fdc24166 100644
--- a/work/workmanager/src/main/java/androidx/work/impl/utils/CancelWorkRunnable.java
+++ b/work/workmanager/src/main/java/androidx/work/impl/utils/CancelWorkRunnable.java
@@ -56,7 +56,10 @@ public abstract class CancelWorkRunnable implements Runnable {
}
void reschedulePendingWorkers(WorkManagerImpl workManagerImpl) {
- Schedulers.schedule(workManagerImpl.getWorkDatabase(), workManagerImpl.getSchedulers());
+ Schedulers.schedule(
+ workManagerImpl.getConfiguration(),
+ workManagerImpl.getWorkDatabase(),
+ workManagerImpl.getSchedulers());
}
private void recursivelyCancelWorkAndDependents(WorkDatabase workDatabase, String workSpecId) {
diff --git a/work/workmanager/src/main/java/androidx/work/impl/utils/EnqueueRunnable.java b/work/workmanager/src/main/java/androidx/work/impl/utils/EnqueueRunnable.java
index 004b895b894..00d7b8f920f 100644
--- a/work/workmanager/src/main/java/androidx/work/impl/utils/EnqueueRunnable.java
+++ b/work/workmanager/src/main/java/androidx/work/impl/utils/EnqueueRunnable.java
@@ -106,7 +106,10 @@ public class EnqueueRunnable implements Runnable {
@VisibleForTesting
public void scheduleWorkInBackground() {
WorkManagerImpl workManager = mWorkContinuation.getWorkManagerImpl();
- Schedulers.schedule(workManager.getWorkDatabase(), workManager.getSchedulers());
+ Schedulers.schedule(
+ workManager.getConfiguration(),
+ workManager.getWorkDatabase(),
+ workManager.getSchedulers());
}
private static boolean processContinuation(@NonNull WorkContinuationImpl workContinuation) {
diff --git a/work/workmanager/src/main/java/androidx/work/impl/utils/PruneWorkRunnable.java b/work/workmanager/src/main/java/androidx/work/impl/utils/PruneWorkRunnable.java
new file mode 100644
index 00000000000..bf93f4602a6
--- /dev/null
+++ b/work/workmanager/src/main/java/androidx/work/impl/utils/PruneWorkRunnable.java
@@ -0,0 +1,47 @@
+/*
+ * 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.impl.utils;
+
+import android.support.annotation.RestrictTo;
+
+import androidx.work.impl.WorkDatabase;
+import androidx.work.impl.WorkManagerImpl;
+import androidx.work.impl.model.WorkSpecDao;
+
+/**
+ * A Runnable that prunes work in the background. Pruned work meets the following criteria:
+ * - Is finished (succeeded, failed, or cancelled)
+ * - Has zero unfinished dependents
+ *
+ * @hide
+ */
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+public class PruneWorkRunnable implements Runnable {
+
+ private WorkManagerImpl mWorkManagerImpl;
+
+ public PruneWorkRunnable(WorkManagerImpl workManagerImpl) {
+ mWorkManagerImpl = workManagerImpl;
+ }
+
+ @Override
+ public void run() {
+ WorkDatabase workDatabase = mWorkManagerImpl.getWorkDatabase();
+ WorkSpecDao workSpecDao = workDatabase.workSpecDao();
+ workSpecDao.pruneFinishedWorkWithZeroDependentsIgnoringKeepForAtLeast();
+ }
+}
diff --git a/work/workmanager/src/schemas/androidx.work.impl.WorkDatabase/2.json b/work/workmanager/src/schemas/androidx.work.impl.WorkDatabase/2.json
index 00bc68d43eb..400e545684d 100644
--- a/work/workmanager/src/schemas/androidx.work.impl.WorkDatabase/2.json
+++ b/work/workmanager/src/schemas/androidx.work.impl.WorkDatabase/2.json
@@ -2,7 +2,7 @@
"formatVersion": 1,
"database": {
"version": 2,
- "identityHash": "244d2ac5ecd0a7fb47b3755737585d7b",
+ "identityHash": "c45e5fcbdf3824dead9778f19e2fd8af",
"entities": [
{
"tableName": "Dependency",
@@ -269,7 +269,7 @@
]
},
{
- "tableName": "systemIdInfo",
+ "tableName": "SystemIdInfo",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`work_spec_id` TEXT NOT NULL, `system_id` INTEGER NOT NULL, PRIMARY KEY(`work_spec_id`), FOREIGN KEY(`work_spec_id`) REFERENCES `WorkSpec`(`id`) ON UPDATE CASCADE ON DELETE CASCADE )",
"fields": [
{
@@ -357,7 +357,7 @@
],
"setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
- "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, \"244d2ac5ecd0a7fb47b3755737585d7b\")"
+ "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, \"c45e5fcbdf3824dead9778f19e2fd8af\")"
]
}
} \ No newline at end of file