Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a0036e4e authored by William Loh's avatar William Loh
Browse files

Eliminate redundant attribute reads in validation

The validator was reading all string attributes in addition to the
attribute reads in PackageParsing. Eliminating the attribute reads
from the validator and instead validating at the time when attributes
are read in PackageParser further reduces the performance regression
to ~5%. The mean times measured on a lynx devices are:

PackageParsingPerfTest#sequentialNoCache[v1]_new_ns: 748223578
PackageParsingPerfTest#sequentialNoCache[v1]_old_ns: 790309363
PackageParsingPerfTest#sequentialNoCache[v1]_none_ns: 717520130

Bug: 289190523, 267185315
Test: atest PackageParsingPerfTest
Test: atest AndroidPackageParsingValidationTest
Change-Id: I53e3606a48fd97b2e27e41f34bb83029ab908807
parent b6496fef
Loading
Loading
Loading
Loading
+400 −137

File changed.

Preview size limit exceeded, changes collapsed.

+6 −5
Original line number Diff line number Diff line
@@ -1393,16 +1393,17 @@ public class TypedArray implements AutoCloseable {
    private CharSequence loadStringValueAt(int index) {
        final int[] data = mData;
        final int cookie = data[index + STYLE_ASSET_COOKIE];
        CharSequence value = null;
        if (cookie < 0) {
            if (mXml != null) {
                return mXml.getPooledString(data[index + STYLE_DATA]);
                value = mXml.getPooledString(data[index + STYLE_DATA]);
            }
            return null;
        } else {
            value = mAssets.getPooledStringForCookie(cookie, data[index + STYLE_DATA]);
        }
        CharSequence value = mAssets.getPooledStringForCookie(cookie, data[index + STYLE_DATA]);
        if (mXml != null && mXml.mValidator != null) {
        if (value != null && mXml != null && mXml.mValidator != null) {
            try {
                mXml.mValidator.validateAttr(mXml, index, value);
                mXml.mValidator.validateResStrAttr(mXml, index / STYLE_NUM_ENTRIES, value);
            } catch (XmlPullParserException e) {
                throw new RuntimeException("Failed to validate resource string: " + e.getMessage());
            }
+23 −19
Original line number Diff line number Diff line
@@ -16,9 +16,8 @@

package android.content.res;

import static android.content.res.Element.TAG_MANIFEST;

import android.annotation.NonNull;
import android.annotation.StyleableRes;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -55,25 +54,20 @@ public class Validator {
            return;
        }
        if (eventType == XmlPullParser.START_TAG) {
            try {
            String tag = parser.getName();
                // only validate manifests
                if (depth == 0 && mElements.size() == 0 && !TAG_MANIFEST.equals(tag)) {
                    return;
                }
                Element parent = mElements.peek();
                if (parent == null || parent.hasChild(tag)) {
            if (Element.shouldValidate(tag)) {
                Element element = Element.obtain(tag);
                    element.validateStringAttrs(parser);
                    if (parent != null) {
                Element parent = mElements.peek();
                if (parent != null && parent.hasChild(tag)) {
                    try {
                        parent.seen(element);
                    }
                    mElements.push(element);
                }
            } catch (XmlPullParserException e) {
                    } catch (SecurityException e) {
                        cleanUp();
                        throw e;
                    }
                }
                mElements.push(element);
            }
        } else if (eventType == XmlPullParser.END_TAG && depth == mElements.size()) {
            mElements.pop().recycle();
        } else if (eventType == XmlPullParser.END_DOCUMENT) {
@@ -84,11 +78,21 @@ public class Validator {
    /**
     * Validates the resource string of a manifest tag attribute.
     */
    public void validateAttr(@NonNull XmlPullParser parser, int index, CharSequence stringValue)
            throws XmlPullParserException {
    public void validateResStrAttr(@NonNull XmlPullParser parser, @StyleableRes int index,
            CharSequence stringValue) throws XmlPullParserException {
        if (parser.getDepth() > mElements.size()) {
            return;
        }
        mElements.peek().validateResStrAttr(index, stringValue);
    }

    /**
     * Validates the string of a manifest tag attribute by name.
     */
    public void validateStrAttr(@NonNull XmlPullParser parser, String attrName, String attrValue) {
        if (parser.getDepth() > mElements.size()) {
            return;
        }
        mElements.peek().validateResStringAttr(index, stringValue);
        mElements.peek().validateStrAttr(attrName, attrValue);
    }
}
+5 −1
Original line number Diff line number Diff line
@@ -319,7 +319,11 @@ public final class XmlBlock implements AutoCloseable {
                        "Namespace=" + getAttributeNamespace(idx)
                        + "Name=" + getAttributeName(idx)
                        + ", Value=" + getAttributeValue(idx));
                return getAttributeValue(idx);
                String value = getAttributeValue(idx);
                if (mValidator != null) {
                    mValidator.validateStrAttr(this, name, value);
                }
                return value;
            }
            return null;
        }
+290 −504

File changed.

Preview size limit exceeded, changes collapsed.