more robustly re-schedule key sync

This commit is contained in:
Vincent Breitmoser
2018-07-19 11:32:12 +02:00
parent e21a46fc07
commit 71ad44ea7c
4 changed files with 32 additions and 14 deletions

View File

@@ -151,7 +151,7 @@ public final class Constants {
public static final String SYNC_CONTACTS = "syncContacts"; public static final String SYNC_CONTACTS = "syncContacts";
public static final String SYNC_KEYSERVER = "syncKeyserver"; public static final String SYNC_KEYSERVER = "syncKeyserver";
public static final String ENABLE_WIFI_SYNC_ONLY = "enableWifiSyncOnly"; public static final String ENABLE_WIFI_SYNC_ONLY = "enableWifiSyncOnly";
public static final String SYNC_IS_SCHEDULED = "syncIsScheduled"; public static final String SYNC_WORK_UUID = "syncWorkUuid";
// other settings // other settings
public static final String EXPERIMENTAL_ENABLE_LINKED_IDENTITIES = "experimentalEnableLinkedIdentities"; public static final String EXPERIMENTAL_ENABLE_LINKED_IDENTITIES = "experimentalEnableLinkedIdentities";
public static final String EXPERIMENTAL_ENABLE_KEYBASE = "experimentalEnableKeybase"; public static final String EXPERIMENTAL_ENABLE_KEYBASE = "experimentalEnableKeybase";

View File

@@ -104,7 +104,7 @@ public class KeychainApplication extends Application {
TlsCertificatePinning.addPinnedCertificate("api.keybase.io", getAssets(), "api.keybase.io.CA.cer"); TlsCertificatePinning.addPinnedCertificate("api.keybase.io", getAssets(), "api.keybase.io.CA.cer");
TlsCertificatePinning.addPinnedCertificate("keyserver.ubuntu.com", getAssets(), "DigiCertGlobalRootCA.cer"); TlsCertificatePinning.addPinnedCertificate("keyserver.ubuntu.com", getAssets(), "DigiCertGlobalRootCA.cer");
KeyserverSyncManager.updateKeyserverSyncScheduleAsync(this, Constants.DEBUG_KEYSERVER_SYNC); KeyserverSyncManager.updateKeyserverSyncScheduleAsync(this, false);
TemporaryFileProvider.scheduleCleanupImmediately(); TemporaryFileProvider.scheduleCleanupImmediately();

View File

@@ -18,19 +18,23 @@
package org.sufficientlysecure.keychain.keysync; package org.sufficientlysecure.keychain.keysync;
import java.util.UUID;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import android.content.Context; import android.content.Context;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Build.VERSION; import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES; import android.os.Build.VERSION_CODES;
import android.support.annotation.WorkerThread;
import androidx.work.Constraints.Builder; import androidx.work.Constraints.Builder;
import androidx.work.NetworkType; import androidx.work.NetworkType;
import androidx.work.OneTimeWorkRequest; import androidx.work.OneTimeWorkRequest;
import androidx.work.PeriodicWorkRequest; import androidx.work.PeriodicWorkRequest;
import androidx.work.State;
import androidx.work.SynchronousWorkManager; import androidx.work.SynchronousWorkManager;
import androidx.work.WorkManager; import androidx.work.WorkManager;
import androidx.work.WorkStatus;
import org.sufficientlysecure.keychain.util.Preferences; import org.sufficientlysecure.keychain.util.Preferences;
import timber.log.Timber; import timber.log.Timber;
@@ -42,11 +46,6 @@ public class KeyserverSyncManager {
private static final String PERIODIC_WORK_TAG = "keyserverSync"; private static final String PERIODIC_WORK_TAG = "keyserverSync";
public static void updateKeyserverSyncScheduleAsync(Context context, boolean forceReschedule) { public static void updateKeyserverSyncScheduleAsync(Context context, boolean forceReschedule) {
Preferences prefs = Preferences.getPreferences(context);
if (!forceReschedule && prefs.isKeyserverSyncScheduled() != prefs.isKeyserverSyncEnabled()) {
return;
}
new AsyncTask<Void,Void,Void>() { new AsyncTask<Void,Void,Void>() {
@Override @Override
protected Void doInBackground(Void... voids) { protected Void doInBackground(Void... voids) {
@@ -56,21 +55,37 @@ public class KeyserverSyncManager {
}.execute(); }.execute();
} }
@WorkerThread
private static void updateKeyserverSyncSchedule(Context context, boolean forceReschedule) { private static void updateKeyserverSyncSchedule(Context context, boolean forceReschedule) {
Preferences prefs = Preferences.getPreferences(context); Preferences prefs = Preferences.getPreferences(context);
// for some reason, the task is not actually scheduled sometimes unless we use the synchronous interface.
WorkManager workManager = WorkManager.getInstance(); WorkManager workManager = WorkManager.getInstance();
if (workManager == null) { if (workManager == null) {
Timber.e("WorkManager unavailable!"); Timber.e("WorkManager unavailable!");
return; return;
} }
SynchronousWorkManager synchronousWorkManager = workManager.synchronous(); SynchronousWorkManager synchronousWorkManager = workManager.synchronous();
UUID workUuid = prefs.getKeyserverSyncWorkUuid();
WorkStatus status = workUuid != null ? synchronousWorkManager.getStatusByIdSync(workUuid) : null;
boolean workIsScheduled = status != null && status.getState() != State.CANCELLED;
if (workIsScheduled == prefs.isKeyserverSyncEnabled()) {
if (!forceReschedule) {
Timber.d("Key sync already scheduled, no changes necessary");
return;
}
Timber.d("Key sync already scheduled, but forcing reschedule");
}
Timber.d("Cancelling sync tasks…");
synchronousWorkManager.cancelAllWorkByTagSync(PERIODIC_WORK_TAG); synchronousWorkManager.cancelAllWorkByTagSync(PERIODIC_WORK_TAG);
if (!prefs.isKeyserverSyncEnabled()) { if (!prefs.isKeyserverSyncEnabled()) {
Timber.d("Key sync disabled");
return; return;
} }
Timber.d("Scheduling periodic key sync");
Builder constraints = new Builder() Builder constraints = new Builder()
.setRequiredNetworkType(prefs.getWifiOnlySync() ? NetworkType.UNMETERED : NetworkType.CONNECTED) .setRequiredNetworkType(prefs.getWifiOnlySync() ? NetworkType.UNMETERED : NetworkType.CONNECTED)
.setRequiresBatteryNotLow(true); .setRequiresBatteryNotLow(true);
@@ -85,7 +100,8 @@ public class KeyserverSyncManager {
.build(); .build();
synchronousWorkManager.enqueueSync(workRequest); synchronousWorkManager.enqueueSync(workRequest);
prefs.setKeyserverSyncScheduled(true); Timber.d("Work id: %s", workRequest.getId());
prefs.setKeyserverSyncScheduled(workRequest.getId());
} }
public static void debugRunSyncNow() { public static void debugRunSyncNow() {

View File

@@ -21,6 +21,7 @@ package org.sufficientlysecure.keychain.util;
import java.net.Proxy; import java.net.Proxy;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.ListIterator; import java.util.ListIterator;
import java.util.UUID;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.content.Context; import android.content.Context;
@@ -33,7 +34,6 @@ import android.support.annotation.Nullable;
import com.google.auto.value.AutoValue; import com.google.auto.value.AutoValue;
import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.Constants.Pref; import org.sufficientlysecure.keychain.Constants.Pref;
import org.sufficientlysecure.keychain.analytics.AnalyticsManager;
import org.sufficientlysecure.keychain.keyimport.HkpKeyserverAddress; import org.sufficientlysecure.keychain.keyimport.HkpKeyserverAddress;
import timber.log.Timber; import timber.log.Timber;
@@ -350,12 +350,14 @@ public class Preferences {
return mSharedPreferences.getBoolean(Pref.SYNC_KEYSERVER, true); return mSharedPreferences.getBoolean(Pref.SYNC_KEYSERVER, true);
} }
public boolean isKeyserverSyncScheduled() { public UUID getKeyserverSyncWorkUuid() {
return mSharedPreferences.getBoolean(Pref.SYNC_IS_SCHEDULED, false); String uuidString = mSharedPreferences.getString(Pref.SYNC_WORK_UUID, null);
return uuidString != null ? UUID.fromString(uuidString) : null;
} }
public void setKeyserverSyncScheduled(boolean isScheduled) { public void setKeyserverSyncScheduled(UUID uuid) {
mSharedPreferences.edit().putBoolean(Pref.SYNC_IS_SCHEDULED, isScheduled).apply(); String value = uuid != null ? uuid.toString() : null;
mSharedPreferences.edit().putString(Pref.SYNC_WORK_UUID, value).apply();
} }
public boolean isAnalyticsAskedPolitely() { public boolean isAnalyticsAskedPolitely() {