@Override
    public void handleTag(boolean opening, String tag, Editable output, XMLReader xmlReader) {
      if ("ul".equalsIgnoreCase(tag)) {
        // Ensure there are at least two newlines both before and after the list.
        ensureAtLeastTwoTrailingNewlines(output);
      } else if ("li".equalsIgnoreCase(tag)) {
        appendNewlineIfNoTrailingNewline(output);
        int outputLength = output.length();
        if (opening) {
          // Attach a BulletSpan to the beginning of the list entry. The span will be removed
          // when processing the closing of this tag/entry.
          output.setSpan(new BulletSpan(), outputLength, outputLength, Spannable.SPAN_MARK_MARK);
        } else {
          // Attach a BulletSpan, spanning the whole list entry. This removes the span
          // attached to the start of this list entry when processing the opening of this tag/entry.
          // We also attach a LeadingMarginSpan to the same location to indent the list entries
          // and their bullets.
          BulletSpan[] bulletSpans = output.getSpans(0, outputLength, BulletSpan.class);
          if (bulletSpans.length > 0) {
            BulletSpan startMarkSpan = bulletSpans[bulletSpans.length - 1];
            int startIndex = output.getSpanStart(startMarkSpan);
            output.removeSpan(startMarkSpan);
            if (startIndex != outputLength) {
              output.setSpan(
                  new LeadingMarginSpan.Standard(10),
                  startIndex,
                  outputLength,
                  Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
              output.setSpan(
                  new BulletSpan(10),
                  startIndex,
                  outputLength,
                  Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
            }
          }
        }
      }
    }
{@link TagHandler} that adds support for bullet lists.
java/com/google/android/apps/authenticator/util/Utilities.java