579 lines
19 KiB
Java
579 lines
19 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.DrawableRes;
|
||
|
import android.annotation.IntDef;
|
||
|
import android.annotation.NonNull;
|
||
|
import android.annotation.Nullable;
|
||
|
import android.annotation.TestApi;
|
||
|
import android.app.PendingIntent;
|
||
|
import android.content.Context;
|
||
|
import android.content.pm.ApplicationInfo;
|
||
|
import android.content.pm.PackageInfo;
|
||
|
import android.content.pm.PackageManager;
|
||
|
import android.content.pm.PackageManager.NameNotFoundException;
|
||
|
import android.graphics.drawable.Drawable;
|
||
|
import android.graphics.drawable.Icon;
|
||
|
import android.os.Parcel;
|
||
|
import android.os.Parcelable;
|
||
|
import android.service.print.PrinterInfoProto;
|
||
|
import android.text.TextUtils;
|
||
|
|
||
|
import com.android.internal.util.Preconditions;
|
||
|
|
||
|
import java.lang.annotation.Retention;
|
||
|
import java.lang.annotation.RetentionPolicy;
|
||
|
|
||
|
/**
|
||
|
* This class represents the description of a printer. Instances of
|
||
|
* this class are created by print services to report to the system
|
||
|
* the printers they manage. The information of this class has two
|
||
|
* major components, printer properties such as name, id, status,
|
||
|
* description and printer capabilities which describe the various
|
||
|
* print modes a printer supports such as media sizes, margins, etc.
|
||
|
* <p>
|
||
|
* Once {@link PrinterInfo.Builder#build() built} the objects are immutable.
|
||
|
* </p>
|
||
|
*/
|
||
|
public final class PrinterInfo implements Parcelable {
|
||
|
|
||
|
/** @hide */
|
||
|
@IntDef(prefix = { "STATUS_" }, value = {
|
||
|
STATUS_IDLE,
|
||
|
STATUS_BUSY,
|
||
|
STATUS_UNAVAILABLE
|
||
|
})
|
||
|
@Retention(RetentionPolicy.SOURCE)
|
||
|
public @interface Status {
|
||
|
}
|
||
|
|
||
|
/** Printer status: the printer is idle and ready to print. */
|
||
|
public static final int STATUS_IDLE = PrinterInfoProto.STATUS_IDLE;
|
||
|
|
||
|
/** Printer status: the printer is busy printing. */
|
||
|
public static final int STATUS_BUSY = PrinterInfoProto.STATUS_BUSY;
|
||
|
|
||
|
/** Printer status: the printer is not available. */
|
||
|
public static final int STATUS_UNAVAILABLE = PrinterInfoProto.STATUS_UNAVAILABLE;
|
||
|
|
||
|
private final @NonNull PrinterId mId;
|
||
|
|
||
|
/** Resource inside the printer's services's package to be used as an icon */
|
||
|
private final int mIconResourceId;
|
||
|
|
||
|
/** If a custom icon can be loaded for the printer */
|
||
|
private final boolean mHasCustomPrinterIcon;
|
||
|
|
||
|
/** The generation of the icon in the cache. */
|
||
|
private final int mCustomPrinterIconGen;
|
||
|
|
||
|
/** Intent that launches the activity showing more information about the printer. */
|
||
|
private final @Nullable PendingIntent mInfoIntent;
|
||
|
|
||
|
private final @NonNull String mName;
|
||
|
|
||
|
private final @Status int mStatus;
|
||
|
|
||
|
private final @Nullable String mDescription;
|
||
|
|
||
|
private final @Nullable PrinterCapabilitiesInfo mCapabilities;
|
||
|
|
||
|
private PrinterInfo(@NonNull PrinterId printerId, @NonNull String name, @Status int status,
|
||
|
int iconResourceId, boolean hasCustomPrinterIcon, String description,
|
||
|
PendingIntent infoIntent, PrinterCapabilitiesInfo capabilities,
|
||
|
int customPrinterIconGen) {
|
||
|
mId = printerId;
|
||
|
mName = name;
|
||
|
mStatus = status;
|
||
|
mIconResourceId = iconResourceId;
|
||
|
mHasCustomPrinterIcon = hasCustomPrinterIcon;
|
||
|
mDescription = description;
|
||
|
mInfoIntent = infoIntent;
|
||
|
mCapabilities = capabilities;
|
||
|
mCustomPrinterIconGen = customPrinterIconGen;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get the globally unique printer id.
|
||
|
*
|
||
|
* @return The printer id.
|
||
|
*/
|
||
|
public @NonNull PrinterId getId() {
|
||
|
return mId;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get the icon to be used for this printer. If no per printer icon is available, the printer's
|
||
|
* service's icon is returned. If the printer has a custom icon this icon might get requested
|
||
|
* asynchronously. Once the icon is loaded the discovery sessions will be notified that the
|
||
|
* printer changed.
|
||
|
*
|
||
|
* @param context The context that will be using the icons
|
||
|
* @return The icon to be used for the printer or null if no icon could be found.
|
||
|
* @hide
|
||
|
*/
|
||
|
@TestApi
|
||
|
public @Nullable Drawable loadIcon(@NonNull Context context) {
|
||
|
Drawable drawable = null;
|
||
|
PackageManager packageManager = context.getPackageManager();
|
||
|
|
||
|
if (mHasCustomPrinterIcon) {
|
||
|
PrintManager printManager = (PrintManager) context
|
||
|
.getSystemService(Context.PRINT_SERVICE);
|
||
|
|
||
|
Icon icon = printManager.getCustomPrinterIcon(mId);
|
||
|
|
||
|
if (icon != null) {
|
||
|
drawable = icon.loadDrawable(context);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (drawable == null) {
|
||
|
try {
|
||
|
String packageName = mId.getServiceName().getPackageName();
|
||
|
PackageInfo packageInfo = packageManager.getPackageInfo(packageName, 0);
|
||
|
ApplicationInfo appInfo = packageInfo.applicationInfo;
|
||
|
|
||
|
// If no custom icon is available, try the icon from the resources
|
||
|
if (mIconResourceId != 0) {
|
||
|
drawable = packageManager.getDrawable(packageName, mIconResourceId, appInfo);
|
||
|
}
|
||
|
|
||
|
// Fall back to the printer's service's icon if no per printer icon could be found
|
||
|
if (drawable == null) {
|
||
|
drawable = appInfo.loadIcon(packageManager);
|
||
|
}
|
||
|
} catch (NameNotFoundException e) {
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return drawable;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Check if the printer has a custom printer icon.
|
||
|
*
|
||
|
* @return {@code true} iff the printer has a custom printer icon.
|
||
|
*
|
||
|
* @hide
|
||
|
*/
|
||
|
public boolean getHasCustomPrinterIcon() {
|
||
|
return mHasCustomPrinterIcon;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get the printer name.
|
||
|
*
|
||
|
* @return The printer name.
|
||
|
*/
|
||
|
public @NonNull String getName() {
|
||
|
return mName;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets the printer status.
|
||
|
*
|
||
|
* @return The status.
|
||
|
*
|
||
|
* @see #STATUS_BUSY
|
||
|
* @see #STATUS_IDLE
|
||
|
* @see #STATUS_UNAVAILABLE
|
||
|
*/
|
||
|
public @Status int getStatus() {
|
||
|
return mStatus;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets the printer description.
|
||
|
*
|
||
|
* @return The description.
|
||
|
*/
|
||
|
public @Nullable String getDescription() {
|
||
|
return mDescription;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get the {@link PendingIntent} that launches the activity showing more information about the
|
||
|
* printer.
|
||
|
*
|
||
|
* @return the {@link PendingIntent} that launches the activity showing more information about
|
||
|
* the printer or null if it is not configured
|
||
|
* @hide
|
||
|
*/
|
||
|
public @Nullable PendingIntent getInfoIntent() {
|
||
|
return mInfoIntent;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets the printer capabilities.
|
||
|
*
|
||
|
* @return The capabilities.
|
||
|
*/
|
||
|
public @Nullable PrinterCapabilitiesInfo getCapabilities() {
|
||
|
return mCapabilities;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Check if printerId is valid.
|
||
|
*
|
||
|
* @param printerId The printerId that might be valid
|
||
|
* @return The valid printerId
|
||
|
* @throws IllegalArgumentException if printerId is not valid.
|
||
|
*/
|
||
|
private static @NonNull PrinterId checkPrinterId(PrinterId printerId) {
|
||
|
return Preconditions.checkNotNull(printerId, "printerId cannot be null.");
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Check if status is valid.
|
||
|
*
|
||
|
* @param status The status that might be valid
|
||
|
* @return The valid status
|
||
|
* @throws IllegalArgumentException if status is not valid.
|
||
|
*/
|
||
|
private static @Status int checkStatus(int status) {
|
||
|
if (!(status == STATUS_IDLE
|
||
|
|| status == STATUS_BUSY
|
||
|
|| status == STATUS_UNAVAILABLE)) {
|
||
|
throw new IllegalArgumentException("status is invalid.");
|
||
|
}
|
||
|
|
||
|
return status;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Check if name is valid.
|
||
|
*
|
||
|
* @param name The name that might be valid
|
||
|
* @return The valid name
|
||
|
* @throws IllegalArgumentException if name is not valid.
|
||
|
*/
|
||
|
private static @NonNull String checkName(String name) {
|
||
|
return Preconditions.checkStringNotEmpty(name, "name cannot be empty.");
|
||
|
}
|
||
|
|
||
|
private PrinterInfo(Parcel parcel) {
|
||
|
// mName can be null due to unchecked set in Builder.setName and status can be invalid
|
||
|
// due to unchecked set in Builder.setStatus, hence we can only check mId for a valid state
|
||
|
mId = checkPrinterId((PrinterId) parcel.readParcelable(null, android.print.PrinterId.class));
|
||
|
mName = checkName(parcel.readString());
|
||
|
mStatus = checkStatus(parcel.readInt());
|
||
|
mDescription = parcel.readString();
|
||
|
mCapabilities = parcel.readParcelable(null, android.print.PrinterCapabilitiesInfo.class);
|
||
|
mIconResourceId = parcel.readInt();
|
||
|
mHasCustomPrinterIcon = parcel.readByte() != 0;
|
||
|
mCustomPrinterIconGen = parcel.readInt();
|
||
|
mInfoIntent = parcel.readParcelable(null, android.app.PendingIntent.class);
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public int describeContents() {
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public void writeToParcel(Parcel parcel, int flags) {
|
||
|
parcel.writeParcelable(mId, flags);
|
||
|
parcel.writeString(mName);
|
||
|
parcel.writeInt(mStatus);
|
||
|
parcel.writeString(mDescription);
|
||
|
parcel.writeParcelable(mCapabilities, flags);
|
||
|
parcel.writeInt(mIconResourceId);
|
||
|
parcel.writeByte((byte) (mHasCustomPrinterIcon ? 1 : 0));
|
||
|
parcel.writeInt(mCustomPrinterIconGen);
|
||
|
parcel.writeParcelable(mInfoIntent, flags);
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public int hashCode() {
|
||
|
final int prime = 31;
|
||
|
int result = 1;
|
||
|
result = prime * result + mId.hashCode();
|
||
|
result = prime * result + mName.hashCode();
|
||
|
result = prime * result + mStatus;
|
||
|
result = prime * result + ((mDescription != null) ? mDescription.hashCode() : 0);
|
||
|
result = prime * result + ((mCapabilities != null) ? mCapabilities.hashCode() : 0);
|
||
|
result = prime * result + mIconResourceId;
|
||
|
result = prime * result + (mHasCustomPrinterIcon ? 1 : 0);
|
||
|
result = prime * result + mCustomPrinterIconGen;
|
||
|
result = prime * result + ((mInfoIntent != null) ? mInfoIntent.hashCode() : 0);
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Compare two {@link PrinterInfo printerInfos} in all aspects beside being null and the
|
||
|
* {@link #mStatus}.
|
||
|
*
|
||
|
* @param other the other {@link PrinterInfo}
|
||
|
* @return true iff the infos are equivalent
|
||
|
* @hide
|
||
|
*/
|
||
|
public boolean equalsIgnoringStatus(PrinterInfo other) {
|
||
|
if (!mId.equals(other.mId)) {
|
||
|
return false;
|
||
|
}
|
||
|
if (!mName.equals(other.mName)) {
|
||
|
return false;
|
||
|
}
|
||
|
if (!TextUtils.equals(mDescription, other.mDescription)) {
|
||
|
return false;
|
||
|
}
|
||
|
if (mCapabilities == null) {
|
||
|
if (other.mCapabilities != null) {
|
||
|
return false;
|
||
|
}
|
||
|
} else if (!mCapabilities.equals(other.mCapabilities)) {
|
||
|
return false;
|
||
|
}
|
||
|
if (mIconResourceId != other.mIconResourceId) {
|
||
|
return false;
|
||
|
}
|
||
|
if (mHasCustomPrinterIcon != other.mHasCustomPrinterIcon) {
|
||
|
return false;
|
||
|
}
|
||
|
if (mCustomPrinterIconGen != other.mCustomPrinterIconGen) {
|
||
|
return false;
|
||
|
}
|
||
|
if (mInfoIntent == null) {
|
||
|
if (other.mInfoIntent != null) {
|
||
|
return false;
|
||
|
}
|
||
|
} else if (!mInfoIntent.equals(other.mInfoIntent)) {
|
||
|
return false;
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public boolean equals(@Nullable Object obj) {
|
||
|
if (this == obj) {
|
||
|
return true;
|
||
|
}
|
||
|
if (obj == null) {
|
||
|
return false;
|
||
|
}
|
||
|
if (getClass() != obj.getClass()) {
|
||
|
return false;
|
||
|
}
|
||
|
PrinterInfo other = (PrinterInfo) obj;
|
||
|
if (!equalsIgnoringStatus(other)) {
|
||
|
return false;
|
||
|
}
|
||
|
if (mStatus != other.mStatus) {
|
||
|
return false;
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public String toString() {
|
||
|
StringBuilder builder = new StringBuilder();
|
||
|
builder.append("PrinterInfo{");
|
||
|
builder.append("id=").append(mId);
|
||
|
builder.append(", name=").append(mName);
|
||
|
builder.append(", status=").append(mStatus);
|
||
|
builder.append(", description=").append(mDescription);
|
||
|
builder.append(", capabilities=").append(mCapabilities);
|
||
|
builder.append(", iconResId=").append(mIconResourceId);
|
||
|
builder.append(", hasCustomPrinterIcon=").append(mHasCustomPrinterIcon);
|
||
|
builder.append(", customPrinterIconGen=").append(mCustomPrinterIconGen);
|
||
|
builder.append(", infoIntent=").append(mInfoIntent);
|
||
|
builder.append("\"}");
|
||
|
return builder.toString();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Builder for creating of a {@link PrinterInfo}.
|
||
|
*/
|
||
|
public static final class Builder {
|
||
|
private @NonNull PrinterId mPrinterId;
|
||
|
private @NonNull String mName;
|
||
|
private @Status int mStatus;
|
||
|
private int mIconResourceId;
|
||
|
private boolean mHasCustomPrinterIcon;
|
||
|
private String mDescription;
|
||
|
private PendingIntent mInfoIntent;
|
||
|
private PrinterCapabilitiesInfo mCapabilities;
|
||
|
private int mCustomPrinterIconGen;
|
||
|
|
||
|
/**
|
||
|
* Constructor.
|
||
|
*
|
||
|
* @param printerId The printer id. Cannot be null.
|
||
|
* @param name The printer name. Cannot be empty.
|
||
|
* @param status The printer status. Must be a valid status.
|
||
|
* @throws IllegalArgumentException If the printer id is null, or the
|
||
|
* printer name is empty or the status is not a valid one.
|
||
|
*/
|
||
|
public Builder(@NonNull PrinterId printerId, @NonNull String name, @Status int status) {
|
||
|
mPrinterId = checkPrinterId(printerId);
|
||
|
mName = checkName(name);
|
||
|
mStatus = checkStatus(status);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Constructor.
|
||
|
*
|
||
|
* @param other Other info from which to start building.
|
||
|
*/
|
||
|
public Builder(@NonNull PrinterInfo other) {
|
||
|
mPrinterId = other.mId;
|
||
|
mName = other.mName;
|
||
|
mStatus = other.mStatus;
|
||
|
mIconResourceId = other.mIconResourceId;
|
||
|
mHasCustomPrinterIcon = other.mHasCustomPrinterIcon;
|
||
|
mDescription = other.mDescription;
|
||
|
mInfoIntent = other.mInfoIntent;
|
||
|
mCapabilities = other.mCapabilities;
|
||
|
mCustomPrinterIconGen = other.mCustomPrinterIconGen;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Sets the printer status.
|
||
|
*
|
||
|
* @param status The status.
|
||
|
* @return This builder.
|
||
|
* @see PrinterInfo#STATUS_IDLE
|
||
|
* @see PrinterInfo#STATUS_BUSY
|
||
|
* @see PrinterInfo#STATUS_UNAVAILABLE
|
||
|
*/
|
||
|
public @NonNull Builder setStatus(@Status int status) {
|
||
|
mStatus = checkStatus(status);
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Set a drawable resource as icon for this printer. If no icon is set the printer's
|
||
|
* service's icon is used for the printer.
|
||
|
*
|
||
|
* @param iconResourceId The resource ID of the icon.
|
||
|
* @return This builder.
|
||
|
* @see PrinterInfo.Builder#setHasCustomPrinterIcon
|
||
|
*/
|
||
|
public @NonNull Builder setIconResourceId(@DrawableRes int iconResourceId) {
|
||
|
mIconResourceId = Preconditions.checkArgumentNonnegative(iconResourceId,
|
||
|
"iconResourceId can't be negative");
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Declares that the print service can load a custom per printer's icon. If both
|
||
|
* {@link PrinterInfo.Builder#setIconResourceId} and a custom icon are set the resource icon
|
||
|
* is shown while the custom icon loads but then the custom icon is used. If
|
||
|
* {@link PrinterInfo.Builder#setIconResourceId} is not set the printer's service's icon is
|
||
|
* shown while loading.
|
||
|
* <p>
|
||
|
* The icon is requested asynchronously and only when needed via
|
||
|
* {@link android.printservice.PrinterDiscoverySession#onRequestCustomPrinterIcon}.
|
||
|
* </p>
|
||
|
*
|
||
|
* @param hasCustomPrinterIcon If the printer has a custom icon or not.
|
||
|
*
|
||
|
* @return This builder.
|
||
|
*/
|
||
|
public @NonNull Builder setHasCustomPrinterIcon(boolean hasCustomPrinterIcon) {
|
||
|
mHasCustomPrinterIcon = hasCustomPrinterIcon;
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Sets the <strong>localized</strong> printer name which
|
||
|
* is shown to the user
|
||
|
*
|
||
|
* @param name The name.
|
||
|
* @return This builder.
|
||
|
*/
|
||
|
public @NonNull Builder setName(@NonNull String name) {
|
||
|
mName = checkName(name);
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Sets the <strong>localized</strong> printer description
|
||
|
* which is shown to the user
|
||
|
*
|
||
|
* @param description The description.
|
||
|
* @return This builder.
|
||
|
*/
|
||
|
public @NonNull Builder setDescription(@NonNull String description) {
|
||
|
mDescription = description;
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Sets the {@link PendingIntent} that launches an activity showing more information about
|
||
|
* the printer.
|
||
|
*
|
||
|
* @param infoIntent The {@link PendingIntent intent}.
|
||
|
* @return This builder.
|
||
|
*/
|
||
|
public @NonNull Builder setInfoIntent(@NonNull PendingIntent infoIntent) {
|
||
|
mInfoIntent = infoIntent;
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Sets the printer capabilities.
|
||
|
*
|
||
|
* @param capabilities The capabilities.
|
||
|
* @return This builder.
|
||
|
*/
|
||
|
public @NonNull Builder setCapabilities(@NonNull PrinterCapabilitiesInfo capabilities) {
|
||
|
mCapabilities = capabilities;
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Creates a new {@link PrinterInfo}.
|
||
|
*
|
||
|
* @return A new {@link PrinterInfo}.
|
||
|
*/
|
||
|
public @NonNull PrinterInfo build() {
|
||
|
return new PrinterInfo(mPrinterId, mName, mStatus, mIconResourceId,
|
||
|
mHasCustomPrinterIcon, mDescription, mInfoIntent, mCapabilities,
|
||
|
mCustomPrinterIconGen);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Increments the generation number of the custom printer icon. As the {@link PrinterInfo}
|
||
|
* does not match the previous one anymore, users of the {@link PrinterInfo} will reload the
|
||
|
* icon if needed.
|
||
|
*
|
||
|
* @return This builder.
|
||
|
* @hide
|
||
|
*/
|
||
|
public @NonNull Builder incCustomPrinterIconGen() {
|
||
|
mCustomPrinterIconGen++;
|
||
|
return this;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public static final @android.annotation.NonNull Parcelable.Creator<PrinterInfo> CREATOR =
|
||
|
new Parcelable.Creator<PrinterInfo>() {
|
||
|
@Override
|
||
|
public PrinterInfo createFromParcel(Parcel parcel) {
|
||
|
return new PrinterInfo(parcel);
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public PrinterInfo[] newArray(int size) {
|
||
|
return new PrinterInfo[size];
|
||
|
}
|
||
|
};
|
||
|
}
|