am c7c4d6dd: Merge "Refinement of the print service APIs." into klp-dev
* commit 'c7c4d6dd4df2b177d0b6e382fdcde9bf2032baea': Refinement of the print service APIs.
This commit is contained in:
@@ -162,8 +162,9 @@ LOCAL_SRC_FILES += \
|
||||
core/java/android/os/IVibratorService.aidl \
|
||||
core/java/android/service/notification/INotificationListener.aidl \
|
||||
core/java/android/print/ILayoutResultCallback.aidl \
|
||||
core/java/android/print/IPrinterDiscoverySessionController.aidl \
|
||||
core/java/android/print/IPrinterDiscoverySessionObserver.aidl \
|
||||
core/java/android/print/IPrintDocumentAdapter.aidl \
|
||||
core/java/android/print/IPrinterDiscoveryObserver.aidl \
|
||||
core/java/android/print/IPrintClient.aidl \
|
||||
core/java/android/print/IPrintManager.aidl \
|
||||
core/java/android/print/IPrintSpooler.aidl \
|
||||
|
||||
@@ -167,6 +167,7 @@ $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framew
|
||||
$(call add-clean-step, rm -rf $(HOST_OUT)/obj/STATIC_LIBRARIES/libandroidfw_intermediates/import_includes)
|
||||
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates)
|
||||
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates)
|
||||
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/src/core/java/android/print/IPrinterDiscoveryObserver.*)
|
||||
# ************************************************
|
||||
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
|
||||
# ************************************************
|
||||
|
||||
107
api/current.txt
107
api/current.txt
@@ -18629,11 +18629,11 @@ package android.print {
|
||||
}
|
||||
|
||||
public static final class PrintAttributes.MediaSize {
|
||||
ctor public PrintAttributes.MediaSize(java.lang.String, java.lang.CharSequence, int, int);
|
||||
ctor public PrintAttributes.MediaSize(java.lang.String, java.lang.String, int, int);
|
||||
method public static android.print.PrintAttributes.MediaSize createMediaSize(android.content.pm.PackageManager, int);
|
||||
method public int getHeightMils();
|
||||
method public java.lang.String getId();
|
||||
method public java.lang.CharSequence getLabel();
|
||||
method public java.lang.String getLabel();
|
||||
method public int getWidthMils();
|
||||
field public static final int ISO_A0 = 1; // 0x1
|
||||
field public static final int ISO_A1 = 2; // 0x2
|
||||
@@ -18677,17 +18677,17 @@ package android.print {
|
||||
}
|
||||
|
||||
public static final class PrintAttributes.Resolution {
|
||||
ctor public PrintAttributes.Resolution(java.lang.String, java.lang.CharSequence, int, int);
|
||||
ctor public PrintAttributes.Resolution(java.lang.String, java.lang.String, int, int);
|
||||
method public int getHorizontalDpi();
|
||||
method public java.lang.String getId();
|
||||
method public java.lang.CharSequence getLabel();
|
||||
method public java.lang.String getLabel();
|
||||
method public int getVerticalDpi();
|
||||
}
|
||||
|
||||
public static final class PrintAttributes.Tray {
|
||||
ctor public PrintAttributes.Tray(java.lang.String, java.lang.CharSequence);
|
||||
ctor public PrintAttributes.Tray(java.lang.String, java.lang.String);
|
||||
method public java.lang.String getId();
|
||||
method public java.lang.CharSequence getLabel();
|
||||
method public java.lang.String getLabel();
|
||||
}
|
||||
|
||||
public abstract class PrintDocumentAdapter {
|
||||
@@ -18714,6 +18714,7 @@ package android.print {
|
||||
public final class PrintDocumentInfo implements android.os.Parcelable {
|
||||
method public int describeContents();
|
||||
method public int getContentType();
|
||||
method public java.lang.String getName();
|
||||
method public int getPageCount();
|
||||
method public void writeToParcel(android.os.Parcel, int);
|
||||
field public static final int CONTENT_TYPE_DOCUMENT = 0; // 0x0
|
||||
@@ -18724,12 +18725,18 @@ package android.print {
|
||||
}
|
||||
|
||||
public static final class PrintDocumentInfo.Builder {
|
||||
ctor public PrintDocumentInfo.Builder();
|
||||
ctor public PrintDocumentInfo.Builder(java.lang.String);
|
||||
method public android.print.PrintDocumentInfo create();
|
||||
method public android.print.PrintDocumentInfo.Builder setContentType(int);
|
||||
method public android.print.PrintDocumentInfo.Builder setPageCount(int);
|
||||
}
|
||||
|
||||
public final class PrintFileDocumentAdapter extends android.print.PrintDocumentAdapter {
|
||||
ctor public PrintFileDocumentAdapter(android.content.Context, java.io.File, android.print.PrintDocumentInfo);
|
||||
method public void onLayout(android.print.PrintAttributes, android.print.PrintAttributes, android.os.CancellationSignal, android.print.PrintDocumentAdapter.LayoutResultCallback, android.os.Bundle);
|
||||
method public void onWrite(android.print.PageRange[], java.io.FileDescriptor, android.os.CancellationSignal, android.print.PrintDocumentAdapter.WriteResultCallback);
|
||||
}
|
||||
|
||||
public final class PrintJob {
|
||||
method public void cancel();
|
||||
method public int getId();
|
||||
@@ -18758,50 +18765,66 @@ package android.print {
|
||||
|
||||
public final class PrintManager {
|
||||
method public java.util.List<android.print.PrintJob> getPrintJobs();
|
||||
method public android.print.PrintJob print(java.lang.String, java.io.File, android.print.PrintAttributes);
|
||||
method public android.print.PrintJob print(java.lang.String, java.io.File, android.print.PrintDocumentInfo, android.print.PrintAttributes);
|
||||
method public android.print.PrintJob print(java.lang.String, android.print.PrintDocumentAdapter, android.print.PrintAttributes);
|
||||
}
|
||||
|
||||
public final class PrinterId implements android.os.Parcelable {
|
||||
method public int describeContents();
|
||||
method public java.lang.String getPrinterName();
|
||||
method public void writeToParcel(android.os.Parcel, int);
|
||||
field public static final android.os.Parcelable.Creator CREATOR;
|
||||
}
|
||||
|
||||
public final class PrinterInfo implements android.os.Parcelable {
|
||||
public final class PrinterCapabilitiesInfo implements android.os.Parcelable {
|
||||
method public int describeContents();
|
||||
method public int getColorModes();
|
||||
method public void getDefaults(android.print.PrintAttributes);
|
||||
method public int getDuplexModes();
|
||||
method public int getFittingModes();
|
||||
method public android.print.PrinterId getId();
|
||||
method public java.util.List<android.print.PrintAttributes.Tray> getInputTrays();
|
||||
method public java.util.List<android.print.PrintAttributes.MediaSize> getMediaSizes();
|
||||
method public android.print.PrintAttributes.Margins getMinMargins();
|
||||
method public int getOrientations();
|
||||
method public java.util.List<android.print.PrintAttributes.Tray> getOutputTrays();
|
||||
method public java.util.List<android.print.PrintAttributes.Resolution> getResolutions();
|
||||
method public void writeToParcel(android.os.Parcel, int);
|
||||
field public static final android.os.Parcelable.Creator CREATOR;
|
||||
}
|
||||
|
||||
public static final class PrinterCapabilitiesInfo.Builder {
|
||||
ctor public PrinterCapabilitiesInfo.Builder(android.print.PrinterId);
|
||||
method public android.print.PrinterCapabilitiesInfo.Builder addInputTray(android.print.PrintAttributes.Tray, boolean);
|
||||
method public android.print.PrinterCapabilitiesInfo.Builder addMediaSize(android.print.PrintAttributes.MediaSize, boolean);
|
||||
method public android.print.PrinterCapabilitiesInfo.Builder addOutputTray(android.print.PrintAttributes.Tray, boolean);
|
||||
method public android.print.PrinterCapabilitiesInfo.Builder addResolution(android.print.PrintAttributes.Resolution, boolean);
|
||||
method public android.print.PrinterCapabilitiesInfo create();
|
||||
method public android.print.PrinterCapabilitiesInfo.Builder setColorModes(int, int);
|
||||
method public android.print.PrinterCapabilitiesInfo.Builder setDuplexModes(int, int);
|
||||
method public android.print.PrinterCapabilitiesInfo.Builder setFittingModes(int, int);
|
||||
method public android.print.PrinterCapabilitiesInfo.Builder setMinMargins(android.print.PrintAttributes.Margins, android.print.PrintAttributes.Margins);
|
||||
method public android.print.PrinterCapabilitiesInfo.Builder setOrientations(int, int);
|
||||
}
|
||||
|
||||
public final class PrinterId implements android.os.Parcelable {
|
||||
method public int describeContents();
|
||||
method public java.lang.String getLocalId();
|
||||
method public void writeToParcel(android.os.Parcel, int);
|
||||
field public static final android.os.Parcelable.Creator CREATOR;
|
||||
}
|
||||
|
||||
public final class PrinterInfo implements android.os.Parcelable {
|
||||
method public int describeContents();
|
||||
method public android.print.PrinterCapabilitiesInfo getCapabilities();
|
||||
method public java.lang.String getDescription();
|
||||
method public android.print.PrinterId getId();
|
||||
method public java.lang.String getName();
|
||||
method public int getStatus();
|
||||
method public boolean hasAllRequiredAttributes();
|
||||
method public void writeToParcel(android.os.Parcel, int);
|
||||
field public static final android.os.Parcelable.Creator CREATOR;
|
||||
field public static final int STATUS_READY = 1; // 0x1
|
||||
}
|
||||
|
||||
public static final class PrinterInfo.Builder {
|
||||
ctor public PrinterInfo.Builder(android.print.PrinterId);
|
||||
method public android.print.PrinterInfo.Builder addInputTray(android.print.PrintAttributes.Tray, boolean);
|
||||
method public android.print.PrinterInfo.Builder addMediaSize(android.print.PrintAttributes.MediaSize, boolean);
|
||||
method public android.print.PrinterInfo.Builder addOutputTray(android.print.PrintAttributes.Tray, boolean);
|
||||
method public android.print.PrinterInfo.Builder addResolution(android.print.PrintAttributes.Resolution, boolean);
|
||||
ctor public PrinterInfo.Builder(android.print.PrinterId, java.lang.String, int);
|
||||
ctor public PrinterInfo.Builder(android.print.PrinterInfo);
|
||||
method public android.print.PrinterInfo create();
|
||||
method public android.print.PrinterInfo.Builder setColorModes(int, int);
|
||||
method public android.print.PrinterInfo.Builder setDuplexModes(int, int);
|
||||
method public android.print.PrinterInfo.Builder setFittingModes(int, int);
|
||||
method public android.print.PrinterInfo.Builder setMinMargins(android.print.PrintAttributes.Margins, android.print.PrintAttributes.Margins);
|
||||
method public android.print.PrinterInfo.Builder setOrientations(int, int);
|
||||
method public android.print.PrinterInfo.Builder setStatus(int);
|
||||
method public android.print.PrinterInfo.Builder setCapabilities(android.print.PrinterCapabilitiesInfo);
|
||||
method public android.print.PrinterInfo.Builder setDescription(java.lang.String);
|
||||
method public android.print.PrinterInfo.Builder setName(java.lang.String);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -18853,6 +18876,9 @@ package android.printservice {
|
||||
method public android.printservice.PrintDocument getDocument();
|
||||
method public int getId();
|
||||
method public android.print.PrintJobInfo getInfo();
|
||||
method public boolean isCancelled();
|
||||
method public boolean isCompleted();
|
||||
method public boolean isFailed();
|
||||
method public boolean isQueued();
|
||||
method public boolean isStarted();
|
||||
method public boolean setTag(java.lang.String);
|
||||
@@ -18861,23 +18887,30 @@ package android.printservice {
|
||||
|
||||
public abstract class PrintService extends android.app.Service {
|
||||
ctor public PrintService();
|
||||
method public final void addDiscoveredPrinters(java.util.List<android.print.PrinterInfo>);
|
||||
method protected final void attachBaseContext(android.content.Context);
|
||||
method public final android.print.PrinterId generatePrinterId(java.lang.String);
|
||||
method public final java.util.List<android.printservice.PrintJob> getPrintJobs();
|
||||
method public final java.util.List<android.printservice.PrintJob> getActivePrintJobs();
|
||||
method public final android.os.IBinder onBind(android.content.Intent);
|
||||
method protected void onConnected();
|
||||
method protected abstract android.printservice.PrinterDiscoverySession onCreatePrinterDiscoverySession();
|
||||
method protected void onDisconnected();
|
||||
method protected abstract void onPrintJobQueued(android.printservice.PrintJob);
|
||||
method protected void onRequestCancelPrintJob(android.printservice.PrintJob);
|
||||
method protected void onRequestUpdatePrinters(java.util.List<android.print.PrinterId>);
|
||||
method protected abstract void onStartPrinterDiscovery();
|
||||
method protected abstract void onStopPrinterDiscovery();
|
||||
method public final void removeDiscoveredPrinters(java.util.List<android.print.PrinterId>);
|
||||
method public final void updateDiscoveredPrinters(java.util.List<android.print.PrinterInfo>);
|
||||
method protected abstract void onRequestCancelPrintJob(android.printservice.PrintJob);
|
||||
field public static final java.lang.String SERVICE_INTERFACE = "android.printservice.PrintService";
|
||||
field public static final java.lang.String SERVICE_META_DATA = "android.printservice";
|
||||
}
|
||||
|
||||
public abstract class PrinterDiscoverySession {
|
||||
ctor public PrinterDiscoverySession(android.content.Context);
|
||||
method public final void addPrinters(java.util.List<android.print.PrinterInfo>);
|
||||
method public final boolean isClosed();
|
||||
method public abstract void onClose();
|
||||
method public abstract void onOpen(java.util.List<android.print.PrinterId>);
|
||||
method public abstract void onRequestPrinterUpdate(android.print.PrinterId);
|
||||
method public final void removePrinters(java.util.List<android.print.PrinterId>);
|
||||
method public final void updatePrinters(java.util.List<android.print.PrinterInfo>);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
package android.provider {
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
package android.print;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.print.IPrinterDiscoveryObserver;
|
||||
import android.print.IPrinterDiscoverySessionObserver;
|
||||
import android.print.PrinterId;
|
||||
import android.print.PrintJobInfo;
|
||||
|
||||
@@ -28,10 +28,8 @@ import android.print.PrintJobInfo;
|
||||
* @hide
|
||||
*/
|
||||
oneway interface IPrintSpoolerClient {
|
||||
void createPrinterDiscoverySession(IPrinterDiscoverySessionObserver observer);
|
||||
void onPrintJobQueued(in PrintJobInfo printJob);
|
||||
void onStartPrinterDiscovery(IPrinterDiscoveryObserver observer);
|
||||
void onStopPrinterDiscovery();
|
||||
void onRequestUpdatePrinters(in List<PrinterId> printerIds);
|
||||
void onAllPrintJobsForServiceHandled(in ComponentName printService);
|
||||
void onAllPrintJobsHandled();
|
||||
}
|
||||
|
||||
@@ -17,15 +17,14 @@
|
||||
package android.print;
|
||||
|
||||
import android.print.PrinterId;
|
||||
import android.print.PrinterInfo;
|
||||
|
||||
/**
|
||||
* Interface for observing printer discovery.
|
||||
* Interface for the controlling part of a printer discovery session.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
oneway interface IPrinterDiscoveryObserver {
|
||||
void onPrintersAdded(in List<PrinterInfo> printers);
|
||||
void onPrintersRemoved(in List<PrinterId> printers);
|
||||
void onPrintersUpdated(in List<PrinterInfo> printers);
|
||||
oneway interface IPrinterDiscoverySessionController {
|
||||
void open(in List<PrinterId> priorityList);
|
||||
void requestPrinterUpdate(in PrinterId printerId);
|
||||
void close();
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 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.print.IPrinterDiscoverySessionController;
|
||||
import android.print.PrinterId;
|
||||
import android.print.PrinterInfo;
|
||||
|
||||
/**
|
||||
* Interface for the observing part of a printer discovery session.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
oneway interface IPrinterDiscoverySessionObserver {
|
||||
void setController(IPrinterDiscoverySessionController controller);
|
||||
void onPrintersAdded(in List<PrinterInfo> printers);
|
||||
void onPrintersRemoved(in List<PrinterId> printerIds);
|
||||
void onPrintersUpdated(in List<PrinterInfo> printerIds);
|
||||
}
|
||||
@@ -931,7 +931,7 @@ public final class PrintAttributes implements Parcelable {
|
||||
}
|
||||
|
||||
private final String mId;
|
||||
private final CharSequence mLabel;
|
||||
private final String mLabel;
|
||||
private final int mWidthMils;
|
||||
private final int mHeightMils;
|
||||
|
||||
@@ -948,7 +948,7 @@ public final class PrintAttributes implements Parcelable {
|
||||
* @throws IllegalArgumentException If the widthMils is less than or equal to zero.
|
||||
* @throws IllegalArgumentException If the heightMils is less than or equal to zero.
|
||||
*/
|
||||
public MediaSize(String id, CharSequence label, int widthMils, int heightMils) {
|
||||
public MediaSize(String id, String label, int widthMils, int heightMils) {
|
||||
if (TextUtils.isEmpty(id)) {
|
||||
throw new IllegalArgumentException("id cannot be empty.");
|
||||
}
|
||||
@@ -983,7 +983,7 @@ public final class PrintAttributes implements Parcelable {
|
||||
*
|
||||
* @return The human readable label.
|
||||
*/
|
||||
public CharSequence getLabel() {
|
||||
public String getLabel() {
|
||||
return mLabel;
|
||||
}
|
||||
|
||||
@@ -1007,7 +1007,7 @@ public final class PrintAttributes implements Parcelable {
|
||||
|
||||
void writeToParcel(Parcel parcel) {
|
||||
parcel.writeString(mId);
|
||||
parcel.writeCharSequence(mLabel);
|
||||
parcel.writeString(mLabel);
|
||||
parcel.writeInt(mWidthMils);
|
||||
parcel.writeInt(mHeightMils);
|
||||
}
|
||||
@@ -1015,7 +1015,7 @@ public final class PrintAttributes implements Parcelable {
|
||||
static MediaSize createFromParcel(Parcel parcel) {
|
||||
return new MediaSize(
|
||||
parcel.readString(),
|
||||
parcel.readCharSequence(),
|
||||
parcel.readString(),
|
||||
parcel.readInt(),
|
||||
parcel.readInt());
|
||||
}
|
||||
@@ -1076,7 +1076,7 @@ public final class PrintAttributes implements Parcelable {
|
||||
*/
|
||||
public static final class Resolution {
|
||||
private final String mId;
|
||||
private final CharSequence mLabel;
|
||||
private final String mLabel;
|
||||
private final int mHorizontalDpi;
|
||||
private final int mVerticalDpi;
|
||||
|
||||
@@ -1093,7 +1093,7 @@ public final class PrintAttributes implements Parcelable {
|
||||
* @throws IllegalArgumentException If the horizontalDpi is less than or equal to zero.
|
||||
* @throws IllegalArgumentException If the verticalDpi is less than or equal to zero.
|
||||
*/
|
||||
public Resolution(String id, CharSequence label, int horizontalDpi, int verticalDpi) {
|
||||
public Resolution(String id, String label, int horizontalDpi, int verticalDpi) {
|
||||
if (TextUtils.isEmpty(id)) {
|
||||
throw new IllegalArgumentException("id cannot be empty.");
|
||||
}
|
||||
@@ -1128,7 +1128,7 @@ public final class PrintAttributes implements Parcelable {
|
||||
*
|
||||
* @return The human readable label.
|
||||
*/
|
||||
public CharSequence getLabel() {
|
||||
public String getLabel() {
|
||||
return mLabel;
|
||||
}
|
||||
|
||||
@@ -1152,7 +1152,7 @@ public final class PrintAttributes implements Parcelable {
|
||||
|
||||
void writeToParcel(Parcel parcel) {
|
||||
parcel.writeString(mId);
|
||||
parcel.writeCharSequence(mLabel);
|
||||
parcel.writeString(mLabel);
|
||||
parcel.writeInt(mHorizontalDpi);
|
||||
parcel.writeInt(mVerticalDpi);
|
||||
}
|
||||
@@ -1160,7 +1160,7 @@ public final class PrintAttributes implements Parcelable {
|
||||
static Resolution createFromParcel(Parcel parcel) {
|
||||
return new Resolution(
|
||||
parcel.readString(),
|
||||
parcel.readCharSequence(),
|
||||
parcel.readString(),
|
||||
parcel.readInt(),
|
||||
parcel.readInt());
|
||||
}
|
||||
@@ -1364,7 +1364,7 @@ public final class PrintAttributes implements Parcelable {
|
||||
*/
|
||||
public static final class Tray {
|
||||
private final String mId;
|
||||
private final CharSequence mLabel;
|
||||
private final String mLabel;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
@@ -1375,7 +1375,7 @@ public final class PrintAttributes implements Parcelable {
|
||||
* @throws IllegalArgumentException If the id is empty.
|
||||
* @throws IllegalArgumentException If the label is empty.
|
||||
*/
|
||||
public Tray(String id, CharSequence label) {
|
||||
public Tray(String id, String label) {
|
||||
if (TextUtils.isEmpty(id)) {
|
||||
throw new IllegalArgumentException("id cannot be empty.");
|
||||
}
|
||||
@@ -1400,19 +1400,19 @@ public final class PrintAttributes implements Parcelable {
|
||||
*
|
||||
* @return The human readable label.
|
||||
*/
|
||||
public CharSequence getLabel() {
|
||||
public String getLabel() {
|
||||
return mLabel;
|
||||
}
|
||||
|
||||
void writeToParcel(Parcel parcel) {
|
||||
parcel.writeString(mId);
|
||||
parcel.writeCharSequence(mLabel);
|
||||
parcel.writeString(mLabel);
|
||||
}
|
||||
|
||||
static Tray createFromParcel(Parcel parcel) {
|
||||
return new Tray(
|
||||
parcel.readString(),
|
||||
parcel.readCharSequence());
|
||||
parcel.readString());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1457,7 +1457,7 @@ public final class PrintAttributes implements Parcelable {
|
||||
}
|
||||
}
|
||||
|
||||
private static String duplexModeToString(int duplexMode) {
|
||||
static String duplexModeToString(int duplexMode) {
|
||||
switch (duplexMode) {
|
||||
case DUPLEX_MODE_NONE: {
|
||||
return "DUPLEX_MODE_NONE";
|
||||
@@ -1473,7 +1473,7 @@ public final class PrintAttributes implements Parcelable {
|
||||
}
|
||||
}
|
||||
|
||||
private static String colorModeToString(int colorMode) {
|
||||
static String colorModeToString(int colorMode) {
|
||||
switch (colorMode) {
|
||||
case COLOR_MODE_MONOCHROME: {
|
||||
return "COLOR_MODE_MONOCHROME";
|
||||
@@ -1486,7 +1486,7 @@ public final class PrintAttributes implements Parcelable {
|
||||
}
|
||||
}
|
||||
|
||||
private static String orientationToString(int orientation) {
|
||||
static String orientationToString(int orientation) {
|
||||
switch (orientation) {
|
||||
case ORIENTATION_PORTRAIT: {
|
||||
return "ORIENTATION_PORTRAIT";
|
||||
@@ -1499,7 +1499,7 @@ public final class PrintAttributes implements Parcelable {
|
||||
}
|
||||
}
|
||||
|
||||
private static String fittingModeToString(int fittingMode) {
|
||||
static String fittingModeToString(int fittingMode) {
|
||||
switch (fittingMode) {
|
||||
case FITTING_MODE_NONE: {
|
||||
return "FITTING_MODE_NONE";
|
||||
|
||||
@@ -18,6 +18,7 @@ package android.print;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.text.TextUtils;
|
||||
|
||||
/**
|
||||
* This class encapsulates information about a printed document.
|
||||
@@ -44,6 +45,7 @@ public final class PrintDocumentInfo implements Parcelable {
|
||||
*/
|
||||
public static final int CONTENT_TYPE_PHOTO = 1;
|
||||
|
||||
private String mName;
|
||||
private int mPageCount;
|
||||
private int mContentType;
|
||||
|
||||
@@ -61,6 +63,7 @@ public final class PrintDocumentInfo implements Parcelable {
|
||||
* @param Prototype from which to clone.
|
||||
*/
|
||||
private PrintDocumentInfo(PrintDocumentInfo prototype) {
|
||||
mName = prototype.mName;
|
||||
mPageCount = prototype.mPageCount;
|
||||
mContentType = prototype.mContentType;
|
||||
}
|
||||
@@ -71,10 +74,20 @@ public final class PrintDocumentInfo implements Parcelable {
|
||||
* @param parcel Data from which to initialize.
|
||||
*/
|
||||
private PrintDocumentInfo(Parcel parcel) {
|
||||
mName = parcel.readString();
|
||||
mPageCount = parcel.readInt();
|
||||
mContentType = parcel.readInt();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the document name.
|
||||
*
|
||||
* @return The document name.
|
||||
*/
|
||||
public String getName() {
|
||||
return mName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the total number of pages.
|
||||
*
|
||||
@@ -106,6 +119,7 @@ public final class PrintDocumentInfo implements Parcelable {
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel parcel, int flags) {
|
||||
parcel.writeString(mName);
|
||||
parcel.writeInt(mPageCount);
|
||||
parcel.writeInt(mContentType);
|
||||
}
|
||||
@@ -114,6 +128,7 @@ public final class PrintDocumentInfo implements Parcelable {
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((mName != null) ? mName.hashCode() : 0);
|
||||
result = prime * result + mContentType;
|
||||
result = prime * result + mPageCount;
|
||||
return result;
|
||||
@@ -131,6 +146,9 @@ public final class PrintDocumentInfo implements Parcelable {
|
||||
return false;
|
||||
}
|
||||
PrintDocumentInfo other = (PrintDocumentInfo) obj;
|
||||
if (!TextUtils.equals(mName, other.mName)) {
|
||||
return false;
|
||||
}
|
||||
if (mContentType != other.mContentType) {
|
||||
return false;
|
||||
}
|
||||
@@ -144,17 +162,47 @@ public final class PrintDocumentInfo implements Parcelable {
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("PrintDocumentInfo{");
|
||||
builder.append("pageCount: ").append(mPageCount);
|
||||
builder.append(", contentType: ").append(mContentType);
|
||||
builder.append("name=").append(mName);
|
||||
builder.append(", pageCount=").append(mPageCount);
|
||||
builder.append(", contentType=").append(contentTyepToString(mContentType));
|
||||
builder.append("}");
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
private String contentTyepToString(int contentType) {
|
||||
switch (contentType) {
|
||||
case CONTENT_TYPE_DOCUMENT: {
|
||||
return "CONTENT_TYPE_DOCUMENT";
|
||||
}
|
||||
case CONTENT_TYPE_PHOTO: {
|
||||
return "CONTENT_TYPE_PHOTO";
|
||||
}
|
||||
default: {
|
||||
return "CONTENT_TYPE_UNKNOWN";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder for creating an {@link PrintDocumentInfo}.
|
||||
*/
|
||||
public static final class Builder {
|
||||
private final PrintDocumentInfo mPrototype = new PrintDocumentInfo();
|
||||
private final PrintDocumentInfo mPrototype;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param name The document name. Cannot be empty.
|
||||
*
|
||||
* @throws IllegalArgumentException If the name is empty.
|
||||
*/
|
||||
public Builder(String name) {
|
||||
if (TextUtils.isEmpty(name)) {
|
||||
throw new IllegalArgumentException("name cannot be empty");
|
||||
}
|
||||
mPrototype = new PrintDocumentInfo();
|
||||
mPrototype.mName = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the total number of pages.
|
||||
|
||||
@@ -36,34 +36,48 @@ import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
* Adapter for printing files.
|
||||
* Adapter for printing files. This class could be useful if you
|
||||
* want to print a file and intercept when the system is ready
|
||||
* spooling the data, so you can deleted the file if it is a
|
||||
* temporary one.
|
||||
*/
|
||||
final class FileDocumentAdapter extends PrintDocumentAdapter {
|
||||
public final class PrintFileDocumentAdapter extends PrintDocumentAdapter {
|
||||
|
||||
private static final String LOG_TAG = "FileDocumentAdapter";
|
||||
private static final String LOG_TAG = "PrintedFileDocumentAdapter";
|
||||
|
||||
private final Context mContext;
|
||||
|
||||
private final File mFile;
|
||||
|
||||
private final PrintDocumentInfo mDocumentInfo;
|
||||
|
||||
private WriteFileAsyncTask mWriteFileAsyncTask;
|
||||
|
||||
public FileDocumentAdapter(Context context, File file) {
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param context Context for accessing resources.
|
||||
* @param file The file to print.
|
||||
* @param documentInfo The information about the printed file.
|
||||
*/
|
||||
public PrintFileDocumentAdapter(Context context, File file,
|
||||
PrintDocumentInfo documentInfo) {
|
||||
if (file == null) {
|
||||
throw new IllegalArgumentException("File cannot be null!");
|
||||
}
|
||||
if (documentInfo == null) {
|
||||
throw new IllegalArgumentException("documentInfo cannot be null!");
|
||||
}
|
||||
mContext = context;
|
||||
mFile = file;
|
||||
mDocumentInfo = documentInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLayout(PrintAttributes oldAttributes, PrintAttributes newAttributes,
|
||||
CancellationSignal cancellationSignal, LayoutResultCallback callback,
|
||||
Bundle metadata) {
|
||||
// TODO: When we have a PDF rendering library we should query the page count.
|
||||
PrintDocumentInfo info = new PrintDocumentInfo.Builder()
|
||||
.setPageCount(PrintDocumentInfo.PAGE_COUNT_UNKNOWN).create();
|
||||
callback.onLayoutFinished(info, false);
|
||||
callback.onLayoutFinished(mDocumentInfo, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -109,6 +109,9 @@ public final class PrintJobInfo implements Parcelable {
|
||||
/** The unique id of the printer. */
|
||||
private PrinterId mPrinterId;
|
||||
|
||||
/** The name of the printer - internally used */
|
||||
private String mPrinterName;
|
||||
|
||||
/** The status of the print job. */
|
||||
private int mState;
|
||||
|
||||
@@ -146,6 +149,7 @@ public final class PrintJobInfo implements Parcelable {
|
||||
mId = other.mId;
|
||||
mLabel = other.mLabel;
|
||||
mPrinterId = other.mPrinterId;
|
||||
mPrinterName = other.mPrinterName;
|
||||
mState = other.mState;
|
||||
mAppId = other.mAppId;
|
||||
mUserId = other.mUserId;
|
||||
@@ -161,6 +165,7 @@ public final class PrintJobInfo implements Parcelable {
|
||||
mId = parcel.readInt();
|
||||
mLabel = parcel.readCharSequence();
|
||||
mPrinterId = parcel.readParcelable(null);
|
||||
mPrinterName = parcel.readString();
|
||||
mState = parcel.readInt();
|
||||
mAppId = parcel.readInt();
|
||||
mUserId = parcel.readInt();
|
||||
@@ -244,6 +249,28 @@ public final class PrintJobInfo implements Parcelable {
|
||||
mPrinterId = printerId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of the target printer.
|
||||
*
|
||||
* @return The printer name.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public String getPrinterName() {
|
||||
return mPrinterName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the name of the target printer.
|
||||
*
|
||||
* @param printerName The printer name.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public void setPrinterName(String printerName) {
|
||||
mPrinterName = printerName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current job state.
|
||||
*
|
||||
@@ -445,6 +472,7 @@ public final class PrintJobInfo implements Parcelable {
|
||||
parcel.writeInt(mId);
|
||||
parcel.writeCharSequence(mLabel);
|
||||
parcel.writeParcelable(mPrinterId, flags);
|
||||
parcel.writeString(mPrinterName);
|
||||
parcel.writeInt(mState);
|
||||
parcel.writeInt(mAppId);
|
||||
parcel.writeInt(mUserId);
|
||||
|
||||
@@ -161,13 +161,16 @@ public final class PrintManager {
|
||||
*
|
||||
* @param printJobName A name for the new print job.
|
||||
* @param pdfFile The PDF file to print.
|
||||
* @param documentInfo Information about the printed document.
|
||||
* @param attributes The default print job attributes.
|
||||
* @return The created print job.
|
||||
*
|
||||
* @see PrintJob
|
||||
*/
|
||||
public PrintJob print(String printJobName, File pdfFile, PrintAttributes attributes) {
|
||||
FileDocumentAdapter documentAdapter = new FileDocumentAdapter(mContext, pdfFile);
|
||||
public PrintJob print(String printJobName, File pdfFile, PrintDocumentInfo documentInfo,
|
||||
PrintAttributes attributes) {
|
||||
PrintFileDocumentAdapter documentAdapter = new PrintFileDocumentAdapter(
|
||||
mContext, pdfFile, documentInfo);
|
||||
return print(printJobName, documentAdapter, attributes);
|
||||
}
|
||||
|
||||
|
||||
19
core/java/android/print/PrinterCapabilitiesInfo.aidl
Normal file
19
core/java/android/print/PrinterCapabilitiesInfo.aidl
Normal file
@@ -0,0 +1,19 @@
|
||||
/**
|
||||
* 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;
|
||||
|
||||
parcelable PrinterCapabilitiesInfo;
|
||||
972
core/java/android/print/PrinterCapabilitiesInfo.java
Normal file
972
core/java/android/print/PrinterCapabilitiesInfo.java
Normal file
@@ -0,0 +1,972 @@
|
||||
/*
|
||||
* 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.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.print.PrintAttributes.Margins;
|
||||
import android.print.PrintAttributes.MediaSize;
|
||||
import android.print.PrintAttributes.Resolution;
|
||||
import android.print.PrintAttributes.Tray;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* This class represents the capabilities of a printer.
|
||||
*/
|
||||
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_INPUT_TRAY = 2;
|
||||
private static final int PROPERTY_OUTPUT_TRAY = 3;
|
||||
private static final int PROPERTY_DUPLEX_MODE = 4;
|
||||
private static final int PROPERTY_COLOR_MODE = 5;
|
||||
private static final int PROPERTY_FITTING_MODE = 6;
|
||||
private static final int PROPERTY_ORIENTATION = 7;
|
||||
private static final int PROPERTY_COUNT = 8;
|
||||
|
||||
private static final Margins DEFAULT_MARGINS = new Margins(0, 0, 0, 0);
|
||||
|
||||
private Margins mMinMargins = DEFAULT_MARGINS;
|
||||
private List<MediaSize> mMediaSizes;
|
||||
private List<Resolution> mResolutions;
|
||||
private List<Tray> mInputTrays;
|
||||
private List<Tray> mOutputTrays;
|
||||
|
||||
private int mDuplexModes;
|
||||
private int mColorModes;
|
||||
private int mFittingModes;
|
||||
private int mOrientations;
|
||||
|
||||
private final int[] mDefaults = new int[PROPERTY_COUNT];
|
||||
private Margins mDefaultMargins = DEFAULT_MARGINS;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public PrinterCapabilitiesInfo() {
|
||||
Arrays.fill(mDefaults, DEFAULT_UNDEFINED);
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public PrinterCapabilitiesInfo(PrinterCapabilitiesInfo prototype) {
|
||||
copyFrom(prototype);
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public void copyFrom(PrinterCapabilitiesInfo other) {
|
||||
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;
|
||||
}
|
||||
|
||||
if (other.mInputTrays != null) {
|
||||
if (mInputTrays != null) {
|
||||
mInputTrays.clear();
|
||||
mInputTrays.addAll(other.mInputTrays);
|
||||
} else {
|
||||
mInputTrays = new ArrayList<Tray>(other.mInputTrays);
|
||||
}
|
||||
} else {
|
||||
mInputTrays = null;
|
||||
}
|
||||
|
||||
if (other.mOutputTrays != null) {
|
||||
if (mOutputTrays != null) {
|
||||
mOutputTrays.clear();
|
||||
mOutputTrays.addAll(other.mOutputTrays);
|
||||
} else {
|
||||
mOutputTrays = new ArrayList<Tray>(other.mOutputTrays);
|
||||
}
|
||||
} else {
|
||||
mOutputTrays = null;
|
||||
}
|
||||
|
||||
mDuplexModes = other.mDuplexModes;
|
||||
mColorModes = other.mColorModes;
|
||||
mFittingModes = other.mFittingModes;
|
||||
mOrientations = other.mOrientations;
|
||||
|
||||
final int defaultCount = other.mDefaults.length;
|
||||
for (int i = 0; i < defaultCount; i++) {
|
||||
mDefaults[i] = other.mDefaults[i];
|
||||
}
|
||||
|
||||
mDefaultMargins = other.mDefaultMargins;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the supported media sizes.
|
||||
*
|
||||
* @return The media sizes.
|
||||
*/
|
||||
public List<MediaSize> getMediaSizes() {
|
||||
return mMediaSizes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the supported resolutions.
|
||||
*
|
||||
* @return The resolutions.
|
||||
*/
|
||||
public List<Resolution> getResolutions() {
|
||||
return mResolutions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the minimal supported margins.
|
||||
*
|
||||
* @return The minimal margins.
|
||||
*/
|
||||
public Margins getMinMargins() {
|
||||
return mMinMargins;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the available input trays.
|
||||
*
|
||||
* @return The input trays.
|
||||
*/
|
||||
public List<Tray> getInputTrays() {
|
||||
return mInputTrays;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the available output trays.
|
||||
*
|
||||
* @return The output trays.
|
||||
*/
|
||||
public List<Tray> getOutputTrays() {
|
||||
return mOutputTrays;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the supported duplex modes.
|
||||
*
|
||||
* @return The duplex modes.
|
||||
*
|
||||
* @see PrintAttributes#DUPLEX_MODE_NONE
|
||||
* @see PrintAttributes#DUPLEX_MODE_LONG_EDGE
|
||||
* @see PrintAttributes#DUPLEX_MODE_SHORT_EDGE
|
||||
*/
|
||||
public int getDuplexModes() {
|
||||
return mDuplexModes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the supported color modes.
|
||||
*
|
||||
* @return The color modes.
|
||||
*
|
||||
* @see PrintAttributes#COLOR_MODE_COLOR
|
||||
* @see PrintAttributes#COLOR_MODE_MONOCHROME
|
||||
*/
|
||||
public int getColorModes() {
|
||||
return mColorModes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the supported fitting modes.
|
||||
*
|
||||
* @return The fitting modes.
|
||||
*
|
||||
* @see PrintAttributes#FITTING_MODE_NONE
|
||||
* @see PrintAttributes#FITTING_MODE_FIT_TO_PAGE
|
||||
*/
|
||||
public int getFittingModes() {
|
||||
return mFittingModes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the supported orientations.
|
||||
*
|
||||
* @return The orientations.
|
||||
*
|
||||
* @see PrintAttributes#ORIENTATION_PORTRAIT
|
||||
* @see PrintAttributes#ORIENTATION_LANDSCAPE
|
||||
*/
|
||||
public int getOrientations() {
|
||||
return mOrientations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the default print attributes.
|
||||
*
|
||||
* @param outAttributes The attributes to populated.
|
||||
*/
|
||||
public void getDefaults(PrintAttributes outAttributes) {
|
||||
outAttributes.clear();
|
||||
|
||||
outAttributes.setMargins(mDefaultMargins);
|
||||
|
||||
final int mediaSizeIndex = mDefaults[PROPERTY_MEDIA_SIZE];
|
||||
if (mediaSizeIndex >= 0) {
|
||||
outAttributes.setMediaSize(mMediaSizes.get(mediaSizeIndex));
|
||||
}
|
||||
|
||||
final int resolutionIndex = mDefaults[PROPERTY_RESOLUTION];
|
||||
if (resolutionIndex >= 0) {
|
||||
outAttributes.setResolution(mResolutions.get(resolutionIndex));
|
||||
}
|
||||
|
||||
final int inputTrayIndex = mDefaults[PROPERTY_INPUT_TRAY];
|
||||
if (inputTrayIndex >= 0) {
|
||||
outAttributes.setInputTray(mInputTrays.get(inputTrayIndex));
|
||||
}
|
||||
|
||||
final int outputTrayIndex = mDefaults[PROPERTY_OUTPUT_TRAY];
|
||||
if (outputTrayIndex >= 0) {
|
||||
outAttributes.setOutputTray(mOutputTrays.get(outputTrayIndex));
|
||||
}
|
||||
|
||||
final int duplexMode = mDefaults[PROPERTY_DUPLEX_MODE];
|
||||
if (duplexMode > 0) {
|
||||
outAttributes.setDuplexMode(duplexMode);
|
||||
}
|
||||
|
||||
final int colorMode = mDefaults[PROPERTY_COLOR_MODE];
|
||||
if (colorMode > 0) {
|
||||
outAttributes.setColorMode(colorMode);
|
||||
}
|
||||
|
||||
final int fittingMode = mDefaults[PROPERTY_FITTING_MODE];
|
||||
if (fittingMode > 0) {
|
||||
outAttributes.setFittingMode(fittingMode);
|
||||
}
|
||||
|
||||
final int orientation = mDefaults[PROPERTY_ORIENTATION];
|
||||
if (orientation > 0) {
|
||||
outAttributes.setOrientation(orientation);
|
||||
}
|
||||
}
|
||||
|
||||
private PrinterCapabilitiesInfo(Parcel parcel) {
|
||||
mMinMargins = readMargins(parcel);
|
||||
readMediaSizes(parcel);
|
||||
readResolutions(parcel);
|
||||
mInputTrays = readInputTrays(parcel);
|
||||
mOutputTrays = readOutputTrays(parcel);
|
||||
|
||||
mColorModes = parcel.readInt();
|
||||
mDuplexModes = parcel.readInt();
|
||||
mFittingModes = parcel.readInt();
|
||||
mOrientations = parcel.readInt();
|
||||
|
||||
readDefaults(parcel);
|
||||
mDefaultMargins = readMargins(parcel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel parcel, int flags) {
|
||||
writeMargins(mMinMargins, parcel);
|
||||
writeMediaSizes(parcel);
|
||||
writeResolutions(parcel);
|
||||
writeInputTrays(parcel);
|
||||
writeOutputTrays(parcel);
|
||||
|
||||
parcel.writeInt(mColorModes);
|
||||
parcel.writeInt(mDuplexModes);
|
||||
parcel.writeInt(mFittingModes);
|
||||
parcel.writeInt(mOrientations);
|
||||
|
||||
writeDefaults(parcel);
|
||||
writeMargins(mDefaultMargins, 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 + ((mInputTrays == null) ? 0 : mInputTrays.hashCode());
|
||||
result = prime * result + ((mOutputTrays == null) ? 0 : mOutputTrays.hashCode());
|
||||
result = prime * result + mColorModes;
|
||||
result = prime * result + mDuplexModes;
|
||||
result = prime * result + mFittingModes;
|
||||
result = prime * result + mOrientations;
|
||||
result = prime * result + Arrays.hashCode(mDefaults);
|
||||
result = prime * result + ((mDefaultMargins == null) ? 0 : mDefaultMargins.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(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 (mInputTrays == null) {
|
||||
if (other.mInputTrays != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!mInputTrays.equals(other.mInputTrays)) {
|
||||
return false;
|
||||
}
|
||||
if (mOutputTrays == null) {
|
||||
if (other.mOutputTrays != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!mOutputTrays.equals(other.mOutputTrays)) {
|
||||
return false;
|
||||
}
|
||||
if (mDuplexModes != other.mDuplexModes) {
|
||||
return false;
|
||||
}
|
||||
if (mColorModes != other.mColorModes) {
|
||||
return false;
|
||||
}
|
||||
if (mFittingModes != other.mFittingModes) {
|
||||
return false;
|
||||
}
|
||||
if (mOrientations != other.mOrientations) {
|
||||
return false;
|
||||
}
|
||||
if (!Arrays.equals(mDefaults, other.mDefaults)) {
|
||||
return false;
|
||||
}
|
||||
if (mDefaultMargins == null) {
|
||||
if (other.mDefaultMargins != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!mDefaultMargins.equals(other.mDefaultMargins)) {
|
||||
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(", inputTrays=").append(mInputTrays);
|
||||
builder.append(", outputTrays=").append(mOutputTrays);
|
||||
builder.append(", duplexModes=").append(duplexModesToString());
|
||||
builder.append(", colorModes=").append(colorModesToString());
|
||||
builder.append(", fittingModes=").append(fittingModesToString());
|
||||
builder.append(", orientations=").append(orientationsToString());
|
||||
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() > 0) {
|
||||
builder.append(", ");
|
||||
}
|
||||
builder.append(PrintAttributes.duplexModeToString(duplexMode));
|
||||
}
|
||||
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() > 0) {
|
||||
builder.append(", ");
|
||||
}
|
||||
builder.append(PrintAttributes.colorModeToString(colorMode));
|
||||
}
|
||||
builder.append(']');
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
private String fittingModesToString() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append('[');
|
||||
int fittingModes = mFittingModes;
|
||||
while (fittingModes != 0) {
|
||||
final int fittingMode = 1 << Integer.numberOfTrailingZeros(fittingModes);
|
||||
fittingModes &= ~fittingMode;
|
||||
if (builder.length() > 0) {
|
||||
builder.append(", ");
|
||||
}
|
||||
builder.append(PrintAttributes.fittingModeToString(fittingMode));
|
||||
}
|
||||
builder.append(']');
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
private String orientationsToString() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append('[');
|
||||
int orientations = mOrientations;
|
||||
while (orientations != 0) {
|
||||
final int orientation = 1 << Integer.numberOfTrailingZeros(orientations);
|
||||
orientations &= ~orientation;
|
||||
if (builder.length() > 0) {
|
||||
builder.append(", ");
|
||||
}
|
||||
builder.append(PrintAttributes.orientationToString(orientation));
|
||||
}
|
||||
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 writeInputTrays(Parcel parcel) {
|
||||
if (mInputTrays == null) {
|
||||
parcel.writeInt(0);
|
||||
return;
|
||||
}
|
||||
final int inputTrayCount = mInputTrays.size();
|
||||
parcel.writeInt(inputTrayCount);
|
||||
for (int i = 0; i < inputTrayCount; i++) {
|
||||
mInputTrays.get(i).writeToParcel(parcel);
|
||||
}
|
||||
}
|
||||
|
||||
private List<Tray> readInputTrays(Parcel parcel) {
|
||||
final int inputTrayCount = parcel.readInt();
|
||||
if (inputTrayCount <= 0) {
|
||||
return null;
|
||||
}
|
||||
List<Tray> inputTrays = new ArrayList<Tray>(inputTrayCount);
|
||||
for (int i = 0; i < inputTrayCount; i++) {
|
||||
inputTrays.add(Tray.createFromParcel(parcel));
|
||||
}
|
||||
return inputTrays;
|
||||
}
|
||||
|
||||
private void writeOutputTrays(Parcel parcel) {
|
||||
if (mOutputTrays == null) {
|
||||
parcel.writeInt(0);
|
||||
return;
|
||||
}
|
||||
final int outputTrayCount = mOutputTrays.size();
|
||||
parcel.writeInt(outputTrayCount);
|
||||
for (int i = 0; i < outputTrayCount; i++) {
|
||||
mOutputTrays.get(i).writeToParcel(parcel);
|
||||
}
|
||||
}
|
||||
|
||||
private List<Tray> readOutputTrays(Parcel parcel) {
|
||||
final int outputTrayCount = parcel.readInt();
|
||||
if (outputTrayCount <= 0) {
|
||||
return null;
|
||||
}
|
||||
List<Tray> outputTrays = new ArrayList<Tray>(outputTrayCount);
|
||||
for (int i = 0; i < outputTrayCount; i++) {
|
||||
outputTrays.add(Tray.createFromParcel(parcel));
|
||||
}
|
||||
return outputTrays;
|
||||
}
|
||||
|
||||
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 PrinterInfo}. 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 PrinterInfo}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 null.
|
||||
*
|
||||
* @throws IllegalArgumentException If the printer id is null.
|
||||
*/
|
||||
public Builder(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 Builder addMediaSize(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 Builder addResolution(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.
|
||||
* <p>
|
||||
* <strong>Required:</strong> No
|
||||
* </p>
|
||||
*
|
||||
* @param margins The margins.
|
||||
* @param defaultMargins The default margins.
|
||||
* @return This builder.
|
||||
*
|
||||
* @see PrintAttributes.Margins
|
||||
*/
|
||||
public Builder setMinMargins(Margins margins, Margins defaultMargins) {
|
||||
if (margins.getLeftMils() > defaultMargins.getLeftMils()
|
||||
|| margins.getTopMils() > defaultMargins.getTopMils()
|
||||
|| margins.getRightMils() < defaultMargins.getRightMils()
|
||||
|| margins.getBottomMils() < defaultMargins.getBottomMils()) {
|
||||
throw new IllegalArgumentException("Default margins"
|
||||
+ " cannot be outside of the min margins.");
|
||||
}
|
||||
mPrototype.mMinMargins = margins;
|
||||
mPrototype.mDefaultMargins = defaultMargins;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an input tray.
|
||||
* <p>
|
||||
* <strong>Required:</strong> No
|
||||
* </p>
|
||||
*
|
||||
* @param inputTray A tray.
|
||||
* @param isDefault Whether this is the default.
|
||||
* @return This builder.
|
||||
*
|
||||
* @throws IllegalArgumentException If set as default and there
|
||||
* is already a default.
|
||||
*
|
||||
* @see PrintAttributes.Tray
|
||||
*/
|
||||
public Builder addInputTray(Tray inputTray, boolean isDefault) {
|
||||
if (mPrototype.mInputTrays == null) {
|
||||
mPrototype.mInputTrays = new ArrayList<Tray>();
|
||||
}
|
||||
final int insertionIndex = mPrototype.mInputTrays.size();
|
||||
mPrototype.mInputTrays.add(inputTray);
|
||||
if (isDefault) {
|
||||
throwIfDefaultAlreadySpecified(PROPERTY_INPUT_TRAY);
|
||||
mPrototype.mDefaults[PROPERTY_INPUT_TRAY] = insertionIndex;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an output tray.
|
||||
* <p>
|
||||
* <strong>Required:</strong> No
|
||||
* </p>
|
||||
*
|
||||
* @param outputTray A tray.
|
||||
* @param isDefault Whether this is the default.
|
||||
* @return This builder.
|
||||
*
|
||||
* @throws IllegalArgumentException If set as default and there
|
||||
* is already a default.
|
||||
*
|
||||
* @see PrintAttributes.Tray
|
||||
*/
|
||||
public Builder addOutputTray(Tray outputTray, boolean isDefault) {
|
||||
if (mPrototype.mOutputTrays == null) {
|
||||
mPrototype.mOutputTrays = new ArrayList<Tray>();
|
||||
}
|
||||
final int insertionIndex = mPrototype.mOutputTrays.size();
|
||||
mPrototype.mOutputTrays.add(outputTray);
|
||||
if (isDefault) {
|
||||
throwIfDefaultAlreadySpecified(PROPERTY_OUTPUT_TRAY);
|
||||
mPrototype.mDefaults[PROPERTY_OUTPUT_TRAY] = insertionIndex;
|
||||
}
|
||||
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.
|
||||
*
|
||||
* @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 Builder setColorModes(int colorModes, int defaultColorMode) {
|
||||
int currentModes = colorModes;
|
||||
while (currentModes > 0) {
|
||||
final int currentMode = (1 << Integer.numberOfTrailingZeros(currentModes));
|
||||
currentModes &= ~currentMode;
|
||||
PrintAttributes.enforceValidColorMode(currentMode);
|
||||
}
|
||||
if ((colorModes & defaultColorMode) == 0) {
|
||||
throw new IllegalArgumentException("Default color mode not in color modes.");
|
||||
}
|
||||
PrintAttributes.enforceValidColorMode(colorModes);
|
||||
mPrototype.mColorModes = colorModes;
|
||||
mPrototype.mDefaults[PROPERTY_COLOR_MODE] = defaultColorMode;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set 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 Builder setDuplexModes(int duplexModes, int defaultDuplexMode) {
|
||||
int currentModes = duplexModes;
|
||||
while (currentModes > 0) {
|
||||
final int currentMode = (1 << Integer.numberOfTrailingZeros(currentModes));
|
||||
currentModes &= ~currentMode;
|
||||
PrintAttributes.enforceValidDuplexMode(currentMode);
|
||||
}
|
||||
if ((duplexModes & defaultDuplexMode) == 0) {
|
||||
throw new IllegalArgumentException("Default duplex mode not in duplex modes.");
|
||||
}
|
||||
PrintAttributes.enforceValidDuplexMode(defaultDuplexMode);
|
||||
mPrototype.mDuplexModes = duplexModes;
|
||||
mPrototype.mDefaults[PROPERTY_DUPLEX_MODE] = defaultDuplexMode;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the fitting modes.
|
||||
* <p>
|
||||
* <strong>Required:</strong> No
|
||||
* </p>
|
||||
*
|
||||
* @param fittingModes The fitting mode bit mask.
|
||||
* @param defaultFittingMode The default fitting mode.
|
||||
* @return This builder.
|
||||
*
|
||||
* @throws IllegalArgumentException If fitting modes contains an invalid
|
||||
* mode bit or if the default fitting mode is invalid.
|
||||
*
|
||||
* @see PrintAttributes#FITTING_MODE_NONE
|
||||
* @see PrintAttributes#FITTING_MODE_FIT_TO_PAGE
|
||||
*/
|
||||
public Builder setFittingModes(int fittingModes, int defaultFittingMode) {
|
||||
int currentModes = fittingModes;
|
||||
while (currentModes > 0) {
|
||||
final int currentMode = (1 << Integer.numberOfTrailingZeros(currentModes));
|
||||
currentModes &= ~currentMode;
|
||||
PrintAttributes.enfoceValidFittingMode(currentMode);
|
||||
}
|
||||
if ((fittingModes & defaultFittingMode) == 0) {
|
||||
throw new IllegalArgumentException("Default fitting mode not in fiting modes.");
|
||||
}
|
||||
PrintAttributes.enfoceValidFittingMode(defaultFittingMode);
|
||||
mPrototype.mFittingModes = fittingModes;
|
||||
mPrototype.mDefaults[PROPERTY_FITTING_MODE] = defaultFittingMode;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the orientations.
|
||||
* <p>
|
||||
* <strong>Required:</strong> Yes
|
||||
* </p>
|
||||
*
|
||||
* @param orientations The orientation bit mask.
|
||||
* @param defaultOrientation The default orientation.
|
||||
* @return This builder.
|
||||
*
|
||||
* @throws IllegalArgumentException If orientations contains an invalid
|
||||
* mode bit or if the default orientation is invalid.
|
||||
*
|
||||
* @see PrintAttributes#ORIENTATION_PORTRAIT
|
||||
* @see PrintAttributes#ORIENTATION_LANDSCAPE
|
||||
*/
|
||||
public Builder setOrientations(int orientations, int defaultOrientation) {
|
||||
int currentOrientaions = orientations;
|
||||
while (currentOrientaions > 0) {
|
||||
final int currentOrnt = (1 << Integer.numberOfTrailingZeros(currentOrientaions));
|
||||
currentOrientaions &= ~currentOrnt;
|
||||
PrintAttributes.enforceValidOrientation(currentOrnt);
|
||||
}
|
||||
if ((orientations & defaultOrientation) == 0) {
|
||||
throw new IllegalArgumentException("Default orientation not in orientations.");
|
||||
}
|
||||
PrintAttributes.enforceValidOrientation(defaultOrientation);
|
||||
mPrototype.mOrientations = orientations;
|
||||
mPrototype.mDefaults[PROPERTY_ORIENTATION] = defaultOrientation;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Crates a new {@link PrinterCapabilitiesInfo} enforcing that all
|
||||
* required properties have need specified. See individual methods
|
||||
* in this class for reference about required attributes.
|
||||
*
|
||||
* @return A new {@link PrinterCapabilitiesInfo}.
|
||||
*
|
||||
* @throws IllegalStateException If a required attribute was not specified.
|
||||
*/
|
||||
public PrinterCapabilitiesInfo create() {
|
||||
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.mOrientations == 0) {
|
||||
throw new IllegalStateException("No oprientation specified.");
|
||||
}
|
||||
if (mPrototype.mDefaults[PROPERTY_ORIENTATION] == DEFAULT_UNDEFINED) {
|
||||
throw new IllegalStateException("No default orientation specified.");
|
||||
}
|
||||
if (mPrototype.mMinMargins == null) {
|
||||
mPrototype.mMinMargins = new Margins(0, 0, 0, 0);
|
||||
}
|
||||
if (mPrototype.mDefaultMargins == null) {
|
||||
mPrototype.mDefaultMargins = mPrototype.mMinMargins;
|
||||
}
|
||||
return new PrinterCapabilitiesInfo(mPrototype);
|
||||
}
|
||||
|
||||
private void throwIfDefaultAlreadySpecified(int propertyIndex) {
|
||||
if (mPrototype.mDefaults[propertyIndex] != DEFAULT_UNDEFINED) {
|
||||
throw new IllegalArgumentException("Default already specified.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static final 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];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -28,24 +28,24 @@ public final class PrinterId implements Parcelable {
|
||||
|
||||
private final ComponentName mServiceName;
|
||||
|
||||
private final String mPrinterName;
|
||||
private final String mLocalId;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param serviceName The managing print service.
|
||||
* @param printerName The unique name within the managing service.
|
||||
* @param localId The locally unique id within the managing service.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public PrinterId(ComponentName serviceName, String printerName) {
|
||||
public PrinterId(ComponentName serviceName, String localId) {
|
||||
mServiceName = serviceName;
|
||||
mPrinterName = printerName;
|
||||
mLocalId = localId;
|
||||
}
|
||||
|
||||
private PrinterId(Parcel parcel) {
|
||||
mServiceName = parcel.readParcelable(null);
|
||||
mPrinterName = parcel.readString();
|
||||
mLocalId = parcel.readString();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -60,13 +60,13 @@ public final class PrinterId implements Parcelable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of this printer which is unique in the context
|
||||
* Gets the id of this printer which is unique in the context
|
||||
* of the print service that manages it.
|
||||
*
|
||||
* @return The printer name.
|
||||
*/
|
||||
public String getPrinterName() {
|
||||
return mPrinterName;
|
||||
public String getLocalId() {
|
||||
return mLocalId;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -77,7 +77,7 @@ public final class PrinterId implements Parcelable {
|
||||
@Override
|
||||
public void writeToParcel(Parcel parcel, int flags) {
|
||||
parcel.writeParcelable(mServiceName, flags);
|
||||
parcel.writeString(mPrinterName);
|
||||
parcel.writeString(mLocalId);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -99,7 +99,7 @@ public final class PrinterId implements Parcelable {
|
||||
} else if (!mServiceName.equals(other.mServiceName)) {
|
||||
return false;
|
||||
}
|
||||
if (!TextUtils.equals(mPrinterName, other.mPrinterName)) {
|
||||
if (!TextUtils.equals(mLocalId, other.mLocalId)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -111,7 +111,7 @@ public final class PrinterId implements Parcelable {
|
||||
int hashCode = 1;
|
||||
hashCode = prime * hashCode + ((mServiceName != null)
|
||||
? mServiceName.hashCode() : 1);
|
||||
hashCode = prime * hashCode + mPrinterName.hashCode();
|
||||
hashCode = prime * hashCode + mLocalId.hashCode();
|
||||
return hashCode;
|
||||
}
|
||||
|
||||
@@ -119,9 +119,8 @@ public final class PrinterId implements Parcelable {
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("PrinterId{");
|
||||
builder.append(mServiceName.flattenToString());
|
||||
builder.append(":");
|
||||
builder.append(mPrinterName);
|
||||
builder.append("serviceName=").append(mServiceName.flattenToString());
|
||||
builder.append(", localId=").append(mLocalId);
|
||||
builder.append('}');
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
@@ -18,67 +18,30 @@ package android.print;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.print.PrintAttributes.Margins;
|
||||
import android.print.PrintAttributes.MediaSize;
|
||||
import android.print.PrintAttributes.Resolution;
|
||||
import android.print.PrintAttributes.Tray;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import android.text.TextUtils;
|
||||
|
||||
/**
|
||||
* This class represents the description of a printer. A description
|
||||
* contains the printer id, human readable name, status, and available
|
||||
* options for various printer capabilities, such as media size, etc.
|
||||
* This class represents the description of a printer.
|
||||
*/
|
||||
public final class PrinterInfo 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_INPUT_TRAY = 2;
|
||||
private static final int PROPERTY_OUTPUT_TRAY = 3;
|
||||
private static final int PROPERTY_DUPLEX_MODE = 4;
|
||||
private static final int PROPERTY_COLOR_MODE = 5;
|
||||
private static final int PROPERTY_FITTING_MODE = 6;
|
||||
private static final int PROPERTY_ORIENTATION = 7;
|
||||
private static final int PROPERTY_COUNT = 8;
|
||||
|
||||
/** Printer status: the printer is ready to print. */
|
||||
public static final int STATUS_READY = 1;
|
||||
|
||||
private static final Margins DEFAULT_MARGINS = new Margins(0, 0, 0, 0);
|
||||
|
||||
// TODO: Add printer status constants.
|
||||
|
||||
private PrinterId mId;
|
||||
|
||||
private String mName;
|
||||
|
||||
private int mStatus;
|
||||
|
||||
private Margins mMinMargins = DEFAULT_MARGINS;
|
||||
private List<MediaSize> mMediaSizes;
|
||||
private List<Resolution> mResolutions;
|
||||
private List<Tray> mInputTrays;
|
||||
private List<Tray> mOutputTrays;
|
||||
private String mDescription;
|
||||
|
||||
private int mDuplexModes;
|
||||
private int mColorModes;
|
||||
private int mFittingModes;
|
||||
private int mOrientations;
|
||||
private PrinterCapabilitiesInfo mCapabilities;
|
||||
|
||||
private final int[] mDefaults = new int[PROPERTY_COUNT];
|
||||
private Margins mDefaultMargins = DEFAULT_MARGINS;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public PrinterInfo() {
|
||||
Arrays.fill(mDefaults, DEFAULT_UNDEFINED);
|
||||
private PrinterInfo() {
|
||||
/* do nothing */
|
||||
}
|
||||
|
||||
private PrinterInfo(PrinterInfo prototype) {
|
||||
@@ -90,63 +53,18 @@ public final class PrinterInfo implements Parcelable {
|
||||
*/
|
||||
public void copyFrom(PrinterInfo other) {
|
||||
mId = other.mId;
|
||||
mName = other.mName;
|
||||
mStatus = other.mStatus;
|
||||
|
||||
mMinMargins = other.mMinMargins;
|
||||
if (other.mMediaSizes != null) {
|
||||
if (mMediaSizes != null) {
|
||||
mMediaSizes.clear();
|
||||
mMediaSizes.addAll(other.mMediaSizes);
|
||||
mDescription = other.mDescription;
|
||||
if (other.mCapabilities != null) {
|
||||
if (mCapabilities != null) {
|
||||
mCapabilities.copyFrom(other.mCapabilities);
|
||||
} else {
|
||||
mMediaSizes = new ArrayList<MediaSize>(other.mMediaSizes);
|
||||
mCapabilities = new PrinterCapabilitiesInfo(other.mCapabilities);
|
||||
}
|
||||
} else {
|
||||
mMediaSizes = null;
|
||||
mCapabilities = null;
|
||||
}
|
||||
|
||||
if (other.mResolutions != null) {
|
||||
if (mResolutions != null) {
|
||||
mResolutions.clear();
|
||||
mResolutions.addAll(other.mResolutions);
|
||||
} else {
|
||||
mResolutions = new ArrayList<Resolution>(other.mResolutions);
|
||||
}
|
||||
} else {
|
||||
mResolutions = null;
|
||||
}
|
||||
|
||||
if (other.mInputTrays != null) {
|
||||
if (mInputTrays != null) {
|
||||
mInputTrays.clear();
|
||||
mInputTrays.addAll(other.mInputTrays);
|
||||
} else {
|
||||
mInputTrays = new ArrayList<Tray>(other.mInputTrays);
|
||||
}
|
||||
} else {
|
||||
mInputTrays = null;
|
||||
}
|
||||
|
||||
if (other.mOutputTrays != null) {
|
||||
if (mOutputTrays != null) {
|
||||
mOutputTrays.clear();
|
||||
mOutputTrays.addAll(other.mOutputTrays);
|
||||
} else {
|
||||
mOutputTrays = new ArrayList<Tray>(other.mOutputTrays);
|
||||
}
|
||||
} else {
|
||||
mOutputTrays = null;
|
||||
}
|
||||
|
||||
mDuplexModes = other.mDuplexModes;
|
||||
mColorModes = other.mColorModes;
|
||||
mFittingModes = other.mFittingModes;
|
||||
mOrientations = other.mOrientations;
|
||||
|
||||
final int defaultCount = other.mDefaults.length;
|
||||
for (int i = 0; i < defaultCount; i++) {
|
||||
mDefaults[i] = other.mDefaults[i];
|
||||
}
|
||||
mDefaultMargins = other.mDefaultMargins;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -159,7 +77,16 @@ public final class PrinterInfo implements Parcelable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the status of the printer.
|
||||
* Get the printer name.
|
||||
*
|
||||
* @return The printer name.
|
||||
*/
|
||||
public String getName() {
|
||||
return mName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the printer status.
|
||||
*
|
||||
* @return The status.
|
||||
*/
|
||||
@@ -168,184 +95,29 @@ public final class PrinterInfo implements Parcelable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the supported media sizes.
|
||||
* Gets the printer description.
|
||||
*
|
||||
* @return The supported media sizes.
|
||||
* @return The description.
|
||||
*/
|
||||
public List<MediaSize> getMediaSizes() {
|
||||
return mMediaSizes;
|
||||
public String getDescription() {
|
||||
return mDescription;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the supported resolutions.
|
||||
* Gets the printer capabilities.
|
||||
*
|
||||
* @return The supported resolutions.
|
||||
* @return The capabilities.
|
||||
*/
|
||||
public List<Resolution> getResolutions() {
|
||||
return mResolutions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the minimal supported margins.
|
||||
*
|
||||
* @return The minimal margins.
|
||||
*/
|
||||
public Margins getMinMargins() {
|
||||
return mMinMargins;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the available input trays.
|
||||
*
|
||||
* @return The input trays.
|
||||
*/
|
||||
public List<Tray> getInputTrays() {
|
||||
return mInputTrays;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the available output trays.
|
||||
*
|
||||
* @return The output trays.
|
||||
*/
|
||||
public List<Tray> getOutputTrays() {
|
||||
return mOutputTrays;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the supported duplex modes.
|
||||
*
|
||||
* @return The duplex modes.
|
||||
*
|
||||
* @see PrintAttributes#DUPLEX_MODE_NONE
|
||||
* @see PrintAttributes#DUPLEX_MODE_LONG_EDGE
|
||||
* @see PrintAttributes#DUPLEX_MODE_SHORT_EDGE
|
||||
*/
|
||||
public int getDuplexModes() {
|
||||
return mDuplexModes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the supported color modes.
|
||||
*
|
||||
* @return The color modes.
|
||||
*
|
||||
* @see PrintAttributes#COLOR_MODE_COLOR
|
||||
* @see PrintAttributes#COLOR_MODE_MONOCHROME
|
||||
*/
|
||||
public int getColorModes() {
|
||||
return mColorModes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the supported fitting modes.
|
||||
*
|
||||
* @return The fitting modes.
|
||||
*
|
||||
* @see PrintAttributes#FITTING_MODE_NONE
|
||||
* @see PrintAttributes#FITTING_MODE_FIT_TO_PAGE
|
||||
*/
|
||||
public int getFittingModes() {
|
||||
return mFittingModes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the supported orientations.
|
||||
*
|
||||
* @return The orientations.
|
||||
*
|
||||
* @see PrintAttributes#ORIENTATION_PORTRAIT
|
||||
* @see PrintAttributes#ORIENTATION_LANDSCAPE
|
||||
*/
|
||||
public int getOrientations() {
|
||||
return mOrientations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the default print attributes.
|
||||
*
|
||||
* @param outAttributes The attributes to populated.
|
||||
*/
|
||||
public void getDefaults(PrintAttributes outAttributes) {
|
||||
outAttributes.clear();
|
||||
|
||||
outAttributes.setMargins(mDefaultMargins);
|
||||
|
||||
final int mediaSizeIndex = mDefaults[PROPERTY_MEDIA_SIZE];
|
||||
if (mediaSizeIndex >= 0) {
|
||||
outAttributes.setMediaSize(mMediaSizes.get(mediaSizeIndex));
|
||||
}
|
||||
|
||||
final int resolutionIndex = mDefaults[PROPERTY_RESOLUTION];
|
||||
if (resolutionIndex >= 0) {
|
||||
outAttributes.setResolution(mResolutions.get(resolutionIndex));
|
||||
}
|
||||
|
||||
final int inputTrayIndex = mDefaults[PROPERTY_INPUT_TRAY];
|
||||
if (inputTrayIndex >= 0) {
|
||||
outAttributes.setInputTray(mInputTrays.get(inputTrayIndex));
|
||||
}
|
||||
|
||||
final int outputTrayIndex = mDefaults[PROPERTY_OUTPUT_TRAY];
|
||||
if (outputTrayIndex >= 0) {
|
||||
outAttributes.setOutputTray(mOutputTrays.get(outputTrayIndex));
|
||||
}
|
||||
|
||||
final int duplexMode = mDefaults[PROPERTY_DUPLEX_MODE];
|
||||
if (duplexMode > 0) {
|
||||
outAttributes.setDuplexMode(duplexMode);
|
||||
}
|
||||
|
||||
final int colorMode = mDefaults[PROPERTY_COLOR_MODE];
|
||||
if (colorMode > 0) {
|
||||
outAttributes.setColorMode(mColorModes & colorMode);
|
||||
}
|
||||
|
||||
final int fittingMode = mDefaults[PROPERTY_FITTING_MODE];
|
||||
if (fittingMode > 0) {
|
||||
outAttributes.setFittingMode(fittingMode);
|
||||
}
|
||||
|
||||
final int orientation = mDefaults[PROPERTY_ORIENTATION];
|
||||
if (orientation > 0) {
|
||||
outAttributes.setOrientation(orientation);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether this printer info is fully-populated, i.e. whether
|
||||
* all required attributes are specified. See the {@link Builder}
|
||||
* documentation for which attributes are required.
|
||||
*
|
||||
* @return Whether this info has all required attributes.
|
||||
*/
|
||||
public boolean hasAllRequiredAttributes() {
|
||||
return (mMediaSizes != null && !mMediaSizes.isEmpty()
|
||||
&& mResolutions != null && !mResolutions.isEmpty()
|
||||
&& mColorModes != 0 || mOrientations != 0
|
||||
&& mDefaults[PROPERTY_MEDIA_SIZE] != DEFAULT_UNDEFINED
|
||||
&& mDefaults[PROPERTY_RESOLUTION] != DEFAULT_UNDEFINED
|
||||
&& mDefaults[PROPERTY_COLOR_MODE] != DEFAULT_UNDEFINED
|
||||
&& mDefaults[PROPERTY_ORIENTATION] != DEFAULT_UNDEFINED);
|
||||
public PrinterCapabilitiesInfo getCapabilities() {
|
||||
return mCapabilities;
|
||||
}
|
||||
|
||||
private PrinterInfo(Parcel parcel) {
|
||||
mId = parcel.readParcelable(null);
|
||||
mName = parcel.readString();
|
||||
mStatus = parcel.readInt();
|
||||
|
||||
mMinMargins = readMargins(parcel);
|
||||
readMediaSizes(parcel);
|
||||
readResolutions(parcel);
|
||||
mInputTrays = readInputTrays(parcel);
|
||||
mOutputTrays = readOutputTrays(parcel);
|
||||
|
||||
mColorModes = parcel.readInt();
|
||||
mDuplexModes = parcel.readInt();
|
||||
mFittingModes = parcel.readInt();
|
||||
mOrientations = parcel.readInt();
|
||||
|
||||
readDefaults(parcel);
|
||||
mDefaultMargins = readMargins(parcel);
|
||||
mDescription = parcel.readString();
|
||||
mCapabilities = parcel.readParcelable(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -356,40 +128,21 @@ public final class PrinterInfo implements Parcelable {
|
||||
@Override
|
||||
public void writeToParcel(Parcel parcel, int flags) {
|
||||
parcel.writeParcelable(mId, flags);
|
||||
parcel.writeString(mName);
|
||||
parcel.writeInt(mStatus);
|
||||
|
||||
writeMargins(mMinMargins, parcel);
|
||||
writeMediaSizes(parcel);
|
||||
writeResolutions(parcel);
|
||||
writeInputTrays(parcel);
|
||||
writeOutputTrays(parcel);
|
||||
|
||||
parcel.writeInt(mColorModes);
|
||||
parcel.writeInt(mDuplexModes);
|
||||
parcel.writeInt(mFittingModes);
|
||||
parcel.writeInt(mOrientations);
|
||||
|
||||
writeDefaults(parcel);
|
||||
writeMargins(mDefaultMargins, parcel);
|
||||
parcel.writeString(mDescription);
|
||||
parcel.writeParcelable(mCapabilities, flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((mId == null) ? 0 : mId.hashCode());
|
||||
result = prime * result + ((mId != null) ? mId.hashCode() : 0);
|
||||
result = prime * result + ((mName != null) ? mName.hashCode() : 0);
|
||||
result = prime * result + mStatus;
|
||||
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 + ((mInputTrays == null) ? 0 : mInputTrays.hashCode());
|
||||
result = prime * result + ((mOutputTrays == null) ? 0 : mOutputTrays.hashCode());
|
||||
result = prime * result + mDuplexModes;
|
||||
result = prime * result + mColorModes;
|
||||
result = prime * result + mFittingModes;
|
||||
result = prime * result + mOrientations;
|
||||
result = prime * result + Arrays.hashCode(mDefaults);
|
||||
result = prime * result + ((mDefaultMargins == null) ? 0 : mDefaultMargins.hashCode());
|
||||
result = prime * result + ((mDescription != null) ? mDescription.hashCode() : 0);
|
||||
result = prime * result + ((mCapabilities != null) ? mCapabilities.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -412,64 +165,20 @@ public final class PrinterInfo implements Parcelable {
|
||||
} else if (!mId.equals(other.mId)) {
|
||||
return false;
|
||||
}
|
||||
if (!TextUtils.equals(mName, other.mName)) {
|
||||
return false;
|
||||
}
|
||||
if (mStatus != other.mStatus) {
|
||||
return false;
|
||||
}
|
||||
if (mMinMargins == null) {
|
||||
if (other.mMinMargins != null) {
|
||||
if (!TextUtils.equals(mDescription, other.mDescription)) {
|
||||
return false;
|
||||
}
|
||||
if (mCapabilities == null) {
|
||||
if (other.mCapabilities != 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 (mInputTrays == null) {
|
||||
if (other.mInputTrays != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!mInputTrays.equals(other.mInputTrays)) {
|
||||
return false;
|
||||
}
|
||||
if (mOutputTrays == null) {
|
||||
if (other.mOutputTrays != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!mOutputTrays.equals(other.mOutputTrays)) {
|
||||
return false;
|
||||
}
|
||||
if (mDuplexModes != other.mDuplexModes) {
|
||||
return false;
|
||||
}
|
||||
if (mColorModes != other.mColorModes) {
|
||||
return false;
|
||||
}
|
||||
if (mFittingModes != other.mFittingModes) {
|
||||
return false;
|
||||
}
|
||||
if (mOrientations != other.mOrientations) {
|
||||
return false;
|
||||
}
|
||||
if (!Arrays.equals(mDefaults, other.mDefaults)) {
|
||||
return false;
|
||||
}
|
||||
if (mDefaultMargins == null) {
|
||||
if (other.mDefaultMargins != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!mDefaultMargins.equals(other.mDefaultMargins)) {
|
||||
} else if (!mCapabilities.equals(other.mCapabilities)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -479,434 +188,83 @@ public final class PrinterInfo implements Parcelable {
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("PrinterInfo{");
|
||||
builder.append(mId).append(", \"");
|
||||
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("\"}");
|
||||
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 writeInputTrays(Parcel parcel) {
|
||||
if (mInputTrays == null) {
|
||||
parcel.writeInt(0);
|
||||
return;
|
||||
}
|
||||
final int inputTrayCount = mInputTrays.size();
|
||||
parcel.writeInt(inputTrayCount);
|
||||
for (int i = 0; i < inputTrayCount; i++) {
|
||||
mInputTrays.get(i).writeToParcel(parcel);
|
||||
}
|
||||
}
|
||||
|
||||
private List<Tray> readInputTrays(Parcel parcel) {
|
||||
final int inputTrayCount = parcel.readInt();
|
||||
if (inputTrayCount <= 0) {
|
||||
return null;
|
||||
}
|
||||
List<Tray> inputTrays = new ArrayList<Tray>(inputTrayCount);
|
||||
for (int i = 0; i < inputTrayCount; i++) {
|
||||
inputTrays.add(Tray.createFromParcel(parcel));
|
||||
}
|
||||
return inputTrays;
|
||||
}
|
||||
|
||||
private void writeOutputTrays(Parcel parcel) {
|
||||
if (mOutputTrays == null) {
|
||||
parcel.writeInt(0);
|
||||
return;
|
||||
}
|
||||
final int outputTrayCount = mOutputTrays.size();
|
||||
parcel.writeInt(outputTrayCount);
|
||||
for (int i = 0; i < outputTrayCount; i++) {
|
||||
mOutputTrays.get(i).writeToParcel(parcel);
|
||||
}
|
||||
}
|
||||
|
||||
private List<Tray> readOutputTrays(Parcel parcel) {
|
||||
final int outputTrayCount = parcel.readInt();
|
||||
if (outputTrayCount <= 0) {
|
||||
return null;
|
||||
}
|
||||
List<Tray> outputTrays = new ArrayList<Tray>(outputTrayCount);
|
||||
for (int i = 0; i < outputTrayCount; i++) {
|
||||
outputTrays.add(Tray.createFromParcel(parcel));
|
||||
}
|
||||
return outputTrays;
|
||||
}
|
||||
|
||||
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 PrinterInfo}. 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 PrinterInfo}s.
|
||||
* <p>
|
||||
* Look at the individual methods for a reference whether a property is
|
||||
* required or if it is optional.
|
||||
* </p>
|
||||
* Builder for creating of a {@link PrinterInfo}.
|
||||
*/
|
||||
public static final class Builder {
|
||||
private final PrinterInfo mPrototype;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
* Constructor.
|
||||
*
|
||||
* @param printerId The printer id. Cannot be null.
|
||||
*
|
||||
* @throws IllegalArgumentException If the printer id is null.
|
||||
* @param name The printer name. Cannot be empty.
|
||||
* @param status The printer status. Must be a valid status.
|
||||
*/
|
||||
public Builder(PrinterId printerId) {
|
||||
public Builder(PrinterId printerId, String name, int status) {
|
||||
if (printerId == null) {
|
||||
throw new IllegalArgumentException("printerId cannot be null.");
|
||||
}
|
||||
if (TextUtils.isEmpty(name)) {
|
||||
throw new IllegalArgumentException("name cannot be empty.");
|
||||
}
|
||||
if (!isValidStatus(status)) {
|
||||
throw new IllegalArgumentException("status is invalid.");
|
||||
}
|
||||
mPrototype = new PrinterInfo();
|
||||
mPrototype.mId = printerId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the printer status.
|
||||
* <p>
|
||||
* <strong>Required:</strong> Yes
|
||||
* </p>
|
||||
*
|
||||
* @param status The status.
|
||||
* @return This builder.
|
||||
*/
|
||||
public Builder setStatus(int status) {
|
||||
mPrototype.mName = name;
|
||||
mPrototype.mStatus = status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param prototype Prototype from which to start building.
|
||||
*/
|
||||
public Builder(PrinterInfo prototype) {
|
||||
mPrototype = prototype;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the printer name.
|
||||
*
|
||||
* @param name The name.
|
||||
* @return This builder.
|
||||
*/
|
||||
public Builder setName(String name) {
|
||||
mPrototype.mName = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a supported media size.
|
||||
* <p>
|
||||
* <strong>Required:</strong> Yes
|
||||
* </p>
|
||||
* Sets the printer description.
|
||||
*
|
||||
* @param mediaSize A media size.
|
||||
* @param isDefault Whether this is the default.
|
||||
* @param description The description.
|
||||
* @return This builder.
|
||||
* @throws IllegalArgumentException If set as default and there
|
||||
* is already a default.
|
||||
*
|
||||
* @see PrintAttributes.MediaSize
|
||||
*/
|
||||
public Builder addMediaSize(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;
|
||||
}
|
||||
public Builder setDescription(String description) {
|
||||
mPrototype.mDescription = description;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a supported resolution.
|
||||
* <p>
|
||||
* <strong>Required:</strong> Yes
|
||||
* </p>
|
||||
* Sets the printer capabilities.
|
||||
*
|
||||
* @param resolution A resolution.
|
||||
* @param isDefault Whether this is the default.
|
||||
* @param capabilities The capabilities.
|
||||
* @return This builder.
|
||||
*
|
||||
* @throws IllegalArgumentException If set as default and there
|
||||
* is already a default.
|
||||
*
|
||||
* @see PrintAttributes.Resolution
|
||||
*/
|
||||
public Builder addResolution(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.
|
||||
* <p>
|
||||
* <strong>Required:</strong> No
|
||||
* </p>
|
||||
*
|
||||
* @param margins The margins.
|
||||
* @param defaultMargins The default margins.
|
||||
* @return This builder.
|
||||
*
|
||||
* @see PrintAttributes.Margins
|
||||
*/
|
||||
public Builder setMinMargins(Margins margins, Margins defaultMargins) {
|
||||
if (margins.getLeftMils() > defaultMargins.getLeftMils()
|
||||
|| margins.getTopMils() > defaultMargins.getTopMils()
|
||||
|| margins.getRightMils() < defaultMargins.getRightMils()
|
||||
|| margins.getBottomMils() < defaultMargins.getBottomMils()) {
|
||||
throw new IllegalArgumentException("Default margins"
|
||||
+ " cannot be outside of the min margins.");
|
||||
}
|
||||
mPrototype.mMinMargins = margins;
|
||||
mPrototype.mDefaultMargins = defaultMargins;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an input tray.
|
||||
* <p>
|
||||
* <strong>Required:</strong> No
|
||||
* </p>
|
||||
*
|
||||
* @param inputTray A tray.
|
||||
* @param isDefault Whether this is the default.
|
||||
* @return This builder.
|
||||
*
|
||||
* @throws IllegalArgumentException If set as default and there
|
||||
* is already a default.
|
||||
*
|
||||
* @see PrintAttributes.Tray
|
||||
*/
|
||||
public Builder addInputTray(Tray inputTray, boolean isDefault) {
|
||||
if (mPrototype.mInputTrays == null) {
|
||||
mPrototype.mInputTrays = new ArrayList<Tray>();
|
||||
}
|
||||
final int insertionIndex = mPrototype.mInputTrays.size();
|
||||
mPrototype.mInputTrays.add(inputTray);
|
||||
if (isDefault) {
|
||||
throwIfDefaultAlreadySpecified(PROPERTY_INPUT_TRAY);
|
||||
mPrototype.mDefaults[PROPERTY_INPUT_TRAY] = insertionIndex;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an output tray.
|
||||
* <p>
|
||||
* <strong>Required:</strong> No
|
||||
* </p>
|
||||
*
|
||||
* @param outputTray A tray.
|
||||
* @param isDefault Whether this is the default.
|
||||
* @return This builder.
|
||||
*
|
||||
* @throws IllegalArgumentException If set as default and there
|
||||
* is already a default.
|
||||
*
|
||||
* @see PrintAttributes.Tray
|
||||
*/
|
||||
public Builder addOutputTray(Tray outputTray, boolean isDefault) {
|
||||
if (mPrototype.mOutputTrays == null) {
|
||||
mPrototype.mOutputTrays = new ArrayList<Tray>();
|
||||
}
|
||||
final int insertionIndex = mPrototype.mOutputTrays.size();
|
||||
mPrototype.mOutputTrays.add(outputTray);
|
||||
if (isDefault) {
|
||||
throwIfDefaultAlreadySpecified(PROPERTY_OUTPUT_TRAY);
|
||||
mPrototype.mDefaults[PROPERTY_OUTPUT_TRAY] = insertionIndex;
|
||||
}
|
||||
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.
|
||||
*
|
||||
* @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 Builder setColorModes(int colorModes, int defaultColorMode) {
|
||||
int currentModes = colorModes;
|
||||
while (currentModes > 0) {
|
||||
final int currentMode = (1 << Integer.numberOfTrailingZeros(currentModes));
|
||||
currentModes &= ~currentMode;
|
||||
PrintAttributes.enforceValidColorMode(currentMode);
|
||||
}
|
||||
if ((colorModes & defaultColorMode) == 0) {
|
||||
throw new IllegalArgumentException("Default color mode not in color modes.");
|
||||
}
|
||||
PrintAttributes.enforceValidColorMode(colorModes);
|
||||
mPrototype.mColorModes = colorModes;
|
||||
mPrototype.mDefaults[PROPERTY_COLOR_MODE] = defaultColorMode;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set 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 Builder setDuplexModes(int duplexModes, int defaultDuplexMode) {
|
||||
int currentModes = duplexModes;
|
||||
while (currentModes > 0) {
|
||||
final int currentMode = (1 << Integer.numberOfTrailingZeros(currentModes));
|
||||
currentModes &= ~currentMode;
|
||||
PrintAttributes.enforceValidDuplexMode(currentMode);
|
||||
}
|
||||
if ((duplexModes & defaultDuplexMode) == 0) {
|
||||
throw new IllegalArgumentException("Default duplex mode not in duplex modes.");
|
||||
}
|
||||
PrintAttributes.enforceValidDuplexMode(defaultDuplexMode);
|
||||
mPrototype.mDuplexModes = duplexModes;
|
||||
mPrototype.mDefaults[PROPERTY_DUPLEX_MODE] = defaultDuplexMode;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the fitting modes.
|
||||
* <p>
|
||||
* <strong>Required:</strong> No
|
||||
* </p>
|
||||
*
|
||||
* @param fittingModes The fitting mode bit mask.
|
||||
* @param defaultFittingMode The default fitting mode.
|
||||
* @return This builder.
|
||||
*
|
||||
* @throws IllegalArgumentException If fitting modes contains an invalid
|
||||
* mode bit or if the default fitting mode is invalid.
|
||||
*
|
||||
* @see PrintAttributes#FITTING_MODE_NONE
|
||||
* @see PrintAttributes#FITTING_MODE_FIT_TO_PAGE
|
||||
*/
|
||||
public Builder setFittingModes(int fittingModes, int defaultFittingMode) {
|
||||
int currentModes = fittingModes;
|
||||
while (currentModes > 0) {
|
||||
final int currentMode = (1 << Integer.numberOfTrailingZeros(currentModes));
|
||||
currentModes &= ~currentMode;
|
||||
PrintAttributes.enfoceValidFittingMode(currentMode);
|
||||
}
|
||||
if ((fittingModes & defaultFittingMode) == 0) {
|
||||
throw new IllegalArgumentException("Default fitting mode not in fiting modes.");
|
||||
}
|
||||
PrintAttributes.enfoceValidFittingMode(defaultFittingMode);
|
||||
mPrototype.mFittingModes = fittingModes;
|
||||
mPrototype.mDefaults[PROPERTY_FITTING_MODE] = defaultFittingMode;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the orientations.
|
||||
* <p>
|
||||
* <strong>Required:</strong> Yes
|
||||
* </p>
|
||||
*
|
||||
* @param orientations The orientation bit mask.
|
||||
* @param defaultOrientation The default orientation.
|
||||
* @return This builder.
|
||||
*
|
||||
* @throws IllegalArgumentException If orientations contains an invalid
|
||||
* mode bit or if the default orientation is invalid.
|
||||
*
|
||||
* @see PrintAttributes#ORIENTATION_PORTRAIT
|
||||
* @see PrintAttributes#ORIENTATION_LANDSCAPE
|
||||
*/
|
||||
public Builder setOrientations(int orientations, int defaultOrientation) {
|
||||
int currentOrientaions = orientations;
|
||||
while (currentOrientaions > 0) {
|
||||
final int currentOrnt = (1 << Integer.numberOfTrailingZeros(currentOrientaions));
|
||||
currentOrientaions &= ~currentOrnt;
|
||||
PrintAttributes.enforceValidOrientation(currentOrnt);
|
||||
}
|
||||
if ((orientations & defaultOrientation) == 0) {
|
||||
throw new IllegalArgumentException("Default orientation not in orientations.");
|
||||
}
|
||||
PrintAttributes.enforceValidOrientation(defaultOrientation);
|
||||
mPrototype.mOrientations = orientations;
|
||||
mPrototype.mDefaults[PROPERTY_ORIENTATION] = defaultOrientation;
|
||||
public Builder setCapabilities(PrinterCapabilitiesInfo capabilities) {
|
||||
mPrototype.mCapabilities = capabilities;
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -919,10 +277,8 @@ public final class PrinterInfo implements Parcelable {
|
||||
return new PrinterInfo(mPrototype);
|
||||
}
|
||||
|
||||
private void throwIfDefaultAlreadySpecified(int propertyIndex) {
|
||||
if (mPrototype.mDefaults[propertyIndex] != DEFAULT_UNDEFINED) {
|
||||
throw new IllegalArgumentException("Default already specified.");
|
||||
}
|
||||
private boolean isValidStatus(int status) {
|
||||
return (status == PrinterInfo.STATUS_READY);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,16 +10,14 @@
|
||||
* 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
|
||||
* See the License for the specific languag<EFBFBD>e governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.printservice;
|
||||
|
||||
import android.os.ICancellationSignal;
|
||||
import android.print.IPrinterDiscoveryObserver;
|
||||
import android.print.IPrinterDiscoverySessionObserver;
|
||||
import android.print.PrintJobInfo;
|
||||
import android.print.PrinterId;
|
||||
import android.printservice.IPrintServiceClient;
|
||||
|
||||
/**
|
||||
@@ -29,9 +27,7 @@ import android.printservice.IPrintServiceClient;
|
||||
*/
|
||||
oneway interface IPrintService {
|
||||
void setClient(IPrintServiceClient client);
|
||||
void onRequestUpdatePrinters(in List<PrinterId> printerIds);
|
||||
void onRequestCancelPrintJob(in PrintJobInfo printJobInfo);
|
||||
void requestCancelPrintJob(in PrintJobInfo printJobInfo);
|
||||
void onPrintJobQueued(in PrintJobInfo printJobInfo);
|
||||
void onStartPrinterDiscovery(IPrinterDiscoveryObserver observer);
|
||||
void onStopPrinterDiscovery();
|
||||
void createPrinterDiscoverySession(IPrinterDiscoverySessionObserver observer);
|
||||
}
|
||||
|
||||
@@ -55,14 +55,14 @@ public final class PrintDocument {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the data associated with this document. It is a responsibility of the
|
||||
* client to open a stream to the returned file descriptor and fully read the
|
||||
* data.
|
||||
* Gets the data associated with this document.
|
||||
* <p>
|
||||
* <strong>Note:</strong> It is your responsibility to close the file descriptor.
|
||||
* <strong>Note: </strong> It is a responsibility of the client to open a
|
||||
* stream to the returned file descriptor, fully read the data, and close
|
||||
* the file descriptor.
|
||||
* </p>
|
||||
*
|
||||
* @return A file descriptor for reading the data or <code>null</code>.
|
||||
* @return A file descriptor for reading the data.
|
||||
*/
|
||||
public FileDescriptor getData() {
|
||||
ParcelFileDescriptor source = null;
|
||||
|
||||
@@ -21,9 +21,9 @@ import android.print.PrintJobInfo;
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* This class represents a print job from the perspective of a
|
||||
* print service. It provides APIs for observing the print job
|
||||
* state and performing operations on the print job.
|
||||
* This class represents a print job from the perspective of a print
|
||||
* service. It provides APIs for observing the print job state and
|
||||
* performing operations on the print job.
|
||||
*/
|
||||
public final class PrintJob {
|
||||
|
||||
@@ -38,7 +38,8 @@ public final class PrintJob {
|
||||
PrintJob(PrintJobInfo jobInfo, IPrintServiceClient client) {
|
||||
mCachedInfo = jobInfo;
|
||||
mPrintServiceClient = client;
|
||||
mDocument = new PrintDocument(mCachedInfo.getId(), client, jobInfo.getDocumentInfo());
|
||||
mDocument = new PrintDocument(mCachedInfo.getId(), client,
|
||||
jobInfo.getDocumentInfo());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -77,7 +78,7 @@ public final class PrintJob {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the document of this print job.
|
||||
* Gets the printed document.
|
||||
*
|
||||
* @return The document.
|
||||
*/
|
||||
@@ -87,11 +88,12 @@ public final class PrintJob {
|
||||
|
||||
/**
|
||||
* Gets whether this print job is queued. Such a print job is
|
||||
* ready to be printed and can be started.
|
||||
* ready to be printed and can be started or cancelled.
|
||||
*
|
||||
* @return Whether the print job is queued.
|
||||
*
|
||||
* @see #start()
|
||||
* @see #cancel()
|
||||
*/
|
||||
public boolean isQueued() {
|
||||
return getInfo().getState() == PrintJobInfo.STATE_QUEUED;
|
||||
@@ -111,6 +113,42 @@ public final class PrintJob {
|
||||
return getInfo().getState() == PrintJobInfo.STATE_STARTED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether this print job is completed. Such a print job
|
||||
* is successfully printed. This is a final state.
|
||||
*
|
||||
* @return Whether the print job is completed.
|
||||
*
|
||||
* @see #complete()
|
||||
*/
|
||||
public boolean isCompleted() {
|
||||
return getInfo().getState() == PrintJobInfo.STATE_COMPLETED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether this print job is failed. Such a print job is
|
||||
* not successfully printed due to an error. This is a final state.
|
||||
*
|
||||
* @return Whether the print job is failed.
|
||||
*
|
||||
* @see #fail(CharSequence)
|
||||
*/
|
||||
public boolean isFailed() {
|
||||
return getInfo().getState() == PrintJobInfo.STATE_FAILED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether this print job is cancelled. Such a print job was
|
||||
* cancelled as a result of a user request. This is a final state.
|
||||
*
|
||||
* @return Whether the print job is cancelled.
|
||||
*
|
||||
* @see #cancel()
|
||||
*/
|
||||
public boolean isCancelled() {
|
||||
return getInfo().getState() == PrintJobInfo.STATE_FAILED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the print job. You should call this method if {@link
|
||||
* #isQueued()} returns true and you started printing.
|
||||
@@ -163,12 +201,13 @@ public final class PrintJob {
|
||||
/**
|
||||
* Cancels the print job. You should call this method if {@link
|
||||
* #isQueued()} or {@link #isStarted()} returns true and you canceled
|
||||
* the print job as a response to a call to {@link PrintService
|
||||
* #onRequestCancelPrintJob(PrintJob)}.
|
||||
* the print job as a response to a call to {@link
|
||||
* PrintService#onRequestCancelPrintJob(PrintJob)}.
|
||||
*
|
||||
* @return Whether the job as canceled.
|
||||
* @return Whether the job is canceled.
|
||||
*
|
||||
* @see #isStarted()
|
||||
* @see #isQueued()
|
||||
*/
|
||||
public boolean cancel() {
|
||||
if (isQueued() || isStarted()) {
|
||||
|
||||
@@ -25,10 +25,9 @@ import android.os.IBinder;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.os.RemoteException;
|
||||
import android.print.IPrinterDiscoveryObserver;
|
||||
import android.print.IPrinterDiscoverySessionObserver;
|
||||
import android.print.PrintJobInfo;
|
||||
import android.print.PrinterId;
|
||||
import android.print.PrinterInfo;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -37,84 +36,82 @@ import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* This is the base class for implementing print services. A print service
|
||||
* knows how to discover and interact one or more printers via one or more
|
||||
* protocols.
|
||||
* This is the base class for implementing print services. A print service knows
|
||||
* how to discover and interact one or more printers via one or more protocols.
|
||||
* </p>
|
||||
* <h3>Printer discovery</h3>
|
||||
* <p>
|
||||
* A print service is responsible for discovering and reporting printers.
|
||||
* A printer discovery period starts with a call to
|
||||
* {@link #onStartPrinterDiscovery()} and ends with a call to
|
||||
* {@link #onStopPrinterDiscovery()}. During a printer discovery
|
||||
* period the print service reports newly discovered printers by
|
||||
* calling {@link #addDiscoveredPrinters(List)} and reports added printers
|
||||
* that disappeared by calling {@link #removeDiscoveredPrinters(List)}.
|
||||
* Calls to {@link #addDiscoveredPrinters(List)} and
|
||||
* {@link #removeDiscoveredPrinters(List)} before a call to
|
||||
* {@link #onStartPrinterDiscovery()} and after a call to
|
||||
* {@link #onStopPrinterDiscovery()} are a no-op.
|
||||
* A print service is responsible for discovering printers, adding discovered printers,
|
||||
* removing added printers, and updating added printers. When the system is interested
|
||||
* in printers managed by your service it will call {@link
|
||||
* #onCreatePrinterDiscoverySession()} from which you must return a new {@link
|
||||
* PrinterDiscoverySession} instance. The returned session encapsulates the interaction
|
||||
* between the system and your service during printer discovery. For description of this
|
||||
* interaction refer to the documentation for {@link PrinterDiscoverySession}.
|
||||
* </p>
|
||||
* <p>
|
||||
* For every printer discovery period all printers have to be added. Each
|
||||
* printer known to this print service should be added only once during a
|
||||
* discovery period, unless it was added and then removed before that.
|
||||
* Only an already added printer can be removed.
|
||||
* For every printer discovery session all printers have to be added since system does
|
||||
* not retain printers across sessions. Hence, each printer known to this print service
|
||||
* should be added only once during a discovery session. Only an already added printer
|
||||
* can be removed or updated. Removed printers can be added again.
|
||||
* </p>
|
||||
* <h3>Print jobs</h3>
|
||||
* <p>
|
||||
* When a new print job targeted to the printers managed by this print
|
||||
* service is queued, i.e. ready for processing by the print service,
|
||||
* a call to {@link #onPrintJobQueued(PrintJob)} is made and the print
|
||||
* service may handle it immediately or schedule that for an appropriate
|
||||
* time in the future. The list of all print jobs for this service
|
||||
* are be available by calling {@link #getPrintJobs()}.
|
||||
* When a new print job targeted to a printer managed by this print service is is queued,
|
||||
* i.e. ready for processing by the print service, you will receive a call to {@link
|
||||
* #onPrintJobQueued(PrintJob)}. The print service may handle the print job immediately
|
||||
* or schedule that for an appropriate time in the future. The list of all active print
|
||||
* jobs for this service is obtained by calling {@link #getActivePrintJobs()}. Active
|
||||
* print jobs are ones that are queued or started.
|
||||
* </p>
|
||||
* <p>
|
||||
* A print service is responsible for setting the print job state as
|
||||
* appropriate while processing it. Initially, a print job is in a
|
||||
* {@link PrintJobInfo#STATE_QUEUED} state which means that the data to
|
||||
* be printed is spooled by the system and the print service can obtain
|
||||
* that data by calling {@link PrintJob#getDocument()}. A queued print
|
||||
* job's {@link PrintJob#isQueued()} method returns true.
|
||||
* A print service is responsible for setting a print job's state as appropriate
|
||||
* while processing it. Initially, a print job is queued, i.e. {@link PrintJob#isQueued()
|
||||
* PrintJob.isQueued()} returns true, which means that the document to be printed is
|
||||
* spooled by the system and the print service can begin processing it. You can obtain
|
||||
* the printed document by calling {@link PrintJob#getDocument() PrintJob.getDocument()}
|
||||
* whose data is accessed via {@link PrintDocument#getData() PrintDocument.getData()}.
|
||||
* After the print service starts printing the data it should set the print job's
|
||||
* state to started by calling {@link PrintJob#start()} after which
|
||||
* {@link PrintJob#isStarted() PrintJob.isStarted()} would return true. Upon successful
|
||||
* completion, the print job should be marked as completed by calling {@link
|
||||
* PrintJob#complete() PrintJob.complete()} after which {@link PrintJob#isCompleted()
|
||||
* PrintJob.isCompleted()} would return true. In case of a failure, the print job should
|
||||
* be marked as failed by calling {@link PrintJob#fail(CharSequence) PrintJob.fail(
|
||||
* CharSequence)} after which {@link PrintJob#isFailed() PrintJob.isFailed()} would
|
||||
* return true.
|
||||
* </p>
|
||||
* <p>
|
||||
* After the print service starts printing the data it should set the
|
||||
* print job state to {@link PrintJobInfo#STATE_STARTED} by calling
|
||||
* {@link PrintJob#start()}. Upon successful completion, the print job
|
||||
* state has to be set to {@link PrintJobInfo#STATE_COMPLETED} by calling
|
||||
* {@link PrintJob#complete()}. In case of a failure, the print job
|
||||
* state should be set to {@link PrintJobInfo#STATE_FAILED} by calling
|
||||
* {@link PrintJob#fail(CharSequence)}. If a print job is in a
|
||||
* {@link PrintJobInfo#STATE_STARTED} state, i.e. {@link PrintJob#isStarted()}
|
||||
* return true, and the user requests to cancel it, the print service will
|
||||
* receive a call to {@link #onRequestCancelPrintJob(PrintJob)} which
|
||||
* requests from the service to do a best effort in canceling the job. In
|
||||
* case the job is successfully canceled, its state has to be set to
|
||||
* {@link PrintJobInfo#STATE_CANCELED}. by calling {@link PrintJob#cancel()}.
|
||||
* If a print job is queued or started and the user requests to cancel it, the print
|
||||
* service will receive a call to {@link #onRequestCancelPrintJob(PrintJob)} which
|
||||
* requests from the service to do best effort in canceling the job. In case the job
|
||||
* is successfully canceled, its state has to be marked as cancelled by calling {@link
|
||||
* PrintJob#cancel() PrintJob.cancel()} after which {@link PrintJob#isCancelled()
|
||||
* PrintJob.isCacnelled()} would return true.
|
||||
* </p>
|
||||
* <h3>Lifecycle</h3>
|
||||
* <p>
|
||||
* The lifecycle of a print service is managed exclusively by the system
|
||||
* and follows the established service lifecycle. Additionally, starting
|
||||
* or stopping a print service is triggered exclusively by an explicit
|
||||
* user action through enabling or disabling it in the device settings.
|
||||
* After the system binds to a print service, it calls {@link #onConnected()}.
|
||||
* This method can be overriden by clients to perform post binding setup.
|
||||
* Also after the system unbinds from a print service, it calls
|
||||
* {@link #onDisconnected()}. This method can be overriden by clients to
|
||||
* perform post unbinding cleanup.
|
||||
* The lifecycle of a print service is managed exclusively by the system and follows
|
||||
* the established service lifecycle. Additionally, starting or stopping a print service
|
||||
* is triggered exclusively by an explicit user action through enabling or disabling it
|
||||
* in the device settings. After the system binds to a print service, it calls {@link
|
||||
* #onConnected()}. This method can be overriden by clients to perform post binding setup.
|
||||
* Also after the system unbinds from a print service, it calls {@link #onDisconnected()}.
|
||||
* This method can be overriden by clients to perform post unbinding cleanup. Your should
|
||||
* not do any work after the system disconnected from your print service since the
|
||||
* service can be killed at any time to reclaim memory. The system will not disconnect
|
||||
* from a print service if there are active print jobs for the printers managed by it.
|
||||
* </p>
|
||||
* <h3>Declaration</h3>
|
||||
* <p>
|
||||
* A print service is declared as any other service in an AndroidManifest.xml
|
||||
* but it must also specify that it handles the {@link android.content.Intent}
|
||||
* with action {@link #SERVICE_INTERFACE}. Failure to declare this intent
|
||||
* will cause the system to ignore the print service. Additionally, a print
|
||||
* service must request the {@link android.Manifest.permission#BIND_PRINT_SERVICE}
|
||||
* permission to ensure that only the system can bind to it. Failure to
|
||||
* declare this intent will cause the system to ignore the print service.
|
||||
* Following is an example declaration:
|
||||
* A print service is declared as any other service in an AndroidManifest.xml but it must
|
||||
* also specify that it handles the {@link android.content.Intent} with action {@link
|
||||
* #SERVICE_INTERFACE android.printservice.PrintService}. Failure to declare this intent
|
||||
* will cause the system to ignore the print service. Additionally, a print service must
|
||||
* request the {@link android.Manifest.permission#BIND_PRINT_SERVICE
|
||||
* android.permission.BIND_PRINT_SERVICE} permission to ensure that only the system can
|
||||
* bind to it. Failure to declare this intent will cause the system to ignore the print
|
||||
* service. Following is an example declaration:
|
||||
* </p>
|
||||
* <pre>
|
||||
* <service android:name=".MyPrintService"
|
||||
@@ -127,17 +124,15 @@ import java.util.List;
|
||||
* </pre>
|
||||
* <h3>Configuration</h3>
|
||||
* <p>
|
||||
* A print service can be configured by specifying an optional settings
|
||||
* activity which exposes service specific options, an optional add
|
||||
* prints activity which is used for manual addition of printers, vendor
|
||||
* name ,etc. It is a responsibility of the system to launch the settings
|
||||
* and add printers activities when appropriate.
|
||||
* A print service can be configured by specifying an optional settings activity which
|
||||
* exposes service specific settings, an optional add printers activity which is used for
|
||||
* manual addition of printers, vendor name ,etc. It is a responsibility of the system
|
||||
* to launch the settings and add printers activities when appropriate.
|
||||
* </p>
|
||||
* <p>
|
||||
* A print service is configured by providing a
|
||||
* {@link #SERVICE_META_DATA meta-data} entry in the manifest when declaring
|
||||
* the service. A service declaration with a meta-data tag is presented
|
||||
* below:
|
||||
* A print service is configured by providing a {@link #SERVICE_META_DATA meta-data}
|
||||
* entry in the manifest when declaring the service. A service declaration with a meta-data
|
||||
* tag is presented below:
|
||||
* <pre> <service android:name=".MyPrintService"
|
||||
* android:permission="android.permission.BIND_PRINT_SERVICE">
|
||||
* <intent-filter>
|
||||
@@ -147,8 +142,9 @@ import java.util.List;
|
||||
* </service></pre>
|
||||
* </p>
|
||||
* <p>
|
||||
* For more details refer to {@link #SERVICE_META_DATA} and
|
||||
* <code><{@link android.R.styleable#PrintService print-service}></code>.
|
||||
* For more details for how to configure your print service via the meta-data refer to
|
||||
* {@link #SERVICE_META_DATA} and <code><{@link android.R.styleable#PrintService
|
||||
* print-service}></code>.
|
||||
* </p>
|
||||
*/
|
||||
public abstract class PrintService extends Service {
|
||||
@@ -157,21 +153,25 @@ public abstract class PrintService extends Service {
|
||||
|
||||
/**
|
||||
* The {@link Intent} action that must be declared as handled by a service
|
||||
* in its manifest to allow the system to recognize it as a print service.
|
||||
* in its manifest for the system to recognize it as a print service.
|
||||
*/
|
||||
public static final String SERVICE_INTERFACE = "android.printservice.PrintService";
|
||||
|
||||
/**
|
||||
* Name under which a PrintService component publishes additional information
|
||||
* about itself. This meta-data must reference an XML resource containing a
|
||||
* <code><{@link android.R.styleable#PrintService print-service}></code>
|
||||
* tag. This is a a sample XML file configuring a print service:
|
||||
* Name under which a {@link PrintService} component publishes additional information
|
||||
* about itself. This meta-data must reference a XML resource containing a <code>
|
||||
* <{@link android.R.styleable#PrintService print-service}></code> tag. This is
|
||||
* a sample XML file configuring a print service:
|
||||
* <pre> <print-service
|
||||
* android:vendor="SomeVendor"
|
||||
* android:settingsActivity="foo.bar.MySettingsActivity"
|
||||
* andorid:addPrintersActivity="foo.bar.MyAddPrintersActivity."
|
||||
* . . .
|
||||
* /></pre>
|
||||
* <p>
|
||||
* For detailed configuration options that can be specified via the meta-data
|
||||
* refer to {@link android.R.styleable#PrintService android.R.styleable.PrintService}.
|
||||
* </p>
|
||||
*/
|
||||
public static final String SERVICE_META_DATA = "android.printservice";
|
||||
|
||||
@@ -181,12 +181,12 @@ public abstract class PrintService extends Service {
|
||||
|
||||
private IPrintServiceClient mClient;
|
||||
|
||||
private IPrinterDiscoveryObserver mDiscoveryObserver;
|
||||
private int mLastSessionId = -1;
|
||||
|
||||
@Override
|
||||
protected void attachBaseContext(Context base) {
|
||||
protected final void attachBaseContext(Context base) {
|
||||
super.attachBaseContext(base);
|
||||
mHandler = new MyHandler(base.getMainLooper());
|
||||
mHandler = new ServiceHandler(base.getMainLooper());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -204,203 +204,47 @@ public abstract class PrintService extends Service {
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback requesting from this service to start printer discovery.
|
||||
* At the end of the printer discovery period the system will call
|
||||
* {@link #onStopPrinterDiscovery()}. Discovered printers should be
|
||||
* reported by calling {@link #addDiscoveredPrinters(List)} and reported
|
||||
* ones that disappear should be reported by calling
|
||||
* {@link #removeDiscoveredPrinters(List)}.
|
||||
* Callback asking you to create a new {@link PrinterDiscoverySession}.
|
||||
*
|
||||
* @see #onStopPrinterDiscovery()
|
||||
* @see #addDiscoveredPrinters(List)
|
||||
* @see #removeDiscoveredPrinters(List)
|
||||
* @see #updateDiscoveredPrinters(List)
|
||||
* @see PrinterDiscoverySession
|
||||
*/
|
||||
protected abstract void onStartPrinterDiscovery();
|
||||
protected abstract PrinterDiscoverySession onCreatePrinterDiscoverySession();
|
||||
|
||||
/**
|
||||
* Callback requesting from this service to stop printer discovery.
|
||||
*
|
||||
* @see #onStartPrinterDiscovery()
|
||||
* @see #addDiscoveredPrinters(List)
|
||||
* @see #removeDiscoveredPrinters(List)
|
||||
* @see #updateDiscoveredPrinters(List)
|
||||
*/
|
||||
protected abstract void onStopPrinterDiscovery();
|
||||
|
||||
/**
|
||||
* Adds discovered printers. This method should be called during a
|
||||
* printer discovery period, i.e. after a call to
|
||||
* {@link #onStartPrinterDiscovery()} and before the corresponding
|
||||
* call to {@link #onStopPrinterDiscovery()}, otherwise it does nothing.
|
||||
* <p>
|
||||
* <strong>Note:</strong> For every printer discovery period all
|
||||
* printers have to be added. You can call this method as many times as
|
||||
* necessary during the discovery period but should not pass in already
|
||||
* added printers. If a printer is already added in the same printer
|
||||
* discovery period, it will be ignored.
|
||||
* </p>
|
||||
* <p>
|
||||
* A {@link PrinterInfo} can have all of its required attributes specified,
|
||||
* or not. Whether all attributes are specified can be verified by calling
|
||||
* {@link PrinterInfo#hasAllRequiredAttributes()}. You can add printers
|
||||
* regardless if all required attributes are specified. When the system
|
||||
* (and the user) needs to interact with a printer, you will receive a
|
||||
* call to {@link #onRequestUpdatePrinters(List)}. If you fail to update
|
||||
* a printer that was added without all required attributes via calling
|
||||
* {@link #updateDiscoveredPrinters(List)}, then this printer will be
|
||||
* ignored, i.e. considered unavailable.
|
||||
* <p>
|
||||
*
|
||||
* @param printers A list with discovered printers.
|
||||
*
|
||||
* @see #updateDiscoveredPrinters(List)
|
||||
* @see #removeDiscoveredPrinters(List)
|
||||
* @see #onStartPrinterDiscovery()
|
||||
* @see #onStopPrinterDiscovery()
|
||||
*/
|
||||
public final void addDiscoveredPrinters(List<PrinterInfo> printers) {
|
||||
final IPrinterDiscoveryObserver observer;
|
||||
synchronized (mLock) {
|
||||
observer = mDiscoveryObserver;
|
||||
}
|
||||
if (observer != null) {
|
||||
try {
|
||||
observer.onPrintersAdded(printers);
|
||||
} catch (RemoteException re) {
|
||||
Log.e(LOG_TAG, "Error adding discovered printers", re);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes discovered printers given their ids. This method should be called
|
||||
* during a printer discovery period, i.e. after a call to
|
||||
* {@link #onStartPrinterDiscovery()} and before the corresponding
|
||||
* call to {@link #onStopPrinterDiscovery()}, otherwise it does nothing.
|
||||
* <p>
|
||||
* For every printer discovery period all printers have to be added. You
|
||||
* should remove only printers that were added in this printer discovery
|
||||
* period by a call to {@link #addDiscoveredPrinters(List)}. You can call
|
||||
* this method as many times as necessary during the discovery period
|
||||
* but should not pass in already removed printer ids. If a printer with
|
||||
* a given id is already removed, it will be ignored.
|
||||
* </p>
|
||||
*
|
||||
* @param printerIds A list with disappeared printer ids.
|
||||
*
|
||||
* @see #addDiscoveredPrinters(List)
|
||||
* @see #updateDiscoveredPrinters(List)
|
||||
* @see #onStartPrinterDiscovery()
|
||||
* @see #onStopPrinterDiscovery()
|
||||
*/
|
||||
public final void removeDiscoveredPrinters(List<PrinterId> printerIds) {
|
||||
final IPrinterDiscoveryObserver observer;
|
||||
synchronized (mLock) {
|
||||
observer = mDiscoveryObserver;
|
||||
}
|
||||
if (observer != null) {
|
||||
try {
|
||||
observer.onPrintersRemoved(printerIds);
|
||||
} catch (RemoteException re) {
|
||||
Log.e(LOG_TAG, "Error removing discovered printers", re);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates discovered printers that are already added. This method should
|
||||
* be called during a printer discovery period, i.e. after a call to
|
||||
* {@link #onStartPrinterDiscovery()} and before the corresponding
|
||||
* call to {@link #onStopPrinterDiscovery()}, otherwise it does nothing.
|
||||
* <p>
|
||||
* For every printer discovery period all printers have to be added. You
|
||||
* should update only printers that were added in this printer discovery
|
||||
* period by a call to {@link #addDiscoveredPrinters(List)}. You can call
|
||||
* this method as many times as necessary during the discovery period
|
||||
* but should not try to update already removed or never added printers.
|
||||
* If a printer is already removed or never added, it will be ignored.
|
||||
* </p>
|
||||
*
|
||||
* @param printers A list with updated printers.
|
||||
*
|
||||
* @see #addDiscoveredPrinters(List)
|
||||
* @see #removeDiscoveredPrinters(List)
|
||||
* @see #onStartPrinterDiscovery()
|
||||
* @see #onStopPrinterDiscovery()
|
||||
*/
|
||||
public final void updateDiscoveredPrinters(List<PrinterInfo> printers) {
|
||||
final IPrinterDiscoveryObserver observer;
|
||||
synchronized (mLock) {
|
||||
observer = mDiscoveryObserver;
|
||||
}
|
||||
if (observer != null) {
|
||||
try {
|
||||
observer.onPrintersUpdated(printers);
|
||||
} catch (RemoteException re) {
|
||||
Log.e(LOG_TAG, "Error updating discovered printers", re);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the system will start interacting with a printer
|
||||
* giving you a change to update it in case some of its capabilities
|
||||
* have changed. For example, this method will be called when the
|
||||
* user selects a printer. Hence, it updating this printer should
|
||||
* be done as quickly as possible in order to achieve maximally
|
||||
* smooth user experience.
|
||||
* <p>
|
||||
* A {@link PrinterInfo} can have all of its required attributes specified,
|
||||
* or not. Whether all attributes are specified can be verified by calling
|
||||
* {@link PrinterInfo#hasAllRequiredAttributes()}. You can add printers
|
||||
* regardless if all required attributes are specified. When the system
|
||||
* (and the user) needs to interact with a printer, you will receive a
|
||||
* call to this method. If you fail to update a printer that was added
|
||||
* without all required attributes via calling
|
||||
* {@link #updateDiscoveredPrinters(List)}, then this printer will be
|
||||
* ignored, i.e. considered unavailable.
|
||||
* </p>
|
||||
*
|
||||
* @param printerIds The printers to be updated.
|
||||
*/
|
||||
protected void onRequestUpdatePrinters(List<PrinterId> printerIds) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when canceling of a print job is requested. The service
|
||||
* Called when cancellation of a print job is requested. The service
|
||||
* should do best effort to fulfill the request. After the cancellation
|
||||
* is performed, the print job should be set to a cancelled state by
|
||||
* is performed, the print job should be marked as cancelled state by
|
||||
* calling {@link PrintJob#cancel()}.
|
||||
*
|
||||
* @param printJob The print job to be canceled.
|
||||
* @param printJob The print job to cancel.
|
||||
*
|
||||
* @see PrintJob#cancel() PrintJob.cancel()
|
||||
* @see PrintJob#isCancelled() PrintJob.isCancelled()
|
||||
*/
|
||||
protected void onRequestCancelPrintJob(PrintJob printJob) {
|
||||
}
|
||||
protected abstract void onRequestCancelPrintJob(PrintJob printJob);
|
||||
|
||||
/**
|
||||
* Called when there is a queued print job for one of the printers
|
||||
* managed by this print service. A queued print job is ready for
|
||||
* processing by a print service which can get the data to be printed
|
||||
* by calling {@link PrintJob#getDocument()}. This service may start
|
||||
* processing the passed in print job or schedule handling of queued
|
||||
* print jobs at a convenient time. The service can get the print
|
||||
* jobs by a call to {@link #getPrintJobs()} and examine their state
|
||||
* to find the ones with state {@link PrintJobInfo#STATE_QUEUED} by
|
||||
* calling {@link PrintJob#isQueued()}.
|
||||
* managed by this print service.
|
||||
*
|
||||
* @param printJob The new queued print job.
|
||||
*
|
||||
* @see #getPrintJobs()
|
||||
* @see PrintJob#isQueued() PrintJob.isQueued()
|
||||
* @see #getActivePrintJobs()
|
||||
*/
|
||||
protected abstract void onPrintJobQueued(PrintJob printJob);
|
||||
|
||||
/**
|
||||
* Gets the print jobs for the printers managed by this service.
|
||||
* Gets the active print jobs for the printers managed by this service.
|
||||
* Active print jobs are ones that are not in a final state, i.e. whose
|
||||
* state is queued or started.
|
||||
*
|
||||
* @return The print jobs.
|
||||
* @return The active print jobs.
|
||||
*
|
||||
* @see PrintJob#isQueued() PrintJob.isQueued()
|
||||
* @see PrintJob#isStarted() PrintJob.isStarted()
|
||||
*/
|
||||
public final List<PrintJob> getPrintJobs() {
|
||||
public final List<PrintJob> getActivePrintJobs() {
|
||||
final IPrintServiceClient client;
|
||||
synchronized (mLock) {
|
||||
client = mClient;
|
||||
@@ -428,14 +272,14 @@ public abstract class PrintService extends Service {
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a global printer id given the printer's locally unique name.
|
||||
* Generates a global printer id given the printer's locally unique one.
|
||||
*
|
||||
* @param printerName The printer name.
|
||||
* @param localId A locally unique id in the context of your print service.
|
||||
* @return Global printer id.
|
||||
*/
|
||||
public final PrinterId generatePrinterId(String printerName) {
|
||||
public final PrinterId generatePrinterId(String localId) {
|
||||
return new PrinterId(new ComponentName(getPackageName(),
|
||||
getClass().getName()), printerName);
|
||||
getClass().getName()), localId);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -443,69 +287,58 @@ public abstract class PrintService extends Service {
|
||||
return new IPrintService.Stub() {
|
||||
@Override
|
||||
public void setClient(IPrintServiceClient client) {
|
||||
mHandler.obtainMessage(MyHandler.MSG_SET_CLEINT, client).sendToTarget();
|
||||
mHandler.obtainMessage(ServiceHandler.MSG_SET_CLEINT, client)
|
||||
.sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartPrinterDiscovery(IPrinterDiscoveryObserver observer) {
|
||||
mHandler.obtainMessage(MyHandler.MSG_ON_START_PRINTER_DISCOVERY,
|
||||
public void createPrinterDiscoverySession(IPrinterDiscoverySessionObserver observer) {
|
||||
mHandler.obtainMessage(ServiceHandler.MSG_ON_CREATE_PRINTER_DISCOVERY_SESSION,
|
||||
observer).sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStopPrinterDiscovery() {
|
||||
mHandler.sendEmptyMessage(MyHandler.MSG_ON_STOP_PRINTER_DISCOVERY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestUpdatePrinters(List<PrinterId> printerIds) {
|
||||
mHandler.obtainMessage(MyHandler.MSG_ON_REQUEST_UPDATE_PRINTERS,
|
||||
printerIds).sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestCancelPrintJob(PrintJobInfo printJobInfo) {
|
||||
mHandler.obtainMessage(MyHandler.MSG_ON_REQUEST_CANCEL_PRINTJOB,
|
||||
public void requestCancelPrintJob(PrintJobInfo printJobInfo) {
|
||||
mHandler.obtainMessage(ServiceHandler.MSG_ON_REQUEST_CANCEL_PRINTJOB,
|
||||
printJobInfo).sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPrintJobQueued(PrintJobInfo printJobInfo) {
|
||||
mHandler.obtainMessage(MyHandler.MSG_ON_PRINTJOB_QUEUED,
|
||||
mHandler.obtainMessage(ServiceHandler.MSG_ON_PRINTJOB_QUEUED,
|
||||
printJobInfo).sendToTarget();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private final class MyHandler extends Handler {
|
||||
public static final int MSG_ON_START_PRINTER_DISCOVERY = 1;
|
||||
public static final int MSG_ON_STOP_PRINTER_DISCOVERY = 2;
|
||||
private final class ServiceHandler extends Handler {
|
||||
public static final int MSG_ON_CREATE_PRINTER_DISCOVERY_SESSION = 1;
|
||||
public static final int MSG_ON_PRINTJOB_QUEUED = 2;
|
||||
public static final int MSG_ON_REQUEST_CANCEL_PRINTJOB = 3;
|
||||
public static final int MSG_ON_REQUEST_UPDATE_PRINTERS = 4;
|
||||
public static final int MSG_ON_PRINTJOB_QUEUED = 5;
|
||||
public static final int MSG_SET_CLEINT = 6;
|
||||
public static final int MSG_SET_CLEINT = 4;
|
||||
|
||||
public MyHandler(Looper looper) {
|
||||
public ServiceHandler(Looper looper) {
|
||||
super(looper, null, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void handleMessage(Message message) {
|
||||
final int action = message.what;
|
||||
switch (action) {
|
||||
case MSG_ON_START_PRINTER_DISCOVERY: {
|
||||
synchronized (mLock) {
|
||||
mDiscoveryObserver = (IPrinterDiscoveryObserver) message.obj;
|
||||
case MSG_ON_CREATE_PRINTER_DISCOVERY_SESSION: {
|
||||
IPrinterDiscoverySessionObserver observer =
|
||||
(IPrinterDiscoverySessionObserver) message.obj;
|
||||
PrinterDiscoverySession session = onCreatePrinterDiscoverySession();
|
||||
if (session == null) {
|
||||
throw new NullPointerException("session cannot be null");
|
||||
}
|
||||
onStartPrinterDiscovery();
|
||||
} break;
|
||||
|
||||
case MSG_ON_STOP_PRINTER_DISCOVERY: {
|
||||
synchronized (mLock) {
|
||||
mDiscoveryObserver = null;
|
||||
if (session.getId() == mLastSessionId) {
|
||||
throw new IllegalStateException("cannot reuse sessions");
|
||||
}
|
||||
mLastSessionId = session.getId();
|
||||
}
|
||||
onStopPrinterDiscovery();
|
||||
session.setObserver(observer);
|
||||
} break;
|
||||
|
||||
case MSG_ON_REQUEST_CANCEL_PRINTJOB: {
|
||||
@@ -513,11 +346,6 @@ public abstract class PrintService extends Service {
|
||||
onRequestCancelPrintJob(new PrintJob(printJobInfo, mClient));
|
||||
} break;
|
||||
|
||||
case MSG_ON_REQUEST_UPDATE_PRINTERS: {
|
||||
List<PrinterId> printerIds = (List<PrinterId>) message.obj;
|
||||
onRequestUpdatePrinters(printerIds);
|
||||
} break;
|
||||
|
||||
case MSG_ON_PRINTJOB_QUEUED: {
|
||||
PrintJobInfo printJobInfo = (PrintJobInfo) message.obj;
|
||||
onPrintJobQueued(new PrintJob(printJobInfo, mClient));
|
||||
@@ -527,9 +355,6 @@ public abstract class PrintService extends Service {
|
||||
IPrintServiceClient client = (IPrintServiceClient) message.obj;
|
||||
synchronized (mLock) {
|
||||
mClient = client;
|
||||
if (client == null) {
|
||||
mDiscoveryObserver = null;
|
||||
}
|
||||
}
|
||||
if (client != null) {
|
||||
onConnected();
|
||||
|
||||
357
core/java/android/printservice/PrinterDiscoverySession.java
Normal file
357
core/java/android/printservice/PrinterDiscoverySession.java
Normal file
@@ -0,0 +1,357 @@
|
||||
/*
|
||||
* 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.printservice;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.os.RemoteException;
|
||||
import android.print.IPrinterDiscoverySessionController;
|
||||
import android.print.IPrinterDiscoverySessionObserver;
|
||||
import android.print.PrinterId;
|
||||
import android.print.PrinterInfo;
|
||||
import android.util.Log;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* This class encapsulates the interaction between a print service and the
|
||||
* system during printer discovery. During printer discovery you are responsible
|
||||
* for adding discovered printers, removing already added printers that
|
||||
* disappeared, and updating already added printers.
|
||||
* <p>
|
||||
* The opening of the session is announced by a call to {@link
|
||||
* PrinterDiscoverySession#onOpen(List)} at which point you should start printer
|
||||
* discovery. The closing of the session is announced by a call to {@link
|
||||
* PrinterDiscoverySession#onClose()} at which point you should stop printer
|
||||
* discovery. Discovered printers are added by invoking {@link
|
||||
* PrinterDiscoverySession#addPrinters(List)}. Added printers that disappeared
|
||||
* are removed by invoking {@link PrinterDiscoverySession#removePrinters(List)}.
|
||||
* Added printers whose properties or capabilities changed are updated through
|
||||
* a call to {@link PrinterDiscoverySession#updatePrinters(List)}.
|
||||
* </p>
|
||||
* <p>
|
||||
* The system will make a call to
|
||||
* {@link PrinterDiscoverySession#onRequestPrinterUpdate(PrinterId)} if you
|
||||
* need to update a given printer. It is possible that you add a printer without
|
||||
* specifying its capabilities. This enables you to avoid querying all
|
||||
* discovered printers for their capabilities, rather querying the capabilities
|
||||
* of a printer only if necessary. For example, the system will require that you
|
||||
* update a printer if it gets selected by the user. If you did not report the
|
||||
* printer capabilities when adding it, you must do so after the system requests
|
||||
* a printer update. Otherwise, the printer will be ignored.
|
||||
* </p>
|
||||
* <p>
|
||||
* During printer discovery all printers that are known to your print service
|
||||
* have to be added. The system does not retain any printers from previous
|
||||
* sessions.
|
||||
* </p>
|
||||
*/
|
||||
public abstract class PrinterDiscoverySession {
|
||||
private static final String LOG_TAG = "PrinterDiscoverySession";
|
||||
|
||||
private static int sIdCounter = 0;
|
||||
|
||||
private final Object mLock = new Object();
|
||||
|
||||
private final Handler mHandler;
|
||||
|
||||
private final int mId;
|
||||
|
||||
private IPrinterDiscoverySessionController mController;
|
||||
|
||||
private IPrinterDiscoverySessionObserver mObserver;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param context A context instance.
|
||||
*/
|
||||
public PrinterDiscoverySession(Context context) {
|
||||
mId = sIdCounter++;
|
||||
mHandler = new SessionHandler(context.getMainLooper());
|
||||
mController = new PrinterDiscoverySessionController(this);
|
||||
}
|
||||
|
||||
void setObserver(IPrinterDiscoverySessionObserver observer) {
|
||||
synchronized (mLock) {
|
||||
mObserver = observer;
|
||||
try {
|
||||
mObserver.setController(mController);
|
||||
} catch (RemoteException re) {
|
||||
Log.e(LOG_TAG, "Error setting session controller", re);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int getId() {
|
||||
return mId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds discovered printers. Adding an already added printer has no effect.
|
||||
* Removed printers can be added again. You can call this method multiple
|
||||
* times during printer discovery.
|
||||
* <p>
|
||||
* <strong>Note: </strong> Calling this method when the session is closed,
|
||||
* which is if {@link #isClosed()} returns true, will throw an {@link
|
||||
* IllegalStateException}.
|
||||
* </p>
|
||||
*
|
||||
* @param printers The printers to add.
|
||||
*
|
||||
* @see #removePrinters(List)
|
||||
* @see #updatePrinters(List)
|
||||
* @see #isClosed()
|
||||
*/
|
||||
public final void addPrinters(List<PrinterInfo> printers) {
|
||||
final IPrinterDiscoverySessionObserver observer;
|
||||
synchronized (mLock) {
|
||||
throwIfClosedLocked();
|
||||
observer = mObserver;
|
||||
}
|
||||
if (observer != null) {
|
||||
try {
|
||||
observer.onPrintersAdded(printers);
|
||||
} catch (RemoteException re) {
|
||||
Log.e(LOG_TAG, "Error adding printers", re);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes added printers. Removing an already removed or never added
|
||||
* printer has no effect. Removed printers can be added again. You
|
||||
* can call this method multiple times during printer discovery.
|
||||
* <p>
|
||||
* <strong>Note: </strong> Calling this method when the session is closed,
|
||||
* which is if {@link #isClosed()} returns true, will throw an {@link
|
||||
* IllegalStateException}.
|
||||
* </p>
|
||||
*
|
||||
* @param printerIds The ids of the removed printers.
|
||||
*
|
||||
* @see #addPrinters(List)
|
||||
* @see #updatePrinters(List)
|
||||
* @see #isClosed()
|
||||
*/
|
||||
public final void removePrinters(List<PrinterId> printerIds) {
|
||||
final IPrinterDiscoverySessionObserver observer;
|
||||
synchronized (mLock) {
|
||||
throwIfClosedLocked();
|
||||
observer = mObserver;
|
||||
}
|
||||
if (observer != null) {
|
||||
try {
|
||||
observer.onPrintersRemoved(printerIds);
|
||||
} catch (RemoteException re) {
|
||||
Log.e(LOG_TAG, "Error removing printers", re);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates added printers. Updating a printer that was not added or that
|
||||
* was removed has no effect. You can call this method multiple times
|
||||
* during printer discovery.
|
||||
* <p>
|
||||
* <strong>Note: </strong> Calling this method when the session is closed,
|
||||
* which is if {@link #isClosed()} returns true, will throw an {@link
|
||||
* IllegalStateException}.
|
||||
* </p>
|
||||
*
|
||||
* @param printers The printers to update.
|
||||
*
|
||||
* @see #addPrinters(List)
|
||||
* @see #removePrinters(List)
|
||||
* @see #isClosed()
|
||||
*/
|
||||
public final void updatePrinters(List<PrinterInfo> printers) {
|
||||
final IPrinterDiscoverySessionObserver observer;
|
||||
synchronized (mLock) {
|
||||
throwIfClosedLocked();
|
||||
observer = mObserver;
|
||||
}
|
||||
if (observer != null) {
|
||||
try {
|
||||
observer.onPrintersUpdated(printers);
|
||||
} catch (RemoteException re) {
|
||||
Log.e(LOG_TAG, "Error updating printers", re);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback notifying you that the session is open and you should start
|
||||
* printer discovery. Discovered printers should be added via calling
|
||||
* {@link #addPrinters(List)}. Added printers that disappeared should be
|
||||
* removed via calling {@link #removePrinters(List)}. Added printers whose
|
||||
* properties or capabilities changes should be updated via calling {@link
|
||||
* #updatePrinters(List)}. When the session is closed you will receive a
|
||||
* call to {@link #onClose()}.
|
||||
* <p>
|
||||
* During printer discovery all printers that are known to your print
|
||||
* service have to be added. The system does not retain any printers from
|
||||
* previous sessions.
|
||||
* </p>
|
||||
* <p>
|
||||
* <strong>Note: </strong>You are also given a list of printers whose
|
||||
* availability has to be checked first. For example, these printers could
|
||||
* be the user's favorite ones, therefore they have to be verified first.
|
||||
* </p>
|
||||
*
|
||||
* @see #onClose()
|
||||
* @see #isClosed()
|
||||
* @see #addPrinters(List)
|
||||
* @see #removePrinters(List)
|
||||
* @see #updatePrinters(List)
|
||||
*/
|
||||
public abstract void onOpen(List<PrinterId> priorityList);
|
||||
|
||||
/**
|
||||
* Callback notifying you that the session is closed and you should stop
|
||||
* printer discovery. After the session is closed and any attempt to call
|
||||
* any of its methods will throw an exception. Whether a session is closed
|
||||
* can be checked by calling {@link #isClosed()}. Once the session is closed
|
||||
* it will never be opened again.
|
||||
*
|
||||
* @see #onOpen(List)
|
||||
* @see #isClosed()
|
||||
* @see #addPrinters(List)
|
||||
* @see #removePrinters(List)
|
||||
* @see #updatePrinters(List)
|
||||
*/
|
||||
public abstract void onClose();
|
||||
|
||||
/**
|
||||
* Requests that you update a printer. You are responsible for updating
|
||||
* the printer by also reporting its capabilities via calling {@link
|
||||
* #updatePrinters(List)}.
|
||||
* <p>
|
||||
* <strong>Note: </strong> A printer can be initially added without its
|
||||
* capabilities to avoid polling printers that the user will not select.
|
||||
* However, after this method is called you are expected to update the
|
||||
* printer <strong>including</strong> its capabilities. Otherwise, the
|
||||
* printer will be ignored.
|
||||
* <p>
|
||||
* A scenario when you may be requested to update a printer is if the user
|
||||
* selects it and the system has to present print options UI based on the
|
||||
* printer's capabilities.
|
||||
* </p>
|
||||
*
|
||||
* @param printerId The printer id.
|
||||
*
|
||||
* @see #updatePrinters(List)
|
||||
* @see PrinterInfo.Builder#setCapabilities(PrinterCapabilitiesInfo)
|
||||
* PrinterInfo.Builder.setCapabilities(PrinterCapabilitiesInfo)
|
||||
*/
|
||||
public abstract void onRequestPrinterUpdate(PrinterId printerId);
|
||||
|
||||
/**
|
||||
* Gets whether this session is closed.
|
||||
*
|
||||
* @return Whether the session is closed.
|
||||
*/
|
||||
public final boolean isClosed() {
|
||||
synchronized (mLock) {
|
||||
return (mController == null && mObserver == null);
|
||||
}
|
||||
}
|
||||
|
||||
void close() {
|
||||
synchronized (mLock) {
|
||||
throwIfClosedLocked();
|
||||
mController = null;
|
||||
mObserver = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void throwIfClosedLocked() {
|
||||
if (isClosed()) {
|
||||
throw new IllegalStateException("Session is closed");
|
||||
}
|
||||
}
|
||||
|
||||
private final class SessionHandler extends Handler {
|
||||
public static final int MSG_OPEN = 1;
|
||||
public static final int MSG_CLOSE = 2;
|
||||
public static final int MSG_REQUEST_PRINTER_UPDATE = 3;
|
||||
|
||||
public SessionHandler(Looper looper) {
|
||||
super(looper, null, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void handleMessage(Message message) {
|
||||
switch (message.what) {
|
||||
case MSG_OPEN: {
|
||||
List<PrinterId> priorityList = (List<PrinterId>) message.obj;
|
||||
onOpen(priorityList);
|
||||
} break;
|
||||
|
||||
case MSG_CLOSE: {
|
||||
onClose();
|
||||
close();
|
||||
} break;
|
||||
|
||||
case MSG_REQUEST_PRINTER_UPDATE: {
|
||||
PrinterId printerId = (PrinterId) message.obj;
|
||||
onRequestPrinterUpdate(printerId);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static final class PrinterDiscoverySessionController extends
|
||||
IPrinterDiscoverySessionController.Stub {
|
||||
private final WeakReference<PrinterDiscoverySession> mWeakSession;
|
||||
|
||||
public PrinterDiscoverySessionController(PrinterDiscoverySession session) {
|
||||
mWeakSession = new WeakReference<PrinterDiscoverySession>(session);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void open(List<PrinterId> priorityList) {
|
||||
PrinterDiscoverySession session = mWeakSession.get();
|
||||
if (session != null) {
|
||||
session.mHandler.obtainMessage(SessionHandler.MSG_OPEN,
|
||||
priorityList).sendToTarget();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
PrinterDiscoverySession session = mWeakSession.get();
|
||||
if (session != null) {
|
||||
session.mHandler.sendEmptyMessage(SessionHandler.MSG_CLOSE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void requestPrinterUpdate(PrinterId printerId) {
|
||||
PrinterDiscoverySession session = mWeakSession.get();
|
||||
if (session != null) {
|
||||
session.mHandler.obtainMessage(
|
||||
SessionHandler.MSG_REQUEST_PRINTER_UPDATE,
|
||||
printerId).sendToTarget();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
24
core/java/android/printservice/package.html
Normal file
24
core/java/android/printservice/package.html
Normal file
@@ -0,0 +1,24 @@
|
||||
<HTML>
|
||||
<BODY>
|
||||
<p>
|
||||
Provides classes for implementing print services. Print services are plug-in components
|
||||
that know how to talk to printers via some standard protocols. These services serve as a
|
||||
bridge between the system and the printers. Hence, the printer and print protocol specific
|
||||
implementation is factored out of the system and can by independently developed and updated.
|
||||
</p>
|
||||
<p>
|
||||
A print service implementation should extend {@link android.printservice.PrintService}
|
||||
and implement its abstract methods. Also the print service has to follow the contract for
|
||||
managing print {@link android.printservice.PrintJob}s to ensure correct interaction with
|
||||
the system and consistent user experience.
|
||||
<p/>
|
||||
<p>
|
||||
The system is responsible for starting and stopping a print service depending on whether
|
||||
there are active print jobs for the printers managed by the service. The print service
|
||||
should also perform printer discovery in a timely fashion to ensure good user experience.
|
||||
The interaction between the system and the print service during printer discovery is
|
||||
encapsulated by a {@link android.printservice.PrinterDiscoverySession} instance created
|
||||
by the print service when requested by the system.
|
||||
</p>
|
||||
</BODY>
|
||||
</HTML>
|
||||
@@ -86,7 +86,7 @@ public class NotificationController {
|
||||
printJob.getLabel()))
|
||||
.addAction(R.drawable.stat_notify_cancelling, mContext.getString(R.string.cancel),
|
||||
createCancelIntent(printJob))
|
||||
.setContentText(printJob.getPrinterId().getPrinterName())
|
||||
.setContentText(printJob.getPrinterName())
|
||||
.setWhen(System.currentTimeMillis())
|
||||
.setOngoing(true)
|
||||
.setShowWhen(true);
|
||||
@@ -119,7 +119,7 @@ public class NotificationController {
|
||||
intent.setAction(INTENT_ACTION_CANCEL_PRINTJOB + "_" + String.valueOf(printJob.getId()));
|
||||
intent.putExtra(INTENT_EXTRA_PRINTJOB_ID, printJob.getId());
|
||||
intent.putExtra(INTENT_EXTRA_PRINTJOB_LABEL, printJob.getLabel());
|
||||
intent.putExtra(INTENT_EXTRA_PRINTER_NAME, printJob.getPrinterId().getPrinterName());
|
||||
intent.putExtra(INTENT_EXTRA_PRINTER_NAME, printJob.getPrinterName());
|
||||
return PendingIntent.getBroadcast(mContext, 0, intent, PendingIntent.FLAG_ONE_SHOT);
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,8 @@ import android.os.Message;
|
||||
import android.os.RemoteException;
|
||||
import android.print.ILayoutResultCallback;
|
||||
import android.print.IPrintDocumentAdapter;
|
||||
import android.print.IPrinterDiscoveryObserver;
|
||||
import android.print.IPrinterDiscoverySessionController;
|
||||
import android.print.IPrinterDiscoverySessionObserver;
|
||||
import android.print.IWriteResultCallback;
|
||||
import android.print.PageRange;
|
||||
import android.print.PrintAttributes;
|
||||
@@ -42,6 +43,7 @@ import android.print.PrintAttributes.MediaSize;
|
||||
import android.print.PrintDocumentAdapter;
|
||||
import android.print.PrintDocumentInfo;
|
||||
import android.print.PrintJobInfo;
|
||||
import android.print.PrinterCapabilitiesInfo;
|
||||
import android.print.PrinterId;
|
||||
import android.print.PrinterInfo;
|
||||
import android.text.Editable;
|
||||
@@ -70,6 +72,7 @@ import android.widget.TextView;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
@@ -133,7 +136,7 @@ public class PrintJobConfigActivity extends Activity {
|
||||
private Editor mEditor;
|
||||
private Document mDocument;
|
||||
private PrintController mController;
|
||||
private PrinterDiscoveryObserver mPrinterDiscoveryObserver;
|
||||
private PrinterDiscoverySessionObserver mPrinterDiscoverySessionObserver;
|
||||
|
||||
private int mPrintJobId;
|
||||
|
||||
@@ -181,8 +184,9 @@ public class PrintJobConfigActivity extends Activity {
|
||||
|
||||
mController.initialize();
|
||||
mEditor.initialize();
|
||||
mPrinterDiscoveryObserver = new PrinterDiscoveryObserver(mEditor, getMainLooper());
|
||||
mSpooler.startPrinterDiscovery(mPrinterDiscoveryObserver);
|
||||
mPrinterDiscoverySessionObserver = new PrinterDiscoverySessionObserver(mEditor,
|
||||
getMainLooper());
|
||||
mSpooler.createPrinterDiscoverySession(mPrinterDiscoverySessionObserver);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -190,9 +194,9 @@ public class PrintJobConfigActivity extends Activity {
|
||||
// We can safely do the work in here since at this point
|
||||
// the system is bound to our (spooler) process which
|
||||
// guarantees that this process will not be killed.
|
||||
mSpooler.stopPrinterDiscovery();
|
||||
mPrinterDiscoveryObserver.destroy();
|
||||
mPrinterDiscoveryObserver = null;
|
||||
mPrinterDiscoverySessionObserver.close();
|
||||
mPrinterDiscoverySessionObserver.destroy();
|
||||
mPrinterDiscoverySessionObserver = null;
|
||||
if (mController.hasStarted()) {
|
||||
mController.finish();
|
||||
}
|
||||
@@ -622,14 +626,15 @@ public class PrintJobConfigActivity extends Activity {
|
||||
SpinnerItem<PrinterInfo> dstItem = mDestinationSpinnerAdapter.getItem(position);
|
||||
if (dstItem != null) {
|
||||
PrinterInfo printer = dstItem.value;
|
||||
mSpooler.setPrintJobPrinterIdNoPersistence(mPrintJobId, printer.getId());
|
||||
printer.getDefaults(mCurrPrintAttributes);
|
||||
if (!printer.hasAllRequiredAttributes()) {
|
||||
mSpooler.setPrintJobPrinterNoPersistence(mPrintJobId, printer.getId());
|
||||
PrinterCapabilitiesInfo capabilities = printer.getCapabilities();
|
||||
if (capabilities == null) {
|
||||
List<PrinterId> printerIds = new ArrayList<PrinterId>();
|
||||
printerIds.add(printer.getId());
|
||||
mSpooler.onReqeustUpdatePrinters(printerIds);
|
||||
mPrinterDiscoverySessionObserver.requestPrinterUpdate(printer.getId());
|
||||
//TODO: We need a timeout for the update.
|
||||
} else {
|
||||
capabilities.getDefaults(mCurrPrintAttributes);
|
||||
if (!mController.hasStarted()) {
|
||||
mController.start();
|
||||
}
|
||||
@@ -1058,8 +1063,8 @@ public class PrintJobConfigActivity extends Activity {
|
||||
|
||||
final int selectedIndex = mDestinationSpinner.getSelectedItemPosition();
|
||||
|
||||
if (selectedIndex < 0 || !mDestinationSpinnerAdapter.getItem(
|
||||
selectedIndex).value.hasAllRequiredAttributes()) {
|
||||
if (selectedIndex < 0 || mDestinationSpinnerAdapter.getItem(
|
||||
selectedIndex).value.getCapabilities() == null) {
|
||||
|
||||
// Destination
|
||||
mDestinationSpinner.setEnabled(false);
|
||||
@@ -1117,7 +1122,8 @@ public class PrintJobConfigActivity extends Activity {
|
||||
} else {
|
||||
PrintAttributes defaultAttributes = mTempPrintAttributes;
|
||||
PrinterInfo printer = mDestinationSpinnerAdapter.getItem(selectedIndex).value;
|
||||
printer.getDefaults(defaultAttributes);
|
||||
PrinterCapabilitiesInfo capabilities = printer.getCapabilities();
|
||||
printer.getCapabilities().getDefaults(defaultAttributes);
|
||||
|
||||
// Destination
|
||||
if (mDestinationSpinnerAdapter.getCount() > 1) {
|
||||
@@ -1130,7 +1136,7 @@ public class PrintJobConfigActivity extends Activity {
|
||||
mCopiesEditText.setEnabled(true);
|
||||
|
||||
// Media size.
|
||||
List<MediaSize> mediaSizes = printer.getMediaSizes();
|
||||
List<MediaSize> mediaSizes = capabilities.getMediaSizes();
|
||||
boolean mediaSizesChanged = false;
|
||||
final int mediaSizeCount = mediaSizes.size();
|
||||
if (mediaSizeCount != mMediaSizeSpinnerAdapter.getCount()) {
|
||||
@@ -1168,7 +1174,7 @@ public class PrintJobConfigActivity extends Activity {
|
||||
}
|
||||
|
||||
// Color mode.
|
||||
final int colorModes = printer.getColorModes();
|
||||
final int colorModes = capabilities.getColorModes();
|
||||
boolean colorModesChanged = false;
|
||||
if (Integer.bitCount(colorModes) != mColorModeSpinnerAdapter.getCount()) {
|
||||
colorModesChanged = true;
|
||||
@@ -1219,7 +1225,7 @@ public class PrintJobConfigActivity extends Activity {
|
||||
}
|
||||
|
||||
// Orientation.
|
||||
final int orientations = printer.getOrientations();
|
||||
final int orientations = capabilities.getOrientations();
|
||||
boolean orientationsChanged = false;
|
||||
if (Integer.bitCount(orientations) != mOrientationSpinnerAdapter.getCount()) {
|
||||
orientationsChanged = true;
|
||||
@@ -1345,7 +1351,7 @@ public class PrintJobConfigActivity extends Activity {
|
||||
}
|
||||
if (!duplicate) {
|
||||
mDestinationSpinnerAdapter.add(new SpinnerItem<PrinterInfo>(
|
||||
addedPrinter, addedPrinter.getId().getPrinterName()));
|
||||
addedPrinter, addedPrinter.getName()));
|
||||
} else {
|
||||
Log.w(LOG_TAG, "Skipping a duplicate printer: " + addedPrinter);
|
||||
}
|
||||
@@ -1470,7 +1476,7 @@ public class PrintJobConfigActivity extends Activity {
|
||||
|
||||
PrinterInfo printerInfo = getItem(position).value;
|
||||
TextView title = (TextView) convertView.findViewById(R.id.title);
|
||||
title.setText(printerInfo.getId().getPrinterName());
|
||||
title.setText(printerInfo.getName());
|
||||
|
||||
try {
|
||||
TextView subtitle = (TextView)
|
||||
@@ -1489,21 +1495,35 @@ public class PrintJobConfigActivity extends Activity {
|
||||
}
|
||||
}
|
||||
|
||||
private static final class PrinterDiscoveryObserver extends IPrinterDiscoveryObserver.Stub {
|
||||
private static final int MSG_ON_PRINTERS_ADDED = 1;
|
||||
private static final int MSG_ON_PRINTERS_REMOVED = 2;
|
||||
private static final int MSG_ON_PRINTERS_UPDATED = 3;
|
||||
private static final class PrinterDiscoverySessionObserver
|
||||
extends IPrinterDiscoverySessionObserver.Stub {
|
||||
private static final int MSG_SET_CONTROLLER = 1;
|
||||
private static final int MSG_ON_PRINTERS_ADDED = 2;
|
||||
private static final int MSG_ON_PRINTERS_REMOVED = 3;
|
||||
private static final int MSG_ON_PRINTERS_UPDATED = 4;
|
||||
|
||||
private Handler mHandler;
|
||||
private Editor mEditor;
|
||||
private IPrinterDiscoverySessionController mController;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public PrinterDiscoveryObserver(Editor editor, Looper looper) {
|
||||
public PrinterDiscoverySessionObserver(Editor editor, Looper looper) {
|
||||
mEditor = editor;
|
||||
mHandler = new Handler(looper, null, true) {
|
||||
@Override
|
||||
public void handleMessage(Message message) {
|
||||
switch (message.what) {
|
||||
case MSG_SET_CONTROLLER: {
|
||||
mController = (IPrinterDiscoverySessionController) message.obj;
|
||||
// TODO: This should be cleaned up
|
||||
List<PrinterId> printerIds = Collections.emptyList();
|
||||
try {
|
||||
mController.open(printerIds);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(LOG_TAG, "Error starting printer discovery");
|
||||
}
|
||||
} break;
|
||||
|
||||
case MSG_ON_PRINTERS_ADDED: {
|
||||
List<PrinterInfo> printers = (List<PrinterInfo>) message.obj;
|
||||
mEditor.addPrinters(printers);
|
||||
@@ -1523,6 +1543,46 @@ public class PrintJobConfigActivity extends Activity {
|
||||
};
|
||||
}
|
||||
|
||||
public void open(List<PrinterId> priorityList) {
|
||||
if (mController != null) {
|
||||
try {
|
||||
mController.open(priorityList);
|
||||
} catch (RemoteException re) {
|
||||
Log.e(LOG_TAG, "Error closing printer discovery session", re);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void close() {
|
||||
if (mController != null) {
|
||||
try {
|
||||
mController.close();
|
||||
} catch (RemoteException re) {
|
||||
Log.e(LOG_TAG, "Error closing printer discovery session", re);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void requestPrinterUpdate(PrinterId printerId) {
|
||||
if (mController != null) {
|
||||
try {
|
||||
mController.requestPrinterUpdate(printerId);
|
||||
} catch (RemoteException re) {
|
||||
Log.e(LOG_TAG, "Error requestin printer update", re);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setController(IPrinterDiscoverySessionController controller) {
|
||||
synchronized (this) {
|
||||
if (mHandler != null) {
|
||||
mHandler.obtainMessage(MSG_SET_CONTROLLER, controller)
|
||||
.sendToTarget();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPrintersAdded(List<PrinterInfo> printers) {
|
||||
synchronized (this) {
|
||||
|
||||
@@ -21,7 +21,7 @@ import android.content.Context;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.print.IPrintClient;
|
||||
import android.print.IPrinterDiscoveryObserver;
|
||||
import android.print.IPrinterDiscoverySessionObserver;
|
||||
import android.print.PageRange;
|
||||
import android.print.PrintAttributes;
|
||||
import android.print.PrintAttributes.Margins;
|
||||
@@ -32,6 +32,7 @@ import android.print.PrintDocumentInfo;
|
||||
import android.print.PrintJobInfo;
|
||||
import android.print.PrintManager;
|
||||
import android.print.PrinterId;
|
||||
import android.print.PrinterInfo;
|
||||
import android.util.AtomicFile;
|
||||
import android.util.Log;
|
||||
import android.util.Slog;
|
||||
@@ -199,16 +200,8 @@ public class PrintSpooler {
|
||||
}
|
||||
}
|
||||
|
||||
public void startPrinterDiscovery(IPrinterDiscoveryObserver observer) {
|
||||
mService.startPrinterDiscovery(observer);
|
||||
}
|
||||
|
||||
public void stopPrinterDiscovery() {
|
||||
mService.stopPrinterDiscovery();
|
||||
}
|
||||
|
||||
public void onReqeustUpdatePrinters(List<PrinterId> printerIds) {
|
||||
mService.onReqeustUpdatePrinters(printerIds);
|
||||
public void createPrinterDiscoverySession(IPrinterDiscoverySessionObserver observer) {
|
||||
mService.createPrinterDiscoverySession(observer);
|
||||
}
|
||||
|
||||
private int generatePrintJobIdLocked() {
|
||||
@@ -417,11 +410,12 @@ public class PrintSpooler {
|
||||
}
|
||||
}
|
||||
|
||||
public void setPrintJobPrinterIdNoPersistence(int printJobId, PrinterId printerId) {
|
||||
public void setPrintJobPrinterNoPersistence(int printJobId, PrinterInfo printer) {
|
||||
synchronized (mLock) {
|
||||
PrintJobInfo printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY);
|
||||
if (printJob != null) {
|
||||
printJob.setPrinterId(printerId);
|
||||
printJob.setPrinterId(printer.getId());
|
||||
printJob.setPrinterName(printer.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -500,6 +494,7 @@ public class PrintSpooler {
|
||||
private static final String ATTR_START = "start";
|
||||
private static final String ATTR_END = "end";
|
||||
|
||||
private static final String ATTR_NAME = "name";
|
||||
private static final String ATTR_PAGE_COUNT = "pageCount";
|
||||
private static final String ATTR_CONTENT_TYPE = "contentType";
|
||||
|
||||
@@ -573,7 +568,7 @@ public class PrintSpooler {
|
||||
PrinterId printerId = printJob.getPrinterId();
|
||||
if (printerId != null) {
|
||||
serializer.startTag(null, TAG_PRINTER_ID);
|
||||
serializer.attribute(null, ATTR_PRINTER_NAME, printerId.getPrinterName());
|
||||
serializer.attribute(null, ATTR_PRINTER_NAME, printerId.getLocalId());
|
||||
serializer.attribute(null, ATTR_SERVICE_NAME, printerId.getServiceName()
|
||||
.flattenToString());
|
||||
serializer.endTag(null, TAG_PRINTER_ID);
|
||||
@@ -675,6 +670,7 @@ public class PrintSpooler {
|
||||
PrintDocumentInfo documentInfo = printJob.getDocumentInfo();
|
||||
if (documentInfo != null) {
|
||||
serializer.startTag(null, TAG_DOCUMENT_INFO);
|
||||
serializer.attribute(null, ATTR_NAME, documentInfo.getName());
|
||||
serializer.attribute(null, ATTR_CONTENT_TYPE, String.valueOf(
|
||||
documentInfo.getContentType()));
|
||||
serializer.attribute(null, ATTR_PAGE_COUNT, String.valueOf(
|
||||
@@ -921,11 +917,13 @@ public class PrintSpooler {
|
||||
|
||||
skipEmptyTextTags(parser);
|
||||
if (accept(parser, XmlPullParser.START_TAG, TAG_DOCUMENT_INFO)) {
|
||||
String name = parser.getAttributeValue(null, ATTR_NAME);
|
||||
final int pageCount = Integer.parseInt(parser.getAttributeValue(null,
|
||||
ATTR_PAGE_COUNT));
|
||||
final int contentType = Integer.parseInt(parser.getAttributeValue(null,
|
||||
ATTR_CONTENT_TYPE));
|
||||
PrintDocumentInfo info = new PrintDocumentInfo.Builder().setPageCount(pageCount)
|
||||
PrintDocumentInfo info = new PrintDocumentInfo.Builder(name)
|
||||
.setPageCount(pageCount)
|
||||
.setContentType(contentType).create();
|
||||
printJob.setDocumentInfo(info);
|
||||
parser.next();
|
||||
|
||||
@@ -32,10 +32,9 @@ import android.print.IPrintDocumentAdapter;
|
||||
import android.print.IPrintSpooler;
|
||||
import android.print.IPrintSpoolerCallbacks;
|
||||
import android.print.IPrintSpoolerClient;
|
||||
import android.print.IPrinterDiscoveryObserver;
|
||||
import android.print.IPrinterDiscoverySessionObserver;
|
||||
import android.print.PrintAttributes;
|
||||
import android.print.PrintJobInfo;
|
||||
import android.print.PrinterId;
|
||||
import android.util.Log;
|
||||
import android.util.Slog;
|
||||
|
||||
@@ -167,20 +166,11 @@ public final class PrintSpoolerService extends Service {
|
||||
printJob).sendToTarget();
|
||||
}
|
||||
|
||||
public void onReqeustUpdatePrinters(List<PrinterId> printers) {
|
||||
mHandler.obtainMessage(MyHandler.MSG_ON_REQUEST_UPDATE_PRINTERS,
|
||||
printers).sendToTarget();
|
||||
}
|
||||
|
||||
public void startPrinterDiscovery(IPrinterDiscoveryObserver observer) {
|
||||
mHandler.obtainMessage(MyHandler.MSG_ON_START_PRINTER_DISCOVERY,
|
||||
public void createPrinterDiscoverySession(IPrinterDiscoverySessionObserver observer) {
|
||||
mHandler.obtainMessage(MyHandler.MSG_CREATE_PRINTER_DISCOVERY_SESSION,
|
||||
observer).sendToTarget();
|
||||
}
|
||||
|
||||
public void stopPrinterDiscovery() {
|
||||
mHandler.sendEmptyMessage(MyHandler.MSG_ON_STOP_PRINTER_DISCOVERY);
|
||||
}
|
||||
|
||||
public void onAllPrintJobsForServiceHandled(ComponentName service) {
|
||||
mHandler.obtainMessage(MyHandler.MSG_ON_ALL_PRINT_JOBS_FOR_SERIVICE_HANDLED,
|
||||
service).sendToTarget();
|
||||
@@ -193,12 +183,10 @@ public final class PrintSpoolerService extends Service {
|
||||
private final class MyHandler extends Handler {
|
||||
public static final int MSG_SET_CLIENT = 1;
|
||||
public static final int MSG_START_PRINT_JOB_CONFIG_ACTIVITY = 2;
|
||||
public static final int MSG_ON_START_PRINTER_DISCOVERY = 3;
|
||||
public static final int MSG_ON_STOP_PRINTER_DISCOVERY = 4;
|
||||
public static final int MSG_CREATE_PRINTER_DISCOVERY_SESSION = 3;
|
||||
public static final int MSG_ON_PRINT_JOB_QUEUED = 5;
|
||||
public static final int MSG_ON_ALL_PRINT_JOBS_FOR_SERIVICE_HANDLED = 6;
|
||||
public static final int MSG_ON_ALL_PRINT_JOBS_HANDLED = 7;
|
||||
public static final int MSG_ON_REQUEST_UPDATE_PRINTERS = 8;
|
||||
public static final int MSG_CHECK_ALL_PRINTJOBS_HANDLED = 9;
|
||||
|
||||
public MyHandler(Looper looper) {
|
||||
@@ -206,7 +194,6 @@ public final class PrintSpoolerService extends Service {
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void handleMessage(Message message) {
|
||||
switch (message.what) {
|
||||
case MSG_SET_CLIENT: {
|
||||
@@ -233,23 +220,14 @@ public final class PrintSpoolerService extends Service {
|
||||
}
|
||||
} break;
|
||||
|
||||
case MSG_ON_START_PRINTER_DISCOVERY: {
|
||||
IPrinterDiscoveryObserver observer = (IPrinterDiscoveryObserver) message.obj;
|
||||
case MSG_CREATE_PRINTER_DISCOVERY_SESSION: {
|
||||
IPrinterDiscoverySessionObserver observer =
|
||||
(IPrinterDiscoverySessionObserver) message.obj;
|
||||
if (mClient != null) {
|
||||
try {
|
||||
mClient.onStartPrinterDiscovery(observer);
|
||||
mClient.createPrinterDiscoverySession(observer);
|
||||
} catch (RemoteException re) {
|
||||
Log.e(LOG_TAG, "Error notifying start printer discovery.", re);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
case MSG_ON_STOP_PRINTER_DISCOVERY: {
|
||||
if (mClient != null) {
|
||||
try {
|
||||
mClient.onStopPrinterDiscovery();
|
||||
} catch (RemoteException re) {
|
||||
Log.e(LOG_TAG, "Error notifying stop printer discovery.", re);
|
||||
Log.e(LOG_TAG, "Error creating printer discovery session.", re);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
@@ -287,17 +265,6 @@ public final class PrintSpoolerService extends Service {
|
||||
}
|
||||
} break;
|
||||
|
||||
case MSG_ON_REQUEST_UPDATE_PRINTERS: {
|
||||
List<PrinterId> printerIds = (List<PrinterId>) message.obj;
|
||||
if (mClient != null) {
|
||||
try {
|
||||
mClient.onRequestUpdatePrinters(printerIds);
|
||||
} catch (RemoteException re) {
|
||||
Slog.e(LOG_TAG, "Error requesting to update pritners.", re);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
case MSG_CHECK_ALL_PRINTJOBS_HANDLED: {
|
||||
PrintSpooler spooler = PrintSpooler.peekInstance();
|
||||
if (spooler != null) {
|
||||
|
||||
@@ -24,13 +24,14 @@ import android.os.Binder;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.IBinder.DeathRecipient;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.os.RemoteException;
|
||||
import android.os.UserHandle;
|
||||
import android.os.IBinder.DeathRecipient;
|
||||
import android.print.IPrinterDiscoveryObserver;
|
||||
import android.print.IPrinterDiscoverySessionController;
|
||||
import android.print.IPrinterDiscoverySessionObserver;
|
||||
import android.print.PrintJobInfo;
|
||||
import android.print.PrintManager;
|
||||
import android.print.PrinterId;
|
||||
@@ -128,18 +129,18 @@ final class RemotePrintService implements DeathRecipient {
|
||||
printJob).sendToTarget();
|
||||
}
|
||||
|
||||
private void handleOnRequestCancelPrintJob(final PrintJobInfo printJob) {
|
||||
private void handleRequestCancelPrintJob(final PrintJobInfo printJob) {
|
||||
throwIfDestroyed();
|
||||
// If we are not bound, then we have no print jobs to handle
|
||||
// which means that there are no print jobs to be cancelled.
|
||||
if (isBound()) {
|
||||
if (DEBUG) {
|
||||
Slog.i(LOG_TAG, "[user: " + mUserId + "] handleOnRequestCancelPrintJob()");
|
||||
Slog.i(LOG_TAG, "[user: " + mUserId + "] handleRequestCancelPrintJob()");
|
||||
}
|
||||
try {
|
||||
mPrintService.onRequestCancelPrintJob(printJob);
|
||||
mPrintService.requestCancelPrintJob(printJob);
|
||||
} catch (RemoteException re) {
|
||||
Slog.e(LOG_TAG, "Error canceling pring job.", re);
|
||||
Slog.e(LOG_TAG, "Error canceling a pring job.", re);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -171,85 +172,34 @@ final class RemotePrintService implements DeathRecipient {
|
||||
}
|
||||
}
|
||||
|
||||
public void onStartPrinterDiscovery(IPrinterDiscoveryObserver observer) {
|
||||
mHandler.obtainMessage(MyHandler.MSG_ON_START_PRINTER_DISCOVERY, observer).sendToTarget();
|
||||
public void createPrinterDiscoverySession(IPrinterDiscoverySessionObserver observer) {
|
||||
mHandler.obtainMessage(MyHandler.MSG_CREATE_PRINTER_DISCOVERY_SESSION,
|
||||
observer).sendToTarget();
|
||||
}
|
||||
|
||||
private void handleOnStartPrinterDiscovery(final IPrinterDiscoveryObserver observer) {
|
||||
private void handleCreatePrinterDiscoverySession(
|
||||
final IPrinterDiscoverySessionObserver observer) {
|
||||
throwIfDestroyed();
|
||||
if (!isBound()) {
|
||||
ensureBound();
|
||||
mPendingCommands.add(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
handleOnStartPrinterDiscovery(observer);
|
||||
handleCreatePrinterDiscoverySession(observer);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if (DEBUG) {
|
||||
Slog.i(LOG_TAG, "[user: " + mUserId + "] onStartPrinterDiscovery()");
|
||||
Slog.i(LOG_TAG, "[user: " + mUserId + "] createPrinterDiscoverySession()");
|
||||
}
|
||||
try {
|
||||
mPrintService.onStartPrinterDiscovery(observer);
|
||||
mPrintService.createPrinterDiscoverySession(observer);
|
||||
} catch (RemoteException re) {
|
||||
Slog.e(LOG_TAG, "Error announcing start printer dicovery.", re);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void onStopPrinterDiscovery() {
|
||||
mHandler.sendEmptyMessage(MyHandler.MSG_ON_STOP_PRINTER_DISCOVERY);
|
||||
}
|
||||
|
||||
private void handleStopPrinterDiscovery() {
|
||||
throwIfDestroyed();
|
||||
if (!isBound()) {
|
||||
ensureBound();
|
||||
mPendingCommands.add(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
handleStopPrinterDiscovery();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if (DEBUG) {
|
||||
Slog.i(LOG_TAG, "[user: " + mUserId + "] onStopPrinterDiscovery()");
|
||||
}
|
||||
try {
|
||||
mPrintService.onStopPrinterDiscovery();
|
||||
} catch (RemoteException re) {
|
||||
Slog.e(LOG_TAG, "Error announcing stop printer dicovery.", re);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void onRequestUpdatePrinters(List<PrinterId> printerIds) {
|
||||
mHandler.obtainMessage(MyHandler.MSG_ON_REQUEST_UPDATE_PRINTERS,
|
||||
printerIds).sendToTarget();
|
||||
}
|
||||
|
||||
private void handleReqeustUpdatePrinters(final List<PrinterId> printerIds) {
|
||||
throwIfDestroyed();
|
||||
if (!isBound()) {
|
||||
ensureBound();
|
||||
mPendingCommands.add(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
handleReqeustUpdatePrinters(printerIds);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if (DEBUG) {
|
||||
Slog.i(LOG_TAG, "[user: " + mUserId + "] handleReqeustUpdatePrinters()");
|
||||
}
|
||||
try {
|
||||
mPrintService.onRequestUpdatePrinters(printerIds);
|
||||
} catch (RemoteException re) {
|
||||
Slog.e(LOG_TAG, "Error requesting to update printers.", re);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isBound() {
|
||||
return mPrintService != null;
|
||||
}
|
||||
@@ -331,18 +281,15 @@ final class RemotePrintService implements DeathRecipient {
|
||||
public static final int MSG_ON_ALL_PRINT_JOBS_HANDLED = 1;
|
||||
public static final int MSG_ON_REQUEST_CANCEL_PRINT_JOB = 2;
|
||||
public static final int MSG_ON_PRINT_JOB_QUEUED = 3;
|
||||
public static final int MSG_ON_START_PRINTER_DISCOVERY = 4;
|
||||
public static final int MSG_ON_STOP_PRINTER_DISCOVERY = 5;
|
||||
public static final int MSG_ON_REQUEST_UPDATE_PRINTERS = 6;
|
||||
public static final int MSG_DESTROY = 7;
|
||||
public static final int MSG_BINDER_DIED = 8;
|
||||
public static final int MSG_CREATE_PRINTER_DISCOVERY_SESSION = 4;
|
||||
public static final int MSG_DESTROY = 6;
|
||||
public static final int MSG_BINDER_DIED = 7;
|
||||
|
||||
public MyHandler(Looper looper) {
|
||||
super(looper, null, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void handleMessage(Message message) {
|
||||
switch (message.what) {
|
||||
case MSG_ON_ALL_PRINT_JOBS_HANDLED: {
|
||||
@@ -351,7 +298,7 @@ final class RemotePrintService implements DeathRecipient {
|
||||
|
||||
case MSG_ON_REQUEST_CANCEL_PRINT_JOB: {
|
||||
PrintJobInfo printJob = (PrintJobInfo) message.obj;
|
||||
handleOnRequestCancelPrintJob(printJob);
|
||||
handleRequestCancelPrintJob(printJob);
|
||||
} break;
|
||||
|
||||
case MSG_ON_PRINT_JOB_QUEUED: {
|
||||
@@ -359,21 +306,13 @@ final class RemotePrintService implements DeathRecipient {
|
||||
handleOnPrintJobQueued(printJob);
|
||||
} break;
|
||||
|
||||
case MSG_ON_START_PRINTER_DISCOVERY: {
|
||||
IPrinterDiscoveryObserver observer = (IPrinterDiscoveryObserver) message.obj;
|
||||
handleOnStartPrinterDiscovery(new SecurePrinterDiscoveryObserver(
|
||||
case MSG_CREATE_PRINTER_DISCOVERY_SESSION: {
|
||||
IPrinterDiscoverySessionObserver observer =
|
||||
(IPrinterDiscoverySessionObserver) message.obj;
|
||||
handleCreatePrinterDiscoverySession(new SecurePrinterDiscoverySessionObserver(
|
||||
mComponentName, observer));
|
||||
} break;
|
||||
|
||||
case MSG_ON_REQUEST_UPDATE_PRINTERS: {
|
||||
List<PrinterId> printerIds = (List<PrinterId>) message.obj;
|
||||
handleReqeustUpdatePrinters(printerIds);
|
||||
} break;
|
||||
|
||||
case MSG_ON_STOP_PRINTER_DISCOVERY: {
|
||||
handleStopPrinterDiscovery();
|
||||
} break;
|
||||
|
||||
case MSG_DESTROY: {
|
||||
handleDestroy();
|
||||
} break;
|
||||
@@ -464,14 +403,14 @@ final class RemotePrintService implements DeathRecipient {
|
||||
}
|
||||
}
|
||||
|
||||
private static final class SecurePrinterDiscoveryObserver
|
||||
extends IPrinterDiscoveryObserver.Stub {
|
||||
private static final class SecurePrinterDiscoverySessionObserver
|
||||
extends IPrinterDiscoverySessionObserver.Stub {
|
||||
private final ComponentName mComponentName;
|
||||
|
||||
private final IPrinterDiscoveryObserver mDecoratedObsever;
|
||||
private final IPrinterDiscoverySessionObserver mDecoratedObsever;
|
||||
|
||||
public SecurePrinterDiscoveryObserver(ComponentName componentName,
|
||||
IPrinterDiscoveryObserver observer) {
|
||||
public SecurePrinterDiscoverySessionObserver(ComponentName componentName,
|
||||
IPrinterDiscoverySessionObserver observer) {
|
||||
mComponentName = componentName;
|
||||
mDecoratedObsever = observer;
|
||||
}
|
||||
@@ -506,6 +445,15 @@ final class RemotePrintService implements DeathRecipient {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setController(IPrinterDiscoverySessionController controller) {
|
||||
try {
|
||||
mDecoratedObsever.setController(controller);
|
||||
} catch (RemoteException re) {
|
||||
Slog.e(LOG_TAG, "Error setting controller", re);
|
||||
}
|
||||
}
|
||||
|
||||
private void throwIfPrinterIdsForPrinterInfoTampered(
|
||||
List<PrinterInfo> printerInfos) {
|
||||
final int printerInfoCount = printerInfos.size();
|
||||
|
||||
@@ -32,10 +32,9 @@ import android.print.IPrintDocumentAdapter;
|
||||
import android.print.IPrintSpooler;
|
||||
import android.print.IPrintSpoolerCallbacks;
|
||||
import android.print.IPrintSpoolerClient;
|
||||
import android.print.IPrinterDiscoveryObserver;
|
||||
import android.print.IPrinterDiscoverySessionObserver;
|
||||
import android.print.PrintAttributes;
|
||||
import android.print.PrintJobInfo;
|
||||
import android.print.PrinterId;
|
||||
import android.util.Slog;
|
||||
import android.util.TimedRemoteCaller;
|
||||
|
||||
@@ -92,10 +91,8 @@ final class RemotePrintSpooler {
|
||||
|
||||
public static interface PrintSpoolerCallbacks {
|
||||
public void onPrintJobQueued(PrintJobInfo printJob);
|
||||
public void onStartPrinterDiscovery(IPrinterDiscoveryObserver observer);
|
||||
public void onStopPrinterDiscovery();
|
||||
public void onAllPrintJobsForServiceHandled(ComponentName printService);
|
||||
public void onRequestUpdatePrinters(List<PrinterId> printerIds);
|
||||
public void createPrinterDiscoverySession(IPrinterDiscoverySessionObserver observer);
|
||||
}
|
||||
|
||||
public RemotePrintSpooler(Context context, int userId,
|
||||
@@ -600,38 +597,12 @@ final class RemotePrintSpooler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartPrinterDiscovery(IPrinterDiscoveryObserver observer) {
|
||||
public void createPrinterDiscoverySession(IPrinterDiscoverySessionObserver observer) {
|
||||
RemotePrintSpooler spooler = mWeakSpooler.get();
|
||||
if (spooler != null) {
|
||||
final long identity = Binder.clearCallingIdentity();
|
||||
try {
|
||||
spooler.mCallbacks.onStartPrinterDiscovery(observer);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(identity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStopPrinterDiscovery() {
|
||||
RemotePrintSpooler spooler = mWeakSpooler.get();
|
||||
if (spooler != null) {
|
||||
final long identity = Binder.clearCallingIdentity();
|
||||
try {
|
||||
spooler.mCallbacks.onStopPrinterDiscovery();
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(identity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestUpdatePrinters(List<PrinterId> printerIds) {
|
||||
RemotePrintSpooler spooler = mWeakSpooler.get();
|
||||
if (spooler != null) {
|
||||
final long identity = Binder.clearCallingIdentity();
|
||||
try {
|
||||
spooler.mCallbacks.onRequestUpdatePrinters(printerIds);
|
||||
spooler.mCallbacks.createPrinterDiscoverySession(observer);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(identity);
|
||||
}
|
||||
|
||||
@@ -21,9 +21,8 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.print.IPrinterDiscoveryObserver;
|
||||
import android.print.IPrinterDiscoverySessionObserver;
|
||||
import android.print.PrintJobInfo;
|
||||
import android.print.PrinterId;
|
||||
import android.printservice.PrintServiceInfo;
|
||||
import android.provider.Settings;
|
||||
import android.text.TextUtils;
|
||||
@@ -106,7 +105,7 @@ final class UserState implements PrintSpoolerCallbacks {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartPrinterDiscovery(IPrinterDiscoveryObserver observer) {
|
||||
public void createPrinterDiscoverySession(IPrinterDiscoverySessionObserver observer) {
|
||||
final List<RemotePrintService> services;
|
||||
synchronized (mLock) {
|
||||
throwIfDestroyedLocked();
|
||||
@@ -118,39 +117,7 @@ final class UserState implements PrintSpoolerCallbacks {
|
||||
final int serviceCount = services.size();
|
||||
for (int i = 0; i < serviceCount; i++) {
|
||||
RemotePrintService service = services.get(i);
|
||||
service.onStartPrinterDiscovery(observer);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStopPrinterDiscovery() {
|
||||
final List<RemotePrintService> services;
|
||||
synchronized (mLock) {
|
||||
throwIfDestroyedLocked();
|
||||
if (mActiveServices.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
services = new ArrayList<RemotePrintService>(mActiveServices.values());
|
||||
}
|
||||
final int serviceCount = services.size();
|
||||
for (int i = 0; i < serviceCount; i++) {
|
||||
RemotePrintService service = services.get(i);
|
||||
service.onStopPrinterDiscovery();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestUpdatePrinters(List<PrinterId> printerIds) {
|
||||
final RemotePrintService service;
|
||||
synchronized (mLock) {
|
||||
throwIfDestroyedLocked();
|
||||
if (mActiveServices.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
service = mActiveServices.get(printerIds.get(0).getServiceName());
|
||||
}
|
||||
if (service != null) {
|
||||
service.onRequestUpdatePrinters(printerIds);
|
||||
service.createPrinterDiscoverySession(observer);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user