diff options
| -rw-r--r-- | api/current.txt | 2 | ||||
| -rw-r--r-- | api/system-current.txt | 2 | ||||
| -rw-r--r-- | api/test-current.txt | 4 | ||||
| -rw-r--r-- | core/java/android/print/IPrintSpooler.aidl | 17 | ||||
| -rw-r--r-- | core/java/android/print/PrintJobInfo.java | 124 | ||||
| -rw-r--r-- | core/java/android/printservice/IPrintServiceClient.aidl | 16 | ||||
| -rw-r--r-- | core/java/android/printservice/PrintJob.java | 81 | ||||
| -rw-r--r-- | packages/PrintSpooler/src/com/android/printspooler/model/NotificationController.java | 81 | ||||
| -rw-r--r-- | packages/PrintSpooler/src/com/android/printspooler/model/PrintSpoolerService.java | 81 | ||||
| -rw-r--r-- | services/print/java/com/android/server/print/RemotePrintService.java | 30 | ||||
| -rw-r--r-- | services/print/java/com/android/server/print/RemotePrintSpooler.java | 58 |
11 files changed, 407 insertions, 89 deletions
diff --git a/api/current.txt b/api/current.txt index 59b8fb3c0383..7ddd5af61420 100644 --- a/api/current.txt +++ b/api/current.txt @@ -28864,6 +28864,8 @@ package android.printservice { method public boolean isFailed(); method public boolean isQueued(); method public boolean isStarted(); + method public void setProgress(float); + method public void setStatus(java.lang.CharSequence); method public boolean setTag(java.lang.String); method public boolean start(); } diff --git a/api/system-current.txt b/api/system-current.txt index f02956867093..edc9f18c1046 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -30847,6 +30847,8 @@ package android.printservice { method public boolean isFailed(); method public boolean isQueued(); method public boolean isStarted(); + method public void setProgress(float); + method public void setStatus(java.lang.CharSequence); method public boolean setTag(java.lang.String); method public boolean start(); } diff --git a/api/test-current.txt b/api/test-current.txt index 59b8fb3c0383..483870277c52 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -28745,7 +28745,9 @@ package android.print { method public java.lang.String getLabel(); method public android.print.PageRange[] getPages(); method public android.print.PrinterId getPrinterId(); + method public float getProgress(); method public int getState(); + method public java.lang.CharSequence getStatus(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.print.PrintJobInfo> CREATOR; field public static final int STATE_BLOCKED = 4; // 0x4 @@ -28864,6 +28866,8 @@ package android.printservice { method public boolean isFailed(); method public boolean isQueued(); method public boolean isStarted(); + method public void setProgress(float); + method public void setStatus(java.lang.CharSequence); method public boolean setTag(java.lang.String); method public boolean start(); } diff --git a/core/java/android/print/IPrintSpooler.aidl b/core/java/android/print/IPrintSpooler.aidl index db2bf1a65e13..b7cfbea43646 100644 --- a/core/java/android/print/IPrintSpooler.aidl +++ b/core/java/android/print/IPrintSpooler.aidl @@ -41,6 +41,23 @@ oneway interface IPrintSpooler { void createPrintJob(in PrintJobInfo printJob); void setPrintJobState(in PrintJobId printJobId, int status, String stateReason, IPrintSpoolerCallbacks callback, int sequence); + + /** + * Set the progress of this print job + * + * @param printJobId The print job to update + * @param progress The new progress + */ + void setProgress(in PrintJobId printJobId, in float progress); + + /** + * Set the status of this print job + * + * @param printJobId The print job to update + * @param status The new status, can be null + */ + void setStatus(in PrintJobId printJobId, in CharSequence status); + void setPrintJobTag(in PrintJobId printJobId, String tag, IPrintSpoolerCallbacks callback, int sequence); void writePrintJobData(in ParcelFileDescriptor fd, in PrintJobId printJobId); diff --git a/core/java/android/print/PrintJobInfo.java b/core/java/android/print/PrintJobInfo.java index 63f94fe642fb..7148c8757830 100644 --- a/core/java/android/print/PrintJobInfo.java +++ b/core/java/android/print/PrintJobInfo.java @@ -16,10 +16,15 @@ package android.print; +import android.annotation.FloatRange; +import android.annotation.Nullable; +import android.annotation.TestApi; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; +import com.android.internal.util.Preconditions; + import java.util.Arrays; /** @@ -149,9 +154,6 @@ public final class PrintJobInfo implements Parcelable { /** How many copies to print. */ private int mCopies; - /** Reason for the print job being in its current state. */ - private String mStateReason; - /** The pages to print */ private PageRange[] mPageRanges; @@ -161,6 +163,12 @@ public final class PrintJobInfo implements Parcelable { /** Information about the printed document. */ private PrintDocumentInfo mDocumentInfo; + /** The progress made on printing this job or -1 if not set. */ + private float mProgress; + + /** A short string describing the status of this job. */ + private CharSequence mStatus; + /** Advanced printer specific options. */ private Bundle mAdvancedOptions; @@ -169,7 +177,7 @@ public final class PrintJobInfo implements Parcelable { /** @hide*/ public PrintJobInfo() { - /* do nothing */ + mProgress = -1; } /** @hide */ @@ -183,10 +191,11 @@ public final class PrintJobInfo implements Parcelable { mTag = other.mTag; mCreationTime = other.mCreationTime; mCopies = other.mCopies; - mStateReason = other.mStateReason; mPageRanges = other.mPageRanges; mAttributes = other.mAttributes; mDocumentInfo = other.mDocumentInfo; + mProgress = other.mProgress; + mStatus = other.mStatus; mCanceling = other.mCanceling; mAdvancedOptions = other.mAdvancedOptions; } @@ -201,7 +210,6 @@ public final class PrintJobInfo implements Parcelable { mTag = parcel.readString(); mCreationTime = parcel.readLong(); mCopies = parcel.readInt(); - mStateReason = parcel.readString(); Parcelable[] parcelables = parcel.readParcelableArray(null); if (parcelables != null) { mPageRanges = new PageRange[parcelables.length]; @@ -211,6 +219,8 @@ public final class PrintJobInfo implements Parcelable { } mAttributes = (PrintAttributes) parcel.readParcelable(null); mDocumentInfo = (PrintDocumentInfo) parcel.readParcelable(null); + mProgress = parcel.readFloat(); + mStatus = parcel.readCharSequence(); mCanceling = (parcel.readInt() == 1); mAdvancedOptions = parcel.readBundle(); } @@ -227,7 +237,7 @@ public final class PrintJobInfo implements Parcelable { /** * Sets the unique print job id. * - * @param The job id. + * @param id The job id. * * @hide */ @@ -265,7 +275,7 @@ public final class PrintJobInfo implements Parcelable { } /** - * Sets the unique target pritner id. + * Sets the unique target printer id. * * @param printerId The target printer id. * @@ -326,6 +336,30 @@ public final class PrintJobInfo implements Parcelable { } /** + * Sets the progress of the print job. + * + * @param progress the progress of the job + * + * @hide + */ + public void setProgress(@FloatRange(from=0.0, to=1.0) float progress) { + Preconditions.checkArgumentInRange(progress, 0, 1, "progress"); + + mProgress = progress; + } + + /** + * Sets the status of the print job. + * + * @param status the status of the job, can be null + * + * @hide + */ + public void setStatus(@Nullable CharSequence status) { + mStatus = status; + } + + /** * Sets the owning application id. * * @return The owning app id. @@ -416,30 +450,6 @@ public final class PrintJobInfo implements Parcelable { } /** - * Gets the reason for the print job being in the current state. - * - * @return The reason, or null if there is no reason or the - * reason is unknown. - * - * @hide - */ - public String getStateReason() { - return mStateReason; - } - - /** - * Sets the reason for the print job being in the current state. - * - * @param stateReason The reason, or null if there is no reason - * or the reason is unknown. - * - * @hide - */ - public void setStateReason(String stateReason) { - mStateReason = stateReason; - } - - /** * Gets the included pages. * * @return The included pages or <code>null</code> if not set. @@ -604,10 +614,11 @@ public final class PrintJobInfo implements Parcelable { parcel.writeString(mTag); parcel.writeLong(mCreationTime); parcel.writeInt(mCopies); - parcel.writeString(mStateReason); parcel.writeParcelableArray(mPageRanges, flags); parcel.writeParcelable(mAttributes, flags); parcel.writeParcelable(mDocumentInfo, 0); + parcel.writeFloat(mProgress); + parcel.writeCharSequence(mStatus); parcel.writeInt(mCanceling ? 1 : 0); parcel.writeBundle(mAdvancedOptions); } @@ -631,6 +642,9 @@ public final class PrintJobInfo implements Parcelable { builder.append(", pages: " + (mPageRanges != null ? Arrays.toString(mPageRanges) : null)); builder.append(", hasAdvancedOptions: " + (mAdvancedOptions != null)); + builder.append(", progress: " + mProgress); + builder.append(", status: " + (mStatus != null + ? mStatus.toString() : null)); builder.append("}"); return builder.toString(); } @@ -666,6 +680,28 @@ public final class PrintJobInfo implements Parcelable { } /** + * Get the progress that has been made printing this job. + * + * @return the print progress or -1 if not set + * @hide + */ + @TestApi + public float getProgress() { + return mProgress; + } + + /** + * Get the status of this job. + * + * @return the status of this job or null if not set + * @hide + */ + @TestApi + public @Nullable CharSequence getStatus() { + return mStatus; + } + + /** * Builder for creating a {@link PrintJobInfo}. */ public static final class Builder { @@ -711,6 +747,28 @@ public final class PrintJobInfo implements Parcelable { } /** + * Sets the progress of the print job. + * + * @param progress the progress of the job + * @hide + */ + public void setProgress(@FloatRange(from=0.0, to=1.0) float progress) { + Preconditions.checkArgumentInRange(progress, 0, 1, "progress"); + + mPrototype.mProgress = progress; + } + + /** + * Sets the status of the print job. + * + * @param status the status of the job, can be null + * @hide + */ + public void setStatus(@Nullable CharSequence status) { + mPrototype.mStatus = status; + } + + /** * Puts an advanced (printer specific) option. * * @param key The option key. diff --git a/core/java/android/printservice/IPrintServiceClient.aidl b/core/java/android/printservice/IPrintServiceClient.aidl index c2dfc30a4e25..b4baa4851392 100644 --- a/core/java/android/printservice/IPrintServiceClient.aidl +++ b/core/java/android/printservice/IPrintServiceClient.aidl @@ -35,6 +35,22 @@ interface IPrintServiceClient { boolean setPrintJobTag(in PrintJobId printJobId, String tag); oneway void writePrintJobData(in ParcelFileDescriptor fd, in PrintJobId printJobId); + /** + * Set the progress of this print job + * + * @param printJobId The print job to update + * @param progress The new progress + */ + void setProgress(in PrintJobId printJobId, in float progress); + + /** + * Set the status of this print job + * + * @param printJobId The print job to update + * @param status The new status, can be null + */ + void setStatus(in PrintJobId printJobId, in CharSequence status); + void onPrintersAdded(in ParceledListSlice printers); void onPrintersRemoved(in ParceledListSlice printerIds); } diff --git a/core/java/android/printservice/PrintJob.java b/core/java/android/printservice/PrintJob.java index 6fa0bddb43f4..86fc292cb003 100644 --- a/core/java/android/printservice/PrintJob.java +++ b/core/java/android/printservice/PrintJob.java @@ -16,6 +16,10 @@ package android.printservice; +import android.annotation.FloatRange; +import android.annotation.MainThread; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.os.RemoteException; import android.print.PrintJobId; import android.print.PrintJobInfo; @@ -41,7 +45,7 @@ public final class PrintJob { private PrintJobInfo mCachedInfo; - PrintJob(PrintJobInfo jobInfo, IPrintServiceClient client) { + PrintJob(@NonNull PrintJobInfo jobInfo, @NonNull IPrintServiceClient client) { mCachedInfo = jobInfo; mPrintServiceClient = client; mDocument = new PrintDocument(mCachedInfo.getId(), client, @@ -53,6 +57,7 @@ public final class PrintJob { * * @return The id. */ + @MainThread public PrintJobId getId() { PrintService.throwIfNotCalledOnMainThread(); return mCachedInfo.getId(); @@ -68,7 +73,8 @@ public final class PrintJob { * * @return The print job info. */ - public PrintJobInfo getInfo() { + @MainThread + public @NonNull PrintJobInfo getInfo() { PrintService.throwIfNotCalledOnMainThread(); if (isInImmutableState()) { return mCachedInfo; @@ -90,7 +96,8 @@ public final class PrintJob { * * @return The document. */ - public PrintDocument getDocument() { + @MainThread + public @NonNull PrintDocument getDocument() { PrintService.throwIfNotCalledOnMainThread(); return mDocument; } @@ -104,6 +111,7 @@ public final class PrintJob { * @see #start() * @see #cancel() */ + @MainThread public boolean isQueued() { PrintService.throwIfNotCalledOnMainThread(); return getInfo().getState() == PrintJobInfo.STATE_QUEUED; @@ -117,8 +125,9 @@ public final class PrintJob { * * @see #complete() * @see #cancel() - * @see #fail(CharSequence) + * @see #fail(String) */ + @MainThread public boolean isStarted() { PrintService.throwIfNotCalledOnMainThread(); return getInfo().getState() == PrintJobInfo.STATE_STARTED; @@ -132,8 +141,9 @@ public final class PrintJob { * * @see #start() * @see #cancel() - * @see #fail(CharSequence) + * @see #fail(String) */ + @MainThread public boolean isBlocked() { PrintService.throwIfNotCalledOnMainThread(); return getInfo().getState() == PrintJobInfo.STATE_BLOCKED; @@ -147,6 +157,7 @@ public final class PrintJob { * * @see #complete() */ + @MainThread public boolean isCompleted() { PrintService.throwIfNotCalledOnMainThread(); return getInfo().getState() == PrintJobInfo.STATE_COMPLETED; @@ -158,8 +169,9 @@ public final class PrintJob { * * @return Whether the print job is failed. * - * @see #fail(CharSequence) + * @see #fail(String) */ + @MainThread public boolean isFailed() { PrintService.throwIfNotCalledOnMainThread(); return getInfo().getState() == PrintJobInfo.STATE_FAILED; @@ -173,6 +185,7 @@ public final class PrintJob { * * @see #cancel() */ + @MainThread public boolean isCancelled() { PrintService.throwIfNotCalledOnMainThread(); return getInfo().getState() == PrintJobInfo.STATE_CANCELED; @@ -182,12 +195,16 @@ public final class PrintJob { * Starts the print job. You should call this method if {@link * #isQueued()} or {@link #isBlocked()} returns true and you started * resumed printing. + * <p> + * This resets the print status to null. Set the new status by using {@link #setStatus}. + * </p> * * @return Whether the job was started. * * @see #isQueued() * @see #isBlocked() */ + @MainThread public boolean start() { PrintService.throwIfNotCalledOnMainThread(); final int state = getInfo().getState(); @@ -205,18 +222,20 @@ public final class PrintJob { * paper to continue printing. To resume the print job call {@link * #start()}. * + * @param reason The human readable, short, and translated reason why the print job is blocked. * @return Whether the job was blocked. * * @see #isStarted() * @see #isBlocked() */ - public boolean block(String reason) { + @MainThread + public boolean block(@Nullable 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))) { + && !TextUtils.equals(info.getStatus(), reason))) { return setState(PrintJobInfo.STATE_BLOCKED, reason); } return false; @@ -230,6 +249,7 @@ public final class PrintJob { * * @see #isStarted() */ + @MainThread public boolean complete() { PrintService.throwIfNotCalledOnMainThread(); if (isStarted()) { @@ -251,7 +271,8 @@ public final class PrintJob { * @see #isStarted() * @see #isBlocked() */ - public boolean fail(String error) { + @MainThread + public boolean fail(@Nullable String error) { PrintService.throwIfNotCalledOnMainThread(); if (!isInImmutableState()) { return setState(PrintJobInfo.STATE_FAILED, error); @@ -271,6 +292,7 @@ public final class PrintJob { * @see #isQueued() * @see #isBlocked() */ + @MainThread public boolean cancel() { PrintService.throwIfNotCalledOnMainThread(); if (!isInImmutableState()) { @@ -280,6 +302,39 @@ public final class PrintJob { } /** + * Sets the progress of this print job as a fraction of 1. + * + * @param progress The new progress + */ + @MainThread + public void setProgress(@FloatRange(from=0.0, to=1.0) float progress) { + PrintService.throwIfNotCalledOnMainThread(); + + try { + mPrintServiceClient.setProgress(mCachedInfo.getId(), progress); + } catch (RemoteException re) { + Log.e(LOG_TAG, "Error setting progress for job: " + mCachedInfo.getId(), re); + } + } + + /** + * Sets the status of this print job. This should be a human readable, short, and translated + * description of the current state of the print job. + * + * @param status The new status. If null the status will be empty. + */ + @MainThread + public void setStatus(@Nullable CharSequence status) { + PrintService.throwIfNotCalledOnMainThread(); + + try { + mPrintServiceClient.setStatus(mCachedInfo.getId(), status); + } catch (RemoteException re) { + Log.e(LOG_TAG, "Error setting status for job: " + mCachedInfo.getId(), re); + } + } + + /** * Sets a tag that is valid in the context of a {@link PrintService} * and is not interpreted by the system. For example, a print service * may set as a tag the key of the print job returned by a remote @@ -288,6 +343,7 @@ public final class PrintJob { * @param tag The tag. * @return True if the tag was set, false otherwise. */ + @MainThread public boolean setTag(String tag) { PrintService.throwIfNotCalledOnMainThread(); if (isInImmutableState()) { @@ -319,6 +375,7 @@ public final class PrintJob { * @param key The option key. * @return The option value. */ + @MainThread public String getAdvancedStringOption(String key) { PrintService.throwIfNotCalledOnMainThread(); return getInfo().getAdvancedStringOption(key); @@ -331,6 +388,7 @@ public final class PrintJob { * @param key The option key. * @return Whether the option is present. */ + @MainThread public boolean hasAdvancedOption(String key) { PrintService.throwIfNotCalledOnMainThread(); return getInfo().hasAdvancedOption(key); @@ -342,6 +400,7 @@ public final class PrintJob { * @param key The option key. * @return The option value. */ + @MainThread public int getAdvancedIntOption(String key) { PrintService.throwIfNotCalledOnMainThread(); return getInfo().getAdvancedIntOption(key); @@ -374,14 +433,14 @@ public final class PrintJob { || state == PrintJobInfo.STATE_FAILED; } - private boolean setState(int state, String error) { + private boolean setState(int state, @Nullable String error) { try { if (mPrintServiceClient.setPrintJobState(mCachedInfo.getId(), state, error)) { // Best effort - update the state of the cached info since // 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.setStateReason(error); + mCachedInfo.setStatus(error); return true; } } catch (RemoteException re) { diff --git a/packages/PrintSpooler/src/com/android/printspooler/model/NotificationController.java b/packages/PrintSpooler/src/com/android/printspooler/model/NotificationController.java index f006ccb94247..82fd51233ef2 100644 --- a/packages/PrintSpooler/src/com/android/printspooler/model/NotificationController.java +++ b/packages/PrintSpooler/src/com/android/printspooler/model/NotificationController.java @@ -16,6 +16,8 @@ package com.android.printspooler.model; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.app.Notification; import android.app.Notification.Action; import android.app.Notification.InboxStyle; @@ -129,68 +131,69 @@ final class NotificationController { mContext.getString(R.string.cancel), createCancelIntent(printJob)).build(); } - private void createPrintingNotification(PrintJobInfo printJob) { + /** + * Create a notification for a print job. + * + * @param printJob the job the notification is for + * @param firstAction the first action shown in the notification + * @param secondAction the second action shown in the notification + */ + private void createNotification(@NonNull PrintJobInfo printJob, @Nullable Action firstAction, + @Nullable Action secondAction) { Notification.Builder builder = new Notification.Builder(mContext) .setContentIntent(createContentIntent(printJob.getId())) .setSmallIcon(computeNotificationIcon(printJob)) .setContentTitle(computeNotificationTitle(printJob)) - .addAction(createCancelAction(printJob)) - .setContentText(printJob.getPrinterName()) .setWhen(System.currentTimeMillis()) .setOngoing(true) .setShowWhen(true) .setColor(mContext.getColor( com.android.internal.R.color.system_notification_accent_color)); + + if (firstAction != null) { + builder.addAction(firstAction); + } + + if (secondAction != null) { + builder.addAction(secondAction); + } + + if (printJob.getState() == PrintJobInfo.STATE_STARTED) { + float progress = printJob.getProgress(); + if (progress >= 0) { + builder.setProgress(Integer.MAX_VALUE, (int)(Integer.MAX_VALUE * progress), + false); + } + } + + CharSequence status = printJob.getStatus(); + if (status != null) { + builder.setContentText(status); + } else { + builder.setContentText(printJob.getPrinterName()); + } + mNotificationManager.notify(0, builder.build()); } + private void createPrintingNotification(PrintJobInfo printJob) { + createNotification(printJob, createCancelAction(printJob), null); + } + private void createFailedNotification(PrintJobInfo printJob) { Action.Builder restartActionBuilder = new Action.Builder( Icon.createWithResource(mContext, R.drawable.ic_restart), mContext.getString(R.string.restart), createRestartIntent(printJob.getId())); - Notification.Builder builder = new Notification.Builder(mContext) - .setContentIntent(createContentIntent(printJob.getId())) - .setSmallIcon(computeNotificationIcon(printJob)) - .setContentTitle(computeNotificationTitle(printJob)) - .addAction(createCancelAction(printJob)) - .addAction(restartActionBuilder.build()) - .setContentText(printJob.getPrinterName()) - .setWhen(System.currentTimeMillis()) - .setOngoing(true) - .setShowWhen(true) - .setColor(mContext.getColor( - com.android.internal.R.color.system_notification_accent_color)); - mNotificationManager.notify(0, builder.build()); + createNotification(printJob, createCancelAction(printJob), restartActionBuilder.build()); } private void createBlockedNotification(PrintJobInfo printJob) { - Notification.Builder builder = new Notification.Builder(mContext) - .setContentIntent(createContentIntent(printJob.getId())) - .setSmallIcon(computeNotificationIcon(printJob)) - .setContentTitle(computeNotificationTitle(printJob)) - .addAction(createCancelAction(printJob)) - .setContentText(printJob.getPrinterName()) - .setWhen(System.currentTimeMillis()) - .setOngoing(true) - .setShowWhen(true) - .setColor(mContext.getColor( - com.android.internal.R.color.system_notification_accent_color)); - mNotificationManager.notify(0, builder.build()); + createNotification(printJob, createCancelAction(printJob), null); } private void createCancellingNotification(PrintJobInfo printJob) { - Notification.Builder builder = new Notification.Builder(mContext) - .setContentIntent(createContentIntent(printJob.getId())) - .setSmallIcon(computeNotificationIcon(printJob)) - .setContentTitle(computeNotificationTitle(printJob)) - .setContentText(printJob.getPrinterName()) - .setWhen(System.currentTimeMillis()) - .setOngoing(true) - .setShowWhen(true) - .setColor(mContext.getColor( - com.android.internal.R.color.system_notification_accent_color)); - mNotificationManager.notify(0, builder.build()); + createNotification(printJob, null, null); } private void createStackedNotification(List<PrintJobInfo> printJobs) { diff --git a/packages/PrintSpooler/src/com/android/printspooler/model/PrintSpoolerService.java b/packages/PrintSpooler/src/com/android/printspooler/model/PrintSpoolerService.java index 7adcfec728e7..b92a389c1679 100644 --- a/packages/PrintSpooler/src/com/android/printspooler/model/PrintSpoolerService.java +++ b/packages/PrintSpooler/src/com/android/printspooler/model/PrintSpoolerService.java @@ -16,6 +16,9 @@ package com.android.printspooler.model; +import android.annotation.FloatRange; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.app.Service; import android.content.ComponentName; import android.content.Context; @@ -497,7 +500,7 @@ public final class PrintSpoolerService extends Service { success = true; printJob.setState(state); - printJob.setStateReason(error); + printJob.setStatus(error); printJob.setCancelling(false); if (DEBUG_PRINT_JOB_LIFECYCLE) { @@ -547,6 +550,35 @@ public final class PrintSpoolerService extends Service { return success; } + /** + * Set the progress for a print job. + * + * @param printJobId ID of the print job to update + * @param progress the new progress + */ + public void setProgress(@NonNull PrintJobId printJobId, + @FloatRange(from=0.0, to=1.0) float progress) { + synchronized (mLock) { + getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY).setProgress(progress); + + mNotificationController.onUpdateNotifications(mPrintJobs); + } + } + + /** + * Set the status for a print job. + * + * @param printJobId ID of the print job to update + * @param status the new status + */ + public void setStatus(@NonNull PrintJobId printJobId, @Nullable CharSequence status) { + synchronized (mLock) { + getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY).setStatus(status); + + mNotificationController.onUpdateNotifications(mPrintJobs); + } + } + public boolean hasActivePrintJobsLocked() { final int printJobCount = mPrintJobs.size(); for (int i = 0; i < printJobCount; i++) { @@ -693,6 +725,8 @@ public final class PrintSpoolerService extends Service { private static final String ATTR_COPIES = "copies"; private static final String ATTR_PRINTER_NAME = "printerName"; private static final String ATTR_STATE_REASON = "stateReason"; + private static final String ATTR_STATUS = "status"; + private static final String ATTR_PROGRESS = "progress"; private static final String ATTR_CANCELLING = "cancelling"; private static final String TAG_ADVANCED_OPTIONS = "advancedOptions"; @@ -801,13 +835,19 @@ public final class PrintSpoolerService extends Service { if (!TextUtils.isEmpty(printerName)) { serializer.attribute(null, ATTR_PRINTER_NAME, printerName); } - String stateReason = printJob.getStateReason(); - if (!TextUtils.isEmpty(stateReason)) { - serializer.attribute(null, ATTR_STATE_REASON, stateReason); - } serializer.attribute(null, ATTR_CANCELLING, String.valueOf( printJob.isCancelling())); + float progress = printJob.getProgress(); + if (progress != Float.NaN) { + serializer.attribute(null, ATTR_PROGRESS, String.valueOf(progress)); + } + + CharSequence status = printJob.getStatus(); + if (!TextUtils.isEmpty(status)) { + serializer.attribute(null, ATTR_STATUS, status.toString()); + } + PrinterId printerId = printJob.getPrinterId(); if (printerId != null) { serializer.startTag(null, TAG_PRINTER_ID); @@ -1025,8 +1065,25 @@ public final class PrintSpoolerService extends Service { printJob.setCopies(Integer.parseInt(copies)); String printerName = parser.getAttributeValue(null, ATTR_PRINTER_NAME); printJob.setPrinterName(printerName); + + String progressString = parser.getAttributeValue(null, ATTR_PROGRESS); + if (progressString != null) { + float progress = Float.parseFloat(progressString); + + if (progress != Float.NaN) { + printJob.setProgress(progress); + } + } + + CharSequence status = parser.getAttributeValue(null, ATTR_STATUS); + printJob.setStatus(status); + + // stateReason is deprecated, but might be used by old print jobs String stateReason = parser.getAttributeValue(null, ATTR_STATE_REASON); - printJob.setStateReason(stateReason); + if (stateReason != null) { + printJob.setStatus(stateReason); + } + String cancelling = parser.getAttributeValue(null, ATTR_CANCELLING); printJob.setCancelling(!TextUtils.isEmpty(cancelling) ? Boolean.parseBoolean(cancelling) : false); @@ -1323,6 +1380,18 @@ public final class PrintSpoolerService extends Service { .removeApprovedService(serviceToRemove); } + @Override + public void setProgress(@NonNull PrintJobId printJobId, + @FloatRange(from=0.0, to=1.0) float progress) throws RemoteException { + PrintSpoolerService.this.setProgress(printJobId, progress); + } + + @Override + public void setStatus(@NonNull PrintJobId printJobId, + @Nullable CharSequence status) throws RemoteException { + PrintSpoolerService.this.setStatus(printJobId, status); + } + public PrintSpoolerService getService() { return PrintSpoolerService.this; } diff --git a/services/print/java/com/android/server/print/RemotePrintService.java b/services/print/java/com/android/server/print/RemotePrintService.java index 0ab1657fcc52..77a47f81e62b 100644 --- a/services/print/java/com/android/server/print/RemotePrintService.java +++ b/services/print/java/com/android/server/print/RemotePrintService.java @@ -16,6 +16,9 @@ package com.android.server.print; +import android.annotation.FloatRange; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.content.ComponentName; import android.content.Context; import android.content.Intent; @@ -757,6 +760,33 @@ final class RemotePrintService implements DeathRecipient { } @Override + public void setProgress(@NonNull PrintJobId printJobId, + @FloatRange(from=0.0, to=1.0) float progress) { + RemotePrintService service = mWeakService.get(); + if (service != null) { + final long identity = Binder.clearCallingIdentity(); + try { + service.mSpooler.setProgress(printJobId, progress); + } finally { + Binder.restoreCallingIdentity(identity); + } + } + } + + @Override + public void setStatus(@NonNull PrintJobId printJobId, @Nullable CharSequence status) { + RemotePrintService service = mWeakService.get(); + if (service != null) { + final long identity = Binder.clearCallingIdentity(); + try { + service.mSpooler.setStatus(printJobId, status); + } finally { + Binder.restoreCallingIdentity(identity); + } + } + } + + @Override @SuppressWarnings({"rawtypes", "unchecked"}) public void onPrintersAdded(ParceledListSlice printers) { RemotePrintService service = mWeakService.get(); diff --git a/services/print/java/com/android/server/print/RemotePrintSpooler.java b/services/print/java/com/android/server/print/RemotePrintSpooler.java index e5370f489e9b..c506b6f5f495 100644 --- a/services/print/java/com/android/server/print/RemotePrintSpooler.java +++ b/services/print/java/com/android/server/print/RemotePrintSpooler.java @@ -16,6 +16,9 @@ package com.android.server.print; +import android.annotation.FloatRange; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.content.ComponentName; import android.content.Context; import android.content.Intent; @@ -229,6 +232,61 @@ final class RemotePrintSpooler { return false; } + /** + * Set progress of a print job. + * + * @param printJobId The print job to update + * @param progress The new progress + */ + public final void setProgress(@NonNull PrintJobId printJobId, + @FloatRange(from=0.0, to=1.0) float progress) { + throwIfCalledOnMainThread(); + synchronized (mLock) { + throwIfDestroyedLocked(); + mCanUnbind = false; + } + try { + getRemoteInstanceLazy().setProgress(printJobId, progress); + } catch (RemoteException|TimeoutException re) { + Slog.e(LOG_TAG, "Error setting progress.", re); + } finally { + if (DEBUG) { + Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier() + "] setProgress()"); + } + synchronized (mLock) { + mCanUnbind = true; + mLock.notifyAll(); + } + } + } + + /** + * Set status of a print job. + * + * @param printJobId The print job to update + * @param status The new status + */ + public final void setStatus(@NonNull PrintJobId printJobId, @Nullable CharSequence status) { + throwIfCalledOnMainThread(); + synchronized (mLock) { + throwIfDestroyedLocked(); + mCanUnbind = false; + } + try { + getRemoteInstanceLazy().setStatus(printJobId, status); + } catch (RemoteException|TimeoutException re) { + Slog.e(LOG_TAG, "Error setting status.", re); + } finally { + if (DEBUG) { + Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier() + "] setStatus()"); + } + synchronized (mLock) { + mCanUnbind = true; + mLock.notifyAll(); + } + } + } + public final boolean setPrintJobTag(PrintJobId printJobId, String tag) { throwIfCalledOnMainThread(); synchronized (mLock) { |