summaryrefslogtreecommitdiffstats
path: root/packages/PrintSpooler/src/com/android/printspooler/PrintSpooler.java
diff options
context:
space:
mode:
Diffstat (limited to 'packages/PrintSpooler/src/com/android/printspooler/PrintSpooler.java')
-rw-r--r--packages/PrintSpooler/src/com/android/printspooler/PrintSpooler.java734
1 files changed, 734 insertions, 0 deletions
diff --git a/packages/PrintSpooler/src/com/android/printspooler/PrintSpooler.java b/packages/PrintSpooler/src/com/android/printspooler/PrintSpooler.java
new file mode 100644
index 0000000..2b27b69
--- /dev/null
+++ b/packages/PrintSpooler/src/com/android/printspooler/PrintSpooler.java
@@ -0,0 +1,734 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.printspooler;
+
+import java.io.Closeable;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.os.AsyncTask;
+import android.os.ParcelFileDescriptor;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.print.IPrintClient;
+import android.print.IPrintManager;
+import android.print.PrintAttributes;
+import android.print.PrintJobInfo;
+import android.print.PrintManager;
+import android.print.PrinterId;
+import android.util.AtomicFile;
+import android.util.Log;
+import android.util.Slog;
+import android.util.Xml;
+
+import com.android.internal.util.FastXmlSerializer;
+
+public class PrintSpooler {
+
+ private static final String LOG_TAG = PrintSpooler.class.getSimpleName();
+
+ private static final boolean DEBUG_PRINT_JOB_LIFECYCLE = false;
+
+ private static final boolean DEBUG_PERSISTENCE = false;
+
+ private static final boolean PERSISTNECE_MANAGER_ENABLED = false;
+
+ private static final String PRINT_FILE_EXTENSION = "pdf";
+
+ private static int sPrintJobIdCounter;
+
+ private static final Object sLock = new Object();
+
+ private final Object mLock = new Object();
+
+ private static PrintSpooler sInstance;
+
+ private final List<PrintJobInfo> mPrintJobs = new ArrayList<PrintJobInfo>();
+
+ private final PersistenceManager mPersistanceManager;
+
+ private final Context mContext;
+
+ private final IPrintManager mPrintManager;
+
+ public static PrintSpooler getInstance(Context context) {
+ synchronized (sLock) {
+ if (sInstance == null) {
+ sInstance = new PrintSpooler(context);
+ }
+ return sInstance;
+ }
+ }
+
+ private PrintSpooler(Context context) {
+ mContext = context;
+ mPersistanceManager = new PersistenceManager();
+ mPersistanceManager.readStateLocked();
+ mPrintManager = IPrintManager.Stub.asInterface(
+ ServiceManager.getService("print"));
+ }
+
+ public List<PrintJobInfo> getPrintJobs(ComponentName componentName, int state, int appId) {
+ synchronized (mLock) {
+ List<PrintJobInfo> foundPrintJobs = null;
+ final int printJobCount = mPrintJobs.size();
+ for (int i = 0; i < printJobCount; i++) {
+ PrintJobInfo printJob = mPrintJobs.get(i);
+ PrinterId printerId = printJob.getPrinterId();
+ final boolean sameComponent = (componentName == null
+ || (printerId != null
+ && componentName.equals(printerId.getServiceComponentName())));
+ final boolean sameAppId = appId == PrintManager.APP_ID_ANY
+ || printJob.getAppId() == appId;
+ final boolean sameState = state == PrintJobInfo.STATE_ANY
+ || state == printJob.getState();
+ if (sameComponent && sameAppId && sameState) {
+ if (foundPrintJobs == null) {
+ foundPrintJobs = new ArrayList<PrintJobInfo>();
+ }
+ foundPrintJobs.add(printJob);
+ }
+ }
+ return foundPrintJobs;
+ }
+ }
+
+ public PrintJobInfo getPrintJob(int printJobId, int appId) {
+ synchronized (mLock) {
+ final int printJobCount = mPrintJobs.size();
+ for (int i = 0; i < printJobCount; i++) {
+ PrintJobInfo printJob = mPrintJobs.get(i);
+ if (printJob.getId() == printJobId
+ && (appId == PrintManager.APP_ID_ANY || appId == printJob.getAppId())) {
+ return printJob;
+ }
+ }
+ return null;
+ }
+ }
+
+ public boolean cancelPrintJob(int printJobId, int appId) {
+ synchronized (mLock) {
+ PrintJobInfo printJob = getPrintJob(printJobId, appId);
+ if (printJob != null) {
+ switch (printJob.getState()) {
+ case PrintJobInfo.STATE_CREATED: {
+ removePrintJobLocked(printJob);
+ } return true;
+ case PrintJobInfo.STATE_QUEUED: {
+ removePrintJobLocked(printJob);
+ } return true;
+ default: {
+ return false;
+ }
+ }
+ }
+ return false;
+ }
+ }
+
+ public PrintJobInfo createPrintJob(CharSequence label, IPrintClient client,
+ PrintAttributes attributes, int appId) {
+ synchronized (mLock) {
+ final int printJobId = generatePrintJobIdLocked();
+ PrintJobInfo printJob = new PrintJobInfo();
+ printJob.setId(printJobId);
+ printJob.setAppId(appId);
+ printJob.setLabel(label);
+ printJob.setAttributes(attributes);
+
+ addPrintJobLocked(printJob);
+ setPrintJobState(printJobId, PrintJobInfo.STATE_CREATED);
+
+ return printJob;
+ }
+ }
+
+ private int generatePrintJobIdLocked() {
+ int printJobId = sPrintJobIdCounter++;
+ while (isDuplicatePrintJobId(printJobId)) {
+ printJobId = sPrintJobIdCounter++;
+ }
+ return printJobId;
+ }
+
+ private boolean isDuplicatePrintJobId(int printJobId) {
+ final int printJobCount = mPrintJobs.size();
+ for (int j = 0; j < printJobCount; j++) {
+ PrintJobInfo printJob = mPrintJobs.get(j);
+ if (printJob.getId() == printJobId) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @SuppressWarnings("resource")
+ public boolean writePrintJobData(ParcelFileDescriptor fd, int printJobId) {
+ synchronized (mLock) {
+ FileInputStream in = null;
+ FileOutputStream out = null;
+ try {
+ PrintJobInfo printJob = getPrintJob(printJobId, PrintManager.APP_ID_ANY);
+ if (printJob != null) {
+ File file = generateFileForPrintJob(printJobId);
+ in = new FileInputStream(file);
+ out = new FileOutputStream(fd.getFileDescriptor());
+ final byte[] buffer = new byte[8192];
+ while (true) {
+ final int readByteCount = in.read(buffer);
+ if (readByteCount < 0) {
+ return true;
+ }
+ out.write(buffer, 0, readByteCount);
+ }
+ }
+ } catch (FileNotFoundException fnfe) {
+ Log.e(LOG_TAG, "Error writing print job data!", fnfe);
+ } catch (IOException ioe) {
+ Log.e(LOG_TAG, "Error writing print job data!", ioe);
+ } finally {
+ closeIfNotNullNoException(in);
+ closeIfNotNullNoException(out);
+ closeIfNotNullNoException(fd);
+ }
+ }
+ return false;
+ }
+
+ private void closeIfNotNullNoException(Closeable closeable) {
+ if (closeable != null) {
+ try {
+ closeable.close();
+ } catch (IOException ioe) {
+ /* ignore */;
+ }
+ }
+ }
+
+ public File generateFileForPrintJob(int printJobId) {
+ return new File(mContext.getFilesDir(), "print_job_"
+ + printJobId + "." + PRINT_FILE_EXTENSION);
+ }
+
+ private void addPrintJobLocked(PrintJobInfo printJob) {
+ mPrintJobs.add(printJob);
+ if (DEBUG_PRINT_JOB_LIFECYCLE) {
+ Slog.i(LOG_TAG, "[ADD] " + printJob);
+ }
+ }
+
+ private void removePrintJobLocked(PrintJobInfo printJob) {
+ if (mPrintJobs.remove(printJob)) {
+ generateFileForPrintJob(printJob.getId()).delete();
+ if (DEBUG_PRINT_JOB_LIFECYCLE) {
+ Slog.i(LOG_TAG, "[REMOVE] " + printJob);
+ }
+ }
+ }
+
+ public boolean setPrintJobState(int printJobId, int state) {
+ boolean success = false;
+ PrintJobInfo queuedPrintJob = null;
+
+ synchronized (mLock) {
+ PrintJobInfo printJob = getPrintJob(printJobId, PrintManager.APP_ID_ANY);
+ if (printJob != null && printJob.getState() < state) {
+ success = true;
+ printJob.setState(state);
+ // TODO: Update notifications.
+ switch (state) {
+ case PrintJobInfo.STATE_COMPLETED:
+ case PrintJobInfo.STATE_CANCELED: {
+ removePrintJobLocked(printJob);
+ } break;
+ case PrintJobInfo.STATE_QUEUED: {
+ queuedPrintJob = new PrintJobInfo(printJob);
+ } break;
+ }
+ if (DEBUG_PRINT_JOB_LIFECYCLE) {
+ Slog.i(LOG_TAG, "[STATUS CHANGED] " + printJob);
+ }
+ mPersistanceManager.writeStateLocked();
+ }
+ }
+
+ if (queuedPrintJob != null) {
+ try {
+ mPrintManager.onPrintJobQueued(queuedPrintJob.getPrinterId(),
+ queuedPrintJob);
+ } catch (RemoteException re) {
+ /* ignore */
+ }
+ }
+
+ return success;
+ }
+
+ public boolean setPrintJobTag(int printJobId, String tag) {
+ synchronized (mLock) {
+ PrintJobInfo printJob = getPrintJob(printJobId, PrintManager.APP_ID_ANY);
+ if (printJob != null) {
+ printJob.setTag(tag);
+ mPersistanceManager.writeStateLocked();
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public void setPrintJobAttributes(int printJobId, PrintAttributes attributes) {
+ synchronized (mLock) {
+ PrintJobInfo printJob = getPrintJob(printJobId, PrintManager.APP_ID_ANY);
+ if (printJob != null) {
+ printJob.setAttributes(attributes);
+ mPersistanceManager.writeStateLocked();
+ }
+ }
+ }
+
+ public void setPrintJobPrinterId(int printJobId, PrinterId printerId) {
+ synchronized (mLock) {
+ PrintJobInfo printJob = getPrintJob(printJobId, PrintManager.APP_ID_ANY);
+ if (printJob != null) {
+ printJob.setPrinterId(printerId);
+ mPersistanceManager.writeStateLocked();
+ }
+ }
+ }
+
+ private final class PersistenceManager {
+ private static final String PERSIST_FILE_NAME = "print_spooler_state.xml";
+
+ private static final String TAG_SPOOLER = "spooler";
+ private static final String TAG_JOB = "job";
+ private static final String TAG_ID = "id";
+ private static final String TAG_TAG = "tag";
+ private static final String TAG_APP_ID = "app-id";
+ private static final String TAG_STATE = "state";
+ private static final String TAG_ATTRIBUTES = "attributes";
+ private static final String TAG_LABEL = "label";
+ private static final String TAG_PRINTER = "printer";
+
+ private static final String ATTRIBUTE_MEDIA_SIZE = "mediaSize";
+ private static final String ATTRIBUTE_RESOLUTION = "resolution";
+ private static final String ATTRIBUTE_MARGINS = "margins";
+ private static final String ATTRIBUTE_INPUT_TRAY = "inputTray";
+ private static final String ATTRIBUTE_OUTPUT_TRAY = "outputTray";
+ private static final String ATTRIBUTE_DUPLEX_MODE = "duplexMode";
+ private static final String ATTRIBUTE_COLOR_MODE = "colorMode";
+ private static final String ATTRIBUTE_FITTING_MODE = "fittingMode";
+ private static final String ATTRIBUTE_ORIENTATION = "orientation";
+
+ private final AtomicFile mStatePersistFile;
+
+ private boolean mWriteStateScheduled;
+
+ private PersistenceManager() {
+ mStatePersistFile = new AtomicFile(new File(mContext.getFilesDir(),
+ PERSIST_FILE_NAME));
+ }
+
+ public void writeStateLocked() {
+ // TODO: Implement persistence of PrintableInfo
+ if (!PERSISTNECE_MANAGER_ENABLED) {
+ return;
+ }
+ if (mWriteStateScheduled) {
+ return;
+ }
+ mWriteStateScheduled = true;
+ new AsyncTask<Void, Void, Void>() {
+ @Override
+ protected Void doInBackground(Void... params) {
+ synchronized (mLock) {
+ mWriteStateScheduled = false;
+ doWriteStateLocked();
+ }
+ return null;
+ }
+ }.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, (Void[]) null);
+ }
+
+ private void doWriteStateLocked() {
+ FileOutputStream out = null;
+ try {
+ out = mStatePersistFile.startWrite();
+
+ XmlSerializer serializer = new FastXmlSerializer();
+ serializer.setOutput(out, "utf-8");
+ serializer.startDocument(null, true);
+ serializer.startTag(null, TAG_SPOOLER);
+
+ List<PrintJobInfo> printJobs = mPrintJobs;
+
+ final int printJobCount = printJobs.size();
+ for (int j = 0; j < printJobCount; j++) {
+ PrintJobInfo printJob = printJobs.get(j);
+
+ final int state = printJob.getState();
+ if (state < PrintJobInfo.STATE_QUEUED
+ || state > PrintJobInfo.STATE_FAILED) {
+ continue;
+ }
+
+ serializer.startTag(null, TAG_JOB);
+
+ serializer.startTag(null, TAG_ID);
+ serializer.text(String.valueOf(printJob.getId()));
+ serializer.endTag(null, TAG_ID);
+
+ serializer.startTag(null, TAG_TAG);
+ serializer.text(printJob.getTag());
+ serializer.endTag(null, TAG_TAG);
+
+ serializer.startTag(null, TAG_APP_ID);
+ serializer.text(String.valueOf(printJob.getAppId()));
+ serializer.endTag(null, TAG_APP_ID);
+
+ serializer.startTag(null, TAG_LABEL);
+ serializer.text(printJob.getLabel().toString());
+ serializer.endTag(null, TAG_LABEL);
+
+ serializer.startTag(null, TAG_STATE);
+ serializer.text(String.valueOf(printJob.getState()));
+ serializer.endTag(null, TAG_STATE);
+
+ serializer.startTag(null, TAG_PRINTER);
+ serializer.text(printJob.getPrinterId().flattenToString());
+ serializer.endTag(null, TAG_PRINTER);
+
+ PrintAttributes attributes = printJob.getAttributes();
+ if (attributes != null) {
+ serializer.startTag(null, TAG_ATTRIBUTES);
+
+ //TODO: Implement persistence of the attributes below.
+
+// MediaSize mediaSize = attributes.getMediaSize();
+// if (mediaSize != null) {
+// serializer.attribute(null, ATTRIBUTE_MEDIA_SIZE,
+// mediaSize.flattenToString());
+// }
+//
+// Resolution resolution = attributes.getResolution();
+// if (resolution != null) {
+// serializer.attribute(null, ATTRIBUTE_RESOLUTION,
+// resolution.flattenToString());
+// }
+//
+// Margins margins = attributes.getMargins();
+// if (margins != null) {
+// serializer.attribute(null, ATTRIBUTE_MARGINS,
+// margins.flattenToString());
+// }
+//
+// Tray inputTray = attributes.getInputTray();
+// if (inputTray != null) {
+// serializer.attribute(null, ATTRIBUTE_INPUT_TRAY,
+// inputTray.flattenToString());
+// }
+//
+// Tray outputTray = attributes.getOutputTray();
+// if (outputTray != null) {
+// serializer.attribute(null, ATTRIBUTE_OUTPUT_TRAY,
+// outputTray.flattenToString());
+// }
+
+ final int duplexMode = attributes.getDuplexMode();
+ if (duplexMode > 0) {
+ serializer.attribute(null, ATTRIBUTE_DUPLEX_MODE,
+ String.valueOf(duplexMode));
+ }
+
+ final int colorMode = attributes.getColorMode();
+ if (colorMode > 0) {
+ serializer.attribute(null, ATTRIBUTE_COLOR_MODE,
+ String.valueOf(colorMode));
+ }
+
+ final int fittingMode = attributes.getFittingMode();
+ if (fittingMode > 0) {
+ serializer.attribute(null, ATTRIBUTE_FITTING_MODE,
+ String.valueOf(fittingMode));
+ }
+
+ final int orientation = attributes.getOrientation();
+ if (orientation > 0) {
+ serializer.attribute(null, ATTRIBUTE_ORIENTATION,
+ String.valueOf(orientation));
+ }
+
+ serializer.endTag(null, TAG_ATTRIBUTES);
+ }
+
+ serializer.endTag(null, TAG_JOB);
+
+ if (DEBUG_PERSISTENCE) {
+ Log.i(LOG_TAG, "[PERSISTED] " + printJob);
+ }
+ }
+
+ serializer.endTag(null, TAG_SPOOLER);
+ serializer.endDocument();
+ mStatePersistFile.finishWrite(out);
+ } catch (IOException e) {
+ Slog.w(LOG_TAG, "Failed to write state, restoring backup.", e);
+ mStatePersistFile.failWrite(out);
+ } finally {
+ if (out != null) {
+ try {
+ out.close();
+ } catch (IOException ioe) {
+ /* ignore */
+ }
+ }
+ }
+ }
+
+ public void readStateLocked() {
+ if (!PERSISTNECE_MANAGER_ENABLED) {
+ return;
+ }
+ FileInputStream in = null;
+ try {
+ in = mStatePersistFile.openRead();
+ } catch (FileNotFoundException e) {
+ Log.i(LOG_TAG, "No existing print spooler state.");
+ return;
+ }
+ try {
+ XmlPullParser parser = Xml.newPullParser();
+ parser.setInput(in, null);
+ parseState(parser);
+ } catch (IllegalStateException ise) {
+ Slog.w(LOG_TAG, "Failed parsing " + ise);
+ } catch (NullPointerException npe) {
+ Slog.w(LOG_TAG, "Failed parsing " + npe);
+ } catch (NumberFormatException nfe) {
+ Slog.w(LOG_TAG, "Failed parsing " + nfe);
+ } catch (XmlPullParserException xppe) {
+ Slog.w(LOG_TAG, "Failed parsing " + xppe);
+ } catch (IOException ioe) {
+ Slog.w(LOG_TAG, "Failed parsing " + ioe);
+ } catch (IndexOutOfBoundsException iobe) {
+ Slog.w(LOG_TAG, "Failed parsing " + iobe);
+ } finally {
+ try {
+ in.close();
+ } catch (IOException ioe) {
+ /* ignore */
+ }
+ }
+ }
+
+ private void parseState(XmlPullParser parser)
+ throws IOException, XmlPullParserException {
+ parser.next();
+ skipEmptyTextTags(parser);
+ expect(parser, XmlPullParser.START_TAG, TAG_SPOOLER);
+ parser.next();
+
+ while (parsePrintJob(parser)) {
+ parser.next();
+ }
+
+ skipEmptyTextTags(parser);
+ expect(parser, XmlPullParser.END_TAG, TAG_SPOOLER);
+ }
+
+ private boolean parsePrintJob(XmlPullParser parser)
+ throws IOException, XmlPullParserException {
+ skipEmptyTextTags(parser);
+ if (!accept(parser, XmlPullParser.START_TAG, TAG_JOB)) {
+ return false;
+ }
+ parser.next();
+
+ skipEmptyTextTags(parser);
+ expect(parser, XmlPullParser.START_TAG, TAG_ID);
+ parser.next();
+ final int printJobId = Integer.parseInt(parser.getText());
+ parser.next();
+ skipEmptyTextTags(parser);
+ expect(parser, XmlPullParser.END_TAG, TAG_ID);
+ parser.next();
+
+ skipEmptyTextTags(parser);
+ expect(parser, XmlPullParser.START_TAG, TAG_TAG);
+ parser.next();
+ String tag = parser.getText();
+ parser.next();
+ skipEmptyTextTags(parser);
+ expect(parser, XmlPullParser.END_TAG, TAG_TAG);
+ parser.next();
+
+ skipEmptyTextTags(parser);
+ expect(parser, XmlPullParser.START_TAG, TAG_APP_ID);
+ parser.next();
+ final int appId = Integer.parseInt(parser.getText());
+ parser.next();
+ skipEmptyTextTags(parser);
+ expect(parser, XmlPullParser.END_TAG, TAG_APP_ID);
+ parser.next();
+
+ skipEmptyTextTags(parser);
+ expect(parser, XmlPullParser.START_TAG, TAG_LABEL);
+ parser.next();
+ String label = parser.getText();
+ parser.next();
+ skipEmptyTextTags(parser);
+ expect(parser, XmlPullParser.END_TAG, TAG_LABEL);
+ parser.next();
+
+ skipEmptyTextTags(parser);
+ expect(parser, XmlPullParser.START_TAG, TAG_STATE);
+ parser.next();
+ final int state = Integer.parseInt(parser.getText());
+ parser.next();
+ skipEmptyTextTags(parser);
+ expect(parser, XmlPullParser.END_TAG, TAG_STATE);
+ parser.next();
+
+ skipEmptyTextTags(parser);
+ expect(parser, XmlPullParser.START_TAG, TAG_PRINTER);
+ parser.next();
+ PrinterId printerId = PrinterId.unflattenFromString(parser.getText());
+ parser.next();
+ skipEmptyTextTags(parser);
+ expect(parser, XmlPullParser.END_TAG, TAG_PRINTER);
+ parser.next();
+
+ skipEmptyTextTags(parser);
+ expect(parser, XmlPullParser.START_TAG, TAG_ATTRIBUTES);
+
+ final int attributeCount = parser.getAttributeCount();
+ PrintAttributes attributes = null;
+ if (attributeCount > 0) {
+ PrintAttributes.Builder builder = new PrintAttributes.Builder();
+
+ // TODO: Implement reading of the attributes below.
+
+// String mediaSize = parser.getAttributeValue(null, ATTRIBUTE_MEDIA_SIZE);
+// if (mediaSize != null) {
+// builder.setMediaSize(MediaSize.unflattenFromString(mediaSize));
+// }
+//
+// String resolution = parser.getAttributeValue(null, ATTRIBUTE_RESOLUTION);
+// if (resolution != null) {
+// builder.setMediaSize(Resolution.unflattenFromString(resolution));
+// }
+//
+// String margins = parser.getAttributeValue(null, ATTRIBUTE_MARGINS);
+// if (margins != null) {
+// builder.setMediaSize(Margins.unflattenFromString(margins));
+// }
+//
+// String inputTray = parser.getAttributeValue(null, ATTRIBUTE_INPUT_TRAY);
+// if (inputTray != null) {
+// builder.setMediaSize(Tray.unflattenFromString(inputTray));
+// }
+//
+// String outputTray = parser.getAttributeValue(null, ATTRIBUTE_OUTPUT_TRAY);
+// if (outputTray != null) {
+// builder.setMediaSize(Tray.unflattenFromString(outputTray));
+// }
+//
+// String duplexMode = parser.getAttributeValue(null, ATTRIBUTE_DUPLEX_MODE);
+// if (duplexMode != null) {
+// builder.setDuplexMode(Integer.parseInt(duplexMode));
+// }
+
+ String colorMode = parser.getAttributeValue(null, ATTRIBUTE_COLOR_MODE);
+ if (colorMode != null) {
+ builder.setColorMode(Integer.parseInt(colorMode));
+ }
+
+ String fittingMode = parser.getAttributeValue(null, ATTRIBUTE_COLOR_MODE);
+ if (fittingMode != null) {
+ builder.setFittingMode(Integer.parseInt(fittingMode));
+ }
+ }
+ parser.next();
+ skipEmptyTextTags(parser);
+ expect(parser, XmlPullParser.END_TAG, TAG_ATTRIBUTES);
+ parser.next();
+
+ PrintJobInfo printJob = new PrintJobInfo();
+ printJob.setId(printJobId);
+ printJob.setTag(tag);
+ printJob.setAppId(appId);
+ printJob.setLabel(label);
+ printJob.setState(state);
+ printJob.setAttributes(attributes);
+ printJob.setPrinterId(printerId);
+
+ mPrintJobs.add(printJob);
+
+ if (DEBUG_PERSISTENCE) {
+ Log.i(LOG_TAG, "[RESTORED] " + printJob);
+ }
+
+ skipEmptyTextTags(parser);
+ expect(parser, XmlPullParser.END_TAG, TAG_JOB);
+
+ return true;
+ }
+
+ private void expect(XmlPullParser parser, int type, String tag)
+ throws IOException, XmlPullParserException {
+ if (!accept(parser, type, tag)) {
+ throw new XmlPullParserException("Exepected event: " + type
+ + " and tag: " + tag + " but got event: " + parser.getEventType()
+ + " and tag:" + parser.getName());
+ }
+ }
+
+ private void skipEmptyTextTags(XmlPullParser parser)
+ throws IOException, XmlPullParserException {
+ while (accept(parser, XmlPullParser.TEXT, null)
+ && "\n".equals(parser.getText())) {
+ parser.next();
+ }
+ }
+
+ private boolean accept(XmlPullParser parser, int type, String tag)
+ throws IOException, XmlPullParserException {
+ if (parser.getEventType() != type) {
+ return false;
+ }
+ if (tag != null) {
+ if (!tag.equals(parser.getName())) {
+ return false;
+ }
+ } else if (parser.getName() != null) {
+ return false;
+ }
+ return true;
+ }
+ }
+}