blob: d13879ba691477574bdbcc13e7b1987d2aeb7b8c [file] [log] [blame]
Svetoslav Ganov798bed62013-08-11 12:29:39 -07001/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.print;
18
Philip P. Moltmannc43639c2015-12-18 13:58:40 -080019import android.annotation.NonNull;
Svetoslav Ganov798bed62013-08-11 12:29:39 -070020import android.os.Parcel;
21import android.os.Parcelable;
Philip P. Moltmannc43639c2015-12-18 13:58:40 -080022import android.print.PrintAttributes.ColorMode;
23import android.print.PrintAttributes.DuplexMode;
Svetoslav Ganov798bed62013-08-11 12:29:39 -070024import android.print.PrintAttributes.Margins;
25import android.print.PrintAttributes.MediaSize;
26import android.print.PrintAttributes.Resolution;
Svetoslav Ganov798bed62013-08-11 12:29:39 -070027
28import java.util.ArrayList;
29import java.util.Arrays;
Svetoslav Ganov4d4c66d2013-10-24 18:04:39 -070030import java.util.Collections;
Svetoslav Ganov798bed62013-08-11 12:29:39 -070031import java.util.List;
32
33/**
Svetoslav Ganov4d4c66d2013-10-24 18:04:39 -070034 * This class represents the capabilities of a printer. Instances
35 * of this class are created by a print service to report the
36 * capabilities of a printer it manages. The capabilities of a
37 * printer specify how it can print content. For example, what
38 * are the media sizes supported by the printer, what are the
39 * minimal margins of the printer based on its technical design,
40 * etc.
Svetoslav Ganov798bed62013-08-11 12:29:39 -070041 */
42public final class PrinterCapabilitiesInfo implements Parcelable {
43 /**
44 * Undefined default value.
45 *
46 * @hide
47 */
48 public static final int DEFAULT_UNDEFINED = -1;
49
50 private static final int PROPERTY_MEDIA_SIZE = 0;
51 private static final int PROPERTY_RESOLUTION = 1;
Svetoslav773f54d2013-09-03 14:01:43 -070052 private static final int PROPERTY_COLOR_MODE = 2;
Svetoslav948c9a62015-02-02 19:47:04 -080053 private static final int PROPERTY_DUPLEX_MODE = 3;
54 private static final int PROPERTY_COUNT = 4;
Svetoslav Ganov798bed62013-08-11 12:29:39 -070055
56 private static final Margins DEFAULT_MARGINS = new Margins(0, 0, 0, 0);
57
58 private Margins mMinMargins = DEFAULT_MARGINS;
59 private List<MediaSize> mMediaSizes;
60 private List<Resolution> mResolutions;
Svetoslav Ganov798bed62013-08-11 12:29:39 -070061
Svetoslav Ganov798bed62013-08-11 12:29:39 -070062 private int mColorModes;
Svetoslav948c9a62015-02-02 19:47:04 -080063 private int mDuplexModes;
Svetoslav Ganov798bed62013-08-11 12:29:39 -070064
65 private final int[] mDefaults = new int[PROPERTY_COUNT];
Svetoslav Ganov798bed62013-08-11 12:29:39 -070066
67 /**
68 * @hide
69 */
70 public PrinterCapabilitiesInfo() {
71 Arrays.fill(mDefaults, DEFAULT_UNDEFINED);
72 }
73
74 /**
75 * @hide
76 */
77 public PrinterCapabilitiesInfo(PrinterCapabilitiesInfo prototype) {
78 copyFrom(prototype);
79 }
80
81 /**
82 * @hide
83 */
84 public void copyFrom(PrinterCapabilitiesInfo other) {
Svetoslav651dd4e2013-09-12 14:37:47 -070085 if (this == other) {
86 return;
87 }
88
Svetoslav Ganov798bed62013-08-11 12:29:39 -070089 mMinMargins = other.mMinMargins;
90
91 if (other.mMediaSizes != null) {
92 if (mMediaSizes != null) {
93 mMediaSizes.clear();
94 mMediaSizes.addAll(other.mMediaSizes);
95 } else {
96 mMediaSizes = new ArrayList<MediaSize>(other.mMediaSizes);
97 }
98 } else {
99 mMediaSizes = null;
100 }
101
102 if (other.mResolutions != null) {
103 if (mResolutions != null) {
104 mResolutions.clear();
105 mResolutions.addAll(other.mResolutions);
106 } else {
107 mResolutions = new ArrayList<Resolution>(other.mResolutions);
108 }
109 } else {
110 mResolutions = null;
111 }
112
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700113 mColorModes = other.mColorModes;
Svetoslav948c9a62015-02-02 19:47:04 -0800114 mDuplexModes = other.mDuplexModes;
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700115
116 final int defaultCount = other.mDefaults.length;
117 for (int i = 0; i < defaultCount; i++) {
118 mDefaults[i] = other.mDefaults[i];
119 }
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700120 }
121
122 /**
123 * Gets the supported media sizes.
124 *
125 * @return The media sizes.
126 */
Philip P. Moltmannc43639c2015-12-18 13:58:40 -0800127 public @NonNull List<MediaSize> getMediaSizes() {
Svetoslav Ganov4d4c66d2013-10-24 18:04:39 -0700128 return Collections.unmodifiableList(mMediaSizes);
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700129 }
130
131 /**
132 * Gets the supported resolutions.
133 *
134 * @return The resolutions.
135 */
Philip P. Moltmannc43639c2015-12-18 13:58:40 -0800136 public @NonNull List<Resolution> getResolutions() {
Svetoslav Ganov4d4c66d2013-10-24 18:04:39 -0700137 return Collections.unmodifiableList(mResolutions);
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700138 }
139
140 /**
Svetoslav651dd4e2013-09-12 14:37:47 -0700141 * Gets the minimal margins. These are the minimal margins
142 * the printer physically supports.
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700143 *
144 * @return The minimal margins.
145 */
Philip P. Moltmannc43639c2015-12-18 13:58:40 -0800146 public @NonNull Margins getMinMargins() {
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700147 return mMinMargins;
148 }
149
150 /**
Svetoslav Ganov4d4c66d2013-10-24 18:04:39 -0700151 * Gets the bit mask of supported color modes.
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700152 *
Svetoslav Ganov4d4c66d2013-10-24 18:04:39 -0700153 * @return The bit mask of supported color modes.
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700154 *
155 * @see PrintAttributes#COLOR_MODE_COLOR
156 * @see PrintAttributes#COLOR_MODE_MONOCHROME
157 */
Philip P. Moltmannc43639c2015-12-18 13:58:40 -0800158 public @ColorMode int getColorModes() {
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700159 return mColorModes;
160 }
161
162 /**
Svetoslav948c9a62015-02-02 19:47:04 -0800163 * Gets the bit mask of supported duplex modes.
164 *
165 * @return The bit mask of supported duplex modes.
166 *
167 * @see PrintAttributes#DUPLEX_MODE_NONE
168 * @see PrintAttributes#DUPLEX_MODE_LONG_EDGE
169 * @see PrintAttributes#DUPLEX_MODE_SHORT_EDGE
170 */
Philip P. Moltmannc43639c2015-12-18 13:58:40 -0800171 public @DuplexMode int getDuplexModes() {
Svetoslav948c9a62015-02-02 19:47:04 -0800172 return mDuplexModes;
173 }
174
175 /**
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700176 * Gets the default print attributes.
177 *
Svetoslav651dd4e2013-09-12 14:37:47 -0700178 * @return The default attributes.
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700179 */
Philip P. Moltmannc43639c2015-12-18 13:58:40 -0800180 public @NonNull PrintAttributes getDefaults() {
Svetoslav651dd4e2013-09-12 14:37:47 -0700181 PrintAttributes.Builder builder = new PrintAttributes.Builder();
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700182
Svetoslav651dd4e2013-09-12 14:37:47 -0700183 builder.setMinMargins(mMinMargins);
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700184
185 final int mediaSizeIndex = mDefaults[PROPERTY_MEDIA_SIZE];
186 if (mediaSizeIndex >= 0) {
Svetoslav651dd4e2013-09-12 14:37:47 -0700187 builder.setMediaSize(mMediaSizes.get(mediaSizeIndex));
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700188 }
189
190 final int resolutionIndex = mDefaults[PROPERTY_RESOLUTION];
191 if (resolutionIndex >= 0) {
Svetoslav651dd4e2013-09-12 14:37:47 -0700192 builder.setResolution(mResolutions.get(resolutionIndex));
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700193 }
194
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700195 final int colorMode = mDefaults[PROPERTY_COLOR_MODE];
196 if (colorMode > 0) {
Svetoslav651dd4e2013-09-12 14:37:47 -0700197 builder.setColorMode(colorMode);
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700198 }
Svetoslav651dd4e2013-09-12 14:37:47 -0700199
Svetoslav948c9a62015-02-02 19:47:04 -0800200 final int duplexMode = mDefaults[PROPERTY_DUPLEX_MODE];
201 if (duplexMode > 0) {
202 builder.setDuplexMode(duplexMode);
203 }
204
Svetoslav651dd4e2013-09-12 14:37:47 -0700205 return builder.build();
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700206 }
207
208 private PrinterCapabilitiesInfo(Parcel parcel) {
209 mMinMargins = readMargins(parcel);
210 readMediaSizes(parcel);
211 readResolutions(parcel);
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700212
213 mColorModes = parcel.readInt();
Svetoslav948c9a62015-02-02 19:47:04 -0800214 mDuplexModes = parcel.readInt();
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700215
216 readDefaults(parcel);
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700217 }
218
219 @Override
220 public int describeContents() {
221 return 0;
222 }
223
224 @Override
225 public void writeToParcel(Parcel parcel, int flags) {
226 writeMargins(mMinMargins, parcel);
227 writeMediaSizes(parcel);
228 writeResolutions(parcel);
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700229
230 parcel.writeInt(mColorModes);
Svetoslav948c9a62015-02-02 19:47:04 -0800231 parcel.writeInt(mDuplexModes);
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700232
233 writeDefaults(parcel);
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700234 }
235
236 @Override
237 public int hashCode() {
238 final int prime = 31;
239 int result = 1;
240 result = prime * result + ((mMinMargins == null) ? 0 : mMinMargins.hashCode());
241 result = prime * result + ((mMediaSizes == null) ? 0 : mMediaSizes.hashCode());
242 result = prime * result + ((mResolutions == null) ? 0 : mResolutions.hashCode());
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700243 result = prime * result + mColorModes;
Svetoslav948c9a62015-02-02 19:47:04 -0800244 result = prime * result + mDuplexModes;
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700245 result = prime * result + Arrays.hashCode(mDefaults);
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700246 return result;
247 }
248
249 @Override
250 public boolean equals(Object obj) {
251 if (this == obj) {
252 return true;
253 }
254 if (obj == null) {
255 return false;
256 }
257 if (getClass() != obj.getClass()) {
258 return false;
259 }
260 PrinterCapabilitiesInfo other = (PrinterCapabilitiesInfo) obj;
261 if (mMinMargins == null) {
262 if (other.mMinMargins != null) {
263 return false;
264 }
265 } else if (!mMinMargins.equals(other.mMinMargins)) {
266 return false;
267 }
268 if (mMediaSizes == null) {
269 if (other.mMediaSizes != null) {
270 return false;
271 }
272 } else if (!mMediaSizes.equals(other.mMediaSizes)) {
273 return false;
274 }
275 if (mResolutions == null) {
276 if (other.mResolutions != null) {
277 return false;
278 }
279 } else if (!mResolutions.equals(other.mResolutions)) {
280 return false;
281 }
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700282 if (mColorModes != other.mColorModes) {
283 return false;
284 }
Svetoslav948c9a62015-02-02 19:47:04 -0800285 if (mDuplexModes != other.mDuplexModes) {
286 return false;
287 }
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700288 if (!Arrays.equals(mDefaults, other.mDefaults)) {
289 return false;
290 }
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700291 return true;
292 }
293
294 @Override
295 public String toString() {
296 StringBuilder builder = new StringBuilder();
297 builder.append("PrinterInfo{");
298 builder.append("minMargins=").append(mMinMargins);
299 builder.append(", mediaSizes=").append(mMediaSizes);
300 builder.append(", resolutions=").append(mResolutions);
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700301 builder.append(", colorModes=").append(colorModesToString());
Svetoslav948c9a62015-02-02 19:47:04 -0800302 builder.append(", duplexModes=").append(duplexModesToString());
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700303 builder.append("\"}");
304 return builder.toString();
305 }
306
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700307 private String colorModesToString() {
308 StringBuilder builder = new StringBuilder();
309 builder.append('[');
310 int colorModes = mColorModes;
311 while (colorModes != 0) {
312 final int colorMode = 1 << Integer.numberOfTrailingZeros(colorModes);
313 colorModes &= ~colorMode;
Svetoslav651dd4e2013-09-12 14:37:47 -0700314 if (builder.length() > 1) {
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700315 builder.append(", ");
316 }
317 builder.append(PrintAttributes.colorModeToString(colorMode));
318 }
319 builder.append(']');
320 return builder.toString();
321 }
322
Svetoslav948c9a62015-02-02 19:47:04 -0800323 private String duplexModesToString() {
324 StringBuilder builder = new StringBuilder();
325 builder.append('[');
326 int duplexModes = mDuplexModes;
327 while (duplexModes != 0) {
328 final int duplexMode = 1 << Integer.numberOfTrailingZeros(duplexModes);
329 duplexModes &= ~duplexMode;
330 if (builder.length() > 1) {
331 builder.append(", ");
332 }
333 builder.append(PrintAttributes.duplexModeToString(duplexMode));
334 }
335 builder.append(']');
336 return builder.toString();
337 }
338
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700339 private void writeMediaSizes(Parcel parcel) {
340 if (mMediaSizes == null) {
341 parcel.writeInt(0);
342 return;
343 }
344 final int mediaSizeCount = mMediaSizes.size();
345 parcel.writeInt(mediaSizeCount);
346 for (int i = 0; i < mediaSizeCount; i++) {
347 mMediaSizes.get(i).writeToParcel(parcel);
348 }
349 }
350
351 private void readMediaSizes(Parcel parcel) {
352 final int mediaSizeCount = parcel.readInt();
353 if (mediaSizeCount > 0 && mMediaSizes == null) {
354 mMediaSizes = new ArrayList<MediaSize>();
355 }
356 for (int i = 0; i < mediaSizeCount; i++) {
357 mMediaSizes.add(MediaSize.createFromParcel(parcel));
358 }
359 }
360
361 private void writeResolutions(Parcel parcel) {
362 if (mResolutions == null) {
363 parcel.writeInt(0);
364 return;
365 }
366 final int resolutionCount = mResolutions.size();
367 parcel.writeInt(resolutionCount);
368 for (int i = 0; i < resolutionCount; i++) {
369 mResolutions.get(i).writeToParcel(parcel);
370 }
371 }
372
373 private void readResolutions(Parcel parcel) {
374 final int resolutionCount = parcel.readInt();
375 if (resolutionCount > 0 && mResolutions == null) {
376 mResolutions = new ArrayList<Resolution>();
377 }
378 for (int i = 0; i < resolutionCount; i++) {
379 mResolutions.add(Resolution.createFromParcel(parcel));
380 }
381 }
382
383 private void writeMargins(Margins margins, Parcel parcel) {
384 if (margins == null) {
385 parcel.writeInt(0);
386 } else {
387 parcel.writeInt(1);
388 margins.writeToParcel(parcel);
389 }
390 }
391
392 private Margins readMargins(Parcel parcel) {
393 return (parcel.readInt() == 1) ? Margins.createFromParcel(parcel) : null;
394 }
395
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700396 private void readDefaults(Parcel parcel) {
397 final int defaultCount = parcel.readInt();
398 for (int i = 0; i < defaultCount; i++) {
399 mDefaults[i] = parcel.readInt();
400 }
401 }
402
403 private void writeDefaults(Parcel parcel) {
404 final int defaultCount = mDefaults.length;
405 parcel.writeInt(defaultCount);
406 for (int i = 0; i < defaultCount; i++) {
407 parcel.writeInt(mDefaults[i]);
408 }
409 }
410
411 /**
Svetoslav Ganov4d4c66d2013-10-24 18:04:39 -0700412 * Builder for creating of a {@link PrinterCapabilitiesInfo}. This class is
413 * responsible to enforce that all required attributes have at least one
414 * default value. In other words, this class creates only well-formed {@link
415 * PrinterCapabilitiesInfo}s.
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700416 * <p>
417 * Look at the individual methods for a reference whether a property is
418 * required or if it is optional.
419 * </p>
420 */
421 public static final class Builder {
422 private final PrinterCapabilitiesInfo mPrototype;
423
424 /**
425 * Creates a new instance.
426 *
Svetoslav Ganov4d4c66d2013-10-24 18:04:39 -0700427 * @param printerId The printer id. Cannot be <code>null</code>.
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700428 *
Svetoslav Ganov4d4c66d2013-10-24 18:04:39 -0700429 * @throws IllegalArgumentException If the printer id is <code>null</code>.
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700430 */
Philip P. Moltmannc43639c2015-12-18 13:58:40 -0800431 public Builder(@NonNull PrinterId printerId) {
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700432 if (printerId == null) {
433 throw new IllegalArgumentException("printerId cannot be null.");
434 }
435 mPrototype = new PrinterCapabilitiesInfo();
436 }
437
438 /**
439 * Adds a supported media size.
440 * <p>
441 * <strong>Required:</strong> Yes
442 * </p>
443 *
444 * @param mediaSize A media size.
445 * @param isDefault Whether this is the default.
446 * @return This builder.
447 * @throws IllegalArgumentException If set as default and there
448 * is already a default.
449 *
450 * @see PrintAttributes.MediaSize
451 */
Philip P. Moltmannc43639c2015-12-18 13:58:40 -0800452 public @NonNull Builder addMediaSize(@NonNull MediaSize mediaSize, boolean isDefault) {
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700453 if (mPrototype.mMediaSizes == null) {
454 mPrototype.mMediaSizes = new ArrayList<MediaSize>();
455 }
456 final int insertionIndex = mPrototype.mMediaSizes.size();
457 mPrototype.mMediaSizes.add(mediaSize);
458 if (isDefault) {
459 throwIfDefaultAlreadySpecified(PROPERTY_MEDIA_SIZE);
460 mPrototype.mDefaults[PROPERTY_MEDIA_SIZE] = insertionIndex;
461 }
462 return this;
463 }
464
465 /**
466 * Adds a supported resolution.
467 * <p>
468 * <strong>Required:</strong> Yes
469 * </p>
470 *
471 * @param resolution A resolution.
472 * @param isDefault Whether this is the default.
473 * @return This builder.
474 *
475 * @throws IllegalArgumentException If set as default and there
476 * is already a default.
477 *
478 * @see PrintAttributes.Resolution
479 */
Philip P. Moltmannc43639c2015-12-18 13:58:40 -0800480 public @NonNull Builder addResolution(@NonNull Resolution resolution, boolean isDefault) {
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700481 if (mPrototype.mResolutions == null) {
482 mPrototype.mResolutions = new ArrayList<Resolution>();
483 }
484 final int insertionIndex = mPrototype.mResolutions.size();
485 mPrototype.mResolutions.add(resolution);
486 if (isDefault) {
487 throwIfDefaultAlreadySpecified(PROPERTY_RESOLUTION);
488 mPrototype.mDefaults[PROPERTY_RESOLUTION] = insertionIndex;
489 }
490 return this;
491 }
492
493 /**
Svetoslav651dd4e2013-09-12 14:37:47 -0700494 * Sets the minimal margins. These are the minimal margins
495 * the printer physically supports.
496 *
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700497 * <p>
Svetoslav651dd4e2013-09-12 14:37:47 -0700498 * <strong>Required:</strong> Yes
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700499 * </p>
500 *
501 * @param margins The margins.
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700502 * @return This builder.
503 *
Svetoslav651dd4e2013-09-12 14:37:47 -0700504 * @throws IllegalArgumentException If margins are <code>null</code>.
505 *
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700506 * @see PrintAttributes.Margins
507 */
Philip P. Moltmannc43639c2015-12-18 13:58:40 -0800508 public @NonNull Builder setMinMargins(@NonNull Margins margins) {
Svetoslav651dd4e2013-09-12 14:37:47 -0700509 if (margins == null) {
510 throw new IllegalArgumentException("margins cannot be null");
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700511 }
512 mPrototype.mMinMargins = margins;
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700513 return this;
514 }
515
516 /**
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700517 * Sets the color modes.
518 * <p>
519 * <strong>Required:</strong> Yes
520 * </p>
521 *
522 * @param colorModes The color mode bit mask.
523 * @param defaultColorMode The default color mode.
524 * @return This builder.
Svetoslavb628dd82014-01-02 11:23:44 -0800525 * <p>
526 * <strong>Note:</strong> On platform version 19 (Kitkat) specifying
527 * only PrintAttributes#COLOR_MODE_MONOCHROME leads to a print spooler
528 * crash. Hence, you should declare either both color modes or
529 * PrintAttributes#COLOR_MODE_COLOR.
530 * </p>
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700531 *
532 * @throws IllegalArgumentException If color modes contains an invalid
533 * mode bit or if the default color mode is invalid.
534 *
535 * @see PrintAttributes#COLOR_MODE_COLOR
536 * @see PrintAttributes#COLOR_MODE_MONOCHROME
537 */
Philip P. Moltmannc43639c2015-12-18 13:58:40 -0800538 public @NonNull Builder setColorModes(@ColorMode int colorModes,
539 @ColorMode int defaultColorMode) {
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700540 int currentModes = colorModes;
541 while (currentModes > 0) {
542 final int currentMode = (1 << Integer.numberOfTrailingZeros(currentModes));
543 currentModes &= ~currentMode;
544 PrintAttributes.enforceValidColorMode(currentMode);
545 }
Svetoslav948c9a62015-02-02 19:47:04 -0800546 PrintAttributes.enforceValidColorMode(defaultColorMode);
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700547 mPrototype.mColorModes = colorModes;
548 mPrototype.mDefaults[PROPERTY_COLOR_MODE] = defaultColorMode;
549 return this;
550 }
551
552 /**
Svetoslav948c9a62015-02-02 19:47:04 -0800553 * Sets the duplex modes.
554 * <p>
555 * <strong>Required:</strong> No
556 * </p>
557 *
558 * @param duplexModes The duplex mode bit mask.
559 * @param defaultDuplexMode The default duplex mode.
560 * @return This builder.
561 *
562 * @throws IllegalArgumentException If duplex modes contains an invalid
563 * mode bit or if the default duplex mode is invalid.
564 *
565 * @see PrintAttributes#DUPLEX_MODE_NONE
566 * @see PrintAttributes#DUPLEX_MODE_LONG_EDGE
567 * @see PrintAttributes#DUPLEX_MODE_SHORT_EDGE
568 */
Philip P. Moltmannc43639c2015-12-18 13:58:40 -0800569 public @NonNull Builder setDuplexModes(@DuplexMode int duplexModes,
570 @DuplexMode int defaultDuplexMode) {
Svetoslav948c9a62015-02-02 19:47:04 -0800571 int currentModes = duplexModes;
572 while (currentModes > 0) {
573 final int currentMode = (1 << Integer.numberOfTrailingZeros(currentModes));
574 currentModes &= ~currentMode;
575 PrintAttributes.enforceValidDuplexMode(currentMode);
576 }
577 PrintAttributes.enforceValidDuplexMode(defaultDuplexMode);
578 mPrototype.mDuplexModes = duplexModes;
579 mPrototype.mDefaults[PROPERTY_DUPLEX_MODE] = defaultDuplexMode;
580 return this;
581 }
582
583 /**
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700584 * Crates a new {@link PrinterCapabilitiesInfo} enforcing that all
Svetoslav Ganov4d4c66d2013-10-24 18:04:39 -0700585 * required properties have been specified. See individual methods
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700586 * in this class for reference about required attributes.
Svetoslav948c9a62015-02-02 19:47:04 -0800587 * <p>
588 * <strong>Note:</strong> If you do not add supported duplex modes,
589 * {@link android.print.PrintAttributes#DUPLEX_MODE_NONE} will set
590 * as the only supported mode and also as the default duplex mode.
591 * </p>
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700592 *
593 * @return A new {@link PrinterCapabilitiesInfo}.
594 *
595 * @throws IllegalStateException If a required attribute was not specified.
596 */
Philip P. Moltmannc43639c2015-12-18 13:58:40 -0800597 public @NonNull PrinterCapabilitiesInfo build() {
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700598 if (mPrototype.mMediaSizes == null || mPrototype.mMediaSizes.isEmpty()) {
599 throw new IllegalStateException("No media size specified.");
600 }
601 if (mPrototype.mDefaults[PROPERTY_MEDIA_SIZE] == DEFAULT_UNDEFINED) {
602 throw new IllegalStateException("No default media size specified.");
603 }
604 if (mPrototype.mResolutions == null || mPrototype.mResolutions.isEmpty()) {
605 throw new IllegalStateException("No resolution specified.");
606 }
607 if (mPrototype.mDefaults[PROPERTY_RESOLUTION] == DEFAULT_UNDEFINED) {
608 throw new IllegalStateException("No default resolution specified.");
609 }
610 if (mPrototype.mColorModes == 0) {
611 throw new IllegalStateException("No color mode specified.");
612 }
613 if (mPrototype.mDefaults[PROPERTY_COLOR_MODE] == DEFAULT_UNDEFINED) {
614 throw new IllegalStateException("No default color mode specified.");
615 }
Svetoslav948c9a62015-02-02 19:47:04 -0800616 if (mPrototype.mDuplexModes == 0) {
617 setDuplexModes(PrintAttributes.DUPLEX_MODE_NONE,
618 PrintAttributes.DUPLEX_MODE_NONE);
619 }
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700620 if (mPrototype.mMinMargins == null) {
Svetoslav651dd4e2013-09-12 14:37:47 -0700621 throw new IllegalArgumentException("margins cannot be null");
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700622 }
Svetoslav Ganov4d4c66d2013-10-24 18:04:39 -0700623 return mPrototype;
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700624 }
625
626 private void throwIfDefaultAlreadySpecified(int propertyIndex) {
627 if (mPrototype.mDefaults[propertyIndex] != DEFAULT_UNDEFINED) {
628 throw new IllegalArgumentException("Default already specified.");
629 }
630 }
631 }
632
633 public static final Parcelable.Creator<PrinterCapabilitiesInfo> CREATOR =
634 new Parcelable.Creator<PrinterCapabilitiesInfo>() {
635 @Override
636 public PrinterCapabilitiesInfo createFromParcel(Parcel parcel) {
637 return new PrinterCapabilitiesInfo(parcel);
638 }
639
640 @Override
641 public PrinterCapabilitiesInfo[] newArray(int size) {
642 return new PrinterCapabilitiesInfo[size];
643 }
644 };
645}