am b02b14b2: am ef4a6f86: Merge "Do not do a layout and write while a cancellation is in progress." into klp-dev
* commit 'b02b14b21e46c531ae726094413f036ae36c56f9': Do not do a layout and write while a cancellation is in progress.
This commit is contained in:
@@ -57,6 +57,8 @@ public final class PrintManager {
|
|||||||
|
|
||||||
private static final String LOG_TAG = "PrintManager";
|
private static final String LOG_TAG = "PrintManager";
|
||||||
|
|
||||||
|
private static final boolean DEBUG = false;
|
||||||
|
|
||||||
/** @hide */
|
/** @hide */
|
||||||
public static final int APP_ID_ANY = -2;
|
public static final int APP_ID_ANY = -2;
|
||||||
|
|
||||||
@@ -350,6 +352,16 @@ public final class PrintManager {
|
|||||||
|
|
||||||
private Handler mHandler; // Strong reference OK - cleared in finish()
|
private Handler mHandler; // Strong reference OK - cleared in finish()
|
||||||
|
|
||||||
|
private LayoutSpec mLastLayoutSpec;
|
||||||
|
|
||||||
|
private WriteSpec mLastWriteSpec;
|
||||||
|
|
||||||
|
private boolean mStartReqeusted;
|
||||||
|
private boolean mStarted;
|
||||||
|
|
||||||
|
private boolean mFinishRequested;
|
||||||
|
private boolean mFinished;
|
||||||
|
|
||||||
public PrintDocumentAdapterDelegate(PrintDocumentAdapter documentAdapter, Looper looper) {
|
public PrintDocumentAdapterDelegate(PrintDocumentAdapter documentAdapter, Looper looper) {
|
||||||
mDocumentAdapter = documentAdapter;
|
mDocumentAdapter = documentAdapter;
|
||||||
mHandler = new MyHandler(looper);
|
mHandler = new MyHandler(looper);
|
||||||
@@ -357,47 +369,102 @@ public final class PrintManager {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void start() {
|
public void start() {
|
||||||
mHandler.sendEmptyMessage(MyHandler.MSG_START);
|
synchronized (mLock) {
|
||||||
|
// Started or finished - nothing to do.
|
||||||
|
if (mStartReqeusted || mFinishRequested) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mStartReqeusted = true;
|
||||||
|
|
||||||
|
doPendingWorkLocked();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void layout(PrintAttributes oldAttributes, PrintAttributes newAttributes,
|
public void layout(PrintAttributes oldAttributes, PrintAttributes newAttributes,
|
||||||
ILayoutResultCallback callback, Bundle metadata, int sequence) {
|
ILayoutResultCallback callback, Bundle metadata, int sequence) {
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
if (mLayoutOrWriteCancellation != null) {
|
// Start not called or finish called - nothing to do.
|
||||||
mLayoutOrWriteCancellation.cancel();
|
if (!mStartReqeusted || mFinishRequested) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Layout cancels write and overrides layout.
|
||||||
|
if (mLastWriteSpec != null) {
|
||||||
|
IoUtils.closeQuietly(mLastWriteSpec.fd);
|
||||||
|
mLastWriteSpec = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
mLastLayoutSpec = new LayoutSpec();
|
||||||
|
mLastLayoutSpec.callback = callback;
|
||||||
|
mLastLayoutSpec.oldAttributes = oldAttributes;
|
||||||
|
mLastLayoutSpec.newAttributes = newAttributes;
|
||||||
|
mLastLayoutSpec.metadata = metadata;
|
||||||
|
mLastLayoutSpec.sequence = sequence;
|
||||||
|
|
||||||
|
// Cancel the previous cancellable operation.When the
|
||||||
|
// cancellation completes we will do the pending work.
|
||||||
|
if (cancelPreviousCancellableOperationLocked()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
doPendingWorkLocked();
|
||||||
}
|
}
|
||||||
SomeArgs args = SomeArgs.obtain();
|
|
||||||
args.arg1 = oldAttributes;
|
|
||||||
args.arg2 = newAttributes;
|
|
||||||
args.arg3 = callback;
|
|
||||||
args.arg4 = metadata;
|
|
||||||
args.argi1 = sequence;
|
|
||||||
mHandler.removeMessages(MyHandler.MSG_LAYOUT);
|
|
||||||
mHandler.obtainMessage(MyHandler.MSG_LAYOUT, args).sendToTarget();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(PageRange[] pages, ParcelFileDescriptor fd,
|
public void write(PageRange[] pages, ParcelFileDescriptor fd,
|
||||||
IWriteResultCallback callback, int sequence) {
|
IWriteResultCallback callback, int sequence) {
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
if (mLayoutOrWriteCancellation != null) {
|
// Start not called or finish called - nothing to do.
|
||||||
mLayoutOrWriteCancellation.cancel();
|
if (!mStartReqeusted || mFinishRequested) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Write cancels previous writes.
|
||||||
|
if (mLastWriteSpec != null) {
|
||||||
|
IoUtils.closeQuietly(mLastWriteSpec.fd);
|
||||||
|
mLastWriteSpec = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
mLastWriteSpec = new WriteSpec();
|
||||||
|
mLastWriteSpec.callback = callback;
|
||||||
|
mLastWriteSpec.pages = pages;
|
||||||
|
mLastWriteSpec.fd = fd;
|
||||||
|
mLastWriteSpec.sequence = sequence;
|
||||||
|
|
||||||
|
// Cancel the previous cancellable operation.When the
|
||||||
|
// cancellation completes we will do the pending work.
|
||||||
|
if (cancelPreviousCancellableOperationLocked()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
doPendingWorkLocked();
|
||||||
}
|
}
|
||||||
SomeArgs args = SomeArgs.obtain();
|
|
||||||
args.arg1 = pages;
|
|
||||||
args.arg2 = fd;
|
|
||||||
args.arg3 = callback;
|
|
||||||
args.argi1 = sequence;
|
|
||||||
mHandler.removeMessages(MyHandler.MSG_WRITE);
|
|
||||||
mHandler.obtainMessage(MyHandler.MSG_WRITE, args).sendToTarget();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void finish() {
|
public void finish() {
|
||||||
mHandler.sendEmptyMessage(MyHandler.MSG_FINISH);
|
synchronized (mLock) {
|
||||||
|
// Start not called or finish called - nothing to do.
|
||||||
|
if (!mStartReqeusted || mFinishRequested) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mFinishRequested = true;
|
||||||
|
|
||||||
|
// When the current write or layout complete we
|
||||||
|
// will do the pending work.
|
||||||
|
if (mLastLayoutSpec != null || mLastWriteSpec != null) {
|
||||||
|
if (DEBUG) {
|
||||||
|
Log.i(LOG_TAG, "Waiting for current operation");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
doPendingWorkLocked();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isFinished() {
|
private boolean isFinished() {
|
||||||
@@ -407,7 +474,49 @@ public final class PrintManager {
|
|||||||
private void doFinish() {
|
private void doFinish() {
|
||||||
mDocumentAdapter = null;
|
mDocumentAdapter = null;
|
||||||
mHandler = null;
|
mHandler = null;
|
||||||
mLayoutOrWriteCancellation = null;
|
synchronized (mLock) {
|
||||||
|
mLayoutOrWriteCancellation = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean cancelPreviousCancellableOperationLocked() {
|
||||||
|
if (mLayoutOrWriteCancellation != null) {
|
||||||
|
mLayoutOrWriteCancellation.cancel();
|
||||||
|
if (DEBUG) {
|
||||||
|
Log.i(LOG_TAG, "Cancelling previous operation");
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doPendingWorkLocked() {
|
||||||
|
if (mStartReqeusted && !mStarted) {
|
||||||
|
mStarted = true;
|
||||||
|
mHandler.sendEmptyMessage(MyHandler.MSG_START);
|
||||||
|
} else if (mLastLayoutSpec != null) {
|
||||||
|
mHandler.sendEmptyMessage(MyHandler.MSG_LAYOUT);
|
||||||
|
} else if (mLastWriteSpec != null) {
|
||||||
|
mHandler.sendEmptyMessage(MyHandler.MSG_WRITE);
|
||||||
|
} else if (mFinishRequested && !mFinished) {
|
||||||
|
mFinished = true;
|
||||||
|
mHandler.sendEmptyMessage(MyHandler.MSG_FINISH);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class LayoutSpec {
|
||||||
|
ILayoutResultCallback callback;
|
||||||
|
PrintAttributes oldAttributes;
|
||||||
|
PrintAttributes newAttributes;
|
||||||
|
Bundle metadata;
|
||||||
|
int sequence;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class WriteSpec {
|
||||||
|
IWriteResultCallback callback;
|
||||||
|
PageRange[] pages;
|
||||||
|
ParcelFileDescriptor fd;
|
||||||
|
int sequence;
|
||||||
}
|
}
|
||||||
|
|
||||||
private final class MyHandler extends Handler {
|
private final class MyHandler extends Handler {
|
||||||
@@ -431,41 +540,52 @@ public final class PrintManager {
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case MSG_LAYOUT: {
|
case MSG_LAYOUT: {
|
||||||
SomeArgs args = (SomeArgs) message.obj;
|
final CancellationSignal cancellation;
|
||||||
PrintAttributes oldAttributes = (PrintAttributes) args.arg1;
|
final LayoutSpec layoutSpec;
|
||||||
PrintAttributes newAttributes = (PrintAttributes) args.arg2;
|
|
||||||
ILayoutResultCallback callback = (ILayoutResultCallback) args.arg3;
|
|
||||||
Bundle metadata = (Bundle) args.arg4;
|
|
||||||
final int sequence = args.argi1;
|
|
||||||
args.recycle();
|
|
||||||
|
|
||||||
CancellationSignal cancellation = new CancellationSignal();
|
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
|
layoutSpec = mLastLayoutSpec;
|
||||||
|
mLastLayoutSpec = null;
|
||||||
|
cancellation = new CancellationSignal();
|
||||||
mLayoutOrWriteCancellation = cancellation;
|
mLayoutOrWriteCancellation = cancellation;
|
||||||
}
|
}
|
||||||
|
|
||||||
mDocumentAdapter.onLayout(oldAttributes, newAttributes, cancellation,
|
if (layoutSpec != null) {
|
||||||
new MyLayoutResultCallback(callback, sequence), metadata);
|
if (DEBUG) {
|
||||||
|
Log.i(LOG_TAG, "Performing layout");
|
||||||
|
}
|
||||||
|
mDocumentAdapter.onLayout(layoutSpec.oldAttributes,
|
||||||
|
layoutSpec.newAttributes, cancellation,
|
||||||
|
new MyLayoutResultCallback(layoutSpec.callback,
|
||||||
|
layoutSpec.sequence), layoutSpec.metadata);
|
||||||
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case MSG_WRITE: {
|
case MSG_WRITE: {
|
||||||
SomeArgs args = (SomeArgs) message.obj;
|
final CancellationSignal cancellation;
|
||||||
PageRange[] pages = (PageRange[]) args.arg1;
|
final WriteSpec writeSpec;
|
||||||
ParcelFileDescriptor fd = (ParcelFileDescriptor) args.arg2;
|
|
||||||
IWriteResultCallback callback = (IWriteResultCallback) args.arg3;
|
|
||||||
final int sequence = args.argi1;
|
|
||||||
args.recycle();
|
|
||||||
|
|
||||||
CancellationSignal cancellation = new CancellationSignal();
|
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
|
writeSpec= mLastWriteSpec;
|
||||||
|
mLastWriteSpec = null;
|
||||||
|
cancellation = new CancellationSignal();
|
||||||
mLayoutOrWriteCancellation = cancellation;
|
mLayoutOrWriteCancellation = cancellation;
|
||||||
}
|
}
|
||||||
|
|
||||||
mDocumentAdapter.onWrite(pages, fd, cancellation,
|
if (writeSpec != null) {
|
||||||
new MyWriteResultCallback(callback, fd, sequence));
|
if (DEBUG) {
|
||||||
|
Log.i(LOG_TAG, "Performing write");
|
||||||
|
}
|
||||||
|
mDocumentAdapter.onWrite(writeSpec.pages, writeSpec.fd,
|
||||||
|
cancellation, new MyWriteResultCallback(writeSpec.callback,
|
||||||
|
writeSpec.fd, writeSpec.sequence));
|
||||||
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case MSG_FINISH: {
|
case MSG_FINISH: {
|
||||||
|
if (DEBUG) {
|
||||||
|
Log.i(LOG_TAG, "Performing finish");
|
||||||
|
}
|
||||||
mDocumentAdapter.onFinish();
|
mDocumentAdapter.onFinish();
|
||||||
doFinish();
|
doFinish();
|
||||||
} break;
|
} break;
|
||||||
@@ -533,6 +653,7 @@ public final class PrintManager {
|
|||||||
private void clearLocked() {
|
private void clearLocked() {
|
||||||
mLayoutOrWriteCancellation = null;
|
mLayoutOrWriteCancellation = null;
|
||||||
mCallback = null;
|
mCallback = null;
|
||||||
|
doPendingWorkLocked();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -598,6 +719,7 @@ public final class PrintManager {
|
|||||||
IoUtils.closeQuietly(mFd);
|
IoUtils.closeQuietly(mFd);
|
||||||
mCallback = null;
|
mCallback = null;
|
||||||
mFd = null;
|
mFd = null;
|
||||||
|
doPendingWorkLocked();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user