diff --git a/api/current.txt b/api/current.txt
index 52bdf68b6451c..cfcf7025192ca 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -18661,6 +18661,7 @@ package android.print {
method public java.util.List getOutputTrays();
method public java.util.List 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
@@ -18746,9 +18747,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);
method protected abstract void onStartPrinterDiscovery();
method protected abstract void onStopPrinterDiscovery();
method public final void removeDiscoveredPrinters(java.util.List);
+ method public final void updateDiscoveredPrinters(java.util.List);
field public static final java.lang.String SERVICE_INTERFACE = "android.printservice.PrintService";
field public static final java.lang.String SERVICE_META_DATA = "android.printservice";
}
diff --git a/core/java/android/print/IPrintSpoolerClient.aidl b/core/java/android/print/IPrintSpoolerClient.aidl
index 47975e1eafa92..46857e4eac989 100644
--- a/core/java/android/print/IPrintSpoolerClient.aidl
+++ b/core/java/android/print/IPrintSpoolerClient.aidl
@@ -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 printerIds);
void onAllPrintJobsForServiceHandled(in ComponentName printService);
void onAllPrintJobsHandled();
}
diff --git a/core/java/android/print/IPrinterDiscoveryObserver.aidl b/core/java/android/print/IPrinterDiscoveryObserver.aidl
index 39aeb8c73ec90..deabbcb04d77a 100644
--- a/core/java/android/print/IPrinterDiscoveryObserver.aidl
+++ b/core/java/android/print/IPrinterDiscoveryObserver.aidl
@@ -25,6 +25,7 @@ import android.print.PrinterInfo;
* @hide
*/
oneway interface IPrinterDiscoveryObserver {
- void addDiscoveredPrinters(in List printers);
- void removeDiscoveredPrinters(in List printers);
+ void onPrintersAdded(in List printers);
+ void onPrintersRemoved(in List printers);
+ void onPrintersUpdated(in List printers);
}
diff --git a/core/java/android/print/PrinterId.java b/core/java/android/print/PrinterId.java
index e884026aee75c..e27fbb2360550 100644
--- a/core/java/android/print/PrinterId.java
+++ b/core/java/android/print/PrinterId.java
@@ -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;
diff --git a/core/java/android/print/PrinterInfo.java b/core/java/android/print/PrinterInfo.java
index c0daa6eb458db..15bcb734b63eb 100644
--- a/core/java/android/print/PrinterInfo.java
+++ b/core/java/android/print/PrinterInfo.java
@@ -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 mMediaSizes = new ArrayList(); // required
- private final List mResolutions = new ArrayList(); // required
+ private Margins mMinMargins = DEFAULT_MARGINS;
+ private List mMediaSizes;
+ private List mResolutions;
private List mInputTrays;
private List 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(prototype.mInputTrays) : null;
- mOutputTrays = (prototype.mOutputTrays != null)
- ? new ArrayList(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(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(other.mResolutions);
+ }
+ } else {
+ mResolutions = null;
+ }
+
+ if (other.mInputTrays != null) {
+ if (mInputTrays != null) {
+ mInputTrays.clear();
+ mInputTrays.addAll(other.mInputTrays);
+ } else {
+ mInputTrays = new ArrayList(other.mInputTrays);
+ }
+ } else {
+ mInputTrays = null;
+ }
+
+ if (other.mOutputTrays != null) {
+ if (mOutputTrays != null) {
+ mOutputTrays.clear();
+ mOutputTrays.addAll(other.mOutputTrays);
+ } else {
+ mOutputTrays = new ArrayList(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();
+ }
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();
+ }
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();
+ }
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();
+ }
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.");
}
}
diff --git a/core/java/android/printservice/IPrintService.aidl b/core/java/android/printservice/IPrintService.aidl
index c72385adda3fc..e6fdbf999a352 100644
--- a/core/java/android/printservice/IPrintService.aidl
+++ b/core/java/android/printservice/IPrintService.aidl
@@ -29,8 +29,9 @@ import android.printservice.IPrintServiceClient;
*/
oneway interface IPrintService {
void setClient(IPrintServiceClient client);
- void requestCancelPrintJob(in PrintJobInfo printJobInfo);
+ void onRequestUpdatePrinters(in List printerIds);
+ void onRequestCancelPrintJob(in PrintJobInfo printJobInfo);
void onPrintJobQueued(in PrintJobInfo printJobInfo);
- void startPrinterDiscovery(IPrinterDiscoveryObserver observer);
- void stopPrinterDiscovery();
+ void onStartPrinterDiscovery(IPrinterDiscoveryObserver observer);
+ void onStopPrinterDiscovery();
}
diff --git a/core/java/android/printservice/PrintService.java b/core/java/android/printservice/PrintService.java
index dde31d25678b9..15e1b7399719d 100644
--- a/core/java/android/printservice/PrintService.java
+++ b/core/java/android/printservice/PrintService.java
@@ -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.
*
+ *
+ * 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.
+ *
*
* @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.
*
*
* @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.
+ *
+ * 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.
+ *
+ *
+ * @param printers A list with updated printers.
+ *
+ * @see #addDiscoveredPrinters(List)
+ * @see #removeDiscoveredPrinters(List)
+ * @see #onStartPrinterDiscovery()
+ * @see #onStopPrinterDiscovery()
+ */
+ public final void updateDiscoveredPrinters(List 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.
+ *
+ * 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.
+ *
+ *
+ * @param printerIds The printers to be updated.
+ */
+ protected void onRequestUpdatePrinters(List 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 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 printerIds = (List) 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;
diff --git a/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java b/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java
index 86c4f372dc041..d61fd2cadc5a3 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java
@@ -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 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 printerIds = new ArrayList();
+ 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 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 pritners) {
+ SpinnerItem selectedItem =
+ (SpinnerItem) 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 printers = (List) message.obj;
mEditor.addPrinters(printers);
} break;
- case MESSAGE_REMOVE_DICOVERED_PRINTERS: {
+
+ case MSG_ON_PRINTERS_REMOVED: {
List printerIds = (List) message.obj;
mEditor.removePrinters(printerIds);
} break;
+
+ case MSG_ON_PRINTERS_UPDATED: {
+ List printers = (List) message.obj;
+ mEditor.updatePrinters(printers);
+ } break;
}
}
};
}
@Override
- public void addDiscoveredPrinters(List printers) {
+ public void onPrintersAdded(List 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 printers) {
+ public void onPrintersRemoved(List 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 printers) {
+ synchronized (this) {
+ if (mHandler != null) {
+ mHandler.obtainMessage(MSG_ON_PRINTERS_UPDATED, printers)
.sendToTarget();
}
}
diff --git a/packages/PrintSpooler/src/com/android/printspooler/PrintSpooler.java b/packages/PrintSpooler/src/com/android/printspooler/PrintSpooler.java
index cef4341f14b2e..870bfffda6216 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/PrintSpooler.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/PrintSpooler.java
@@ -118,19 +118,29 @@ public class PrintSpooler {
}
}
+ public void onReqeustUpdatePrinters(List 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 printerIds = (List) args.arg2;
+ args.recycle();
+ try {
+ client.onRequestUpdatePrinters(printerIds);
+ } catch (RemoteException re) {
+ Slog.e(LOG_TAG, "Error requesting to update pritners.", re);
+ }
+ } break;
}
}
}
diff --git a/services/java/com/android/server/print/RemotePrintService.java b/services/java/com/android/server/print/RemotePrintService.java
index a8f856650e6cd..7acf6ab11576c 100644
--- a/services/java/com/android/server/print/RemotePrintService.java
+++ b/services/java/com/android/server/print/RemotePrintService.java
@@ -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 printerIds) {
+ mHandler.obtainMessage(MyHandler.MSG_ON_REQUEST_UPDATE_PRINTERS,
+ printerIds).sendToTarget();
+ }
+
+ private void handleReqeustUpdatePritners(final List 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 printerIds = (List) 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 printers) {
+ public void onPrintersAdded(List 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 printerIds) {
+ public void onPrintersUpdated(List printers) {
+ throwIfPrinterIdsForPrinterInfoTampered(printers);
+ try {
+ mDecoratedObsever.onPrintersUpdated(printers);
+ } catch (RemoteException re) {
+ Slog.e(LOG_TAG, "Error delegating to onPrintersUpdated.", re);
+ }
+ }
+
+ @Override
+ public void onPrintersRemoved(List 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);
}
}
diff --git a/services/java/com/android/server/print/RemotePrintSpooler.java b/services/java/com/android/server/print/RemotePrintSpooler.java
index ded410b25b5c1..fe5b0675413ac 100644
--- a/services/java/com/android/server/print/RemotePrintSpooler.java
+++ b/services/java/com/android/server/print/RemotePrintSpooler.java
@@ -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 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 printerIds) {
+ RemotePrintSpooler spooler = mWeakSpooler.get();
+ if (spooler != null) {
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ spooler.mCallbacks.onRequestUpdatePrinters(printerIds);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+ }
}
}
diff --git a/services/java/com/android/server/print/UserState.java b/services/java/com/android/server/print/UserState.java
index 5cef4d3ceae70..c41f9b02056fd 100644
--- a/services/java/com/android/server/print/UserState.java
+++ b/services/java/com/android/server/print/UserState.java
@@ -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 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()) {