Support independent application migration versions.
This commit is contained in:
parent
f81c0b448e
commit
d1a6582ad7
11 changed files with 158 additions and 63 deletions
|
@ -36,6 +36,7 @@ import org.signal.aesgcmprovider.AesGcmProvider;
|
|||
import org.thoughtcrime.securesms.components.TypingStatusRepository;
|
||||
import org.thoughtcrime.securesms.components.TypingStatusSender;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper;
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencyProvider;
|
||||
import org.thoughtcrime.securesms.gcm.FcmJobService;
|
||||
|
@ -69,6 +70,7 @@ import org.thoughtcrime.securesms.service.RotateSenderCertificateListener;
|
|||
import org.thoughtcrime.securesms.service.RotateSignedPreKeyListener;
|
||||
import org.thoughtcrime.securesms.service.UpdateApkRefreshListener;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.thoughtcrime.securesms.util.VersionTracker;
|
||||
import org.thoughtcrime.securesms.util.dynamiclanguage.DynamicLanguageContextWrapper;
|
||||
import org.webrtc.PeerConnectionFactory;
|
||||
import org.webrtc.PeerConnectionFactory.InitializationOptions;
|
||||
|
@ -94,7 +96,7 @@ public class ApplicationContext extends MultiDexApplication implements DefaultLi
|
|||
private static final String TAG = ApplicationContext.class.getSimpleName();
|
||||
|
||||
private ExpiringMessageManager expiringMessageManager;
|
||||
private ViewOnceMessageManager viewOnceMessageManager;
|
||||
private ViewOnceMessageManager viewOnceMessageManager;
|
||||
private TypingStatusRepository typingStatusRepository;
|
||||
private TypingStatusSender typingStatusSender;
|
||||
private JobManager jobManager;
|
||||
|
@ -114,6 +116,7 @@ public class ApplicationContext extends MultiDexApplication implements DefaultLi
|
|||
initializeSecurityProvider();
|
||||
initializeLogging();
|
||||
initializeCrashHandling();
|
||||
initializeFirstEverAppLaunch();
|
||||
initializeAppDependencies();
|
||||
initializeJobManager();
|
||||
initializeApplicationMigrations();
|
||||
|
@ -223,7 +226,7 @@ public class ApplicationContext extends MultiDexApplication implements DefaultLi
|
|||
.setConstraintFactories(JobManagerFactories.getConstraintFactories(this))
|
||||
.setConstraintObservers(JobManagerFactories.getConstraintObservers(this))
|
||||
.setJobStorage(new FastJobStorage(DatabaseFactory.getJobDatabase(this)))
|
||||
.setJobMigrator(new JobMigrator(TextSecurePreferences.getJobManagerVersion(this), 2, JobManagerFactories.getJobMigrations(this)))
|
||||
.setJobMigrator(new JobMigrator(TextSecurePreferences.getJobManagerVersion(this), JobManager.CURRENT_VERSION, JobManagerFactories.getJobMigrations(this)))
|
||||
.build());
|
||||
}
|
||||
|
||||
|
@ -239,6 +242,20 @@ public class ApplicationContext extends MultiDexApplication implements DefaultLi
|
|||
ApplicationDependencies.init(this, new ApplicationDependencyProvider(this, new SignalServiceNetworkAccess(this)));
|
||||
}
|
||||
|
||||
private void initializeFirstEverAppLaunch() {
|
||||
if (TextSecurePreferences.getFirstInstallVersion(this) == -1) {
|
||||
if (!SQLCipherOpenHelper.databaseFileExists(this)) {
|
||||
Log.i(TAG, "First ever app launch!");
|
||||
|
||||
TextSecurePreferences.setAppMigrationVersion(this, ApplicationMigrations.CURRENT_VERSION);
|
||||
TextSecurePreferences.setJobManagerVersion(this, JobManager.CURRENT_VERSION);
|
||||
}
|
||||
|
||||
Log.i(TAG, "Setting first install version to " + BuildConfig.CANONICAL_VERSION_CODE);
|
||||
TextSecurePreferences.setFirstInstallVersion(this, BuildConfig.CANONICAL_VERSION_CODE);
|
||||
}
|
||||
}
|
||||
|
||||
private void initializeGcmCheck() {
|
||||
if (TextSecurePreferences.isPushRegistered(this)) {
|
||||
long nextSetTime = TextSecurePreferences.getFcmTokenLastSetTime(this) + TimeUnit.HOURS.toMillis(6);
|
||||
|
|
|
@ -30,7 +30,7 @@ public abstract class PassphraseRequiredActionBarActivity extends BaseActionBarA
|
|||
private static final int STATE_NORMAL = 0;
|
||||
private static final int STATE_CREATE_PASSPHRASE = 1;
|
||||
private static final int STATE_PROMPT_PASSPHRASE = 2;
|
||||
private static final int STATE_UPGRADE_DATABASE = 3;
|
||||
private static final int STATE_UI_BLOCKING_UPGRADE = 3;
|
||||
private static final int STATE_PROMPT_PUSH_REGISTRATION = 4;
|
||||
private static final int STATE_EXPERIENCE_UPGRADE = 5;
|
||||
private static final int STATE_WELCOME_SCREEN = 6;
|
||||
|
@ -133,7 +133,7 @@ public abstract class PassphraseRequiredActionBarActivity extends BaseActionBarA
|
|||
switch (state) {
|
||||
case STATE_CREATE_PASSPHRASE: return getCreatePassphraseIntent();
|
||||
case STATE_PROMPT_PASSPHRASE: return getPromptPassphraseIntent();
|
||||
case STATE_UPGRADE_DATABASE: return getUpgradeDatabaseIntent();
|
||||
case STATE_UI_BLOCKING_UPGRADE: return getUiBlockingUpgradeIntent();
|
||||
case STATE_WELCOME_SCREEN: return getWelcomeIntent();
|
||||
case STATE_PROMPT_PUSH_REGISTRATION: return getPushRegistrationIntent();
|
||||
case STATE_EXPERIENCE_UPGRADE: return getExperienceUpgradeIntent();
|
||||
|
@ -146,8 +146,8 @@ public abstract class PassphraseRequiredActionBarActivity extends BaseActionBarA
|
|||
return STATE_CREATE_PASSPHRASE;
|
||||
} else if (locked) {
|
||||
return STATE_PROMPT_PASSPHRASE;
|
||||
} else if (ApplicationMigrations.isUpdate(this)) {
|
||||
return STATE_UPGRADE_DATABASE;
|
||||
} else if (ApplicationMigrations.isUpdate(this) && ApplicationMigrations.isUiBlockingMigrationRunning()) {
|
||||
return STATE_UI_BLOCKING_UPGRADE;
|
||||
} else if (!TextSecurePreferences.hasSeenWelcomeScreen(this)) {
|
||||
return STATE_WELCOME_SCREEN;
|
||||
} else if (!TextSecurePreferences.hasPromptedPushRegistration(this)) {
|
||||
|
@ -167,7 +167,7 @@ public abstract class PassphraseRequiredActionBarActivity extends BaseActionBarA
|
|||
return getRoutedIntent(PassphrasePromptActivity.class, getIntent());
|
||||
}
|
||||
|
||||
private Intent getUpgradeDatabaseIntent() {
|
||||
private Intent getUiBlockingUpgradeIntent() {
|
||||
return getRoutedIntent(ApplicationMigrationActivity.class,
|
||||
TextSecurePreferences.hasPromptedPushRegistration(this)
|
||||
? getConversationListIntent()
|
||||
|
|
|
@ -535,6 +535,10 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
|
|||
db.setVersion(DATABASE_VERSION);
|
||||
}
|
||||
|
||||
public static boolean databaseFileExists(@NonNull Context context) {
|
||||
return context.getDatabasePath(DATABASE_NAME).exists();
|
||||
}
|
||||
|
||||
private void executeStatements(SQLiteDatabase db, String[] statements) {
|
||||
for (String statement : statements)
|
||||
db.execSQL(statement);
|
||||
|
|
|
@ -261,7 +261,7 @@ class JobController {
|
|||
JobSpec jobSpec = new JobSpec(job.getId(),
|
||||
job.getFactoryKey(),
|
||||
job.getParameters().getQueue(),
|
||||
job.getParameters().getCreateTime(),
|
||||
System.currentTimeMillis(),
|
||||
job.getNextRunAttemptTime(),
|
||||
job.getRunAttempt(),
|
||||
job.getParameters().getMaxAttempts(),
|
||||
|
|
|
@ -33,6 +33,8 @@ public class JobManager implements ConstraintObserver.Notifier {
|
|||
|
||||
private static final String TAG = JobManager.class.getSimpleName();
|
||||
|
||||
public static final int CURRENT_VERSION = 2;
|
||||
|
||||
private final Application application;
|
||||
private final Configuration configuration;
|
||||
private final ExecutorService executor;
|
||||
|
|
|
@ -93,7 +93,7 @@ public class FastJobStorage implements JobStorage {
|
|||
public synchronized @NonNull List<JobSpec> getPendingJobsWithNoDependenciesInCreatedOrder(long currentTime) {
|
||||
Optional<JobSpec> migrationJob = getMigrationJob();
|
||||
|
||||
if (migrationJob.isPresent() && !migrationJob.get().isRunning()) {
|
||||
if (migrationJob.isPresent() && !migrationJob.get().isRunning() && migrationJob.get().getNextRunAttemptTime() <= currentTime) {
|
||||
return Collections.singletonList(migrationJob.get());
|
||||
} else if (migrationJob.isPresent()) {
|
||||
return Collections.emptyList();
|
||||
|
|
|
@ -59,6 +59,7 @@ import org.thoughtcrime.securesms.contactshare.SimpleTextWatcher;
|
|||
import org.thoughtcrime.securesms.logging.Log;
|
||||
import org.thoughtcrime.securesms.logsubmit.util.Scrubber;
|
||||
import org.thoughtcrime.securesms.util.BucketInfo;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
import org.thoughtcrime.securesms.util.task.ProgressDialogAsyncTask;
|
||||
|
||||
|
@ -513,19 +514,19 @@ public class SubmitLogFragment extends Fragment {
|
|||
final PackageManager pm = context.getPackageManager();
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
|
||||
builder.append("Time : ").append(System.currentTimeMillis()).append('\n');
|
||||
builder.append("Device : ")
|
||||
.append(Build.MANUFACTURER).append(" ")
|
||||
.append(Build.MODEL).append(" (")
|
||||
.append(Build.PRODUCT).append(")\n");
|
||||
builder.append("Android : ").append(VERSION.RELEASE).append(" (")
|
||||
.append(VERSION.INCREMENTAL).append(", ")
|
||||
.append(Build.DISPLAY).append(")\n");
|
||||
builder.append("ABIs : ").append(TextUtils.join(", ", getSupportedAbis())).append("\n");
|
||||
builder.append("Memory : ").append(getMemoryUsage(context)).append("\n");
|
||||
builder.append("Memclass: ").append(getMemoryClass(context)).append("\n");
|
||||
builder.append("OS Host : ").append(Build.HOST).append("\n");
|
||||
builder.append("App : ");
|
||||
builder.append("Time : ").append(System.currentTimeMillis()).append('\n');
|
||||
builder.append("Device : ").append(Build.MANUFACTURER).append(" ")
|
||||
.append(Build.MODEL).append(" (")
|
||||
.append(Build.PRODUCT).append(")\n");
|
||||
builder.append("Android : ").append(VERSION.RELEASE).append(" (")
|
||||
.append(VERSION.INCREMENTAL).append(", ")
|
||||
.append(Build.DISPLAY).append(")\n");
|
||||
builder.append("ABIs : ").append(TextUtils.join(", ", getSupportedAbis())).append("\n");
|
||||
builder.append("Memory : ").append(getMemoryUsage(context)).append("\n");
|
||||
builder.append("Memclass : ").append(getMemoryClass(context)).append("\n");
|
||||
builder.append("OS Host : ").append(Build.HOST).append("\n");
|
||||
builder.append("First Version: ").append(TextSecurePreferences.getFirstInstallVersion(context)).append("\n");
|
||||
builder.append("App : ");
|
||||
try {
|
||||
builder.append(pm.getApplicationLabel(pm.getApplicationInfo(context.getPackageName(), 0)))
|
||||
.append(" ")
|
||||
|
|
|
@ -35,7 +35,7 @@ public class ApplicationMigrationActivity extends BaseActivity {
|
|||
public void onCreate(Bundle bundle) {
|
||||
super.onCreate(bundle);
|
||||
|
||||
ApplicationMigrations.isUiBlockingMigrationRunning().observe(this, running -> {
|
||||
ApplicationMigrations.getUiBlockingMigrationStatus().observe(this, running -> {
|
||||
if (running == null) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -6,19 +6,17 @@ import androidx.annotation.NonNull;
|
|||
import androidx.lifecycle.LiveData;
|
||||
import androidx.lifecycle.MutableLiveData;
|
||||
|
||||
import com.annimon.stream.Stream;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
import org.greenrobot.eventbus.ThreadMode;
|
||||
import org.thoughtcrime.securesms.database.RecipientDatabase;
|
||||
import org.thoughtcrime.securesms.jobmanager.JobManager;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
import org.thoughtcrime.securesms.util.VersionTracker;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Manages application-level migrations.
|
||||
|
@ -38,10 +36,14 @@ public class ApplicationMigrations {
|
|||
|
||||
private static final MutableLiveData<Boolean> UI_BLOCKING_MIGRATION_RUNNING = new MutableLiveData<>();
|
||||
|
||||
private static final int LEGACY_CANONICAL_VERSION = 455;
|
||||
|
||||
public static final int CURRENT_VERSION = 3;
|
||||
|
||||
private static final class Version {
|
||||
static final int LEGACY = 455;
|
||||
static final int RECIPIENT_ID = 525; // TODO [greyson] USE PROPER APPLICATION VERSION
|
||||
static final int RECIPIENT_SEARCH = 525; // TODO [greyson] USE PROPER APPLICATION VERSION
|
||||
static final int LEGACY = 1;
|
||||
static final int RECIPIENT_ID = 2;
|
||||
static final int RECIPIENT_SEARCH = 3;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -50,58 +52,80 @@ public class ApplicationMigrations {
|
|||
* executing before we add the migration jobs.
|
||||
*/
|
||||
public static void onApplicationCreate(@NonNull Context context, @NonNull JobManager jobManager) {
|
||||
if (isLegacyUpdate(context)) {
|
||||
Log.i(TAG, "Detected the need for a legacy update. Last seen canonical version: " + VersionTracker.getLastSeenVersion(context));
|
||||
TextSecurePreferences.setAppMigrationVersion(context, 0);
|
||||
}
|
||||
|
||||
if (!isUpdate(context)) {
|
||||
Log.d(TAG, "Not an update. Skipping.");
|
||||
return;
|
||||
}
|
||||
|
||||
final int currentVersion = Util.getCanonicalVersionCode();
|
||||
final int lastSeenVersion = VersionTracker.getLastSeenVersion(context);
|
||||
final int lastSeenVersion = TextSecurePreferences.getAppMigrationVersion(context);
|
||||
Log.d(TAG, "currentVersion: " + CURRENT_VERSION + ", lastSeenVersion: " + lastSeenVersion);
|
||||
|
||||
Log.d(TAG, "currentVersion: " + currentVersion + " lastSeenVersion: " + lastSeenVersion);
|
||||
|
||||
List<MigrationJob> migrationJobs = getMigrationJobs(context, lastSeenVersion);
|
||||
LinkedHashMap<Integer, MigrationJob> migrationJobs = getMigrationJobs(context, lastSeenVersion);
|
||||
|
||||
if (migrationJobs.size() > 0) {
|
||||
Log.i(TAG, "About to enqueue " + migrationJobs.size() + " migration(s).");
|
||||
|
||||
boolean uiBlocking = Stream.of(migrationJobs).reduce(false, (existing, job) -> existing || job.isUiBlocking());
|
||||
UI_BLOCKING_MIGRATION_RUNNING.postValue(uiBlocking);
|
||||
boolean uiBlocking = true;
|
||||
int uiBlockingVersion = lastSeenVersion;
|
||||
|
||||
if (uiBlocking) {
|
||||
Log.i(TAG, "Migration set is UI-blocking.");
|
||||
for (Map.Entry<Integer, MigrationJob> entry : migrationJobs.entrySet()) {
|
||||
int version = entry.getKey();
|
||||
MigrationJob job = entry.getValue();
|
||||
|
||||
uiBlocking &= job.isUiBlocking();
|
||||
if (uiBlocking) {
|
||||
uiBlockingVersion = version;
|
||||
}
|
||||
|
||||
jobManager.add(job);
|
||||
jobManager.add(new MigrationCompleteJob(version));
|
||||
}
|
||||
|
||||
if (uiBlockingVersion > lastSeenVersion) {
|
||||
Log.i(TAG, "Migration set is UI-blocking through version " + uiBlockingVersion + ".");
|
||||
UI_BLOCKING_MIGRATION_RUNNING.setValue(true);
|
||||
} else {
|
||||
Log.i(TAG, "Migration set is non-UI-blocking.");
|
||||
UI_BLOCKING_MIGRATION_RUNNING.setValue(false);
|
||||
}
|
||||
|
||||
for (MigrationJob job : migrationJobs) {
|
||||
jobManager.add(job);
|
||||
}
|
||||
|
||||
jobManager.add(new MigrationCompleteJob(currentVersion));
|
||||
|
||||
final long startTime = System.currentTimeMillis();
|
||||
final int uiVersion = uiBlockingVersion;
|
||||
|
||||
EventBus.getDefault().register(new Object() {
|
||||
@Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
|
||||
public void onMigrationComplete(MigrationCompleteEvent event) {
|
||||
Log.i(TAG, "Received MigrationCompleteEvent for version " + event.getVersion() + ".");
|
||||
Log.i(TAG, "Received MigrationCompleteEvent for version " + event.getVersion() + ". (Current: " + CURRENT_VERSION + ")");
|
||||
|
||||
if (event.getVersion() == currentVersion) {
|
||||
if (event.getVersion() > CURRENT_VERSION) {
|
||||
throw new AssertionError("Received a higher version than the current version? App downgrades are not supported. (received: " + event.getVersion() + ", current: " + CURRENT_VERSION + ")");
|
||||
}
|
||||
|
||||
Log.i(TAG, "Updating last migration version to " + event.getVersion());
|
||||
TextSecurePreferences.setAppMigrationVersion(context, event.getVersion());
|
||||
|
||||
if (event.getVersion() == CURRENT_VERSION) {
|
||||
Log.i(TAG, "Migration complete. Took " + (System.currentTimeMillis() - startTime) + " ms.");
|
||||
EventBus.getDefault().unregister(this);
|
||||
|
||||
VersionTracker.updateLastSeenVersion(context);
|
||||
UI_BLOCKING_MIGRATION_RUNNING.postValue(false);
|
||||
} else {
|
||||
Log.i(TAG, "Version doesn't match. Looking for " + currentVersion + ", but received " + event.getVersion() + ".");
|
||||
UI_BLOCKING_MIGRATION_RUNNING.setValue(false);
|
||||
} else if (event.getVersion() >= uiVersion) {
|
||||
Log.i(TAG, "Version is >= the UI-blocking version. Posting 'false'.");
|
||||
UI_BLOCKING_MIGRATION_RUNNING.setValue(false);
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
Log.d(TAG, "No migrations.");
|
||||
TextSecurePreferences.setAppMigrationVersion(context, CURRENT_VERSION);
|
||||
VersionTracker.updateLastSeenVersion(context);
|
||||
UI_BLOCKING_MIGRATION_RUNNING.postValue(false);
|
||||
UI_BLOCKING_MIGRATION_RUNNING.setValue(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -109,36 +133,45 @@ public class ApplicationMigrations {
|
|||
* @return A {@link LiveData} object that will update with whether or not a UI blocking migration
|
||||
* is in progress.
|
||||
*/
|
||||
public static LiveData<Boolean> isUiBlockingMigrationRunning() {
|
||||
public static LiveData<Boolean> getUiBlockingMigrationStatus() {
|
||||
return UI_BLOCKING_MIGRATION_RUNNING;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return True if a UI blocking migration is running.
|
||||
*/
|
||||
public static boolean isUiBlockingMigrationRunning() {
|
||||
Boolean value = UI_BLOCKING_MIGRATION_RUNNING.getValue();
|
||||
return value != null && value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Whether or not we're in the middle of an update, as determined by the last seen and
|
||||
* current version.
|
||||
*/
|
||||
public static boolean isUpdate(Context context) {
|
||||
int currentVersionCode = Util.getCanonicalVersionCode();
|
||||
int previousVersionCode = VersionTracker.getLastSeenVersion(context);
|
||||
|
||||
return previousVersionCode < currentVersionCode;
|
||||
public static boolean isUpdate(@NonNull Context context) {
|
||||
return isLegacyUpdate(context) || TextSecurePreferences.getAppMigrationVersion(context) < CURRENT_VERSION;
|
||||
}
|
||||
|
||||
private static List<MigrationJob> getMigrationJobs(@NonNull Context context, int lastSeenVersion) {
|
||||
List<MigrationJob> jobs = new LinkedList<>();
|
||||
private static LinkedHashMap<Integer, MigrationJob> getMigrationJobs(@NonNull Context context, int lastSeenVersion) {
|
||||
LinkedHashMap<Integer, MigrationJob> jobs = new LinkedHashMap<>();
|
||||
|
||||
if (lastSeenVersion < Version.LEGACY) {
|
||||
jobs.add(new LegacyMigrationJob());
|
||||
jobs.put(Version.LEGACY, new LegacyMigrationJob());
|
||||
}
|
||||
|
||||
if (lastSeenVersion < Version.RECIPIENT_ID) {
|
||||
jobs.add(new DatabaseMigrationJob());
|
||||
jobs.put(Version.RECIPIENT_ID, new DatabaseMigrationJob());
|
||||
}
|
||||
|
||||
if (lastSeenVersion < Version.RECIPIENT_SEARCH) {
|
||||
jobs.add(new RecipientSearchMigrationJob());
|
||||
jobs.put(Version.RECIPIENT_SEARCH, new RecipientSearchMigrationJob());
|
||||
}
|
||||
|
||||
return jobs;
|
||||
}
|
||||
|
||||
private static boolean isLegacyUpdate(@NonNull Context context) {
|
||||
return VersionTracker.getLastSeenVersion(context) < LEGACY_CANONICAL_VERSION;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -189,6 +189,10 @@ public class TextSecurePreferences {
|
|||
|
||||
private static final String JOB_MANAGER_VERSION = "pref_job_manager_version";
|
||||
|
||||
private static final String APP_MIGRATION_VERSION = "pref_app_migration_version";
|
||||
|
||||
private static final String FIRST_INSTALL_VERSION = "pref_first_install_version";
|
||||
|
||||
public static boolean isScreenLockEnabled(@NonNull Context context) {
|
||||
return getBooleanPreference(context, SCREEN_LOCK, false);
|
||||
}
|
||||
|
@ -1128,6 +1132,23 @@ public class TextSecurePreferences {
|
|||
return getIntegerPreference(contex, JOB_MANAGER_VERSION, 1);
|
||||
}
|
||||
|
||||
public static void setAppMigrationVersion(Context context, int version) {
|
||||
setIntegerPrefrence(context, APP_MIGRATION_VERSION, version);
|
||||
}
|
||||
|
||||
public static int getAppMigrationVersion(Context context) {
|
||||
return getIntegerPreference(context, APP_MIGRATION_VERSION, 1);
|
||||
}
|
||||
|
||||
public static void setFirstInstallVersion(Context context, int version) {
|
||||
setIntegerPrefrence(context, FIRST_INSTALL_VERSION, version);
|
||||
}
|
||||
|
||||
public static int getFirstInstallVersion(Context context) {
|
||||
return getIntegerPreference(context, FIRST_INSTALL_VERSION, -1);
|
||||
}
|
||||
|
||||
|
||||
public static void setBooleanPreference(Context context, String key, boolean value) {
|
||||
PreferenceManager.getDefaultSharedPreferences(context).edit().putBoolean(key, value).apply();
|
||||
}
|
||||
|
|
|
@ -380,6 +380,23 @@ public class FastJobStorageTest {
|
|||
assertEquals("1", jobs.get(0).getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getPendingJobsWithNoDependenciesInCreatedOrder_onlyMigrationJobWithAppropriateNextRunTime() {
|
||||
FullSpec migrationSpec1 = new FullSpec(new JobSpec("1", "f1", Job.Parameters.MIGRATION_QUEUE_KEY, 0, 999, 0, 0, 0, -1, -1, EMPTY_DATA, false),
|
||||
Collections.emptyList(),
|
||||
Collections.emptyList());
|
||||
FullSpec migrationSpec2 = new FullSpec(new JobSpec("2", "f2", Job.Parameters.MIGRATION_QUEUE_KEY, 5, 0, 0, 0, 0, -1, -1, EMPTY_DATA, false),
|
||||
Collections.emptyList(),
|
||||
Collections.emptyList());
|
||||
|
||||
FastJobStorage subject = new FastJobStorage(fixedDataDatabase(Arrays.asList(migrationSpec1, migrationSpec2)));
|
||||
subject.init();
|
||||
|
||||
List<JobSpec> jobs = subject.getPendingJobsWithNoDependenciesInCreatedOrder(10);
|
||||
|
||||
assertTrue(jobs.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deleteJobs_writesToDatabase() {
|
||||
JobDatabase database = noopDatabase();
|
||||
|
|
Loading…
Add table
Reference in a new issue