1798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov/*
2798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * Copyright (C) 2013 The Android Open Source Project
3798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov *
4798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * Licensed under the Apache License, Version 2.0 (the "License");
5798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * you may not use this file except in compliance with the License.
6798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * You may obtain a copy of the License at
7798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov *
8798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov *      http://www.apache.org/licenses/LICENSE-2.0
9798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov *
10798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * Unless required by applicable law or agreed to in writing, software
11798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * distributed under the License is distributed on an "AS IS" BASIS,
12798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * See the License for the specific language governing permissions and
14798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * limitations under the License.
15798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov */
16798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
17798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganovpackage android.print;
18798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
19c43639c3067dda5df189fb3cbf14f256c17e677dPhilip P. Moltmannimport android.annotation.NonNull;
20798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganovimport android.os.Parcel;
21798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganovimport android.os.Parcelable;
22c43639c3067dda5df189fb3cbf14f256c17e677dPhilip P. Moltmannimport android.print.PrintAttributes.ColorMode;
23c43639c3067dda5df189fb3cbf14f256c17e677dPhilip P. Moltmannimport android.print.PrintAttributes.DuplexMode;
24798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganovimport android.print.PrintAttributes.Margins;
25798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganovimport android.print.PrintAttributes.MediaSize;
26798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganovimport android.print.PrintAttributes.Resolution;
27e680a8db52652830b99d9effce6c04a2a60c142ePhilip P. Moltmannimport com.android.internal.util.Preconditions;
28798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
29798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganovimport java.util.ArrayList;
30798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganovimport java.util.Arrays;
314d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganovimport java.util.Collections;
32798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganovimport java.util.List;
33e680a8db52652830b99d9effce6c04a2a60c142ePhilip P. Moltmannimport java.util.function.IntConsumer;
34798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
35798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov/**
364d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * This class represents the capabilities of a printer. Instances
374d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * of this class are created by a print service to report the
384d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * capabilities of a printer it manages. The capabilities of a
394d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * printer specify how it can print content. For example, what
404d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * are the media sizes supported by the printer, what are the
414d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * minimal margins of the printer based on its technical design,
424d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * etc.
43798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov */
44798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganovpublic final class PrinterCapabilitiesInfo implements Parcelable {
45798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    /**
46798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     * Undefined default value.
47798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     *
48798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     * @hide
49798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     */
50798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    public static final int DEFAULT_UNDEFINED = -1;
51798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
52798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    private static final int PROPERTY_MEDIA_SIZE = 0;
53798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    private static final int PROPERTY_RESOLUTION = 1;
54773f54de3de9bce7b6f915aa47ed686b161d77aaSvetoslav    private static final int PROPERTY_COLOR_MODE = 2;
55948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav    private static final int PROPERTY_DUPLEX_MODE = 3;
56948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav    private static final int PROPERTY_COUNT = 4;
57798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
58798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    private static final Margins DEFAULT_MARGINS = new Margins(0,  0,  0,  0);
59798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
60e680a8db52652830b99d9effce6c04a2a60c142ePhilip P. Moltmann    private @NonNull Margins mMinMargins = DEFAULT_MARGINS;
61e680a8db52652830b99d9effce6c04a2a60c142ePhilip P. Moltmann    private @NonNull List<MediaSize> mMediaSizes;
62e680a8db52652830b99d9effce6c04a2a60c142ePhilip P. Moltmann    private @NonNull List<Resolution> mResolutions;
63798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
64798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    private int mColorModes;
65948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav    private int mDuplexModes;
66798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
67798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    private final int[] mDefaults = new int[PROPERTY_COUNT];
68798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
69798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    /**
70798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     * @hide
71798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     */
72798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    public PrinterCapabilitiesInfo() {
73798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        Arrays.fill(mDefaults, DEFAULT_UNDEFINED);
74798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    }
75798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
76798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    /**
77798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     * @hide
78798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     */
79798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    public PrinterCapabilitiesInfo(PrinterCapabilitiesInfo prototype) {
80798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        copyFrom(prototype);
81798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    }
82798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
83798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    /**
84798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     * @hide
85798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     */
86798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    public void copyFrom(PrinterCapabilitiesInfo other) {
87651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav        if (this == other) {
88651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav            return;
89651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav        }
90651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav
91798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        mMinMargins = other.mMinMargins;
92798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
93798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        if (other.mMediaSizes != null) {
94798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            if (mMediaSizes != null) {
95798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov                mMediaSizes.clear();
96798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov                mMediaSizes.addAll(other.mMediaSizes);
97798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            } else {
98798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov                mMediaSizes = new ArrayList<MediaSize>(other.mMediaSizes);
99798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            }
100798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        } else {
101798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            mMediaSizes = null;
102798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        }
103798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
104798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        if (other.mResolutions != null) {
105798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            if (mResolutions != null) {
106798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov                mResolutions.clear();
107798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov                mResolutions.addAll(other.mResolutions);
108798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            } else {
109798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov                mResolutions = new ArrayList<Resolution>(other.mResolutions);
110798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            }
111798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        } else {
112798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            mResolutions = null;
113798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        }
114798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
115798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        mColorModes = other.mColorModes;
116948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav        mDuplexModes = other.mDuplexModes;
117798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
118798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        final int defaultCount = other.mDefaults.length;
119798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        for (int i = 0; i < defaultCount; i++) {
120798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            mDefaults[i] = other.mDefaults[i];
121798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        }
122798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    }
123798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
124798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    /**
125798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     * Gets the supported media sizes.
126798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     *
127798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     * @return The media sizes.
128798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     */
129c43639c3067dda5df189fb3cbf14f256c17e677dPhilip P. Moltmann    public @NonNull List<MediaSize> getMediaSizes() {
1304d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov        return Collections.unmodifiableList(mMediaSizes);
131798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    }
132798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
133798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    /**
134798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     * Gets the supported resolutions.
135798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     *
136798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     * @return The resolutions.
137798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     */
138c43639c3067dda5df189fb3cbf14f256c17e677dPhilip P. Moltmann    public @NonNull List<Resolution> getResolutions() {
1394d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov        return Collections.unmodifiableList(mResolutions);
140798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    }
141798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
142798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    /**
143651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav     * Gets the minimal margins. These are the minimal margins
144651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav     * the printer physically supports.
145798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     *
146798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     * @return The minimal margins.
147798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     */
148c43639c3067dda5df189fb3cbf14f256c17e677dPhilip P. Moltmann    public @NonNull Margins getMinMargins() {
149798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        return mMinMargins;
150798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    }
151798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
152798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    /**
1534d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov     * Gets the bit mask of supported color modes.
154798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     *
1554d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov     * @return The bit mask of supported color modes.
156798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     *
157798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     * @see PrintAttributes#COLOR_MODE_COLOR
158798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     * @see PrintAttributes#COLOR_MODE_MONOCHROME
159798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     */
160c43639c3067dda5df189fb3cbf14f256c17e677dPhilip P. Moltmann    public @ColorMode int getColorModes() {
161798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        return mColorModes;
162798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    }
163798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
164798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    /**
165948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav     * Gets the bit mask of supported duplex modes.
166948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav     *
167948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav     * @return The bit mask of supported duplex modes.
168948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav     *
169948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav     * @see PrintAttributes#DUPLEX_MODE_NONE
170948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav     * @see PrintAttributes#DUPLEX_MODE_LONG_EDGE
171948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav     * @see PrintAttributes#DUPLEX_MODE_SHORT_EDGE
172948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav     */
173c43639c3067dda5df189fb3cbf14f256c17e677dPhilip P. Moltmann    public @DuplexMode int getDuplexModes() {
174948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav        return mDuplexModes;
175948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav    }
176948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav
177948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav    /**
178798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     * Gets the default print attributes.
179798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     *
180651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav     * @return The default attributes.
181798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     */
182c43639c3067dda5df189fb3cbf14f256c17e677dPhilip P. Moltmann    public @NonNull PrintAttributes getDefaults() {
183651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav        PrintAttributes.Builder builder = new PrintAttributes.Builder();
184798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
185651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav        builder.setMinMargins(mMinMargins);
186798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
187798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        final int mediaSizeIndex = mDefaults[PROPERTY_MEDIA_SIZE];
188798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        if (mediaSizeIndex >= 0) {
189651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav            builder.setMediaSize(mMediaSizes.get(mediaSizeIndex));
190798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        }
191798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
192798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        final int resolutionIndex = mDefaults[PROPERTY_RESOLUTION];
193798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        if (resolutionIndex >= 0) {
194651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav            builder.setResolution(mResolutions.get(resolutionIndex));
195798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        }
196798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
197798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        final int colorMode = mDefaults[PROPERTY_COLOR_MODE];
198798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        if (colorMode > 0) {
199651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav            builder.setColorMode(colorMode);
200798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        }
201651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav
202948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav        final int duplexMode = mDefaults[PROPERTY_DUPLEX_MODE];
203948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav        if (duplexMode > 0) {
204948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav            builder.setDuplexMode(duplexMode);
205948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav        }
206948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav
207651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav        return builder.build();
208798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    }
209798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
210e680a8db52652830b99d9effce6c04a2a60c142ePhilip P. Moltmann    /**
211e680a8db52652830b99d9effce6c04a2a60c142ePhilip P. Moltmann     * Call enforceSingle for each bit in the mask.
212e680a8db52652830b99d9effce6c04a2a60c142ePhilip P. Moltmann     *
213e680a8db52652830b99d9effce6c04a2a60c142ePhilip P. Moltmann     * @param mask The mask
214e680a8db52652830b99d9effce6c04a2a60c142ePhilip P. Moltmann     * @param enforceSingle The function to call
215e680a8db52652830b99d9effce6c04a2a60c142ePhilip P. Moltmann     */
216e680a8db52652830b99d9effce6c04a2a60c142ePhilip P. Moltmann    private static void enforceValidMask(int mask, IntConsumer enforceSingle) {
217e680a8db52652830b99d9effce6c04a2a60c142ePhilip P. Moltmann        int current = mask;
218e680a8db52652830b99d9effce6c04a2a60c142ePhilip P. Moltmann        while (current > 0) {
219e680a8db52652830b99d9effce6c04a2a60c142ePhilip P. Moltmann            final int currentMode = (1 << Integer.numberOfTrailingZeros(current));
220e680a8db52652830b99d9effce6c04a2a60c142ePhilip P. Moltmann            current &= ~currentMode;
221e680a8db52652830b99d9effce6c04a2a60c142ePhilip P. Moltmann            enforceSingle.accept(currentMode);
222e680a8db52652830b99d9effce6c04a2a60c142ePhilip P. Moltmann        }
223e680a8db52652830b99d9effce6c04a2a60c142ePhilip P. Moltmann    }
224e680a8db52652830b99d9effce6c04a2a60c142ePhilip P. Moltmann
225798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    private PrinterCapabilitiesInfo(Parcel parcel) {
226e680a8db52652830b99d9effce6c04a2a60c142ePhilip P. Moltmann        mMinMargins = Preconditions.checkNotNull(readMargins(parcel));
227798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        readMediaSizes(parcel);
228798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        readResolutions(parcel);
229798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
230798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        mColorModes = parcel.readInt();
231e680a8db52652830b99d9effce6c04a2a60c142ePhilip P. Moltmann        enforceValidMask(mColorModes,
232e680a8db52652830b99d9effce6c04a2a60c142ePhilip P. Moltmann                (currentMode) -> PrintAttributes.enforceValidColorMode(currentMode));
233e680a8db52652830b99d9effce6c04a2a60c142ePhilip P. Moltmann
234948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav        mDuplexModes = parcel.readInt();
235e680a8db52652830b99d9effce6c04a2a60c142ePhilip P. Moltmann        enforceValidMask(mDuplexModes,
2360d1407e60998fc73cf93801de9c637e8d0e19b5bPhilip P. Moltmann                (currentMode) -> PrintAttributes.enforceValidDuplexMode(currentMode));
237798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
238798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        readDefaults(parcel);
239e680a8db52652830b99d9effce6c04a2a60c142ePhilip P. Moltmann        Preconditions.checkArgument(mMediaSizes.size() > mDefaults[PROPERTY_MEDIA_SIZE]);
240e680a8db52652830b99d9effce6c04a2a60c142ePhilip P. Moltmann        Preconditions.checkArgument(mResolutions.size() > mDefaults[PROPERTY_RESOLUTION]);
241798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    }
242798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
243798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    @Override
244798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    public int describeContents() {
245798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        return 0;
246798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    }
247798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
248798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    @Override
249798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    public void writeToParcel(Parcel parcel, int flags) {
250798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        writeMargins(mMinMargins, parcel);
251798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        writeMediaSizes(parcel);
252798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        writeResolutions(parcel);
253798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
254798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        parcel.writeInt(mColorModes);
255948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav        parcel.writeInt(mDuplexModes);
256798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
257798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        writeDefaults(parcel);
258798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    }
259798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
260798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    @Override
261798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    public int hashCode() {
262798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        final int prime = 31;
263798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        int result = 1;
264798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        result = prime * result + ((mMinMargins == null) ? 0 : mMinMargins.hashCode());
265798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        result = prime * result + ((mMediaSizes == null) ? 0 : mMediaSizes.hashCode());
266798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        result = prime * result + ((mResolutions == null) ? 0 : mResolutions.hashCode());
267798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        result = prime * result + mColorModes;
268948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav        result = prime * result + mDuplexModes;
269798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        result = prime * result + Arrays.hashCode(mDefaults);
270798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        return result;
271798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    }
272798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
273798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    @Override
274798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    public boolean equals(Object obj) {
275798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        if (this == obj) {
276798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            return true;
277798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        }
278798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        if (obj == null) {
279798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            return false;
280798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        }
281798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        if (getClass() != obj.getClass()) {
282798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            return false;
283798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        }
284798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        PrinterCapabilitiesInfo other = (PrinterCapabilitiesInfo) obj;
285798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        if (mMinMargins == null) {
286798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            if (other.mMinMargins != null) {
287798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov                return false;
288798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            }
289798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        } else if (!mMinMargins.equals(other.mMinMargins)) {
290798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            return false;
291798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        }
292798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        if (mMediaSizes == null) {
293798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            if (other.mMediaSizes != null) {
294798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov                return false;
295798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            }
296798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        } else if (!mMediaSizes.equals(other.mMediaSizes)) {
297798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            return false;
298798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        }
299798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        if (mResolutions == null) {
300798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            if (other.mResolutions != null) {
301798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov                return false;
302798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            }
303798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        } else if (!mResolutions.equals(other.mResolutions)) {
304798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            return false;
305798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        }
306798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        if (mColorModes != other.mColorModes) {
307798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            return false;
308798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        }
309948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav        if (mDuplexModes != other.mDuplexModes) {
310948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav            return false;
311948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav        }
312798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        if (!Arrays.equals(mDefaults, other.mDefaults)) {
313798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            return false;
314798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        }
315798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        return true;
316798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    }
317798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
318798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    @Override
319798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    public String toString() {
320798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        StringBuilder builder = new StringBuilder();
321798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        builder.append("PrinterInfo{");
322798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        builder.append("minMargins=").append(mMinMargins);
323798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        builder.append(", mediaSizes=").append(mMediaSizes);
324798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        builder.append(", resolutions=").append(mResolutions);
325798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        builder.append(", colorModes=").append(colorModesToString());
326948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav        builder.append(", duplexModes=").append(duplexModesToString());
327798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        builder.append("\"}");
328798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        return builder.toString();
329798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    }
330798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
331798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    private String colorModesToString() {
332798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        StringBuilder builder = new StringBuilder();
333798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        builder.append('[');
334798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        int colorModes = mColorModes;
335798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        while (colorModes != 0) {
336798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            final int colorMode = 1 << Integer.numberOfTrailingZeros(colorModes);
337798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            colorModes &= ~colorMode;
338651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav            if (builder.length() > 1) {
339798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov                builder.append(", ");
340798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            }
341798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            builder.append(PrintAttributes.colorModeToString(colorMode));
342798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        }
343798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        builder.append(']');
344798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        return builder.toString();
345798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    }
346798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
347948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav    private String duplexModesToString() {
348948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav        StringBuilder builder = new StringBuilder();
349948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav        builder.append('[');
350948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav        int duplexModes = mDuplexModes;
351948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav        while (duplexModes != 0) {
352948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav            final int duplexMode = 1 << Integer.numberOfTrailingZeros(duplexModes);
353948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav            duplexModes &= ~duplexMode;
354948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav            if (builder.length() > 1) {
355948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav                builder.append(", ");
356948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav            }
357948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav            builder.append(PrintAttributes.duplexModeToString(duplexMode));
358948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav        }
359948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav        builder.append(']');
360948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav        return builder.toString();
361948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav    }
362948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav
363798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    private void writeMediaSizes(Parcel parcel) {
364798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        if (mMediaSizes == null) {
365798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            parcel.writeInt(0);
366798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            return;
367798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        }
368798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        final int mediaSizeCount = mMediaSizes.size();
369798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        parcel.writeInt(mediaSizeCount);
370798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        for (int i = 0; i < mediaSizeCount; i++) {
371798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            mMediaSizes.get(i).writeToParcel(parcel);
372798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        }
373798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    }
374798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
375798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    private void readMediaSizes(Parcel parcel) {
376798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        final int mediaSizeCount = parcel.readInt();
377798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        if (mediaSizeCount > 0 && mMediaSizes == null) {
378798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            mMediaSizes = new ArrayList<MediaSize>();
379798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        }
380798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        for (int i = 0; i < mediaSizeCount; i++) {
381798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            mMediaSizes.add(MediaSize.createFromParcel(parcel));
382798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        }
383798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    }
384798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
385798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    private void writeResolutions(Parcel parcel) {
386798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        if (mResolutions == null) {
387798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            parcel.writeInt(0);
388798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            return;
389798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        }
390798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        final int resolutionCount = mResolutions.size();
391798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        parcel.writeInt(resolutionCount);
392798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        for (int i = 0; i < resolutionCount; i++) {
393798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            mResolutions.get(i).writeToParcel(parcel);
394798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        }
395798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    }
396798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
397798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    private void readResolutions(Parcel parcel) {
398798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        final int resolutionCount = parcel.readInt();
399798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        if (resolutionCount > 0 && mResolutions == null) {
400798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            mResolutions = new ArrayList<Resolution>();
401798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        }
402798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        for (int i = 0; i < resolutionCount; i++) {
403798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            mResolutions.add(Resolution.createFromParcel(parcel));
404798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        }
405798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    }
406798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
407798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    private void writeMargins(Margins margins, Parcel parcel) {
408798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        if (margins == null) {
409798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            parcel.writeInt(0);
410798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        } else {
411798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            parcel.writeInt(1);
412798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            margins.writeToParcel(parcel);
413798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        }
414798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    }
415798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
416798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    private Margins readMargins(Parcel parcel) {
417798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        return (parcel.readInt() == 1) ? Margins.createFromParcel(parcel) : null;
418798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    }
419798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
420798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    private void readDefaults(Parcel parcel) {
421798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        final int defaultCount = parcel.readInt();
422798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        for (int i = 0; i < defaultCount; i++) {
423798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            mDefaults[i] = parcel.readInt();
424798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        }
425798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    }
426798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
427798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    private void writeDefaults(Parcel parcel) {
428798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        final int defaultCount = mDefaults.length;
429798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        parcel.writeInt(defaultCount);
430798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        for (int i = 0; i < defaultCount; i++) {
431798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            parcel.writeInt(mDefaults[i]);
432798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        }
433798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    }
434798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
435798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    /**
4364d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov     * Builder for creating of a {@link PrinterCapabilitiesInfo}. This class is
4374d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov     * responsible to enforce that all required attributes have at least one
4384d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov     * default value. In other words, this class creates only well-formed {@link
4394d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov     * PrinterCapabilitiesInfo}s.
440798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     * <p>
441798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     * Look at the individual methods for a reference whether a property is
442798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     * required or if it is optional.
443798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     * </p>
444798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     */
445798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    public static final class Builder {
446798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        private final PrinterCapabilitiesInfo mPrototype;
447798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
448798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        /**
449798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         * Creates a new instance.
450798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         *
4514d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov         * @param printerId The printer id. Cannot be <code>null</code>.
452798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         *
4534d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov         * @throws IllegalArgumentException If the printer id is <code>null</code>.
454798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         */
455c43639c3067dda5df189fb3cbf14f256c17e677dPhilip P. Moltmann        public Builder(@NonNull PrinterId printerId) {
456798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            if (printerId == null) {
457798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov                throw new IllegalArgumentException("printerId cannot be null.");
458798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            }
459798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            mPrototype = new PrinterCapabilitiesInfo();
460798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        }
461798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
462798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        /**
463798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         * Adds a supported media size.
464798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         * <p>
465798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         * <strong>Required:</strong> Yes
466798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         * </p>
467798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         *
468798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         * @param mediaSize A media size.
469798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         * @param isDefault Whether this is the default.
470798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         * @return This builder.
471798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         * @throws IllegalArgumentException If set as default and there
472798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         *     is already a default.
473798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         *
474798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         * @see PrintAttributes.MediaSize
475798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         */
476c43639c3067dda5df189fb3cbf14f256c17e677dPhilip P. Moltmann        public @NonNull Builder addMediaSize(@NonNull MediaSize mediaSize, boolean isDefault) {
477798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            if (mPrototype.mMediaSizes == null) {
478798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov                mPrototype.mMediaSizes = new ArrayList<MediaSize>();
479798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            }
480798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            final int insertionIndex = mPrototype.mMediaSizes.size();
481798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            mPrototype.mMediaSizes.add(mediaSize);
482798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            if (isDefault) {
483798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov                throwIfDefaultAlreadySpecified(PROPERTY_MEDIA_SIZE);
484798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov                mPrototype.mDefaults[PROPERTY_MEDIA_SIZE] = insertionIndex;
485798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            }
486798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            return this;
487798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        }
488798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
489798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        /**
490798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         * Adds a supported resolution.
491798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         * <p>
492798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         * <strong>Required:</strong> Yes
493798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         * </p>
494798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         *
495798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         * @param resolution A resolution.
496798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         * @param isDefault Whether this is the default.
497798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         * @return This builder.
498798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         *
499798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         * @throws IllegalArgumentException If set as default and there
500798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         *     is already a default.
501798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         *
502798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         * @see PrintAttributes.Resolution
503798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         */
504c43639c3067dda5df189fb3cbf14f256c17e677dPhilip P. Moltmann        public @NonNull Builder addResolution(@NonNull Resolution resolution, boolean isDefault) {
505798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            if (mPrototype.mResolutions == null) {
506798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov                mPrototype.mResolutions = new ArrayList<Resolution>();
507798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            }
508798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            final int insertionIndex = mPrototype.mResolutions.size();
509798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            mPrototype.mResolutions.add(resolution);
510798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            if (isDefault) {
511798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov                throwIfDefaultAlreadySpecified(PROPERTY_RESOLUTION);
512798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov                mPrototype.mDefaults[PROPERTY_RESOLUTION] = insertionIndex;
513798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            }
514798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            return this;
515798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        }
516798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
517798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        /**
518651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav         * Sets the minimal margins. These are the minimal margins
519651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav         * the printer physically supports.
520651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav         *
521798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         * <p>
522651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav         * <strong>Required:</strong> Yes
523798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         * </p>
524798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         *
525798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         * @param margins The margins.
526798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         * @return This builder.
527798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         *
528651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav         * @throws IllegalArgumentException If margins are <code>null</code>.
529651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav         *
530798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         * @see PrintAttributes.Margins
531798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         */
532c43639c3067dda5df189fb3cbf14f256c17e677dPhilip P. Moltmann        public @NonNull Builder setMinMargins(@NonNull Margins margins) {
533651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav            if (margins == null) {
534651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav                throw new IllegalArgumentException("margins cannot be null");
535798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            }
536798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            mPrototype.mMinMargins = margins;
537798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            return this;
538798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        }
539798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
540798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        /**
541798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         * Sets the color modes.
542798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         * <p>
543798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         * <strong>Required:</strong> Yes
544798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         * </p>
545798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         *
546798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         * @param colorModes The color mode bit mask.
547798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         * @param defaultColorMode The default color mode.
548798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         * @return This builder.
549b628dd825b319704f8a8135addef766ec892ce84Svetoslav         * <p>
550b628dd825b319704f8a8135addef766ec892ce84Svetoslav         * <strong>Note:</strong> On platform version 19 (Kitkat) specifying
551b628dd825b319704f8a8135addef766ec892ce84Svetoslav         * only PrintAttributes#COLOR_MODE_MONOCHROME leads to a print spooler
552b628dd825b319704f8a8135addef766ec892ce84Svetoslav         * crash. Hence, you should declare either both color modes or
553b628dd825b319704f8a8135addef766ec892ce84Svetoslav         * PrintAttributes#COLOR_MODE_COLOR.
554b628dd825b319704f8a8135addef766ec892ce84Svetoslav         * </p>
555798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         *
556798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         * @throws IllegalArgumentException If color modes contains an invalid
557798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         *         mode bit or if the default color mode is invalid.
558798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         *
559798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         * @see PrintAttributes#COLOR_MODE_COLOR
560798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         * @see PrintAttributes#COLOR_MODE_MONOCHROME
561798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         */
562c43639c3067dda5df189fb3cbf14f256c17e677dPhilip P. Moltmann        public @NonNull Builder setColorModes(@ColorMode int colorModes,
563c43639c3067dda5df189fb3cbf14f256c17e677dPhilip P. Moltmann                @ColorMode int defaultColorMode) {
564e680a8db52652830b99d9effce6c04a2a60c142ePhilip P. Moltmann            enforceValidMask(colorModes,
565e680a8db52652830b99d9effce6c04a2a60c142ePhilip P. Moltmann                    (currentMode) -> PrintAttributes.enforceValidColorMode(currentMode));
566948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav            PrintAttributes.enforceValidColorMode(defaultColorMode);
567798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            mPrototype.mColorModes = colorModes;
568798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            mPrototype.mDefaults[PROPERTY_COLOR_MODE] = defaultColorMode;
569798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            return this;
570798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        }
571798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
572798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        /**
573948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav         * Sets the duplex modes.
574948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav         * <p>
575948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav         * <strong>Required:</strong> No
576948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav         * </p>
577948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav         *
578948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav         * @param duplexModes The duplex mode bit mask.
579948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav         * @param defaultDuplexMode The default duplex mode.
580948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav         * @return This builder.
581948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav         *
582948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav         * @throws IllegalArgumentException If duplex modes contains an invalid
583948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav         *         mode bit or if the default duplex mode is invalid.
584948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav         *
585948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav         * @see PrintAttributes#DUPLEX_MODE_NONE
586948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav         * @see PrintAttributes#DUPLEX_MODE_LONG_EDGE
587948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav         * @see PrintAttributes#DUPLEX_MODE_SHORT_EDGE
588948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav         */
589c43639c3067dda5df189fb3cbf14f256c17e677dPhilip P. Moltmann        public @NonNull Builder setDuplexModes(@DuplexMode int duplexModes,
590c43639c3067dda5df189fb3cbf14f256c17e677dPhilip P. Moltmann                @DuplexMode int defaultDuplexMode) {
591e680a8db52652830b99d9effce6c04a2a60c142ePhilip P. Moltmann            enforceValidMask(duplexModes,
592e680a8db52652830b99d9effce6c04a2a60c142ePhilip P. Moltmann                    (currentMode) -> PrintAttributes.enforceValidDuplexMode(currentMode));
593948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav            PrintAttributes.enforceValidDuplexMode(defaultDuplexMode);
594948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav            mPrototype.mDuplexModes = duplexModes;
595948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav            mPrototype.mDefaults[PROPERTY_DUPLEX_MODE] = defaultDuplexMode;
596948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav            return this;
597948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav        }
598948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav
599948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav        /**
600798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         * Crates a new {@link PrinterCapabilitiesInfo} enforcing that all
6014d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov         * required properties have been specified. See individual methods
602798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         * in this class for reference about required attributes.
603948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav         * <p>
604948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav         * <strong>Note:</strong> If you do not add supported duplex modes,
605948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav         * {@link android.print.PrintAttributes#DUPLEX_MODE_NONE} will set
606948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav         * as the only supported mode and also as the default duplex mode.
607948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav         * </p>
608798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         *
609798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         * @return A new {@link PrinterCapabilitiesInfo}.
610798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         *
611798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         * @throws IllegalStateException If a required attribute was not specified.
612798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         */
613c43639c3067dda5df189fb3cbf14f256c17e677dPhilip P. Moltmann        public @NonNull PrinterCapabilitiesInfo build() {
614798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            if (mPrototype.mMediaSizes == null || mPrototype.mMediaSizes.isEmpty()) {
615798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov                throw new IllegalStateException("No media size specified.");
616798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            }
617798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            if (mPrototype.mDefaults[PROPERTY_MEDIA_SIZE] == DEFAULT_UNDEFINED) {
618798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov                throw new IllegalStateException("No default media size specified.");
619798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            }
620798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            if (mPrototype.mResolutions == null || mPrototype.mResolutions.isEmpty()) {
621798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov                throw new IllegalStateException("No resolution specified.");
622798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            }
623798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            if (mPrototype.mDefaults[PROPERTY_RESOLUTION] == DEFAULT_UNDEFINED) {
624798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov                throw new IllegalStateException("No default resolution specified.");
625798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            }
626798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            if (mPrototype.mColorModes == 0) {
627798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov                throw new IllegalStateException("No color mode specified.");
628798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            }
629798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            if (mPrototype.mDefaults[PROPERTY_COLOR_MODE] == DEFAULT_UNDEFINED) {
630798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov                throw new IllegalStateException("No default color mode specified.");
631798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            }
632948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav            if (mPrototype.mDuplexModes == 0) {
633948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav                setDuplexModes(PrintAttributes.DUPLEX_MODE_NONE,
634948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav                        PrintAttributes.DUPLEX_MODE_NONE);
635948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav            }
636798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            if (mPrototype.mMinMargins == null) {
637651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav                throw new IllegalArgumentException("margins cannot be null");
638798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            }
6394d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov            return mPrototype;
640798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        }
641798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
642798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        private void throwIfDefaultAlreadySpecified(int propertyIndex) {
643798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            if (mPrototype.mDefaults[propertyIndex] != DEFAULT_UNDEFINED) {
644798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov                throw new IllegalArgumentException("Default already specified.");
645798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            }
646798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        }
647798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    }
648798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
649798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    public static final Parcelable.Creator<PrinterCapabilitiesInfo> CREATOR =
650798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            new Parcelable.Creator<PrinterCapabilitiesInfo>() {
651798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        @Override
652798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        public PrinterCapabilitiesInfo createFromParcel(Parcel parcel) {
653798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            return new PrinterCapabilitiesInfo(parcel);
654798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        }
655798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
656798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        @Override
657798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        public PrinterCapabilitiesInfo[] newArray(int size) {
658798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            return new PrinterCapabilitiesInfo[size];
659798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        }
660798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    };
661798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov}
662