Home | History | Annotate | Download | only in print
      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*/
    200     public PrintJobInfo() {
    201         mProgress = -1;
    202     }
    203 
    204     /** @hide */
    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 
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    515     public void setPages(PageRange[] pageRanges) {
    516         mPageRanges = pageRanges;
    517     }
    518 
    519     /**
    520      * Gets the print job attributes.
    521      *
    522      * @return The attributes.
    523      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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     public boolean hasAdvancedOption(String key) {
    591         return mAdvancedOptions != null && mAdvancedOptions.containsKey(key);
    592     }
    593 
    594     /**
    595      * Gets the value of an advanced (printer specific) print option.
    596      *
    597      * @param key The option key.
    598      * @return The option value.
    599      */
    600     public String getAdvancedStringOption(String key) {
    601         if (mAdvancedOptions != null) {
    602             return mAdvancedOptions.getString(key);
    603         }
    604         return null;
    605     }
    606 
    607     /**
    608      * Gets the value of an advanced (printer specific) print option.
    609      *
    610      * @param key The option key.
    611      * @return The option value.
    612      */
    613     public int getAdvancedIntOption(String key) {
    614         if (mAdvancedOptions != null) {
    615             return mAdvancedOptions.getInt(key);
    616         }
    617         return 0;
    618     }
    619 
    620     /**
    621      * Gets the advanced options.
    622      *
    623      * @return The advanced options.
    624      *
    625      * @hide
    626      */
    627     public Bundle getAdvancedOptions() {
    628         return mAdvancedOptions;
    629     }
    630 
    631     /**
    632      * Sets the advanced options.
    633      *
    634      * @param options The advanced options.
    635      *
    636      * @hide
    637      */
    638     public void setAdvancedOptions(Bundle options) {
    639         mAdvancedOptions = options;
    640     }
    641 
    642     @Override
    643     public int describeContents() {
    644         return 0;
    645     }
    646 
    647     @Override
    648     public void writeToParcel(Parcel parcel, int flags) {
    649         parcel.writeParcelable(mId, flags);
    650         parcel.writeString(mLabel);
    651         parcel.writeParcelable(mPrinterId, flags);
    652         parcel.writeString(mPrinterName);
    653         parcel.writeInt(mState);
    654         parcel.writeInt(mAppId);
    655         parcel.writeString(mTag);
    656         parcel.writeLong(mCreationTime);
    657         parcel.writeInt(mCopies);
    658         parcel.writeParcelableArray(mPageRanges, flags);
    659         parcel.writeParcelable(mAttributes, flags);
    660         parcel.writeParcelable(mDocumentInfo, 0);
    661         parcel.writeFloat(mProgress);
    662         parcel.writeCharSequence(mStatus);
    663         parcel.writeInt(mStatusRes);
    664         parcel.writeCharSequence(mStatusResAppPackageName);
    665         parcel.writeInt(mCanceling ? 1 : 0);
    666         parcel.writeBundle(mAdvancedOptions);
    667     }
    668 
    669     @Override
    670     public String toString() {
    671         StringBuilder builder = new StringBuilder();
    672         builder.append("PrintJobInfo{");
    673         builder.append("label: ").append(mLabel);
    674         builder.append(", id: ").append(mId);
    675         builder.append(", state: ").append(stateToString(mState));
    676         builder.append(", printer: " + mPrinterId);
    677         builder.append(", tag: ").append(mTag);
    678         builder.append(", creationTime: " + mCreationTime);
    679         builder.append(", copies: ").append(mCopies);
    680         builder.append(", attributes: " + (mAttributes != null
    681                 ? mAttributes.toString() : null));
    682         builder.append(", documentInfo: " + (mDocumentInfo != null
    683                 ? mDocumentInfo.toString() : null));
    684         builder.append(", cancelling: " + mCanceling);
    685         builder.append(", pages: " + (mPageRanges != null
    686                 ? Arrays.toString(mPageRanges) : null));
    687         builder.append(", hasAdvancedOptions: " + (mAdvancedOptions != null));
    688         builder.append(", progress: " + mProgress);
    689         builder.append(", status: " + (mStatus != null
    690                 ? mStatus.toString() : null));
    691         builder.append(", statusRes: " + mStatusRes);
    692         builder.append(", statusResAppPackageName: " + (mStatusResAppPackageName != null
    693                 ? mStatusResAppPackageName.toString() : null));
    694         builder.append("}");
    695         return builder.toString();
    696     }
    697 
    698     /** @hide */
    699     public static String stateToString(int state) {
    700         switch (state) {
    701             case STATE_CREATED: {
    702                 return "STATE_CREATED";
    703             }
    704             case STATE_QUEUED: {
    705                 return "STATE_QUEUED";
    706             }
    707             case STATE_STARTED: {
    708                 return "STATE_STARTED";
    709             }
    710             case STATE_BLOCKED: {
    711                 return "STATE_BLOCKED";
    712             }
    713             case STATE_FAILED: {
    714                 return "STATE_FAILED";
    715             }
    716             case STATE_COMPLETED: {
    717                 return "STATE_COMPLETED";
    718             }
    719             case STATE_CANCELED: {
    720                 return "STATE_CANCELED";
    721             }
    722             default: {
    723                 return "STATE_UNKNOWN";
    724             }
    725         }
    726     }
    727 
    728     /**
    729      * Get the progress that has been made printing this job.
    730      *
    731      * @return the print progress or -1 if not set
    732      * @hide
    733      */
    734     @TestApi
    735     public float getProgress() {
    736         return mProgress;
    737     }
    738 
    739     /**
    740      * Get the status of this job.
    741      *
    742      * @param pm Package manager used to resolve the string
    743      *
    744      * @return the status of this job or null if not set
    745      * @hide
    746      */
    747     @TestApi
    748     public @Nullable CharSequence getStatus(@NonNull PackageManager pm) {
    749         if (mStatusRes == 0) {
    750             return mStatus;
    751         } else {
    752             try {
    753                 return pm.getResourcesForApplication(mStatusResAppPackageName.toString())
    754                         .getString(mStatusRes);
    755             } catch (PackageManager.NameNotFoundException | Resources.NotFoundException e) {
    756                 return null;
    757             }
    758         }
    759     }
    760 
    761     /**
    762      * Builder for creating a {@link PrintJobInfo}.
    763      */
    764     public static final class Builder {
    765         private final PrintJobInfo mPrototype;
    766 
    767         /**
    768          * Constructor.
    769          *
    770          * @param prototype Prototype to use as a starting point.
    771          * Can be <code>null</code>.
    772          */
    773         public Builder(@Nullable PrintJobInfo prototype) {
    774             mPrototype = (prototype != null)
    775                     ? new PrintJobInfo(prototype)
    776                     : new PrintJobInfo();
    777         }
    778 
    779         /**
    780          * Sets the number of copies.
    781          *
    782          * @param copies The number of copies.
    783          */
    784         public void setCopies(@IntRange(from = 1) int copies) {
    785             mPrototype.mCopies = copies;
    786         }
    787 
    788         /**
    789          * Sets the print job attributes.
    790          *
    791          * @param attributes The attributes.
    792          */
    793         public void setAttributes(@NonNull PrintAttributes attributes) {
    794             mPrototype.mAttributes = attributes;
    795         }
    796 
    797         /**
    798          * Sets the included pages.
    799          *
    800          * @param pages The included pages.
    801          */
    802         public void setPages(@NonNull PageRange[] pages) {
    803             mPrototype.mPageRanges = pages;
    804         }
    805 
    806         /**
    807          * Sets the progress of the print job.
    808          *
    809          * @param progress the progress of the job
    810          * @hide
    811          */
    812         public void setProgress(@FloatRange(from=0.0, to=1.0) float progress) {
    813             Preconditions.checkArgumentInRange(progress, 0, 1, "progress");
    814 
    815             mPrototype.mProgress = progress;
    816         }
    817 
    818         /**
    819          * Sets the status of the print job.
    820          *
    821          * @param status the status of the job, can be null
    822          * @hide
    823          */
    824         public void setStatus(@Nullable CharSequence status) {
    825             mPrototype.mStatus = status;
    826         }
    827 
    828         /**
    829          * Puts an advanced (printer specific) option.
    830          *
    831          * @param key The option key.
    832          * @param value The option value.
    833          */
    834         public void putAdvancedOption(@NonNull String key, @Nullable String value) {
    835             Preconditions.checkNotNull(key, "key cannot be null");
    836 
    837             if (mPrototype.mAdvancedOptions == null) {
    838                 mPrototype.mAdvancedOptions = new Bundle();
    839             }
    840             mPrototype.mAdvancedOptions.putString(key, value);
    841         }
    842 
    843         /**
    844          * Puts an advanced (printer specific) option.
    845          *
    846          * @param key The option key.
    847          * @param value The option value.
    848          */
    849         public void putAdvancedOption(@NonNull String key, int value) {
    850             if (mPrototype.mAdvancedOptions == null) {
    851                 mPrototype.mAdvancedOptions = new Bundle();
    852             }
    853             mPrototype.mAdvancedOptions.putInt(key, value);
    854         }
    855 
    856         /**
    857          * Creates a new {@link PrintJobInfo} instance.
    858          *
    859          * @return The new instance.
    860          */
    861         public @NonNull PrintJobInfo build() {
    862             return mPrototype;
    863         }
    864     }
    865 
    866     public static final Parcelable.Creator<PrintJobInfo> CREATOR =
    867             new Creator<PrintJobInfo>() {
    868         @Override
    869         public PrintJobInfo createFromParcel(Parcel parcel) {
    870             return new PrintJobInfo(parcel);
    871         }
    872 
    873         @Override
    874         public PrintJobInfo[] newArray(int size) {
    875             return new PrintJobInfo[size];
    876         }
    877     };
    878 }
    879