Use CancellationSignal for cancellation in UI code

This commit is contained in:
Vincent Breitmoser
2018-07-17 14:13:03 +02:00
parent 9e079329d5
commit 1fcc1889ec
4 changed files with 118 additions and 122 deletions

View File

@@ -24,6 +24,7 @@ import android.annotation.SuppressLint;
import android.content.Context;
import android.os.AsyncTask;
import android.os.Parcelable;
import android.support.v4.os.CancellationSignal;
import org.sufficientlysecure.keychain.daos.KeyWritableRepository;
import org.sufficientlysecure.keychain.operations.BackupOperation;
@@ -64,90 +65,101 @@ public class KeychainServiceTask {
private final KeyWritableRepository keyRepository;
@SuppressLint("StaticFieldLeak")
public void startOperationInBackground(
public CancellationSignal startOperationInBackground(
Parcelable inputParcel, CryptoInputParcel cryptoInput, OperationCallback operationCallback) {
new AsyncTask<Void,ProgressUpdate,OperationResult>() {
private AtomicBoolean operationCancelledBoolean = new AtomicBoolean(false);
AtomicBoolean operationCancelledBoolean = new AtomicBoolean(false);
@Override
protected OperationResult doInBackground(Void... voids) {
BaseOperation op;
AsyncTask<Void, ProgressUpdate, OperationResult> asyncTask =
new AsyncTask<Void, ProgressUpdate, OperationResult>() {
@Override
protected OperationResult doInBackground(Void... voids) {
BaseOperation op;
if (inputParcel instanceof SignEncryptParcel) {
op = new SignEncryptOperation(context, keyRepository, asyncProgressable, operationCancelledBoolean);
} else if (inputParcel instanceof PgpDecryptVerifyInputParcel) {
op = new PgpDecryptVerifyOperation(context, keyRepository, asyncProgressable);
} else if (inputParcel instanceof SaveKeyringParcel) {
op = new EditKeyOperation(context, keyRepository, asyncProgressable, operationCancelledBoolean);
} else if (inputParcel instanceof ChangeUnlockParcel) {
op = new ChangeUnlockOperation(context, keyRepository, asyncProgressable);
} else if (inputParcel instanceof RevokeKeyringParcel) {
op = new RevokeOperation(context, keyRepository, asyncProgressable);
} else if (inputParcel instanceof CertifyActionsParcel) {
op = new CertifyOperation(context, keyRepository, asyncProgressable, operationCancelledBoolean);
} else if (inputParcel instanceof DeleteKeyringParcel) {
op = new DeleteOperation(context, keyRepository, asyncProgressable);
} else if (inputParcel instanceof PromoteKeyringParcel) {
op = new PromoteKeyOperation(context, keyRepository, asyncProgressable, operationCancelledBoolean);
} else if (inputParcel instanceof ImportKeyringParcel) {
op = new ImportOperation(context, keyRepository, asyncProgressable, operationCancelledBoolean);
} else if (inputParcel instanceof BackupKeyringParcel) {
op = new BackupOperation(context, keyRepository, asyncProgressable, operationCancelledBoolean);
} else if (inputParcel instanceof UploadKeyringParcel) {
op = new UploadOperation(context, keyRepository, asyncProgressable, operationCancelledBoolean);
} else if (inputParcel instanceof KeybaseVerificationParcel) {
op = new KeybaseVerificationOperation(context, keyRepository, asyncProgressable);
} else if (inputParcel instanceof InputDataParcel) {
op = new InputDataOperation(context, keyRepository, asyncProgressable);
} else if (inputParcel instanceof BenchmarkInputParcel) {
op = new BenchmarkOperation(context, keyRepository, asyncProgressable);
} else if (inputParcel instanceof KeySyncParcel) {
op = new KeySyncOperation(context, keyRepository, asyncProgressable, operationCancelledBoolean);
} else {
throw new AssertionError("Unrecognized input parcel in KeychainService!");
}
if (inputParcel instanceof SignEncryptParcel) {
op = new SignEncryptOperation(context, keyRepository, asyncProgressable,
operationCancelledBoolean);
} else if (inputParcel instanceof PgpDecryptVerifyInputParcel) {
op = new PgpDecryptVerifyOperation(context, keyRepository, asyncProgressable);
} else if (inputParcel instanceof SaveKeyringParcel) {
op = new EditKeyOperation(context, keyRepository, asyncProgressable,
operationCancelledBoolean);
} else if (inputParcel instanceof ChangeUnlockParcel) {
op = new ChangeUnlockOperation(context, keyRepository, asyncProgressable);
} else if (inputParcel instanceof RevokeKeyringParcel) {
op = new RevokeOperation(context, keyRepository, asyncProgressable);
} else if (inputParcel instanceof CertifyActionsParcel) {
op = new CertifyOperation(context, keyRepository, asyncProgressable,
operationCancelledBoolean);
} else if (inputParcel instanceof DeleteKeyringParcel) {
op = new DeleteOperation(context, keyRepository, asyncProgressable);
} else if (inputParcel instanceof PromoteKeyringParcel) {
op = new PromoteKeyOperation(context, keyRepository, asyncProgressable,
operationCancelledBoolean);
} else if (inputParcel instanceof ImportKeyringParcel) {
op = new ImportOperation(context, keyRepository, asyncProgressable,
operationCancelledBoolean);
} else if (inputParcel instanceof BackupKeyringParcel) {
op = new BackupOperation(context, keyRepository, asyncProgressable,
operationCancelledBoolean);
} else if (inputParcel instanceof UploadKeyringParcel) {
op = new UploadOperation(context, keyRepository, asyncProgressable,
operationCancelledBoolean);
} else if (inputParcel instanceof KeybaseVerificationParcel) {
op = new KeybaseVerificationOperation(context, keyRepository, asyncProgressable);
} else if (inputParcel instanceof InputDataParcel) {
op = new InputDataOperation(context, keyRepository, asyncProgressable);
} else if (inputParcel instanceof BenchmarkInputParcel) {
op = new BenchmarkOperation(context, keyRepository, asyncProgressable);
} else if (inputParcel instanceof KeySyncParcel) {
op = new KeySyncOperation(context, keyRepository, asyncProgressable,
operationCancelledBoolean);
} else {
throw new AssertionError("Unrecognized input parcel in KeychainService!");
}
if (isCancelled()) {
return null;
}
if (isCancelled()) {
return null;
}
// noinspection unchecked, we make sure it's the correct op above
return op.execute(inputParcel, cryptoInput);
}
// noinspection unchecked, we make sure it's the correct op above
return op.execute(inputParcel, cryptoInput);
}
Progressable asyncProgressable = new Progressable() {
@Override
public void setPreventCancel() {
publishProgress((ProgressUpdate) null);
}
Progressable asyncProgressable = new Progressable() {
@Override
public void setPreventCancel() {
publishProgress((ProgressUpdate) null);
}
@Override
public void setProgress(Integer resourceId, int current, int total) {
publishProgress(new ProgressUpdate(resourceId, current, total));
}
};
@Override
public void setProgress(Integer resourceId, int current, int total) {
publishProgress(new ProgressUpdate(resourceId, current, total));
}
};
@Override
protected void onProgressUpdate(ProgressUpdate... values) {
ProgressUpdate progressUpdate = values[0];
if (progressUpdate == null) {
operationCallback.setPreventCancel();
} else {
operationCallback.setProgress(progressUpdate.resourceId, progressUpdate.current, progressUpdate.total);
}
}
@Override
protected void onProgressUpdate(ProgressUpdate... values) {
ProgressUpdate progressUpdate = values[0];
if (progressUpdate == null) {
operationCallback.setPreventCancel();
} else {
operationCallback.setProgress(progressUpdate.resourceId, progressUpdate.current,
progressUpdate.total);
}
}
@Override
protected void onCancelled() {
super.onCancelled();
operationCancelledBoolean.set(true);
}
@Override
protected void onPostExecute(OperationResult result) {
operationCallback.operationFinished(result);
}
};
asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
@Override
protected void onPostExecute(OperationResult result) {
operationCallback.operationFinished(result);
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
CancellationSignal cancellationSignal = new CancellationSignal();
cancellationSignal.setOnCancelListener(() -> {
operationCancelledBoolean.set(true);
});
return cancellationSignal;
}
public interface OperationCallback {

View File

@@ -22,6 +22,7 @@ import android.app.ProgressDialog;
import android.os.Handler;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.os.CancellationSignal;
import org.sufficientlysecure.keychain.ui.dialog.ProgressDialogFragment;
@@ -36,16 +37,16 @@ public class ProgressDialogManager {
}
public void showProgressDialog() {
showProgressDialog("", ProgressDialog.STYLE_SPINNER, false);
showProgressDialog("", ProgressDialog.STYLE_SPINNER, null);
}
public void showProgressDialog(
String progressDialogMessage, int progressDialogStyle, boolean cancelable) {
String progressDialogMessage, int progressDialogStyle, CancellationSignal cancellationSignal) {
final ProgressDialogFragment frag = ProgressDialogFragment.newInstance(
progressDialogMessage,
progressDialogStyle,
cancelable);
progressDialogMessage, progressDialogStyle, cancellationSignal != null);
frag.setCancellationSignal(cancellationSignal);
// TODO: This is a hack!, see
// http://stackoverflow.com/questions/10114324/show-dialogfragment-from-onactivityresult
@@ -79,9 +80,7 @@ public class ProgressDialogManager {
progressDialogFragment.dismissAllowingStateLoss();
}
public void onSetProgress(Integer resourceInt, int progress, int max) {
ProgressDialogFragment progressDialogFragment =
(ProgressDialogFragment) activity.getSupportFragmentManager()
.findFragmentByTag(TAG_PROGRESS_DIALOG);
@@ -95,7 +94,5 @@ public class ProgressDialogManager {
} else {
progressDialogFragment.setProgress(progress, max);
}
}
}