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 import android.service.print.PrintJobInfoProto;
     32 
     33 import com.android.internal.util.Preconditions;
     34 
     35 import java.lang.annotation.Retention;
     36 import java.lang.annotation.RetentionPolicy;
     37 import java.util.Arrays;
     38 
     39 /**
     40  * This class represents the description of a print job. The print job
     41  * state includes properties such as its id, print attributes used for
     42  * generating the content, and so on. Note that the print jobs state may
     43  * change over time and this class represents a snapshot of this state.
     44  */
     45 public final class PrintJobInfo implements Parcelable {
     46 
     47     /** @hide */
     48     @IntDef(prefix = { "STATE_" }, value = {
     49             STATE_CREATED,
     50             STATE_QUEUED,
     51             STATE_STARTED,
     52             STATE_BLOCKED,
     53             STATE_COMPLETED,
     54             STATE_FAILED,
     55             STATE_CANCELED
     56     })
     57     @Retention(RetentionPolicy.SOURCE)
     58     public @interface State {
     59     }
     60 
     61     /**
     62      * Constant for matching any print job state.
     63      *
     64      * @hide
     65      */
     66     public static final int STATE_ANY = -1;
     67 
     68     /**
     69      * Constant for matching any print job state.
     70      *
     71      * @hide
     72      */
     73     public static final int STATE_ANY_VISIBLE_TO_CLIENTS = -2;
     74 
     75     /**
     76      * Constant for matching any active print job state.
     77      *
     78      * @hide
     79      */
     80     public static final int STATE_ANY_ACTIVE = -3;
     81 
     82     /**
     83      * Constant for matching any scheduled, i.e. delivered to a print
     84      * service, print job state.
     85      *
     86      * @hide
     87      */
     88     public static final int STATE_ANY_SCHEDULED = -4;
     89 
     90     /**
     91      * Print job state: The print job is being created but not yet
     92      * ready to be printed.
     93      * <p>
     94      * Next valid states: {@link #STATE_QUEUED}
     95      * </p>
     96      */
     97     public static final int STATE_CREATED = PrintJobInfoProto.STATE_CREATED;
     98 
     99     /**
    100      * Print job state: The print jobs is created, it is ready
    101      * to be printed and should be processed.
    102      * <p>
    103      * Next valid states: {@link #STATE_STARTED}, {@link #STATE_FAILED},
    104      * {@link #STATE_CANCELED}
    105      * </p>
    106      */
    107     public static final int STATE_QUEUED = PrintJobInfoProto.STATE_QUEUED;
    108 
    109     /**
    110      * Print job state: The print job is being printed.
    111      * <p>
    112      * Next valid states: {@link #STATE_COMPLETED}, {@link #STATE_FAILED},
    113      * {@link #STATE_CANCELED}, {@link #STATE_BLOCKED}
    114      * </p>
    115      */
    116     public static final int STATE_STARTED = PrintJobInfoProto.STATE_STARTED;
    117 
    118     /**
    119      * Print job state: The print job is blocked.
    120      * <p>
    121      * Next valid states: {@link #STATE_FAILED}, {@link #STATE_CANCELED},
    122      * {@link #STATE_STARTED}
    123      * </p>
    124      */
    125     public static final int STATE_BLOCKED = PrintJobInfoProto.STATE_BLOCKED;
    126 
    127     /**
    128      * Print job state: The print job is successfully printed.
    129      * This is a terminal state.
    130      * <p>
    131      * Next valid states: None
    132      * </p>
    133      */
    134     public static final int STATE_COMPLETED = PrintJobInfoProto.STATE_COMPLETED;
    135 
    136     /**
    137      * Print job state: The print job was printing but printing failed.
    138      * <p>
    139      * Next valid states: {@link #STATE_CANCELED}, {@link #STATE_STARTED}
    140      * </p>
    141      */
    142     public static final int STATE_FAILED = PrintJobInfoProto.STATE_FAILED;
    143 
    144     /**
    145      * Print job state: The print job is canceled.
    146      * This is a terminal state.
    147      * <p>
    148      * Next valid states: None
    149      * </p>
    150      */
    151     public static final int STATE_CANCELED = PrintJobInfoProto.STATE_CANCELED;
    152 
    153     /** The unique print job id. */
    154     private PrintJobId mId;
    155 
    156     /** The human readable print job label. */
    157     private String mLabel;
    158 
    159     /** The unique id of the printer. */
    160     private PrinterId mPrinterId;
    161 
    162     /** The name of the printer - internally used */
    163     private String mPrinterName;
    164 
    165     /** The state of the print job. */
    166     private int mState;
    167 
    168     /** The id of the app that created the job. */
    169     private int mAppId;
    170 
    171     /** Optional tag assigned by a print service.*/
    172     private String mTag;
    173 
    174     /** The wall time when the print job was created. */
    175     private long mCreationTime;
    176 
    177     /** How many copies to print. */
    178     private int mCopies;
    179 
    180     /** The pages to print */
    181     private PageRange[] mPageRanges;
    182 
    183     /** The print job attributes size. */
    184     private PrintAttributes mAttributes;
    185 
    186     /** Information about the printed document. */
    187     private PrintDocumentInfo mDocumentInfo;
    188 
    189     /** The progress made on printing this job or -1 if not set. */
    190     private float mProgress;
    191 
    192     /** A short string describing the status of this job. */
    193     private @Nullable CharSequence mStatus;
    194 
    195     /** A string resource describing the status of this job. */
    196     private @StringRes int mStatusRes;
    197     private @Nullable CharSequence mStatusResAppPackageName;
    198 
    199     /** Advanced printer specific options. */
    200     private Bundle mAdvancedOptions;
    201 
    202     /** Whether we are trying to cancel this print job. */
    203     private boolean mCanceling;
    204 
    205     /** @hide*/
    206     public PrintJobInfo() {
    207         mProgress = -1;
    208     }
    209 
    210     /** @hide */
    211     public PrintJobInfo(PrintJobInfo other) {
    212         mId = other.mId;
    213         mLabel = other.mLabel;
    214         mPrinterId = other.mPrinterId;
    215         mPrinterName = other.mPrinterName;
    216         mState = other.mState;
    217         mAppId = other.mAppId;
    218         mTag = other.mTag;
    219         mCreationTime = other.mCreationTime;
    220         mCopies = other.mCopies;
    221         mPageRanges = other.mPageRanges;
    222         mAttributes = other.mAttributes;
    223         mDocumentInfo = other.mDocumentInfo;
    224         mProgress = other.mProgress;
    225         mStatus = other.mStatus;
    226         mStatusRes = other.mStatusRes;
    227         mStatusResAppPackageName = other.mStatusResAppPackageName;
    228         mCanceling = other.mCanceling;
    229         mAdvancedOptions = other.mAdvancedOptions;
    230     }
    231 
    232     private PrintJobInfo(@NonNull Parcel parcel) {
    233         mId = parcel.readParcelable(null);
    234         mLabel = parcel.readString();
    235         mPrinterId = parcel.readParcelable(null);
    236         mPrinterName = parcel.readString();
    237         mState = parcel.readInt();
    238         mAppId = parcel.readInt();
    239         mTag = parcel.readString();
    240         mCreationTime = parcel.readLong();
    241         mCopies = parcel.readInt();
    242         Parcelable[] parcelables = parcel.readParcelableArray(null);
    243         if (parcelables != null) {
    244             mPageRanges = new PageRange[parcelables.length];
    245             for (int i = 0; i < parcelables.length; i++) {
    246                 mPageRanges[i] = (PageRange) parcelables[i];
    247             }
    248         }
    249         mAttributes = (PrintAttributes) parcel.readParcelable(null);
    250         mDocumentInfo = (PrintDocumentInfo) parcel.readParcelable(null);
    251         mProgress = parcel.readFloat();
    252         mStatus = parcel.readCharSequence();
    253         mStatusRes = parcel.readInt();
    254         mStatusResAppPackageName = parcel.readCharSequence();
    255         mCanceling = (parcel.readInt() == 1);
    256         mAdvancedOptions = parcel.readBundle();
    257 
    258         if (mAdvancedOptions != null) {
    259             Preconditions.checkArgument(!mAdvancedOptions.containsKey(null));
    260         }
    261     }
    262 
    263     /**
    264      * Gets the unique print job id.
    265      *
    266      * @return The id.
    267      */
    268     public @Nullable PrintJobId getId() {
    269         return mId;
    270     }
    271 
    272     /**
    273      * Sets the unique print job id.
    274      *
    275      * @param id The job id.
    276      *
    277      * @hide
    278      */
    279     public void setId(@NonNull PrintJobId id) {
    280         this.mId = id;
    281     }
    282 
    283     /**
    284      * Gets the human readable job label.
    285      *
    286      * @return The label.
    287      */
    288     public @NonNull String getLabel() {
    289         return mLabel;
    290     }
    291 
    292     /**
    293      * Sets the human readable job label.
    294      *
    295      * @param label The label.
    296      *
    297      * @hide
    298      */
    299     public void setLabel(@NonNull String label) {
    300         mLabel = label;
    301     }
    302 
    303     /**
    304      * Gets the unique target printer id.
    305      *
    306      * @return The target printer id.
    307      */
    308     public @Nullable PrinterId getPrinterId() {
    309         return mPrinterId;
    310     }
    311 
    312     /**
    313      * Sets the unique target printer id.
    314      *
    315      * @param printerId The target printer id.
    316      *
    317      * @hide
    318      */
    319     public void setPrinterId(@NonNull PrinterId printerId) {
    320         mPrinterId = printerId;
    321     }
    322 
    323     /**
    324      * Gets the name of the target printer.
    325      *
    326      * @return The printer name.
    327      *
    328      * @hide
    329      */
    330     public @Nullable String getPrinterName() {
    331         return mPrinterName;
    332     }
    333 
    334     /**
    335      * Sets the name of the target printer.
    336      *
    337      * @param printerName The printer name.
    338      *
    339      * @hide
    340      */
    341     public void setPrinterName(@NonNull String printerName) {
    342         mPrinterName = printerName;
    343     }
    344 
    345     /**
    346      * Gets the current job state.
    347      *
    348      * @return The job state.
    349      *
    350      * @see #STATE_CREATED
    351      * @see #STATE_QUEUED
    352      * @see #STATE_STARTED
    353      * @see #STATE_COMPLETED
    354      * @see #STATE_BLOCKED
    355      * @see #STATE_FAILED
    356      * @see #STATE_CANCELED
    357      */
    358     public @State int getState() {
    359         return mState;
    360     }
    361 
    362     /**
    363      * Sets the current job state.
    364      *
    365      * @param state The job state.
    366      *
    367      * @hide
    368      */
    369     public void setState(int state) {
    370         mState = state;
    371     }
    372 
    373     /**
    374      * Sets the progress of the print job.
    375      *
    376      * @param progress the progress of the job
    377      *
    378      * @hide
    379      */
    380     public void setProgress(@FloatRange(from=0.0, to=1.0) float progress) {
    381         Preconditions.checkArgumentInRange(progress, 0, 1, "progress");
    382 
    383         mProgress = progress;
    384     }
    385 
    386     /**
    387      * Sets the status of the print job.
    388      *
    389      * @param status the status of the job, can be null
    390      *
    391      * @hide
    392      */
    393     public void setStatus(@Nullable CharSequence status) {
    394         mStatusRes = 0;
    395         mStatusResAppPackageName = null;
    396 
    397         mStatus = status;
    398     }
    399 
    400     /**
    401      * Sets the status of the print job.
    402      *
    403      * @param status The new status as a string resource
    404      * @param appPackageName App package name the resource belongs to
    405      *
    406      * @hide
    407      */
    408     public void setStatus(@StringRes int status, @NonNull CharSequence appPackageName) {
    409         mStatus = null;
    410 
    411         mStatusRes = status;
    412         mStatusResAppPackageName = appPackageName;
    413     }
    414 
    415     /**
    416      * Sets the owning application id.
    417      *
    418      * @return The owning app id.
    419      *
    420      * @hide
    421      */
    422     public int getAppId() {
    423         return mAppId;
    424     }
    425 
    426     /**
    427      * Sets the owning application id.
    428      *
    429      * @param appId The owning app id.
    430      *
    431      * @hide
    432      */
    433     public void setAppId(int appId) {
    434         mAppId = appId;
    435     }
    436 
    437     /**
    438      * Gets the optional tag assigned by a print service.
    439      *
    440      * @return The tag.
    441      *
    442      * @hide
    443      */
    444     public String getTag() {
    445         return mTag;
    446     }
    447 
    448     /**
    449      * Sets the optional tag assigned by a print service.
    450      *
    451      * @param tag The tag.
    452      *
    453      * @hide
    454      */
    455     public void setTag(String tag) {
    456         mTag = tag;
    457     }
    458 
    459     /**
    460      * Gets the wall time in millisecond when this print job was created.
    461      *
    462      * @return The creation time in milliseconds.
    463      */
    464     public long getCreationTime() {
    465         return mCreationTime;
    466     }
    467 
    468     /**
    469      * Sets the wall time in milliseconds when this print job was created.
    470      *
    471      * @param creationTime The creation time in milliseconds.
    472      *
    473      * @hide
    474      */
    475     public void setCreationTime(long creationTime) {
    476         if (creationTime < 0) {
    477             throw new IllegalArgumentException("creationTime must be non-negative.");
    478         }
    479         mCreationTime = creationTime;
    480     }
    481 
    482     /**
    483      * Gets the number of copies.
    484      *
    485      * @return The number of copies or zero if not set.
    486      */
    487     public @IntRange(from = 0) int getCopies() {
    488         return mCopies;
    489     }
    490 
    491     /**
    492      * Sets the number of copies.
    493      *
    494      * @param copyCount The number of copies.
    495      *
    496      * @hide
    497      */
    498     public void setCopies(int copyCount) {
    499         if (copyCount < 1) {
    500             throw new IllegalArgumentException("Copies must be more than one.");
    501         }
    502         mCopies = copyCount;
    503     }
    504 
    505     /**
    506      * Gets the included pages.
    507      *
    508      * @return The included pages or <code>null</code> if not set.
    509      */
    510     public @Nullable PageRange[] getPages() {
    511         return mPageRanges;
    512     }
    513 
    514     /**
    515      * Sets the included pages.
    516      *
    517      * @param pageRanges The included pages.
    518      *
    519      * @hide
    520      */
    521     public void setPages(PageRange[] pageRanges) {
    522         mPageRanges = pageRanges;
    523     }
    524 
    525     /**
    526      * Gets the print job attributes.
    527      *
    528      * @return The attributes.
    529      */
    530     public @NonNull PrintAttributes getAttributes() {
    531         return mAttributes;
    532     }
    533 
    534     /**
    535      * Sets the print job attributes.
    536      *
    537      * @param attributes The attributes.
    538      *
    539      * @hide
    540      */
    541     public void setAttributes(PrintAttributes attributes) {
    542         mAttributes = attributes;
    543     }
    544 
    545     /**
    546      * Gets the info describing the printed document.
    547      *
    548      * @return The document info.
    549      *
    550      * @hide
    551      */
    552     public PrintDocumentInfo getDocumentInfo() {
    553         return mDocumentInfo;
    554     }
    555 
    556     /**
    557      * Sets the info describing the printed document.
    558      *
    559      * @param info The document info.
    560      *
    561      * @hide
    562      */
    563     public void setDocumentInfo(PrintDocumentInfo info) {
    564         mDocumentInfo = info;
    565     }
    566 
    567     /**
    568      * Gets whether this print is being cancelled.
    569      *
    570      * @return True if the print job is being cancelled.
    571      *
    572      * @hide
    573      */
    574     public boolean isCancelling() {
    575         return mCanceling;
    576     }
    577 
    578     /**
    579      * Sets whether this print is being cancelled.
    580      *
    581      * @param cancelling True if the print job is being cancelled.
    582      *
    583      * @hide
    584      */
    585     public void setCancelling(boolean cancelling) {
    586         mCanceling = cancelling;
    587     }
    588 
    589     /**
    590      * Gets whether this job has a given advanced (printer specific) print
    591      * option.
    592      *
    593      * @param key The option key.
    594      * @return Whether the option is present.
    595      */
    596     public boolean hasAdvancedOption(String key) {
    597         return mAdvancedOptions != null && mAdvancedOptions.containsKey(key);
    598     }
    599 
    600     /**
    601      * Gets the value of an advanced (printer specific) print option.
    602      *
    603      * @param key The option key.
    604      * @return The option value.
    605      */
    606     public String getAdvancedStringOption(String key) {
    607         if (mAdvancedOptions != null) {
    608             return mAdvancedOptions.getString(key);
    609         }
    610         return null;
    611     }
    612 
    613     /**
    614      * Gets the value of an advanced (printer specific) print option.
    615      *
    616      * @param key The option key.
    617      * @return The option value.
    618      */
    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      */
    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      */
    644     public void setAdvancedOptions(Bundle options) {
    645         mAdvancedOptions = options;
    646     }
    647 
    648     @Override
    649     public int describeContents() {
    650         return 0;
    651     }
    652 
    653     @Override
    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
    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 */
    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
    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
    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          */
    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          */
    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          */
    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          */
    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          */
    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          */
    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          */
    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          */
    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          */
    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