PrinterInfo.java revision 4b9a4d16872bbb50712e007b419ac0b35ff1582d
1/* 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; 24import android.print.PrintAttributes.Tray; 25import android.text.TextUtils; 26import android.util.SparseIntArray; 27 28import java.util.ArrayList; 29import java.util.List; 30 31/** 32 * This class represents the description of a printer. A description 33 * contains the printer id, human readable name, status, and available 34 * options for various printer capabilities, such as media size, etc. 35 */ 36public final class PrinterInfo implements Parcelable { 37 /** 38 * Undefined default value. 39 * 40 * @hide 41 */ 42 public static final int DEFAULT_UNDEFINED = -1; 43 44 private static final int MIN_COPIES = 1; 45 46 private static final int PROPERTY_MEDIA_SIZE = 0; 47 private static final int PROPERTY_RESOLUTION = 1; 48 private static final int PROPERTY_INPUT_TRAY = 2; 49 private static final int PROPERTY_OUTPUT_TRAY = 3; 50 private static final int PROPERTY_DUPLEX_MODE = 4; 51 private static final int PROPERTY_COLOR_MODE = 5; 52 private static final int PROPERTY_FITTING_MODE = 6; 53 private static final int PROPERTY_ORIENTATION = 7; 54 55 /** Printer status: the printer is ready to print. */ 56 public static final int STATUS_READY = 1; 57 58 // TODO: Add printer status constants. 59 60 private PrinterId mId; 61 private CharSequence mLabel; 62 private int mStatus; 63 64 private Margins mMinMargins; 65 private final List<MediaSize> mMediaSizes = new ArrayList<MediaSize>(); // required 66 private final List<Resolution> mResolutions = new ArrayList<Resolution>(); // required 67 private List<Tray> mInputTrays; 68 private List<Tray> mOutputTrays; 69 70 private int mDuplexModes; 71 private int mColorModes; 72 private int mFittingModes; 73 private int mOrientations; 74 75 private final SparseIntArray mDefaults = new SparseIntArray(); 76 private Margins mDefaultMargins; 77 78 private PrinterInfo() { 79 mDefaults.put(PROPERTY_MEDIA_SIZE, DEFAULT_UNDEFINED); 80 mDefaults.put(PROPERTY_RESOLUTION, DEFAULT_UNDEFINED); 81 mDefaults.put(PROPERTY_INPUT_TRAY, DEFAULT_UNDEFINED); 82 mDefaults.put(PROPERTY_OUTPUT_TRAY, DEFAULT_UNDEFINED); 83 mDefaults.put(PROPERTY_DUPLEX_MODE, DEFAULT_UNDEFINED); 84 mDefaults.put(PROPERTY_COLOR_MODE, DEFAULT_UNDEFINED); 85 mDefaults.put(PROPERTY_FITTING_MODE, DEFAULT_UNDEFINED); 86 mDefaults.put(PROPERTY_ORIENTATION, DEFAULT_UNDEFINED); 87 } 88 89 /** 90 * Get the globally unique printer id. 91 * 92 * @return The printer id. 93 */ 94 public PrinterId getId() { 95 return mId; 96 } 97 98 /** 99 * Gets the human readable printer label. 100 * 101 * @return The human readable label. 102 */ 103 public CharSequence getLabel() { 104 return mLabel; 105 } 106 107 /** 108 * Gets the status of the printer. 109 * 110 * @return The status. 111 */ 112 public int getStatus() { 113 return mStatus; 114 } 115 116 /** 117 * Gets the supported media sizes. 118 * 119 * @return The supported media sizes. 120 */ 121 public List<MediaSize> getMediaSizes() { 122 return mMediaSizes; 123 } 124 125 /** 126 * Gets the supported resolutions. 127 * 128 * @return The supported resolutions. 129 */ 130 public List<Resolution> getResolutions() { 131 return mResolutions; 132 } 133 134 /** 135 * Gets the minimal supported margins. 136 * 137 * @return The minimal margins. 138 */ 139 public Margins getMinMargins() { 140 return mMinMargins; 141 } 142 143 /** 144 * Gets the available input trays. 145 * 146 * @return The input trays. 147 */ 148 public List<Tray> getInputTrays() { 149 return mInputTrays; 150 } 151 152 /** 153 * Gets the available output trays. 154 * 155 * @return The output trays. 156 */ 157 public List<Tray> getOutputTrays() { 158 return mOutputTrays; 159 } 160 161 /** 162 * Gets the supported duplex modes. 163 * 164 * @return The duplex modes. 165 * 166 * @see PrintAttributes#DUPLEX_MODE_NONE 167 * @see PrintAttributes#DUPLEX_MODE_LONG_EDGE 168 * @see PrintAttributes#DUPLEX_MODE_SHORT_EDGE 169 */ 170 public int getDuplexModes() { 171 return mDuplexModes; 172 } 173 174 /** 175 * Gets the supported color modes. 176 * 177 * @return The color modes. 178 * 179 * @see PrintAttributes#COLOR_MODE_COLOR 180 * @see PrintAttributes#COLOR_MODE_MONOCHROME 181 */ 182 public int getColorModes() { 183 return mColorModes; 184 } 185 186 /** 187 * Gets the supported fitting modes. 188 * 189 * @return The fitting modes. 190 * 191 * @see PrintAttributes#FITTING_MODE_NONE 192 * @see PrintAttributes#FITTING_MODE_FIT_TO_PAGE 193 */ 194 public int getFittingModes() { 195 return mFittingModes; 196 } 197 198 /** 199 * Gets the supported orientations. 200 * 201 * @return The orientations. 202 * 203 * @see PrintAttributes#ORIENTATION_PORTRAIT 204 * @see PrintAttributes#ORIENTATION_LANDSCAPE 205 */ 206 public int getOrientations() { 207 return mOrientations; 208 } 209 210 /** 211 * Gets the default print attributes. 212 * 213 * @param outAttributes The attributes to populated. 214 */ 215 public void getDefaults(PrintAttributes outAttributes) { 216 outAttributes.clear(); 217 218 // TODO: Do we want a printer to specify default copies? 219 outAttributes.setCopies(MIN_COPIES); 220 221 outAttributes.setMargins(mDefaultMargins); 222 223 final int mediaSizeIndex = mDefaults.get(PROPERTY_MEDIA_SIZE); 224 if (mediaSizeIndex >= 0) { 225 outAttributes.setMediaSize(mMediaSizes.get(mediaSizeIndex)); 226 } 227 228 final int resolutionIndex = mDefaults.get(PROPERTY_RESOLUTION); 229 if (resolutionIndex >= 0) { 230 outAttributes.setResolution(mResolutions.get(resolutionIndex)); 231 } 232 233 final int inputTrayIndex = mDefaults.get(PROPERTY_INPUT_TRAY); 234 if (inputTrayIndex >= 0) { 235 outAttributes.setInputTray(mInputTrays.get(inputTrayIndex)); 236 } 237 238 final int outputTrayIndex = mDefaults.get(PROPERTY_OUTPUT_TRAY); 239 if (outputTrayIndex >= 0) { 240 outAttributes.setOutputTray(mOutputTrays.get(outputTrayIndex)); 241 } 242 243 final int duplexMode = mDefaults.get(PROPERTY_DUPLEX_MODE); 244 if (duplexMode > 0) { 245 outAttributes.setDuplexMode(duplexMode); 246 } 247 248 final int colorMode = mDefaults.get(PROPERTY_COLOR_MODE); 249 if (colorMode > 0) { 250 outAttributes.setColorMode(mColorModes & colorMode); 251 } 252 253 final int fittingMode = mDefaults.get(PROPERTY_FITTING_MODE); 254 if (fittingMode > 0) { 255 outAttributes.setFittingMode(fittingMode); 256 } 257 258 final int orientation = mDefaults.get(PROPERTY_ORIENTATION); 259 if (orientation > 0) { 260 outAttributes.setOrientation(orientation); 261 } 262 } 263 264 private PrinterInfo(Parcel parcel) { 265 mId = parcel.readParcelable(null); 266 mLabel = parcel.readCharSequence(); 267 mStatus = parcel.readInt(); 268 269 mMinMargins = readMargins(parcel); 270 readMediaSizes(parcel); 271 readResolutions(parcel); 272 mInputTrays = readInputTrays(parcel); 273 mOutputTrays = readOutputTrays(parcel); 274 275 mColorModes = parcel.readInt(); 276 mDuplexModes = parcel.readInt(); 277 mFittingModes = parcel.readInt(); 278 mOrientations = parcel.readInt(); 279 280 readDefaults(parcel); 281 mDefaultMargins = readMargins(parcel); 282 } 283 284 @Override 285 public int describeContents() { 286 return 0; 287 } 288 289 @Override 290 public void writeToParcel(Parcel parcel, int flags) { 291 parcel.writeParcelable(mId, flags); 292 parcel.writeCharSequence(mLabel); 293 parcel.writeInt(mStatus); 294 295 writeMargins(mMinMargins, parcel); 296 writeMediaSizes(parcel); 297 writeResolutions(parcel); 298 writeInputTrays(parcel); 299 writeOutputTrays(parcel); 300 301 parcel.writeInt(mColorModes); 302 parcel.writeInt(mDuplexModes); 303 parcel.writeInt(mFittingModes); 304 parcel.writeInt(mOrientations); 305 306 writeDefaults(parcel); 307 writeMargins(mDefaultMargins, parcel); 308 } 309 310 @Override 311 public String toString() { 312 StringBuilder builder = new StringBuilder(); 313 builder.append("PrinterInfo{"); 314 builder.append(mId).append(", \""); 315 builder.append(mLabel); 316 builder.append("\"}"); 317 return builder.toString(); 318 } 319 320 private void writeMediaSizes(Parcel parcel) { 321 if (mMediaSizes == null) { 322 parcel.writeInt(0); 323 return; 324 } 325 final int mediaSizeCount = mMediaSizes.size(); 326 parcel.writeInt(mediaSizeCount); 327 for (int i = 0; i < mediaSizeCount; i++) { 328 mMediaSizes.get(i).writeToParcel(parcel); 329 } 330 } 331 332 private void readMediaSizes(Parcel parcel) { 333 final int mediaSizeCount = parcel.readInt(); 334 for (int i = 0; i < mediaSizeCount; i++) { 335 mMediaSizes.add(MediaSize.createFromParcel(parcel)); 336 } 337 } 338 339 private void writeResolutions(Parcel parcel) { 340 final int resolutionCount = mResolutions.size(); 341 parcel.writeInt(resolutionCount); 342 for (int i = 0; i < resolutionCount; i++) { 343 mResolutions.get(i).writeToParcel(parcel); 344 } 345 } 346 347 private void readResolutions(Parcel parcel) { 348 final int resolutionCount = parcel.readInt(); 349 for (int i = 0; i < resolutionCount; i++) { 350 mResolutions.add(Resolution.createFromParcel(parcel)); 351 } 352 } 353 354 private void writeMargins(Margins margins, Parcel parcel) { 355 if (margins == null) { 356 parcel.writeInt(0); 357 } else { 358 parcel.writeInt(1); 359 margins.writeToParcel(parcel); 360 } 361 } 362 363 private Margins readMargins(Parcel parcel) { 364 return (parcel.readInt() == 1) ? Margins.createFromParcel(parcel) : null; 365 } 366 367 private void writeInputTrays(Parcel parcel) { 368 if (mInputTrays == null) { 369 parcel.writeInt(0); 370 return; 371 } 372 final int inputTrayCount = mInputTrays.size(); 373 parcel.writeInt(inputTrayCount); 374 for (int i = 0; i < inputTrayCount; i++) { 375 mInputTrays.get(i).writeToParcel(parcel); 376 } 377 } 378 379 private List<Tray> readInputTrays(Parcel parcel) { 380 final int inputTrayCount = parcel.readInt(); 381 if (inputTrayCount <= 0) { 382 return null; 383 } 384 List<Tray> inputTrays = new ArrayList<Tray>(inputTrayCount); 385 for (int i = 0; i < inputTrayCount; i++) { 386 inputTrays.add(Tray.createFromParcel(parcel)); 387 } 388 return inputTrays; 389 } 390 391 private void writeOutputTrays(Parcel parcel) { 392 if (mOutputTrays == null) { 393 parcel.writeInt(0); 394 return; 395 } 396 final int outputTrayCount = mOutputTrays.size(); 397 parcel.writeInt(outputTrayCount); 398 for (int i = 0; i < outputTrayCount; i++) { 399 mOutputTrays.get(i).writeToParcel(parcel); 400 } 401 } 402 403 private List<Tray> readOutputTrays(Parcel parcel) { 404 final int outputTrayCount = parcel.readInt(); 405 if (outputTrayCount <= 0) { 406 return null; 407 } 408 List<Tray> outputTrays = new ArrayList<Tray>(outputTrayCount); 409 for (int i = 0; i < outputTrayCount; i++) { 410 outputTrays.add(Tray.createFromParcel(parcel)); 411 } 412 return outputTrays; 413 } 414 415 private void readDefaults(Parcel parcel) { 416 final int defaultCount = parcel.readInt(); 417 for (int i = 0; i < defaultCount; i++) { 418 mDefaults.append(mDefaults.size(), parcel.readInt()); 419 } 420 } 421 422 private void writeDefaults(Parcel parcel) { 423 final int defaultCount = mDefaults.size(); 424 parcel.writeInt(defaultCount); 425 for (int i = 0; i < defaultCount; i++) { 426 parcel.writeInt(mDefaults.valueAt(i)); 427 } 428 } 429 430 /** 431 * Builder for creating of a {@link PrinterInfo}. This class is responsible 432 * to enforce that all required attributes have at least one default value. 433 * In other words, this class creates only well-formed {@link PrinterInfo}s. 434 * <p> 435 * Look at the individual methods for a reference whether a property is 436 * required or if it is optional. 437 * </p> 438 */ 439 public static final class Builder { 440 private final PrinterInfo mPrinterInfo; 441 442 /** 443 * Creates a new instance. 444 * 445 * @param printerId The printer id. 446 * @param label The human readable printer label. 447 * 448 * @throws IllegalArgumentException IF the printer id is null. 449 * @throws IllegalArgumentException IF the label is empty. 450 */ 451 public Builder(PrinterId printerId, CharSequence label) { 452 if (printerId == null) { 453 throw new IllegalArgumentException("printerId cannot be null."); 454 } 455 if (TextUtils.isEmpty(label)) { 456 throw new IllegalArgumentException("label cannot be empty."); 457 } 458 mPrinterInfo = new PrinterInfo(); 459 mPrinterInfo.mLabel = label; 460 mPrinterInfo.mId = printerId; 461 } 462 463 /** 464 * Sets the printer status. 465 * <p> 466 * <strong>Required:</strong> Yes 467 * </p> 468 * 469 * @param status The status. 470 * @return This builder. 471 */ 472 public Builder setStatus(int status) { 473 mPrinterInfo.mStatus = status; 474 return this; 475 } 476 477 /** 478 * Adds a supported media size. 479 * <p> 480 * <strong>Required:</strong> Yes 481 * </p> 482 * 483 * @param mediaSize A media size. 484 * @param isDefault Whether this is the default. 485 * @return This builder. 486 * @throws IllegalArgumentException If set as default and there 487 * is already a default. 488 * 489 * @see PrintAttributes.MediaSize 490 */ 491 public Builder addMediaSize(MediaSize mediaSize, boolean isDefault) { 492 final int insertionIndex = mPrinterInfo.mMediaSizes.size(); 493 mPrinterInfo.mMediaSizes.add(mediaSize); 494 if (isDefault) { 495 throwIfDefaultAlreadySpecified(PROPERTY_MEDIA_SIZE); 496 mPrinterInfo.mDefaults.put(PROPERTY_MEDIA_SIZE, insertionIndex); 497 } 498 return this; 499 } 500 501 /** 502 * Adds a supported resolution. 503 * <p> 504 * <strong>Required:</strong> Yes 505 * </p> 506 * 507 * @param resolution A resolution. 508 * @param isDefault Whether this is the default. 509 * @return This builder. 510 * 511 * @throws IllegalArgumentException If set as default and there 512 * is already a default. 513 * 514 * @see PrintAttributes.Resolution 515 */ 516 public Builder addResolution(Resolution resolution, boolean isDefault) { 517 final int insertionIndex = mPrinterInfo.mResolutions.size(); 518 mPrinterInfo.mResolutions.add(resolution); 519 if (isDefault) { 520 throwIfDefaultAlreadySpecified(PROPERTY_RESOLUTION); 521 mPrinterInfo.mDefaults.put(PROPERTY_RESOLUTION, insertionIndex); 522 } 523 return this; 524 } 525 526 /** 527 * Sets the minimal margins. 528 * <p> 529 * <strong>Required:</strong> No 530 * </p> 531 * 532 * @param margins The margins. 533 * @param defaultMargins The default margins. 534 * @return This builder. 535 * 536 * @see PrintAttributes.Margins 537 */ 538 public Builder setMinMargins(Margins margins, Margins defaultMargins) { 539 if (margins.getLeftMils() > defaultMargins.getLeftMils() 540 || margins.getTopMils() > defaultMargins.getTopMils() 541 || margins.getRightMils() < defaultMargins.getRightMils() 542 || margins.getBottomMils() < defaultMargins.getBottomMils()) { 543 throw new IllegalArgumentException("Default margins" 544 + " cannot be outside of the min margins."); 545 } 546 mPrinterInfo.mMinMargins = margins; 547 mPrinterInfo.mDefaultMargins = defaultMargins; 548 return this; 549 } 550 551 /** 552 * Adds an input tray. 553 * <p> 554 * <strong>Required:</strong> No 555 * </p> 556 * 557 * @param inputTray A tray. 558 * @param isDefault Whether this is the default. 559 * @return This builder. 560 * 561 * @throws IllegalArgumentException If set as default and there 562 * is already a default. 563 * 564 * @see PrintAttributes.Tray 565 */ 566 public Builder addInputTray(Tray inputTray, boolean isDefault) { 567 if (mPrinterInfo.mInputTrays == null) { 568 mPrinterInfo.mInputTrays = new ArrayList<Tray>(); 569 } 570 final int insertionIndex = mPrinterInfo.mInputTrays.size(); 571 mPrinterInfo.mInputTrays.add(inputTray); 572 if (isDefault) { 573 throwIfDefaultAlreadySpecified(PROPERTY_INPUT_TRAY); 574 mPrinterInfo.mDefaults.put(PROPERTY_INPUT_TRAY, insertionIndex); 575 } 576 return this; 577 } 578 579 /** 580 * Adds an output tray. 581 * <p> 582 * <strong>Required:</strong> No 583 * </p> 584 * 585 * @param outputTray A tray. 586 * @param isDefault Whether this is the default. 587 * @return This builder. 588 * 589 * @throws IllegalArgumentException If set as default and there 590 * is already a default. 591 * 592 * @see PrintAttributes.Tray 593 */ 594 public Builder addOutputTray(Tray outputTray, boolean isDefault) { 595 if (mPrinterInfo.mOutputTrays == null) { 596 mPrinterInfo.mOutputTrays = new ArrayList<Tray>(); 597 } 598 final int insertionIndex = mPrinterInfo.mOutputTrays.size(); 599 mPrinterInfo.mOutputTrays.add(outputTray); 600 if (isDefault) { 601 throwIfDefaultAlreadySpecified(PROPERTY_OUTPUT_TRAY); 602 mPrinterInfo.mDefaults.put(PROPERTY_OUTPUT_TRAY, insertionIndex); 603 } 604 return this; 605 } 606 607 /** 608 * Sets the color modes. 609 * <p> 610 * <strong>Required:</strong> Yes 611 * </p> 612 * 613 * @param colorModes The color mode bit mask. 614 * @param defaultColorMode The default color mode. 615 * @return This builder. 616 * 617 * @throws IllegalArgumentException If color modes contains an invalid 618 * mode bit or if the default color mode is invalid. 619 * 620 * @see PrintAttributes#COLOR_MODE_COLOR 621 * @see PrintAttributes#COLOR_MODE_MONOCHROME 622 */ 623 public Builder setColorModes(int colorModes, int defaultColorMode) { 624 int currentModes = colorModes; 625 while (currentModes > 0) { 626 final int currentMode = (1 << Integer.numberOfTrailingZeros(currentModes)); 627 currentModes &= ~currentMode; 628 PrintAttributes.enforceValidColorMode(currentMode); 629 } 630 if ((colorModes & defaultColorMode) == 0) { 631 throw new IllegalArgumentException("Default color mode not in color modes."); 632 } 633 PrintAttributes.enforceValidColorMode(colorModes); 634 mPrinterInfo.mColorModes = colorModes; 635 mPrinterInfo.mDefaults.put(PROPERTY_COLOR_MODE, defaultColorMode); 636 return this; 637 } 638 639 /** 640 * Set the duplex modes. 641 * <p> 642 * <strong>Required:</strong> No 643 * </p> 644 * 645 * @param duplexModes The duplex mode bit mask. 646 * @param defaultDuplexMode The default duplex mode. 647 * @return This builder. 648 * 649 * @throws IllegalArgumentException If duplex modes contains an invalid 650 * mode bit or if the default duplex mode is invalid. 651 * 652 * @see PrintAttributes#DUPLEX_MODE_NONE 653 * @see PrintAttributes#DUPLEX_MODE_LONG_EDGE 654 * @see PrintAttributes#DUPLEX_MODE_SHORT_EDGE 655 */ 656 public Builder setDuplexModes(int duplexModes, int defaultDuplexMode) { 657 int currentModes = duplexModes; 658 while (currentModes > 0) { 659 final int currentMode = (1 << Integer.numberOfTrailingZeros(currentModes)); 660 currentModes &= ~currentMode; 661 PrintAttributes.enforceValidDuplexMode(currentMode); 662 } 663 if ((duplexModes & defaultDuplexMode) == 0) { 664 throw new IllegalArgumentException("Default duplex mode not in duplex modes."); 665 } 666 PrintAttributes.enforceValidDuplexMode(defaultDuplexMode); 667 mPrinterInfo.mDuplexModes = duplexModes; 668 mPrinterInfo.mDefaults.put(PROPERTY_DUPLEX_MODE, defaultDuplexMode); 669 return this; 670 } 671 672 /** 673 * Sets the fitting modes. 674 * <p> 675 * <strong>Required:</strong> No 676 * </p> 677 * 678 * @param fittingModes The fitting mode bit mask. 679 * @param defaultFittingMode The default fitting mode. 680 * @return This builder. 681 * 682 * @throws IllegalArgumentException If fitting modes contains an invalid 683 * mode bit or if the default fitting mode is invalid. 684 * 685 * @see PrintAttributes#FITTING_MODE_NONE 686 * @see PrintAttributes#FITTING_MODE_FIT_TO_PAGE 687 */ 688 public Builder setFittingModes(int fittingModes, int defaultFittingMode) { 689 int currentModes = fittingModes; 690 while (currentModes > 0) { 691 final int currentMode = (1 << Integer.numberOfTrailingZeros(currentModes)); 692 currentModes &= ~currentMode; 693 PrintAttributes.enfoceValidFittingMode(currentMode); 694 } 695 if ((fittingModes & defaultFittingMode) == 0) { 696 throw new IllegalArgumentException("Default fitting mode not in fiting modes."); 697 } 698 PrintAttributes.enfoceValidFittingMode(defaultFittingMode); 699 mPrinterInfo.mFittingModes = fittingModes; 700 mPrinterInfo.mDefaults.put(PROPERTY_FITTING_MODE, defaultFittingMode); 701 return this; 702 } 703 704 /** 705 * Sets the orientations. 706 * <p> 707 * <strong>Required:</strong> Yes 708 * </p> 709 * 710 * @param orientations The orientation bit mask. 711 * @param defaultOrientation The default orientation. 712 * @return This builder. 713 * 714 * @throws IllegalArgumentException If orientations contains an invalid 715 * mode bit or if the default orientation is invalid. 716 * 717 * @see PrintAttributes#ORIENTATION_PORTRAIT 718 * @see PrintAttributes#ORIENTATION_LANDSCAPE 719 */ 720 public Builder setOrientations(int orientations, int defaultOrientation) { 721 int currentOrientaions = orientations; 722 while (currentOrientaions > 0) { 723 final int currentOrnt = (1 << Integer.numberOfTrailingZeros(currentOrientaions)); 724 currentOrientaions &= ~currentOrnt; 725 PrintAttributes.enforceValidOrientation(currentOrnt); 726 } 727 if ((orientations & defaultOrientation) == 0) { 728 throw new IllegalArgumentException("Default orientation not in orientations."); 729 } 730 PrintAttributes.enforceValidOrientation(defaultOrientation); 731 mPrinterInfo.mOrientations = orientations; 732 mPrinterInfo.mDefaults.put(PROPERTY_ORIENTATION, defaultOrientation); 733 return this; 734 } 735 736 /** 737 * Crates a new {@link PrinterInfo} enforcing that all required properties 738 * have need specified. See individual methods in this class for reference 739 * about required attributes. 740 * 741 * @return A new {@link PrinterInfo}. 742 * 743 * @throws IllegalStateException If a required attribute was not specified. 744 */ 745 public PrinterInfo create() { 746 if (mPrinterInfo.mMediaSizes == null || mPrinterInfo.mMediaSizes.isEmpty()) { 747 throw new IllegalStateException("No media size specified."); 748 } 749 if (mPrinterInfo.mDefaults.valueAt(PROPERTY_MEDIA_SIZE) == DEFAULT_UNDEFINED) { 750 throw new IllegalStateException("No default media size specified."); 751 } 752 if (mPrinterInfo.mResolutions == null || mPrinterInfo.mResolutions.isEmpty()) { 753 throw new IllegalStateException("No resolution specified."); 754 } 755 if (mPrinterInfo.mDefaults.valueAt(PROPERTY_RESOLUTION) == DEFAULT_UNDEFINED) { 756 throw new IllegalStateException("No default resolution specified."); 757 } 758 if (mPrinterInfo.mColorModes == 0) { 759 throw new IllegalStateException("No color mode specified."); 760 } 761 if (mPrinterInfo.mDefaults.valueAt(PROPERTY_COLOR_MODE) == DEFAULT_UNDEFINED) { 762 throw new IllegalStateException("No default color mode specified."); 763 } 764 if (mPrinterInfo.mOrientations == 0) { 765 throw new IllegalStateException("No oprientation specified."); 766 } 767 if (mPrinterInfo.mDefaults.valueAt(PROPERTY_ORIENTATION) == DEFAULT_UNDEFINED) { 768 throw new IllegalStateException("No default orientation specified."); 769 } 770 if (mPrinterInfo.mMinMargins == null) { 771 mPrinterInfo.mMinMargins = new Margins(0, 0, 0, 0); 772 } 773 if (mPrinterInfo.mDefaultMargins == null) { 774 mPrinterInfo.mDefaultMargins = mPrinterInfo.mMinMargins; 775 } 776 return mPrinterInfo; 777 } 778 779 private void throwIfDefaultAlreadySpecified(int propertyIndex) { 780 if (mPrinterInfo.mDefaults.get(propertyIndex) != DEFAULT_UNDEFINED) { 781 throw new IllegalArgumentException("Default already specified."); 782 } 783 } 784 } 785 786 public static final Parcelable.Creator<PrinterInfo> CREATOR = 787 new Parcelable.Creator<PrinterInfo>() { 788 @Override 789 public PrinterInfo createFromParcel(Parcel parcel) { 790 return new PrinterInfo(parcel); 791 } 792 793 @Override 794 public PrinterInfo[] newArray(int size) { 795 return new PrinterInfo[size]; 796 } 797 }; 798} 799