diff options
Diffstat (limited to 'core')
-rw-r--r-- | core/java/android/print/IPrintManager.aidl | 4 | ||||
-rw-r--r-- | core/java/android/print/PrintDocumentAdapter.java | 18 | ||||
-rw-r--r-- | core/java/android/print/PrintDocumentInfo.java | 30 | ||||
-rw-r--r-- | core/java/android/print/PrintFileDocumentAdapter.java | 10 | ||||
-rw-r--r-- | core/java/android/print/PrintJobInfo.java | 62 | ||||
-rw-r--r-- | core/java/android/print/PrintManager.java | 13 | ||||
-rw-r--r-- | core/java/android/print/PrinterDiscoverySession.java | 35 | ||||
-rw-r--r-- | core/java/android/print/pdf/PrintedPdfDocument.java | 5 | ||||
-rw-r--r-- | core/java/android/printservice/IPrintService.aidl | 4 | ||||
-rw-r--r-- | core/java/android/printservice/PrintDocument.java | 11 | ||||
-rw-r--r-- | core/java/android/printservice/PrintJob.java | 71 | ||||
-rw-r--r-- | core/java/android/printservice/PrintService.java | 44 | ||||
-rw-r--r-- | core/java/android/printservice/PrinterDiscoverySession.java | 100 | ||||
-rw-r--r-- | core/res/AndroidManifest.xml | 11 | ||||
-rw-r--r-- | core/res/res/values/strings.xml | 16 | ||||
-rwxr-xr-x | core/res/res/values/symbols.xml | 1 |
16 files changed, 327 insertions, 108 deletions
diff --git a/core/java/android/print/IPrintManager.aidl b/core/java/android/print/IPrintManager.aidl index 3bfd9a1..fb6bb2e 100644 --- a/core/java/android/print/IPrintManager.aidl +++ b/core/java/android/print/IPrintManager.aidl @@ -41,7 +41,9 @@ interface IPrintManager { void startPrinterDiscovery(in IPrinterDiscoveryObserver observer, in List<PrinterId> priorityList, int userId); void stopPrinterDiscovery(in IPrinterDiscoveryObserver observer, int userId); - void requestPrinterUpdate(in PrinterId printerId, int userId); + void validatePrinters(in List<PrinterId> printerIds, int userId); + void startPrinterStateTracking(in PrinterId printerId, int userId); + void stopPrinterStateTracking(in PrinterId printerId, int userId); void destroyPrinterDiscoverySession(in IPrinterDiscoveryObserver observer, int userId); } diff --git a/core/java/android/print/PrintDocumentAdapter.java b/core/java/android/print/PrintDocumentAdapter.java index 8a64e85..33b4aad 100644 --- a/core/java/android/print/PrintDocumentAdapter.java +++ b/core/java/android/print/PrintDocumentAdapter.java @@ -18,8 +18,8 @@ package android.print; import android.os.Bundle; import android.os.CancellationSignal; +import android.os.ParcelFileDescriptor; -import java.io.FileDescriptor; import java.util.List; /** @@ -41,7 +41,7 @@ import java.util.List; * <li> * After every call to {@link #onLayout(PrintAttributes, PrintAttributes, * CancellationSignal, LayoutResultCallback, Bundle)}, you may get a call to - * {@link #onWrite(PageRange[], FileDescriptor, CancellationSignal, WriteResultCallback)} + * {@link #onWrite(PageRange[], ParcelFileDescriptor, CancellationSignal, WriteResultCallback)} * asking you to write a PDF file with the content for specific pages. * </li> * <li> @@ -64,7 +64,7 @@ import java.util.List; * PrintAttributes, CancellationSignal, LayoutResultCallback, Bundle)} on * the UI thread (assuming onStart initializes resources needed for layout). * This will ensure that the UI does not change while you are laying out the - * printed content. Then you can handle {@link #onWrite(PageRange[], FileDescriptor, + * printed content. Then you can handle {@link #onWrite(PageRange[], ParcelFileDescriptor, * CancellationSignal, WriteResultCallback)} and {@link #onFinish()} on another * thread. This will ensure that the UI is frozen for the minimal amount of * time. Also this assumes that you will generate the printed content in @@ -150,10 +150,10 @@ public abstract class PrintDocumentAdapter { * from of a PDF file to the given file descriptor. This method is invoked * on the main thread. *<p> - * After you are done writing, you should <strong>not</strong> close the - * file descriptor, rather you must invoke: {@link WriteResultCallback - * #onWriteFinished(List)}, if writing completed successfully; or {@link - * WriteResultCallback#onWriteFailed(CharSequence)}, if an error occurred. + * After you are done writing, you should close the file descriptor and + * invoke {@link WriteResultCallback #onWriteFinished(List)}, if writing + * completed successfully; or {@link WriteResultCallback#onWriteFailed( + * CharSequence)}, if an error occurred. * </p> * <p> * <strong>Note:</strong> If the printed content is large, it is a good @@ -171,7 +171,7 @@ public abstract class PrintDocumentAdapter { * @see WriteResultCallback * @see CancellationSignal */ - public abstract void onWrite(PageRange[] pages, FileDescriptor destination, + public abstract void onWrite(PageRange[] pages, ParcelFileDescriptor destination, CancellationSignal cancellationSignal, WriteResultCallback callback); /** @@ -185,7 +185,7 @@ public abstract class PrintDocumentAdapter { /** * Base class for implementing a callback for the result of {@link - * PrintDocumentAdapter#onWrite(PageRange[], FileDescriptor, CancellationSignal, + * PrintDocumentAdapter#onWrite(PageRange[], ParcelFileDescriptor, CancellationSignal, * WriteResultCallback)}. */ public static abstract class WriteResultCallback { diff --git a/core/java/android/print/PrintDocumentInfo.java b/core/java/android/print/PrintDocumentInfo.java index b32961b..f2b91ae 100644 --- a/core/java/android/print/PrintDocumentInfo.java +++ b/core/java/android/print/PrintDocumentInfo.java @@ -60,6 +60,7 @@ public final class PrintDocumentInfo implements Parcelable { private int mColorMode; private Margins mMargins; private MediaSize mMediaSize; + private long mDataSize; /** * Creates a new instance. @@ -82,6 +83,7 @@ public final class PrintDocumentInfo implements Parcelable { mColorMode = prototype.mColorMode; mMargins = prototype.mMargins; mMediaSize = prototype.mMediaSize; + mDataSize = prototype.mDataSize; } /** @@ -98,6 +100,7 @@ public final class PrintDocumentInfo implements Parcelable { mColorMode = parcel.readInt(); mMargins = Margins.createFromParcel(parcel); mMediaSize = MediaSize.createFromParcel(parcel); + mDataSize = parcel.readLong(); } /** @@ -188,6 +191,26 @@ public final class PrintDocumentInfo implements Parcelable { return mMediaSize; } + /** + * Gets the document data size in bytes. + * + * @return The data size. + */ + public long getDataSize() { + return mDataSize; + } + + /** + * Sets the document data size in bytes. + * + * @param dataSize The data size. + * + * @hide + */ + public void setDataSize(long dataSize) { + mDataSize = dataSize; + } + @Override public int describeContents() { return 0; @@ -203,6 +226,7 @@ public final class PrintDocumentInfo implements Parcelable { parcel.writeInt(mColorMode); mMargins.writeToParcel(parcel); mMediaSize.writeToParcel(parcel); + parcel.writeLong(mDataSize); } @Override @@ -217,6 +241,8 @@ public final class PrintDocumentInfo implements Parcelable { result = prime * result + mColorMode; result = prime * result + (mMargins != null ? mMargins.hashCode() : 0); result = prime * result + (mMediaSize != null ? mMediaSize.hashCode() : 0); + result = prime * result + (int) mDataSize; + result = prime * result + (int) mDataSize >> 32; return result; } @@ -264,6 +290,9 @@ public final class PrintDocumentInfo implements Parcelable { } else if (!mMediaSize.equals(other.mMediaSize)) { return false; } + if (mDataSize != other.mDataSize) { + return false; + } return true; } @@ -279,6 +308,7 @@ public final class PrintDocumentInfo implements Parcelable { builder.append(", colorMode=").append(PrintAttributes.colorModeToString(mColorMode)); builder.append(", margins=").append(mMargins); builder.append(", mediaSize=").append(mMediaSize); + builder.append(", size=").append(mDataSize); builder.append("}"); return builder.toString(); } diff --git a/core/java/android/print/PrintFileDocumentAdapter.java b/core/java/android/print/PrintFileDocumentAdapter.java index dbc8b6f..b905396 100644 --- a/core/java/android/print/PrintFileDocumentAdapter.java +++ b/core/java/android/print/PrintFileDocumentAdapter.java @@ -21,6 +21,7 @@ import android.os.AsyncTask; import android.os.Bundle; import android.os.CancellationSignal; import android.os.CancellationSignal.OnCancelListener; +import android.os.ParcelFileDescriptor; import android.util.Log; import com.android.internal.R; @@ -28,7 +29,6 @@ import com.android.internal.R; import libcore.io.IoUtils; import java.io.File; -import java.io.FileDescriptor; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; @@ -81,7 +81,7 @@ public class PrintFileDocumentAdapter extends PrintDocumentAdapter { } @Override - public void onWrite(PageRange[] pages, FileDescriptor destination, + public void onWrite(PageRange[] pages, ParcelFileDescriptor destination, CancellationSignal cancellationSignal, WriteResultCallback callback) { mWriteFileAsyncTask = new WriteFileAsyncTask(destination, cancellationSignal, callback); mWriteFileAsyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, @@ -90,13 +90,13 @@ public class PrintFileDocumentAdapter extends PrintDocumentAdapter { private final class WriteFileAsyncTask extends AsyncTask<Void, Void, Void> { - private final FileDescriptor mDestination; + private final ParcelFileDescriptor mDestination; private final WriteResultCallback mResultCallback; private final CancellationSignal mCancellationSignal; - public WriteFileAsyncTask(FileDescriptor destination, + public WriteFileAsyncTask(ParcelFileDescriptor destination, CancellationSignal cancellationSignal, WriteResultCallback callback) { mDestination = destination; mResultCallback = callback; @@ -112,7 +112,7 @@ public class PrintFileDocumentAdapter extends PrintDocumentAdapter { @Override protected Void doInBackground(Void... params) { InputStream in = null; - OutputStream out = new FileOutputStream(mDestination); + OutputStream out = new FileOutputStream(mDestination.getFileDescriptor()); final byte[] buffer = new byte[8192]; try { in = new FileInputStream(mFile); diff --git a/core/java/android/print/PrintJobInfo.java b/core/java/android/print/PrintJobInfo.java index 602f3c1..b919ad6 100644 --- a/core/java/android/print/PrintJobInfo.java +++ b/core/java/android/print/PrintJobInfo.java @@ -44,6 +44,13 @@ public final class PrintJobInfo implements Parcelable { public static final int STATE_ANY_VISIBLE_TO_CLIENTS = -2; /** + * Constant for matching any active print job state. + * + * @hide + */ + public static final int STATE_ANY_ACTIVE = -3; + + /** * Print job state: The print job is being created but not yet * ready to be printed. * <p> @@ -55,7 +62,7 @@ public final class PrintJobInfo implements Parcelable { public static final int STATE_CREATED = 1; /** - * Print job status: The print jobs is created, it is ready + * Print job state: The print jobs is created, it is ready * to be printed and should be processed. * <p> * Next valid states: {@link #STATE_STARTED}, {@link #STATE_FAILED}, @@ -65,40 +72,49 @@ public final class PrintJobInfo implements Parcelable { public static final int STATE_QUEUED = 2; /** - * Print job status: The print job is being printed. + * Print job state: The print job is being printed. * <p> * Next valid states: {@link #STATE_COMPLETED}, {@link #STATE_FAILED}, - * {@link #STATE_CANCELED} + * {@link #STATE_CANCELED}, {@link #STATE_BLOCKED} * </p> */ public static final int STATE_STARTED = 3; /** - * Print job status: The print job was successfully printed. + * Print job state: The print job is blocked. + * <p> + * Next valid states: {@link #STATE_FAILED}, {@link #STATE_CANCELED}, + * {@link #STATE_STARTED} + * </p> + */ + public static final int STATE_BLOCKED = 4; + + /** + * Print job state: The print job was successfully printed. * This is a terminal state. * <p> * Next valid states: None * </p> */ - public static final int STATE_COMPLETED = 4; + public static final int STATE_COMPLETED = 5; /** - * Print job status: The print job was printing but printing failed. + * Print job state: The print job was printing but printing failed. * This is a terminal state. * <p> * Next valid states: None * </p> */ - public static final int STATE_FAILED = 5; + public static final int STATE_FAILED = 6; /** - * Print job status: The print job was canceled. + * Print job state: The print job was canceled. * This is a terminal state. * <p> * Next valid states: None * </p> */ - public static final int STATE_CANCELED = 6; + public static final int STATE_CANCELED = 7; /** The unique print job id. */ private int mId; @@ -127,8 +143,8 @@ public final class PrintJobInfo implements Parcelable { /** How many copies to print. */ private int mCopies; - /** Failure reason if this job failed. */ - private String mFailureReason; + /** Reason for the print job being in its current state. */ + private String mStateReason; /** The pages to print */ private PageRange[] mPageRanges; @@ -155,7 +171,7 @@ public final class PrintJobInfo implements Parcelable { mUserId = other.mUserId; mTag = other.mTag; mCopies = other.mCopies; - mFailureReason = other.mFailureReason; + mStateReason = other.mStateReason; mPageRanges = other.mPageRanges; mAttributes = other.mAttributes; mDocumentInfo = other.mDocumentInfo; @@ -171,7 +187,7 @@ public final class PrintJobInfo implements Parcelable { mUserId = parcel.readInt(); mTag = parcel.readString(); mCopies = parcel.readInt(); - mFailureReason = parcel.readString(); + mStateReason = parcel.readString(); if (parcel.readInt() == 1) { Parcelable[] parcelables = parcel.readParcelableArray(null); mPageRanges = new PageRange[parcelables.length]; @@ -377,25 +393,27 @@ public final class PrintJobInfo implements Parcelable { } /** - * The failure reason if this print job failed. + * Gets the reason for the print job being in the current state. * - * @return The failure reason. + * @return The reason, or null if there is no reason or the + * reason is unknown. * * @hide */ - public String getFailureReason() { - return mFailureReason; + public String getStateReason() { + return mStateReason; } /** - * The failure reason if this print job failed. + * Sets the reason for the print job being in the current state. * - * @param failureReason The failure reason. + * @param stateReason The reason, or null if there is no reason + * or the reason is unknown. * * @hide */ - public void setFailureReason(String failureReason) { - mFailureReason = failureReason; + public void setStateReason(String stateReason) { + mStateReason = stateReason; } /** @@ -476,7 +494,7 @@ public final class PrintJobInfo implements Parcelable { parcel.writeInt(mUserId); parcel.writeString(mTag); parcel.writeInt(mCopies); - parcel.writeString(mFailureReason); + parcel.writeString(mStateReason); if (mPageRanges != null) { parcel.writeInt(1); parcel.writeParcelableArray(mPageRanges, flags); diff --git a/core/java/android/print/PrintManager.java b/core/java/android/print/PrintManager.java index d3e35c3..6e32c05 100644 --- a/core/java/android/print/PrintManager.java +++ b/core/java/android/print/PrintManager.java @@ -36,7 +36,6 @@ import com.android.internal.os.SomeArgs; import libcore.io.IoUtils; import java.io.File; -import java.io.FileDescriptor; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Collections; @@ -163,7 +162,7 @@ public final class PrintManager { * @param pdfFile The PDF file to print. * @param documentInfo Information about the printed document. * @param attributes The default print job attributes. - * @return The created print job. + * @return The created print job on success or null on failure. * * @see PrintJob */ @@ -181,7 +180,7 @@ public final class PrintManager { * @param printJobName A name for the new print job. * @param documentAdapter An adapter that emits the document to print. * @param attributes The default print job attributes. - * @return The created print job. + * @return The created print job on success or null on failure. * * @see PrintJob */ @@ -279,7 +278,7 @@ public final class PrintManager { } SomeArgs args = SomeArgs.obtain(); args.arg1 = pages; - args.arg2 = fd.getFileDescriptor(); + args.arg2 = fd; args.arg3 = callback; args.argi1 = sequence; mHandler.removeMessages(MyHandler.MSG_WRITE); @@ -342,7 +341,7 @@ public final class PrintManager { case MSG_WRITE: { SomeArgs args = (SomeArgs) message.obj; PageRange[] pages = (PageRange[]) args.arg1; - FileDescriptor fd = (FileDescriptor) args.arg2; + ParcelFileDescriptor fd = (ParcelFileDescriptor) args.arg2; IWriteResultCallback callback = (IWriteResultCallback) args.arg3; final int sequence = args.argi1; args.recycle(); @@ -428,12 +427,12 @@ public final class PrintManager { } private final class MyWriteResultCallback extends WriteResultCallback { - private FileDescriptor mFd; + private ParcelFileDescriptor mFd; private int mSequence; private IWriteResultCallback mCallback; public MyWriteResultCallback(IWriteResultCallback callback, - FileDescriptor fd, int sequence) { + ParcelFileDescriptor fd, int sequence) { mFd = fd; mSequence = sequence; mCallback = callback; diff --git a/core/java/android/print/PrinterDiscoverySession.java b/core/java/android/print/PrinterDiscoverySession.java index 8fbdd9c..46f0bef 100644 --- a/core/java/android/print/PrinterDiscoverySession.java +++ b/core/java/android/print/PrinterDiscoverySession.java @@ -74,6 +74,7 @@ public final class PrinterDiscoverySession { public final void startPrinterDisovery(List<PrinterId> priorityList) { if (isDestroyed()) { Log.w(LOG_TAG, "Ignoring start printers dsicovery - session destroyed"); + return; } if (!mIsPrinterDiscoveryStarted) { mIsPrinterDiscoveryStarted = true; @@ -88,6 +89,7 @@ public final class PrinterDiscoverySession { public final void stopPrinterDiscovery() { if (isDestroyed()) { Log.w(LOG_TAG, "Ignoring stop printers discovery - session destroyed"); + return; } if (mIsPrinterDiscoveryStarted) { mIsPrinterDiscoveryStarted = false; @@ -99,14 +101,39 @@ public final class PrinterDiscoverySession { } } - public final void requestPrinterUpdate(PrinterId printerId) { + public final void startPrinterStateTracking(PrinterId printerId) { + if (isDestroyed()) { + Log.w(LOG_TAG, "Ignoring start printer state tracking - session destroyed"); + return; + } + try { + mPrintManager.startPrinterStateTracking(printerId, mUserId); + } catch (RemoteException re) { + Log.e(LOG_TAG, "Error starting printer state tracking", re); + } + } + + public final void stopPrinterStateTracking(PrinterId printerId) { if (isDestroyed()) { - Log.w(LOG_TAG, "Ignoring reqeust printer update - session destroyed"); + Log.w(LOG_TAG, "Ignoring stop printer state tracking - session destroyed"); + return; + } + try { + mPrintManager.stopPrinterStateTracking(printerId, mUserId); + } catch (RemoteException re) { + Log.e(LOG_TAG, "Error stoping printer state tracking", re); + } + } + + public final void validatePrinters(List<PrinterId> printerIds) { + if (isDestroyed()) { + Log.w(LOG_TAG, "Ignoring validate printers - session destroyed"); + return; } try { - mPrintManager.requestPrinterUpdate(printerId, mUserId); + mPrintManager.validatePrinters(printerIds, mUserId); } catch (RemoteException re) { - Log.e(LOG_TAG, "Error requesting printer update", re); + Log.e(LOG_TAG, "Error validating printers", re); } } diff --git a/core/java/android/print/pdf/PrintedPdfDocument.java b/core/java/android/print/pdf/PrintedPdfDocument.java index a3be38b..bee17ef 100644 --- a/core/java/android/print/pdf/PrintedPdfDocument.java +++ b/core/java/android/print/pdf/PrintedPdfDocument.java @@ -111,7 +111,10 @@ public final class PrintedPdfDocument { * @see #finishPage(Page) */ public Page startPage(int pageNumber) { - PageInfo pageInfo = new PageInfo.Builder(mPageSize, 0).create(); + PageInfo pageInfo = new PageInfo + .Builder(mPageSize, 0) + .setContentSize(mContentSize) + .create(); Page page = mDocument.startPage(pageInfo); return page; } diff --git a/core/java/android/printservice/IPrintService.aidl b/core/java/android/printservice/IPrintService.aidl index 2cee1d8..ee36619 100644 --- a/core/java/android/printservice/IPrintService.aidl +++ b/core/java/android/printservice/IPrintService.aidl @@ -33,6 +33,8 @@ oneway interface IPrintService { void createPrinterDiscoverySession(); void startPrinterDiscovery(in List<PrinterId> priorityList); void stopPrinterDiscovery(); - void requestPrinterUpdate(in PrinterId printerId); + void validatePrinters(in List<PrinterId> printerIds); + void startPrinterStateTracking(in PrinterId printerId); + void stopPrinterStateTracking(in PrinterId printerId); void destroyPrinterDiscoverySession(); } diff --git a/core/java/android/printservice/PrintDocument.java b/core/java/android/printservice/PrintDocument.java index 7437dc5..8292cfb 100644 --- a/core/java/android/printservice/PrintDocument.java +++ b/core/java/android/printservice/PrintDocument.java @@ -21,12 +21,15 @@ import android.os.RemoteException; import android.print.PrintDocumentInfo; import android.util.Log; -import java.io.FileDescriptor; import java.io.IOException; /** * This class represents a printed document from the perspective of a print * service. It exposes APIs to query the document and obtain its data. + * <p> + * <strong>Note: </strong> All methods of this class must be executed on the + * main application thread. + * </p> */ public final class PrintDocument { @@ -51,6 +54,7 @@ public final class PrintDocument { * @return The document info. */ public PrintDocumentInfo getInfo() { + PrintService.throwIfNotCalledOnMainThread(); return mInfo; } @@ -64,7 +68,8 @@ public final class PrintDocument { * * @return A file descriptor for reading the data. */ - public FileDescriptor getData() { + public ParcelFileDescriptor getData() { + PrintService.throwIfNotCalledOnMainThread(); ParcelFileDescriptor source = null; ParcelFileDescriptor sink = null; try { @@ -72,7 +77,7 @@ public final class PrintDocument { source = fds[0]; sink = fds[1]; mPrintServiceClient.writePrintJobData(sink, mPrintJobId); - return source.getFileDescriptor(); + return source; } catch (IOException ioe) { Log.e(LOG_TAG, "Error calling getting print job data!", ioe); } catch (RemoteException re) { diff --git a/core/java/android/printservice/PrintJob.java b/core/java/android/printservice/PrintJob.java index d2fbef2..8bae9d6 100644 --- a/core/java/android/printservice/PrintJob.java +++ b/core/java/android/printservice/PrintJob.java @@ -18,6 +18,7 @@ package android.printservice; import android.os.RemoteException; import android.print.PrintJobInfo; +import android.text.TextUtils; import android.util.Log; /** @@ -123,6 +124,21 @@ public final class PrintJob { } /** + * Gets whether this print job is blocked. Such a print job is halted + * due to an abnormal condition and can be started or canceled or failed. + * + * @return Whether the print job is blocked. + * + * @see #start() + * @see #cancel() + * @see #fail(CharSequence) + */ + public boolean isBlocked() { + PrintService.throwIfNotCalledOnMainThread(); + return getInfo().getState() == PrintJobInfo.STATE_BLOCKED; + } + + /** * Gets whether this print job is completed. Such a print job * is successfully printed. This is a final state. * @@ -163,21 +179,49 @@ public final class PrintJob { /** * Starts the print job. You should call this method if {@link - * #isQueued()} returns true and you started printing. + * #isQueued()} or {@link #isBlocked()} returns true and you started + * resumed printing. * - * @return Whether the job as started. + * @return Whether the job was started. * * @see #isQueued() + * @see #isBlocked() */ public boolean start() { PrintService.throwIfNotCalledOnMainThread(); - if (isQueued()) { + final int state = getInfo().getState(); + if (state == PrintJobInfo.STATE_QUEUED + || state == PrintJobInfo.STATE_BLOCKED) { return setState(PrintJobInfo.STATE_STARTED, null); } return false; } /** + * Blocks the print job. You should call this method if {@link + * #isStarted()} or {@link #isBlocked()} returns true and you need + * to block the print job. For example, the user has to add some + * paper to continue printing. To resume the print job call {@link + * #start()}. + * + * @return Whether the job was blocked. + * + * @see #isStarted() + * @see #isBlocked() + */ + public boolean block(String reason) { + PrintService.throwIfNotCalledOnMainThread(); + PrintJobInfo info = getInfo(); + final int state = info.getState(); + if (state == PrintJobInfo.STATE_STARTED + || (state == PrintJobInfo.STATE_BLOCKED + && !TextUtils.equals(info.getStateReason(), reason))) { + return setState(PrintJobInfo.STATE_BLOCKED, reason); + } + return false; + } + + /** * Completes the print job. You should call this method if {@link * #isStarted()} returns true and you are done printing. * @@ -195,8 +239,8 @@ public final class PrintJob { /** * Fails the print job. You should call this method if {@link - * #isQueued()} or {@link #isStarted()} returns true you failed - * while printing. + * #isQueued()} or {@link #isStarted()} or {@link #isBlocked()} + * returns true you failed while printing. * * @param error The human readable, short, and translated reason * for the failure. @@ -204,10 +248,11 @@ public final class PrintJob { * * @see #isQueued() * @see #isStarted() + * @see #isBlocked() */ public boolean fail(String error) { PrintService.throwIfNotCalledOnMainThread(); - if (isQueued() || isStarted()) { + if (!isInImmutableState()) { return setState(PrintJobInfo.STATE_FAILED, error); } return false; @@ -215,18 +260,19 @@ public final class PrintJob { /** * Cancels the print job. You should call this method if {@link - * #isQueued()} or {@link #isStarted()} returns true and you canceled - * the print job as a response to a call to {@link - * PrintService#onRequestCancelPrintJob(PrintJob)}. + * #isQueued()} or {@link #isStarted() or #isBlocked()} returns + * true and you canceled the print job as a response to a call to + * {@link PrintService#onRequestCancelPrintJob(PrintJob)}. * * @return Whether the job is canceled. * * @see #isStarted() * @see #isQueued() + * @see #isBlocked() */ public boolean cancel() { PrintService.throwIfNotCalledOnMainThread(); - if (isQueued() || isStarted()) { + if (!isInImmutableState()) { return setState(PrintJobInfo.STATE_CANCELED, null); } return false; @@ -277,7 +323,8 @@ public final class PrintJob { private boolean isInImmutableState() { final int state = mCachedInfo.getState(); return state == PrintJobInfo.STATE_COMPLETED - || state == PrintJobInfo.STATE_CANCELED; + || state == PrintJobInfo.STATE_CANCELED + || state == PrintJobInfo.STATE_FAILED; } private boolean setState(int state, String error) { @@ -287,7 +334,7 @@ public final class PrintJob { // we may not be able to re-fetch it later if the job gets // removed from the spooler as a result of the state change. mCachedInfo.setState(state); - mCachedInfo.setFailureReason(error); + mCachedInfo.setStateReason(error); return true; } } catch (RemoteException re) { diff --git a/core/java/android/printservice/PrintService.java b/core/java/android/printservice/PrintService.java index f6c0a9a..96552af 100644 --- a/core/java/android/printservice/PrintService.java +++ b/core/java/android/printservice/PrintService.java @@ -314,8 +314,20 @@ public abstract class PrintService extends Service { } @Override - public void requestPrinterUpdate(PrinterId printerId) { - mHandler.obtainMessage(ServiceHandler.MSG_REQUEST_PRINTER_UPDATE, + public void validatePrinters(List<PrinterId> printerIds) { + mHandler.obtainMessage(ServiceHandler.MSG_VALIDATE_PRINTERS, + printerIds).sendToTarget(); + } + + @Override + public void startPrinterStateTracking(PrinterId printerId) { + mHandler.obtainMessage(ServiceHandler.MSG_START_PRINTER_STATE_TRACKING, + printerId).sendToTarget(); + } + + @Override + public void stopPrinterStateTracking(PrinterId printerId) { + mHandler.obtainMessage(ServiceHandler.MSG_STOP_PRINTER_STATE_TRACKING, printerId).sendToTarget(); } @@ -344,10 +356,12 @@ public abstract class PrintService extends Service { public static final int MSG_DESTROY_PRINTER_DISCOVERY_SESSION = 2; public static final int MSG_START_PRINTER_DISCOVERY = 3; public static final int MSG_STOP_PRINTER_DISCOVERY = 4; - public static final int MSG_REQUEST_PRINTER_UPDATE = 5; - public static final int MSG_ON_PRINTJOB_QUEUED = 6; - public static final int MSG_ON_REQUEST_CANCEL_PRINTJOB = 7; - public static final int MSG_SET_CLEINT = 8; + public static final int MSG_VALIDATE_PRINTERS = 5; + public static final int MSG_START_PRINTER_STATE_TRACKING = 6; + public static final int MSG_STOP_PRINTER_STATE_TRACKING = 7; + public static final int MSG_ON_PRINTJOB_QUEUED = 8; + public static final int MSG_ON_REQUEST_CANCEL_PRINTJOB = 9; + public static final int MSG_SET_CLEINT = 10; public ServiceHandler(Looper looper) { super(looper, null, true); @@ -391,10 +405,24 @@ public abstract class PrintService extends Service { } } break; - case MSG_REQUEST_PRINTER_UPDATE: { + case MSG_VALIDATE_PRINTERS: { + if (mDiscoverySession != null) { + List<PrinterId> printerIds = (List<PrinterId>) message.obj; + mDiscoverySession.validatePrinters(printerIds); + } + } break; + + case MSG_START_PRINTER_STATE_TRACKING: { + if (mDiscoverySession != null) { + PrinterId printerId = (PrinterId) message.obj; + mDiscoverySession.startPrinterStateTracking(printerId); + } + } break; + + case MSG_STOP_PRINTER_STATE_TRACKING: { if (mDiscoverySession != null) { PrinterId printerId = (PrinterId) message.obj; - mDiscoverySession.requestPrinterUpdate(printerId); + mDiscoverySession.stopPrinterStateTracking(printerId); } } break; diff --git a/core/java/android/printservice/PrinterDiscoverySession.java b/core/java/android/printservice/PrinterDiscoverySession.java index 8b959a6..1f86ecc 100644 --- a/core/java/android/printservice/PrinterDiscoverySession.java +++ b/core/java/android/printservice/PrinterDiscoverySession.java @@ -53,15 +53,23 @@ import java.util.List; * session. Printers are <strong>not</strong> persisted across sessions. * </p> * <p> - * The system will make a call to - * {@link PrinterDiscoverySession#onRequestPrinterUpdate(PrinterId)} if you - * need to update a given printer. It is possible that you add a printer without + * The system will make a call to {@link #onValidatePrinters(List)} if you + * need to update some printers. It is possible that you add a printer without * specifying its capabilities. This enables you to avoid querying all discovered * printers for their capabilities, rather querying the capabilities of a printer * only if necessary. For example, the system will request that you update a printer - * if it gets selected by the user. If you did not report the printer capabilities - * when adding it, you must do so after the system requests a printer update. - * Otherwise, the printer will be ignored. + * if it gets selected by the user. When validating printers you do not need to + * provide the printers' capabilities but may do so. + * </p> + * <p> + * If the system is interested in being constantly updated for the state of a + * printer you will receive a call to {@link #onStartPrinterStateTracking(PrinterId)} + * after which you will have to do a best effort to keep the system updated for + * changes in the printer state and capabilities. You also <strong>must</strong> + * update the printer capabilities if you did not provide them when adding it, or + * the printer will be ignored. When the system is no longer interested in getting + * updates for a printer you will receive a call to {@link #onStopPrinterStateTracking( + * PrinterId)}. * </p> * <p> * <strong>Note: </strong> All callbacks in this class are executed on the main @@ -115,7 +123,7 @@ public abstract class PrinterDiscoverySession { * the printer that was added but not removed. * <p> * <strong>Note: </strong> Calls to this method after the session is - * destroyed, i.e. after the {@link #onDestroy()} callback, will be ignored. + * destroyed, that is after the {@link #onDestroy()} callback, will be ignored. * </p> * * @return The printers. @@ -139,7 +147,7 @@ public abstract class PrinterDiscoverySession { * times during the life of this session. Duplicates will be ignored. * <p> * <strong>Note: </strong> Calls to this method after the session is - * destroyed, i.e. after the {@link #onDestroy()} callback, will be ignored. + * destroyed, that is after the {@link #onDestroy()} callback, will be ignored. * </p> * * @param printers The printers to add. @@ -218,7 +226,7 @@ public abstract class PrinterDiscoverySession { * call this method multiple times during the lifetime of this session. * <p> * <strong>Note: </strong> Calls to this method after the session is - * destroyed, i.e. after the {@link #onDestroy()} callback, will be ignored. + * destroyed, that is after the {@link #onDestroy()} callback, will be ignored. * </p> * * @param printerIds The ids of the removed printers. @@ -293,7 +301,7 @@ public abstract class PrinterDiscoverySession { * during the lifetime of this session. * <p> * <strong>Note: </strong> Calls to this method after the session is - * destroyed, i.e. after the {@link #onDestroy()} callback, will be ignored. + * destroyed, that is after the {@link #onDestroy()} callback, will be ignored. * </p> * * @param printers The printers to update. @@ -441,7 +449,9 @@ public abstract class PrinterDiscoverySession { * <p> * <strong>Note: </strong>You are also given a list of printers whose availability * has to be checked first. For example, these printers could be the user's favorite - * ones, therefore they have to be verified first. + * ones, therefore they have to be verified first. You do <strong>not need</strong> + * to provide the capabilities of the printers, rather verify whether they exist + * similarly to {@link #onValidatePrinters(List)}. * </p> * * @param priorityList The list of printers to validate first. Never null. @@ -463,9 +473,28 @@ public abstract class PrinterDiscoverySession { public abstract void onStopPrinterDiscovery(); /** - * Requests that you update a printer. You are responsible for updating - * the printer by also reporting its capabilities via calling {@link - * #updatePrinters(List)}. + * Callback asking you to validate that the given printers are valid, that + * is they exist. You are responsible for checking whether these printers + * exist and for the ones that do exist notify the system via calling + * {@link #updatePrinters(List)}. + * <p> + * <strong>Note: </strong> You are <strong>not required</strong> to provide + * the printer capabilities when updating the printers that do exist. + * <p> + * + * @param printerIds The printers to validate. + * + * @see #updatePrinters(List) + * @see PrinterInfo.Builder#setCapabilities(PrinterCapabilitiesInfo) + * PrinterInfo.Builder.setCapabilities(PrinterCapabilitiesInfo) + */ + public abstract void onValidatePrinters(List<PrinterId> printerIds); + + /** + * Callback asking you to start tracking the state of a printer. Tracking + * the state means that you should do a best effort to observe the state + * of this printer and notify the system if that state changes via calling + * {@link #updatePrinters(List)}. * <p> * <strong>Note: </strong> A printer can be initially added without its * capabilities to avoid polling printers that the user will not select. @@ -473,18 +502,33 @@ public abstract class PrinterDiscoverySession { * printer <strong>including</strong> its capabilities. Otherwise, the * printer will be ignored. * <p> - * A scenario when you may be requested to update a printer is if the user - * selects it and the system has to present print options UI based on the - * printer's capabilities. + * <p> + * A scenario when you may be requested to track a printer's state is if + * the user selects that printer and the system has to present print + * options UI based on the printer's capabilities. In this case the user + * should be promptly informed if, for example, the printer becomes + * unavailable. * </p> * - * @param printerId The printer id. + * @param printerId The printer to start tracking. * + * @see #onStopPrinterStateTracking(PrinterId) * @see #updatePrinters(List) * @see PrinterInfo.Builder#setCapabilities(PrinterCapabilitiesInfo) * PrinterInfo.Builder.setCapabilities(PrinterCapabilitiesInfo) */ - public abstract void onRequestPrinterUpdate(PrinterId printerId); + public abstract void onStartPrinterStateTracking(PrinterId printerId); + + /** + * Callback asking you to stop tracking the state of a printer. The passed + * in printer id is the one for which you received a call to {@link + * #onStartPrinterStateTracking(PrinterId)}. + * + * @param printerId The printer to stop tracking. + * + * @see #onStartPrinterStateTracking(PrinterId) + */ + public abstract void onStopPrinterStateTracking(PrinterId printerId); /** * Notifies you that the session is destroyed. After this callback is invoked @@ -538,9 +582,21 @@ public abstract class PrinterDiscoverySession { } } - void requestPrinterUpdate(PrinterId printerId) { - if (!mIsDestroyed) { - onRequestPrinterUpdate(printerId); + void validatePrinters(List<PrinterId> printerIds) { + if (!mIsDestroyed && mObserver != null) { + onValidatePrinters(printerIds); + } + } + + void startPrinterStateTracking(PrinterId printerId) { + if (!mIsDestroyed && mObserver != null) { + onStartPrinterStateTracking(printerId); + } + } + + void stopPrinterStateTracking(PrinterId printerId) { + if (!mIsDestroyed && mObserver != null) { + onStopPrinterStateTracking(printerId); } } diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index faf6e63..b749aa64 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -1915,13 +1915,10 @@ android:description="@string/permdesc_bindNfcService" android:protectionLevel="signature" /> - <!-- Allows an application to call APIs that give it access to all print jobs - on the device. Usually an app can access only the print jobts it created. - This permission is not available to third party applications. - @hide --> - <permission android:name="android.permission.ACCESS_ALL_PRINT_JOBS" - android:label="@string/permlab_accessAllPrintJobs" - android:description="@string/permdesc_accessAllPrintJobs" + <!-- Must be required by the PrintSpooler to ensure that only the system can bind to it. --> + <permission android:name="android.permission.BIND_PRINT_SPOOLER_SERVICE" + android:label="@string/permlab_bindPrintSpoolerService" + android:description="@string/permdesc_bindPrintSpoolerService" android:protectionLevel="signature" /> <!-- Must be required by a TextService (e.g. SpellCheckerService) diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index ead46c2..4b32e2b 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -984,12 +984,13 @@ <string name="permdesc_bindPrintService">Allows the holder to bind to the top-level interface of a print service. Should never be needed for normal apps.</string> - <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. --> - <string name="permlab_accessAllPrintJobs">access all print jobs</string> - <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. --> - <string name="permdesc_accessAllPrintJobs">Allows the holder to access print jobs - created by another app. Should never be needed for normal apps.</string> - + <!-- Title of an application permission, listed so the user can choose + whether they want to allow the application to do this. --> + <string name="permlab_bindPrintSpoolerService">bind to a print spooler service</string> + <!-- Description of an application permission, listed so the user can + choose whether they want to allow the application to do this. --> + <string name="permdesc_bindPrintSpoolerService">Allows the holder to bind to the top-level + interface of a print spooler service. Should never be needed for normal apps.</string> <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. --> <string name="permlab_bindNfcService">bind to NFC service</string> @@ -4292,6 +4293,9 @@ <!-- Write fail reason: couldn't write the printed content. [CHAR LIMIT=none] --> <string name="write_fail_reason_cannot_write">Error writing content</string> + <!-- Print fail reason: unknown. [CHAR LIMIT=25] --> + <string name="reason_unknown">unknown</string> + <!-- PIN entry dialog label/hint for PIN [CHAR LIMIT=none] --> <string name="restr_pin_enter_pin">Enter PIN</string> <!-- PIN entry dialog label/hint for old PIN [CHAR LIMIT=none] --> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index a9c812e..67f25d1 100755 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -868,6 +868,7 @@ <java-symbol type="string" name="mediaSize_na_junior_legal" /> <java-symbol type="string" name="mediaSize_na_ledger" /> <java-symbol type="string" name="mediaSize_na_tabloid" /> + <java-symbol type="string" name="reason_unknown" /> <java-symbol type="string" name="restr_pin_enter_pin" /> <java-symbol type="string" name="write_fail_reason_cancelled" /> <java-symbol type="string" name="write_fail_reason_cannot_write" /> |