diff options
author | Svetoslav Ganov <svetoslavganov@google.com> | 2013-10-17 22:20:40 -0700 |
---|---|---|
committer | Svetoslav Ganov <svetoslavganov@google.com> | 2013-10-18 13:12:06 -0700 |
commit | 858a1850e2e1c4516129d27ecdf54aaeade606ca (patch) | |
tree | 2f5d1c2a61b5e131e842f148dba7bd90d2a7845c /packages/PrintSpooler/src | |
parent | b346270dde839029f9d4994cf2c3fc670a4249a6 (diff) | |
download | frameworks_base-858a1850e2e1c4516129d27ecdf54aaeade606ca.zip frameworks_base-858a1850e2e1c4516129d27ecdf54aaeade606ca.tar.gz frameworks_base-858a1850e2e1c4516129d27ecdf54aaeade606ca.tar.bz2 |
Hide the print dialog if the printing activity is destroyed.
1. For an app to print it creates a PrintDocumentAdapter implementation
which is passed to the print dialog activity. If the activity that
created the adapter is destroyed then the adapter, which may rely on
the activity state, may be in an invalid state. For example, an app
creates an adapter and calls print resuting in the app activity and
the print dialog activity being stacked. Now the user rotates the
device which triggers the recreating of the activity stack (assume the
app does not handle rotation). The recreated print dialog activity
receives the intent that originally created it with containing the
adapter that was constructed in the context of the old, now destroyed,
app activity instance.
To handle this we are limiting an app to be able to print only from
and activity and when this activity is destroyed we mark the adapter
as invalid which will result in hiding the print dialog activity. Note
that if the app process is killed we already handle this in the print
dialog activiy by registering a death recipient on the adapter binder.
2. In the PrintManager.PrintDocumentAdapterDelegate some of the state is
accessed only on the main thread and some from miltiple threads. The
code was trying to avoid locking for state that is not accessed by
multiple threads but this is error prone and the benefit does not
justify the complexity and added fragility. Now grabbing a lock all
the time.
3. The PrintJobConfigActivity waits for it to bind to the print spooler
service before instantiating its print controller and editor. However,
these can be accessed by invoking some of the activity cycle callbacks.
This change is adding null checks for the case where the activity
callbacks are called before the binding to the spooler is completed.
bug:11242661
Change-Id: Id906b3170e4f0a0553772dfa62686f06fdca0eaf
Diffstat (limited to 'packages/PrintSpooler/src')
-rw-r--r-- | packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java | 71 |
1 files changed, 56 insertions, 15 deletions
diff --git a/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java b/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java index 2997707..c90cb1f 100644 --- a/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java +++ b/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java @@ -40,6 +40,7 @@ import android.os.Message; import android.os.RemoteException; import android.print.ILayoutResultCallback; import android.print.IPrintDocumentAdapter; +import android.print.IPrintDocumentAdapterObserver; import android.print.IWriteResultCallback; import android.print.PageRange; import android.print.PrintAttributes; @@ -201,6 +202,14 @@ public class PrintJobConfigActivity extends Activity { throw new IllegalArgumentException("PrintDocumentAdapter cannot be null"); } + try { + IPrintDocumentAdapter.Stub.asInterface(mIPrintDocumentAdapter) + .setObserver(new PrintDocumentAdapterObserver(this)); + } catch (RemoteException re) { + finish(); + return; + } + PrintAttributes attributes = printJob.getAttributes(); if (attributes != null) { mCurrPrintAttributes.copyFrom(attributes); @@ -249,27 +258,29 @@ public class PrintJobConfigActivity extends Activity { // We can safely do the work in here since at this point // the system is bound to our (spooler) process which // guarantees that this process will not be killed. - if (mController.hasStarted()) { + if (mController != null && mController.hasStarted()) { mController.finish(); } - if (mEditor.isPrintConfirmed() && mController.isFinished()) { - mSpoolerProvider.getSpooler().setPrintJobState(mPrintJobId, - PrintJobInfo.STATE_QUEUED, null); + if (mEditor != null && mEditor.isPrintConfirmed() + && mController != null && mController.isFinished()) { + mSpoolerProvider.getSpooler().setPrintJobState(mPrintJobId, + PrintJobInfo.STATE_QUEUED, null); } else { mSpoolerProvider.getSpooler().setPrintJobState(mPrintJobId, PrintJobInfo.STATE_CANCELED, null); } - mIPrintDocumentAdapter.unlinkToDeath(mDeathRecipient, 0); if (mGeneratingPrintJobDialog != null) { mGeneratingPrintJobDialog.dismiss(); mGeneratingPrintJobDialog = null; } + mIPrintDocumentAdapter.unlinkToDeath(mDeathRecipient, 0); mSpoolerProvider.destroy(); super.onDestroy(); } public boolean onTouchEvent(MotionEvent event) { - if (!mEditor.isPrintConfirmed() && mEditor.shouldCloseOnTouch(event)) { + if (mController != null && mEditor != null && + !mEditor.isPrintConfirmed() && mEditor.shouldCloseOnTouch(event)) { if (!mController.isWorking()) { PrintJobConfigActivity.this.finish(); } @@ -287,17 +298,19 @@ public class PrintJobConfigActivity extends Activity { } public boolean onKeyUp(int keyCode, KeyEvent event) { - if (keyCode == KeyEvent.KEYCODE_BACK) { - if (mEditor.isShwoingGeneratingPrintJobUi()) { - return true; - } - if (event.isTracking() && !event.isCanceled()) { - if (!mController.isWorking()) { - PrintJobConfigActivity.this.finish(); + if (mController != null && mEditor != null) { + if (keyCode == KeyEvent.KEYCODE_BACK) { + if (mEditor.isShwoingGeneratingPrintJobUi()) { + return true; + } + if (event.isTracking() && !event.isCanceled()) { + if (!mController.isWorking()) { + PrintJobConfigActivity.this.finish(); + } } + mEditor.cancel(); + return true; } - mEditor.cancel(); - return true; } return super.onKeyUp(keyCode, event); } @@ -2703,4 +2716,32 @@ public class PrintJobConfigActivity extends Activity { /* do noting - we are in the same process */ } } + + private static final class PrintDocumentAdapterObserver + extends IPrintDocumentAdapterObserver.Stub { + private final WeakReference<PrintJobConfigActivity> mWeakActvity; + + public PrintDocumentAdapterObserver(PrintJobConfigActivity activity) { + mWeakActvity = new WeakReference<PrintJobConfigActivity>(activity); + } + + @Override + public void onDestroy() { + final PrintJobConfigActivity activity = mWeakActvity.get(); + if (activity != null) { + activity.mController.mHandler.post(new Runnable() { + @Override + public void run() { + if (activity.mController != null) { + activity.mController.cancel(); + } + if (activity.mEditor != null) { + activity.mEditor.cancel(); + } + activity.finish(); + } + }); + } + } + } } |