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