diff --git a/core/java/android/content/pm/parsing/ApkLiteParseUtils.java b/core/java/android/content/pm/parsing/ApkLiteParseUtils.java index 5887047728a63..76b98659067fe 100644 --- a/core/java/android/content/pm/parsing/ApkLiteParseUtils.java +++ b/core/java/android/content/pm/parsing/ApkLiteParseUtils.java @@ -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 parseApkLite(ParseInput input, String codePath, - XmlPullParser parser, AttributeSet attrs, PackageParser.SigningDetails signingDetails) + XmlResourceParser parser, PackageParser.SigningDetails signingDetails) throws IOException, XmlPullParserException { - ParseResult> result = parsePackageSplitNames(input, parser, attrs); + ParseResult> result = parsePackageSplitNames(input, parser); if (result.isError()) { return input.error(result); } Pair 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 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 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, " 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); - } - if ("minSdkVersion".equals(attr)) { - minSdkVersion = attrs.getAttributeIntValue(i, DEFAULT_MIN_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 (!TextUtils.isEmpty(targetSdkVersionString)) { + try { + targetVer = Integer.parseInt(targetSdkVersionString); + } catch (NumberFormatException ignored) { + targetCode = targetSdkVersionString; + if (minCode == null) { + minCode = targetCode; + } + } + } else { + targetVer = minVer; + targetCode = minCode; + } + + ParseResult targetResult = ParsingPackageUtils.computeTargetSdkVersion( + targetVer, targetCode, ParsingPackageUtils.SDK_CODENAMES, input); + if (targetResult.isError()) { + return input.error(targetResult); + } + + ParseResult 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> 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 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"); diff --git a/core/java/android/content/pm/parsing/ParsingPackageImpl.java b/core/java/android/content/pm/parsing/ParsingPackageImpl.java index f0b76499093c9..4c44ba1fc9ef2 100644 --- a/core/java/android/content/pm/parsing/ParsingPackageImpl.java +++ b/core/java/android/content/pm/parsing/ParsingPackageImpl.java @@ -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; diff --git a/core/java/android/content/pm/parsing/ParsingPackageUtils.java b/core/java/android/content/pm/parsing/ParsingPackageUtils.java index b74760ac8bc42..6fd533355aad7 100644 --- a/core/java/android/content/pm/parsing/ParsingPackageUtils.java +++ b/core/java/android/content/pm/parsing/ParsingPackageUtils.java @@ -582,12 +582,12 @@ public class ParsingPackageUtils { */ private ParseResult 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> 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); diff --git a/core/java/android/content/pm/parsing/ParsingUtils.java b/core/java/android/content/pm/parsing/ParsingUtils.java index 5da5fbf4d8a7b..07ec6a80c2832 100644 --- a/core/java/android/content/pm/parsing/ParsingUtils.java +++ b/core/java/android/content/pm/parsing/ParsingUtils.java @@ -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) {