am 5c880d0d: am 6f688e87: am 8f34715b: Merge "Refactor how the print dialog activity is started." into klp-dev

* commit '5c880d0d1551603dcc4366406ec9ee3b812a8fc4':
  Refactor how the print dialog activity is started.
diff --git a/Android.mk b/Android.mk
index 50009c8b..c6dd857 100644
--- a/Android.mk
+++ b/Android.mk
@@ -169,7 +169,6 @@
 	core/java/android/print/ILayoutResultCallback.aidl \
 	core/java/android/print/IPrinterDiscoveryObserver.aidl \
 	core/java/android/print/IPrintDocumentAdapter.aidl \
-	core/java/android/print/IPrintClient.aidl \
 	core/java/android/print/IPrintJobStateChangeListener.aidl \
 	core/java/android/print/IPrintManager.aidl \
 	core/java/android/print/IPrintSpooler.aidl \
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 2739298..2fa195c 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -184,6 +184,8 @@
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/media/audio/)
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/media/audio/effects/)
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/framework-res_intermediates)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/src/core/java/android/print/IPrintClient.*)
+
 # ************************************************
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
 # ************************************************
diff --git a/core/java/android/print/IPrintManager.aidl b/core/java/android/print/IPrintManager.aidl
index 3bd515b..8fa7ab9 100644
--- a/core/java/android/print/IPrintManager.aidl
+++ b/core/java/android/print/IPrintManager.aidl
@@ -16,9 +16,9 @@
 
 package android.print;
 
+import android.os.Bundle;
 import android.print.IPrinterDiscoveryObserver;
 import android.print.IPrintDocumentAdapter;
-import android.print.IPrintClient;
 import android.print.PrintJobId;
 import android.print.IPrintJobStateChangeListener;
 import android.print.PrinterId;
@@ -34,9 +34,8 @@
 interface IPrintManager {
     List<PrintJobInfo> getPrintJobInfos(int appId, int userId);
     PrintJobInfo getPrintJobInfo(in PrintJobId printJobId, int appId, int userId);
-    PrintJobInfo print(String printJobName, in IPrintClient client,
-            in IPrintDocumentAdapter printAdapter, in PrintAttributes attributes,
-            int appId, int userId);
+    Bundle print(String printJobName, in IPrintDocumentAdapter printAdapter,
+            in PrintAttributes attributes, String packageName, int appId, int userId);
     void cancelPrintJob(in PrintJobId printJobId, int appId, int userId);
     void restartPrintJob(in PrintJobId printJobId, int appId, int userId);
 
diff --git a/core/java/android/print/IPrintSpooler.aidl b/core/java/android/print/IPrintSpooler.aidl
index 5f06b83..7b2cf25 100644
--- a/core/java/android/print/IPrintSpooler.aidl
+++ b/core/java/android/print/IPrintSpooler.aidl
@@ -18,8 +18,6 @@
 
 import android.content.ComponentName;
 import android.os.ParcelFileDescriptor;
-import android.print.IPrintDocumentAdapter;
-import android.print.IPrintClient;
 import android.print.IPrintSpoolerClient;
 import android.print.IPrintSpoolerCallbacks;
 import android.print.PrinterInfo;
@@ -40,8 +38,7 @@
             int state, int appId, int sequence);
     void getPrintJobInfo(in PrintJobId printJobId, IPrintSpoolerCallbacks callback,
             int appId, int sequence);
-    void createPrintJob(in PrintJobInfo printJob, in IPrintClient client,
-            in IPrintDocumentAdapter printAdapter);
+    void createPrintJob(in PrintJobInfo printJob);
     void setPrintJobState(in PrintJobId printJobId, int status, String stateReason,
             IPrintSpoolerCallbacks callback, int sequence);
     void setPrintJobTag(in PrintJobId printJobId, String tag, IPrintSpoolerCallbacks callback,
diff --git a/core/java/android/print/PrintManager.java b/core/java/android/print/PrintManager.java
index 1cb4e8d..1233da2 100644
--- a/core/java/android/print/PrintManager.java
+++ b/core/java/android/print/PrintManager.java
@@ -60,8 +60,47 @@
 
     private static final boolean DEBUG = false;
 
-    private static final int MSG_START_PRINT_JOB_CONFIG_ACTIVITY = 1;
-    private static final int MSG_NOTIFY_PRINT_JOB_STATE_CHANGED = 2;
+    private static final int MSG_NOTIFY_PRINT_JOB_STATE_CHANGED = 1;
+
+    /**
+     * The action for launching the print dialog activity.
+     *
+     * @hide
+     */
+    public static final String ACTION_PRINT_DIALOG = "android.print.PRINT_DIALOG";
+
+    /**
+     * Extra with the intent for starting the print dialog.
+     * <p>
+     * <strong>Type:</strong> {@link android.content.IntentSender}
+     * </p>
+     *
+     * @hide
+     */
+    public static final String EXTRA_PRINT_DIALOG_INTENT =
+            "android.print.intent.extra.EXTRA_PRINT_DIALOG_INTENT";
+
+    /**
+     * Extra with a print job.
+     * <p>
+     * <strong>Type:</strong> {@link android.print.PrintJobInfo}
+     * </p>
+     *
+     * @hide
+     */
+    public static final String EXTRA_PRINT_JOB =
+            "android.print.intent.extra.EXTRA_PRINT_JOB";
+
+    /**
+     * Extra with the print document adapter to be printed.
+     * <p>
+     * <strong>Type:</strong> {@link android.print.IPrintDocumentAdapter}
+     * </p>
+     *
+     * @hide
+     */
+    public static final String EXTRA_PRINT_DOCUMENT_ADAPTER =
+            "android.print.intent.extra.EXTRA_PRINT_DOCUMENT_ADAPTER";
 
     /** @hide */
     public static final int APP_ID_ANY = -2;
@@ -74,8 +113,6 @@
 
     private final int mAppId;
 
-    private final PrintClient mPrintClient;
-
     private final Handler mHandler;
 
     private Map<PrintJobStateChangeListener, PrintJobStateChangeListenerWrapper> mPrintJobStateChangeListeners;
@@ -103,24 +140,10 @@
         mService = service;
         mUserId = userId;
         mAppId = appId;
-        mPrintClient = new PrintClient(this);
         mHandler = new Handler(context.getMainLooper(), null, false) {
             @Override
             public void handleMessage(Message message) {
                 switch (message.what) {
-                    case MSG_START_PRINT_JOB_CONFIG_ACTIVITY: {
-                        SomeArgs args = (SomeArgs) message.obj;
-                        Context context = (Context) args.arg1;
-                        IntentSender intent = (IntentSender) args.arg2;
-                        args.recycle();
-                        try {
-                            context.startIntentSender(intent, null, 0, 0, 0);
-                        } catch (SendIntentException sie) {
-                            Log.e(LOG_TAG, "Couldn't start print job config activity.", sie);
-                        }
-                    }
-                        break;
-
                     case MSG_NOTIFY_PRINT_JOB_STATE_CHANGED: {
                         SomeArgs args = (SomeArgs) message.obj;
                         PrintJobStateChangeListener listener =
@@ -128,8 +151,7 @@
                         PrintJobId printJobId = (PrintJobId) args.arg2;
                         args.recycle();
                         listener.onPrintJobStateChanged(printJobId);
-                    }
-                        break;
+                    } break;
                 }
             }
         };
@@ -279,10 +301,20 @@
         PrintDocumentAdapterDelegate delegate = new PrintDocumentAdapterDelegate(documentAdapter,
                 mContext.getMainLooper());
         try {
-            PrintJobInfo printJob = mService.print(printJobName, mPrintClient, delegate,
-                    attributes, mAppId, mUserId);
-            if (printJob != null) {
-                return new PrintJob(printJob, this);
+            Bundle result = mService.print(printJobName, delegate,
+                    attributes, mContext.getPackageName(), mAppId, mUserId);
+            if (result != null) {
+                PrintJobInfo printJob = result.getParcelable(EXTRA_PRINT_JOB);
+                IntentSender intent = result.getParcelable(EXTRA_PRINT_DIALOG_INTENT);
+                if (printJob == null || intent == null) {
+                    return null;
+                }
+                try {
+                    mContext.startIntentSender(intent, null, 0, 0, 0);
+                    return new PrintJob(printJob, this);
+                } catch (SendIntentException sie) {
+                    Log.e(LOG_TAG, "Couldn't start print job config activity.", sie);
+                }
             }
         } catch (RemoteException re) {
             Log.e(LOG_TAG, "Error creating a print job", re);
@@ -333,27 +365,6 @@
         return new PrinterDiscoverySession(mService, mContext, mUserId);
     }
 
-    private static final class PrintClient extends IPrintClient.Stub {
-
-        private final WeakReference<PrintManager> mWeakPrintManager;
-
-        public PrintClient(PrintManager manager) {
-            mWeakPrintManager = new WeakReference<PrintManager>(manager);
-        }
-
-        @Override
-        public void startPrintJobConfigActivity(IntentSender intent) {
-            PrintManager manager = mWeakPrintManager.get();
-            if (manager != null) {
-                SomeArgs args = SomeArgs.obtain();
-                args.arg1 = manager.mContext;
-                args.arg2 = intent;
-                manager.mHandler.obtainMessage(MSG_START_PRINT_JOB_CONFIG_ACTIVITY,
-                        args).sendToTarget();
-            }
-        }
-    }
-
     private static final class PrintDocumentAdapterDelegate extends IPrintDocumentAdapter.Stub {
 
         private final Object mLock = new Object();
diff --git a/packages/PrintSpooler/AndroidManifest.xml b/packages/PrintSpooler/AndroidManifest.xml
index 1e6954e..7eea3e9 100644
--- a/packages/PrintSpooler/AndroidManifest.xml
+++ b/packages/PrintSpooler/AndroidManifest.xml
@@ -58,8 +58,13 @@
         <activity
             android:name=".PrintJobConfigActivity"
             android:configChanges="orientation|screenSize"
-            android:exported="false"
+            android:permission="android.permission.BIND_PRINT_SPOOLER_SERVICE"
             android:theme="@style/PrintJobConfigActivityTheme">
+            <intent-filter>
+                <action android:name="android.print.PRINT_DILAOG" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <data android:scheme="printjob" android:pathPattern="*" />
+            </intent-filter>
         </activity>
 
         <activity
diff --git a/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java b/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java
index 2922dd1..007d9c0 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java
@@ -19,9 +19,11 @@
 import android.app.Activity;
 import android.app.Dialog;
 import android.app.LoaderManager;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.Loader;
+import android.content.ServiceConnection;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.database.DataSetObserver;
@@ -52,6 +54,7 @@
 import android.print.PrinterCapabilitiesInfo;
 import android.print.PrinterId;
 import android.print.PrinterInfo;
+import android.provider.DocumentsContract;
 import android.text.Editable;
 import android.text.TextUtils;
 import android.text.TextUtils.SimpleStringSplitter;
@@ -66,9 +69,9 @@
 import android.view.View.MeasureSpec;
 import android.view.View.OnAttachStateChangeListener;
 import android.view.View.OnClickListener;
-import android.view.ViewGroup.LayoutParams;
 import android.view.ViewConfiguration;
 import android.view.ViewGroup;
+import android.view.ViewGroup.LayoutParams;
 import android.view.ViewPropertyAnimator;
 import android.view.inputmethod.InputMethodManager;
 import android.widget.AdapterView;
@@ -84,6 +87,8 @@
 
 import com.android.printspooler.MediaSizeUtils.MediaSizeComparator;
 
+import libcore.io.IoUtils;
+
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
@@ -100,8 +105,6 @@
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
-import libcore.io.IoUtils;
-
 /**
  * Activity for configuring a print job.
  */
@@ -111,9 +114,6 @@
 
     private static final boolean DEBUG = false;
 
-    public static final String EXTRA_PRINT_DOCUMENT_ADAPTER = "printDocumentAdapter";
-    public static final String EXTRA_PRINT_JOB = "printJob";
-
     public static final String INTENT_EXTRA_PRINTER_ID = "INTENT_EXTRA_PRINTER_ID";
 
     private static final int LOADER_ID_PRINTERS_LOADER = 1;
@@ -177,6 +177,10 @@
 
     private Dialog mGeneratingPrintJobDialog;
 
+    private PrintSpoolerProvider mSpoolerProvider;
+
+    private String mCallingPackageName;
+
     @Override
     protected void onCreate(Bundle bundle) {
         super.onCreate(bundle);
@@ -185,13 +189,13 @@
 
         Bundle extras = getIntent().getExtras();
 
-        PrintJobInfo printJob = extras.getParcelable(EXTRA_PRINT_JOB);
+        PrintJobInfo printJob = extras.getParcelable(PrintManager.EXTRA_PRINT_JOB);
         if (printJob == null) {
             throw new IllegalArgumentException("printJob cannot be null");
         }
 
         mPrintJobId = printJob.getId();
-        mIPrintDocumentAdapter = extras.getBinder(EXTRA_PRINT_DOCUMENT_ADAPTER);
+        mIPrintDocumentAdapter = extras.getBinder(PrintManager.EXTRA_PRINT_DOCUMENT_ADAPTER);
         if (mIPrintDocumentAdapter == null) {
             throw new IllegalArgumentException("PrintDocumentAdapter cannot be null");
         }
@@ -201,13 +205,9 @@
             mCurrPrintAttributes.copyFrom(attributes);
         }
 
-        setContentView(R.layout.print_job_config_activity_container);
+        mCallingPackageName = extras.getString(DocumentsContract.EXTRA_PACKAGE_NAME);
 
-        mDocument = new Document();
-        mController = new PrintController(new RemotePrintDocumentAdapter(
-                IPrintDocumentAdapter.Stub.asInterface(mIPrintDocumentAdapter),
-                PrintSpoolerService.peekInstance().generateFileForPrintJob(mPrintJobId)));
-        mEditor = new Editor();
+        setContentView(R.layout.print_job_config_activity_container);
 
         try {
             mIPrintDocumentAdapter.linkToDeath(mDeathRecipient, 0);
@@ -216,14 +216,31 @@
             return;
         }
 
-        mController.initialize();
-        mEditor.initialize();
+        mDocument = new Document();
+        mEditor = new Editor();
+
+        mSpoolerProvider = new PrintSpoolerProvider(this,
+                new Runnable() {
+            @Override
+            public void run() {
+                // We got the spooler so unleash the UI.
+                mController = new PrintController(new RemotePrintDocumentAdapter(
+                        IPrintDocumentAdapter.Stub.asInterface(mIPrintDocumentAdapter),
+                        mSpoolerProvider.getSpooler().generateFileForPrintJob(mPrintJobId)));
+                mController.initialize();
+
+                mEditor.initialize();
+                mEditor.postCreate();
+            }
+        });
     }
 
     @Override
     public void onResume() {
         super.onResume();
-        mEditor.refreshCurrentPrinter();
+        if (mSpoolerProvider.getSpooler() != null) {
+            mEditor.refreshCurrentPrinter();
+        }
     }
 
     @Override
@@ -235,10 +252,10 @@
             mController.finish();
         }
         if (mEditor.isPrintConfirmed() && mController.isFinished()) {
-            PrintSpoolerService.peekInstance().setPrintJobState(mPrintJobId,
+            mSpoolerProvider.getSpooler().setPrintJobState(mPrintJobId,
                     PrintJobInfo.STATE_QUEUED, null);
         } else {
-            PrintSpoolerService.peekInstance().setPrintJobState(mPrintJobId,
+            mSpoolerProvider.getSpooler().setPrintJobState(mPrintJobId,
                     PrintJobInfo.STATE_CANCELED, null);
         }
         mIPrintDocumentAdapter.unlinkToDeath(mDeathRecipient, 0);
@@ -246,6 +263,7 @@
             mGeneratingPrintJobDialog.dismiss();
             mGeneratingPrintJobDialog = null;
         }
+        mSpoolerProvider.destroy();
         super.onDestroy();
     }
 
@@ -367,7 +385,7 @@
                 // we handle writing as usual.
                 handleOnLayoutFinished(mDocument.info, false, mRequestCounter.get());
             } else {
-                PrintSpoolerService.peekInstance().setPrintJobAttributesNoPersistence(
+                mSpoolerProvider.getSpooler().setPrintJobAttributesNoPersistence(
                         mPrintJobId, mCurrPrintAttributes);
 
                 mMetadata.putBoolean(PrintDocumentAdapter.EXTRA_PRINT_PREVIEW,
@@ -412,7 +430,7 @@
             if (infoChanged) {
                 mDocument.info = info;
                 // Set the info.
-                PrintSpoolerService.peekInstance().setPrintJobPrintDocumentInfoNoPersistence(
+                mSpoolerProvider.getSpooler().setPrintJobPrintDocumentInfoNoPersistence(
                         mPrintJobId, info);
             }
 
@@ -420,7 +438,7 @@
             // drop the pages since we have to fetch them again.
             if (infoChanged || layoutChanged) {
                 mDocument.pages = null;
-                PrintSpoolerService.peekInstance().setPrintJobPagesNoPersistence(
+                mSpoolerProvider.getSpooler().setPrintJobPagesNoPersistence(
                         mPrintJobId, null);
             }
 
@@ -499,12 +517,12 @@
             mControllerState = CONTROLLER_STATE_WRITE_COMPLETED;
 
             // Update the document size.
-            File file = PrintSpoolerService.peekInstance()
+            File file = mSpoolerProvider.getSpooler()
                     .generateFileForPrintJob(mPrintJobId);
             mDocument.info.setDataSize(file.length());
 
             // Update the print job with the updated info.
-            PrintSpoolerService.peekInstance().setPrintJobPrintDocumentInfoNoPersistence(
+            mSpoolerProvider.getSpooler().setPrintJobPrintDocumentInfoNoPersistence(
                     mPrintJobId, mDocument.info);
 
             // Update which pages we have fetched.
@@ -528,12 +546,12 @@
             if (Arrays.equals(writtenPages, requestedPages)) {
                 // We got a document with exactly the pages we wanted. Hence,
                 // the printer has to print all pages in the data.
-                PrintSpoolerService.peekInstance().setPrintJobPagesNoPersistence(mPrintJobId,
+                mSpoolerProvider.getSpooler().setPrintJobPagesNoPersistence(mPrintJobId,
                         ALL_PAGES_ARRAY);
             } else if (Arrays.equals(writtenPages, ALL_PAGES_ARRAY)) {
                 // We requested specific pages but got all of them. Hence,
                 // the printer has to print only the requested pages.
-                PrintSpoolerService.peekInstance().setPrintJobPagesNoPersistence(mPrintJobId,
+                mSpoolerProvider.getSpooler().setPrintJobPagesNoPersistence(mPrintJobId,
                         requestedPages);
             } else if (PageRangeUtils.contains(writtenPages, requestedPages)) {
                 // We requested specific pages and got more but not all pages.
@@ -543,7 +561,7 @@
                 final int offset = -writtenPages[0].getStart();
                 PageRange[] offsetPages = Arrays.copyOf(requestedPages, requestedPages.length);
                 PageRangeUtils.offset(offsetPages, offset);
-                PrintSpoolerService.peekInstance().setPrintJobPagesNoPersistence(mPrintJobId,
+                mSpoolerProvider.getSpooler().setPrintJobPagesNoPersistence(mPrintJobId,
                         offsetPages);
             } else if (Arrays.equals(requestedPages, ALL_PAGES_ARRAY)
                     && writtenPages.length == 1 && writtenPages[0].getStart() == 0
@@ -551,7 +569,7 @@
                 // We requested all pages via the special constant and got all
                 // of them as an explicit enumeration. Hence, the printer has
                 // to print only the requested pages.
-                PrintSpoolerService.peekInstance().setPrintJobPagesNoPersistence(mPrintJobId,
+                mSpoolerProvider.getSpooler().setPrintJobPagesNoPersistence(mPrintJobId,
                         writtenPages);
             } else {
                 // We did not get the pages we requested, then the application
@@ -566,11 +584,12 @@
 
         private void requestCreatePdfFileOrFinish() {
             if (mEditor.isPrintingToPdf()) {
-                PrintJobInfo printJob = PrintSpoolerService.peekInstance()
+                PrintJobInfo printJob = mSpoolerProvider.getSpooler()
                         .getPrintJobInfo(mPrintJobId, PrintManager.APP_ID_ANY);
                 Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
                 intent.setType("application/pdf");
                 intent.putExtra(Intent.EXTRA_TITLE, printJob.getLabel());
+                intent.putExtra(DocumentsContract.EXTRA_PACKAGE_NAME, mCallingPackageName);
                 startActivityForResult(intent, ACTIVITY_REQUEST_CREATE_FILE);
             } else {
                 PrintJobConfigActivity.this.finish();
@@ -741,12 +760,12 @@
                 InputStream in = null;
                 OutputStream out = null;
                 try {
-                    PrintJobInfo printJob = PrintSpoolerService.peekInstance()
+                    PrintJobInfo printJob = mSpoolerProvider.getSpooler()
                             .getPrintJobInfo(mPrintJobId, PrintManager.APP_ID_ANY);
                     if (printJob == null) {
                         return null;
                     }
-                    File file = PrintSpoolerService.peekInstance()
+                    File file = mSpoolerProvider.getSpooler()
                             .generateFileForPrintJob(mPrintJobId);
                     in = new FileInputStream(file);
                     out = getContentResolver().openOutputStream(uri);
@@ -789,21 +808,21 @@
         private EditText mPageRangeEditText;
 
         private Spinner mDestinationSpinner;
-        private final DestinationAdapter mDestinationSpinnerAdapter;
+        private DestinationAdapter mDestinationSpinnerAdapter;
 
         private Spinner mMediaSizeSpinner;
-        private final ArrayAdapter<SpinnerItem<MediaSize>> mMediaSizeSpinnerAdapter;
+        private ArrayAdapter<SpinnerItem<MediaSize>> mMediaSizeSpinnerAdapter;
 
         private Spinner mColorModeSpinner;
-        private final ArrayAdapter<SpinnerItem<Integer>> mColorModeSpinnerAdapter;
+        private ArrayAdapter<SpinnerItem<Integer>> mColorModeSpinnerAdapter;
 
         private Spinner mOrientationSpinner;
-        private final  ArrayAdapter<SpinnerItem<Integer>> mOrientationSpinnerAdapter;
+        private  ArrayAdapter<SpinnerItem<Integer>> mOrientationSpinnerAdapter;
 
         private Spinner mRangeOptionsSpinner;
-        private final ArrayAdapter<SpinnerItem<Integer>> mRangeOptionsSpinnerAdapter;
+        private ArrayAdapter<SpinnerItem<Integer>> mRangeOptionsSpinnerAdapter;
 
-        private final SimpleStringSplitter mStringCommaSplitter =
+        private SimpleStringSplitter mStringCommaSplitter =
                 new SimpleStringSplitter(',');
 
         private View mContentContainer;
@@ -814,7 +833,7 @@
 
         private PrinterInfo mCurrentPrinter;
 
-        private final MediaSizeComparator mMediaSizeComparator;
+        private MediaSizeComparator mMediaSizeComparator;
 
         private final OnItemSelectedListener mOnItemSelectedListener =
                 new AdapterView.OnItemSelectedListener() {
@@ -826,6 +845,11 @@
                         return;
                     }
 
+                    if (position == AdapterView.INVALID_POSITION) {
+                        updateUi();
+                        return;
+                    }
+
                     if (id == DEST_ADAPTER_ITEM_ID_ALL_PRINTERS) {
                         startSelectPrinterActivity();
                         return;
@@ -836,7 +860,7 @@
                     mCurrentPrinter = (PrinterInfo) mDestinationSpinnerAdapter
                             .getItem(position);
 
-                    PrintSpoolerService.peekInstance().setPrintJobPrinterNoPersistence(
+                    mSpoolerProvider.getSpooler().setPrintJobPrinterNoPersistence(
                             mPrintJobId, mCurrentPrinter);
 
                     if (mCurrentPrinter.getStatus() == PrinterInfo.STATUS_UNAVAILABLE) {
@@ -1053,7 +1077,7 @@
                 }
 
                 mCopiesEditText.setError(null);
-                PrintSpoolerService.peekInstance().setPrintJobCopiesNoPersistence(
+                mSpoolerProvider.getSpooler().setPrintJobCopiesNoPersistence(
                         mPrintJobId, copies);
                 updateUi();
 
@@ -1145,6 +1169,10 @@
         private boolean mFavoritePrinterSelected;
 
         public Editor() {
+            showUi(UI_EDITING_PRINT_JOB, null);
+        }
+
+        public void postCreate() {
             // Destination.
             mMediaSizeComparator = new MediaSizeComparator(PrintJobConfigActivity.this);
             mDestinationSpinnerAdapter = new DestinationAdapter();
@@ -1621,7 +1649,7 @@
             if (!TextUtils.equals(mCopiesEditText.getText(), MIN_COPIES_STRING)) {
                 mIgnoreNextCopiesChange = true;
             }
-            PrintSpoolerService.peekInstance().setPrintJobCopiesNoPersistence(
+            mSpoolerProvider.getSpooler().setPrintJobCopiesNoPersistence(
                     mPrintJobId, MIN_COPIES);
 
             // Destination.
@@ -1629,7 +1657,7 @@
             mDestinationSpinner.setDropDownWidth(ViewGroup.LayoutParams.MATCH_PARENT);
             mDestinationSpinner.setAdapter(mDestinationSpinnerAdapter);
             mDestinationSpinner.setOnItemSelectedListener(mOnItemSelectedListener);
-            if (mDestinationSpinnerAdapter.getCount() > 0 && mController.hasStarted()) {
+            if (mDestinationSpinnerAdapter.getCount() > 0) {
                 mIgnoreNextDestinationChange = true;
             }
 
@@ -2089,10 +2117,13 @@
             @Override
             public long getItemId(int position) {
                 if (mPrinters.isEmpty()) {
-                    if (position == 0 && mFakePdfPrinter != null) {
-                        return DEST_ADAPTER_ITEM_ID_SAVE_AS_PDF;
-                    }
-                    if (position == 1) {
+                    if (position == 0) {
+                        if (mFakePdfPrinter != null) {
+                            return DEST_ADAPTER_ITEM_ID_SAVE_AS_PDF;
+                        } else {
+                            return DEST_ADAPTER_ITEM_ID_ALL_PRINTERS;
+                        }
+                    } else if (position == 1) {
                         return DEST_ADAPTER_ITEM_ID_ALL_PRINTERS;
                     }
                 } else {
@@ -2484,4 +2515,41 @@
             }
         }
     }
+
+    private static final class PrintSpoolerProvider implements ServiceConnection {
+        private final Context mContext;
+        private final Runnable mCallback;
+
+        private PrintSpoolerService mSpooler;
+
+        public PrintSpoolerProvider(Context context, Runnable callback) {
+            mContext = context;
+            mCallback = callback;
+            Intent intent = new Intent(mContext, PrintSpoolerService.class);
+            mContext.bindService(intent, this, 0);
+        }
+
+        public PrintSpoolerService getSpooler() {
+            return mSpooler;
+        }
+
+        public void destroy() {
+            if (mSpooler != null) {
+                mContext.unbindService(this);
+            }
+        }
+
+        @Override
+        public void onServiceConnected(ComponentName name, IBinder service) {
+            mSpooler = ((PrintSpoolerService.PrintSpooler) service).getService();
+            if (mSpooler != null) {
+                mCallback.run();
+            }
+        }
+
+        @Override
+        public void onServiceDisconnected(ComponentName name) {
+            /* do noting - we are in the same process */
+        }
+    }
 }
diff --git a/packages/PrintSpooler/src/com/android/printspooler/PrintSpoolerService.java b/packages/PrintSpooler/src/com/android/printspooler/PrintSpoolerService.java
index e1ddb40..98d00a9 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/PrintSpoolerService.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/PrintSpoolerService.java
@@ -16,18 +16,14 @@
 
 package com.android.printspooler;
 
-import android.app.PendingIntent;
 import android.app.Service;
 import android.content.ComponentName;
 import android.content.Intent;
-import android.content.IntentSender;
 import android.os.AsyncTask;
 import android.os.IBinder;
 import android.os.Message;
 import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
-import android.print.IPrintClient;
-import android.print.IPrintDocumentAdapter;
 import android.print.IPrintSpooler;
 import android.print.IPrintSpoolerCallbacks;
 import android.print.IPrintSpoolerClient;
@@ -50,7 +46,6 @@
 import android.util.Xml;
 
 import com.android.internal.os.HandlerCaller;
-import com.android.internal.os.SomeArgs;
 import com.android.internal.util.FastXmlSerializer;
 
 import libcore.io.IoUtils;
@@ -132,110 +127,7 @@
 
     @Override
     public IBinder onBind(Intent intent) {
-        return new IPrintSpooler.Stub() {
-            @Override
-            public void getPrintJobInfos(IPrintSpoolerCallbacks callback,
-                    ComponentName componentName, int state, int appId, int sequence)
-                    throws RemoteException {
-                List<PrintJobInfo> printJobs = null;
-                try {
-                    printJobs = PrintSpoolerService.this.getPrintJobInfos(
-                            componentName, state, appId);
-                } finally {
-                    callback.onGetPrintJobInfosResult(printJobs, sequence);
-                }
-            }
-
-            @Override
-            public void getPrintJobInfo(PrintJobId printJobId, IPrintSpoolerCallbacks callback,
-                    int appId, int sequence) throws RemoteException {
-                PrintJobInfo printJob = null;
-                try {
-                    printJob = PrintSpoolerService.this.getPrintJobInfo(printJobId, appId);
-                } finally {
-                    callback.onGetPrintJobInfoResult(printJob, sequence);
-                }
-            }
-
-            @SuppressWarnings("deprecation")
-            @Override
-            public void createPrintJob(PrintJobInfo printJob, IPrintClient client,
-                IPrintDocumentAdapter printAdapter) throws RemoteException {
-                PrintSpoolerService.this.createPrintJob(printJob);
-
-                Intent intent = new Intent(printJob.getId().flattenToString());
-                intent.setClass(PrintSpoolerService.this, PrintJobConfigActivity.class);
-                intent.putExtra(PrintJobConfigActivity.EXTRA_PRINT_DOCUMENT_ADAPTER,
-                        printAdapter.asBinder());
-                intent.putExtra(PrintJobConfigActivity.EXTRA_PRINT_JOB, printJob);
-
-                IntentSender sender = PendingIntent.getActivity(
-                        PrintSpoolerService.this, 0, intent, PendingIntent.FLAG_ONE_SHOT
-                        | PendingIntent.FLAG_CANCEL_CURRENT).getIntentSender();
-
-                Message message = mHandlerCaller.obtainMessageO(
-                        HandlerCallerCallback.MSG_ON_PRINT_JOB_STATE_CHANGED,
-                        printJob);
-                mHandlerCaller.executeOrSendMessage(message);
-
-                message = mHandlerCaller.obtainMessageOO(
-                        HandlerCallerCallback.MSG_START_PRINT_JOB_CONFIG_ACTIVITY,
-                        client, sender);
-                mHandlerCaller.executeOrSendMessage(message);
-
-                printJob.setCreationTime(System.currentTimeMillis());
-            }
-
-            @Override
-            public void setPrintJobState(PrintJobId printJobId, int state, String error,
-                    IPrintSpoolerCallbacks callback, int sequece) throws RemoteException {
-                boolean success = false;
-                try {
-                    success = PrintSpoolerService.this.setPrintJobState(
-                            printJobId, state, error);
-                } finally {
-                    callback.onSetPrintJobStateResult(success, sequece);
-                }
-            }
-
-            @Override
-            public void setPrintJobTag(PrintJobId printJobId, String tag,
-                    IPrintSpoolerCallbacks callback, int sequece) throws RemoteException {
-                boolean success = false;
-                try {
-                    success = PrintSpoolerService.this.setPrintJobTag(printJobId, tag);
-                } finally {
-                    callback.onSetPrintJobTagResult(success, sequece);
-                }
-            }
-
-            @Override
-            public void writePrintJobData(ParcelFileDescriptor fd, PrintJobId printJobId) {
-                PrintSpoolerService.this.writePrintJobData(fd, printJobId);
-            }
-
-            @Override
-            public void setClient(IPrintSpoolerClient client) {
-                Message message = mHandlerCaller.obtainMessageO(
-                        HandlerCallerCallback.MSG_SET_CLIENT, client);
-                mHandlerCaller.executeOrSendMessage(message);
-            }
-
-            @Override
-            public void removeObsoletePrintJobs() {
-                PrintSpoolerService.this.removeObsoletePrintJobs();
-            }
-
-            @Override
-            protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
-                PrintSpoolerService.this.dump(fd, writer, args);
-            }
-
-            @Override
-            public void setPrintJobCancelling(PrintJobId printJobId, boolean cancelling) {
-                PrintSpoolerService.this.setPrintJobCancelling(printJobId, cancelling);
-            }
-        };
+        return new PrintSpooler();
     }
 
     @Override
@@ -286,12 +178,11 @@
 
     private final class HandlerCallerCallback implements HandlerCaller.Callback {
         public static final int MSG_SET_CLIENT = 1;
-        public static final int MSG_START_PRINT_JOB_CONFIG_ACTIVITY = 2;
-        public static final int MSG_ON_PRINT_JOB_QUEUED = 3;
-        public static final int MSG_ON_ALL_PRINT_JOBS_FOR_SERIVICE_HANDLED = 4;
-        public static final int MSG_ON_ALL_PRINT_JOBS_HANDLED = 5;
-        public static final int MSG_CHECK_ALL_PRINTJOBS_HANDLED = 6;
-        public static final int MSG_ON_PRINT_JOB_STATE_CHANGED = 7;
+        public static final int MSG_ON_PRINT_JOB_QUEUED = 2;
+        public static final int MSG_ON_ALL_PRINT_JOBS_FOR_SERIVICE_HANDLED = 3;
+        public static final int MSG_ON_ALL_PRINT_JOBS_HANDLED = 4;
+        public static final int MSG_CHECK_ALL_PRINTJOBS_HANDLED = 5;
+        public static final int MSG_ON_PRINT_JOB_STATE_CHANGED = 6;
 
         @Override
         public void executeMessage(Message message) {
@@ -308,18 +199,6 @@
                     }
                 } break;
 
-                case MSG_START_PRINT_JOB_CONFIG_ACTIVITY: {
-                    SomeArgs args = (SomeArgs) message.obj;
-                    IPrintClient client = (IPrintClient) args.arg1;
-                    IntentSender sender = (IntentSender) args.arg2;
-                    args.recycle();
-                    try {
-                        client.startPrintJobConfigActivity(sender);
-                    } catch (RemoteException re) {
-                        Slog.i(LOG_TAG, "Error starting print job config activity!", re);
-                    }
-                } break;
-
                 case MSG_ON_PRINT_JOB_QUEUED: {
                     PrintJobInfo printJob = (PrintJobInfo) message.obj;
                     if (mClient != null) {
@@ -426,6 +305,11 @@
         synchronized (mLock) {
             addPrintJobLocked(printJob);
             setPrintJobState(printJob.getId(), PrintJobInfo.STATE_CREATED, null);
+
+            Message message = mHandlerCaller.obtainMessageO(
+                    HandlerCallerCallback.MSG_ON_PRINT_JOB_STATE_CHANGED,
+                    printJob);
+            mHandlerCaller.executeOrSendMessage(message);
         }
     }
 
@@ -1277,4 +1161,89 @@
             return true;
         }
     }
+
+    final class PrintSpooler extends IPrintSpooler.Stub {
+        @Override
+        public void getPrintJobInfos(IPrintSpoolerCallbacks callback,
+                ComponentName componentName, int state, int appId, int sequence)
+                throws RemoteException {
+            List<PrintJobInfo> printJobs = null;
+            try {
+                printJobs = PrintSpoolerService.this.getPrintJobInfos(
+                        componentName, state, appId);
+            } finally {
+                callback.onGetPrintJobInfosResult(printJobs, sequence);
+            }
+        }
+
+        @Override
+        public void getPrintJobInfo(PrintJobId printJobId, IPrintSpoolerCallbacks callback,
+                int appId, int sequence) throws RemoteException {
+            PrintJobInfo printJob = null;
+            try {
+                printJob = PrintSpoolerService.this.getPrintJobInfo(printJobId, appId);
+            } finally {
+                callback.onGetPrintJobInfoResult(printJob, sequence);
+            }
+        }
+
+        @Override
+        public void createPrintJob(PrintJobInfo printJob) {
+            PrintSpoolerService.this.createPrintJob(printJob);
+        }
+
+        @Override
+        public void setPrintJobState(PrintJobId printJobId, int state, String error,
+                IPrintSpoolerCallbacks callback, int sequece) throws RemoteException {
+            boolean success = false;
+            try {
+                success = PrintSpoolerService.this.setPrintJobState(
+                        printJobId, state, error);
+            } finally {
+                callback.onSetPrintJobStateResult(success, sequece);
+            }
+        }
+
+        @Override
+        public void setPrintJobTag(PrintJobId printJobId, String tag,
+                IPrintSpoolerCallbacks callback, int sequece) throws RemoteException {
+            boolean success = false;
+            try {
+                success = PrintSpoolerService.this.setPrintJobTag(printJobId, tag);
+            } finally {
+                callback.onSetPrintJobTagResult(success, sequece);
+            }
+        }
+
+        @Override
+        public void writePrintJobData(ParcelFileDescriptor fd, PrintJobId printJobId) {
+            PrintSpoolerService.this.writePrintJobData(fd, printJobId);
+        }
+
+        @Override
+        public void setClient(IPrintSpoolerClient client) {
+            Message message = mHandlerCaller.obtainMessageO(
+                    HandlerCallerCallback.MSG_SET_CLIENT, client);
+            mHandlerCaller.executeOrSendMessage(message);
+        }
+
+        @Override
+        public void removeObsoletePrintJobs() {
+            PrintSpoolerService.this.removeObsoletePrintJobs();
+        }
+
+        @Override
+        protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
+            PrintSpoolerService.this.dump(fd, writer, args);
+        }
+
+        @Override
+        public void setPrintJobCancelling(PrintJobId printJobId, boolean cancelling) {
+            PrintSpoolerService.this.setPrintJobCancelling(printJobId, cancelling);
+        }
+
+        public PrintSpoolerService getService() {
+            return PrintSpoolerService.this;
+        }
+    }
 }
diff --git a/services/java/com/android/server/print/PrintManagerService.java b/services/java/com/android/server/print/PrintManagerService.java
index b8e1b04..7538caf 100644
--- a/services/java/com/android/server/print/PrintManagerService.java
+++ b/services/java/com/android/server/print/PrintManagerService.java
@@ -31,10 +31,10 @@
 import android.database.ContentObserver;
 import android.net.Uri;
 import android.os.Binder;
+import android.os.Bundle;
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.UserHandle;
-import android.print.IPrintClient;
 import android.print.IPrintDocumentAdapter;
 import android.print.IPrintJobStateChangeListener;
 import android.print.IPrintManager;
@@ -45,6 +45,7 @@
 import android.print.PrinterId;
 import android.printservice.PrintServiceInfo;
 import android.provider.Settings;
+import android.text.TextUtils;
 import android.util.SparseArray;
 
 import com.android.internal.R;
@@ -96,19 +97,19 @@
     }
 
     @Override
-    public PrintJobInfo print(String printJobName, final IPrintClient client,
-            final IPrintDocumentAdapter documentAdapter, PrintAttributes attributes,
-            int appId, int userId) {
+    public Bundle print(String printJobName, IPrintDocumentAdapter adapter,
+            PrintAttributes attributes, String packageName, int appId, int userId) {
         final int resolvedAppId = resolveCallingAppEnforcingPermissions(appId);
         final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
+        String resolvedPackageName = resolveCallingPackageNameEnforcingSecurity(packageName);
         final UserState userState;
         synchronized (mLock) {
             userState = getOrCreateUserStateLocked(resolvedUserId);
         }
         final long identity = Binder.clearCallingIdentity();
         try {
-            return userState.print(printJobName, client, documentAdapter,
-                    attributes, resolvedAppId);
+            return userState.print(printJobName, adapter, attributes,
+                    resolvedPackageName, resolvedAppId);
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
@@ -605,6 +606,21 @@
                 + "UserHandle.USER_CURRENT or UserHandle.USER_CURRENT_OR_SELF.");
     }
 
+    private String resolveCallingPackageNameEnforcingSecurity(String packageName) {
+        if (TextUtils.isEmpty(packageName)) {
+            return null;
+        }
+        String[] packages = mContext.getPackageManager().getPackagesForUid(
+                Binder.getCallingUid());
+        final int packageCount = packages.length;
+        for (int i = 0; i < packageCount; i++) {
+            if (packageName.equals(packages[i])) {
+                return packageName;
+            }
+        }
+        return null;
+    }
+
     private void showEnableInstalledPrintServiceNotification(ComponentName component,
             String label) {
         Intent intent = new Intent(Settings.ACTION_PRINT_SETTINGS);
diff --git a/services/java/com/android/server/print/RemotePrintSpooler.java b/services/java/com/android/server/print/RemotePrintSpooler.java
index 4866f57..ffe9806 100644
--- a/services/java/com/android/server/print/RemotePrintSpooler.java
+++ b/services/java/com/android/server/print/RemotePrintSpooler.java
@@ -26,8 +26,6 @@
 import android.os.RemoteException;
 import android.os.SystemClock;
 import android.os.UserHandle;
-import android.print.IPrintClient;
-import android.print.IPrintDocumentAdapter;
 import android.print.IPrintSpooler;
 import android.print.IPrintSpoolerCallbacks;
 import android.print.IPrintSpoolerClient;
@@ -130,15 +128,14 @@
         return null;
     }
 
-    public final void createPrintJob(PrintJobInfo printJob, IPrintClient client,
-            IPrintDocumentAdapter documentAdapter) {
+    public final void createPrintJob(PrintJobInfo printJob) {
         throwIfCalledOnMainThread();
         synchronized (mLock) {
             throwIfDestroyedLocked();
             mCanUnbind = false;
         }
         try {
-            getRemoteInstanceLazy().createPrintJob(printJob, client, documentAdapter);
+            getRemoteInstanceLazy().createPrintJob(printJob);
         } catch (RemoteException re) {
             Slog.e(LOG_TAG, "Error creating print job.", re);
         } catch (TimeoutException te) {
diff --git a/services/java/com/android/server/print/UserState.java b/services/java/com/android/server/print/UserState.java
index b6c7853..1b373ed 100644
--- a/services/java/com/android/server/print/UserState.java
+++ b/services/java/com/android/server/print/UserState.java
@@ -16,16 +16,20 @@
 
 package com.android.server.print;
 
+import android.app.PendingIntent;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.content.IntentSender;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ParceledListSlice;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
+import android.net.Uri;
 import android.os.AsyncTask;
 import android.os.Binder;
+import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.IBinder.DeathRecipient;
@@ -33,7 +37,6 @@
 import android.os.Message;
 import android.os.RemoteCallbackList;
 import android.os.RemoteException;
-import android.print.IPrintClient;
 import android.print.IPrintDocumentAdapter;
 import android.print.IPrintJobStateChangeListener;
 import android.print.IPrinterDiscoveryObserver;
@@ -44,6 +47,7 @@
 import android.print.PrinterId;
 import android.print.PrinterInfo;
 import android.printservice.PrintServiceInfo;
+import android.provider.DocumentsContract;
 import android.provider.Settings;
 import android.text.TextUtils;
 import android.text.TextUtils.SimpleStringSplitter;
@@ -158,9 +162,9 @@
         mSpooler.removeObsoletePrintJobs();
     }
 
-    public PrintJobInfo print(String printJobName, final IPrintClient client,
-            final IPrintDocumentAdapter documentAdapter, PrintAttributes attributes,
-            int appId) {
+    @SuppressWarnings("deprecation")
+    public Bundle print(String printJobName, IPrintDocumentAdapter adapter,
+            PrintAttributes attributes, String packageName, int appId) {
         // Create print job place holder.
         final PrintJobInfo printJob = new PrintJobInfo();
         printJob.setId(new PrintJobId());
@@ -169,9 +173,10 @@
         printJob.setAttributes(attributes);
         printJob.setState(PrintJobInfo.STATE_CREATED);
         printJob.setCopies(1);
+        printJob.setCreationTime(System.currentTimeMillis());
 
         // Track this job so we can forget it when the creator dies.
-        if (!mPrintJobForAppCache.onPrintJobCreated(client.asBinder(), appId,
+        if (!mPrintJobForAppCache.onPrintJobCreated(adapter.asBinder(), appId,
                 printJob)) {
             // Not adding a print job means the client is dead - done.
             return null;
@@ -181,12 +186,31 @@
         new AsyncTask<Void, Void, Void>() {
             @Override
             protected Void doInBackground(Void... params) {
-                mSpooler.createPrintJob(printJob, client, documentAdapter);
+                mSpooler.createPrintJob(printJob);
                 return null;
             }
         }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[]) null);
 
-        return printJob;
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            Intent intent = new Intent(PrintManager.ACTION_PRINT_DIALOG);
+            intent.setData(Uri.fromParts("printjob", printJob.getId().flattenToString(), null));
+            intent.putExtra(PrintManager.EXTRA_PRINT_DOCUMENT_ADAPTER, adapter.asBinder());
+            intent.putExtra(PrintManager.EXTRA_PRINT_JOB, printJob);
+            intent.putExtra(DocumentsContract.EXTRA_PACKAGE_NAME, packageName);
+
+            IntentSender intentSender = PendingIntent.getActivity(
+                    mContext, 0, intent, PendingIntent.FLAG_ONE_SHOT
+                    | PendingIntent.FLAG_CANCEL_CURRENT).getIntentSender();
+
+            Bundle result = new Bundle();
+            result.putParcelable(PrintManager.EXTRA_PRINT_JOB, printJob);
+            result.putParcelable(PrintManager.EXTRA_PRINT_DIALOG_INTENT, intentSender);
+
+            return result;
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
     }
 
     public List<PrintJobInfo> getPrintJobInfos(int appId) {