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 17 package android.print; 18 19 import android.annotation.IntDef; 20 import android.annotation.IntRange; 21 import android.annotation.NonNull; 22 import android.os.Parcel; 23 import android.os.Parcelable; 24 import android.text.TextUtils; 25 import com.android.internal.util.Preconditions; 26 27 import java.lang.annotation.Retention; 28 import java.lang.annotation.RetentionPolicy; 29 30 /** 31 * This class encapsulates information about a document for printing 32 * purposes. This meta-data is used by the platform and print services, 33 * components that interact with printers. For example, this class 34 * contains the number of pages contained in the document it describes and 35 * this number of pages is shown to the user allowing him/her to select 36 * the range to print. Also a print service may optimize the printing 37 * process based on the content type, such as document or photo. 38 * <p> 39 * Instances of this class are created by the printing application and 40 * passed to the {@link PrintDocumentAdapter.LayoutResultCallback#onLayoutFinished( 41 * PrintDocumentInfo, boolean) PrintDocumentAdapter.LayoutResultCallback.onLayoutFinished( 42 * PrintDocumentInfo, boolean)} callback after successfully laying out the 43 * content which is performed in {@link PrintDocumentAdapter#onLayout(PrintAttributes, 44 * PrintAttributes, android.os.CancellationSignal, PrintDocumentAdapter.LayoutResultCallback, 45 * android.os.Bundle) PrintDocumentAdapter.onLayout(PrintAttributes, 46 * PrintAttributes, android.os.CancellationSignal, 47 * PrintDocumentAdapter.LayoutResultCallback, android.os.Bundle)}. 48 * </p> 49 * <p> 50 * An example usage looks like this: 51 * <pre> 52 * 53 * . . . 54 * 55 * public void onLayout(PrintAttributes oldAttributes, PrintAttributes newAttributes, 56 * CancellationSignal cancellationSignal, LayoutResultCallback callback, 57 * Bundle metadata) { 58 * 59 * // Assume the app defined a LayoutResult class which contains 60 * // the layout result data and that the content is a document. 61 * LayoutResult result = doSomeLayoutWork(); 62 * 63 * PrintDocumentInfo info = new PrintDocumentInfo 64 * .Builder("printed_file.pdf") 65 * .setContentType(PrintDocumentInfo.CONTENT_TYPE_DOCUMENT) 66 * .setPageCount(result.getPageCount()) 67 * .build(); 68 * 69 * callback.onLayoutFinished(info, result.getContentChanged()); 70 * } 71 * 72 * . . . 73 * 74 * </pre> 75 * </p> 76 */ 77 public final class PrintDocumentInfo implements Parcelable { 78 79 /** 80 * Constant for unknown page count. 81 */ 82 public static final int PAGE_COUNT_UNKNOWN = -1; 83 84 /** @hide */ 85 @Retention(RetentionPolicy.SOURCE) 86 @IntDef(prefix = { "CONTENT_TYPE_" }, value = { 87 CONTENT_TYPE_UNKNOWN, 88 CONTENT_TYPE_DOCUMENT, 89 CONTENT_TYPE_PHOTO 90 }) 91 public @interface ContentType { 92 } 93 94 /** 95 * Content type: unknown. 96 */ 97 public static final int CONTENT_TYPE_UNKNOWN = -1; 98 99 /** 100 * Content type: document. 101 * <p> 102 * A print service may use normal paper to print the content instead 103 * of dedicated photo paper. Also it may use a lower quality printing 104 * process as the content is not as sensitive to print quality variation 105 * as a photo is. 106 * </p> 107 */ 108 public static final int CONTENT_TYPE_DOCUMENT = 0; 109 110 /** 111 * Content type: photo. 112 * <p> 113 * A print service may use dedicated photo paper to print the content 114 * instead of normal paper. Also it may use a higher quality printing 115 * process as the content is more sensitive to print quality variation 116 * than a document. 117 * </p> 118 */ 119 public static final int CONTENT_TYPE_PHOTO = 1; 120 121 private @NonNull String mName; 122 private @IntRange(from = -1) int mPageCount; 123 private int mContentType; 124 private long mDataSize; 125 126 /** 127 * Creates a new instance. 128 */ PrintDocumentInfo()129 private PrintDocumentInfo() { 130 /* do nothing */ 131 } 132 133 /** 134 * Creates a new instance. 135 * 136 * @param prototype from which to clone. 137 */ PrintDocumentInfo(@onNull PrintDocumentInfo prototype)138 private PrintDocumentInfo(@NonNull PrintDocumentInfo prototype) { 139 mName = prototype.mName; 140 mPageCount = prototype.mPageCount; 141 mContentType = prototype.mContentType; 142 mDataSize = prototype.mDataSize; 143 } 144 145 /** 146 * Creates a new instance. 147 * 148 * @param parcel Data from which to initialize. 149 */ PrintDocumentInfo(Parcel parcel)150 private PrintDocumentInfo(Parcel parcel) { 151 mName = Preconditions.checkStringNotEmpty(parcel.readString()); 152 mPageCount = parcel.readInt(); 153 Preconditions.checkArgument(mPageCount == PAGE_COUNT_UNKNOWN || mPageCount > 0); 154 mContentType = parcel.readInt(); 155 mDataSize = Preconditions.checkArgumentNonnegative(parcel.readLong()); 156 } 157 158 /** 159 * Gets the document name. This name may be shown to 160 * the user. 161 * 162 * @return The document name. 163 */ getName()164 public @NonNull String getName() { 165 return mName; 166 } 167 168 /** 169 * Gets the total number of pages. 170 * 171 * @return The number of pages. 172 * 173 * @see #PAGE_COUNT_UNKNOWN 174 */ getPageCount()175 public @IntRange(from = -1) int getPageCount() { 176 return mPageCount; 177 } 178 179 /** 180 * Gets the content type. 181 * 182 * @return The content type. 183 * 184 * @see #CONTENT_TYPE_UNKNOWN 185 * @see #CONTENT_TYPE_DOCUMENT 186 * @see #CONTENT_TYPE_PHOTO 187 */ getContentType()188 public int getContentType() { 189 return mContentType; 190 } 191 192 /** 193 * Gets the document data size in bytes. 194 * 195 * @return The data size. 196 */ getDataSize()197 public @IntRange(from = 0) long getDataSize() { 198 return mDataSize; 199 } 200 201 /** 202 * Sets the document data size in bytes. 203 * 204 * @param dataSize The data size. 205 * 206 * @hide 207 */ setDataSize(@ntRangefrom = 0) long dataSize)208 public void setDataSize(@IntRange(from = 0) long dataSize) { 209 mDataSize = dataSize; 210 } 211 212 @Override describeContents()213 public int describeContents() { 214 return 0; 215 } 216 217 @Override writeToParcel(Parcel parcel, int flags)218 public void writeToParcel(Parcel parcel, int flags) { 219 parcel.writeString(mName); 220 parcel.writeInt(mPageCount); 221 parcel.writeInt(mContentType); 222 parcel.writeLong(mDataSize); 223 } 224 225 @Override hashCode()226 public int hashCode() { 227 final int prime = 31; 228 int result = 1; 229 result = prime * result + ((mName != null) ? mName.hashCode() : 0); 230 result = prime * result + mContentType; 231 result = prime * result + mPageCount; 232 result = prime * result + (int) mDataSize; 233 result = prime * result + (int) (mDataSize >> 32); 234 return result; 235 } 236 237 @Override equals(Object obj)238 public boolean equals(Object obj) { 239 if (this == obj) { 240 return true; 241 } 242 if (obj == null) { 243 return false; 244 } 245 if (getClass() != obj.getClass()) { 246 return false; 247 } 248 PrintDocumentInfo other = (PrintDocumentInfo) obj; 249 if (!TextUtils.equals(mName, other.mName)) { 250 return false; 251 } 252 if (mContentType != other.mContentType) { 253 return false; 254 } 255 if (mPageCount != other.mPageCount) { 256 return false; 257 } 258 if (mDataSize != other.mDataSize) { 259 return false; 260 } 261 return true; 262 } 263 264 @Override toString()265 public String toString() { 266 StringBuilder builder = new StringBuilder(); 267 builder.append("PrintDocumentInfo{"); 268 builder.append("name=").append(mName); 269 builder.append(", pageCount=").append(mPageCount); 270 builder.append(", contentType=").append(contentTypeToString(mContentType)); 271 builder.append(", dataSize=").append(mDataSize); 272 builder.append("}"); 273 return builder.toString(); 274 } 275 contentTypeToString(int contentType)276 private String contentTypeToString(int contentType) { 277 switch (contentType) { 278 case CONTENT_TYPE_DOCUMENT: { 279 return "CONTENT_TYPE_DOCUMENT"; 280 } 281 case CONTENT_TYPE_PHOTO: { 282 return "CONTENT_TYPE_PHOTO"; 283 } 284 default: { 285 return "CONTENT_TYPE_UNKNOWN"; 286 } 287 } 288 } 289 290 /** 291 * Builder for creating a {@link PrintDocumentInfo}. 292 */ 293 public static final class Builder { 294 private final PrintDocumentInfo mPrototype; 295 296 /** 297 * Constructor. 298 * 299 * <p> 300 * The values of the relevant properties are initialized with defaults. 301 * Please refer to the documentation of the individual setters for 302 * information about the default values. 303 * </p> 304 * 305 * @param name The document name which may be shown to the user and 306 * is the file name if the content it describes is saved as a PDF. 307 * Cannot be empty. 308 */ Builder(@onNull String name)309 public Builder(@NonNull String name) { 310 if (TextUtils.isEmpty(name)) { 311 throw new IllegalArgumentException("name cannot be empty"); 312 } 313 mPrototype = new PrintDocumentInfo(); 314 mPrototype.mName = name; 315 } 316 317 /** 318 * Sets the total number of pages. 319 * <p> 320 * <strong>Default: </strong> {@link #PAGE_COUNT_UNKNOWN} 321 * </p> 322 * 323 * @param pageCount The number of pages. Must be greater than or equal to zero or 324 * {@link PrintDocumentInfo#PAGE_COUNT_UNKNOWN}. 325 * @return This builder. 326 */ setPageCount(@ntRangefrom = -1) int pageCount)327 public @NonNull Builder setPageCount(@IntRange(from = -1) int pageCount) { 328 if (pageCount < 0 && pageCount != PAGE_COUNT_UNKNOWN) { 329 throw new IllegalArgumentException("pageCount" 330 + " must be greater than or equal to zero or" 331 + " DocumentInfo#PAGE_COUNT_UNKNOWN"); 332 } 333 mPrototype.mPageCount = pageCount; 334 return this; 335 } 336 337 /** 338 * Sets the content type. 339 * <p> 340 * <strong>Default: </strong> {@link #CONTENT_TYPE_DOCUMENT} 341 * </p> 342 * 343 * @param type The content type. 344 * @return This builder. 345 * @see #CONTENT_TYPE_UNKNOWN 346 * @see #CONTENT_TYPE_DOCUMENT 347 * @see #CONTENT_TYPE_PHOTO 348 */ setContentType(@ontentType int type)349 public @NonNull Builder setContentType(@ContentType int type) { 350 mPrototype.mContentType = type; 351 return this; 352 } 353 354 /** 355 * Creates a new {@link PrintDocumentInfo} instance. 356 * 357 * @return The new instance. 358 */ build()359 public @NonNull PrintDocumentInfo build() { 360 // Zero pages is the same as unknown as in this case 361 // we will have to ask for all pages and look a the 362 // wiritten PDF file for the page count. 363 if (mPrototype.mPageCount == 0) { 364 mPrototype.mPageCount = PAGE_COUNT_UNKNOWN; 365 } 366 return new PrintDocumentInfo(mPrototype); 367 } 368 } 369 370 public static final @android.annotation.NonNull Parcelable.Creator<PrintDocumentInfo> CREATOR = 371 new Creator<PrintDocumentInfo>() { 372 @Override 373 public PrintDocumentInfo createFromParcel(Parcel parcel) { 374 return new PrintDocumentInfo(parcel); 375 } 376 377 @Override 378 public PrintDocumentInfo[] newArray(int size) { 379 return new PrintDocumentInfo[size]; 380 } 381 }; 382 } 383