summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSvetoslav Ganov <svetoslavganov@google.com>2013-07-31 17:25:13 -0700
committerSvetoslav Ganov <svetoslavganov@google.com>2013-07-31 18:59:53 -0700
commit55b409a97cf6376399a0940313ea852368727d6f (patch)
tree9a919b2d64c469e11d94d6205d44cdd9ab553802
parent85b1f883056a1d74473fd9ce774948878f389ab6 (diff)
downloadframeworks_base-55b409a97cf6376399a0940313ea852368727d6f.zip
frameworks_base-55b409a97cf6376399a0940313ea852368727d6f.tar.gz
frameworks_base-55b409a97cf6376399a0940313ea852368727d6f.tar.bz2
Iteration of the print sub-system.
1. Added APIs for adding partially initialized PrintInfo objects enabling light-weight lookps for print serivces that want to populate the list of available printers without querying each of them for its capabilities. This includes APIs for the system to request from a print service to update certain printers. 2. Fixed a bug in PrinterId#equals(). 3. Added equals and hasCode implementaion to PrinterInfo. Also the defaul in PrinterInfo are now an array instead of a SparseArray - cheaper. 4. Now PrintJobConfigActivity works with partially specified printers. Specifically, if such a printer is selected the activity is requesting from the print service to update the printer. We are currently not handling the timeout case. It also handles udpated pritners. Change-Id: I5e83e924ef597c9e22cbd06a971d4f4d3bd3a9c1
-rw-r--r--api/current.txt3
-rw-r--r--core/java/android/print/IPrintSpoolerClient.aidl2
-rw-r--r--core/java/android/print/IPrinterDiscoveryObserver.aidl5
-rw-r--r--core/java/android/print/PrinterId.java3
-rw-r--r--core/java/android/print/PrinterInfo.java336
-rw-r--r--core/java/android/printservice/IPrintService.aidl7
-rw-r--r--core/java/android/printservice/PrintService.java138
-rw-r--r--packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java102
-rw-r--r--packages/PrintSpooler/src/com/android/printspooler/PrintSpooler.java63
-rw-r--r--services/java/com/android/server/print/RemotePrintService.java107
-rw-r--r--services/java/com/android/server/print/RemotePrintSpooler.java17
-rw-r--r--services/java/com/android/server/print/UserState.java16
12 files changed, 606 insertions, 193 deletions
diff --git a/api/current.txt b/api/current.txt
index 52bdf68..cfcf702 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -18661,6 +18661,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
@@ -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<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";
}
diff --git a/core/java/android/print/IPrintSpoolerClient.aidl b/core/java/android/print/IPrintSpoolerClient.aidl
index 47975e1..46857e4 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<PrinterId> 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 39aeb8c..deabbcb 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<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);
}
diff --git a/core/java/android/print/PrinterId.java b/core/java/android/print/PrinterId.java
index e884026..e27fbb2 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 c0daa6e..15bcb73 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<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;
-
- 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;
-
- mDuplexModes = prototype.mDuplexModes;
- mColorModes = prototype.mColorModes;
- mFittingModes = prototype.mFittingModes;
- mOrientations = prototype.mOrientations;
-
- final int defaultCount = prototype.mDefaults.size();
+ copyFrom(prototype);
+ }
+
+ /**
+ * @hide
+ */
+ public void copyFrom(PrinterInfo other) {
+ mId = other.mId;
+ mLabel = other.mLabel;
+ mStatus = other.mStatus;
+
+ mMinMargins = other.mMinMargins;
+ if (other.mMediaSizes != null) {
+ if (mMediaSizes != null) {
+ mMediaSizes.clear();
+ mMediaSizes.addAll(other.mMediaSizes);
+ } else {
+ mMediaSizes = new ArrayList<MediaSize>(other.mMediaSizes);
+ }
+ } else {
+ mMediaSizes = null;
+ }
+
+ if (other.mResolutions != null) {
+ if (mResolutions != null) {
+ mResolutions.clear();
+ mResolutions.addAll(other.mResolutions);
+ } else {
+ mResolutions = new ArrayList<Resolution>(other.mResolutions);
+ }
+ } else {
+ mResolutions = null;
+ }
+
+ if (other.mInputTrays != null) {
+ if (mInputTrays != null) {
+ mInputTrays.clear();
+ mInputTrays.addAll(other.mInputTrays);
+ } else {
+ mInputTrays = new ArrayList<Tray>(other.mInputTrays);
+ }
+ } else {
+ mInputTrays = null;
+ }
+
+ if (other.mOutputTrays != null) {
+ if (mOutputTrays != null) {
+ mOutputTrays.clear();
+ mOutputTrays.addAll(other.mOutputTrays);
+ } else {
+ mOutputTrays = new ArrayList<Tray>(other.mOutputTrays);
+ }
+ } else {
+ mOutputTrays = null;
+ }
+
+ mDuplexModes = other.mDuplexModes;
+ mColorModes = other.mColorModes;
+ mFittingModes = other.mFittingModes;
+ mOrientations = other.mOrientations;
+
+ final int defaultCount = other.mDefaults.length;
for (int i = 0; i < defaultCount; i++) {
- mDefaults.put(prototype.mDefaults.keyAt(i), prototype.mDefaults.valueAt(i));
+ mDefaults[i] = other.mDefaults[i];
}
- mDefaultMargins = prototype.mDefaultMargins;
+ 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();
@@ -328,6 +388,112 @@ public final class PrinterInfo implements Parcelable {
}
@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();
builder.append("PrinterInfo{");
@@ -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.");
}
}
diff --git a/core/java/android/printservice/IPrintService.aidl b/core/java/android/printservice/IPrintService.aidl
index c72385a..e6fdbf9 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<PrinterId> 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 dde31d2..15e1b73 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.
* </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,7 +301,7 @@ 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);
}
@@ -297,6 +309,65 @@ public abstract class PrintService extends Service {
}
/**
+ * 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
* is performed, the print job should be set to a cancelled state by
@@ -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;
diff --git a/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java b/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java
index 86c4f37..d61fd2c 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<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(MSG_ON_PRINTERS_ADDED, printers)
+ .sendToTarget();
+ }
+ }
+ }
+
+ @Override
+ public void onPrintersRemoved(List<PrinterId> printers) {
synchronized (this) {
if (mHandler != null) {
- mHandler.obtainMessage(MESSAGE_ADD_DICOVERED_PRINTERS, printers)
+ mHandler.obtainMessage(MSG_ON_PRINTERS_REMOVED, printers)
.sendToTarget();
}
}
}
@Override
- public void removeDiscoveredPrinters(List<PrinterId> printers) {
+ public void onPrintersUpdated(List<PrinterInfo> printers) {
synchronized (this) {
if (mHandler != null) {
- mHandler.obtainMessage(MESSAGE_REMOVE_DICOVERED_PRINTERS, printers)
+ 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 cef4341..870bfff 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<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;
}
}
}
diff --git a/services/java/com/android/server/print/RemotePrintService.java b/services/java/com/android/server/print/RemotePrintService.java
index a8f8566..7acf6ab 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<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);
}
@@ -274,10 +302,16 @@ 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.onPrintersAdded(printers);
+ } catch (RemoteException re) {
+ Slog.e(LOG_TAG, "Error delegating to onPrintersAdded", re);
+ }
+ }
+
+ @Override
+ public void onPrintersUpdated(List<PrinterInfo> printers) {
throwIfPrinterIdsForPrinterInfoTampered(printers);
try {
- mDecoratedObsever.addDiscoveredPrinters(printers);
+ mDecoratedObsever.onPrintersUpdated(printers);
} catch (RemoteException re) {
- Slog.e(LOG_TAG, "Error delegating to addDiscoveredPrinters", re);
+ Slog.e(LOG_TAG, "Error delegating to onPrintersUpdated.", re);
}
}
@Override
- public void removeDiscoveredPrinters(List<PrinterId> printerIds) {
+ 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);
}
}
diff --git a/services/java/com/android/server/print/RemotePrintSpooler.java b/services/java/com/android/server/print/RemotePrintSpooler.java
index ded410b..fe5b067 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<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);
+ }
+ }
+ }
}
}
diff --git a/services/java/com/android/server/print/UserState.java b/services/java/com/android/server/print/UserState.java
index 5cef4d3..c41f9b0 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<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()) {