Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 594e1311 authored by Philip P. Moltmann's avatar Philip P. Moltmann Committed by Android (Google) Code Review
Browse files

Merge "Force cancel pending RemotePrintDocument commands when the PrintActivity exits" into nyc-dev

parents a486f456 645a3e1c
Loading
Loading
Loading
Loading
+118 −17
Original line number Diff line number Diff line
@@ -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;
            }
        } 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,15 +595,26 @@ public final class RemotePrintDocument {
                        Log.w(LOG_TAG, "Error while canceling", re);
                    }
                }
            } else if (isCanceling()) {
                // Nothing to do
            } else {
            }

            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() {
            if (mState != STATE_PENDING && mState != STATE_RUNNING) {
@@ -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;
+4 −4
Original line number Diff line number Diff line
@@ -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();