PrinterCapabilitiesInfo.java revision 773f54de3de9bce7b6f915aa47ed686b161d77aa
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; 24 25import java.util.ArrayList; 26import java.util.Arrays; 27import java.util.List; 28 29/** 30 * This class represents the capabilities of a printer. 31 */ 32public final class PrinterCapabilitiesInfo implements Parcelable { 33 /** 34 * Undefined default value. 35 * 36 * @hide 37 */ 38 public static final int DEFAULT_UNDEFINED = -1; 39 40 private static final int PROPERTY_MEDIA_SIZE = 0; 41 private static final int PROPERTY_RESOLUTION = 1; 42 private static final int PROPERTY_COLOR_MODE = 2; 43 private static final int PROPERTY_COUNT = 3; 44 45 private static final Margins DEFAULT_MARGINS = new Margins(0, 0, 0, 0); 46 47 private Margins mMinMargins = DEFAULT_MARGINS; 48 private List<MediaSize> mMediaSizes; 49 private List<Resolution> mResolutions; 50 51 private int mColorModes; 52 53 private final int[] mDefaults = new int[PROPERTY_COUNT]; 54 private Margins mDefaultMargins = DEFAULT_MARGINS; 55 56 /** 57 * @hide 58 */ 59 public PrinterCapabilitiesInfo() { 60 Arrays.fill(mDefaults, DEFAULT_UNDEFINED); 61 } 62 63 /** 64 * @hide 65 */ 66 public PrinterCapabilitiesInfo(PrinterCapabilitiesInfo prototype) { 67 copyFrom(prototype); 68 } 69 70 /** 71 * @hide 72 */ 73 public void copyFrom(PrinterCapabilitiesInfo other) { 74 mMinMargins = other.mMinMargins; 75 76 if (other.mMediaSizes != null) { 77 if (mMediaSizes != null) { 78 mMediaSizes.clear(); 79 mMediaSizes.addAll(other.mMediaSizes); 80 } else { 81 mMediaSizes = new ArrayList<MediaSize>(other.mMediaSizes); 82 } 83 } else { 84 mMediaSizes = null; 85 } 86 87 if (other.mResolutions != null) { 88 if (mResolutions != null) { 89 mResolutions.clear(); 90 mResolutions.addAll(other.mResolutions); 91 } else { 92 mResolutions = new ArrayList<Resolution>(other.mResolutions); 93 } 94 } else { 95 mResolutions = null; 96 } 97 98 mColorModes = other.mColorModes; 99 100 final int defaultCount = other.mDefaults.length; 101 for (int i = 0; i < defaultCount; i++) { 102 mDefaults[i] = other.mDefaults[i]; 103 } 104 105 mDefaultMargins = other.mDefaultMargins; 106 } 107 108 /** 109 * Gets the supported media sizes. 110 * 111 * @return The media sizes. 112 */ 113 public List<MediaSize> getMediaSizes() { 114 return mMediaSizes; 115 } 116 117 /** 118 * Gets the supported resolutions. 119 * 120 * @return The resolutions. 121 */ 122 public List<Resolution> getResolutions() { 123 return mResolutions; 124 } 125 126 /** 127 * Gets the minimal supported margins. 128 * 129 * @return The minimal margins. 130 */ 131 public Margins getMinMargins() { 132 return mMinMargins; 133 } 134 135 /** 136 * Gets the supported color modes. 137 * 138 * @return The color modes. 139 * 140 * @see PrintAttributes#COLOR_MODE_COLOR 141 * @see PrintAttributes#COLOR_MODE_MONOCHROME 142 */ 143 public int getColorModes() { 144 return mColorModes; 145 } 146 147 /** 148 * Gets the default print attributes. 149 * 150 * @param outAttributes The attributes to populated. 151 */ 152 public void getDefaults(PrintAttributes outAttributes) { 153 outAttributes.clear(); 154 155 outAttributes.setMargins(mDefaultMargins); 156 157 final int mediaSizeIndex = mDefaults[PROPERTY_MEDIA_SIZE]; 158 if (mediaSizeIndex >= 0) { 159 outAttributes.setMediaSize(mMediaSizes.get(mediaSizeIndex)); 160 } 161 162 final int resolutionIndex = mDefaults[PROPERTY_RESOLUTION]; 163 if (resolutionIndex >= 0) { 164 outAttributes.setResolution(mResolutions.get(resolutionIndex)); 165 } 166 167 final int colorMode = mDefaults[PROPERTY_COLOR_MODE]; 168 if (colorMode > 0) { 169 outAttributes.setColorMode(colorMode); 170 } 171 } 172 173 private PrinterCapabilitiesInfo(Parcel parcel) { 174 mMinMargins = readMargins(parcel); 175 readMediaSizes(parcel); 176 readResolutions(parcel); 177 178 mColorModes = parcel.readInt(); 179 180 readDefaults(parcel); 181 mDefaultMargins = readMargins(parcel); 182 } 183 184 @Override 185 public int describeContents() { 186 return 0; 187 } 188 189 @Override 190 public void writeToParcel(Parcel parcel, int flags) { 191 writeMargins(mMinMargins, parcel); 192 writeMediaSizes(parcel); 193 writeResolutions(parcel); 194 195 parcel.writeInt(mColorModes); 196 197 writeDefaults(parcel); 198 writeMargins(mDefaultMargins, parcel); 199 } 200 201 @Override 202 public int hashCode() { 203 final int prime = 31; 204 int result = 1; 205 result = prime * result + ((mMinMargins == null) ? 0 : mMinMargins.hashCode()); 206 result = prime * result + ((mMediaSizes == null) ? 0 : mMediaSizes.hashCode()); 207 result = prime * result + ((mResolutions == null) ? 0 : mResolutions.hashCode()); 208 result = prime * result + mColorModes; 209 result = prime * result + Arrays.hashCode(mDefaults); 210 result = prime * result + ((mDefaultMargins == null) ? 0 : mDefaultMargins.hashCode()); 211 return result; 212 } 213 214 @Override 215 public boolean equals(Object obj) { 216 if (this == obj) { 217 return true; 218 } 219 if (obj == null) { 220 return false; 221 } 222 if (getClass() != obj.getClass()) { 223 return false; 224 } 225 PrinterCapabilitiesInfo other = (PrinterCapabilitiesInfo) obj; 226 if (mMinMargins == null) { 227 if (other.mMinMargins != null) { 228 return false; 229 } 230 } else if (!mMinMargins.equals(other.mMinMargins)) { 231 return false; 232 } 233 if (mMediaSizes == null) { 234 if (other.mMediaSizes != null) { 235 return false; 236 } 237 } else if (!mMediaSizes.equals(other.mMediaSizes)) { 238 return false; 239 } 240 if (mResolutions == null) { 241 if (other.mResolutions != null) { 242 return false; 243 } 244 } else if (!mResolutions.equals(other.mResolutions)) { 245 return false; 246 } 247 if (mColorModes != other.mColorModes) { 248 return false; 249 } 250 if (!Arrays.equals(mDefaults, other.mDefaults)) { 251 return false; 252 } 253 if (mDefaultMargins == null) { 254 if (other.mDefaultMargins != null) { 255 return false; 256 } 257 } else if (!mDefaultMargins.equals(other.mDefaultMargins)) { 258 return false; 259 } 260 return true; 261 } 262 263 @Override 264 public String toString() { 265 StringBuilder builder = new StringBuilder(); 266 builder.append("PrinterInfo{"); 267 builder.append("minMargins=").append(mMinMargins); 268 builder.append(", mediaSizes=").append(mMediaSizes); 269 builder.append(", resolutions=").append(mResolutions); 270 builder.append(", colorModes=").append(colorModesToString()); 271 builder.append("\"}"); 272 return builder.toString(); 273 } 274 275 private String colorModesToString() { 276 StringBuilder builder = new StringBuilder(); 277 builder.append('['); 278 int colorModes = mColorModes; 279 while (colorModes != 0) { 280 final int colorMode = 1 << Integer.numberOfTrailingZeros(colorModes); 281 colorModes &= ~colorMode; 282 if (builder.length() > 0) { 283 builder.append(", "); 284 } 285 builder.append(PrintAttributes.colorModeToString(colorMode)); 286 } 287 builder.append(']'); 288 return builder.toString(); 289 } 290 291 private void writeMediaSizes(Parcel parcel) { 292 if (mMediaSizes == null) { 293 parcel.writeInt(0); 294 return; 295 } 296 final int mediaSizeCount = mMediaSizes.size(); 297 parcel.writeInt(mediaSizeCount); 298 for (int i = 0; i < mediaSizeCount; i++) { 299 mMediaSizes.get(i).writeToParcel(parcel); 300 } 301 } 302 303 private void readMediaSizes(Parcel parcel) { 304 final int mediaSizeCount = parcel.readInt(); 305 if (mediaSizeCount > 0 && mMediaSizes == null) { 306 mMediaSizes = new ArrayList<MediaSize>(); 307 } 308 for (int i = 0; i < mediaSizeCount; i++) { 309 mMediaSizes.add(MediaSize.createFromParcel(parcel)); 310 } 311 } 312 313 private void writeResolutions(Parcel parcel) { 314 if (mResolutions == null) { 315 parcel.writeInt(0); 316 return; 317 } 318 final int resolutionCount = mResolutions.size(); 319 parcel.writeInt(resolutionCount); 320 for (int i = 0; i < resolutionCount; i++) { 321 mResolutions.get(i).writeToParcel(parcel); 322 } 323 } 324 325 private void readResolutions(Parcel parcel) { 326 final int resolutionCount = parcel.readInt(); 327 if (resolutionCount > 0 && mResolutions == null) { 328 mResolutions = new ArrayList<Resolution>(); 329 } 330 for (int i = 0; i < resolutionCount; i++) { 331 mResolutions.add(Resolution.createFromParcel(parcel)); 332 } 333 } 334 335 private void writeMargins(Margins margins, Parcel parcel) { 336 if (margins == null) { 337 parcel.writeInt(0); 338 } else { 339 parcel.writeInt(1); 340 margins.writeToParcel(parcel); 341 } 342 } 343 344 private Margins readMargins(Parcel parcel) { 345 return (parcel.readInt() == 1) ? Margins.createFromParcel(parcel) : null; 346 } 347 348 private void readDefaults(Parcel parcel) { 349 final int defaultCount = parcel.readInt(); 350 for (int i = 0; i < defaultCount; i++) { 351 mDefaults[i] = parcel.readInt(); 352 } 353 } 354 355 private void writeDefaults(Parcel parcel) { 356 final int defaultCount = mDefaults.length; 357 parcel.writeInt(defaultCount); 358 for (int i = 0; i < defaultCount; i++) { 359 parcel.writeInt(mDefaults[i]); 360 } 361 } 362 363 /** 364 * Builder for creating of a {@link PrinterInfo}. This class is responsible 365 * to enforce that all required attributes have at least one default value. 366 * In other words, this class creates only well-formed {@link PrinterInfo}s. 367 * <p> 368 * Look at the individual methods for a reference whether a property is 369 * required or if it is optional. 370 * </p> 371 */ 372 public static final class Builder { 373 private final PrinterCapabilitiesInfo mPrototype; 374 375 /** 376 * Creates a new instance. 377 * 378 * @param printerId The printer id. Cannot be null. 379 * 380 * @throws IllegalArgumentException If the printer id is null. 381 */ 382 public Builder(PrinterId printerId) { 383 if (printerId == null) { 384 throw new IllegalArgumentException("printerId cannot be null."); 385 } 386 mPrototype = new PrinterCapabilitiesInfo(); 387 } 388 389 /** 390 * Adds a supported media size. 391 * <p> 392 * <strong>Required:</strong> Yes 393 * </p> 394 * 395 * @param mediaSize A media size. 396 * @param isDefault Whether this is the default. 397 * @return This builder. 398 * @throws IllegalArgumentException If set as default and there 399 * is already a default. 400 * 401 * @see PrintAttributes.MediaSize 402 */ 403 public Builder addMediaSize(MediaSize mediaSize, boolean isDefault) { 404 if (mPrototype.mMediaSizes == null) { 405 mPrototype.mMediaSizes = new ArrayList<MediaSize>(); 406 } 407 final int insertionIndex = mPrototype.mMediaSizes.size(); 408 mPrototype.mMediaSizes.add(mediaSize); 409 if (isDefault) { 410 throwIfDefaultAlreadySpecified(PROPERTY_MEDIA_SIZE); 411 mPrototype.mDefaults[PROPERTY_MEDIA_SIZE] = insertionIndex; 412 } 413 return this; 414 } 415 416 /** 417 * Adds a supported resolution. 418 * <p> 419 * <strong>Required:</strong> Yes 420 * </p> 421 * 422 * @param resolution A resolution. 423 * @param isDefault Whether this is the default. 424 * @return This builder. 425 * 426 * @throws IllegalArgumentException If set as default and there 427 * is already a default. 428 * 429 * @see PrintAttributes.Resolution 430 */ 431 public Builder addResolution(Resolution resolution, boolean isDefault) { 432 if (mPrototype.mResolutions == null) { 433 mPrototype.mResolutions = new ArrayList<Resolution>(); 434 } 435 final int insertionIndex = mPrototype.mResolutions.size(); 436 mPrototype.mResolutions.add(resolution); 437 if (isDefault) { 438 throwIfDefaultAlreadySpecified(PROPERTY_RESOLUTION); 439 mPrototype.mDefaults[PROPERTY_RESOLUTION] = insertionIndex; 440 } 441 return this; 442 } 443 444 /** 445 * Sets the minimal margins. 446 * <p> 447 * <strong>Required:</strong> No 448 * </p> 449 * 450 * @param margins The margins. 451 * @param defaultMargins The default margins. 452 * @return This builder. 453 * 454 * @see PrintAttributes.Margins 455 */ 456 public Builder setMinMargins(Margins margins, Margins defaultMargins) { 457 if (margins.getLeftMils() > defaultMargins.getLeftMils() 458 || margins.getTopMils() > defaultMargins.getTopMils() 459 || margins.getRightMils() < defaultMargins.getRightMils() 460 || margins.getBottomMils() < defaultMargins.getBottomMils()) { 461 throw new IllegalArgumentException("Default margins" 462 + " cannot be outside of the min margins."); 463 } 464 mPrototype.mMinMargins = margins; 465 mPrototype.mDefaultMargins = defaultMargins; 466 return this; 467 } 468 469 /** 470 * Sets the color modes. 471 * <p> 472 * <strong>Required:</strong> Yes 473 * </p> 474 * 475 * @param colorModes The color mode bit mask. 476 * @param defaultColorMode The default color mode. 477 * @return This builder. 478 * 479 * @throws IllegalArgumentException If color modes contains an invalid 480 * mode bit or if the default color mode is invalid. 481 * 482 * @see PrintAttributes#COLOR_MODE_COLOR 483 * @see PrintAttributes#COLOR_MODE_MONOCHROME 484 */ 485 public Builder setColorModes(int colorModes, int defaultColorMode) { 486 int currentModes = colorModes; 487 while (currentModes > 0) { 488 final int currentMode = (1 << Integer.numberOfTrailingZeros(currentModes)); 489 currentModes &= ~currentMode; 490 PrintAttributes.enforceValidColorMode(currentMode); 491 } 492 if ((colorModes & defaultColorMode) == 0) { 493 throw new IllegalArgumentException("Default color mode not in color modes."); 494 } 495 PrintAttributes.enforceValidColorMode(colorModes); 496 mPrototype.mColorModes = colorModes; 497 mPrototype.mDefaults[PROPERTY_COLOR_MODE] = defaultColorMode; 498 return this; 499 } 500 501 /** 502 * Crates a new {@link PrinterCapabilitiesInfo} enforcing that all 503 * required properties have need specified. See individual methods 504 * in this class for reference about required attributes. 505 * 506 * @return A new {@link PrinterCapabilitiesInfo}. 507 * 508 * @throws IllegalStateException If a required attribute was not specified. 509 */ 510 public PrinterCapabilitiesInfo create() { 511 if (mPrototype.mMediaSizes == null || mPrototype.mMediaSizes.isEmpty()) { 512 throw new IllegalStateException("No media size specified."); 513 } 514 if (mPrototype.mDefaults[PROPERTY_MEDIA_SIZE] == DEFAULT_UNDEFINED) { 515 throw new IllegalStateException("No default media size specified."); 516 } 517 if (mPrototype.mResolutions == null || mPrototype.mResolutions.isEmpty()) { 518 throw new IllegalStateException("No resolution specified."); 519 } 520 if (mPrototype.mDefaults[PROPERTY_RESOLUTION] == DEFAULT_UNDEFINED) { 521 throw new IllegalStateException("No default resolution specified."); 522 } 523 if (mPrototype.mColorModes == 0) { 524 throw new IllegalStateException("No color mode specified."); 525 } 526 if (mPrototype.mDefaults[PROPERTY_COLOR_MODE] == DEFAULT_UNDEFINED) { 527 throw new IllegalStateException("No default color mode specified."); 528 } 529 if (mPrototype.mMinMargins == null) { 530 mPrototype.mMinMargins = new Margins(0, 0, 0, 0); 531 } 532 if (mPrototype.mDefaultMargins == null) { 533 mPrototype.mDefaultMargins = mPrototype.mMinMargins; 534 } 535 return new PrinterCapabilitiesInfo(mPrototype); 536 } 537 538 private void throwIfDefaultAlreadySpecified(int propertyIndex) { 539 if (mPrototype.mDefaults[propertyIndex] != DEFAULT_UNDEFINED) { 540 throw new IllegalArgumentException("Default already specified."); 541 } 542 } 543 } 544 545 public static final Parcelable.Creator<PrinterCapabilitiesInfo> CREATOR = 546 new Parcelable.Creator<PrinterCapabilitiesInfo>() { 547 @Override 548 public PrinterCapabilitiesInfo createFromParcel(Parcel parcel) { 549 return new PrinterCapabilitiesInfo(parcel); 550 } 551 552 @Override 553 public PrinterCapabilitiesInfo[] newArray(int size) { 554 return new PrinterCapabilitiesInfo[size]; 555 } 556 }; 557} 558 559