public static File generateFileForPrintJob(Context context, PrintJobId printJobId) {
   return new File(
       context.getFilesDir(),
       PRINT_JOB_FILE_PREFIX + printJobId.flattenToString() + "." + PRINT_FILE_EXTENSION);
 }
    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;
    }
  private void handleReadPrintJobsLocked() {
    // Make a map with the files for a print job since we may have
    // to delete some. One example of getting orphan files if the
    // spooler crashes while constructing a print job. We do not
    // persist partially populated print jobs under construction to
    // avoid special handling for various attributes missing.
    ArrayMap<PrintJobId, File> fileForJobMap = null;
    File[] files = getFilesDir().listFiles();
    if (files != null) {
      final int fileCount = files.length;
      for (int i = 0; i < fileCount; i++) {
        File file = files[i];
        if (file.isFile() && file.getName().startsWith(PRINT_JOB_FILE_PREFIX)) {
          if (fileForJobMap == null) {
            fileForJobMap = new ArrayMap<PrintJobId, File>();
          }
          String printJobIdString =
              file.getName().substring(PRINT_JOB_FILE_PREFIX.length(), file.getName().indexOf('.'));
          PrintJobId printJobId = PrintJobId.unflattenFromString(printJobIdString);
          fileForJobMap.put(printJobId, file);
        }
      }
    }

    final int printJobCount = mPrintJobs.size();
    for (int i = 0; i < printJobCount; i++) {
      PrintJobInfo printJob = mPrintJobs.get(i);

      // We want to have only the orphan files at the end.
      if (fileForJobMap != null) {
        fileForJobMap.remove(printJob.getId());
      }

      switch (printJob.getState()) {
        case PrintJobInfo.STATE_QUEUED:
        case PrintJobInfo.STATE_STARTED:
        case PrintJobInfo.STATE_BLOCKED:
          {
            // We have a print job that was queued or started or blocked in
            // the past but the device battery died or a crash occurred. In
            // this case we assume the print job failed and let the user
            // decide whether to restart the job or just cancel it.
            setPrintJobState(
                printJob.getId(),
                PrintJobInfo.STATE_FAILED,
                getString(R.string.no_connection_to_printer));
          }
          break;
      }
    }

    if (!mPrintJobs.isEmpty()) {
      // Update the notification.
      mNotificationController.onUpdateNotifications(mPrintJobs);
    }

    // Delete the orphan files.
    if (fileForJobMap != null) {
      final int orphanFileCount = fileForJobMap.size();
      for (int i = 0; i < orphanFileCount; i++) {
        File file = fileForJobMap.valueAt(i);
        file.delete();
      }
    }
  }