From c80814e70aea8940d0d43cd7170baae8c0c4e8e3 Mon Sep 17 00:00:00 2001 From: Svet Ganov Date: Mon, 24 Nov 2014 02:01:37 -0800 Subject: [PATCH] Lockup in the print spooler. A recent change modified the way we destroy the remote renderer from asynchronous to synchronous. This caused problems since it was possible that the remote rendering service is unbound while we are reading the contents of a rendered page. As a result the reader was blocking on I/O and the print spooler was getting into a locked state that required a restart of its process. Now the remote renderer is destroyed asynchronously. bug:18498626 Change-Id: I1312bf808f30430728b4038dd4be43c55d2be825 --- .../model/PageContentRepository.java | 26 ++++++++++++++----- .../android/printspooler/ui/PageAdapter.java | 6 ++--- .../printspooler/ui/PrintActivity.java | 10 +++++-- .../ui/PrintPreviewController.java | 4 +-- 4 files changed, 33 insertions(+), 13 deletions(-) diff --git a/packages/PrintSpooler/src/com/android/printspooler/model/PageContentRepository.java b/packages/PrintSpooler/src/com/android/printspooler/model/PageContentRepository.java index 09236491e217b..90875c0b31ffe 100644 --- a/packages/PrintSpooler/src/com/android/printspooler/model/PageContentRepository.java +++ b/packages/PrintSpooler/src/com/android/printspooler/model/PageContentRepository.java @@ -106,12 +106,26 @@ public final class PageContentRepository { mRenderer.close(callback); } - public void destroy() { + public void destroy(final Runnable callback) { + if (mState == STATE_OPENED) { + close(new Runnable() { + @Override + public void run() { + destroy(callback); + } + }); + return; + } + mState = STATE_DESTROYED; if (DEBUG) { Log.i(LOG_TAG, "STATE_DESTROYED"); } mRenderer.destroy(); + + if (callback != null) { + callback.run(); + } } public void startPreload(int firstShownPage, int lastShownPage) { @@ -158,7 +172,7 @@ public final class PageContentRepository { try { if (mState != STATE_DESTROYED) { mCloseGuard.warnIfOpen(); - destroy(); + destroy(null); } } finally { super.finalize(); @@ -455,6 +469,10 @@ public final class PageContentRepository { public void close(final Runnable callback) { cancelAllRendering(); + if (mOpenTask != null) { + mOpenTask.cancel(); + } + new AsyncTask() { @Override protected void onPreExecute() { @@ -492,10 +510,6 @@ public final class PageContentRepository { mContext.unbindService(AsyncRenderer.this); } - if (mOpenTask != null) { - mOpenTask.cancel(); - } - mPageContentCache.invalidate(); mPageContentCache.clear(); mDestroyed = true; diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java index 0d2e7361cfdda..2757b816db409 100644 --- a/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java +++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java @@ -493,13 +493,13 @@ public final class PageAdapter extends Adapter { return selectedPages; } - public void destroy() { - mPageContentRepository.destroy(); + public void destroy(Runnable callback) { mCloseGuard.close(); mState = STATE_DESTROYED; if (DEBUG) { Log.i(LOG_TAG, "STATE_DESTROYED"); } + mPageContentRepository.destroy(callback); } @Override @@ -507,7 +507,7 @@ public final class PageAdapter extends Adapter { try { if (mState != STATE_DESTROYED) { mCloseGuard.warnIfOpen(); - destroy(); + destroy(null); } } finally { super.finalize(); diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java index 71d53409ed914..352b545af8d60 100644 --- a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java +++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java @@ -1635,9 +1635,15 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat mSpoolerProvider.destroy(); mPrintedDocument.finish(); mPrintedDocument.destroy(); - mPrintPreviewController.destroy(); + mPrintPreviewController.destroy(new Runnable() { + @Override + public void run() { + finish(); + } + }); + } else { + finish(); } - finish(); } private final class SpinnerItem { diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintPreviewController.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintPreviewController.java index 15342ae3f5950..8716fd21cdb84 100644 --- a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintPreviewController.java +++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintPreviewController.java @@ -192,10 +192,10 @@ class PrintPreviewController implements MutexFileProvider.OnReleaseRequestCallba }); } - public void destroy() { + public void destroy(Runnable callback) { mHandler.cancelQueuedOperations(); mRecyclerView.setAdapter(null); - mPageAdapter.destroy(); + mPageAdapter.destroy(callback); } @Override