1 /*
2  * Copyright (C) 2013 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.print;
18 
19 import android.annotation.FloatRange;
20 import android.annotation.IntDef;
21 import android.annotation.IntRange;
22 import android.annotation.NonNull;
23 import android.annotation.Nullable;
24 import android.annotation.StringRes;
25 import android.annotation.TestApi;
26 import android.content.pm.PackageManager;
27 import android.content.res.Resources;
28 import android.os.Bundle;
29 import android.os.Parcel;
30 import android.os.Parcelable;
31 
32 import com.android.internal.util.Preconditions;
33 
34 import java.lang.annotation.Retention;
35 import java.lang.annotation.RetentionPolicy;
36 import java.util.Arrays;
37 
38 /**
39  * This class represents the description of a print job. The print job
40  * state includes properties such as its id, print attributes used for
41  * generating the content, and so on. Note that the print jobs state may
42  * change over time and this class represents a snapshot of this state.
43  */
44 public final class PrintJobInfo implements Parcelable {
45 
46     /** @hide */
47     @IntDef({
48             STATE_CREATED, STATE_QUEUED, STATE_STARTED, STATE_BLOCKED, STATE_COMPLETED,
49             STATE_FAILED, STATE_CANCELED
50     })
51     @Retention(RetentionPolicy.SOURCE)
52     public @interface State {
53     }
54 
55     /**
56      * Constant for matching any print job state.
57      *
58      * @hide
59      */
60     public static final int STATE_ANY = -1;
61 
62     /**
63      * Constant for matching any print job state.
64      *
65      * @hide
66      */
67     public static final int STATE_ANY_VISIBLE_TO_CLIENTS = -2;
68 
69     /**
70      * Constant for matching any active print job state.
71      *
72      * @hide
73      */
74     public static final int STATE_ANY_ACTIVE = -3;
75 
76     /**
77      * Constant for matching any scheduled, i.e. delivered to a print
78      * service, print job state.
79      *
80      * @hide
81      */
82     public static final int STATE_ANY_SCHEDULED = -4;
83 
84     /**
85      * Print job state: The print job is being created but not yet
86      * ready to be printed.
87      * <p>
88      * Next valid states: {@link #STATE_QUEUED}
89      * </p>
90      */
91     public static final int STATE_CREATED = 1;
92 
93     /**
94      * Print job state: The print jobs is created, it is ready
95      * to be printed and should be processed.
96      * <p>
97      * Next valid states: {@link #STATE_STARTED}, {@link #STATE_FAILED},
98      * {@link #STATE_CANCELED}
99      * </p>
100      */
101     public static final int STATE_QUEUED = 2;
102 
103     /**
104      * Print job state: The print job is being printed.
105      * <p>
106      * Next valid states: {@link #STATE_COMPLETED}, {@link #STATE_FAILED},
107      * {@link #STATE_CANCELED}, {@link #STATE_BLOCKED}
108      * </p>
109      */
110     public static final int STATE_STARTED = 3;
111 
112     /**
113      * Print job state: The print job is blocked.
114      * <p>
115      * Next valid states: {@link #STATE_FAILED}, {@link #STATE_CANCELED},
116      * {@link #STATE_STARTED}
117      * </p>
118      */
119     public static final int STATE_BLOCKED = 4;
120 
121     /**
122      * Print job state: The print job is successfully printed.
123      * This is a terminal state.
124      * <p>
125      * Next valid states: None
126      * </p>
127      */
128     public static final int STATE_COMPLETED = 5;
129 
130     /**
131      * Print job state: The print job was printing but printing failed.
132      * <p>
133      * Next valid states: {@link #STATE_CANCELED}, {@link #STATE_STARTED}
134      * </p>
135      */
136     public static final int STATE_FAILED = 6;
137 
138     /**
139      * Print job state: The print job is canceled.
140      * This is a terminal state.
141      * <p>
142      * Next valid states: None
143      * </p>
144      */
145     public static final int STATE_CANCELED = 7;
146 
147     /** The unique print job id. */
148     private PrintJobId mId;
149 
150     /** The human readable print job label. */
151     private String mLabel;
152 
153     /** The unique id of the printer. */
154     private PrinterId mPrinterId;
155 
156     /** The name of the printer - internally used */
157     private String mPrinterName;
158 
159     /** The state of the print job. */
160     private int mState;
161 
162     /** The id of the app that created the job. */
163     private int mAppId;
164 
165     /** Optional tag assigned by a print service.*/
166     private String mTag;
167 
168     /** The wall time when the print job was created. */
169     private long mCreationTime;
170 
171     /** How many copies to print. */
172     private int mCopies;
173 
174     /** The pages to print */
175     private PageRange[] mPageRanges;
176 
177     /** The print job attributes size. */
178     private PrintAttributes mAttributes;
179 
180     /** Information about the printed document. */
181     private PrintDocumentInfo mDocumentInfo;
182 
183     /** The progress made on printing this job or -1 if not set. */
184     private float mProgress;
185 
186     /** A short string describing the status of this job. */
187     private @Nullable CharSequence mStatus;
188 
189     /** A string resource describing the status of this job. */
190     private @StringRes int mStatusRes;
191     private @Nullable CharSequence mStatusResAppPackageName;
192 
193     /** Advanced printer specific options. */
194     private Bundle mAdvancedOptions;
195 
196     /** Whether we are trying to cancel this print job. */
197     private boolean mCanceling;
198 
199     /** @hide*/
PrintJobInfo()200     public PrintJobInfo() {
201         mProgress = -1;
202     }
203 
204     /** @hide */
PrintJobInfo(PrintJobInfo other)205     public PrintJobInfo(PrintJobInfo other) {
206         mId = other.mId;
207         mLabel = other.mLabel;
208         mPrinterId = other.mPrinterId;
209         mPrinterName = other.mPrinterName;
210         mState = other.mState;
211         mAppId = other.mAppId;
212         mTag = other.mTag;
213         mCreationTime = other.mCreationTime;
214         mCopies = other.mCopies;
215         mPageRanges = other.mPageRanges;
216         mAttributes = other.mAttributes;
217         mDocumentInfo = other.mDocumentInfo;
218         mProgress = other.mProgress;
219         mStatus = other.mStatus;
220         mStatusRes = other.mStatusRes;
221         mStatusResAppPackageName = other.mStatusResAppPackageName;
222         mCanceling = other.mCanceling;
223         mAdvancedOptions = other.mAdvancedOptions;
224     }
225 
PrintJobInfo(@onNull Parcel parcel)226     private PrintJobInfo(@NonNull Parcel parcel) {
227         mId = parcel.readParcelable(null);
228         mLabel = parcel.readString();
229         mPrinterId = parcel.readParcelable(null);
230         mPrinterName = parcel.readString();
231         mState = parcel.readInt();
232         mAppId = parcel.readInt();
233         mTag = parcel.readString();
234         mCreationTime = parcel.readLong();
235         mCopies = parcel.readInt();
236         Parcelable[] parcelables = parcel.readParcelableArray(null);
237         if (parcelables != null) {
238             mPageRanges = new PageRange[parcelables.length];
239             for (int i = 0; i < parcelables.length; i++) {
240                 mPageRanges[i] = (PageRange) parcelables[i];
241             }
242         }
243         mAttributes = (PrintAttributes) parcel.readParcelable(null);
244         mDocumentInfo = (PrintDocumentInfo) parcel.readParcelable(null);
245         mProgress = parcel.readFloat();
246         mStatus = parcel.readCharSequence();
247         mStatusRes = parcel.readInt();
248         mStatusResAppPackageName = parcel.readCharSequence();
249         mCanceling = (parcel.readInt() == 1);
250         mAdvancedOptions = parcel.readBundle();
251 
252         if (mAdvancedOptions != null) {
253             Preconditions.checkArgument(!mAdvancedOptions.containsKey(null));
254         }
255     }
256 
257     /**
258      * Gets the unique print job id.
259      *
260      * @return The id.
261      */
getId()262     public @Nullable PrintJobId getId() {
263         return mId;
264     }
265 
266     /**
267      * Sets the unique print job id.
268      *
269      * @param id The job id.
270      *
271      * @hide
272      */
setId(@onNull PrintJobId id)273     public void setId(@NonNull PrintJobId id) {
274         this.mId = id;
275     }
276 
277     /**
278      * Gets the human readable job label.
279      *
280      * @return The label.
281      */
getLabel()282     public @NonNull String getLabel() {
283         return mLabel;
284     }
285 
286     /**
287      * Sets the human readable job label.
288      *
289      * @param label The label.
290      *
291      * @hide
292      */
setLabel(@onNull String label)293     public void setLabel(@NonNull String label) {
294         mLabel = label;
295     }
296 
297     /**
298      * Gets the unique target printer id.
299      *
300      * @return The target printer id.
301      */
getPrinterId()302     public @Nullable PrinterId getPrinterId() {
303         return mPrinterId;
304     }
305 
306     /**
307      * Sets the unique target printer id.
308      *
309      * @param printerId The target printer id.
310      *
311      * @hide
312      */
setPrinterId(@onNull PrinterId printerId)313     public void setPrinterId(@NonNull PrinterId printerId) {
314         mPrinterId = printerId;
315     }
316 
317     /**
318      * Gets the name of the target printer.
319      *
320      * @return The printer name.
321      *
322      * @hide
323      */
getPrinterName()324     public @Nullable String getPrinterName() {
325         return mPrinterName;
326     }
327 
328     /**
329      * Sets the name of the target printer.
330      *
331      * @param printerName The printer name.
332      *
333      * @hide
334      */
setPrinterName(@onNull String printerName)335     public void setPrinterName(@NonNull String printerName) {
336         mPrinterName = printerName;
337     }
338 
339     /**
340      * Gets the current job state.
341      *
342      * @return The job state.
343      *
344      * @see #STATE_CREATED
345      * @see #STATE_QUEUED
346      * @see #STATE_STARTED
347      * @see #STATE_COMPLETED
348      * @see #STATE_BLOCKED
349      * @see #STATE_FAILED
350      * @see #STATE_CANCELED
351      */
getState()352     public @State int getState() {
353         return mState;
354     }
355 
356     /**
357      * Sets the current job state.
358      *
359      * @param state The job state.
360      *
361      * @hide
362      */
setState(int state)363     public void setState(int state) {
364         mState = state;
365     }
366 
367     /**
368      * Sets the progress of the print job.
369      *
370      * @param progress the progress of the job
371      *
372      * @hide
373      */
setProgress(@loatRangefrom=0.0, to=1.0) float progress)374     public void setProgress(@FloatRange(from=0.0, to=1.0) float progress) {
375         Preconditions.checkArgumentInRange(progress, 0, 1, "progress");
376 
377         mProgress = progress;
378     }
379 
380     /**
381      * Sets the status of the print job.
382      *
383      * @param status the status of the job, can be null
384      *
385      * @hide
386      */
setStatus(@ullable CharSequence status)387     public void setStatus(@Nullable CharSequence status) {
388         mStatusRes = 0;
389         mStatusResAppPackageName = null;
390 
391         mStatus = status;
392     }
393 
394     /**
395      * Sets the status of the print job.
396      *
397      * @param status The new status as a string resource
398      * @param appPackageName App package name the resource belongs to
399      *
400      * @hide
401      */
setStatus(@tringRes int status, @NonNull CharSequence appPackageName)402     public void setStatus(@StringRes int status, @NonNull CharSequence appPackageName) {
403         mStatus = null;
404 
405         mStatusRes = status;
406         mStatusResAppPackageName = appPackageName;
407     }
408 
409     /**
410      * Sets the owning application id.
411      *
412      * @return The owning app id.
413      *
414      * @hide
415      */
getAppId()416     public int getAppId() {
417         return mAppId;
418     }
419 
420     /**
421      * Sets the owning application id.
422      *
423      * @param appId The owning app id.
424      *
425      * @hide
426      */
setAppId(int appId)427     public void setAppId(int appId) {
428         mAppId = appId;
429     }
430 
431     /**
432      * Gets the optional tag assigned by a print service.
433      *
434      * @return The tag.
435      *
436      * @hide
437      */
getTag()438     public String getTag() {
439         return mTag;
440     }
441 
442     /**
443      * Sets the optional tag assigned by a print service.
444      *
445      * @param tag The tag.
446      *
447      * @hide
448      */
setTag(String tag)449     public void setTag(String tag) {
450         mTag = tag;
451     }
452 
453     /**
454      * Gets the wall time in millisecond when this print job was created.
455      *
456      * @return The creation time in milliseconds.
457      */
getCreationTime()458     public long getCreationTime() {
459         return mCreationTime;
460     }
461 
462     /**
463      * Sets the wall time in milliseconds when this print job was created.
464      *
465      * @param creationTime The creation time in milliseconds.
466      *
467      * @hide
468      */
setCreationTime(long creationTime)469     public void setCreationTime(long creationTime) {
470         if (creationTime < 0) {
471             throw new IllegalArgumentException("creationTime must be non-negative.");
472         }
473         mCreationTime = creationTime;
474     }
475 
476     /**
477      * Gets the number of copies.
478      *
479      * @return The number of copies or zero if not set.
480      */
getCopies()481     public @IntRange(from = 0) int getCopies() {
482         return mCopies;
483     }
484 
485     /**
486      * Sets the number of copies.
487      *
488      * @param copyCount The number of copies.
489      *
490      * @hide
491      */
setCopies(int copyCount)492     public void setCopies(int copyCount) {
493         if (copyCount < 1) {
494             throw new IllegalArgumentException("Copies must be more than one.");
495         }
496         mCopies = copyCount;
497     }
498 
499     /**
500      * Gets the included pages.
501      *
502      * @return The included pages or <code>null</code> if not set.
503      */
getPages()504     public @Nullable PageRange[] getPages() {
505         return mPageRanges;
506     }
507 
508     /**
509      * Sets the included pages.
510      *
511      * @param pageRanges The included pages.
512      *
513      * @hide
514      */
setPages(PageRange[] pageRanges)515     public void setPages(PageRange[] pageRanges) {
516         mPageRanges = pageRanges;
517     }
518 
519     /**
520      * Gets the print job attributes.
521      *
522      * @return The attributes.
523      */
getAttributes()524     public @NonNull PrintAttributes getAttributes() {
525         return mAttributes;
526     }
527 
528     /**
529      * Sets the print job attributes.
530      *
531      * @param attributes The attributes.
532      *
533      * @hide
534      */
setAttributes(PrintAttributes attributes)535     public void setAttributes(PrintAttributes attributes) {
536         mAttributes = attributes;
537     }
538 
539     /**
540      * Gets the info describing the printed document.
541      *
542      * @return The document info.
543      *
544      * @hide
545      */
getDocumentInfo()546     public PrintDocumentInfo getDocumentInfo() {
547         return mDocumentInfo;
548     }
549 
550     /**
551      * Sets the info describing the printed document.
552      *
553      * @param info The document info.
554      *
555      * @hide
556      */
setDocumentInfo(PrintDocumentInfo info)557     public void setDocumentInfo(PrintDocumentInfo info) {
558         mDocumentInfo = info;
559     }
560 
561     /**
562      * Gets whether this print is being cancelled.
563      *
564      * @return True if the print job is being cancelled.
565      *
566      * @hide
567      */
isCancelling()568     public boolean isCancelling() {
569         return mCanceling;
570     }
571 
572     /**
573      * Sets whether this print is being cancelled.
574      *
575      * @param cancelling True if the print job is being cancelled.
576      *
577      * @hide
578      */
setCancelling(boolean cancelling)579     public void setCancelling(boolean cancelling) {
580         mCanceling = cancelling;
581     }
582 
583     /**
584      * Gets whether this job has a given advanced (printer specific) print
585      * option.
586      *
587      * @param key The option key.
588      * @return Whether the option is present.
589      *
590      * @hide
591      */
hasAdvancedOption(String key)592     public boolean hasAdvancedOption(String key) {
593         return mAdvancedOptions != null && mAdvancedOptions.containsKey(key);
594     }
595 
596     /**
597      * Gets the value of an advanced (printer specific) print option.
598      *
599      * @param key The option key.
600      * @return The option value.
601      *
602      * @hide
603      */
getAdvancedStringOption(String key)604     public String getAdvancedStringOption(String key) {
605         if (mAdvancedOptions != null) {
606             return mAdvancedOptions.getString(key);
607         }
608         return null;
609     }
610 
611     /**
612      * Gets the value of an advanced (printer specific) print option.
613      *
614      * @param key The option key.
615      * @return The option value.
616      *
617      * @hide
618      */
getAdvancedIntOption(String key)619     public int getAdvancedIntOption(String key) {
620         if (mAdvancedOptions != null) {
621             return mAdvancedOptions.getInt(key);
622         }
623         return 0;
624     }
625 
626     /**
627      * Gets the advanced options.
628      *
629      * @return The advanced options.
630      *
631      * @hide
632      */
getAdvancedOptions()633     public Bundle getAdvancedOptions() {
634         return mAdvancedOptions;
635     }
636 
637     /**
638      * Sets the advanced options.
639      *
640      * @param options The advanced options.
641      *
642      * @hide
643      */
setAdvancedOptions(Bundle options)644     public void setAdvancedOptions(Bundle options) {
645         mAdvancedOptions = options;
646     }
647 
648     @Override
describeContents()649     public int describeContents() {
650         return 0;
651     }
652 
653     @Override
writeToParcel(Parcel parcel, int flags)654     public void writeToParcel(Parcel parcel, int flags) {
655         parcel.writeParcelable(mId, flags);
656         parcel.writeString(mLabel);
657         parcel.writeParcelable(mPrinterId, flags);
658         parcel.writeString(mPrinterName);
659         parcel.writeInt(mState);
660         parcel.writeInt(mAppId);
661         parcel.writeString(mTag);
662         parcel.writeLong(mCreationTime);
663         parcel.writeInt(mCopies);
664         parcel.writeParcelableArray(mPageRanges, flags);
665         parcel.writeParcelable(mAttributes, flags);
666         parcel.writeParcelable(mDocumentInfo, 0);
667         parcel.writeFloat(mProgress);
668         parcel.writeCharSequence(mStatus);
669         parcel.writeInt(mStatusRes);
670         parcel.writeCharSequence(mStatusResAppPackageName);
671         parcel.writeInt(mCanceling ? 1 : 0);
672         parcel.writeBundle(mAdvancedOptions);
673     }
674 
675     @Override
toString()676     public String toString() {
677         StringBuilder builder = new StringBuilder();
678         builder.append("PrintJobInfo{");
679         builder.append("label: ").append(mLabel);
680         builder.append(", id: ").append(mId);
681         builder.append(", state: ").append(stateToString(mState));
682         builder.append(", printer: " + mPrinterId);
683         builder.append(", tag: ").append(mTag);
684         builder.append(", creationTime: " + mCreationTime);
685         builder.append(", copies: ").append(mCopies);
686         builder.append(", attributes: " + (mAttributes != null
687                 ? mAttributes.toString() : null));
688         builder.append(", documentInfo: " + (mDocumentInfo != null
689                 ? mDocumentInfo.toString() : null));
690         builder.append(", cancelling: " + mCanceling);
691         builder.append(", pages: " + (mPageRanges != null
692                 ? Arrays.toString(mPageRanges) : null));
693         builder.append(", hasAdvancedOptions: " + (mAdvancedOptions != null));
694         builder.append(", progress: " + mProgress);
695         builder.append(", status: " + (mStatus != null
696                 ? mStatus.toString() : null));
697         builder.append(", statusRes: " + mStatusRes);
698         builder.append(", statusResAppPackageName: " + (mStatusResAppPackageName != null
699                 ? mStatusResAppPackageName.toString() : null));
700         builder.append("}");
701         return builder.toString();
702     }
703 
704     /** @hide */
stateToString(int state)705     public static String stateToString(int state) {
706         switch (state) {
707             case STATE_CREATED: {
708                 return "STATE_CREATED";
709             }
710             case STATE_QUEUED: {
711                 return "STATE_QUEUED";
712             }
713             case STATE_STARTED: {
714                 return "STATE_STARTED";
715             }
716             case STATE_BLOCKED: {
717                 return "STATE_BLOCKED";
718             }
719             case STATE_FAILED: {
720                 return "STATE_FAILED";
721             }
722             case STATE_COMPLETED: {
723                 return "STATE_COMPLETED";
724             }
725             case STATE_CANCELED: {
726                 return "STATE_CANCELED";
727             }
728             default: {
729                 return "STATE_UNKNOWN";
730             }
731         }
732     }
733 
734     /**
735      * Get the progress that has been made printing this job.
736      *
737      * @return the print progress or -1 if not set
738      * @hide
739      */
740     @TestApi
getProgress()741     public float getProgress() {
742         return mProgress;
743     }
744 
745     /**
746      * Get the status of this job.
747      *
748      * @param pm Package manager used to resolve the string
749      *
750      * @return the status of this job or null if not set
751      * @hide
752      */
753     @TestApi
getStatus(@onNull PackageManager pm)754     public @Nullable CharSequence getStatus(@NonNull PackageManager pm) {
755         if (mStatusRes == 0) {
756             return mStatus;
757         } else {
758             try {
759                 return pm.getResourcesForApplication(mStatusResAppPackageName.toString())
760                         .getString(mStatusRes);
761             } catch (PackageManager.NameNotFoundException | Resources.NotFoundException e) {
762                 return null;
763             }
764         }
765     }
766 
767     /**
768      * Builder for creating a {@link PrintJobInfo}.
769      */
770     public static final class Builder {
771         private final PrintJobInfo mPrototype;
772 
773         /**
774          * Constructor.
775          *
776          * @param prototype Prototype to use as a starting point.
777          * Can be <code>null</code>.
778          */
Builder(@ullable PrintJobInfo prototype)779         public Builder(@Nullable PrintJobInfo prototype) {
780             mPrototype = (prototype != null)
781                     ? new PrintJobInfo(prototype)
782                     : new PrintJobInfo();
783         }
784 
785         /**
786          * Sets the number of copies.
787          *
788          * @param copies The number of copies.
789          */
setCopies(@ntRangefrom = 1) int copies)790         public void setCopies(@IntRange(from = 1) int copies) {
791             mPrototype.mCopies = copies;
792         }
793 
794         /**
795          * Sets the print job attributes.
796          *
797          * @param attributes The attributes.
798          */
setAttributes(@onNull PrintAttributes attributes)799         public void setAttributes(@NonNull PrintAttributes attributes) {
800             mPrototype.mAttributes = attributes;
801         }
802 
803         /**
804          * Sets the included pages.
805          *
806          * @param pages The included pages.
807          */
setPages(@onNull PageRange[] pages)808         public void setPages(@NonNull PageRange[] pages) {
809             mPrototype.mPageRanges = pages;
810         }
811 
812         /**
813          * Sets the progress of the print job.
814          *
815          * @param progress the progress of the job
816          * @hide
817          */
setProgress(@loatRangefrom=0.0, to=1.0) float progress)818         public void setProgress(@FloatRange(from=0.0, to=1.0) float progress) {
819             Preconditions.checkArgumentInRange(progress, 0, 1, "progress");
820 
821             mPrototype.mProgress = progress;
822         }
823 
824         /**
825          * Sets the status of the print job.
826          *
827          * @param status the status of the job, can be null
828          * @hide
829          */
setStatus(@ullable CharSequence status)830         public void setStatus(@Nullable CharSequence status) {
831             mPrototype.mStatus = status;
832         }
833 
834         /**
835          * Puts an advanced (printer specific) option.
836          *
837          * @param key The option key.
838          * @param value The option value.
839          */
putAdvancedOption(@onNull String key, @Nullable String value)840         public void putAdvancedOption(@NonNull String key, @Nullable String value) {
841             Preconditions.checkNotNull(key, "key cannot be null");
842 
843             if (mPrototype.mAdvancedOptions == null) {
844                 mPrototype.mAdvancedOptions = new Bundle();
845             }
846             mPrototype.mAdvancedOptions.putString(key, value);
847         }
848 
849         /**
850          * Puts an advanced (printer specific) option.
851          *
852          * @param key The option key.
853          * @param value The option value.
854          */
putAdvancedOption(@onNull String key, int value)855         public void putAdvancedOption(@NonNull String key, int value) {
856             if (mPrototype.mAdvancedOptions == null) {
857                 mPrototype.mAdvancedOptions = new Bundle();
858             }
859             mPrototype.mAdvancedOptions.putInt(key, value);
860         }
861 
862         /**
863          * Creates a new {@link PrintJobInfo} instance.
864          *
865          * @return The new instance.
866          */
build()867         public @NonNull PrintJobInfo build() {
868             return mPrototype;
869         }
870     }
871 
872     public static final Parcelable.Creator<PrintJobInfo> CREATOR =
873             new Creator<PrintJobInfo>() {
874         @Override
875         public PrintJobInfo createFromParcel(Parcel parcel) {
876             return new PrintJobInfo(parcel);
877         }
878 
879         @Override
880         public PrintJobInfo[] newArray(int size) {
881             return new PrintJobInfo[size];
882         }
883     };
884 }
885