private boolean parsePrintJob(XmlPullParser parser) throws IOException, XmlPullParserException {
      skipEmptyTextTags(parser);
      if (!accept(parser, XmlPullParser.START_TAG, TAG_JOB)) {
        return false;
      }

      PrintJobInfo printJob = new PrintJobInfo();

      PrintJobId printJobId =
          PrintJobId.unflattenFromString(parser.getAttributeValue(null, ATTR_ID));
      printJob.setId(printJobId);
      String label = parser.getAttributeValue(null, ATTR_LABEL);
      printJob.setLabel(label);
      final int state = Integer.parseInt(parser.getAttributeValue(null, ATTR_STATE));
      printJob.setState(state);
      final int appId = Integer.parseInt(parser.getAttributeValue(null, ATTR_APP_ID));
      printJob.setAppId(appId);
      String tag = parser.getAttributeValue(null, ATTR_TAG);
      printJob.setTag(tag);
      String creationTime = parser.getAttributeValue(null, ATTR_CREATION_TIME);
      printJob.setCreationTime(Long.parseLong(creationTime));
      String copies = parser.getAttributeValue(null, ATTR_COPIES);
      printJob.setCopies(Integer.parseInt(copies));
      String printerName = parser.getAttributeValue(null, ATTR_PRINTER_NAME);
      printJob.setPrinterName(printerName);
      String stateReason = parser.getAttributeValue(null, ATTR_STATE_REASON);
      printJob.setStateReason(stateReason);
      String cancelling = parser.getAttributeValue(null, ATTR_CANCELLING);
      printJob.setCancelling(
          !TextUtils.isEmpty(cancelling) ? Boolean.parseBoolean(cancelling) : false);

      parser.next();

      skipEmptyTextTags(parser);
      if (accept(parser, XmlPullParser.START_TAG, TAG_PRINTER_ID)) {
        String localId = parser.getAttributeValue(null, ATTR_LOCAL_ID);
        ComponentName service =
            ComponentName.unflattenFromString(parser.getAttributeValue(null, ATTR_SERVICE_NAME));
        printJob.setPrinterId(new PrinterId(service, localId));
        parser.next();
        skipEmptyTextTags(parser);
        expect(parser, XmlPullParser.END_TAG, TAG_PRINTER_ID);
        parser.next();
      }

      skipEmptyTextTags(parser);
      List<PageRange> pageRanges = null;
      while (accept(parser, XmlPullParser.START_TAG, TAG_PAGE_RANGE)) {
        final int start = Integer.parseInt(parser.getAttributeValue(null, ATTR_START));
        final int end = Integer.parseInt(parser.getAttributeValue(null, ATTR_END));
        PageRange pageRange = new PageRange(start, end);
        if (pageRanges == null) {
          pageRanges = new ArrayList<PageRange>();
        }
        pageRanges.add(pageRange);
        parser.next();
        skipEmptyTextTags(parser);
        expect(parser, XmlPullParser.END_TAG, TAG_PAGE_RANGE);
        parser.next();
        skipEmptyTextTags(parser);
      }
      if (pageRanges != null) {
        PageRange[] pageRangesArray = new PageRange[pageRanges.size()];
        pageRanges.toArray(pageRangesArray);
        printJob.setPages(pageRangesArray);
      }

      skipEmptyTextTags(parser);
      if (accept(parser, XmlPullParser.START_TAG, TAG_ATTRIBUTES)) {

        PrintAttributes.Builder builder = new PrintAttributes.Builder();

        String colorMode = parser.getAttributeValue(null, ATTR_COLOR_MODE);
        builder.setColorMode(Integer.parseInt(colorMode));

        parser.next();

        skipEmptyTextTags(parser);
        if (accept(parser, XmlPullParser.START_TAG, TAG_MEDIA_SIZE)) {
          String id = parser.getAttributeValue(null, ATTR_ID);
          label = parser.getAttributeValue(null, ATTR_LABEL);
          final int widthMils = Integer.parseInt(parser.getAttributeValue(null, ATTR_WIDTH_MILS));
          final int heightMils = Integer.parseInt(parser.getAttributeValue(null, ATTR_HEIGHT_MILS));
          String packageName = parser.getAttributeValue(null, ATTR_PACKAGE_NAME);
          String labelResIdString = parser.getAttributeValue(null, ATTR_LABEL_RES_ID);
          final int labelResId =
              (labelResIdString != null) ? Integer.parseInt(labelResIdString) : 0;
          label = parser.getAttributeValue(null, ATTR_LABEL);
          MediaSize mediaSize =
              new MediaSize(id, label, packageName, widthMils, heightMils, labelResId);
          builder.setMediaSize(mediaSize);
          parser.next();
          skipEmptyTextTags(parser);
          expect(parser, XmlPullParser.END_TAG, TAG_MEDIA_SIZE);
          parser.next();
        }

        skipEmptyTextTags(parser);
        if (accept(parser, XmlPullParser.START_TAG, TAG_RESOLUTION)) {
          String id = parser.getAttributeValue(null, ATTR_ID);
          label = parser.getAttributeValue(null, ATTR_LABEL);
          final int horizontalDpi =
              Integer.parseInt(parser.getAttributeValue(null, ATTR_HORIZONTAL_DPI));
          final int verticalDpi =
              Integer.parseInt(parser.getAttributeValue(null, ATTR_VERTICAL_DPI));
          Resolution resolution = new Resolution(id, label, horizontalDpi, verticalDpi);
          builder.setResolution(resolution);
          parser.next();
          skipEmptyTextTags(parser);
          expect(parser, XmlPullParser.END_TAG, TAG_RESOLUTION);
          parser.next();
        }

        skipEmptyTextTags(parser);
        if (accept(parser, XmlPullParser.START_TAG, TAG_MARGINS)) {
          final int leftMils = Integer.parseInt(parser.getAttributeValue(null, ATTR_LEFT_MILS));
          final int topMils = Integer.parseInt(parser.getAttributeValue(null, ATTR_TOP_MILS));
          final int rightMils = Integer.parseInt(parser.getAttributeValue(null, ATTR_RIGHT_MILS));
          final int bottomMils = Integer.parseInt(parser.getAttributeValue(null, ATTR_BOTTOM_MILS));
          Margins margins = new Margins(leftMils, topMils, rightMils, bottomMils);
          builder.setMinMargins(margins);
          parser.next();
          skipEmptyTextTags(parser);
          expect(parser, XmlPullParser.END_TAG, TAG_MARGINS);
          parser.next();
        }

        printJob.setAttributes(builder.build());

        skipEmptyTextTags(parser);
        expect(parser, XmlPullParser.END_TAG, TAG_ATTRIBUTES);
        parser.next();
      }

      skipEmptyTextTags(parser);
      if (accept(parser, XmlPullParser.START_TAG, TAG_DOCUMENT_INFO)) {
        String name = parser.getAttributeValue(null, ATTR_NAME);
        final int pageCount = Integer.parseInt(parser.getAttributeValue(null, ATTR_PAGE_COUNT));
        final int contentType = Integer.parseInt(parser.getAttributeValue(null, ATTR_CONTENT_TYPE));
        final int dataSize = Integer.parseInt(parser.getAttributeValue(null, ATTR_DATA_SIZE));
        PrintDocumentInfo info =
            new PrintDocumentInfo.Builder(name)
                .setPageCount(pageCount)
                .setContentType(contentType)
                .build();
        printJob.setDocumentInfo(info);
        info.setDataSize(dataSize);
        parser.next();
        skipEmptyTextTags(parser);
        expect(parser, XmlPullParser.END_TAG, TAG_DOCUMENT_INFO);
        parser.next();
      }

      skipEmptyTextTags(parser);
      if (accept(parser, XmlPullParser.START_TAG, TAG_ADVANCED_OPTIONS)) {
        parser.next();
        skipEmptyTextTags(parser);
        Bundle advancedOptions = new Bundle();
        while (accept(parser, XmlPullParser.START_TAG, TAG_ADVANCED_OPTION)) {
          String key = parser.getAttributeValue(null, ATTR_KEY);
          String value = parser.getAttributeValue(null, ATTR_VALUE);
          String type = parser.getAttributeValue(null, ATTR_TYPE);
          if (TYPE_STRING.equals(type)) {
            advancedOptions.putString(key, value);
          } else if (TYPE_INT.equals(type)) {
            advancedOptions.putInt(key, Integer.valueOf(value));
          }
          parser.next();
          skipEmptyTextTags(parser);
          expect(parser, XmlPullParser.END_TAG, TAG_ADVANCED_OPTION);
          parser.next();
          skipEmptyTextTags(parser);
        }
        printJob.setAdvancedOptions(advancedOptions);
        skipEmptyTextTags(parser);
        expect(parser, XmlPullParser.END_TAG, TAG_ADVANCED_OPTIONS);
        parser.next();
      }

      mPrintJobs.add(printJob);

      if (DEBUG_PERSISTENCE) {
        Log.i(LOG_TAG, "[RESTORED] " + printJob);
      }

      skipEmptyTextTags(parser);
      expect(parser, XmlPullParser.END_TAG, TAG_JOB);

      return true;
    }
  public boolean setPrintJobState(PrintJobId printJobId, int state, String error) {
    boolean success = false;

    synchronized (mLock) {
      PrintJobInfo printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY);
      if (printJob != null) {
        final int oldState = printJob.getState();
        if (oldState == state) {
          return false;
        }

        success = true;

        printJob.setState(state);
        printJob.setStateReason(error);
        printJob.setCancelling(false);

        if (DEBUG_PRINT_JOB_LIFECYCLE) {
          Slog.i(LOG_TAG, "[STATE CHANGED] " + printJob);
        }

        switch (state) {
          case PrintJobInfo.STATE_COMPLETED:
          case PrintJobInfo.STATE_CANCELED:
            mPrintJobs.remove(printJob);
            removePrintJobFileLocked(printJob.getId());
            // $fall-through$

          case PrintJobInfo.STATE_FAILED:
            {
              PrinterId printerId = printJob.getPrinterId();
              if (printerId != null) {
                ComponentName service = printerId.getServiceName();
                if (!hasActivePrintJobsForServiceLocked(service)) {
                  sendOnAllPrintJobsForServiceHandled(service);
                }
              }
            }
            break;

          case PrintJobInfo.STATE_QUEUED:
            {
              sendOnPrintJobQueued(new PrintJobInfo(printJob));
            }
            break;
        }

        if (shouldPersistPrintJob(printJob)) {
          mPersistanceManager.writeStateLocked();
        }

        if (!hasActivePrintJobsLocked()) {
          notifyOnAllPrintJobsHandled();
        }

        Message message =
            mHandlerCaller.obtainMessageO(
                HandlerCallerCallback.MSG_ON_PRINT_JOB_STATE_CHANGED, printJob);
        mHandlerCaller.executeOrSendMessage(message);

        mNotificationController.onUpdateNotifications(mPrintJobs);
      }
    }

    return success;
  }