From 55b409a97cf6376399a0940313ea852368727d6f Mon Sep 17 00:00:00 2001
From: Svetoslav Ganov
Date: Wed, 31 Jul 2013 17:25:13 -0700
Subject: [PATCH] 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
---
api/current.txt | 3 +
.../android/print/IPrintSpoolerClient.aidl | 2 +
.../print/IPrinterDiscoveryObserver.aidl | 5 +-
core/java/android/print/PrinterId.java | 3 +-
core/java/android/print/PrinterInfo.java | 334 +++++++++++++-----
.../android/printservice/IPrintService.aidl | 7 +-
.../android/printservice/PrintService.java | 138 ++++++--
.../printspooler/PrintJobConfigActivity.java | 102 +++++-
.../android/printspooler/PrintSpooler.java | 63 +++-
.../server/print/RemotePrintService.java | 107 ++++--
.../server/print/RemotePrintSpooler.java | 17 +-
.../com/android/server/print/UserState.java | 16 +
12 files changed, 605 insertions(+), 192 deletions(-)
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()) {