diff --git a/Android.mk b/Android.mk index 0957faeba4b38..166db4ee016bb 100644 --- a/Android.mk +++ b/Android.mk @@ -165,7 +165,6 @@ LOCAL_SRC_FILES += \ 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 758273b78f7eb..cfa8be9a13c72 100644 --- a/CleanSpec.mk +++ b/CleanSpec.mk @@ -183,6 +183,8 @@ $(call add-clean-step, rm -f $(PRODUCT_OUT)/system/media/video/*) $(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 3bd515b810dfe..8fa7ab90ebad5 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 @@ import android.printservice.PrintServiceInfo; interface IPrintManager { List 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 5f06b834ade11..7b2cf253d56a1 100644 --- a/core/java/android/print/IPrintSpooler.aidl +++ b/core/java/android/print/IPrintSpooler.aidl @@ -18,8 +18,6 @@ package android.print; 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 @@ oneway interface IPrintSpooler { 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 1cb4e8d6e651b..1233da2183a7f 100644 --- a/core/java/android/print/PrintManager.java +++ b/core/java/android/print/PrintManager.java @@ -60,8 +60,47 @@ public final class PrintManager { 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. + *

+ * Type: {@link android.content.IntentSender} + *

+ * + * @hide + */ + public static final String EXTRA_PRINT_DIALOG_INTENT = + "android.print.intent.extra.EXTRA_PRINT_DIALOG_INTENT"; + + /** + * Extra with a print job. + *

+ * Type: {@link android.print.PrintJobInfo} + *

+ * + * @hide + */ + public static final String EXTRA_PRINT_JOB = + "android.print.intent.extra.EXTRA_PRINT_JOB"; + + /** + * Extra with the print document adapter to be printed. + *

+ * Type: {@link android.print.IPrintDocumentAdapter} + *

+ * + * @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 @@ public final class PrintManager { private final int mAppId; - private final PrintClient mPrintClient; - private final Handler mHandler; private Map mPrintJobStateChangeListeners; @@ -103,24 +140,10 @@ public final class PrintManager { 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 @@ public final class PrintManager { PrintJobId printJobId = (PrintJobId) args.arg2; args.recycle(); listener.onPrintJobStateChanged(printJobId); - } - break; + } break; } } }; @@ -279,10 +301,20 @@ public final class PrintManager { 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 @@ public final class PrintManager { return new PrinterDiscoverySession(mService, mContext, mUserId); } - private static final class PrintClient extends IPrintClient.Stub { - - private final WeakReference mWeakPrintManager; - - public PrintClient(PrintManager manager) { - mWeakPrintManager = new WeakReference(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 1e6954e40d400..7eea3e919a20c 100644 --- a/packages/PrintSpooler/AndroidManifest.xml +++ b/packages/PrintSpooler/AndroidManifest.xml @@ -58,8 +58,13 @@ + + + + + > mMediaSizeSpinnerAdapter; + private ArrayAdapter> mMediaSizeSpinnerAdapter; private Spinner mColorModeSpinner; - private final ArrayAdapter> mColorModeSpinnerAdapter; + private ArrayAdapter> mColorModeSpinnerAdapter; private Spinner mOrientationSpinner; - private final ArrayAdapter> mOrientationSpinnerAdapter; + private ArrayAdapter> mOrientationSpinnerAdapter; private Spinner mRangeOptionsSpinner; - private final ArrayAdapter> mRangeOptionsSpinnerAdapter; + private ArrayAdapter> mRangeOptionsSpinnerAdapter; - private final SimpleStringSplitter mStringCommaSplitter = + private SimpleStringSplitter mStringCommaSplitter = new SimpleStringSplitter(','); private View mContentContainer; @@ -814,7 +833,7 @@ public class PrintJobConfigActivity extends Activity { private PrinterInfo mCurrentPrinter; - private final MediaSizeComparator mMediaSizeComparator; + private MediaSizeComparator mMediaSizeComparator; private final OnItemSelectedListener mOnItemSelectedListener = new AdapterView.OnItemSelectedListener() { @@ -826,6 +845,11 @@ public class PrintJobConfigActivity extends Activity { return; } + if (position == AdapterView.INVALID_POSITION) { + updateUi(); + return; + } + if (id == DEST_ADAPTER_ITEM_ID_ALL_PRINTERS) { startSelectPrinterActivity(); return; @@ -836,7 +860,7 @@ public class PrintJobConfigActivity extends Activity { mCurrentPrinter = (PrinterInfo) mDestinationSpinnerAdapter .getItem(position); - PrintSpoolerService.peekInstance().setPrintJobPrinterNoPersistence( + mSpoolerProvider.getSpooler().setPrintJobPrinterNoPersistence( mPrintJobId, mCurrentPrinter); if (mCurrentPrinter.getStatus() == PrinterInfo.STATUS_UNAVAILABLE) { @@ -1053,7 +1077,7 @@ public class PrintJobConfigActivity extends Activity { } mCopiesEditText.setError(null); - PrintSpoolerService.peekInstance().setPrintJobCopiesNoPersistence( + mSpoolerProvider.getSpooler().setPrintJobCopiesNoPersistence( mPrintJobId, copies); updateUi(); @@ -1145,6 +1169,10 @@ public class PrintJobConfigActivity extends Activity { 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 @@ public class PrintJobConfigActivity extends Activity { if (!TextUtils.equals(mCopiesEditText.getText(), MIN_COPIES_STRING)) { mIgnoreNextCopiesChange = true; } - PrintSpoolerService.peekInstance().setPrintJobCopiesNoPersistence( + mSpoolerProvider.getSpooler().setPrintJobCopiesNoPersistence( mPrintJobId, MIN_COPIES); // Destination. @@ -1629,7 +1657,7 @@ public class PrintJobConfigActivity extends Activity { 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 @@ public class PrintJobConfigActivity extends Activity { @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 @@ public class PrintJobConfigActivity extends Activity { } } } + + 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 e1ddb4011fabd..98d00a92d7561 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.Slog; 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 @@ public final class PrintSpoolerService extends Service { @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 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 @@ public final class PrintSpoolerService extends Service { 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 @@ public final class PrintSpoolerService extends Service { } } 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 @@ public final class PrintSpoolerService extends Service { 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 @@ public final class PrintSpoolerService extends Service { 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 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 b8e1b0404f3c5..7538caf2f8cb5 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.content.pm.ServiceInfo; 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.PrintJobInfo; 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 @@ public final class PrintManagerService extends IPrintManager.Stub { } @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 @@ public final class PrintManagerService extends IPrintManager.Stub { + "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 4866f5792c38a..ffe9806a24180 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.ParcelFileDescriptor; 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 @@ final class RemotePrintSpooler { 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 b6c7853c1f010..1b373edf5d54f 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.Looper; 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.PrintManager; 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 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks { 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 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks { 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 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks { new AsyncTask() { @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 getPrintJobInfos(int appId) {