summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.mk1
-rw-r--r--CleanSpec.mk2
-rw-r--r--core/java/android/print/IPrintManager.aidl7
-rw-r--r--core/java/android/print/IPrintSpooler.aidl5
-rw-r--r--core/java/android/print/PrintManager.java101
-rw-r--r--packages/PrintSpooler/AndroidManifest.xml7
-rw-r--r--packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java160
-rw-r--r--packages/PrintSpooler/src/com/android/printspooler/PrintSpoolerService.java223
-rw-r--r--services/java/com/android/server/print/PrintManagerService.java28
-rw-r--r--services/java/com/android/server/print/RemotePrintSpooler.java7
-rw-r--r--services/java/com/android/server/print/UserState.java38
11 files changed, 333 insertions, 246 deletions
diff --git a/Android.mk b/Android.mk
index 0957faeba4b3..166db4ee016b 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 758273b78f7e..cfa8be9a13c7 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 3bd515b810df..8fa7ab90ebad 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<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 5f06b834ade1..7b2cf253d56a 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 1cb4e8d6e651..1233da2183a7 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.
+ * <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 @@ public final class PrintManager {
private final int mAppId;
- private final PrintClient mPrintClient;
-
private final Handler mHandler;
private Map<PrintJobStateChangeListener, PrintJobStateChangeListenerWrapper> 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<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 1e6954e40d40..7eea3e919a20 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 2922dd1e9535..007d9c0a937f 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java
@@ -19,9 +19,11 @@ package com.android.printspooler;
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.PrintManager;
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;
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 android.widget.TextView;
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.concurrent.atomic.AtomicInteger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import libcore.io.IoUtils;
-
/**
* Activity for configuring a print job.
*/
@@ -111,9 +114,6 @@ public class PrintJobConfigActivity extends Activity {
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 @@ public class PrintJobConfigActivity extends Activity {
private Dialog mGeneratingPrintJobDialog;
+ private PrintSpoolerProvider mSpoolerProvider;
+
+ private String mCallingPackageName;
+
@Override
protected void onCreate(Bundle bundle) {
super.onCreate(bundle);
@@ -185,13 +189,13 @@ public class PrintJobConfigActivity extends Activity {
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 @@ public class PrintJobConfigActivity extends Activity {
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 @@ public class PrintJobConfigActivity extends Activity {
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 @@ public class PrintJobConfigActivity extends Activity {
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 @@ public class PrintJobConfigActivity extends Activity {
mGeneratingPrintJobDialog.dismiss();
mGeneratingPrintJobDialog = null;
}
+ mSpoolerProvider.destroy();
super.onDestroy();
}
@@ -367,7 +385,7 @@ public class PrintJobConfigActivity extends Activity {
// 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 @@ public class PrintJobConfigActivity extends Activity {
if (infoChanged) {
mDocument.info = info;
// Set the info.
- PrintSpoolerService.peekInstance().setPrintJobPrintDocumentInfoNoPersistence(
+ mSpoolerProvider.getSpooler().setPrintJobPrintDocumentInfoNoPersistence(
mPrintJobId, info);
}
@@ -420,7 +438,7 @@ public class PrintJobConfigActivity extends Activity {
// 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 @@ public class PrintJobConfigActivity extends Activity {
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 @@ public class PrintJobConfigActivity extends Activity {
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 @@ public class PrintJobConfigActivity extends Activity {
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 @@ public class PrintJobConfigActivity extends Activity {
// 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 @@ public class PrintJobConfigActivity extends Activity {
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 @@ public class PrintJobConfigActivity extends Activity {
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 @@ public class PrintJobConfigActivity extends Activity {
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 @@ 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 e1ddb4011fab..98d00a92d756 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<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 @@ 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<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 b8e1b0404f3c..7538caf2f8cb 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 4866f5792c38..ffe9806a2418 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 b6c7853c1f01..1b373edf5d54 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<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) {