Merge "Iteration of the print sub-system."

This commit is contained in:
Svetoslav Ganov
2013-08-01 02:16:19 +00:00
committed by Android (Google) Code Review
12 changed files with 605 additions and 192 deletions

View File

@@ -18741,6 +18741,7 @@ package android.print {
method public java.util.List<android.print.PrintAttributes.Tray> getOutputTrays();
method public java.util.List<android.print.PrintAttributes.Resolution> getResolutions();
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
@@ -18826,9 +18827,11 @@ package android.printservice {
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>);
field public static final java.lang.String SERVICE_INTERFACE = "android.printservice.PrintService";
field public static final java.lang.String SERVICE_META_DATA = "android.printservice";
}

View File

@@ -18,6 +18,7 @@ package android.print;
import android.content.ComponentName;
import android.print.IPrinterDiscoveryObserver;
import android.print.PrinterId;
import android.print.PrintJobInfo;
@@ -30,6 +31,7 @@ oneway interface IPrintSpoolerClient {
void onPrintJobQueued(in PrintJobInfo printJob);
void onStartPrinterDiscovery(IPrinterDiscoveryObserver observer);
void onStopPrinterDiscovery();
void onRequestUpdatePrinters(in List<PrinterId> printerIds);
void onAllPrintJobsForServiceHandled(in ComponentName printService);
void onAllPrintJobsHandled();
}

View File

@@ -25,6 +25,7 @@ import android.print.PrinterInfo;
* @hide
*/
oneway interface IPrinterDiscoveryObserver {
void addDiscoveredPrinters(in List<PrinterInfo> printers);
void removeDiscoveredPrinters(in List<PrinterId> printers);
void onPrintersAdded(in List<PrinterInfo> printers);
void onPrintersRemoved(in List<PrinterId> printers);
void onPrintersUpdated(in List<PrinterInfo> printers);
}

View File

@@ -19,6 +19,7 @@ package android.print;
import android.content.ComponentName;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
/**
* This class represents the unique id of a printer.
@@ -98,7 +99,7 @@ public final class PrinterId implements Parcelable {
} else if (!mServiceComponentName.equals(other.mServiceComponentName)) {
return false;
}
if (mLocalId != other.mLocalId) {
if (!TextUtils.equals(mLocalId, other.mLocalId)) {
return false;
}
return true;

View File

@@ -23,9 +23,9 @@ import android.print.PrintAttributes.MediaSize;
import android.print.PrintAttributes.Resolution;
import android.print.PrintAttributes.Tray;
import android.text.TextUtils;
import android.util.SparseIntArray;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
@@ -49,19 +49,22 @@ public final class PrinterInfo implements Parcelable {
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 CharSequence mLabel;
private int mStatus;
private Margins mMinMargins;
private final List<MediaSize> mMediaSizes = new ArrayList<MediaSize>(); // required
private final List<Resolution> mResolutions = new ArrayList<Resolution>(); // required
private Margins mMinMargins = DEFAULT_MARGINS;
private List<MediaSize> mMediaSizes;
private List<Resolution> mResolutions;
private List<Tray> mInputTrays;
private List<Tray> mOutputTrays;
@@ -70,43 +73,83 @@ public final class PrinterInfo implements Parcelable {
private int mFittingModes;
private int mOrientations;
private final SparseIntArray mDefaults = new SparseIntArray();
private Margins mDefaultMargins;
private final int[] mDefaults = new int[PROPERTY_COUNT];
private Margins mDefaultMargins = DEFAULT_MARGINS;
private PrinterInfo() {
mDefaults.put(PROPERTY_MEDIA_SIZE, DEFAULT_UNDEFINED);
mDefaults.put(PROPERTY_RESOLUTION, DEFAULT_UNDEFINED);
mDefaults.put(PROPERTY_INPUT_TRAY, DEFAULT_UNDEFINED);
mDefaults.put(PROPERTY_OUTPUT_TRAY, DEFAULT_UNDEFINED);
mDefaults.put(PROPERTY_DUPLEX_MODE, DEFAULT_UNDEFINED);
mDefaults.put(PROPERTY_COLOR_MODE, DEFAULT_UNDEFINED);
mDefaults.put(PROPERTY_FITTING_MODE, DEFAULT_UNDEFINED);
mDefaults.put(PROPERTY_ORIENTATION, DEFAULT_UNDEFINED);
/**
* @hide
*/
public PrinterInfo() {
Arrays.fill(mDefaults, DEFAULT_UNDEFINED);
}
private PrinterInfo(PrinterInfo prototype) {
mId = prototype.mId;
mLabel = prototype.mLabel;
mStatus = prototype.mStatus;
copyFrom(prototype);
}
mMinMargins = prototype.mMinMargins;
mMediaSizes.addAll(prototype.mMediaSizes);
mResolutions.addAll(prototype.mResolutions);
mInputTrays = (prototype.mInputTrays != null)
? new ArrayList<Tray>(prototype.mInputTrays) : null;
mOutputTrays = (prototype.mOutputTrays != null)
? new ArrayList<Tray>(prototype.mOutputTrays) : null;
/**
* @hide
*/
public void copyFrom(PrinterInfo other) {
mId = other.mId;
mLabel = other.mLabel;
mStatus = other.mStatus;
mDuplexModes = prototype.mDuplexModes;
mColorModes = prototype.mColorModes;
mFittingModes = prototype.mFittingModes;
mOrientations = prototype.mOrientations;
final int defaultCount = prototype.mDefaults.size();
for (int i = 0; i < defaultCount; i++) {
mDefaults.put(prototype.mDefaults.keyAt(i), prototype.mDefaults.valueAt(i));
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;
}
mDefaultMargins = prototype.mDefaultMargins;
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;
}
/**
@@ -240,47 +283,64 @@ public final class PrinterInfo implements Parcelable {
outAttributes.setMargins(mDefaultMargins);
final int mediaSizeIndex = mDefaults.get(PROPERTY_MEDIA_SIZE);
final int mediaSizeIndex = mDefaults[PROPERTY_MEDIA_SIZE];
if (mediaSizeIndex >= 0) {
outAttributes.setMediaSize(mMediaSizes.get(mediaSizeIndex));
}
final int resolutionIndex = mDefaults.get(PROPERTY_RESOLUTION);
final int resolutionIndex = mDefaults[PROPERTY_RESOLUTION];
if (resolutionIndex >= 0) {
outAttributes.setResolution(mResolutions.get(resolutionIndex));
}
final int inputTrayIndex = mDefaults.get(PROPERTY_INPUT_TRAY);
final int inputTrayIndex = mDefaults[PROPERTY_INPUT_TRAY];
if (inputTrayIndex >= 0) {
outAttributes.setInputTray(mInputTrays.get(inputTrayIndex));
}
final int outputTrayIndex = mDefaults.get(PROPERTY_OUTPUT_TRAY);
final int outputTrayIndex = mDefaults[PROPERTY_OUTPUT_TRAY];
if (outputTrayIndex >= 0) {
outAttributes.setOutputTray(mOutputTrays.get(outputTrayIndex));
}
final int duplexMode = mDefaults.get(PROPERTY_DUPLEX_MODE);
final int duplexMode = mDefaults[PROPERTY_DUPLEX_MODE];
if (duplexMode > 0) {
outAttributes.setDuplexMode(duplexMode);
}
final int colorMode = mDefaults.get(PROPERTY_COLOR_MODE);
final int colorMode = mDefaults[PROPERTY_COLOR_MODE];
if (colorMode > 0) {
outAttributes.setColorMode(mColorModes & colorMode);
}
final int fittingMode = mDefaults.get(PROPERTY_FITTING_MODE);
final int fittingMode = mDefaults[PROPERTY_FITTING_MODE];
if (fittingMode > 0) {
outAttributes.setFittingMode(fittingMode);
}
final int orientation = mDefaults.get(PROPERTY_ORIENTATION);
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);
}
private PrinterInfo(Parcel parcel) {
mId = parcel.readParcelable(null);
mLabel = parcel.readCharSequence();
@@ -327,6 +387,112 @@ public final class PrinterInfo implements Parcelable {
writeMargins(mDefaultMargins, parcel);
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((mId == null) ? 0 : mId.hashCode());
result = prime * result + ((mLabel == null) ? 0 : mLabel.hashCode());
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());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
PrinterInfo other = (PrinterInfo) obj;
if (mId == null) {
if (other.mId != null) {
return false;
}
} else if (!mId.equals(other.mId)) {
return false;
}
if (!TextUtils.equals(mLabel, other.mLabel)) {
return false;
}
if (mStatus != other.mStatus) {
return false;
}
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();
@@ -351,12 +517,19 @@ public final class PrinterInfo implements Parcelable {
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++) {
@@ -366,6 +539,9 @@ public final class PrinterInfo implements Parcelable {
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));
}
@@ -435,15 +611,15 @@ public final class PrinterInfo implements Parcelable {
private void readDefaults(Parcel parcel) {
final int defaultCount = parcel.readInt();
for (int i = 0; i < defaultCount; i++) {
mDefaults.append(mDefaults.size(), parcel.readInt());
mDefaults[i] = parcel.readInt();
}
}
private void writeDefaults(Parcel parcel) {
final int defaultCount = mDefaults.size();
final int defaultCount = mDefaults.length;
parcel.writeInt(defaultCount);
for (int i = 0; i < defaultCount; i++) {
parcel.writeInt(mDefaults.valueAt(i));
parcel.writeInt(mDefaults[i]);
}
}
@@ -462,11 +638,11 @@ public final class PrinterInfo implements Parcelable {
/**
* Creates a new instance.
*
* @param printerId The printer id.
* @param label The human readable printer label.
* @param printerId The printer id. Cannot be null.
* @param label The human readable printer label. Cannot be null or empty.
*
* @throws IllegalArgumentException IF the printer id is null.
* @throws IllegalArgumentException IF the label is empty.
* @throws IllegalArgumentException If the printer id is null.
* @throws IllegalArgumentException If the label is empty.
*/
public Builder(PrinterId printerId, CharSequence label) {
if (printerId == null) {
@@ -509,11 +685,14 @@ public final class PrinterInfo implements Parcelable {
* @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.put(PROPERTY_MEDIA_SIZE, insertionIndex);
mPrototype.mDefaults[PROPERTY_MEDIA_SIZE] = insertionIndex;
}
return this;
}
@@ -534,11 +713,14 @@ public final class PrinterInfo implements Parcelable {
* @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.put(PROPERTY_RESOLUTION, insertionIndex);
mPrototype.mDefaults[PROPERTY_RESOLUTION] = insertionIndex;
}
return this;
}
@@ -591,7 +773,7 @@ public final class PrinterInfo implements Parcelable {
mPrototype.mInputTrays.add(inputTray);
if (isDefault) {
throwIfDefaultAlreadySpecified(PROPERTY_INPUT_TRAY);
mPrototype.mDefaults.put(PROPERTY_INPUT_TRAY, insertionIndex);
mPrototype.mDefaults[PROPERTY_INPUT_TRAY] = insertionIndex;
}
return this;
}
@@ -619,7 +801,7 @@ public final class PrinterInfo implements Parcelable {
mPrototype.mOutputTrays.add(outputTray);
if (isDefault) {
throwIfDefaultAlreadySpecified(PROPERTY_OUTPUT_TRAY);
mPrototype.mDefaults.put(PROPERTY_OUTPUT_TRAY, insertionIndex);
mPrototype.mDefaults[PROPERTY_OUTPUT_TRAY] = insertionIndex;
}
return this;
}
@@ -652,7 +834,7 @@ public final class PrinterInfo implements Parcelable {
}
PrintAttributes.enforceValidColorMode(colorModes);
mPrototype.mColorModes = colorModes;
mPrototype.mDefaults.put(PROPERTY_COLOR_MODE, defaultColorMode);
mPrototype.mDefaults[PROPERTY_COLOR_MODE] = defaultColorMode;
return this;
}
@@ -685,7 +867,7 @@ public final class PrinterInfo implements Parcelable {
}
PrintAttributes.enforceValidDuplexMode(defaultDuplexMode);
mPrototype.mDuplexModes = duplexModes;
mPrototype.mDefaults.put(PROPERTY_DUPLEX_MODE, defaultDuplexMode);
mPrototype.mDefaults[PROPERTY_DUPLEX_MODE] = defaultDuplexMode;
return this;
}
@@ -717,7 +899,7 @@ public final class PrinterInfo implements Parcelable {
}
PrintAttributes.enfoceValidFittingMode(defaultFittingMode);
mPrototype.mFittingModes = fittingModes;
mPrototype.mDefaults.put(PROPERTY_FITTING_MODE, defaultFittingMode);
mPrototype.mDefaults[PROPERTY_FITTING_MODE] = defaultFittingMode;
return this;
}
@@ -749,55 +931,21 @@ public final class PrinterInfo implements Parcelable {
}
PrintAttributes.enforceValidOrientation(defaultOrientation);
mPrototype.mOrientations = orientations;
mPrototype.mDefaults.put(PROPERTY_ORIENTATION, defaultOrientation);
mPrototype.mDefaults[PROPERTY_ORIENTATION] = defaultOrientation;
return this;
}
/**
* Crates a new {@link PrinterInfo} enforcing that all required properties
* have need specified. See individual methods in this class for reference
* about required attributes.
* Crates a new {@link PrinterInfo}.
*
* @return A new {@link PrinterInfo}.
*
* @throws IllegalStateException If a required attribute was not specified.
*/
public PrinterInfo create() {
if (mPrototype.mMediaSizes == null || mPrototype.mMediaSizes.isEmpty()) {
throw new IllegalStateException("No media size specified.");
}
if (mPrototype.mDefaults.valueAt(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.valueAt(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.valueAt(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.valueAt(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 PrinterInfo(mPrototype);
}
private void throwIfDefaultAlreadySpecified(int propertyIndex) {
if (mPrototype.mDefaults.get(propertyIndex) != DEFAULT_UNDEFINED) {
if (mPrototype.mDefaults[propertyIndex] != DEFAULT_UNDEFINED) {
throw new IllegalArgumentException("Default already specified.");
}
}

View File

@@ -29,8 +29,9 @@ import android.printservice.IPrintServiceClient;
*/
oneway interface IPrintService {
void setClient(IPrintServiceClient client);
void requestCancelPrintJob(in PrintJobInfo printJobInfo);
void onRequestUpdatePrinters(in List<PrinterId> printerIds);
void onRequestCancelPrintJob(in PrintJobInfo printJobInfo);
void onPrintJobQueued(in PrintJobInfo printJobInfo);
void startPrinterDiscovery(IPrinterDiscoveryObserver observer);
void stopPrinterDiscovery();
void onStartPrinterDiscovery(IPrinterDiscoveryObserver observer);
void onStopPrinterDiscovery();
}

View File

@@ -207,13 +207,14 @@ 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 #addDiscoveredPrinters(List) and reported ones
* that disappear should be reported by calling
* reported by calling {@link #addDiscoveredPrinters(List)} and reported
* ones that disappear should be reported by calling
* {@link #removeDiscoveredPrinters(List)}.
*
* @see #onStopPrinterDiscovery()
* @see #addDiscoveredPrinters(List)
* @see #removeDiscoveredPrinters(List)
* @see #updateDiscoveredPrinters(List)
*/
protected abstract void onStartPrinterDiscovery();
@@ -223,6 +224,7 @@ public abstract class PrintService extends Service {
* @see #onStartPrinterDiscovery()
* @see #addDiscoveredPrinters(List)
* @see #removeDiscoveredPrinters(List)
* @see #updateDiscoveredPrinters(List)
*/
protected abstract void onStopPrinterDiscovery();
@@ -236,12 +238,23 @@ public abstract class PrintService extends Service {
* 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. If you want to update an already
* added printer, you should removed it and then re-add it.
* 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()
@@ -253,7 +266,7 @@ public abstract class PrintService extends Service {
}
if (observer != null) {
try {
observer.addDiscoveredPrinters(printers);
observer.onPrintersAdded(printers);
} catch (RemoteException re) {
Log.e(LOG_TAG, "Error adding discovered printers", re);
}
@@ -271,14 +284,13 @@ public abstract class PrintService extends Service {
* 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 in the same discovery period, it will
* be ignored. If you want to update an already added printer, you should
* removed it and then re-add it.
* 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()
*/
@@ -289,13 +301,72 @@ public abstract class PrintService extends Service {
}
if (observer != null) {
try {
observer.removeDiscoveredPrinters(printerIds);
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
* should do best effort to fulfill the request. After the cancellation
@@ -373,74 +444,87 @@ public abstract class PrintService extends Service {
return new IPrintService.Stub() {
@Override
public void setClient(IPrintServiceClient client) {
mHandler.obtainMessage(MyHandler.MESSAGE_SET_CLEINT, client).sendToTarget();
mHandler.obtainMessage(MyHandler.MSG_SET_CLEINT, client).sendToTarget();
}
@Override
public void startPrinterDiscovery(IPrinterDiscoveryObserver observer) {
mHandler.obtainMessage(MyHandler.MESSAGE_START_PRINTER_DISCOVERY,
public void onStartPrinterDiscovery(IPrinterDiscoveryObserver observer) {
mHandler.obtainMessage(MyHandler.MSG_ON_START_PRINTER_DISCOVERY,
observer).sendToTarget();
}
@Override
public void stopPrinterDiscovery() {
mHandler.sendEmptyMessage(MyHandler.MESSAGE_STOP_PRINTER_DISCOVERY);
public void onStopPrinterDiscovery() {
mHandler.sendEmptyMessage(MyHandler.MSG_ON_STOP_PRINTER_DISCOVERY);
}
@Override
public void requestCancelPrintJob(PrintJobInfo printJobInfo) {
mHandler.obtainMessage(MyHandler.MESSAGE_CANCEL_PRINTJOB,
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,
printJobInfo).sendToTarget();
}
@Override
public void onPrintJobQueued(PrintJobInfo printJobInfo) {
mHandler.obtainMessage(MyHandler.MESSAGE_ON_PRINTJOB_QUEUED,
mHandler.obtainMessage(MyHandler.MSG_ON_PRINTJOB_QUEUED,
printJobInfo).sendToTarget();
}
};
}
private final class MyHandler extends Handler {
public static final int MESSAGE_START_PRINTER_DISCOVERY = 1;
public static final int MESSAGE_STOP_PRINTER_DISCOVERY = 2;
public static final int MESSAGE_CANCEL_PRINTJOB = 3;
public static final int MESSAGE_ON_PRINTJOB_QUEUED = 4;
public static final int MESSAGE_SET_CLEINT = 5;
public static final int MSG_ON_START_PRINTER_DISCOVERY = 1;
public static final int MSG_ON_STOP_PRINTER_DISCOVERY = 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 MyHandler(Looper looper) {
super(looper, null, true);
}
@Override
@SuppressWarnings("unchecked")
public void handleMessage(Message message) {
final int action = message.what;
switch (action) {
case MESSAGE_START_PRINTER_DISCOVERY: {
case MSG_ON_START_PRINTER_DISCOVERY: {
synchronized (mLock) {
mDiscoveryObserver = (IPrinterDiscoveryObserver) message.obj;
}
onStartPrinterDiscovery();
} break;
case MESSAGE_STOP_PRINTER_DISCOVERY: {
case MSG_ON_STOP_PRINTER_DISCOVERY: {
synchronized (mLock) {
mDiscoveryObserver = null;
}
onStopPrinterDiscovery();
} break;
case MESSAGE_CANCEL_PRINTJOB: {
case MSG_ON_REQUEST_CANCEL_PRINTJOB: {
PrintJobInfo printJobInfo = (PrintJobInfo) message.obj;
onRequestCancelPrintJob(new PrintJob(printJobInfo, mClient));
} break;
case MESSAGE_ON_PRINTJOB_QUEUED: {
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));
} break;
case MESSAGE_SET_CLEINT: {
case MSG_SET_CLEINT: {
IPrintServiceClient client = (IPrintServiceClient) message.obj;
synchronized (mLock) {
mClient = client;

View File

@@ -464,7 +464,7 @@ public class PrintJobConfigActivity extends Activity {
} else if (PageRangeUtils.contains(mDocument.pages, mRequestedPages)) {
// We requested specific pages and got more but not all pages.
// Hence, we have to offset appropriately the printed pages to
// exclude the pages we did not request. Note that pages is
// excle the pages we did not request. Note that pages is
// guaranteed to be not null and not empty.
final int offset = mDocument.pages[0].getStart() - pages[0].getStart();
PageRange[] offsetPages = Arrays.copyOf(mDocument.pages, mDocument.pages.length);
@@ -571,16 +571,24 @@ public class PrintJobConfigActivity extends Activity {
mCurrPrintAttributes.clear();
SpinnerItem<PrinterInfo> dstItem = mDestinationSpinnerAdapter.getItem(position);
if (dstItem != null) {
mSpooler.setPrintJobPrinterIdNoPersistence(mPrintJobId, dstItem.value.getId());
dstItem.value.getDefaults(mCurrPrintAttributes);
PrinterInfo printer = dstItem.value;
mSpooler.setPrintJobPrinterIdNoPersistence(mPrintJobId, printer.getId());
printer.getDefaults(mCurrPrintAttributes);
if (!printer.hasAllRequiredAttributes()) {
List<PrinterId> printerIds = new ArrayList<PrinterId>();
printerIds.add(printer.getId());
mSpooler.onReqeustUpdatePrinters(printerIds);
//TODO: We need a timeout for the update.
} else {
if (!mController.hasStarted()) {
mController.start();
}
if (!hasErrors()) {
mController.update();
}
}
}
updateUi();
if (!mController.hasStarted()) {
mController.start();
}
if (!hasErrors()) {
mController.update();
}
} else if (spinner == mMediaSizeSpinner) {
SpinnerItem<MediaSize> mediaItem = mMediaSizeSpinnerAdapter.getItem(position);
mCurrPrintAttributes.setMediaSize(mediaItem.value);
@@ -886,7 +894,9 @@ public class PrintJobConfigActivity extends Activity {
final int selectedIndex = mDestinationSpinner.getSelectedItemPosition();
if (selectedIndex < 0) {
if (selectedIndex < 0 || !mDestinationSpinnerAdapter.getItem(
selectedIndex).value.hasAllRequiredAttributes()) {
// Destination
mDestinationSpinner.setEnabled(false);
@@ -1173,6 +1183,45 @@ public class PrintJobConfigActivity extends Activity {
}
}
@SuppressWarnings("unchecked")
public void updatePrinters(List<PrinterInfo> pritners) {
SpinnerItem<PrinterInfo> selectedItem =
(SpinnerItem<PrinterInfo>) mDestinationSpinner.getSelectedItem();
PrinterId selectedPrinterId = (selectedItem != null)
? selectedItem.value.getId() : null;
boolean updated = false;
final int printerCount = pritners.size();
for (int i = 0; i < printerCount; i++) {
PrinterInfo updatedPrinter = pritners.get(i);
final int existingPrinterCount = mDestinationSpinnerAdapter.getCount();
for (int j = 0; j < existingPrinterCount; j++) {
PrinterInfo existingPrinter = mDestinationSpinnerAdapter.getItem(j).value;
if (updatedPrinter.getId().equals(existingPrinter.getId())) {
existingPrinter.copyFrom(updatedPrinter);
updated = true;
if (selectedPrinterId != null
&& selectedPrinterId.equals(updatedPrinter.getId())) {
// The selected printer was updated. We simulate a fake
// selection to reuse the normal printer change handling.
mOnItemSelectedListener.onItemSelected(mDestinationSpinner,
mDestinationSpinner.getSelectedView(),
mDestinationSpinner.getSelectedItemPosition(),
mDestinationSpinner.getSelectedItemId());
// TODO: This will reset the UI to the defaults for the
// printer. We may need to revisit this.
}
break;
}
}
}
if (updated) {
mDestinationSpinnerAdapter.notifyDataSetChanged();
}
}
private boolean hasErrors() {
return mRangeEditText.getError() != null
|| mCopiesEditText.getError() != null;
@@ -1240,8 +1289,9 @@ public class PrintJobConfigActivity extends Activity {
}
private static final class PrinterDiscoveryObserver extends IPrinterDiscoveryObserver.Stub {
private static final int MESSAGE_ADD_DICOVERED_PRINTERS = 1;
private static final int MESSAGE_REMOVE_DICOVERED_PRINTERS = 2;
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 Handler mHandler;
private Editor mEditor;
@@ -1253,34 +1303,50 @@ public class PrintJobConfigActivity extends Activity {
@Override
public void handleMessage(Message message) {
switch (message.what) {
case MESSAGE_ADD_DICOVERED_PRINTERS: {
case MSG_ON_PRINTERS_ADDED: {
List<PrinterInfo> printers = (List<PrinterInfo>) message.obj;
mEditor.addPrinters(printers);
} break;
case MESSAGE_REMOVE_DICOVERED_PRINTERS: {
case MSG_ON_PRINTERS_REMOVED: {
List<PrinterId> printerIds = (List<PrinterId>) message.obj;
mEditor.removePrinters(printerIds);
} break;
case MSG_ON_PRINTERS_UPDATED: {
List<PrinterInfo> printers = (List<PrinterInfo>) message.obj;
mEditor.updatePrinters(printers);
} break;
}
}
};
}
@Override
public void addDiscoveredPrinters(List<PrinterInfo> printers) {
public void onPrintersAdded(List<PrinterInfo> printers) {
synchronized (this) {
if (mHandler != null) {
mHandler.obtainMessage(MESSAGE_ADD_DICOVERED_PRINTERS, printers)
mHandler.obtainMessage(MSG_ON_PRINTERS_ADDED, printers)
.sendToTarget();
}
}
}
@Override
public void removeDiscoveredPrinters(List<PrinterId> printers) {
public void onPrintersRemoved(List<PrinterId> printers) {
synchronized (this) {
if (mHandler != null) {
mHandler.obtainMessage(MESSAGE_REMOVE_DICOVERED_PRINTERS, printers)
mHandler.obtainMessage(MSG_ON_PRINTERS_REMOVED, printers)
.sendToTarget();
}
}
}
@Override
public void onPrintersUpdated(List<PrinterInfo> printers) {
synchronized (this) {
if (mHandler != null) {
mHandler.obtainMessage(MSG_ON_PRINTERS_UPDATED, printers)
.sendToTarget();
}
}

View File

@@ -118,19 +118,29 @@ public class PrintSpooler {
}
}
public void onReqeustUpdatePrinters(List<PrinterId> printers) {
synchronized (mLock) {
SomeArgs args = SomeArgs.obtain();
args.arg1 = mClient;
args.arg2 = printers;
mHandler.obtainMessage(MyHandler.MSG_REQUEST_UPDATE_PRINTERS,
args).sendToTarget();
}
}
public void startPrinterDiscovery(IPrinterDiscoveryObserver observer) {
synchronized (mLock) {
SomeArgs args = SomeArgs.obtain();
args.arg1 = mClient;
args.arg2 = observer;
mHandler.obtainMessage(MyHandler.MSG_ON_START_PRINTER_DISCOVERY,
mHandler.obtainMessage(MyHandler.MSG_START_PRINTER_DISCOVERY,
args).sendToTarget();
}
}
public void stopPrinterDiscovery() {
synchronized (mLock) {
mHandler.obtainMessage(MyHandler.MSG_ON_STOP_PRINTER_DISCOVERY,
mHandler.obtainMessage(MyHandler.MSG_STOP_PRINTER_DISCOVERY,
mClient).sendToTarget();
}
}
@@ -265,7 +275,7 @@ public class PrintSpooler {
SomeArgs args = SomeArgs.obtain();
args.arg1 = client;
args.arg2 = new PrintJobInfo(printJob);
mHandler.obtainMessage(MyHandler.MSG_ON_PRINT_JOB_QUEUED,
mHandler.obtainMessage(MyHandler.MSG_PRINT_JOB_QUEUED,
args).sendToTarget();
}
}
@@ -273,13 +283,13 @@ public class PrintSpooler {
SomeArgs args = SomeArgs.obtain();
args.arg1 = client;
args.arg2 = service;
mHandler.obtainMessage(MyHandler.MSG_ON_ALL_PRINT_JOBS_FOR_SERIVICE_HANDLED,
mHandler.obtainMessage(MyHandler.MSG_ALL_PRINT_JOBS_FOR_SERIVICE_HANDLED,
args).sendToTarget();
}
}
if (allPrintJobsHandled) {
mHandler.obtainMessage(MyHandler.MSG_ON_ALL_PRINT_JOBS_HANDLED,
mHandler.obtainMessage(MyHandler.MSG_ALL_PRINT_JOBS_HANDLED,
client).sendToTarget();
}
}
@@ -401,12 +411,12 @@ public class PrintSpooler {
args.arg1 = mClient;
args.arg2 = service;
mHandler.obtainMessage(
MyHandler.MSG_ON_ALL_PRINT_JOBS_FOR_SERIVICE_HANDLED,
MyHandler.MSG_ALL_PRINT_JOBS_FOR_SERIVICE_HANDLED,
args).sendToTarget();
}
if (!hasActivePrintJobsLocked()) {
mHandler.obtainMessage(MyHandler.MSG_ON_ALL_PRINT_JOBS_HANDLED,
mHandler.obtainMessage(MyHandler.MSG_ALL_PRINT_JOBS_HANDLED,
mClient).sendToTarget();
}
} break;
@@ -415,7 +425,7 @@ public class PrintSpooler {
SomeArgs args = SomeArgs.obtain();
args.arg1 = mClient;
args.arg2 = new PrintJobInfo(printJob);
mHandler.obtainMessage(MyHandler.MSG_ON_PRINT_JOB_QUEUED,
mHandler.obtainMessage(MyHandler.MSG_PRINT_JOB_QUEUED,
args).sendToTarget();
} break;
}
@@ -1056,20 +1066,22 @@ public class PrintSpooler {
}
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;
public static final int MSG_ON_PRINT_JOB_QUEUED = 3;
public static final int MSG_ON_ALL_PRINT_JOBS_FOR_SERIVICE_HANDLED = 4;
public static final int MSG_ON_ALL_PRINT_JOBS_HANDLED = 5;
public static final int MSG_START_PRINTER_DISCOVERY = 1;
public static final int MSG_STOP_PRINTER_DISCOVERY = 2;
public static final int MSG_PRINT_JOB_QUEUED = 3;
public static final int MSG_ALL_PRINT_JOBS_FOR_SERIVICE_HANDLED = 4;
public static final int MSG_ALL_PRINT_JOBS_HANDLED = 5;
public static final int MSG_REQUEST_UPDATE_PRINTERS = 6;
public MyHandler(Looper looper) {
super(looper, null, false);
}
@Override
@SuppressWarnings("unchecked")
public void handleMessage(Message message) {
switch (message.what) {
case MSG_ON_START_PRINTER_DISCOVERY: {
case MSG_START_PRINTER_DISCOVERY: {
SomeArgs args = (SomeArgs) message.obj;
IPrintSpoolerClient client = (IPrintSpoolerClient) args.arg1;
IPrinterDiscoveryObserver observer = (IPrinterDiscoveryObserver) args.arg2;
@@ -1083,7 +1095,7 @@ public class PrintSpooler {
}
} break;
case MSG_ON_STOP_PRINTER_DISCOVERY: {
case MSG_STOP_PRINTER_DISCOVERY: {
IPrintSpoolerClient client = (IPrintSpoolerClient) message.obj;
if (client != null) {
try {
@@ -1094,7 +1106,7 @@ public class PrintSpooler {
}
} break;
case MSG_ON_PRINT_JOB_QUEUED: {
case MSG_PRINT_JOB_QUEUED: {
SomeArgs args = (SomeArgs) message.obj;
IPrintSpoolerClient client = (IPrintSpoolerClient) args.arg1;
PrintJobInfo printJob = (PrintJobInfo) args.arg2;
@@ -1108,7 +1120,7 @@ public class PrintSpooler {
}
} break;
case MSG_ON_ALL_PRINT_JOBS_FOR_SERIVICE_HANDLED: {
case MSG_ALL_PRINT_JOBS_FOR_SERIVICE_HANDLED: {
SomeArgs args = (SomeArgs) message.obj;
IPrintSpoolerClient client = (IPrintSpoolerClient) args.arg1;
ComponentName service = (ComponentName) args.arg2;
@@ -1117,12 +1129,13 @@ public class PrintSpooler {
try {
client.onAllPrintJobsForServiceHandled(service);
} catch (RemoteException re) {
Slog.e(LOG_TAG, "Error notify for all print jobs per service handled.", re);
Slog.e(LOG_TAG, "Error notify for all print jobs per service"
+ " handled.", re);
}
}
} break;
case MSG_ON_ALL_PRINT_JOBS_HANDLED: {
case MSG_ALL_PRINT_JOBS_HANDLED: {
final IPrintSpoolerClient client = (IPrintSpoolerClient) message.obj;
// This has to run on the tread that is persisting the current state
// since this call may result in the system unbinding from the spooler
@@ -1140,6 +1153,18 @@ public class PrintSpooler {
}
}.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, (Void[]) null);
} break;
case MSG_REQUEST_UPDATE_PRINTERS: {
SomeArgs args = (SomeArgs) message.obj;
IPrintSpoolerClient client = (IPrintSpoolerClient) args.arg1;
List<PrinterId> printerIds = (List<PrinterId>) args.arg2;
args.recycle();
try {
client.onRequestUpdatePrinters(printerIds);
} catch (RemoteException re) {
Slog.e(LOG_TAG, "Error requesting to update pritners.", re);
}
} break;
}
}
}

View File

@@ -100,7 +100,7 @@ final class RemotePrintService implements DeathRecipient {
}
public void onAllPrintJobsHandled() {
mHandler.sendEmptyMessage(MyHandler.MSG_ALL_PRINT_JOBS_HANDLED);
mHandler.sendEmptyMessage(MyHandler.MSG_ON_ALL_PRINT_JOBS_HANDLED);
}
@Override
@@ -109,7 +109,7 @@ final class RemotePrintService implements DeathRecipient {
}
private void handleBinderDied() {
ensureBound();
ensureUnbound();
}
private void handleOnAllPrintJobsHandled() {
@@ -124,7 +124,7 @@ final class RemotePrintService implements DeathRecipient {
}
public void onRequestCancelPrintJob(PrintJobInfo printJob) {
mHandler.obtainMessage(MyHandler.MSG_REQUEST_CANCEL_PRINT_JOB,
mHandler.obtainMessage(MyHandler.MSG_ON_REQUEST_CANCEL_PRINT_JOB,
printJob).sendToTarget();
}
@@ -137,7 +137,7 @@ final class RemotePrintService implements DeathRecipient {
Slog.i(LOG_TAG, "[user: " + mUserId + "] handleOnRequestCancelPrintJob()");
}
try {
mPrintService.requestCancelPrintJob(printJob);
mPrintService.onRequestCancelPrintJob(printJob);
} catch (RemoteException re) {
Slog.e(LOG_TAG, "Error canceling pring job.", re);
}
@@ -145,7 +145,7 @@ final class RemotePrintService implements DeathRecipient {
}
public void onPrintJobQueued(PrintJobInfo printJob) {
mHandler.obtainMessage(MyHandler.MSG_PRINT_JOB_QUEUED,
mHandler.obtainMessage(MyHandler.MSG_ON_PRINT_JOB_QUEUED,
printJob).sendToTarget();
}
@@ -172,7 +172,7 @@ final class RemotePrintService implements DeathRecipient {
}
public void onStartPrinterDiscovery(IPrinterDiscoveryObserver observer) {
mHandler.obtainMessage(MyHandler.MSG_START_PRINTER_DISCOVERY, observer).sendToTarget();
mHandler.obtainMessage(MyHandler.MSG_ON_START_PRINTER_DISCOVERY, observer).sendToTarget();
}
private void handleOnStartPrinterDiscovery(final IPrinterDiscoveryObserver observer) {
@@ -190,7 +190,7 @@ final class RemotePrintService implements DeathRecipient {
Slog.i(LOG_TAG, "[user: " + mUserId + "] onStartPrinterDiscovery()");
}
try {
mPrintService.startPrinterDiscovery(observer);
mPrintService.onStartPrinterDiscovery(observer);
} catch (RemoteException re) {
Slog.e(LOG_TAG, "Error announcing start printer dicovery.", re);
}
@@ -198,7 +198,7 @@ final class RemotePrintService implements DeathRecipient {
}
public void onStopPrinterDiscovery() {
mHandler.sendEmptyMessage(MyHandler.MSG_STOP_PRINTER_DISCOVERY);
mHandler.sendEmptyMessage(MyHandler.MSG_ON_STOP_PRINTER_DISCOVERY);
}
private void handleStopPrinterDiscovery() {
@@ -216,13 +216,40 @@ final class RemotePrintService implements DeathRecipient {
Slog.i(LOG_TAG, "[user: " + mUserId + "] onStopPrinterDiscovery()");
}
try {
mPrintService.stopPrinterDiscovery();
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 handleReqeustUpdatePritners(final List<PrinterId> printerIds) {
throwIfDestroyed();
if (!isBound()) {
ensureBound();
mPendingCommands.add(new Runnable() {
@Override
public void run() {
handleReqeustUpdatePritners(printerIds);
}
});
} else {
if (DEBUG) {
Slog.i(LOG_TAG, "[user: " + mUserId + "] handleReqeustUpdatePritners()");
}
try {
mPrintService.onRequestUpdatePrinters(printerIds);
} catch (RemoteException re) {
Slog.e(LOG_TAG, "Error requesting to update printers.", re);
}
}
}
private boolean isBound() {
return mPrintService != null;
}
@@ -254,6 +281,7 @@ final class RemotePrintService implements DeathRecipient {
} catch (RemoteException re) {
/* ignore */
}
mPrintService.asBinder().unlinkToDeath(this, 0);
mPrintService = null;
mContext.unbindService(mServiceConnection);
}
@@ -273,11 +301,17 @@ final class RemotePrintService implements DeathRecipient {
}
mBinding = false;
mPrintService = IPrintService.Stub.asInterface(service);
try {
service.linkToDeath(RemotePrintService.this, 0);
} catch (RemoteException re) {
handleBinderDied();
return;
}
try {
mPrintService.setClient(mPrintServiceClient);
} catch (RemoteException re) {
Slog.e(LOG_TAG, "Error setting client for: " + service, re);
handleDestroy();
handleBinderDied();
return;
}
final int pendingCommandCount = mPendingCommands.size();
@@ -294,42 +328,49 @@ final class RemotePrintService implements DeathRecipient {
}
private final class MyHandler extends Handler {
public static final int MSG_ALL_PRINT_JOBS_HANDLED = 1;
public static final int MSG_REQUEST_CANCEL_PRINT_JOB = 2;
public static final int MSG_PRINT_JOB_QUEUED = 3;
public static final int MSG_START_PRINTER_DISCOVERY = 4;
public static final int MSG_STOP_PRINTER_DISCOVERY = 5;
public static final int MSG_DESTROY = 6;
public static final int MSG_BINDER_DIED = 7;
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 MyHandler(Looper looper) {
super(looper, null, false);
}
@Override
@SuppressWarnings("unchecked")
public void handleMessage(Message message) {
switch (message.what) {
case MSG_ALL_PRINT_JOBS_HANDLED: {
case MSG_ON_ALL_PRINT_JOBS_HANDLED: {
handleOnAllPrintJobsHandled();
} break;
case MSG_REQUEST_CANCEL_PRINT_JOB: {
case MSG_ON_REQUEST_CANCEL_PRINT_JOB: {
PrintJobInfo printJob = (PrintJobInfo) message.obj;
handleOnRequestCancelPrintJob(printJob);
} break;
case MSG_PRINT_JOB_QUEUED: {
case MSG_ON_PRINT_JOB_QUEUED: {
PrintJobInfo printJob = (PrintJobInfo) message.obj;
handleOnPrintJobQueued(printJob);
} break;
case MSG_START_PRINTER_DISCOVERY: {
case MSG_ON_START_PRINTER_DISCOVERY: {
IPrinterDiscoveryObserver observer = (IPrinterDiscoveryObserver) message.obj;
handleOnStartPrinterDiscovery(new SecurePrinterDiscoveryObserver(
mComponentName, observer));
} break;
case MSG_STOP_PRINTER_DISCOVERY: {
case MSG_ON_REQUEST_UPDATE_PRINTERS: {
List<PrinterId> printerIds = (List<PrinterId>) message.obj;
handleReqeustUpdatePritners(printerIds);
} break;
case MSG_ON_STOP_PRINTER_DISCOVERY: {
handleStopPrinterDiscovery();
} break;
@@ -436,22 +477,32 @@ final class RemotePrintService implements DeathRecipient {
}
@Override
public void addDiscoveredPrinters(List<PrinterInfo> printers) {
public void onPrintersAdded(List<PrinterInfo> printers) {
throwIfPrinterIdsForPrinterInfoTampered(printers);
try {
mDecoratedObsever.addDiscoveredPrinters(printers);
mDecoratedObsever.onPrintersAdded(printers);
} catch (RemoteException re) {
Slog.e(LOG_TAG, "Error delegating to addDiscoveredPrinters", re);
Slog.e(LOG_TAG, "Error delegating to onPrintersAdded", re);
}
}
@Override
public void removeDiscoveredPrinters(List<PrinterId> printerIds) {
public void onPrintersUpdated(List<PrinterInfo> printers) {
throwIfPrinterIdsForPrinterInfoTampered(printers);
try {
mDecoratedObsever.onPrintersUpdated(printers);
} catch (RemoteException re) {
Slog.e(LOG_TAG, "Error delegating to onPrintersUpdated.", re);
}
}
@Override
public void onPrintersRemoved(List<PrinterId> printerIds) {
throwIfPrinterIdsTampered(printerIds);
try {
mDecoratedObsever.removeDiscoveredPrinters(printerIds);
mDecoratedObsever.onPrintersRemoved(printerIds);
} catch (RemoteException re) {
Slog.e(LOG_TAG, "Error delegating to removeDiscoveredPrinters", re);
Slog.e(LOG_TAG, "Error delegating to onPrintersRemoved", re);
}
}

View File

@@ -35,6 +35,7 @@ import android.print.IPrintSpoolerClient;
import android.print.IPrinterDiscoveryObserver;
import android.print.PrintAttributes;
import android.print.PrintJobInfo;
import android.print.PrinterId;
import android.util.Slog;
import android.util.TimedRemoteCaller;
@@ -96,6 +97,7 @@ final class RemotePrintSpooler {
public void onStartPrinterDiscovery(IPrinterDiscoveryObserver observer);
public void onStopPrinterDiscovery();
public void onAllPrintJobsForServiceHandled(ComponentName printService);
public void onRequestUpdatePrinters(List<PrinterId> printerIds);
}
public RemotePrintSpooler(Context context, int userId,
@@ -662,7 +664,7 @@ final class RemotePrintSpooler {
}
@Override
public void onStopPrinterDiscovery() throws RemoteException {
public void onStopPrinterDiscovery() {
RemotePrintSpooler spooler = mWeakSpooler.get();
if (spooler != null) {
final long identity = Binder.clearCallingIdentity();
@@ -673,5 +675,18 @@ final class RemotePrintSpooler {
}
}
}
@Override
public void onRequestUpdatePrinters(List<PrinterId> printerIds) {
RemotePrintSpooler spooler = mWeakSpooler.get();
if (spooler != null) {
final long identity = Binder.clearCallingIdentity();
try {
spooler.mCallbacks.onRequestUpdatePrinters(printerIds);
} finally {
Binder.restoreCallingIdentity(identity);
}
}
}
}
}

View File

@@ -23,6 +23,7 @@ import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.print.IPrinterDiscoveryObserver;
import android.print.PrintJobInfo;
import android.print.PrinterId;
import android.printservice.PrintServiceInfo;
import android.provider.Settings;
import android.text.TextUtils;
@@ -138,6 +139,21 @@ final class UserState implements PrintSpoolerCallbacks {
}
}
@Override
public void onRequestUpdatePrinters(List<PrinterId> printerIds) {
final RemotePrintService service;
synchronized (mLock) {
throwIfDestroyedLocked();
if (mActiveServices.isEmpty()) {
return;
}
service = mActiveServices.get(printerIds.get(0).getService());
}
if (service != null) {
service.onRequestUpdatePrinters(printerIds);
}
}
public void updateIfNeededLocked() {
throwIfDestroyedLocked();
if (readConfigurationLocked()) {