Use CancellationSignal for cancellation in UI code
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ import android.os.SystemClock;
|
||||
import android.support.annotation.UiThread;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.support.v4.os.CancellationSignal;
|
||||
|
||||
import org.sufficientlysecure.keychain.operations.results.InputPendingResult;
|
||||
import org.sufficientlysecure.keychain.operations.results.OperationResult;
|
||||
@@ -42,7 +42,6 @@ import org.sufficientlysecure.keychain.ui.OrbotRequiredDialogActivity;
|
||||
import org.sufficientlysecure.keychain.ui.PassphraseDialogActivity;
|
||||
import org.sufficientlysecure.keychain.ui.RetryUploadDialogActivity;
|
||||
import org.sufficientlysecure.keychain.ui.SecurityTokenOperationActivity;
|
||||
import org.sufficientlysecure.keychain.ui.dialog.ProgressDialogFragment;
|
||||
import timber.log.Timber;
|
||||
|
||||
|
||||
@@ -264,28 +263,6 @@ public class CryptoOperationHelper<T extends Parcelable, S extends OperationResu
|
||||
return true;
|
||||
}
|
||||
|
||||
protected void dismissProgress() {
|
||||
FragmentManager fragmentManager =
|
||||
mUseFragment ? mFragment.getFragmentManager() :
|
||||
mActivity.getSupportFragmentManager();
|
||||
|
||||
if (fragmentManager == null) { // the fragment holding us has died
|
||||
// fragmentManager was null when used with DialogFragments. (they close on click?)
|
||||
return;
|
||||
}
|
||||
|
||||
ProgressDialogFragment progressDialogFragment =
|
||||
(ProgressDialogFragment) fragmentManager.findFragmentByTag(
|
||||
ProgressDialogManager.TAG_PROGRESS_DIALOG);
|
||||
|
||||
if (progressDialogFragment == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
progressDialogFragment.dismissAllowingStateLoss();
|
||||
|
||||
}
|
||||
|
||||
public void cryptoOperation(final CryptoInputParcel cryptoInput) {
|
||||
|
||||
FragmentActivity activity = mUseFragment ? mFragment.getActivity() : mActivity;
|
||||
@@ -298,14 +275,12 @@ public class CryptoOperationHelper<T extends Parcelable, S extends OperationResu
|
||||
ProgressDialogManager progressDialogManager;
|
||||
if (mProgressMessageResource != null) {
|
||||
progressDialogManager = new ProgressDialogManager(activity);
|
||||
progressDialogManager.showProgressDialog(
|
||||
activity.getString(mProgressMessageResource), ProgressDialog.STYLE_HORIZONTAL, mCancellable);
|
||||
} else {
|
||||
progressDialogManager = null;
|
||||
}
|
||||
|
||||
KeychainServiceTask keychainServiceTask = KeychainServiceTask.create(activity);
|
||||
keychainServiceTask.startOperationInBackground(operationInput, cryptoInput, new OperationCallback() {
|
||||
OperationCallback operationCallback = new OperationCallback() {
|
||||
@Override
|
||||
public void operationFinished(OperationResult result) {
|
||||
if (progressDialogManager != null) {
|
||||
@@ -331,7 +306,15 @@ public class CryptoOperationHelper<T extends Parcelable, S extends OperationResu
|
||||
progressDialogManager.setPreventCancel();
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
CancellationSignal cancellationSignal =
|
||||
keychainServiceTask.startOperationInBackground(operationInput, cryptoInput, operationCallback);
|
||||
|
||||
if (progressDialogManager != null) {
|
||||
progressDialogManager.showProgressDialog(activity.getString(mProgressMessageResource),
|
||||
ProgressDialog.STYLE_HORIZONTAL, mCancellable ? cancellationSignal : null);
|
||||
}
|
||||
}
|
||||
|
||||
public void cryptoOperation() {
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.ui.dialog;
|
||||
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Dialog;
|
||||
import android.app.ProgressDialog;
|
||||
@@ -26,6 +27,7 @@ import android.graphics.Color;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
import android.support.v4.os.CancellationSignal;
|
||||
import android.view.ContextThemeWrapper;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
@@ -33,7 +35,6 @@ import android.view.View.OnClickListener;
|
||||
import android.widget.Button;
|
||||
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.service.KeychainServiceTask;
|
||||
import org.sufficientlysecure.keychain.ui.util.ThemeChanger;
|
||||
|
||||
/**
|
||||
@@ -43,15 +44,18 @@ public class ProgressDialogFragment extends DialogFragment {
|
||||
private static final String ARG_MESSAGE = "message";
|
||||
private static final String ARG_STYLE = "style";
|
||||
private static final String ARG_CANCELABLE = "cancelable";
|
||||
private static final String ARG_SERVICE_TYPE = "service_class";
|
||||
|
||||
boolean mCanCancel = false, mPreventCancel = false, mIsCancelled = false;
|
||||
private CancellationSignal cancellationSignal;
|
||||
|
||||
/**
|
||||
* creates a new instance of this fragment
|
||||
* @param message the message to be displayed initially above the progress bar
|
||||
* @param style the progress bar style, as defined in ProgressDialog (horizontal or spinner)
|
||||
* @param cancelable should we let the user cancel this operation
|
||||
*
|
||||
* @param message
|
||||
* the message to be displayed initially above the progress bar
|
||||
* @param style
|
||||
* the progress bar style, as defined in ProgressDialog (horizontal or spinner)
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static ProgressDialogFragment newInstance(String message, int style, boolean cancelable) {
|
||||
@@ -156,6 +160,10 @@ public class ProgressDialogFragment extends DialogFragment {
|
||||
negative.setEnabled(false);
|
||||
}
|
||||
|
||||
public void setCancellationSignal(CancellationSignal cancellationSignal) {
|
||||
this.cancellationSignal = cancellationSignal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
@@ -166,7 +174,7 @@ public class ProgressDialogFragment extends DialogFragment {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
// nvm if we are already cancelled, or weren't able to begin with
|
||||
if (mIsCancelled || ! mCanCancel) {
|
||||
if (mIsCancelled || !mCanCancel || cancellationSignal == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -175,8 +183,7 @@ public class ProgressDialogFragment extends DialogFragment {
|
||||
negative.setClickable(false);
|
||||
negative.setTextColor(Color.GRAY);
|
||||
|
||||
// TODO
|
||||
// KeychainServiceTask.cancelRunningTask();
|
||||
cancellationSignal.cancel();
|
||||
|
||||
// Set the progress bar accordingly
|
||||
ProgressDialog dialog = (ProgressDialog) getDialog();
|
||||
@@ -186,11 +193,8 @@ public class ProgressDialogFragment extends DialogFragment {
|
||||
|
||||
dialog.setIndeterminate(true);
|
||||
dialog.setMessage(getString(R.string.progress_cancelling));
|
||||
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user