PrinterInfo.java revision 4b9a4d16872bbb50712e007b419ac0b35ff1582d
14b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov/*
24b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * Copyright (C) 2013 The Android Open Source Project
34b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov *
44b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * Licensed under the Apache License, Version 2.0 (the "License");
54b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * you may not use this file except in compliance with the License.
64b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * You may obtain a copy of the License at
74b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov *
84b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov *      http://www.apache.org/licenses/LICENSE-2.0
94b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov *
104b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * Unless required by applicable law or agreed to in writing, software
114b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * distributed under the License is distributed on an "AS IS" BASIS,
124b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * See the License for the specific language governing permissions and
144b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * limitations under the License.
154b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov */
164b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
174b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovpackage android.print;
184b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
194b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.os.Parcel;
204b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.os.Parcelable;
214b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.print.PrintAttributes.Margins;
224b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.print.PrintAttributes.MediaSize;
234b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.print.PrintAttributes.Resolution;
244b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.print.PrintAttributes.Tray;
254b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.text.TextUtils;
264b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.util.SparseIntArray;
274b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
284b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport java.util.ArrayList;
294b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport java.util.List;
304b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
314b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov/**
324b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * This class represents the description of a printer. A description
334b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * contains the printer id, human readable name, status, and available
344b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * options for various printer capabilities, such as media size, etc.
354b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov */
364b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovpublic final class PrinterInfo implements Parcelable {
374b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    /**
384b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * Undefined default value.
394b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     *
404b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * @hide
414b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     */
424b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    public static final int DEFAULT_UNDEFINED = -1;
434b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
444b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    private static final int MIN_COPIES = 1;
454b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
464b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    private static final int PROPERTY_MEDIA_SIZE = 0;
474b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    private static final int PROPERTY_RESOLUTION = 1;
484b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    private static final int PROPERTY_INPUT_TRAY = 2;
494b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    private static final int PROPERTY_OUTPUT_TRAY = 3;
504b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    private static final int PROPERTY_DUPLEX_MODE = 4;
514b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    private static final int PROPERTY_COLOR_MODE = 5;
524b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    private static final int PROPERTY_FITTING_MODE = 6;
534b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    private static final int PROPERTY_ORIENTATION = 7;
544b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
554b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    /** Printer status: the printer is ready to print. */
564b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    public static final int STATUS_READY = 1;
574b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
584b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    // TODO: Add printer status constants.
594b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
604b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    private PrinterId mId;
614b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    private CharSequence mLabel;
624b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    private int mStatus;
634b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
644b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    private Margins mMinMargins;
654b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    private final List<MediaSize> mMediaSizes = new ArrayList<MediaSize>(); // required
664b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    private final List<Resolution> mResolutions = new ArrayList<Resolution>(); // required
674b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    private List<Tray> mInputTrays;
684b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    private List<Tray> mOutputTrays;
694b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
704b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    private int mDuplexModes;
714b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    private int mColorModes;
724b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    private int mFittingModes;
734b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    private int mOrientations;
744b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
754b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    private final SparseIntArray mDefaults = new SparseIntArray();
764b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    private Margins mDefaultMargins;
774b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
784b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    private PrinterInfo() {
794b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        mDefaults.put(PROPERTY_MEDIA_SIZE, DEFAULT_UNDEFINED);
804b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        mDefaults.put(PROPERTY_RESOLUTION, DEFAULT_UNDEFINED);
814b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        mDefaults.put(PROPERTY_INPUT_TRAY, DEFAULT_UNDEFINED);
824b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        mDefaults.put(PROPERTY_OUTPUT_TRAY, DEFAULT_UNDEFINED);
834b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        mDefaults.put(PROPERTY_DUPLEX_MODE, DEFAULT_UNDEFINED);
844b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        mDefaults.put(PROPERTY_COLOR_MODE, DEFAULT_UNDEFINED);
854b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        mDefaults.put(PROPERTY_FITTING_MODE, DEFAULT_UNDEFINED);
864b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        mDefaults.put(PROPERTY_ORIENTATION, DEFAULT_UNDEFINED);
874b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    }
884b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
894b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    /**
904b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * Get the globally unique printer id.
914b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     *
924b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * @return The printer id.
934b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     */
944b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    public PrinterId getId() {
954b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        return mId;
964b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    }
974b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
984b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    /**
994b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * Gets the human readable printer label.
1004b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     *
1014b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * @return The human readable label.
1024b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     */
1034b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    public CharSequence getLabel() {
1044b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        return mLabel;
1054b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    }
1064b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
1074b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    /**
1084b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * Gets the status of the printer.
1094b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     *
1104b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * @return The status.
1114b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     */
1124b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    public int getStatus() {
1134b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        return mStatus;
1144b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    }
1154b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
1164b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    /**
1174b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * Gets the supported media sizes.
1184b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     *
1194b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * @return The supported media sizes.
1204b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     */
1214b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    public List<MediaSize> getMediaSizes() {
1224b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        return mMediaSizes;
1234b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    }
1244b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
1254b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    /**
1264b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * Gets the supported resolutions.
1274b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     *
1284b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * @return The supported resolutions.
1294b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     */
1304b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    public List<Resolution> getResolutions() {
1314b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        return mResolutions;
1324b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    }
1334b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
1344b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    /**
1354b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * Gets the minimal supported margins.
1364b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     *
1374b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * @return The minimal margins.
1384b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     */
1394b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    public Margins getMinMargins() {
1404b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        return mMinMargins;
1414b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    }
1424b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
1434b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    /**
1444b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * Gets the available input trays.
1454b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     *
1464b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * @return The input trays.
1474b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     */
1484b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    public List<Tray> getInputTrays() {
1494b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        return mInputTrays;
1504b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    }
1514b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
1524b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    /**
1534b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * Gets the available output trays.
1544b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     *
1554b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * @return The output trays.
1564b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     */
1574b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    public List<Tray> getOutputTrays() {
1584b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        return mOutputTrays;
1594b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    }
1604b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
1614b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    /**
1624b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * Gets the supported duplex modes.
1634b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     *
1644b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * @return The duplex modes.
1654b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     *
1664b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * @see PrintAttributes#DUPLEX_MODE_NONE
1674b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * @see PrintAttributes#DUPLEX_MODE_LONG_EDGE
1684b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * @see PrintAttributes#DUPLEX_MODE_SHORT_EDGE
1694b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     */
1704b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    public int getDuplexModes() {
1714b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        return mDuplexModes;
1724b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    }
1734b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
1744b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    /**
1754b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * Gets the supported color modes.
1764b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     *
1774b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * @return The color modes.
1784b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     *
1794b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * @see PrintAttributes#COLOR_MODE_COLOR
1804b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * @see PrintAttributes#COLOR_MODE_MONOCHROME
1814b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     */
1824b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    public int getColorModes() {
1834b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        return mColorModes;
1844b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    }
1854b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
1864b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    /**
1874b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * Gets the supported fitting modes.
1884b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     *
1894b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * @return The fitting modes.
1904b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     *
1914b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * @see PrintAttributes#FITTING_MODE_NONE
1924b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * @see PrintAttributes#FITTING_MODE_FIT_TO_PAGE
1934b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     */
1944b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    public int getFittingModes() {
1954b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        return mFittingModes;
1964b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    }
1974b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
1984b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    /**
1994b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * Gets the supported orientations.
2004b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     *
2014b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * @return The orientations.
2024b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     *
2034b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * @see PrintAttributes#ORIENTATION_PORTRAIT
2044b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * @see PrintAttributes#ORIENTATION_LANDSCAPE
2054b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     */
2064b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    public int getOrientations() {
2074b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        return mOrientations;
2084b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    }
2094b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
2104b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    /**
2114b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * Gets the default print attributes.
2124b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     *
2134b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * @param outAttributes The attributes to populated.
2144b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     */
2154b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    public void getDefaults(PrintAttributes outAttributes) {
2164b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        outAttributes.clear();
2174b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
2184b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        // TODO: Do we want a printer to specify default copies?
2194b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        outAttributes.setCopies(MIN_COPIES);
2204b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
2214b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        outAttributes.setMargins(mDefaultMargins);
2224b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
2234b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        final int mediaSizeIndex = mDefaults.get(PROPERTY_MEDIA_SIZE);
2244b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        if (mediaSizeIndex >= 0) {
2254b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            outAttributes.setMediaSize(mMediaSizes.get(mediaSizeIndex));
2264b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        }
2274b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
2284b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        final int resolutionIndex = mDefaults.get(PROPERTY_RESOLUTION);
2294b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        if (resolutionIndex >= 0) {
2304b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            outAttributes.setResolution(mResolutions.get(resolutionIndex));
2314b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        }
2324b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
2334b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        final int inputTrayIndex = mDefaults.get(PROPERTY_INPUT_TRAY);
2344b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        if (inputTrayIndex >= 0) {
2354b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            outAttributes.setInputTray(mInputTrays.get(inputTrayIndex));
2364b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        }
2374b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
2384b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        final int outputTrayIndex = mDefaults.get(PROPERTY_OUTPUT_TRAY);
2394b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        if (outputTrayIndex >= 0) {
2404b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            outAttributes.setOutputTray(mOutputTrays.get(outputTrayIndex));
2414b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        }
2424b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
2434b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        final int duplexMode = mDefaults.get(PROPERTY_DUPLEX_MODE);
2444b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        if (duplexMode > 0) {
2454b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            outAttributes.setDuplexMode(duplexMode);
2464b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        }
2474b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
2484b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        final int colorMode = mDefaults.get(PROPERTY_COLOR_MODE);
2494b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        if (colorMode > 0) {
2504b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            outAttributes.setColorMode(mColorModes & colorMode);
2514b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        }
2524b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
2534b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        final int fittingMode = mDefaults.get(PROPERTY_FITTING_MODE);
2544b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        if (fittingMode > 0) {
2554b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            outAttributes.setFittingMode(fittingMode);
2564b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        }
2574b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
2584b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        final int orientation = mDefaults.get(PROPERTY_ORIENTATION);
2594b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        if (orientation > 0) {
2604b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            outAttributes.setOrientation(orientation);
2614b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        }
2624b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    }
2634b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
2644b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    private PrinterInfo(Parcel parcel) {
2654b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        mId = parcel.readParcelable(null);
2664b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        mLabel = parcel.readCharSequence();
2674b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        mStatus = parcel.readInt();
2684b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
2694b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        mMinMargins = readMargins(parcel);
2704b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        readMediaSizes(parcel);
2714b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        readResolutions(parcel);
2724b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        mInputTrays = readInputTrays(parcel);
2734b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        mOutputTrays = readOutputTrays(parcel);
2744b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
2754b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        mColorModes = parcel.readInt();
2764b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        mDuplexModes = parcel.readInt();
2774b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        mFittingModes = parcel.readInt();
2784b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        mOrientations = parcel.readInt();
2794b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
2804b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        readDefaults(parcel);
2814b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        mDefaultMargins = readMargins(parcel);
2824b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    }
2834b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
2844b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    @Override
2854b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    public int describeContents() {
2864b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        return 0;
2874b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    }
2884b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
2894b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    @Override
2904b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    public void writeToParcel(Parcel parcel, int flags) {
2914b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        parcel.writeParcelable(mId, flags);
2924b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        parcel.writeCharSequence(mLabel);
2934b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        parcel.writeInt(mStatus);
2944b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
2954b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        writeMargins(mMinMargins, parcel);
2964b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        writeMediaSizes(parcel);
2974b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        writeResolutions(parcel);
2984b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        writeInputTrays(parcel);
2994b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        writeOutputTrays(parcel);
3004b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
3014b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        parcel.writeInt(mColorModes);
3024b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        parcel.writeInt(mDuplexModes);
3034b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        parcel.writeInt(mFittingModes);
3044b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        parcel.writeInt(mOrientations);
3054b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
3064b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        writeDefaults(parcel);
3074b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        writeMargins(mDefaultMargins, parcel);
3084b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    }
3094b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
3104b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    @Override
3114b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    public String toString() {
3124b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        StringBuilder builder = new StringBuilder();
3134b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        builder.append("PrinterInfo{");
3144b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        builder.append(mId).append(", \"");
3154b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        builder.append(mLabel);
3164b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        builder.append("\"}");
3174b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        return builder.toString();
3184b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    }
3194b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
3204b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    private void writeMediaSizes(Parcel parcel) {
3214b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        if (mMediaSizes == null) {
3224b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            parcel.writeInt(0);
3234b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            return;
3244b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        }
3254b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        final int mediaSizeCount = mMediaSizes.size();
3264b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        parcel.writeInt(mediaSizeCount);
3274b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        for (int i = 0; i < mediaSizeCount; i++) {
3284b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            mMediaSizes.get(i).writeToParcel(parcel);
3294b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        }
3304b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    }
3314b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
3324b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    private void readMediaSizes(Parcel parcel) {
3334b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        final int mediaSizeCount = parcel.readInt();
3344b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        for (int i = 0; i < mediaSizeCount; i++) {
3354b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            mMediaSizes.add(MediaSize.createFromParcel(parcel));
3364b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        }
3374b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    }
3384b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
3394b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    private void writeResolutions(Parcel parcel) {
3404b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        final int resolutionCount = mResolutions.size();
3414b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        parcel.writeInt(resolutionCount);
3424b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        for (int i = 0; i < resolutionCount; i++) {
3434b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            mResolutions.get(i).writeToParcel(parcel);
3444b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        }
3454b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    }
3464b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
3474b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    private void readResolutions(Parcel parcel) {
3484b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        final int resolutionCount = parcel.readInt();
3494b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        for (int i = 0; i < resolutionCount; i++) {
3504b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            mResolutions.add(Resolution.createFromParcel(parcel));
3514b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        }
3524b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    }
3534b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
3544b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    private void writeMargins(Margins margins, Parcel parcel) {
3554b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        if (margins == null) {
3564b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            parcel.writeInt(0);
3574b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        } else {
3584b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            parcel.writeInt(1);
3594b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            margins.writeToParcel(parcel);
3604b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        }
3614b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    }
3624b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
3634b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    private Margins readMargins(Parcel parcel) {
3644b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        return (parcel.readInt() == 1) ? Margins.createFromParcel(parcel) : null;
3654b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    }
3664b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
3674b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    private void writeInputTrays(Parcel parcel) {
3684b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        if (mInputTrays == null) {
3694b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            parcel.writeInt(0);
3704b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            return;
3714b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        }
3724b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        final int inputTrayCount = mInputTrays.size();
3734b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        parcel.writeInt(inputTrayCount);
3744b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        for (int i = 0; i < inputTrayCount; i++) {
3754b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            mInputTrays.get(i).writeToParcel(parcel);
3764b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        }
3774b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    }
3784b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
3794b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    private List<Tray> readInputTrays(Parcel parcel) {
3804b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        final int inputTrayCount = parcel.readInt();
3814b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        if (inputTrayCount <= 0) {
3824b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            return null;
3834b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        }
3844b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        List<Tray> inputTrays = new ArrayList<Tray>(inputTrayCount);
3854b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        for (int i = 0; i < inputTrayCount; i++) {
3864b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            inputTrays.add(Tray.createFromParcel(parcel));
3874b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        }
3884b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        return inputTrays;
3894b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    }
3904b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
3914b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    private void writeOutputTrays(Parcel parcel) {
3924b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        if (mOutputTrays == null) {
3934b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            parcel.writeInt(0);
3944b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            return;
3954b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        }
3964b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        final int outputTrayCount = mOutputTrays.size();
3974b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        parcel.writeInt(outputTrayCount);
3984b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        for (int i = 0; i < outputTrayCount; i++) {
3994b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            mOutputTrays.get(i).writeToParcel(parcel);
4004b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        }
4014b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    }
4024b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
4034b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    private List<Tray> readOutputTrays(Parcel parcel) {
4044b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        final int outputTrayCount = parcel.readInt();
4054b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        if (outputTrayCount <= 0) {
4064b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            return null;
4074b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        }
4084b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        List<Tray> outputTrays = new ArrayList<Tray>(outputTrayCount);
4094b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        for (int i = 0; i < outputTrayCount; i++) {
4104b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            outputTrays.add(Tray.createFromParcel(parcel));
4114b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        }
4124b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        return outputTrays;
4134b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    }
4144b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
4154b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    private void readDefaults(Parcel parcel) {
4164b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        final int defaultCount = parcel.readInt();
4174b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        for (int i = 0; i < defaultCount; i++) {
4184b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            mDefaults.append(mDefaults.size(), parcel.readInt());
4194b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        }
4204b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    }
4214b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
4224b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    private void writeDefaults(Parcel parcel) {
4234b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        final int defaultCount = mDefaults.size();
4244b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        parcel.writeInt(defaultCount);
4254b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        for (int i = 0; i < defaultCount; i++) {
4264b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            parcel.writeInt(mDefaults.valueAt(i));
4274b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        }
4284b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    }
4294b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
4304b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    /**
4314b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * Builder for creating of a {@link PrinterInfo}. This class is responsible
4324b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * to enforce that all required attributes have at least one default value.
4334b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * In other words, this class creates only well-formed {@link PrinterInfo}s.
4344b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * <p>
4354b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * Look at the individual methods for a reference whether a property is
4364b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * required or if it is optional.
4374b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * </p>
4384b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     */
4394b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    public static final class Builder {
4404b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        private final PrinterInfo mPrinterInfo;
4414b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
4424b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        /**
4434b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * Creates a new instance.
4444b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         *
4454b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * @param printerId The printer id.
4464b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * @param label The human readable printer label.
4474b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         *
4484b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * @throws IllegalArgumentException IF the printer id is null.
4494b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * @throws IllegalArgumentException IF the label is empty.
4504b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         */
4514b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        public Builder(PrinterId printerId, CharSequence label) {
4524b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            if (printerId == null) {
4534b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                throw new IllegalArgumentException("printerId cannot be null.");
4544b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            }
4554b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            if (TextUtils.isEmpty(label)) {
4564b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                throw new IllegalArgumentException("label cannot be empty.");
4574b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            }
4584b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            mPrinterInfo = new PrinterInfo();
4594b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            mPrinterInfo.mLabel = label;
4604b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            mPrinterInfo.mId = printerId;
4614b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        }
4624b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
4634b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        /**
4644b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * Sets the printer status.
4654b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * <p>
4664b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * <strong>Required:</strong> Yes
4674b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * </p>
4684b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         *
4694b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * @param status The status.
4704b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * @return This builder.
4714b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         */
4724b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        public Builder setStatus(int status) {
4734b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            mPrinterInfo.mStatus = status;
4744b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            return this;
4754b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        }
4764b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
4774b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        /**
4784b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * Adds a supported media size.
4794b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * <p>
4804b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * <strong>Required:</strong> Yes
4814b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * </p>
4824b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         *
4834b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * @param mediaSize A media size.
4844b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * @param isDefault Whether this is the default.
4854b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * @return This builder.
4864b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * @throws IllegalArgumentException If set as default and there
4874b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         *     is already a default.
4884b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         *
4894b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * @see PrintAttributes.MediaSize
4904b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         */
4914b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        public Builder addMediaSize(MediaSize mediaSize, boolean isDefault) {
4924b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            final int insertionIndex = mPrinterInfo.mMediaSizes.size();
4934b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            mPrinterInfo.mMediaSizes.add(mediaSize);
4944b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            if (isDefault) {
4954b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                throwIfDefaultAlreadySpecified(PROPERTY_MEDIA_SIZE);
4964b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                mPrinterInfo.mDefaults.put(PROPERTY_MEDIA_SIZE, insertionIndex);
4974b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            }
4984b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            return this;
4994b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        }
5004b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
5014b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        /**
5024b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * Adds a supported resolution.
5034b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * <p>
5044b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * <strong>Required:</strong> Yes
5054b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * </p>
5064b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         *
5074b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * @param resolution A resolution.
5084b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * @param isDefault Whether this is the default.
5094b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * @return This builder.
5104b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         *
5114b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * @throws IllegalArgumentException If set as default and there
5124b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         *     is already a default.
5134b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         *
5144b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * @see PrintAttributes.Resolution
5154b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         */
5164b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        public Builder addResolution(Resolution resolution, boolean isDefault) {
5174b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            final int insertionIndex = mPrinterInfo.mResolutions.size();
5184b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            mPrinterInfo.mResolutions.add(resolution);
5194b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            if (isDefault) {
5204b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                throwIfDefaultAlreadySpecified(PROPERTY_RESOLUTION);
5214b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                mPrinterInfo.mDefaults.put(PROPERTY_RESOLUTION, insertionIndex);
5224b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            }
5234b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            return this;
5244b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        }
5254b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
5264b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        /**
5274b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * Sets the minimal margins.
5284b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * <p>
5294b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * <strong>Required:</strong> No
5304b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * </p>
5314b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         *
5324b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * @param margins The margins.
5334b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * @param defaultMargins The default margins.
5344b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * @return This builder.
5354b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         *
5364b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * @see PrintAttributes.Margins
5374b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         */
5384b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        public Builder setMinMargins(Margins margins, Margins defaultMargins) {
5394b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            if (margins.getLeftMils() > defaultMargins.getLeftMils()
5404b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                    || margins.getTopMils() > defaultMargins.getTopMils()
5414b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                    || margins.getRightMils() < defaultMargins.getRightMils()
5424b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                    || margins.getBottomMils() < defaultMargins.getBottomMils()) {
5434b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                throw new IllegalArgumentException("Default margins"
5444b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                    + " cannot be outside of the min margins.");
5454b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            }
5464b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            mPrinterInfo.mMinMargins = margins;
5474b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            mPrinterInfo.mDefaultMargins = defaultMargins;
5484b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            return this;
5494b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        }
5504b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
5514b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        /**
5524b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * Adds an input tray.
5534b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * <p>
5544b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * <strong>Required:</strong> No
5554b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * </p>
5564b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         *
5574b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * @param inputTray A tray.
5584b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * @param isDefault Whether this is the default.
5594b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * @return This builder.
5604b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         *
5614b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * @throws IllegalArgumentException If set as default and there
5624b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         *     is already a default.
5634b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         *
5644b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * @see PrintAttributes.Tray
5654b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         */
5664b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        public Builder addInputTray(Tray inputTray, boolean isDefault) {
5674b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            if (mPrinterInfo.mInputTrays == null) {
5684b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                mPrinterInfo.mInputTrays = new ArrayList<Tray>();
5694b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            }
5704b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            final int insertionIndex = mPrinterInfo.mInputTrays.size();
5714b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            mPrinterInfo.mInputTrays.add(inputTray);
5724b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            if (isDefault) {
5734b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                throwIfDefaultAlreadySpecified(PROPERTY_INPUT_TRAY);
5744b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                mPrinterInfo.mDefaults.put(PROPERTY_INPUT_TRAY, insertionIndex);
5754b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            }
5764b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            return this;
5774b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        }
5784b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
5794b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        /**
5804b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * Adds an output tray.
5814b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * <p>
5824b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * <strong>Required:</strong> No
5834b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * </p>
5844b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         *
5854b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * @param outputTray A tray.
5864b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * @param isDefault Whether this is the default.
5874b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * @return This builder.
5884b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         *
5894b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * @throws IllegalArgumentException If set as default and there
5904b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         *     is already a default.
5914b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         *
5924b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * @see PrintAttributes.Tray
5934b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         */
5944b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        public Builder addOutputTray(Tray outputTray, boolean isDefault) {
5954b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            if (mPrinterInfo.mOutputTrays == null) {
5964b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                mPrinterInfo.mOutputTrays = new ArrayList<Tray>();
5974b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            }
5984b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            final int insertionIndex = mPrinterInfo.mOutputTrays.size();
5994b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            mPrinterInfo.mOutputTrays.add(outputTray);
6004b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            if (isDefault) {
6014b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                throwIfDefaultAlreadySpecified(PROPERTY_OUTPUT_TRAY);
6024b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                mPrinterInfo.mDefaults.put(PROPERTY_OUTPUT_TRAY, insertionIndex);
6034b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            }
6044b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            return this;
6054b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        }
6064b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
6074b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        /**
6084b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * Sets the color modes.
6094b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * <p>
6104b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * <strong>Required:</strong> Yes
6114b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * </p>
6124b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         *
6134b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * @param colorModes The color mode bit mask.
6144b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * @param defaultColorMode The default color mode.
6154b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * @return This builder.
6164b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         *
6174b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * @throws IllegalArgumentException If color modes contains an invalid
6184b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         *         mode bit or if the default color mode is invalid.
6194b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         *
6204b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * @see PrintAttributes#COLOR_MODE_COLOR
6214b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * @see PrintAttributes#COLOR_MODE_MONOCHROME
6224b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         */
6234b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        public Builder setColorModes(int colorModes, int defaultColorMode) {
6244b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            int currentModes = colorModes;
6254b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            while (currentModes > 0) {
6264b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                final int currentMode = (1 << Integer.numberOfTrailingZeros(currentModes));
6274b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                currentModes &= ~currentMode;
6284b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                PrintAttributes.enforceValidColorMode(currentMode);
6294b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            }
6304b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            if ((colorModes & defaultColorMode) == 0) {
6314b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                throw new IllegalArgumentException("Default color mode not in color modes.");
6324b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            }
6334b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            PrintAttributes.enforceValidColorMode(colorModes);
6344b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            mPrinterInfo.mColorModes = colorModes;
6354b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            mPrinterInfo.mDefaults.put(PROPERTY_COLOR_MODE, defaultColorMode);
6364b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            return this;
6374b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        }
6384b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
6394b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        /**
6404b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * Set the duplex modes.
6414b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * <p>
6424b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * <strong>Required:</strong> No
6434b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * </p>
6444b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         *
6454b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * @param duplexModes The duplex mode bit mask.
6464b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * @param defaultDuplexMode The default duplex mode.
6474b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * @return This builder.
6484b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         *
6494b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * @throws IllegalArgumentException If duplex modes contains an invalid
6504b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         *         mode bit or if the default duplex mode is invalid.
6514b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         *
6524b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * @see PrintAttributes#DUPLEX_MODE_NONE
6534b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * @see PrintAttributes#DUPLEX_MODE_LONG_EDGE
6544b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * @see PrintAttributes#DUPLEX_MODE_SHORT_EDGE
6554b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         */
6564b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        public Builder setDuplexModes(int duplexModes, int defaultDuplexMode) {
6574b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            int currentModes = duplexModes;
6584b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            while (currentModes > 0) {
6594b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                final int currentMode = (1 << Integer.numberOfTrailingZeros(currentModes));
6604b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                currentModes &= ~currentMode;
6614b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                PrintAttributes.enforceValidDuplexMode(currentMode);
6624b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            }
6634b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            if ((duplexModes & defaultDuplexMode) == 0) {
6644b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                throw new IllegalArgumentException("Default duplex mode not in duplex modes.");
6654b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            }
6664b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            PrintAttributes.enforceValidDuplexMode(defaultDuplexMode);
6674b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            mPrinterInfo.mDuplexModes = duplexModes;
6684b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            mPrinterInfo.mDefaults.put(PROPERTY_DUPLEX_MODE, defaultDuplexMode);
6694b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            return this;
6704b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        }
6714b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
6724b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        /**
6734b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * Sets the fitting modes.
6744b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * <p>
6754b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * <strong>Required:</strong> No
6764b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * </p>
6774b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         *
6784b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * @param fittingModes The fitting mode bit mask.
6794b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * @param defaultFittingMode The default fitting mode.
6804b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * @return This builder.
6814b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         *
6824b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * @throws IllegalArgumentException If fitting modes contains an invalid
6834b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         *         mode bit or if the default fitting mode is invalid.
6844b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         *
6854b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * @see PrintAttributes#FITTING_MODE_NONE
6864b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * @see PrintAttributes#FITTING_MODE_FIT_TO_PAGE
6874b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         */
6884b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        public Builder setFittingModes(int fittingModes, int defaultFittingMode) {
6894b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            int currentModes = fittingModes;
6904b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            while (currentModes > 0) {
6914b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                final int currentMode = (1 << Integer.numberOfTrailingZeros(currentModes));
6924b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                currentModes &= ~currentMode;
6934b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                PrintAttributes.enfoceValidFittingMode(currentMode);
6944b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            }
6954b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            if ((fittingModes & defaultFittingMode) == 0) {
6964b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                throw new IllegalArgumentException("Default fitting mode not in fiting modes.");
6974b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            }
6984b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            PrintAttributes.enfoceValidFittingMode(defaultFittingMode);
6994b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            mPrinterInfo.mFittingModes = fittingModes;
7004b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            mPrinterInfo.mDefaults.put(PROPERTY_FITTING_MODE, defaultFittingMode);
7014b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            return this;
7024b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        }
7034b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
7044b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        /**
7054b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * Sets the orientations.
7064b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * <p>
7074b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * <strong>Required:</strong> Yes
7084b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * </p>
7094b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         *
7104b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * @param orientations The orientation bit mask.
7114b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * @param defaultOrientation The default orientation.
7124b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * @return This builder.
7134b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         *
7144b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * @throws IllegalArgumentException If orientations contains an invalid
7154b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         *         mode bit or if the default orientation is invalid.
7164b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         *
7174b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * @see PrintAttributes#ORIENTATION_PORTRAIT
7184b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * @see PrintAttributes#ORIENTATION_LANDSCAPE
7194b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         */
7204b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        public Builder setOrientations(int orientations, int defaultOrientation) {
7214b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            int currentOrientaions = orientations;
7224b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            while (currentOrientaions > 0) {
7234b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                final int currentOrnt = (1 << Integer.numberOfTrailingZeros(currentOrientaions));
7244b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                currentOrientaions &= ~currentOrnt;
7254b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                PrintAttributes.enforceValidOrientation(currentOrnt);
7264b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            }
7274b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            if ((orientations & defaultOrientation) == 0) {
7284b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                throw new IllegalArgumentException("Default orientation not in orientations.");
7294b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            }
7304b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            PrintAttributes.enforceValidOrientation(defaultOrientation);
7314b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            mPrinterInfo.mOrientations = orientations;
7324b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            mPrinterInfo.mDefaults.put(PROPERTY_ORIENTATION, defaultOrientation);
7334b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            return this;
7344b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        }
7354b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
7364b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        /**
7374b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * Crates a new {@link PrinterInfo} enforcing that all required properties
7384b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * have need specified. See individual methods in this class for reference
7394b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * about required attributes.
7404b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         *
7414b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * @return A new {@link PrinterInfo}.
7424b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         *
7434b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         * @throws IllegalStateException If a required attribute was not specified.
7444b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov         */
7454b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        public PrinterInfo create() {
7464b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            if (mPrinterInfo.mMediaSizes == null || mPrinterInfo.mMediaSizes.isEmpty()) {
7474b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                throw new IllegalStateException("No media size specified.");
7484b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            }
7494b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            if (mPrinterInfo.mDefaults.valueAt(PROPERTY_MEDIA_SIZE) == DEFAULT_UNDEFINED) {
7504b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                throw new IllegalStateException("No default media size specified.");
7514b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            }
7524b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            if (mPrinterInfo.mResolutions == null || mPrinterInfo.mResolutions.isEmpty()) {
7534b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                throw new IllegalStateException("No resolution specified.");
7544b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            }
7554b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            if (mPrinterInfo.mDefaults.valueAt(PROPERTY_RESOLUTION) == DEFAULT_UNDEFINED) {
7564b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                throw new IllegalStateException("No default resolution specified.");
7574b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            }
7584b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            if (mPrinterInfo.mColorModes == 0) {
7594b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                throw new IllegalStateException("No color mode specified.");
7604b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            }
7614b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            if (mPrinterInfo.mDefaults.valueAt(PROPERTY_COLOR_MODE) == DEFAULT_UNDEFINED) {
7624b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                throw new IllegalStateException("No default color mode specified.");
7634b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            }
7644b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            if (mPrinterInfo.mOrientations == 0) {
7654b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                throw new IllegalStateException("No oprientation specified.");
7664b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            }
7674b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            if (mPrinterInfo.mDefaults.valueAt(PROPERTY_ORIENTATION) == DEFAULT_UNDEFINED) {
7684b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                throw new IllegalStateException("No default orientation specified.");
7694b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            }
7704b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            if (mPrinterInfo.mMinMargins == null) {
7714b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                mPrinterInfo.mMinMargins  = new Margins(0, 0, 0, 0);
7724b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            }
7734b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            if (mPrinterInfo.mDefaultMargins == null) {
7744b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                mPrinterInfo.mDefaultMargins = mPrinterInfo.mMinMargins;
7754b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            }
7764b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            return mPrinterInfo;
7774b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        }
7784b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
7794b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        private void throwIfDefaultAlreadySpecified(int propertyIndex) {
7804b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            if (mPrinterInfo.mDefaults.get(propertyIndex) != DEFAULT_UNDEFINED) {
7814b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                throw new IllegalArgumentException("Default already specified.");
7824b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            }
7834b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        }
7844b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    }
7854b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
7864b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    public static final Parcelable.Creator<PrinterInfo> CREATOR =
7874b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            new Parcelable.Creator<PrinterInfo>() {
7884b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        @Override
7894b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        public PrinterInfo createFromParcel(Parcel parcel) {
7904b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            return new PrinterInfo(parcel);
7914b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        }
7924b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
7934b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        @Override
7944b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        public PrinterInfo[] newArray(int size) {
7954b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            return new PrinterInfo[size];
7964b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        }
7974b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    };
7984b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov}
799