664 lines
22 KiB
Java
664 lines
22 KiB
Java
![]() |
/*
|
||
|
* Copyright (C) 2013 The Android Open Source Project
|
||
|
*
|
||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
* you may not use this file except in compliance with the License.
|
||
|
* You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
* See the License for the specific language governing permissions and
|
||
|
* limitations under the License.
|
||
|
*/
|
||
|
|
||
|
package android.print;
|
||
|
|
||
|
import android.annotation.NonNull;
|
||
|
import android.annotation.Nullable;
|
||
|
import android.os.Parcel;
|
||
|
import android.os.Parcelable;
|
||
|
import android.print.PrintAttributes.ColorMode;
|
||
|
import android.print.PrintAttributes.DuplexMode;
|
||
|
import android.print.PrintAttributes.Margins;
|
||
|
import android.print.PrintAttributes.MediaSize;
|
||
|
import android.print.PrintAttributes.Resolution;
|
||
|
|
||
|
import com.android.internal.util.Preconditions;
|
||
|
|
||
|
import java.util.ArrayList;
|
||
|
import java.util.Arrays;
|
||
|
import java.util.Collections;
|
||
|
import java.util.List;
|
||
|
import java.util.function.IntConsumer;
|
||
|
|
||
|
/**
|
||
|
* This class represents the capabilities of a printer. Instances
|
||
|
* of this class are created by a print service to report the
|
||
|
* capabilities of a printer it manages. The capabilities of a
|
||
|
* printer specify how it can print content. For example, what
|
||
|
* are the media sizes supported by the printer, what are the
|
||
|
* minimal margins of the printer based on its technical design,
|
||
|
* etc.
|
||
|
*/
|
||
|
public final class PrinterCapabilitiesInfo implements Parcelable {
|
||
|
/**
|
||
|
* Undefined default value.
|
||
|
*
|
||
|
* @hide
|
||
|
*/
|
||
|
public static final int DEFAULT_UNDEFINED = -1;
|
||
|
|
||
|
private static final int PROPERTY_MEDIA_SIZE = 0;
|
||
|
private static final int PROPERTY_RESOLUTION = 1;
|
||
|
private static final int PROPERTY_COLOR_MODE = 2;
|
||
|
private static final int PROPERTY_DUPLEX_MODE = 3;
|
||
|
private static final int PROPERTY_COUNT = 4;
|
||
|
|
||
|
private static final Margins DEFAULT_MARGINS = new Margins(0, 0, 0, 0);
|
||
|
|
||
|
private @NonNull Margins mMinMargins = DEFAULT_MARGINS;
|
||
|
private @NonNull List<MediaSize> mMediaSizes;
|
||
|
private @NonNull List<Resolution> mResolutions;
|
||
|
|
||
|
private int mColorModes;
|
||
|
private int mDuplexModes;
|
||
|
|
||
|
private final int[] mDefaults = new int[PROPERTY_COUNT];
|
||
|
|
||
|
/**
|
||
|
* @hide
|
||
|
*/
|
||
|
public PrinterCapabilitiesInfo() {
|
||
|
Arrays.fill(mDefaults, DEFAULT_UNDEFINED);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @hide
|
||
|
*/
|
||
|
public PrinterCapabilitiesInfo(PrinterCapabilitiesInfo prototype) {
|
||
|
copyFrom(prototype);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @hide
|
||
|
*/
|
||
|
public void copyFrom(PrinterCapabilitiesInfo other) {
|
||
|
if (this == other) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
mMinMargins = other.mMinMargins;
|
||
|
|
||
|
if (other.mMediaSizes != null) {
|
||
|
if (mMediaSizes != null) {
|
||
|
mMediaSizes.clear();
|
||
|
mMediaSizes.addAll(other.mMediaSizes);
|
||
|
} else {
|
||
|
mMediaSizes = new ArrayList<MediaSize>(other.mMediaSizes);
|
||
|
}
|
||
|
} else {
|
||
|
mMediaSizes = null;
|
||
|
}
|
||
|
|
||
|
if (other.mResolutions != null) {
|
||
|
if (mResolutions != null) {
|
||
|
mResolutions.clear();
|
||
|
mResolutions.addAll(other.mResolutions);
|
||
|
} else {
|
||
|
mResolutions = new ArrayList<Resolution>(other.mResolutions);
|
||
|
}
|
||
|
} else {
|
||
|
mResolutions = null;
|
||
|
}
|
||
|
|
||
|
mColorModes = other.mColorModes;
|
||
|
mDuplexModes = other.mDuplexModes;
|
||
|
|
||
|
final int defaultCount = other.mDefaults.length;
|
||
|
for (int i = 0; i < defaultCount; i++) {
|
||
|
mDefaults[i] = other.mDefaults[i];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets the supported media sizes.
|
||
|
*
|
||
|
* @return The media sizes.
|
||
|
*/
|
||
|
public @NonNull List<MediaSize> getMediaSizes() {
|
||
|
return Collections.unmodifiableList(mMediaSizes);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets the supported resolutions.
|
||
|
*
|
||
|
* @return The resolutions.
|
||
|
*/
|
||
|
public @NonNull List<Resolution> getResolutions() {
|
||
|
return Collections.unmodifiableList(mResolutions);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets the minimal margins. These are the minimal margins
|
||
|
* the printer physically supports.
|
||
|
*
|
||
|
* @return The minimal margins.
|
||
|
*/
|
||
|
public @NonNull Margins getMinMargins() {
|
||
|
return mMinMargins;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets the bit mask of supported color modes.
|
||
|
*
|
||
|
* @return The bit mask of supported color modes.
|
||
|
*
|
||
|
* @see PrintAttributes#COLOR_MODE_COLOR
|
||
|
* @see PrintAttributes#COLOR_MODE_MONOCHROME
|
||
|
*/
|
||
|
public @ColorMode int getColorModes() {
|
||
|
return mColorModes;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets the bit mask of supported duplex modes.
|
||
|
*
|
||
|
* @return The bit mask of supported duplex modes.
|
||
|
*
|
||
|
* @see PrintAttributes#DUPLEX_MODE_NONE
|
||
|
* @see PrintAttributes#DUPLEX_MODE_LONG_EDGE
|
||
|
* @see PrintAttributes#DUPLEX_MODE_SHORT_EDGE
|
||
|
*/
|
||
|
public @DuplexMode int getDuplexModes() {
|
||
|
return mDuplexModes;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets the default print attributes.
|
||
|
*
|
||
|
* @return The default attributes.
|
||
|
*/
|
||
|
public @NonNull PrintAttributes getDefaults() {
|
||
|
PrintAttributes.Builder builder = new PrintAttributes.Builder();
|
||
|
|
||
|
builder.setMinMargins(mMinMargins);
|
||
|
|
||
|
final int mediaSizeIndex = mDefaults[PROPERTY_MEDIA_SIZE];
|
||
|
if (mediaSizeIndex >= 0) {
|
||
|
builder.setMediaSize(mMediaSizes.get(mediaSizeIndex));
|
||
|
}
|
||
|
|
||
|
final int resolutionIndex = mDefaults[PROPERTY_RESOLUTION];
|
||
|
if (resolutionIndex >= 0) {
|
||
|
builder.setResolution(mResolutions.get(resolutionIndex));
|
||
|
}
|
||
|
|
||
|
final int colorMode = mDefaults[PROPERTY_COLOR_MODE];
|
||
|
if (colorMode > 0) {
|
||
|
builder.setColorMode(colorMode);
|
||
|
}
|
||
|
|
||
|
final int duplexMode = mDefaults[PROPERTY_DUPLEX_MODE];
|
||
|
if (duplexMode > 0) {
|
||
|
builder.setDuplexMode(duplexMode);
|
||
|
}
|
||
|
|
||
|
return builder.build();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Call enforceSingle for each bit in the mask.
|
||
|
*
|
||
|
* @param mask The mask
|
||
|
* @param enforceSingle The function to call
|
||
|
*/
|
||
|
private static void enforceValidMask(int mask, IntConsumer enforceSingle) {
|
||
|
int current = mask;
|
||
|
while (current > 0) {
|
||
|
final int currentMode = (1 << Integer.numberOfTrailingZeros(current));
|
||
|
current &= ~currentMode;
|
||
|
enforceSingle.accept(currentMode);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private PrinterCapabilitiesInfo(Parcel parcel) {
|
||
|
mMinMargins = Preconditions.checkNotNull(readMargins(parcel));
|
||
|
readMediaSizes(parcel);
|
||
|
readResolutions(parcel);
|
||
|
|
||
|
mColorModes = parcel.readInt();
|
||
|
enforceValidMask(mColorModes,
|
||
|
(currentMode) -> PrintAttributes.enforceValidColorMode(currentMode));
|
||
|
|
||
|
mDuplexModes = parcel.readInt();
|
||
|
enforceValidMask(mDuplexModes,
|
||
|
(currentMode) -> PrintAttributes.enforceValidDuplexMode(currentMode));
|
||
|
|
||
|
readDefaults(parcel);
|
||
|
Preconditions.checkArgument(mMediaSizes.size() > mDefaults[PROPERTY_MEDIA_SIZE]);
|
||
|
Preconditions.checkArgument(mResolutions.size() > mDefaults[PROPERTY_RESOLUTION]);
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public int describeContents() {
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public void writeToParcel(Parcel parcel, int flags) {
|
||
|
writeMargins(mMinMargins, parcel);
|
||
|
writeMediaSizes(parcel);
|
||
|
writeResolutions(parcel);
|
||
|
|
||
|
parcel.writeInt(mColorModes);
|
||
|
parcel.writeInt(mDuplexModes);
|
||
|
|
||
|
writeDefaults(parcel);
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public int hashCode() {
|
||
|
final int prime = 31;
|
||
|
int result = 1;
|
||
|
result = prime * result + ((mMinMargins == null) ? 0 : mMinMargins.hashCode());
|
||
|
result = prime * result + ((mMediaSizes == null) ? 0 : mMediaSizes.hashCode());
|
||
|
result = prime * result + ((mResolutions == null) ? 0 : mResolutions.hashCode());
|
||
|
result = prime * result + mColorModes;
|
||
|
result = prime * result + mDuplexModes;
|
||
|
result = prime * result + Arrays.hashCode(mDefaults);
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public boolean equals(@Nullable Object obj) {
|
||
|
if (this == obj) {
|
||
|
return true;
|
||
|
}
|
||
|
if (obj == null) {
|
||
|
return false;
|
||
|
}
|
||
|
if (getClass() != obj.getClass()) {
|
||
|
return false;
|
||
|
}
|
||
|
PrinterCapabilitiesInfo other = (PrinterCapabilitiesInfo) obj;
|
||
|
if (mMinMargins == null) {
|
||
|
if (other.mMinMargins != null) {
|
||
|
return false;
|
||
|
}
|
||
|
} else if (!mMinMargins.equals(other.mMinMargins)) {
|
||
|
return false;
|
||
|
}
|
||
|
if (mMediaSizes == null) {
|
||
|
if (other.mMediaSizes != null) {
|
||
|
return false;
|
||
|
}
|
||
|
} else if (!mMediaSizes.equals(other.mMediaSizes)) {
|
||
|
return false;
|
||
|
}
|
||
|
if (mResolutions == null) {
|
||
|
if (other.mResolutions != null) {
|
||
|
return false;
|
||
|
}
|
||
|
} else if (!mResolutions.equals(other.mResolutions)) {
|
||
|
return false;
|
||
|
}
|
||
|
if (mColorModes != other.mColorModes) {
|
||
|
return false;
|
||
|
}
|
||
|
if (mDuplexModes != other.mDuplexModes) {
|
||
|
return false;
|
||
|
}
|
||
|
if (!Arrays.equals(mDefaults, other.mDefaults)) {
|
||
|
return false;
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public String toString() {
|
||
|
StringBuilder builder = new StringBuilder();
|
||
|
builder.append("PrinterInfo{");
|
||
|
builder.append("minMargins=").append(mMinMargins);
|
||
|
builder.append(", mediaSizes=").append(mMediaSizes);
|
||
|
builder.append(", resolutions=").append(mResolutions);
|
||
|
builder.append(", colorModes=").append(colorModesToString());
|
||
|
builder.append(", duplexModes=").append(duplexModesToString());
|
||
|
builder.append("\"}");
|
||
|
return builder.toString();
|
||
|
}
|
||
|
|
||
|
private String colorModesToString() {
|
||
|
StringBuilder builder = new StringBuilder();
|
||
|
builder.append('[');
|
||
|
int colorModes = mColorModes;
|
||
|
while (colorModes != 0) {
|
||
|
final int colorMode = 1 << Integer.numberOfTrailingZeros(colorModes);
|
||
|
colorModes &= ~colorMode;
|
||
|
if (builder.length() > 1) {
|
||
|
builder.append(", ");
|
||
|
}
|
||
|
builder.append(PrintAttributes.colorModeToString(colorMode));
|
||
|
}
|
||
|
builder.append(']');
|
||
|
return builder.toString();
|
||
|
}
|
||
|
|
||
|
private String duplexModesToString() {
|
||
|
StringBuilder builder = new StringBuilder();
|
||
|
builder.append('[');
|
||
|
int duplexModes = mDuplexModes;
|
||
|
while (duplexModes != 0) {
|
||
|
final int duplexMode = 1 << Integer.numberOfTrailingZeros(duplexModes);
|
||
|
duplexModes &= ~duplexMode;
|
||
|
if (builder.length() > 1) {
|
||
|
builder.append(", ");
|
||
|
}
|
||
|
builder.append(PrintAttributes.duplexModeToString(duplexMode));
|
||
|
}
|
||
|
builder.append(']');
|
||
|
return builder.toString();
|
||
|
}
|
||
|
|
||
|
private void writeMediaSizes(Parcel parcel) {
|
||
|
if (mMediaSizes == null) {
|
||
|
parcel.writeInt(0);
|
||
|
return;
|
||
|
}
|
||
|
final int mediaSizeCount = mMediaSizes.size();
|
||
|
parcel.writeInt(mediaSizeCount);
|
||
|
for (int i = 0; i < mediaSizeCount; i++) {
|
||
|
mMediaSizes.get(i).writeToParcel(parcel);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void readMediaSizes(Parcel parcel) {
|
||
|
final int mediaSizeCount = parcel.readInt();
|
||
|
if (mediaSizeCount > 0 && mMediaSizes == null) {
|
||
|
mMediaSizes = new ArrayList<MediaSize>();
|
||
|
}
|
||
|
for (int i = 0; i < mediaSizeCount; i++) {
|
||
|
mMediaSizes.add(MediaSize.createFromParcel(parcel));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void writeResolutions(Parcel parcel) {
|
||
|
if (mResolutions == null) {
|
||
|
parcel.writeInt(0);
|
||
|
return;
|
||
|
}
|
||
|
final int resolutionCount = mResolutions.size();
|
||
|
parcel.writeInt(resolutionCount);
|
||
|
for (int i = 0; i < resolutionCount; i++) {
|
||
|
mResolutions.get(i).writeToParcel(parcel);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void readResolutions(Parcel parcel) {
|
||
|
final int resolutionCount = parcel.readInt();
|
||
|
if (resolutionCount > 0 && mResolutions == null) {
|
||
|
mResolutions = new ArrayList<Resolution>();
|
||
|
}
|
||
|
for (int i = 0; i < resolutionCount; i++) {
|
||
|
mResolutions.add(Resolution.createFromParcel(parcel));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void writeMargins(Margins margins, Parcel parcel) {
|
||
|
if (margins == null) {
|
||
|
parcel.writeInt(0);
|
||
|
} else {
|
||
|
parcel.writeInt(1);
|
||
|
margins.writeToParcel(parcel);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private Margins readMargins(Parcel parcel) {
|
||
|
return (parcel.readInt() == 1) ? Margins.createFromParcel(parcel) : null;
|
||
|
}
|
||
|
|
||
|
private void readDefaults(Parcel parcel) {
|
||
|
final int defaultCount = parcel.readInt();
|
||
|
for (int i = 0; i < defaultCount; i++) {
|
||
|
mDefaults[i] = parcel.readInt();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void writeDefaults(Parcel parcel) {
|
||
|
final int defaultCount = mDefaults.length;
|
||
|
parcel.writeInt(defaultCount);
|
||
|
for (int i = 0; i < defaultCount; i++) {
|
||
|
parcel.writeInt(mDefaults[i]);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Builder for creating of a {@link PrinterCapabilitiesInfo}. This class is
|
||
|
* responsible to enforce that all required attributes have at least one
|
||
|
* default value. In other words, this class creates only well-formed {@link
|
||
|
* PrinterCapabilitiesInfo}s.
|
||
|
* <p>
|
||
|
* Look at the individual methods for a reference whether a property is
|
||
|
* required or if it is optional.
|
||
|
* </p>
|
||
|
*/
|
||
|
public static final class Builder {
|
||
|
private final PrinterCapabilitiesInfo mPrototype;
|
||
|
|
||
|
/**
|
||
|
* Creates a new instance.
|
||
|
*
|
||
|
* @param printerId The printer id. Cannot be <code>null</code>.
|
||
|
*
|
||
|
* @throws IllegalArgumentException If the printer id is <code>null</code>.
|
||
|
*/
|
||
|
public Builder(@NonNull PrinterId printerId) {
|
||
|
if (printerId == null) {
|
||
|
throw new IllegalArgumentException("printerId cannot be null.");
|
||
|
}
|
||
|
mPrototype = new PrinterCapabilitiesInfo();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Adds a supported media size.
|
||
|
* <p>
|
||
|
* <strong>Required:</strong> Yes
|
||
|
* </p>
|
||
|
*
|
||
|
* @param mediaSize A media size.
|
||
|
* @param isDefault Whether this is the default.
|
||
|
* @return This builder.
|
||
|
* @throws IllegalArgumentException If set as default and there
|
||
|
* is already a default.
|
||
|
*
|
||
|
* @see PrintAttributes.MediaSize
|
||
|
*/
|
||
|
public @NonNull Builder addMediaSize(@NonNull MediaSize mediaSize, boolean isDefault) {
|
||
|
if (mPrototype.mMediaSizes == null) {
|
||
|
mPrototype.mMediaSizes = new ArrayList<MediaSize>();
|
||
|
}
|
||
|
final int insertionIndex = mPrototype.mMediaSizes.size();
|
||
|
mPrototype.mMediaSizes.add(mediaSize);
|
||
|
if (isDefault) {
|
||
|
throwIfDefaultAlreadySpecified(PROPERTY_MEDIA_SIZE);
|
||
|
mPrototype.mDefaults[PROPERTY_MEDIA_SIZE] = insertionIndex;
|
||
|
}
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Adds a supported resolution.
|
||
|
* <p>
|
||
|
* <strong>Required:</strong> Yes
|
||
|
* </p>
|
||
|
*
|
||
|
* @param resolution A resolution.
|
||
|
* @param isDefault Whether this is the default.
|
||
|
* @return This builder.
|
||
|
*
|
||
|
* @throws IllegalArgumentException If set as default and there
|
||
|
* is already a default.
|
||
|
*
|
||
|
* @see PrintAttributes.Resolution
|
||
|
*/
|
||
|
public @NonNull Builder addResolution(@NonNull Resolution resolution, boolean isDefault) {
|
||
|
if (mPrototype.mResolutions == null) {
|
||
|
mPrototype.mResolutions = new ArrayList<Resolution>();
|
||
|
}
|
||
|
final int insertionIndex = mPrototype.mResolutions.size();
|
||
|
mPrototype.mResolutions.add(resolution);
|
||
|
if (isDefault) {
|
||
|
throwIfDefaultAlreadySpecified(PROPERTY_RESOLUTION);
|
||
|
mPrototype.mDefaults[PROPERTY_RESOLUTION] = insertionIndex;
|
||
|
}
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Sets the minimal margins. These are the minimal margins
|
||
|
* the printer physically supports.
|
||
|
*
|
||
|
* <p>
|
||
|
* <strong>Required:</strong> Yes
|
||
|
* </p>
|
||
|
*
|
||
|
* @param margins The margins.
|
||
|
* @return This builder.
|
||
|
*
|
||
|
* @throws IllegalArgumentException If margins are <code>null</code>.
|
||
|
*
|
||
|
* @see PrintAttributes.Margins
|
||
|
*/
|
||
|
public @NonNull Builder setMinMargins(@NonNull Margins margins) {
|
||
|
if (margins == null) {
|
||
|
throw new IllegalArgumentException("margins cannot be null");
|
||
|
}
|
||
|
mPrototype.mMinMargins = margins;
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Sets the color modes.
|
||
|
* <p>
|
||
|
* <strong>Required:</strong> Yes
|
||
|
* </p>
|
||
|
*
|
||
|
* @param colorModes The color mode bit mask.
|
||
|
* @param defaultColorMode The default color mode.
|
||
|
* @return This builder.
|
||
|
* <p>
|
||
|
* <strong>Note:</strong> On platform version 19 (Kitkat) specifying
|
||
|
* only PrintAttributes#COLOR_MODE_MONOCHROME leads to a print spooler
|
||
|
* crash. Hence, you should declare either both color modes or
|
||
|
* PrintAttributes#COLOR_MODE_COLOR.
|
||
|
* </p>
|
||
|
*
|
||
|
* @throws IllegalArgumentException If color modes contains an invalid
|
||
|
* mode bit or if the default color mode is invalid.
|
||
|
*
|
||
|
* @see PrintAttributes#COLOR_MODE_COLOR
|
||
|
* @see PrintAttributes#COLOR_MODE_MONOCHROME
|
||
|
*/
|
||
|
public @NonNull Builder setColorModes(@ColorMode int colorModes,
|
||
|
@ColorMode int defaultColorMode) {
|
||
|
enforceValidMask(colorModes,
|
||
|
(currentMode) -> PrintAttributes.enforceValidColorMode(currentMode));
|
||
|
PrintAttributes.enforceValidColorMode(defaultColorMode);
|
||
|
mPrototype.mColorModes = colorModes;
|
||
|
mPrototype.mDefaults[PROPERTY_COLOR_MODE] = defaultColorMode;
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Sets the duplex modes.
|
||
|
* <p>
|
||
|
* <strong>Required:</strong> No
|
||
|
* </p>
|
||
|
*
|
||
|
* @param duplexModes The duplex mode bit mask.
|
||
|
* @param defaultDuplexMode The default duplex mode.
|
||
|
* @return This builder.
|
||
|
*
|
||
|
* @throws IllegalArgumentException If duplex modes contains an invalid
|
||
|
* mode bit or if the default duplex mode is invalid.
|
||
|
*
|
||
|
* @see PrintAttributes#DUPLEX_MODE_NONE
|
||
|
* @see PrintAttributes#DUPLEX_MODE_LONG_EDGE
|
||
|
* @see PrintAttributes#DUPLEX_MODE_SHORT_EDGE
|
||
|
*/
|
||
|
public @NonNull Builder setDuplexModes(@DuplexMode int duplexModes,
|
||
|
@DuplexMode int defaultDuplexMode) {
|
||
|
enforceValidMask(duplexModes,
|
||
|
(currentMode) -> PrintAttributes.enforceValidDuplexMode(currentMode));
|
||
|
PrintAttributes.enforceValidDuplexMode(defaultDuplexMode);
|
||
|
mPrototype.mDuplexModes = duplexModes;
|
||
|
mPrototype.mDefaults[PROPERTY_DUPLEX_MODE] = defaultDuplexMode;
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Crates a new {@link PrinterCapabilitiesInfo} enforcing that all
|
||
|
* required properties have been specified. See individual methods
|
||
|
* in this class for reference about required attributes.
|
||
|
* <p>
|
||
|
* <strong>Note:</strong> If you do not add supported duplex modes,
|
||
|
* {@link android.print.PrintAttributes#DUPLEX_MODE_NONE} will set
|
||
|
* as the only supported mode and also as the default duplex mode.
|
||
|
* </p>
|
||
|
*
|
||
|
* @return A new {@link PrinterCapabilitiesInfo}.
|
||
|
*
|
||
|
* @throws IllegalStateException If a required attribute was not specified.
|
||
|
*/
|
||
|
public @NonNull PrinterCapabilitiesInfo build() {
|
||
|
if (mPrototype.mMediaSizes == null || mPrototype.mMediaSizes.isEmpty()) {
|
||
|
throw new IllegalStateException("No media size specified.");
|
||
|
}
|
||
|
if (mPrototype.mDefaults[PROPERTY_MEDIA_SIZE] == DEFAULT_UNDEFINED) {
|
||
|
throw new IllegalStateException("No default media size specified.");
|
||
|
}
|
||
|
if (mPrototype.mResolutions == null || mPrototype.mResolutions.isEmpty()) {
|
||
|
throw new IllegalStateException("No resolution specified.");
|
||
|
}
|
||
|
if (mPrototype.mDefaults[PROPERTY_RESOLUTION] == DEFAULT_UNDEFINED) {
|
||
|
throw new IllegalStateException("No default resolution specified.");
|
||
|
}
|
||
|
if (mPrototype.mColorModes == 0) {
|
||
|
throw new IllegalStateException("No color mode specified.");
|
||
|
}
|
||
|
if (mPrototype.mDefaults[PROPERTY_COLOR_MODE] == DEFAULT_UNDEFINED) {
|
||
|
throw new IllegalStateException("No default color mode specified.");
|
||
|
}
|
||
|
if (mPrototype.mDuplexModes == 0) {
|
||
|
setDuplexModes(PrintAttributes.DUPLEX_MODE_NONE,
|
||
|
PrintAttributes.DUPLEX_MODE_NONE);
|
||
|
}
|
||
|
if (mPrototype.mMinMargins == null) {
|
||
|
throw new IllegalArgumentException("margins cannot be null");
|
||
|
}
|
||
|
return mPrototype;
|
||
|
}
|
||
|
|
||
|
private void throwIfDefaultAlreadySpecified(int propertyIndex) {
|
||
|
if (mPrototype.mDefaults[propertyIndex] != DEFAULT_UNDEFINED) {
|
||
|
throw new IllegalArgumentException("Default already specified.");
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public static final @android.annotation.NonNull Parcelable.Creator<PrinterCapabilitiesInfo> CREATOR =
|
||
|
new Parcelable.Creator<PrinterCapabilitiesInfo>() {
|
||
|
@Override
|
||
|
public PrinterCapabilitiesInfo createFromParcel(Parcel parcel) {
|
||
|
return new PrinterCapabilitiesInfo(parcel);
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public PrinterCapabilitiesInfo[] newArray(int size) {
|
||
|
return new PrinterCapabilitiesInfo[size];
|
||
|
}
|
||
|
};
|
||
|
}
|