mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-02-24 03:35:58 +00:00
Fix SQL crash in backup restore by preventing job from running until restore complete.
This commit is contained in:
@@ -17,6 +17,7 @@ import org.thoughtcrime.securesms.backup.BackupPassphrase;
|
||||
import org.thoughtcrime.securesms.backup.FullBackupImporter;
|
||||
import org.thoughtcrime.securesms.crypto.AttachmentSecretProvider;
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase;
|
||||
import org.thoughtcrime.securesms.jobmanager.impl.DataRestoreConstraint;
|
||||
import org.thoughtcrime.securesms.notifications.NotificationChannels;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -38,6 +39,7 @@ final class NewDeviceServerTask implements ServerTask {
|
||||
|
||||
EventBus.getDefault().register(this);
|
||||
try {
|
||||
DataRestoreConstraint.setRestoringData(true);
|
||||
SQLiteDatabase database = SignalDatabase.getBackupDatabase();
|
||||
|
||||
String passphrase = "deadbeef";
|
||||
@@ -66,6 +68,7 @@ final class NewDeviceServerTask implements ServerTask {
|
||||
EventBus.getDefault().post(new Status(0, Status.State.FAILURE_UNKNOWN));
|
||||
} finally {
|
||||
EventBus.getDefault().unregister(this);
|
||||
DataRestoreConstraint.setRestoringData(false);
|
||||
}
|
||||
|
||||
long end = System.currentTimeMillis();
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
package org.thoughtcrime.securesms.jobmanager.impl
|
||||
|
||||
import android.app.job.JobInfo
|
||||
import org.thoughtcrime.securesms.jobmanager.Constraint
|
||||
|
||||
/**
|
||||
* Constraint that, when added, means that a job cannot be performed while a backup restore or device transfer
|
||||
* is occurring.
|
||||
*/
|
||||
object DataRestoreConstraint : Constraint {
|
||||
|
||||
const val KEY = "DataRestoreConstraint"
|
||||
|
||||
@JvmStatic
|
||||
var isRestoringData: Boolean = false
|
||||
set(value) {
|
||||
field = value
|
||||
DataRestoreConstraintObserver.onChange()
|
||||
}
|
||||
|
||||
override fun isMet(): Boolean {
|
||||
return !isRestoringData
|
||||
}
|
||||
|
||||
override fun getFactoryKey(): String = KEY
|
||||
|
||||
override fun applyToJobInfo(jobInfoBuilder: JobInfo.Builder) = Unit
|
||||
|
||||
class Factory : Constraint.Factory<DataRestoreConstraint> {
|
||||
override fun create(): DataRestoreConstraint {
|
||||
return DataRestoreConstraint
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package org.thoughtcrime.securesms.jobmanager.impl
|
||||
|
||||
import org.thoughtcrime.securesms.jobmanager.ConstraintObserver
|
||||
|
||||
/**
|
||||
* An observer for the [DataRestoreConstraint]. This class expects to be told when a change happens,
|
||||
* since the points at which it happens are triggered by application code.
|
||||
*/
|
||||
object DataRestoreConstraintObserver : ConstraintObserver {
|
||||
|
||||
private const val REASON = "DataRestoreConstraint"
|
||||
|
||||
private var notifier: ConstraintObserver.Notifier? = null
|
||||
|
||||
override fun register(notifier: ConstraintObserver.Notifier) {
|
||||
this.notifier = notifier
|
||||
}
|
||||
|
||||
/**
|
||||
* Let the observer know that the change number state has changed.
|
||||
*/
|
||||
fun onChange() {
|
||||
if (DataRestoreConstraint.isMet) {
|
||||
notifier?.onConstraintMet(REASON)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,8 +12,11 @@ import org.thoughtcrime.securesms.jobmanager.JobMigration;
|
||||
import org.thoughtcrime.securesms.jobmanager.impl.AutoDownloadEmojiConstraint;
|
||||
import org.thoughtcrime.securesms.jobmanager.impl.CellServiceConstraintObserver;
|
||||
import org.thoughtcrime.securesms.jobmanager.impl.ChangeNumberConstraint;
|
||||
import org.thoughtcrime.securesms.jobmanager.impl.ChangeNumberConstraintObserver;
|
||||
import org.thoughtcrime.securesms.jobmanager.impl.ChargingConstraint;
|
||||
import org.thoughtcrime.securesms.jobmanager.impl.ChargingConstraintObserver;
|
||||
import org.thoughtcrime.securesms.jobmanager.impl.DataRestoreConstraint;
|
||||
import org.thoughtcrime.securesms.jobmanager.impl.DataRestoreConstraintObserver;
|
||||
import org.thoughtcrime.securesms.jobmanager.impl.DecryptionsDrainedConstraint;
|
||||
import org.thoughtcrime.securesms.jobmanager.impl.DecryptionsDrainedConstraintObserver;
|
||||
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
|
||||
@@ -292,6 +295,7 @@ public final class JobManagerFactories {
|
||||
put(AutoDownloadEmojiConstraint.KEY, new AutoDownloadEmojiConstraint.Factory(application));
|
||||
put(ChangeNumberConstraint.KEY, new ChangeNumberConstraint.Factory());
|
||||
put(ChargingConstraint.KEY, new ChargingConstraint.Factory());
|
||||
put(DataRestoreConstraint.KEY, new DataRestoreConstraint.Factory());
|
||||
put(DecryptionsDrainedConstraint.KEY, new DecryptionsDrainedConstraint.Factory());
|
||||
put(NetworkConstraint.KEY, new NetworkConstraint.Factory(application));
|
||||
put(NetworkOrCellServiceConstraint.KEY, new NetworkOrCellServiceConstraint.Factory(application));
|
||||
@@ -307,7 +311,9 @@ public final class JobManagerFactories {
|
||||
new NetworkConstraintObserver(application),
|
||||
new SqlCipherMigrationConstraintObserver(),
|
||||
new DecryptionsDrainedConstraintObserver(),
|
||||
new NotInCallConstraintObserver());
|
||||
new NotInCallConstraintObserver(),
|
||||
ChangeNumberConstraintObserver.INSTANCE,
|
||||
DataRestoreConstraintObserver.INSTANCE);
|
||||
}
|
||||
|
||||
public static List<JobMigration> getJobMigrations(@NonNull Application application) {
|
||||
|
||||
@@ -4,6 +4,7 @@ import org.signal.core.util.logging.Log
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
|
||||
import org.thoughtcrime.securesms.jobmanager.Job
|
||||
import org.thoughtcrime.securesms.jobmanager.impl.DataRestoreConstraint
|
||||
import org.thoughtcrime.securesms.transport.RetryLaterException
|
||||
import java.lang.Exception
|
||||
import java.lang.IllegalStateException
|
||||
@@ -24,6 +25,7 @@ class RebuildMessageSearchIndexJob private constructor(params: Parameters) : Bas
|
||||
private constructor() : this(
|
||||
Parameters.Builder()
|
||||
.setQueue("RebuildMessageSearchIndex")
|
||||
.addConstraint(DataRestoreConstraint.KEY)
|
||||
.setMaxAttempts(3)
|
||||
.build()
|
||||
)
|
||||
|
||||
@@ -49,6 +49,8 @@ import org.thoughtcrime.securesms.backup.FullBackupImporter;
|
||||
import org.thoughtcrime.securesms.crypto.AttachmentSecretProvider;
|
||||
import org.thoughtcrime.securesms.database.NoExternalStorageException;
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase;
|
||||
import org.thoughtcrime.securesms.jobmanager.impl.DataRestoreConstraint;
|
||||
import org.thoughtcrime.securesms.jobmanager.impl.DataRestoreConstraintObserver;
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
||||
import org.thoughtcrime.securesms.notifications.NotificationChannels;
|
||||
import org.thoughtcrime.securesms.registration.viewmodel.RegistrationViewModel;
|
||||
@@ -282,6 +284,7 @@ public final class RestoreBackupFragment extends LoggingFragment {
|
||||
protected BackupImportResult doInBackground(Void... voids) {
|
||||
try {
|
||||
Log.i(TAG, "Starting backup restore.");
|
||||
DataRestoreConstraint.setRestoringData(true);
|
||||
|
||||
SQLiteDatabase database = SignalDatabase.getBackupDatabase();
|
||||
|
||||
@@ -310,6 +313,8 @@ public final class RestoreBackupFragment extends LoggingFragment {
|
||||
} catch (IOException e) {
|
||||
Log.w(TAG, e);
|
||||
return BackupImportResult.FAILURE_UNKNOWN;
|
||||
} finally {
|
||||
DataRestoreConstraint.setRestoringData(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user