blob: 96f318526384ded91f6e7bcd190677ca9fb55a47 [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
19import android.os.Parcel;
20import android.os.Parcelable;
21import android.print.PrintAttributes.Margins;
22import android.print.PrintAttributes.MediaSize;
23import android.print.PrintAttributes.Resolution;
Svetoslav Ganov798bed62013-08-11 12:29:39 -070024
25import java.util.ArrayList;
26import java.util.Arrays;
Svetoslav Ganov4d4c66d2013-10-24 18:04:39 -070027import java.util.Collections;
Svetoslav Ganov798bed62013-08-11 12:29:39 -070028import java.util.List;
29
30/**
Svetoslav Ganov4d4c66d2013-10-24 18:04:39 -070031 * This class represents the capabilities of a printer. Instances
32 * of this class are created by a print service to report the
33 * capabilities of a printer it manages. The capabilities of a
34 * printer specify how it can print content. For example, what
35 * are the media sizes supported by the printer, what are the
36 * minimal margins of the printer based on its technical design,
37 * etc.
Svetoslav Ganov798bed62013-08-11 12:29:39 -070038 */
39public final class PrinterCapabilitiesInfo implements Parcelable {
40 /**
41 * Undefined default value.
42 *
43 * @hide
44 */
45 public static final int DEFAULT_UNDEFINED = -1;
46
47 private static final int PROPERTY_MEDIA_SIZE = 0;
48 private static final int PROPERTY_RESOLUTION = 1;
Svetoslav773f54d2013-09-03 14:01:43 -070049 private static final int PROPERTY_COLOR_MODE = 2;
Svetoslav948c9a62015-02-02 19:47:04 -080050 private static final int PROPERTY_DUPLEX_MODE = 3;
51 private static final int PROPERTY_COUNT = 4;
Svetoslav Ganov798bed62013-08-11 12:29:39 -070052
53 private static final Margins DEFAULT_MARGINS = new Margins(0, 0, 0, 0);
54
55 private Margins mMinMargins = DEFAULT_MARGINS;
56 private List<MediaSize> mMediaSizes;
57 private List<Resolution> mResolutions;
Svetoslav Ganov798bed62013-08-11 12:29:39 -070058
Svetoslav Ganov798bed62013-08-11 12:29:39 -070059 private int mColorModes;
Svetoslav948c9a62015-02-02 19:47:04 -080060 private int mDuplexModes;
Svetoslav Ganov798bed62013-08-11 12:29:39 -070061
62 private final int[] mDefaults = new int[PROPERTY_COUNT];
Svetoslav Ganov798bed62013-08-11 12:29:39 -070063
64 /**
65 * @hide
66 */
67 public PrinterCapabilitiesInfo() {
68 Arrays.fill(mDefaults, DEFAULT_UNDEFINED);
69 }
70
71 /**
72 * @hide
73 */
74 public PrinterCapabilitiesInfo(PrinterCapabilitiesInfo prototype) {
75 copyFrom(prototype);
76 }
77
78 /**
79 * @hide
80 */
81 public void copyFrom(PrinterCapabilitiesInfo other) {
Svetoslav651dd4e2013-09-12 14:37:47 -070082 if (this == other) {
83 return;
84 }
85
Svetoslav Ganov798bed62013-08-11 12:29:39 -070086 mMinMargins = other.mMinMargins;
87
88 if (other.mMediaSizes != null) {
89 if (mMediaSizes != null) {
90 mMediaSizes.clear();
91 mMediaSizes.addAll(other.mMediaSizes);
92 } else {
93 mMediaSizes = new ArrayList<MediaSize>(other.mMediaSizes);
94 }
95 } else {
96 mMediaSizes = null;
97 }
98
99 if (other.mResolutions != null) {
100 if (mResolutions != null) {
101 mResolutions.clear();
102 mResolutions.addAll(other.mResolutions);
103 } else {
104 mResolutions = new ArrayList<Resolution>(other.mResolutions);
105 }
106 } else {
107 mResolutions = null;
108 }
109
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700110 mColorModes = other.mColorModes;
Svetoslav948c9a62015-02-02 19:47:04 -0800111 mDuplexModes = other.mDuplexModes;
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700112
113 final int defaultCount = other.mDefaults.length;
114 for (int i = 0; i < defaultCount; i++) {
115 mDefaults[i] = other.mDefaults[i];
116 }
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700117 }
118
119 /**
120 * Gets the supported media sizes.
121 *
122 * @return The media sizes.
123 */
124 public List<MediaSize> getMediaSizes() {
Svetoslav Ganov4d4c66d2013-10-24 18:04:39 -0700125 return Collections.unmodifiableList(mMediaSizes);
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700126 }
127
128 /**
129 * Gets the supported resolutions.
130 *
131 * @return The resolutions.
132 */
133 public List<Resolution> getResolutions() {
Svetoslav Ganov4d4c66d2013-10-24 18:04:39 -0700134 return Collections.unmodifiableList(mResolutions);
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700135 }
136
137 /**
Svetoslav651dd4e2013-09-12 14:37:47 -0700138 * Gets the minimal margins. These are the minimal margins
139 * the printer physically supports.
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700140 *
141 * @return The minimal margins.
142 */
143 public Margins getMinMargins() {
144 return mMinMargins;
145 }
146
147 /**
Svetoslav Ganov4d4c66d2013-10-24 18:04:39 -0700148 * Gets the bit mask of supported color modes.
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700149 *
Svetoslav Ganov4d4c66d2013-10-24 18:04:39 -0700150 * @return The bit mask of supported color modes.
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700151 *
152 * @see PrintAttributes#COLOR_MODE_COLOR
153 * @see PrintAttributes#COLOR_MODE_MONOCHROME
154 */
155 public int getColorModes() {
156 return mColorModes;
157 }
158
159 /**
Svetoslav948c9a62015-02-02 19:47:04 -0800160 * Gets the bit mask of supported duplex modes.
161 *
162 * @return The bit mask of supported duplex modes.
163 *
164 * @see PrintAttributes#DUPLEX_MODE_NONE
165 * @see PrintAttributes#DUPLEX_MODE_LONG_EDGE
166 * @see PrintAttributes#DUPLEX_MODE_SHORT_EDGE
167 */
168 public int getDuplexModes() {
169 return mDuplexModes;
170 }
171
172 /**
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700173 * Gets the default print attributes.
174 *
Svetoslav651dd4e2013-09-12 14:37:47 -0700175 * @return The default attributes.
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700176 */
Svetoslav651dd4e2013-09-12 14:37:47 -0700177 public PrintAttributes getDefaults() {
178 PrintAttributes.Builder builder = new PrintAttributes.Builder();
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700179
Svetoslav651dd4e2013-09-12 14:37:47 -0700180 builder.setMinMargins(mMinMargins);
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700181
182 final int mediaSizeIndex = mDefaults[PROPERTY_MEDIA_SIZE];
183 if (mediaSizeIndex >= 0) {
Svetoslav651dd4e2013-09-12 14:37:47 -0700184 builder.setMediaSize(mMediaSizes.get(mediaSizeIndex));
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700185 }
186
187 final int resolutionIndex = mDefaults[PROPERTY_RESOLUTION];
188 if (resolutionIndex >= 0) {
Svetoslav651dd4e2013-09-12 14:37:47 -0700189 builder.setResolution(mResolutions.get(resolutionIndex));
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700190 }
191
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700192 final int colorMode = mDefaults[PROPERTY_COLOR_MODE];
193 if (colorMode > 0) {
Svetoslav651dd4e2013-09-12 14:37:47 -0700194 builder.setColorMode(colorMode);
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700195 }
Svetoslav651dd4e2013-09-12 14:37:47 -0700196
Svetoslav948c9a62015-02-02 19:47:04 -0800197 final int duplexMode = mDefaults[PROPERTY_DUPLEX_MODE];
198 if (duplexMode > 0) {
199 builder.setDuplexMode(duplexMode);
200 }
201
Svetoslav651dd4e2013-09-12 14:37:47 -0700202 return builder.build();
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700203 }
204
205 private PrinterCapabilitiesInfo(Parcel parcel) {
206 mMinMargins = readMargins(parcel);
207 readMediaSizes(parcel);
208 readResolutions(parcel);
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700209
210 mColorModes = parcel.readInt();
Svetoslav948c9a62015-02-02 19:47:04 -0800211 mDuplexModes = parcel.readInt();
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700212
213 readDefaults(parcel);
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700214 }
215
216 @Override
217 public int describeContents() {
218 return 0;
219 }
220
221 @Override
222 public void writeToParcel(Parcel parcel, int flags) {
223 writeMargins(mMinMargins, parcel);
224 writeMediaSizes(parcel);
225 writeResolutions(parcel);
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700226
227 parcel.writeInt(mColorModes);
Svetoslav948c9a62015-02-02 19:47:04 -0800228 parcel.writeInt(mDuplexModes);
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700229
230 writeDefaults(parcel);
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700231 }
232
233 @Override
234 public int hashCode() {
235 final int prime = 31;
236 int result = 1;
237 result = prime * result + ((mMinMargins == null) ? 0 : mMinMargins.hashCode());
238 result = prime * result + ((mMediaSizes == null) ? 0 : mMediaSizes.hashCode());
239 result = prime * result + ((mResolutions == null) ? 0 : mResolutions.hashCode());
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700240 result = prime * result + mColorModes;
Svetoslav948c9a62015-02-02 19:47:04 -0800241 result = prime * result + mDuplexModes;
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700242 result = prime * result + Arrays.hashCode(mDefaults);
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700243 return result;
244 }
245
246 @Override
247 public boolean equals(Object obj) {
248 if (this == obj) {
249 return true;
250 }
251 if (obj == null) {
252 return false;
253 }
254 if (getClass() != obj.getClass()) {
255 return false;
256 }
257 PrinterCapabilitiesInfo other = (PrinterCapabilitiesInfo) obj;
258 if (mMinMargins == null) {
259 if (other.mMinMargins != null) {
260 return false;
261 }
262 } else if (!mMinMargins.equals(other.mMinMargins)) {
263 return false;
264 }
265 if (mMediaSizes == null) {
266 if (other.mMediaSizes != null) {
267 return false;
268 }
269 } else if (!mMediaSizes.equals(other.mMediaSizes)) {
270 return false;
271 }
272 if (mResolutions == null) {
273 if (other.mResolutions != null) {
274 return false;
275 }
276 } else if (!mResolutions.equals(other.mResolutions)) {
277 return false;
278 }
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700279 if (mColorModes != other.mColorModes) {
280 return false;
281 }
Svetoslav948c9a62015-02-02 19:47:04 -0800282 if (mDuplexModes != other.mDuplexModes) {
283 return false;
284 }
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700285 if (!Arrays.equals(mDefaults, other.mDefaults)) {
286 return false;
287 }
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700288 return true;
289 }
290
291 @Override
292 public String toString() {
293 StringBuilder builder = new StringBuilder();
294 builder.append("PrinterInfo{");
295 builder.append("minMargins=").append(mMinMargins);
296 builder.append(", mediaSizes=").append(mMediaSizes);
297 builder.append(", resolutions=").append(mResolutions);
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700298 builder.append(", colorModes=").append(colorModesToString());
Svetoslav948c9a62015-02-02 19:47:04 -0800299 builder.append(", duplexModes=").append(duplexModesToString());
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700300 builder.append("\"}");
301 return builder.toString();
302 }
303
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700304 private String colorModesToString() {
305 StringBuilder builder = new StringBuilder();
306 builder.append('[');
307 int colorModes = mColorModes;
308 while (colorModes != 0) {
309 final int colorMode = 1 << Integer.numberOfTrailingZeros(colorModes);
310 colorModes &= ~colorMode;
Svetoslav651dd4e2013-09-12 14:37:47 -0700311 if (builder.length() > 1) {
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700312 builder.append(", ");
313 }
314 builder.append(PrintAttributes.colorModeToString(colorMode));
315 }
316 builder.append(']');
317 return builder.toString();
318 }
319
Svetoslav948c9a62015-02-02 19:47:04 -0800320 private String duplexModesToString() {
321 StringBuilder builder = new StringBuilder();
322 builder.append('[');
323 int duplexModes = mDuplexModes;
324 while (duplexModes != 0) {
325 final int duplexMode = 1 << Integer.numberOfTrailingZeros(duplexModes);
326 duplexModes &= ~duplexMode;
327 if (builder.length() > 1) {
328 builder.append(", ");
329 }
330 builder.append(PrintAttributes.duplexModeToString(duplexMode));
331 }
332 builder.append(']');
333 return builder.toString();
334 }
335
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700336 private void writeMediaSizes(Parcel parcel) {
337 if (mMediaSizes == null) {
338 parcel.writeInt(0);
339 return;
340 }
341 final int mediaSizeCount = mMediaSizes.size();
342 parcel.writeInt(mediaSizeCount);
343 for (int i = 0; i < mediaSizeCount; i++) {
344 mMediaSizes.get(i).writeToParcel(parcel);
345 }
346 }
347
348 private void readMediaSizes(Parcel parcel) {
349 final int mediaSizeCount = parcel.readInt();
350 if (mediaSizeCount > 0 && mMediaSizes == null) {
351 mMediaSizes = new ArrayList<MediaSize>();
352 }
353 for (int i = 0; i < mediaSizeCount; i++) {
354 mMediaSizes.add(MediaSize.createFromParcel(parcel));
355 }
356 }
357
358 private void writeResolutions(Parcel parcel) {
359 if (mResolutions == null) {
360 parcel.writeInt(0);
361 return;
362 }
363 final int resolutionCount = mResolutions.size();
364 parcel.writeInt(resolutionCount);
365 for (int i = 0; i < resolutionCount; i++) {
366 mResolutions.get(i).writeToParcel(parcel);
367 }
368 }
369
370 private void readResolutions(Parcel parcel) {
371 final int resolutionCount = parcel.readInt();
372 if (resolutionCount > 0 && mResolutions == null) {
373 mResolutions = new ArrayList<Resolution>();
374 }
375 for (int i = 0; i < resolutionCount; i++) {
376 mResolutions.add(Resolution.createFromParcel(parcel));
377 }
378 }
379
380 private void writeMargins(Margins margins, Parcel parcel) {
381 if (margins == null) {
382 parcel.writeInt(0);
383 } else {
384 parcel.writeInt(1);
385 margins.writeToParcel(parcel);
386 }
387 }
388
389 private Margins readMargins(Parcel parcel) {
390 return (parcel.readInt() == 1) ? Margins.createFromParcel(parcel) : null;
391 }
392
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700393 private void readDefaults(Parcel parcel) {
394 final int defaultCount = parcel.readInt();
395 for (int i = 0; i < defaultCount; i++) {
396 mDefaults[i] = parcel.readInt();
397 }
398 }
399
400 private void writeDefaults(Parcel parcel) {
401 final int defaultCount = mDefaults.length;
402 parcel.writeInt(defaultCount);
403 for (int i = 0; i < defaultCount; i++) {
404 parcel.writeInt(mDefaults[i]);
405 }
406 }
407
408 /**
Svetoslav Ganov4d4c66d2013-10-24 18:04:39 -0700409 * Builder for creating of a {@link PrinterCapabilitiesInfo}. This class is
410 * responsible to enforce that all required attributes have at least one
411 * default value. In other words, this class creates only well-formed {@link
412 * PrinterCapabilitiesInfo}s.
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700413 * <p>
414 * Look at the individual methods for a reference whether a property is
415 * required or if it is optional.
416 * </p>
417 */
418 public static final class Builder {
419 private final PrinterCapabilitiesInfo mPrototype;
420
421 /**
422 * Creates a new instance.
423 *
Svetoslav Ganov4d4c66d2013-10-24 18:04:39 -0700424 * @param printerId The printer id. Cannot be <code>null</code>.
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700425 *
Svetoslav Ganov4d4c66d2013-10-24 18:04:39 -0700426 * @throws IllegalArgumentException If the printer id is <code>null</code>.
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700427 */
428 public Builder(PrinterId printerId) {
429 if (printerId == null) {
430 throw new IllegalArgumentException("printerId cannot be null.");
431 }
432 mPrototype = new PrinterCapabilitiesInfo();
433 }
434
435 /**
436 * Adds a supported media size.
437 * <p>
438 * <strong>Required:</strong> Yes
439 * </p>
440 *
441 * @param mediaSize A media size.
442 * @param isDefault Whether this is the default.
443 * @return This builder.
444 * @throws IllegalArgumentException If set as default and there
445 * is already a default.
446 *
447 * @see PrintAttributes.MediaSize
448 */
449 public Builder addMediaSize(MediaSize mediaSize, boolean isDefault) {
450 if (mPrototype.mMediaSizes == null) {
451 mPrototype.mMediaSizes = new ArrayList<MediaSize>();
452 }
453 final int insertionIndex = mPrototype.mMediaSizes.size();
454 mPrototype.mMediaSizes.add(mediaSize);
455 if (isDefault) {
456 throwIfDefaultAlreadySpecified(PROPERTY_MEDIA_SIZE);
457 mPrototype.mDefaults[PROPERTY_MEDIA_SIZE] = insertionIndex;
458 }
459 return this;
460 }
461
462 /**
463 * Adds a supported resolution.
464 * <p>
465 * <strong>Required:</strong> Yes
466 * </p>
467 *
468 * @param resolution A resolution.
469 * @param isDefault Whether this is the default.
470 * @return This builder.
471 *
472 * @throws IllegalArgumentException If set as default and there
473 * is already a default.
474 *
475 * @see PrintAttributes.Resolution
476 */
477 public Builder addResolution(Resolution resolution, boolean isDefault) {
478 if (mPrototype.mResolutions == null) {
479 mPrototype.mResolutions = new ArrayList<Resolution>();
480 }
481 final int insertionIndex = mPrototype.mResolutions.size();
482 mPrototype.mResolutions.add(resolution);
483 if (isDefault) {
484 throwIfDefaultAlreadySpecified(PROPERTY_RESOLUTION);
485 mPrototype.mDefaults[PROPERTY_RESOLUTION] = insertionIndex;
486 }
487 return this;
488 }
489
490 /**
Svetoslav651dd4e2013-09-12 14:37:47 -0700491 * Sets the minimal margins. These are the minimal margins
492 * the printer physically supports.
493 *
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700494 * <p>
Svetoslav651dd4e2013-09-12 14:37:47 -0700495 * <strong>Required:</strong> Yes
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700496 * </p>
497 *
498 * @param margins The margins.
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700499 * @return This builder.
500 *
Svetoslav651dd4e2013-09-12 14:37:47 -0700501 * @throws IllegalArgumentException If margins are <code>null</code>.
502 *
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700503 * @see PrintAttributes.Margins
504 */
Svetoslav651dd4e2013-09-12 14:37:47 -0700505 public Builder setMinMargins(Margins margins) {
506 if (margins == null) {
507 throw new IllegalArgumentException("margins cannot be null");
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700508 }
509 mPrototype.mMinMargins = margins;
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700510 return this;
511 }
512
513 /**
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700514 * Sets the color modes.
515 * <p>
516 * <strong>Required:</strong> Yes
517 * </p>
518 *
519 * @param colorModes The color mode bit mask.
520 * @param defaultColorMode The default color mode.
521 * @return This builder.
Svetoslavb628dd82014-01-02 11:23:44 -0800522 * <p>
523 * <strong>Note:</strong> On platform version 19 (Kitkat) specifying
524 * only PrintAttributes#COLOR_MODE_MONOCHROME leads to a print spooler
525 * crash. Hence, you should declare either both color modes or
526 * PrintAttributes#COLOR_MODE_COLOR.
527 * </p>
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700528 *
529 * @throws IllegalArgumentException If color modes contains an invalid
530 * mode bit or if the default color mode is invalid.
531 *
532 * @see PrintAttributes#COLOR_MODE_COLOR
533 * @see PrintAttributes#COLOR_MODE_MONOCHROME
534 */
535 public Builder setColorModes(int colorModes, int defaultColorMode) {
536 int currentModes = colorModes;
537 while (currentModes > 0) {
538 final int currentMode = (1 << Integer.numberOfTrailingZeros(currentModes));
539 currentModes &= ~currentMode;
540 PrintAttributes.enforceValidColorMode(currentMode);
541 }
Svetoslav948c9a62015-02-02 19:47:04 -0800542 PrintAttributes.enforceValidColorMode(defaultColorMode);
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700543 mPrototype.mColorModes = colorModes;
544 mPrototype.mDefaults[PROPERTY_COLOR_MODE] = defaultColorMode;
545 return this;
546 }
547
548 /**
Svetoslav948c9a62015-02-02 19:47:04 -0800549 * Sets the duplex modes.
550 * <p>
551 * <strong>Required:</strong> No
552 * </p>
553 *
554 * @param duplexModes The duplex mode bit mask.
555 * @param defaultDuplexMode The default duplex mode.
556 * @return This builder.
557 *
558 * @throws IllegalArgumentException If duplex modes contains an invalid
559 * mode bit or if the default duplex mode is invalid.
560 *
561 * @see PrintAttributes#DUPLEX_MODE_NONE
562 * @see PrintAttributes#DUPLEX_MODE_LONG_EDGE
563 * @see PrintAttributes#DUPLEX_MODE_SHORT_EDGE
564 */
565 public Builder setDuplexModes(int duplexModes, int defaultDuplexMode) {
566 int currentModes = duplexModes;
567 while (currentModes > 0) {
568 final int currentMode = (1 << Integer.numberOfTrailingZeros(currentModes));
569 currentModes &= ~currentMode;
570 PrintAttributes.enforceValidDuplexMode(currentMode);
571 }
572 PrintAttributes.enforceValidDuplexMode(defaultDuplexMode);
573 mPrototype.mDuplexModes = duplexModes;
574 mPrototype.mDefaults[PROPERTY_DUPLEX_MODE] = defaultDuplexMode;
575 return this;
576 }
577
578 /**
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700579 * Crates a new {@link PrinterCapabilitiesInfo} enforcing that all
Svetoslav Ganov4d4c66d2013-10-24 18:04:39 -0700580 * required properties have been specified. See individual methods
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700581 * in this class for reference about required attributes.
Svetoslav948c9a62015-02-02 19:47:04 -0800582 * <p>
583 * <strong>Note:</strong> If you do not add supported duplex modes,
584 * {@link android.print.PrintAttributes#DUPLEX_MODE_NONE} will set
585 * as the only supported mode and also as the default duplex mode.
586 * </p>
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700587 *
588 * @return A new {@link PrinterCapabilitiesInfo}.
589 *
590 * @throws IllegalStateException If a required attribute was not specified.
591 */
Svetoslav651dd4e2013-09-12 14:37:47 -0700592 public PrinterCapabilitiesInfo build() {
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700593 if (mPrototype.mMediaSizes == null || mPrototype.mMediaSizes.isEmpty()) {
594 throw new IllegalStateException("No media size specified.");
595 }
596 if (mPrototype.mDefaults[PROPERTY_MEDIA_SIZE] == DEFAULT_UNDEFINED) {
597 throw new IllegalStateException("No default media size specified.");
598 }
599 if (mPrototype.mResolutions == null || mPrototype.mResolutions.isEmpty()) {
600 throw new IllegalStateException("No resolution specified.");
601 }
602 if (mPrototype.mDefaults[PROPERTY_RESOLUTION] == DEFAULT_UNDEFINED) {
603 throw new IllegalStateException("No default resolution specified.");
604 }
605 if (mPrototype.mColorModes == 0) {
606 throw new IllegalStateException("No color mode specified.");
607 }
608 if (mPrototype.mDefaults[PROPERTY_COLOR_MODE] == DEFAULT_UNDEFINED) {
609 throw new IllegalStateException("No default color mode specified.");
610 }
Svetoslav948c9a62015-02-02 19:47:04 -0800611 if (mPrototype.mDuplexModes == 0) {
612 setDuplexModes(PrintAttributes.DUPLEX_MODE_NONE,
613 PrintAttributes.DUPLEX_MODE_NONE);
614 }
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700615 if (mPrototype.mMinMargins == null) {
Svetoslav651dd4e2013-09-12 14:37:47 -0700616 throw new IllegalArgumentException("margins cannot be null");
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700617 }
Svetoslav Ganov4d4c66d2013-10-24 18:04:39 -0700618 return mPrototype;
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700619 }
620
621 private void throwIfDefaultAlreadySpecified(int propertyIndex) {
622 if (mPrototype.mDefaults[propertyIndex] != DEFAULT_UNDEFINED) {
623 throw new IllegalArgumentException("Default already specified.");
624 }
625 }
626 }
627
628 public static final Parcelable.Creator<PrinterCapabilitiesInfo> CREATOR =
629 new Parcelable.Creator<PrinterCapabilitiesInfo>() {
630 @Override
631 public PrinterCapabilitiesInfo createFromParcel(Parcel parcel) {
632 return new PrinterCapabilitiesInfo(parcel);
633 }
634
635 @Override
636 public PrinterCapabilitiesInfo[] newArray(int size) {
637 return new PrinterCapabilitiesInfo[size];
638 }
639 };
640}