Merge "Force cancel pending RemotePrintDocument commands when the PrintActivity exits" into nyc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
594e131160
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.android.printspooler.model;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
@@ -57,6 +58,8 @@ public final class RemotePrintDocument {
|
||||
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
private static final long FORCE_CANCEL_TIMEOUT = 1000; // ms
|
||||
|
||||
private static final int STATE_INITIAL = 0;
|
||||
private static final int STATE_STARTED = 1;
|
||||
private static final int STATE_UPDATING = 2;
|
||||
@@ -212,7 +215,7 @@ public final class RemotePrintDocument {
|
||||
// cancellation and start over.
|
||||
if (mCurrentCommand != null && (mCurrentCommand.isRunning()
|
||||
|| mCurrentCommand.isPending())) {
|
||||
mCurrentCommand.cancel();
|
||||
mCurrentCommand.cancel(false);
|
||||
}
|
||||
|
||||
// Schedule a layout command.
|
||||
@@ -233,7 +236,7 @@ public final class RemotePrintDocument {
|
||||
// Cancel the current write as a new one is to be scheduled.
|
||||
if (mCurrentCommand instanceof WriteCommand
|
||||
&& (mCurrentCommand.isPending() || mCurrentCommand.isRunning())) {
|
||||
mCurrentCommand.cancel();
|
||||
mCurrentCommand.cancel(false);
|
||||
}
|
||||
|
||||
// Schedule a write command.
|
||||
@@ -277,9 +280,9 @@ public final class RemotePrintDocument {
|
||||
}
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
public void cancel(boolean force) {
|
||||
if (DEBUG) {
|
||||
Log.i(LOG_TAG, "[CALLED] cancel()");
|
||||
Log.i(LOG_TAG, "[CALLED] cancel(" + force + ")");
|
||||
}
|
||||
|
||||
mNextCommand = null;
|
||||
@@ -290,7 +293,7 @@ public final class RemotePrintDocument {
|
||||
|
||||
mState = STATE_CANCELING;
|
||||
|
||||
mCurrentCommand.cancel();
|
||||
mCurrentCommand.cancel(force);
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
@@ -441,8 +444,9 @@ public final class RemotePrintDocument {
|
||||
if (mCurrentCommand != null) {
|
||||
if (mCurrentCommand.isPending()) {
|
||||
mCurrentCommand.run();
|
||||
|
||||
mState = STATE_UPDATING;
|
||||
}
|
||||
mState = STATE_UPDATING;
|
||||
} else {
|
||||
mState = STATE_UPDATED;
|
||||
}
|
||||
@@ -535,14 +539,17 @@ public final class RemotePrintDocument {
|
||||
|
||||
protected final CommandDoneCallback mDoneCallback;
|
||||
|
||||
private final Handler mHandler;
|
||||
|
||||
protected ICancellationSignal mCancellation;
|
||||
|
||||
private CharSequence mError;
|
||||
|
||||
private int mState = STATE_PENDING;
|
||||
|
||||
public AsyncCommand(IPrintDocumentAdapter adapter, RemotePrintDocumentInfo document,
|
||||
public AsyncCommand(Looper looper, IPrintDocumentAdapter adapter, RemotePrintDocumentInfo document,
|
||||
CommandDoneCallback doneCallback) {
|
||||
mHandler = new AsyncCommandHandler(looper);
|
||||
mAdapter = adapter;
|
||||
mDocument = document;
|
||||
mDoneCallback = doneCallback;
|
||||
@@ -556,7 +563,29 @@ public final class RemotePrintDocument {
|
||||
return mState == STATE_CANCELED;
|
||||
}
|
||||
|
||||
public final void cancel() {
|
||||
/**
|
||||
* If a force cancel is pending, remove it. This is usually called when a command returns
|
||||
* and thereby does not need to be canceled anymore.
|
||||
*/
|
||||
protected void removeForceCancel() {
|
||||
if (DEBUG) {
|
||||
if (mHandler.hasMessages(AsyncCommandHandler.MSG_FORCE_CANCEL)) {
|
||||
Log.i(LOG_TAG, "[FORCE CANCEL] Removed");
|
||||
}
|
||||
}
|
||||
|
||||
mHandler.removeMessages(AsyncCommandHandler.MSG_FORCE_CANCEL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel the current command.
|
||||
*
|
||||
* @param force If set, does not wait for the {@link PrintDocumentAdapter} to cancel. This
|
||||
* should only be used if this is the last command send to the as otherwise the
|
||||
* {@link PrintDocumentAdapter adapter} might get commands while it is still
|
||||
* running the old one.
|
||||
*/
|
||||
public final void cancel(boolean force) {
|
||||
if (isRunning()) {
|
||||
canceling();
|
||||
if (mCancellation != null) {
|
||||
@@ -566,14 +595,25 @@ public final class RemotePrintDocument {
|
||||
Log.w(LOG_TAG, "Error while canceling", re);
|
||||
}
|
||||
}
|
||||
} else if (isCanceling()) {
|
||||
// Nothing to do
|
||||
} else {
|
||||
canceled();
|
||||
|
||||
// Done.
|
||||
mDoneCallback.onDone();
|
||||
}
|
||||
|
||||
if (isCanceling()) {
|
||||
if (force) {
|
||||
if (DEBUG) {
|
||||
Log.i(LOG_TAG, "[FORCE CANCEL] queued");
|
||||
}
|
||||
mHandler.sendMessageDelayed(
|
||||
mHandler.obtainMessage(AsyncCommandHandler.MSG_FORCE_CANCEL),
|
||||
FORCE_CANCEL_TIMEOUT);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
canceled();
|
||||
|
||||
// Done.
|
||||
mDoneCallback.onDone();
|
||||
}
|
||||
|
||||
protected final void canceling() {
|
||||
@@ -617,7 +657,7 @@ public final class RemotePrintDocument {
|
||||
}
|
||||
|
||||
protected final void failed(CharSequence error) {
|
||||
if (mState != STATE_RUNNING) {
|
||||
if (mState != STATE_RUNNING && mState != STATE_CANCELING) {
|
||||
throw new IllegalStateException("Not running.");
|
||||
}
|
||||
mState = STATE_FAILED;
|
||||
@@ -632,6 +672,37 @@ public final class RemotePrintDocument {
|
||||
public CharSequence getError() {
|
||||
return mError;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handler for the async command.
|
||||
*/
|
||||
private class AsyncCommandHandler extends Handler {
|
||||
/** Message indicated the desire for to force cancel a command */
|
||||
final static int MSG_FORCE_CANCEL = 0;
|
||||
|
||||
AsyncCommandHandler(@NonNull Looper looper) {
|
||||
super(looper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
switch (msg.what) {
|
||||
case MSG_FORCE_CANCEL:
|
||||
if (isCanceling()) {
|
||||
if (DEBUG) {
|
||||
Log.i(LOG_TAG, "[FORCE CANCEL] executed");
|
||||
}
|
||||
failed("Command did not respond to cancellation in "
|
||||
+ FORCE_CANCEL_TIMEOUT + " ms");
|
||||
|
||||
mDoneCallback.onDone();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// not reached;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static final class LayoutCommand extends AsyncCommand {
|
||||
@@ -646,7 +717,7 @@ public final class RemotePrintDocument {
|
||||
public LayoutCommand(Looper looper, IPrintDocumentAdapter adapter,
|
||||
RemotePrintDocumentInfo document, PrintAttributes oldAttributes,
|
||||
PrintAttributes newAttributes, boolean preview, CommandDoneCallback callback) {
|
||||
super(adapter, document, callback);
|
||||
super(looper, adapter, document, callback);
|
||||
mHandler = new LayoutHandler(looper);
|
||||
mRemoteResultCallback = new LayoutResultCallback(mHandler);
|
||||
mOldAttributes.copyFrom(oldAttributes);
|
||||
@@ -795,6 +866,21 @@ public final class RemotePrintDocument {
|
||||
|
||||
@Override
|
||||
public void handleMessage(Message message) {
|
||||
// The command might have been force canceled, see
|
||||
// AsyncCommand.AsyncCommandHandler#handleMessage
|
||||
if (isFailed()) {
|
||||
if (DEBUG) {
|
||||
Log.i(LOG_TAG, "[CALLBACK] on canceled layout command");
|
||||
}
|
||||
|
||||
return;
|
||||
} else {
|
||||
if (message.what != MSG_ON_LAYOUT_STARTED) {
|
||||
// No need to force cancel anymore if layout finished
|
||||
removeForceCancel();
|
||||
}
|
||||
}
|
||||
|
||||
switch (message.what) {
|
||||
case MSG_ON_LAYOUT_STARTED: {
|
||||
ICancellationSignal cancellation = (ICancellationSignal) message.obj;
|
||||
@@ -882,7 +968,7 @@ public final class RemotePrintDocument {
|
||||
public WriteCommand(Context context, Looper looper, IPrintDocumentAdapter adapter,
|
||||
RemotePrintDocumentInfo document, int pageCount, PageRange[] pages,
|
||||
MutexFileProvider fileProvider, CommandDoneCallback callback) {
|
||||
super(adapter, document, callback);
|
||||
super(looper, adapter, document, callback);
|
||||
mContext = context;
|
||||
mHandler = new WriteHandler(looper);
|
||||
mRemoteResultCallback = new WriteResultCallback(mHandler);
|
||||
@@ -1052,6 +1138,21 @@ public final class RemotePrintDocument {
|
||||
|
||||
@Override
|
||||
public void handleMessage(Message message) {
|
||||
// The command might have been force canceled, see
|
||||
// AsyncCommand.AsyncCommandHandler#handleMessage
|
||||
if (isFailed()) {
|
||||
if (DEBUG) {
|
||||
Log.i(LOG_TAG, "[CALLBACK] on canceled write command");
|
||||
}
|
||||
|
||||
return;
|
||||
} else {
|
||||
if (message.what != MSG_ON_WRITE_STARTED) {
|
||||
// No need to force cancel anymore if write finished
|
||||
removeForceCancel();
|
||||
}
|
||||
}
|
||||
|
||||
switch (message.what) {
|
||||
case MSG_ON_WRITE_STARTED: {
|
||||
ICancellationSignal cancellation = (ICancellationSignal) message.obj;
|
||||
|
||||
@@ -320,8 +320,8 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
|
||||
if (isFinishing() || (isFinalState(mState) && !mPrintedDocument.isUpdating())) {
|
||||
return;
|
||||
}
|
||||
mPrintedDocument.cancel();
|
||||
setState(STATE_PRINT_CANCELED);
|
||||
mPrintedDocument.cancel(true);
|
||||
doFinish();
|
||||
}
|
||||
}, PrintActivity.this);
|
||||
@@ -1013,7 +1013,7 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
|
||||
}
|
||||
|
||||
private void requestCreatePdfFileOrFinish() {
|
||||
mPrintedDocument.cancel();
|
||||
mPrintedDocument.cancel(false);
|
||||
|
||||
if (mCurrentPrinter == mDestinationSpinnerAdapter.getPdfPrinter()) {
|
||||
startCreateDocumentActivity();
|
||||
@@ -1130,7 +1130,7 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
|
||||
private void cancelPrint() {
|
||||
setState(STATE_PRINT_CANCELED);
|
||||
updateOptionsUi();
|
||||
mPrintedDocument.cancel();
|
||||
mPrintedDocument.cancel(true);
|
||||
doFinish();
|
||||
}
|
||||
|
||||
@@ -1889,7 +1889,7 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
|
||||
public void onPrinterUnavailable(PrinterInfo printer) {
|
||||
if (mCurrentPrinter.getId().equals(printer.getId())) {
|
||||
setState(STATE_PRINTER_UNAVAILABLE);
|
||||
mPrintedDocument.cancel();
|
||||
mPrintedDocument.cancel(false);
|
||||
ensureErrorUiShown(getString(R.string.print_error_printer_unavailable),
|
||||
PrintErrorFragment.ACTION_NONE);
|
||||
updateOptionsUi();
|
||||
|
||||
Reference in New Issue
Block a user