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
19798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganovimport android.os.Parcel;
20798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganovimport android.os.Parcelable;
21798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganovimport android.print.PrintAttributes.Margins;
22798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganovimport android.print.PrintAttributes.MediaSize;
23798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganovimport android.print.PrintAttributes.Resolution;
24798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
25798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganovimport java.util.ArrayList;
26798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganovimport java.util.Arrays;
274d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganovimport java.util.Collections;
28798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganovimport java.util.List;
29798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
30798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov/**
314d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * This class represents the capabilities of a printer. Instances
324d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * of this class are created by a print service to report the
334d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * capabilities of a printer it manages. The capabilities of a
344d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * printer specify how it can print content. For example, what
354d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * are the media sizes supported by the printer, what are the
364d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * minimal margins of the printer based on its technical design,
374d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * etc.
38798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov */
39798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganovpublic final class PrinterCapabilitiesInfo implements Parcelable {
40798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    /**
41798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     * Undefined default value.
42798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     *
43798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     * @hide
44798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     */
45798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    public static final int DEFAULT_UNDEFINED = -1;
46798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
47798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    private static final int PROPERTY_MEDIA_SIZE = 0;
48798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    private static final int PROPERTY_RESOLUTION = 1;
49773f54de3de9bce7b6f915aa47ed686b161d77aaSvetoslav    private static final int PROPERTY_COLOR_MODE = 2;
50948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav    private static final int PROPERTY_DUPLEX_MODE = 3;
51948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav    private static final int PROPERTY_COUNT = 4;
52798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
53798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    private static final Margins DEFAULT_MARGINS = new Margins(0,  0,  0,  0);
54798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
55798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    private Margins mMinMargins = DEFAULT_MARGINS;
56798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    private List<MediaSize> mMediaSizes;
57798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    private List<Resolution> mResolutions;
58798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
59798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    private int mColorModes;
60948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav    private int mDuplexModes;
61798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
62798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    private final int[] mDefaults = new int[PROPERTY_COUNT];
63798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
64798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    /**
65798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     * @hide
66798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     */
67798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    public PrinterCapabilitiesInfo() {
68798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        Arrays.fill(mDefaults, DEFAULT_UNDEFINED);
69798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    }
70798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
71798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    /**
72798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     * @hide
73798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     */
74798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    public PrinterCapabilitiesInfo(PrinterCapabilitiesInfo prototype) {
75798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        copyFrom(prototype);
76798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    }
77798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
78798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    /**
79798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     * @hide
80798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     */
81798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    public void copyFrom(PrinterCapabilitiesInfo other) {
82651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav        if (this == other) {
83651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav            return;
84651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav        }
85651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav
86798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        mMinMargins = other.mMinMargins;
87798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
88798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        if (other.mMediaSizes != null) {
89798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            if (mMediaSizes != null) {
90798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov                mMediaSizes.clear();
91798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov                mMediaSizes.addAll(other.mMediaSizes);
92798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            } else {
93798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov                mMediaSizes = new ArrayList<MediaSize>(other.mMediaSizes);
94798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            }
95798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        } else {
96798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            mMediaSizes = null;
97798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        }
98798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
99798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        if (other.mResolutions != null) {
100798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            if (mResolutions != null) {
101798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov                mResolutions.clear();
102798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov                mResolutions.addAll(other.mResolutions);
103798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            } else {
104798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov                mResolutions = new ArrayList<Resolution>(other.mResolutions);
105798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            }
106798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        } else {
107798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            mResolutions = null;
108798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        }
109798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
110798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        mColorModes = other.mColorModes;
111948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav        mDuplexModes = other.mDuplexModes;
112798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
113798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        final int defaultCount = other.mDefaults.length;
114798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        for (int i = 0; i < defaultCount; i++) {
115798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            mDefaults[i] = other.mDefaults[i];
116798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        }
117798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    }
118798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
119798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    /**
120798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     * Gets the supported media sizes.
121798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     *
122798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     * @return The media sizes.
123798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     */
124798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    public List<MediaSize> getMediaSizes() {
1254d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov        return Collections.unmodifiableList(mMediaSizes);
126798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    }
127798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
128798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    /**
129798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     * Gets the supported resolutions.
130798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     *
131798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     * @return The resolutions.
132798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     */
133798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    public List<Resolution> getResolutions() {
1344d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov        return Collections.unmodifiableList(mResolutions);
135798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    }
136798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
137798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    /**
138651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav     * Gets the minimal margins. These are the minimal margins
139651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav     * the printer physically supports.
140798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     *
141798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     * @return The minimal margins.
142798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     */
143798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    public Margins getMinMargins() {
144798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        return mMinMargins;
145798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    }
146798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
147798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    /**
1484d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov     * Gets the bit mask of supported color modes.
149798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     *
1504d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov     * @return The bit mask of supported color modes.
151798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     *
152798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     * @see PrintAttributes#COLOR_MODE_COLOR
153798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     * @see PrintAttributes#COLOR_MODE_MONOCHROME
154798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     */
155798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    public int getColorModes() {
156798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        return mColorModes;
157798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    }
158798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
159798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    /**
160948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav     * Gets the bit mask of supported duplex modes.
161948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav     *
162948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav     * @return The bit mask of supported duplex modes.
163948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav     *
164948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav     * @see PrintAttributes#DUPLEX_MODE_NONE
165948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav     * @see PrintAttributes#DUPLEX_MODE_LONG_EDGE
166948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav     * @see PrintAttributes#DUPLEX_MODE_SHORT_EDGE
167948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav     */
168948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav    public int getDuplexModes() {
169948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav        return mDuplexModes;
170948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav    }
171948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav
172948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav    /**
173798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     * Gets the default print attributes.
174798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     *
175651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav     * @return The default attributes.
176798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     */
177651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav    public PrintAttributes getDefaults() {
178651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav        PrintAttributes.Builder builder = new PrintAttributes.Builder();
179798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
180651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav        builder.setMinMargins(mMinMargins);
181798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
182798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        final int mediaSizeIndex = mDefaults[PROPERTY_MEDIA_SIZE];
183798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        if (mediaSizeIndex >= 0) {
184651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav            builder.setMediaSize(mMediaSizes.get(mediaSizeIndex));
185798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        }
186798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
187798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        final int resolutionIndex = mDefaults[PROPERTY_RESOLUTION];
188798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        if (resolutionIndex >= 0) {
189651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav            builder.setResolution(mResolutions.get(resolutionIndex));
190798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        }
191798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
192798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        final int colorMode = mDefaults[PROPERTY_COLOR_MODE];
193798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        if (colorMode > 0) {
194651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav            builder.setColorMode(colorMode);
195798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        }
196651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav
197948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav        final int duplexMode = mDefaults[PROPERTY_DUPLEX_MODE];
198948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav        if (duplexMode > 0) {
199948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav            builder.setDuplexMode(duplexMode);
200948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav        }
201948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav
202651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav        return builder.build();
203798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    }
204798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
205798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    private PrinterCapabilitiesInfo(Parcel parcel) {
206798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        mMinMargins = readMargins(parcel);
207798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        readMediaSizes(parcel);
208798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        readResolutions(parcel);
209798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
210798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        mColorModes = parcel.readInt();
211948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav        mDuplexModes = parcel.readInt();
212798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
213798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        readDefaults(parcel);
214798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    }
215798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
216798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    @Override
217798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    public int describeContents() {
218798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        return 0;
219798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    }
220798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
221798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    @Override
222798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    public void writeToParcel(Parcel parcel, int flags) {
223798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        writeMargins(mMinMargins, parcel);
224798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        writeMediaSizes(parcel);
225798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        writeResolutions(parcel);
226798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
227798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        parcel.writeInt(mColorModes);
228948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav        parcel.writeInt(mDuplexModes);
229798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
230798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        writeDefaults(parcel);
231798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    }
232798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
233798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    @Override
234798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    public int hashCode() {
235798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        final int prime = 31;
236798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        int result = 1;
237798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        result = prime * result + ((mMinMargins == null) ? 0 : mMinMargins.hashCode());
238798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        result = prime * result + ((mMediaSizes == null) ? 0 : mMediaSizes.hashCode());
239798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        result = prime * result + ((mResolutions == null) ? 0 : mResolutions.hashCode());
240798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        result = prime * result + mColorModes;
241948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav        result = prime * result + mDuplexModes;
242798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        result = prime * result + Arrays.hashCode(mDefaults);
243798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        return result;
244798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    }
245798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
246798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    @Override
247798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    public boolean equals(Object obj) {
248798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        if (this == obj) {
249798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            return true;
250798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        }
251798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        if (obj == null) {
252798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            return false;
253798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        }
254798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        if (getClass() != obj.getClass()) {
255798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            return false;
256798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        }
257798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        PrinterCapabilitiesInfo other = (PrinterCapabilitiesInfo) obj;
258798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        if (mMinMargins == null) {
259798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            if (other.mMinMargins != null) {
260798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov                return false;
261798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            }
262798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        } else if (!mMinMargins.equals(other.mMinMargins)) {
263798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            return false;
264798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        }
265798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        if (mMediaSizes == null) {
266798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            if (other.mMediaSizes != null) {
267798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov                return false;
268798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            }
269798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        } else if (!mMediaSizes.equals(other.mMediaSizes)) {
270798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            return false;
271798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        }
272798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        if (mResolutions == null) {
273798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            if (other.mResolutions != null) {
274798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov                return false;
275798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            }
276798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        } else if (!mResolutions.equals(other.mResolutions)) {
277798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            return false;
278798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        }
279798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        if (mColorModes != other.mColorModes) {
280798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            return false;
281798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        }
282948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav        if (mDuplexModes != other.mDuplexModes) {
283948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav            return false;
284948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav        }
285798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        if (!Arrays.equals(mDefaults, other.mDefaults)) {
286798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            return false;
287798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        }
288798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        return true;
289798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    }
290798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
291798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    @Override
292798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    public String toString() {
293798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        StringBuilder builder = new StringBuilder();
294798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        builder.append("PrinterInfo{");
295798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        builder.append("minMargins=").append(mMinMargins);
296798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        builder.append(", mediaSizes=").append(mMediaSizes);
297798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        builder.append(", resolutions=").append(mResolutions);
298798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        builder.append(", colorModes=").append(colorModesToString());
299948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav        builder.append(", duplexModes=").append(duplexModesToString());
300798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        builder.append("\"}");
301798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        return builder.toString();
302798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    }
303798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
304798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    private String colorModesToString() {
305798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        StringBuilder builder = new StringBuilder();
306798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        builder.append('[');
307798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        int colorModes = mColorModes;
308798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        while (colorModes != 0) {
309798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            final int colorMode = 1 << Integer.numberOfTrailingZeros(colorModes);
310798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            colorModes &= ~colorMode;
311651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav            if (builder.length() > 1) {
312798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov                builder.append(", ");
313798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            }
314798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            builder.append(PrintAttributes.colorModeToString(colorMode));
315798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        }
316798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        builder.append(']');
317798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        return builder.toString();
318798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    }
319798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
320948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav    private String duplexModesToString() {
321948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav        StringBuilder builder = new StringBuilder();
322948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav        builder.append('[');
323948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav        int duplexModes = mDuplexModes;
324948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav        while (duplexModes != 0) {
325948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav            final int duplexMode = 1 << Integer.numberOfTrailingZeros(duplexModes);
326948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav            duplexModes &= ~duplexMode;
327948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav            if (builder.length() > 1) {
328948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav                builder.append(", ");
329948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav            }
330948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav            builder.append(PrintAttributes.duplexModeToString(duplexMode));
331948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav        }
332948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav        builder.append(']');
333948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav        return builder.toString();
334948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav    }
335948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav
336798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    private void writeMediaSizes(Parcel parcel) {
337798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        if (mMediaSizes == null) {
338798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            parcel.writeInt(0);
339798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            return;
340798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        }
341798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        final int mediaSizeCount = mMediaSizes.size();
342798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        parcel.writeInt(mediaSizeCount);
343798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        for (int i = 0; i < mediaSizeCount; i++) {
344798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            mMediaSizes.get(i).writeToParcel(parcel);
345798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        }
346798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    }
347798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
348798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    private void readMediaSizes(Parcel parcel) {
349798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        final int mediaSizeCount = parcel.readInt();
350798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        if (mediaSizeCount > 0 && mMediaSizes == null) {
351798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            mMediaSizes = new ArrayList<MediaSize>();
352798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        }
353798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        for (int i = 0; i < mediaSizeCount; i++) {
354798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            mMediaSizes.add(MediaSize.createFromParcel(parcel));
355798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        }
356798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    }
357798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
358798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    private void writeResolutions(Parcel parcel) {
359798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        if (mResolutions == null) {
360798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            parcel.writeInt(0);
361798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            return;
362798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        }
363798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        final int resolutionCount = mResolutions.size();
364798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        parcel.writeInt(resolutionCount);
365798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        for (int i = 0; i < resolutionCount; i++) {
366798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            mResolutions.get(i).writeToParcel(parcel);
367798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        }
368798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    }
369798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
370798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    private void readResolutions(Parcel parcel) {
371798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        final int resolutionCount = parcel.readInt();
372798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        if (resolutionCount > 0 && mResolutions == null) {
373798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            mResolutions = new ArrayList<Resolution>();
374798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        }
375798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        for (int i = 0; i < resolutionCount; i++) {
376798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            mResolutions.add(Resolution.createFromParcel(parcel));
377798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        }
378798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    }
379798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
380798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    private void writeMargins(Margins margins, Parcel parcel) {
381798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        if (margins == null) {
382798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            parcel.writeInt(0);
383798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        } else {
384798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            parcel.writeInt(1);
385798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            margins.writeToParcel(parcel);
386798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        }
387798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    }
388798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
389798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    private Margins readMargins(Parcel parcel) {
390798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        return (parcel.readInt() == 1) ? Margins.createFromParcel(parcel) : null;
391798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    }
392798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
393798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    private void readDefaults(Parcel parcel) {
394798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        final int defaultCount = parcel.readInt();
395798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        for (int i = 0; i < defaultCount; i++) {
396798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            mDefaults[i] = parcel.readInt();
397798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        }
398798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    }
399798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
400798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    private void writeDefaults(Parcel parcel) {
401798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        final int defaultCount = mDefaults.length;
402798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        parcel.writeInt(defaultCount);
403798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        for (int i = 0; i < defaultCount; i++) {
404798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            parcel.writeInt(mDefaults[i]);
405798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        }
406798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    }
407798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
408798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    /**
4094d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov     * Builder for creating of a {@link PrinterCapabilitiesInfo}. This class is
4104d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov     * responsible to enforce that all required attributes have at least one
4114d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov     * default value. In other words, this class creates only well-formed {@link
4124d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov     * PrinterCapabilitiesInfo}s.
413798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     * <p>
414798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     * Look at the individual methods for a reference whether a property is
415798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     * required or if it is optional.
416798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     * </p>
417798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     */
418798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    public static final class Builder {
419798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        private final PrinterCapabilitiesInfo mPrototype;
420798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
421798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        /**
422798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         * Creates a new instance.
423798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         *
4244d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov         * @param printerId The printer id. Cannot be <code>null</code>.
425798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         *
4264d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov         * @throws IllegalArgumentException If the printer id is <code>null</code>.
427798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         */
428798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        public Builder(PrinterId printerId) {
429798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            if (printerId == null) {
430798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov                throw new IllegalArgumentException("printerId cannot be null.");
431798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            }
432798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            mPrototype = new PrinterCapabilitiesInfo();
433798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        }
434798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
435798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        /**
436798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         * Adds a supported media size.
437798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         * <p>
438798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         * <strong>Required:</strong> Yes
439798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         * </p>
440798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         *
441798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         * @param mediaSize A media size.
442798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         * @param isDefault Whether this is the default.
443798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         * @return This builder.
444798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         * @throws IllegalArgumentException If set as default and there
445798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         *     is already a default.
446798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         *
447798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         * @see PrintAttributes.MediaSize
448798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         */
449798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        public Builder addMediaSize(MediaSize mediaSize, boolean isDefault) {
450798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            if (mPrototype.mMediaSizes == null) {
451798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov                mPrototype.mMediaSizes = new ArrayList<MediaSize>();
452798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            }
453798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            final int insertionIndex = mPrototype.mMediaSizes.size();
454798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            mPrototype.mMediaSizes.add(mediaSize);
455798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            if (isDefault) {
456798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov                throwIfDefaultAlreadySpecified(PROPERTY_MEDIA_SIZE);
457798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov                mPrototype.mDefaults[PROPERTY_MEDIA_SIZE] = insertionIndex;
458798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            }
459798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            return this;
460798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        }
461798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
462798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        /**
463798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         * Adds a supported resolution.
464798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         * <p>
465798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         * <strong>Required:</strong> Yes
466798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         * </p>
467798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         *
468798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         * @param resolution A resolution.
469798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         * @param isDefault Whether this is the default.
470798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         * @return This builder.
471798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         *
472798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         * @throws IllegalArgumentException If set as default and there
473798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         *     is already a default.
474798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         *
475798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         * @see PrintAttributes.Resolution
476798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         */
477798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        public Builder addResolution(Resolution resolution, boolean isDefault) {
478798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            if (mPrototype.mResolutions == null) {
479798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov                mPrototype.mResolutions = new ArrayList<Resolution>();
480798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            }
481798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            final int insertionIndex = mPrototype.mResolutions.size();
482798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            mPrototype.mResolutions.add(resolution);
483798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            if (isDefault) {
484798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov                throwIfDefaultAlreadySpecified(PROPERTY_RESOLUTION);
485798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov                mPrototype.mDefaults[PROPERTY_RESOLUTION] = insertionIndex;
486798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            }
487798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            return this;
488798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        }
489798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
490798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        /**
491651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav         * Sets the minimal margins. These are the minimal margins
492651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav         * the printer physically supports.
493651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav         *
494798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         * <p>
495651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav         * <strong>Required:</strong> Yes
496798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         * </p>
497798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         *
498798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         * @param margins The margins.
499798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         * @return This builder.
500798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         *
501651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav         * @throws IllegalArgumentException If margins are <code>null</code>.
502651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav         *
503798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         * @see PrintAttributes.Margins
504798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         */
505651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav        public Builder setMinMargins(Margins margins) {
506651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav            if (margins == null) {
507651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav                throw new IllegalArgumentException("margins cannot be null");
508798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            }
509798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            mPrototype.mMinMargins = margins;
510798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            return this;
511798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        }
512798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
513798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        /**
514798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         * Sets the color modes.
515798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         * <p>
516798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         * <strong>Required:</strong> Yes
517798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         * </p>
518798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         *
519798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         * @param colorModes The color mode bit mask.
520798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         * @param defaultColorMode The default color mode.
521798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         * @return This builder.
522b628dd825b319704f8a8135addef766ec892ce84Svetoslav         * <p>
523b628dd825b319704f8a8135addef766ec892ce84Svetoslav         * <strong>Note:</strong> On platform version 19 (Kitkat) specifying
524b628dd825b319704f8a8135addef766ec892ce84Svetoslav         * only PrintAttributes#COLOR_MODE_MONOCHROME leads to a print spooler
525b628dd825b319704f8a8135addef766ec892ce84Svetoslav         * crash. Hence, you should declare either both color modes or
526b628dd825b319704f8a8135addef766ec892ce84Svetoslav         * PrintAttributes#COLOR_MODE_COLOR.
527b628dd825b319704f8a8135addef766ec892ce84Svetoslav         * </p>
528798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         *
529798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         * @throws IllegalArgumentException If color modes contains an invalid
530798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         *         mode bit or if the default color mode is invalid.
531798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         *
532798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         * @see PrintAttributes#COLOR_MODE_COLOR
533798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         * @see PrintAttributes#COLOR_MODE_MONOCHROME
534798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         */
535798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        public Builder setColorModes(int colorModes, int defaultColorMode) {
536798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            int currentModes = colorModes;
537798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            while (currentModes > 0) {
538798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov                final int currentMode = (1 << Integer.numberOfTrailingZeros(currentModes));
539798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov                currentModes &= ~currentMode;
540798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov                PrintAttributes.enforceValidColorMode(currentMode);
541798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            }
542948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav            PrintAttributes.enforceValidColorMode(defaultColorMode);
543798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            mPrototype.mColorModes = colorModes;
544798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            mPrototype.mDefaults[PROPERTY_COLOR_MODE] = defaultColorMode;
545798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            return this;
546798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        }
547798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
548798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        /**
549948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav         * Sets the duplex modes.
550948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav         * <p>
551948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav         * <strong>Required:</strong> No
552948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav         * </p>
553948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav         *
554948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav         * @param duplexModes The duplex mode bit mask.
555948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav         * @param defaultDuplexMode The default duplex mode.
556948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav         * @return This builder.
557948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav         *
558948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav         * @throws IllegalArgumentException If duplex modes contains an invalid
559948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav         *         mode bit or if the default duplex mode is invalid.
560948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav         *
561948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav         * @see PrintAttributes#DUPLEX_MODE_NONE
562948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav         * @see PrintAttributes#DUPLEX_MODE_LONG_EDGE
563948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav         * @see PrintAttributes#DUPLEX_MODE_SHORT_EDGE
564948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav         */
565948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav        public Builder setDuplexModes(int duplexModes, int defaultDuplexMode) {
566948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav            int currentModes = duplexModes;
567948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav            while (currentModes > 0) {
568948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav                final int currentMode = (1 << Integer.numberOfTrailingZeros(currentModes));
569948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav                currentModes &= ~currentMode;
570948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav                PrintAttributes.enforceValidDuplexMode(currentMode);
571948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav            }
572948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav            PrintAttributes.enforceValidDuplexMode(defaultDuplexMode);
573948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav            mPrototype.mDuplexModes = duplexModes;
574948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav            mPrototype.mDefaults[PROPERTY_DUPLEX_MODE] = defaultDuplexMode;
575948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav            return this;
576948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav        }
577948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav
578948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav        /**
579798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         * Crates a new {@link PrinterCapabilitiesInfo} enforcing that all
5804d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov         * required properties have been specified. See individual methods
581798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         * in this class for reference about required attributes.
582948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav         * <p>
583948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav         * <strong>Note:</strong> If you do not add supported duplex modes,
584948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav         * {@link android.print.PrintAttributes#DUPLEX_MODE_NONE} will set
585948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav         * as the only supported mode and also as the default duplex mode.
586948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav         * </p>
587798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         *
588798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         * @return A new {@link PrinterCapabilitiesInfo}.
589798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         *
590798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         * @throws IllegalStateException If a required attribute was not specified.
591798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov         */
592651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav        public PrinterCapabilitiesInfo build() {
593798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            if (mPrototype.mMediaSizes == null || mPrototype.mMediaSizes.isEmpty()) {
594798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov                throw new IllegalStateException("No media size specified.");
595798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            }
596798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            if (mPrototype.mDefaults[PROPERTY_MEDIA_SIZE] == DEFAULT_UNDEFINED) {
597798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov                throw new IllegalStateException("No default media size specified.");
598798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            }
599798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            if (mPrototype.mResolutions == null || mPrototype.mResolutions.isEmpty()) {
600798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov                throw new IllegalStateException("No resolution specified.");
601798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            }
602798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            if (mPrototype.mDefaults[PROPERTY_RESOLUTION] == DEFAULT_UNDEFINED) {
603798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov                throw new IllegalStateException("No default resolution specified.");
604798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            }
605798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            if (mPrototype.mColorModes == 0) {
606798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov                throw new IllegalStateException("No color mode specified.");
607798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            }
608798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            if (mPrototype.mDefaults[PROPERTY_COLOR_MODE] == DEFAULT_UNDEFINED) {
609798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov                throw new IllegalStateException("No default color mode specified.");
610798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            }
611948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav            if (mPrototype.mDuplexModes == 0) {
612948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav                setDuplexModes(PrintAttributes.DUPLEX_MODE_NONE,
613948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav                        PrintAttributes.DUPLEX_MODE_NONE);
614948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav            }
615798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            if (mPrototype.mMinMargins == null) {
616651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav                throw new IllegalArgumentException("margins cannot be null");
617798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            }
6184d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov            return mPrototype;
619798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        }
620798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
621798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        private void throwIfDefaultAlreadySpecified(int propertyIndex) {
622798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            if (mPrototype.mDefaults[propertyIndex] != DEFAULT_UNDEFINED) {
623798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov                throw new IllegalArgumentException("Default already specified.");
624798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            }
625798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        }
626798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    }
627798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
628798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    public static final Parcelable.Creator<PrinterCapabilitiesInfo> CREATOR =
629798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            new Parcelable.Creator<PrinterCapabilitiesInfo>() {
630798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        @Override
631798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        public PrinterCapabilitiesInfo createFromParcel(Parcel parcel) {
632798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            return new PrinterCapabilitiesInfo(parcel);
633798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        }
634798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
635798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        @Override
636798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        public PrinterCapabilitiesInfo[] newArray(int size) {
637798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            return new PrinterCapabilitiesInfo[size];
638798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        }
639798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    };
640798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov}
641