Crash in print spooler if printing app killed from recents.
If the printing app with the print UI on top is killed from recents we get a crash because: 1) the remote print document was not transitioned to a failed state if the printing app dies (this is an unrecoverable failure); 2) the print preview controller was destroyed asyncronosly during which it also asynchronously disconnects from the rendering service which however happens after the system has already cleaned up all connections of the print UI activity as it is being destoryed. bug:18109386 Change-Id: If6200b14a8aa90622228bbb659e9c4962226f561
This commit is contained in:
@@ -110,13 +110,12 @@ public final class PageContentRepository {
|
||||
mRenderer.close(callback);
|
||||
}
|
||||
|
||||
public void destroy(Runnable callback) {
|
||||
throwIfNotClosed();
|
||||
public void destroy() {
|
||||
mState = STATE_DESTROYED;
|
||||
if (DEBUG) {
|
||||
Log.i(LOG_TAG, "STATE_DESTROYED");
|
||||
}
|
||||
doDestroy(callback);
|
||||
mRenderer.destroy();
|
||||
}
|
||||
|
||||
public void startPreload(int firstShownPage, int lastShownPage) {
|
||||
@@ -163,21 +162,13 @@ public final class PageContentRepository {
|
||||
try {
|
||||
if (mState != STATE_DESTROYED) {
|
||||
mCloseGuard.warnIfOpen();
|
||||
doDestroy(null);
|
||||
destroy();
|
||||
}
|
||||
} finally {
|
||||
super.finalize();
|
||||
}
|
||||
}
|
||||
|
||||
private void doDestroy(Runnable callback) {
|
||||
mState = STATE_DESTROYED;
|
||||
if (DEBUG) {
|
||||
Log.i(LOG_TAG, "STATE_DESTROYED");
|
||||
}
|
||||
mRenderer.destroy(callback);
|
||||
}
|
||||
|
||||
private void throwIfNotOpened() {
|
||||
if (mState != STATE_OPENED) {
|
||||
throw new IllegalStateException("Not opened");
|
||||
@@ -428,6 +419,7 @@ public final class PageContentRepository {
|
||||
private IPdfRenderer mRenderer;
|
||||
|
||||
private boolean mBoundToService;
|
||||
private boolean mDestroyed;
|
||||
|
||||
public AsyncRenderer(Context context, OnMalformedPdfFileListener malformedPdfFileListener) {
|
||||
mContext = context;
|
||||
@@ -441,7 +433,6 @@ public final class PageContentRepository {
|
||||
|
||||
@Override
|
||||
public void onServiceConnected(ComponentName name, IBinder service) {
|
||||
mBoundToService = true;
|
||||
synchronized (mLock) {
|
||||
mRenderer = IPdfRenderer.Stub.asInterface(service);
|
||||
mLock.notifyAll();
|
||||
@@ -465,9 +456,14 @@ public final class PageContentRepository {
|
||||
new AsyncTask<Void, Void, Integer>() {
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
if (mDestroyed) {
|
||||
cancel(true);
|
||||
return;
|
||||
}
|
||||
Intent intent = new Intent(PdfManipulationService.ACTION_GET_RENDERER);
|
||||
intent.setClass(mContext, PdfManipulationService.class);
|
||||
mContext.bindService(intent, AsyncRenderer.this, Context.BIND_AUTO_CREATE);
|
||||
mBoundToService = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -512,6 +508,14 @@ public final class PageContentRepository {
|
||||
cancelAllRendering();
|
||||
|
||||
new AsyncTask<Void, Void, Void>() {
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
if (mDestroyed) {
|
||||
cancel(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Void doInBackground(Void... params) {
|
||||
synchronized (mLock) {
|
||||
@@ -534,27 +538,14 @@ public final class PageContentRepository {
|
||||
}.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR);
|
||||
}
|
||||
|
||||
public void destroy(final Runnable callback) {
|
||||
new AsyncTask<Void, Void, Void>() {
|
||||
@Override
|
||||
protected Void doInBackground(Void... params) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPostExecute(Void result) {
|
||||
if (mBoundToService) {
|
||||
mBoundToService = false;
|
||||
mContext.unbindService(AsyncRenderer.this);
|
||||
}
|
||||
mPageContentCache.invalidate();
|
||||
mPageContentCache.clear();
|
||||
if (callback != null) {
|
||||
callback.run();
|
||||
}
|
||||
|
||||
}
|
||||
}.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR);
|
||||
public void destroy() {
|
||||
if (mBoundToService) {
|
||||
mBoundToService = false;
|
||||
mContext.unbindService(AsyncRenderer.this);
|
||||
}
|
||||
mPageContentCache.invalidate();
|
||||
mPageContentCache.clear();
|
||||
mDestroyed = true;
|
||||
}
|
||||
|
||||
public void startPreload(int firstShownPage, int lastShownPage, RenderSpec renderSpec) {
|
||||
|
||||
@@ -78,7 +78,7 @@ public final class PrintSpoolerService extends Service {
|
||||
|
||||
private static final boolean DEBUG_PERSISTENCE = false;
|
||||
|
||||
private static final boolean PERSISTNECE_MANAGER_ENABLED = true;
|
||||
private static final boolean PERSISTENCE_MANAGER_ENABLED = true;
|
||||
|
||||
private static final long CHECK_ALL_PRINTJOBS_HANDLED_DELAY = 5000;
|
||||
|
||||
@@ -728,7 +728,7 @@ public final class PrintSpoolerService extends Service {
|
||||
}
|
||||
|
||||
public void writeStateLocked() {
|
||||
if (!PERSISTNECE_MANAGER_ENABLED) {
|
||||
if (!PERSISTENCE_MANAGER_ENABLED) {
|
||||
return;
|
||||
}
|
||||
if (mWriteStateScheduled) {
|
||||
@@ -935,7 +935,7 @@ public final class PrintSpoolerService extends Service {
|
||||
}
|
||||
|
||||
public void readStateLocked() {
|
||||
if (!PERSISTNECE_MANAGER_ENABLED) {
|
||||
if (!PERSISTENCE_MANAGER_ENABLED) {
|
||||
return;
|
||||
}
|
||||
FileInputStream in = null;
|
||||
|
||||
@@ -137,7 +137,7 @@ public final class RemotePrintDocument {
|
||||
private final DeathRecipient mDeathRecipient = new DeathRecipient() {
|
||||
@Override
|
||||
public void binderDied() {
|
||||
notifyPrintingAppDied();
|
||||
onPrintingAppDied();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -268,7 +268,7 @@ public final class RemotePrintDocument {
|
||||
mPrintDocumentAdapter.finish();
|
||||
mState = STATE_FINISHED;
|
||||
} catch (RemoteException re) {
|
||||
Log.e(LOG_TAG, "Error calling finish()", re);
|
||||
Log.e(LOG_TAG, "Error calling finish()");
|
||||
mState = STATE_FAILED;
|
||||
}
|
||||
}
|
||||
@@ -1108,7 +1108,8 @@ public final class RemotePrintDocument {
|
||||
}
|
||||
}
|
||||
|
||||
private void notifyPrintingAppDied() {
|
||||
private void onPrintingAppDied() {
|
||||
mState = STATE_FAILED;
|
||||
new Handler(mLooper).post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@@ -1129,7 +1130,7 @@ public final class RemotePrintDocument {
|
||||
public void onDestroy() {
|
||||
final RemotePrintDocument document = mWeakDocument.get();
|
||||
if (document != null) {
|
||||
document.notifyPrintingAppDied();
|
||||
document.onPrintingAppDied();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -484,9 +484,13 @@ public final class PageAdapter extends Adapter implements
|
||||
return selectedPages;
|
||||
}
|
||||
|
||||
public void destroy(Runnable callback) {
|
||||
throwIfNotClosed();
|
||||
doDestroy(callback);
|
||||
public void destroy() {
|
||||
mPageContentRepository.destroy();
|
||||
mCloseGuard.close();
|
||||
mState = STATE_DESTROYED;
|
||||
if (DEBUG) {
|
||||
Log.i(LOG_TAG, "STATE_DESTROYED");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -494,7 +498,7 @@ public final class PageAdapter extends Adapter implements
|
||||
try {
|
||||
if (mState != STATE_DESTROYED) {
|
||||
mCloseGuard.warnIfOpen();
|
||||
doDestroy(null);
|
||||
destroy();
|
||||
}
|
||||
} finally {
|
||||
super.finalize();
|
||||
@@ -741,15 +745,6 @@ public final class PageAdapter extends Adapter implements
|
||||
mPageContentRepository.stopPreload();
|
||||
}
|
||||
|
||||
private void doDestroy(Runnable callback) {
|
||||
mPageContentRepository.destroy(callback);
|
||||
mCloseGuard.close();
|
||||
mState = STATE_DESTROYED;
|
||||
if (DEBUG) {
|
||||
Log.i(LOG_TAG, "STATE_DESTROYED");
|
||||
}
|
||||
}
|
||||
|
||||
private void throwIfNotOpened() {
|
||||
if (mState != STATE_OPENED) {
|
||||
throw new IllegalStateException("Not opened");
|
||||
|
||||
@@ -1616,15 +1616,9 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
|
||||
mSpoolerProvider.destroy();
|
||||
mPrintedDocument.finish();
|
||||
mPrintedDocument.destroy();
|
||||
mPrintPreviewController.destroy(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
finish();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
finish();
|
||||
mPrintPreviewController.destroy();
|
||||
}
|
||||
finish();
|
||||
}
|
||||
|
||||
private final class SpinnerItem<T> {
|
||||
|
||||
@@ -192,15 +192,10 @@ class PrintPreviewController implements MutexFileProvider.OnReleaseRequestCallba
|
||||
});
|
||||
}
|
||||
|
||||
public void destroy(Runnable callback) {
|
||||
if (mPageAdapter.isOpened()) {
|
||||
Message operation = mHandler.obtainMessage(MyHandler.MSG_CLOSE);
|
||||
mHandler.enqueueOperation(operation);
|
||||
}
|
||||
|
||||
Message operation = mHandler.obtainMessage(MyHandler.MSG_DESTROY);
|
||||
operation.obj = callback;
|
||||
mHandler.enqueueOperation(operation);
|
||||
public void destroy() {
|
||||
mHandler.cancelQueuedOperations();
|
||||
mRecyclerView.setAdapter(null);
|
||||
mPageAdapter.destroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -226,7 +221,6 @@ class PrintPreviewController implements MutexFileProvider.OnReleaseRequestCallba
|
||||
private final class MyHandler extends Handler {
|
||||
public static final int MSG_OPEN = 1;
|
||||
public static final int MSG_CLOSE = 2;
|
||||
public static final int MSG_DESTROY = 3;
|
||||
public static final int MSG_UPDATE = 4;
|
||||
public static final int MSG_START_PRELOAD = 5;
|
||||
|
||||
@@ -246,6 +240,10 @@ class PrintPreviewController implements MutexFileProvider.OnReleaseRequestCallba
|
||||
super(looper, null, false);
|
||||
}
|
||||
|
||||
public void cancelQueuedOperations() {
|
||||
mPendingOperations.clear();
|
||||
}
|
||||
|
||||
public void enqueueOperation(Message message) {
|
||||
mPendingOperations.add(message);
|
||||
handleNextOperation();
|
||||
@@ -294,13 +292,6 @@ class PrintPreviewController implements MutexFileProvider.OnReleaseRequestCallba
|
||||
});
|
||||
} break;
|
||||
|
||||
case MSG_DESTROY: {
|
||||
Runnable callback = (Runnable) message.obj;
|
||||
mRecyclerView.setAdapter(null);
|
||||
mPageAdapter.destroy(callback);
|
||||
handleNextOperation();
|
||||
} break;
|
||||
|
||||
case MSG_UPDATE: {
|
||||
SomeArgs args = (SomeArgs) message.obj;
|
||||
PageRange[] writtenPages = (PageRange[]) args.arg1;
|
||||
|
||||
Reference in New Issue
Block a user