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

Commit 8ee5ab57 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Automerger Merge Worker
Browse files

Merge "Fix ApkLite attribute parsing" into sc-dev am: 46620933

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/14603261

Change-Id: Ide64b4c7a6764b7432d568f3edbbbbec0638b65c
parents d9c25573 46620933
Loading
Loading
Loading
Loading
+97 −123
Original line number Diff line number Diff line
@@ -19,6 +19,9 @@ package android.content.pm.parsing;
import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
import static android.content.pm.parsing.ParsingPackageUtils.validateName;
import static android.content.pm.parsing.ParsingUtils.ANDROID_RES_NAMESPACE;
import static android.content.pm.parsing.ParsingUtils.DEFAULT_MIN_SDK_VERSION;
import static android.content.pm.parsing.ParsingUtils.DEFAULT_TARGET_SDK_VERSION;
import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;

import android.annotation.NonNull;
@@ -31,6 +34,7 @@ import android.content.pm.parsing.result.ParseResult;
import android.content.res.ApkAssets;
import android.content.res.XmlResourceParser;
import android.os.Trace;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.AttributeSet;
import android.util.Pair;
@@ -59,10 +63,6 @@ public class ApkLiteParseUtils {

    private static final String TAG = ParsingUtils.TAG;

    // TODO(b/135203078): Consolidate constants
    private static final int DEFAULT_MIN_SDK_VERSION = 1;
    private static final int DEFAULT_TARGET_SDK_VERSION = 0;

    private static final int PARSE_DEFAULT_INSTALL_LOCATION =
            PackageInfo.INSTALL_LOCATION_UNSPECIFIED;

@@ -323,8 +323,7 @@ public class ApkLiteParseUtils {
                signingDetails = PackageParser.SigningDetails.UNKNOWN;
            }

            final AttributeSet attrs = parser;
            return parseApkLite(input, apkPath, parser, attrs, signingDetails);
            return parseApkLite(input, apkPath, parser, signingDetails);
        } catch (XmlPullParserException | IOException | RuntimeException e) {
            Slog.w(TAG, "Failed to parse " + apkPath, e);
            return input.error(PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
@@ -342,32 +341,39 @@ public class ApkLiteParseUtils {
    }

    private static ParseResult<ApkLite> parseApkLite(ParseInput input, String codePath,
            XmlPullParser parser, AttributeSet attrs, PackageParser.SigningDetails signingDetails)
            XmlResourceParser parser, PackageParser.SigningDetails signingDetails)
            throws IOException, XmlPullParserException {
        ParseResult<Pair<String, String>> result = parsePackageSplitNames(input, parser, attrs);
        ParseResult<Pair<String, String>> result = parsePackageSplitNames(input, parser);
        if (result.isError()) {
            return input.error(result);
        }

        Pair<String, String> packageSplit = result.getResult();

        int installLocation = PARSE_DEFAULT_INSTALL_LOCATION;
        int versionCode = 0;
        int versionCodeMajor = 0;
        int installLocation = parser.getAttributeIntValue(ANDROID_RES_NAMESPACE,
                "installLocation", PARSE_DEFAULT_INSTALL_LOCATION);
        int versionCode = parser.getAttributeIntValue(ANDROID_RES_NAMESPACE, "versionCode", 0);
        int versionCodeMajor = parser.getAttributeIntValue(ANDROID_RES_NAMESPACE,
                "versionCodeMajor",
                0);
        int revisionCode = parser.getAttributeIntValue(ANDROID_RES_NAMESPACE, "revisionCode", 0);
        boolean coreApp = parser.getAttributeBooleanValue("", "coreApp", false);
        boolean isolatedSplits = parser.getAttributeBooleanValue(ANDROID_RES_NAMESPACE,
                "isolatedSplits", false);
        boolean isFeatureSplit = parser.getAttributeBooleanValue(ANDROID_RES_NAMESPACE,
                "isFeatureSplit", false);
        boolean isSplitRequired = parser.getAttributeBooleanValue(ANDROID_RES_NAMESPACE,
                "isSplitRequired", false);
        String configForSplit = parser.getAttributeValue(ANDROID_RES_NAMESPACE, "configForSplit");

        int targetSdkVersion = DEFAULT_TARGET_SDK_VERSION;
        int minSdkVersion = DEFAULT_MIN_SDK_VERSION;
        int revisionCode = 0;
        boolean coreApp = false;
        boolean debuggable = false;
        boolean profilableByShell = false;
        boolean multiArch = false;
        boolean use32bitAbi = false;
        boolean extractNativeLibs = true;
        boolean isolatedSplits = false;
        boolean isFeatureSplit = false;
        boolean isSplitRequired = false;
        boolean useEmbeddedDex = false;
        String configForSplit = null;
        String usesSplitName = null;
        String targetPackage = null;
        boolean overlayIsStatic = false;
@@ -377,40 +383,6 @@ public class ApkLiteParseUtils {
        String requiredSystemPropertyName = null;
        String requiredSystemPropertyValue = null;

        for (int i = 0; i < attrs.getAttributeCount(); i++) {
            final String attr = attrs.getAttributeName(i);
            switch (attr) {
                case "installLocation":
                    installLocation = attrs.getAttributeIntValue(i,
                            PARSE_DEFAULT_INSTALL_LOCATION);
                    break;
                case "versionCode":
                    versionCode = attrs.getAttributeIntValue(i, 0);
                    break;
                case "versionCodeMajor":
                    versionCodeMajor = attrs.getAttributeIntValue(i, 0);
                    break;
                case "revisionCode":
                    revisionCode = attrs.getAttributeIntValue(i, 0);
                    break;
                case "coreApp":
                    coreApp = attrs.getAttributeBooleanValue(i, false);
                    break;
                case "isolatedSplits":
                    isolatedSplits = attrs.getAttributeBooleanValue(i, false);
                    break;
                case "configForSplit":
                    configForSplit = attrs.getAttributeValue(i);
                    break;
                case "isFeatureSplit":
                    isFeatureSplit = attrs.getAttributeBooleanValue(i, false);
                    break;
                case "isSplitRequired":
                    isSplitRequired = attrs.getAttributeBooleanValue(i, false);
                    break;
            }
        }

        // Only search the tree when the tag is the direct child of <manifest> tag
        int type;
        final int searchDepth = parser.getDepth() + 1;
@@ -427,34 +399,23 @@ public class ApkLiteParseUtils {
            }

            if (ParsingPackageUtils.TAG_PACKAGE_VERIFIER.equals(parser.getName())) {
                final VerifierInfo verifier = parseVerifier(attrs);
                final VerifierInfo verifier = parseVerifier(parser);
                if (verifier != null) {
                    verifiers.add(verifier);
                }
            } else if (ParsingPackageUtils.TAG_APPLICATION.equals(parser.getName())) {
                for (int i = 0; i < attrs.getAttributeCount(); ++i) {
                    final String attr = attrs.getAttributeName(i);
                    switch (attr) {
                        case "debuggable":
                            debuggable = attrs.getAttributeBooleanValue(i, false);
                            break;
                        case "multiArch":
                            multiArch = attrs.getAttributeBooleanValue(i, false);
                            break;
                        case "use32bitAbi":
                            use32bitAbi = attrs.getAttributeBooleanValue(i, false);
                            break;
                        case "extractNativeLibs":
                            extractNativeLibs = attrs.getAttributeBooleanValue(i, true);
                            break;
                        case "useEmbeddedDex":
                            useEmbeddedDex = attrs.getAttributeBooleanValue(i, false);
                            break;
                        case "rollbackDataPolicy":
                            rollbackDataPolicy = attrs.getAttributeIntValue(i, 0);
                            break;
                    }
                }
                debuggable = parser.getAttributeBooleanValue(ANDROID_RES_NAMESPACE, "debuggable",
                        false);
                multiArch = parser.getAttributeBooleanValue(ANDROID_RES_NAMESPACE, "multiArch",
                        false);
                use32bitAbi = parser.getAttributeBooleanValue(ANDROID_RES_NAMESPACE, "use32bitAbi",
                        false);
                extractNativeLibs = parser.getAttributeBooleanValue(ANDROID_RES_NAMESPACE,
                        "extractNativeLibs", true);
                useEmbeddedDex = parser.getAttributeBooleanValue(ANDROID_RES_NAMESPACE,
                        "useEmbeddedDex", false);
                rollbackDataPolicy = parser.getAttributeIntValue(ANDROID_RES_NAMESPACE,
                        "rollbackDataPolicy", 0);

                final int innerDepth = parser.getDepth();
                int innerType;
@@ -470,52 +431,79 @@ public class ApkLiteParseUtils {
                    }

                    if (ParsingPackageUtils.TAG_PROFILEABLE.equals(parser.getName())) {
                        for (int i = 0; i < attrs.getAttributeCount(); ++i) {
                            final String attr = attrs.getAttributeName(i);
                            if ("shell".equals(attr)) {
                                profilableByShell = attrs.getAttributeBooleanValue(i,
                                        profilableByShell);
                            }
                        }
                        profilableByShell = parser.getAttributeBooleanValue(ANDROID_RES_NAMESPACE,
                                "shell", profilableByShell);
                    }
                }
            } else if (ParsingPackageUtils.TAG_OVERLAY.equals(parser.getName())) {
                for (int i = 0; i < attrs.getAttributeCount(); ++i) {
                    final String attr = attrs.getAttributeName(i);
                    if ("requiredSystemPropertyName".equals(attr)) {
                        requiredSystemPropertyName = attrs.getAttributeValue(i);
                    } else if ("requiredSystemPropertyValue".equals(attr)) {
                        requiredSystemPropertyValue = attrs.getAttributeValue(i);
                    } else if ("targetPackage".equals(attr)) {
                        targetPackage = attrs.getAttributeValue(i);;
                    } else if ("isStatic".equals(attr)) {
                        overlayIsStatic = attrs.getAttributeBooleanValue(i, false);
                    } else if ("priority".equals(attr)) {
                        overlayPriority = attrs.getAttributeIntValue(i, 0);
                    }
                }
                requiredSystemPropertyName = parser.getAttributeValue(ANDROID_RES_NAMESPACE,
                        "requiredSystemPropertyName");
                requiredSystemPropertyValue = parser.getAttributeValue(ANDROID_RES_NAMESPACE,
                        "requiredSystemPropertyValue");
                targetPackage = parser.getAttributeValue(ANDROID_RES_NAMESPACE, "targetPackage");
                overlayIsStatic = parser.getAttributeBooleanValue(ANDROID_RES_NAMESPACE, "isStatic",
                        false);
                overlayPriority = parser.getAttributeIntValue(ANDROID_RES_NAMESPACE, "priority", 0);
            } else if (ParsingPackageUtils.TAG_USES_SPLIT.equals(parser.getName())) {
                if (usesSplitName != null) {
                    Slog.w(TAG, "Only one <uses-split> permitted. Ignoring others.");
                    continue;
                }

                usesSplitName = attrs.getAttributeValue(PackageParser.ANDROID_RESOURCES, "name");
                usesSplitName = parser.getAttributeValue(ANDROID_RES_NAMESPACE, "name");
                if (usesSplitName == null) {
                    return input.error(PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
                            "<uses-split> tag requires 'android:name' attribute");
                }
            } else if (ParsingPackageUtils.TAG_USES_SDK.equals(parser.getName())) {
                for (int i = 0; i < attrs.getAttributeCount(); ++i) {
                    final String attr = attrs.getAttributeName(i);
                    if ("targetSdkVersion".equals(attr)) {
                        targetSdkVersion = attrs.getAttributeIntValue(i,
                                DEFAULT_TARGET_SDK_VERSION);
                // Mirrors ParsingPackageUtils#parseUsesSdk until lite and full parsing is combined
                String minSdkVersionString = parser.getAttributeValue(ANDROID_RES_NAMESPACE,
                        "minSdkVersion");
                String targetSdkVersionString = parser.getAttributeValue(ANDROID_RES_NAMESPACE,
                        "targetSdkVersion");

                int minVer = DEFAULT_MIN_SDK_VERSION;
                String minCode = null;
                int targetVer = DEFAULT_TARGET_SDK_VERSION;
                String targetCode = null;

                if (!TextUtils.isEmpty(minSdkVersionString)) {
                    try {
                        minVer = Integer.parseInt(minSdkVersionString);
                    } catch (NumberFormatException ignored) {
                        minCode = minSdkVersionString;
                    }
                    if ("minSdkVersion".equals(attr)) {
                        minSdkVersion = attrs.getAttributeIntValue(i, DEFAULT_MIN_SDK_VERSION);
                }

                if (!TextUtils.isEmpty(targetSdkVersionString)) {
                    try {
                        targetVer = Integer.parseInt(targetSdkVersionString);
                    } catch (NumberFormatException ignored) {
                        targetCode = targetSdkVersionString;
                        if (minCode == null) {
                            minCode = targetCode;
                        }
                    }
                } else {
                    targetVer = minVer;
                    targetCode = minCode;
                }

                ParseResult<Integer> targetResult = ParsingPackageUtils.computeTargetSdkVersion(
                        targetVer, targetCode, ParsingPackageUtils.SDK_CODENAMES, input);
                if (targetResult.isError()) {
                    return input.error(targetResult);
                }

                ParseResult<Integer> minResult = ParsingPackageUtils.computeMinSdkVersion(
                        minVer, minCode, ParsingPackageUtils.SDK_VERSION,
                        ParsingPackageUtils.SDK_CODENAMES, input);
                if (minResult.isError()) {
                    return input.error(minResult);
                }

                targetSdkVersion = targetResult.getResult();
                minSdkVersion = minResult.getResult();
            }
        }

@@ -541,7 +529,7 @@ public class ApkLiteParseUtils {
    }

    public static ParseResult<Pair<String, String>> parsePackageSplitNames(ParseInput input,
            XmlPullParser parser, AttributeSet attrs) throws IOException, XmlPullParserException {
            XmlResourceParser parser) throws IOException, XmlPullParserException {
        int type;
        while ((type = parser.next()) != XmlPullParser.START_TAG
                && type != XmlPullParser.END_DOCUMENT) {
@@ -556,7 +544,7 @@ public class ApkLiteParseUtils {
                    "No <manifest> tag");
        }

        final String packageName = attrs.getAttributeValue(null, "package");
        final String packageName = parser.getAttributeValue(null, "package");
        if (!"android".equals(packageName)) {
            final ParseResult<?> nameResult = validateName(input, packageName, true, true);
            if (nameResult.isError()) {
@@ -565,7 +553,7 @@ public class ApkLiteParseUtils {
            }
        }

        String splitName = attrs.getAttributeValue(null, "split");
        String splitName = parser.getAttributeValue(null, "split");
        if (splitName != null) {
            if (splitName.length() == 0) {
                splitName = null;
@@ -583,22 +571,8 @@ public class ApkLiteParseUtils {
    }

    public static VerifierInfo parseVerifier(AttributeSet attrs) {
        String packageName = null;
        String encodedPublicKey = null;

        final int attrCount = attrs.getAttributeCount();
        for (int i = 0; i < attrCount; i++) {
            final int attrResId = attrs.getAttributeNameResource(i);
            switch (attrResId) {
                case R.attr.name:
                    packageName = attrs.getAttributeValue(i);
                    break;

                case R.attr.publicKey:
                    encodedPublicKey = attrs.getAttributeValue(i);
                    break;
            }
        }
        String packageName = attrs.getAttributeValue(ANDROID_RES_NAMESPACE, "name");
        String encodedPublicKey = attrs.getAttributeValue(ANDROID_RES_NAMESPACE, "publicKey");

        if (packageName == null || packageName.length() == 0) {
            Slog.i(TAG, "verifier package name was null; skipping");
+2 −2
Original line number Diff line number Diff line
@@ -356,7 +356,7 @@ public class ParsingPackageImpl implements ParsingPackage, Parcelable {
    private float minAspectRatio;
    @Nullable
    private SparseIntArray minExtensionVersions;
    private int minSdkVersion;
    private int minSdkVersion = ParsingUtils.DEFAULT_MIN_SDK_VERSION;
    private int networkSecurityConfigRes;
    @Nullable
    private CharSequence nonLocalizedLabel;
@@ -369,7 +369,7 @@ public class ParsingPackageImpl implements ParsingPackage, Parcelable {
    private int requiresSmallestWidthDp;
    private int roundIconRes;
    private int targetSandboxVersion;
    private int targetSdkVersion;
    private int targetSdkVersion = ParsingUtils.DEFAULT_TARGET_SDK_VERSION;
    @Nullable
    @DataClass.ParcelWith(ForInternedString.class)
    private String taskAffinity;
+4 −4
Original line number Diff line number Diff line
@@ -582,12 +582,12 @@ public class ParsingPackageUtils {
     */
    private ParseResult<ParsingPackage> parseBaseApk(ParseInput input, String apkPath,
            String codePath, Resources res, XmlResourceParser parser, int flags)
            throws XmlPullParserException, IOException, PackageParserException {
            throws XmlPullParserException, IOException {
        final String splitName;
        final String pkgName;

        ParseResult<Pair<String, String>> packageSplitResult =
                ApkLiteParseUtils.parsePackageSplitNames(input, parser, parser);
                ApkLiteParseUtils.parsePackageSplitNames(input, parser);
        if (packageSplitResult.isError()) {
            return input.error(packageSplitResult);
        }
@@ -1460,9 +1460,9 @@ public class ParsingPackageUtils {
        if (SDK_VERSION > 0) {
            TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestUsesSdk);
            try {
                int minVers = 1;
                int minVers = ParsingUtils.DEFAULT_MIN_SDK_VERSION;
                String minCode = null;
                int targetVers = 0;
                int targetVers = ParsingUtils.DEFAULT_TARGET_SDK_VERSION;
                String targetCode = null;

                TypedValue val = sa.peekValue(R.styleable.AndroidManifestUsesSdk_minSdkVersion);
+5 −0
Original line number Diff line number Diff line
@@ -35,6 +35,11 @@ public class ParsingUtils {

    public static final String TAG = "PackageParsing";

    public static final String ANDROID_RES_NAMESPACE = "http://schemas.android.com/apk/res/android";

    public static final int DEFAULT_MIN_SDK_VERSION = 1;
    public static final int DEFAULT_TARGET_SDK_VERSION = 0;

    @Nullable
    public static String buildClassName(String pkg, CharSequence clsSeq) {
        if (clsSeq == null || clsSeq.length() <= 0) {