Merge "Fix ApkLite attribute parsing" into sc-dev

This commit is contained in:
TreeHugger Robot
2021-06-07 21:42:17 +00:00
committed by Android (Google) Code Review
4 changed files with 109 additions and 130 deletions

View File

@@ -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_BAD_PACKAGE_NAME;
import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 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.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 static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
import android.annotation.NonNull; import android.annotation.NonNull;
@@ -31,6 +34,7 @@ import android.content.pm.parsing.result.ParseResult;
import android.content.res.ApkAssets; import android.content.res.ApkAssets;
import android.content.res.XmlResourceParser; import android.content.res.XmlResourceParser;
import android.os.Trace; import android.os.Trace;
import android.text.TextUtils;
import android.util.ArrayMap; import android.util.ArrayMap;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.util.Pair; import android.util.Pair;
@@ -59,10 +63,6 @@ public class ApkLiteParseUtils {
private static final String TAG = ParsingUtils.TAG; 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 = private static final int PARSE_DEFAULT_INSTALL_LOCATION =
PackageInfo.INSTALL_LOCATION_UNSPECIFIED; PackageInfo.INSTALL_LOCATION_UNSPECIFIED;
@@ -323,8 +323,7 @@ public class ApkLiteParseUtils {
signingDetails = PackageParser.SigningDetails.UNKNOWN; signingDetails = PackageParser.SigningDetails.UNKNOWN;
} }
final AttributeSet attrs = parser; return parseApkLite(input, apkPath, parser, signingDetails);
return parseApkLite(input, apkPath, parser, attrs, signingDetails);
} catch (XmlPullParserException | IOException | RuntimeException e) { } catch (XmlPullParserException | IOException | RuntimeException e) {
Slog.w(TAG, "Failed to parse " + apkPath, e); Slog.w(TAG, "Failed to parse " + apkPath, e);
return input.error(PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION, 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, private static ParseResult<ApkLite> parseApkLite(ParseInput input, String codePath,
XmlPullParser parser, AttributeSet attrs, PackageParser.SigningDetails signingDetails) XmlResourceParser parser, PackageParser.SigningDetails signingDetails)
throws IOException, XmlPullParserException { throws IOException, XmlPullParserException {
ParseResult<Pair<String, String>> result = parsePackageSplitNames(input, parser, attrs); ParseResult<Pair<String, String>> result = parsePackageSplitNames(input, parser);
if (result.isError()) { if (result.isError()) {
return input.error(result); return input.error(result);
} }
Pair<String, String> packageSplit = result.getResult(); Pair<String, String> packageSplit = result.getResult();
int installLocation = PARSE_DEFAULT_INSTALL_LOCATION; int installLocation = parser.getAttributeIntValue(ANDROID_RES_NAMESPACE,
int versionCode = 0; "installLocation", PARSE_DEFAULT_INSTALL_LOCATION);
int versionCodeMajor = 0; 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 targetSdkVersion = DEFAULT_TARGET_SDK_VERSION;
int minSdkVersion = DEFAULT_MIN_SDK_VERSION; int minSdkVersion = DEFAULT_MIN_SDK_VERSION;
int revisionCode = 0;
boolean coreApp = false;
boolean debuggable = false; boolean debuggable = false;
boolean profilableByShell = false; boolean profilableByShell = false;
boolean multiArch = false; boolean multiArch = false;
boolean use32bitAbi = false; boolean use32bitAbi = false;
boolean extractNativeLibs = true; boolean extractNativeLibs = true;
boolean isolatedSplits = false;
boolean isFeatureSplit = false;
boolean isSplitRequired = false;
boolean useEmbeddedDex = false; boolean useEmbeddedDex = false;
String configForSplit = null;
String usesSplitName = null; String usesSplitName = null;
String targetPackage = null; String targetPackage = null;
boolean overlayIsStatic = false; boolean overlayIsStatic = false;
@@ -377,40 +383,6 @@ public class ApkLiteParseUtils {
String requiredSystemPropertyName = null; String requiredSystemPropertyName = null;
String requiredSystemPropertyValue = 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 // Only search the tree when the tag is the direct child of <manifest> tag
int type; int type;
final int searchDepth = parser.getDepth() + 1; final int searchDepth = parser.getDepth() + 1;
@@ -427,34 +399,23 @@ public class ApkLiteParseUtils {
} }
if (ParsingPackageUtils.TAG_PACKAGE_VERIFIER.equals(parser.getName())) { if (ParsingPackageUtils.TAG_PACKAGE_VERIFIER.equals(parser.getName())) {
final VerifierInfo verifier = parseVerifier(attrs); final VerifierInfo verifier = parseVerifier(parser);
if (verifier != null) { if (verifier != null) {
verifiers.add(verifier); verifiers.add(verifier);
} }
} else if (ParsingPackageUtils.TAG_APPLICATION.equals(parser.getName())) { } else if (ParsingPackageUtils.TAG_APPLICATION.equals(parser.getName())) {
for (int i = 0; i < attrs.getAttributeCount(); ++i) { debuggable = parser.getAttributeBooleanValue(ANDROID_RES_NAMESPACE, "debuggable",
final String attr = attrs.getAttributeName(i); false);
switch (attr) { multiArch = parser.getAttributeBooleanValue(ANDROID_RES_NAMESPACE, "multiArch",
case "debuggable": false);
debuggable = attrs.getAttributeBooleanValue(i, false); use32bitAbi = parser.getAttributeBooleanValue(ANDROID_RES_NAMESPACE, "use32bitAbi",
break; false);
case "multiArch": extractNativeLibs = parser.getAttributeBooleanValue(ANDROID_RES_NAMESPACE,
multiArch = attrs.getAttributeBooleanValue(i, false); "extractNativeLibs", true);
break; useEmbeddedDex = parser.getAttributeBooleanValue(ANDROID_RES_NAMESPACE,
case "use32bitAbi": "useEmbeddedDex", false);
use32bitAbi = attrs.getAttributeBooleanValue(i, false); rollbackDataPolicy = parser.getAttributeIntValue(ANDROID_RES_NAMESPACE,
break; "rollbackDataPolicy", 0);
case "extractNativeLibs":
extractNativeLibs = attrs.getAttributeBooleanValue(i, true);
break;
case "useEmbeddedDex":
useEmbeddedDex = attrs.getAttributeBooleanValue(i, false);
break;
case "rollbackDataPolicy":
rollbackDataPolicy = attrs.getAttributeIntValue(i, 0);
break;
}
}
final int innerDepth = parser.getDepth(); final int innerDepth = parser.getDepth();
int innerType; int innerType;
@@ -470,52 +431,79 @@ public class ApkLiteParseUtils {
} }
if (ParsingPackageUtils.TAG_PROFILEABLE.equals(parser.getName())) { if (ParsingPackageUtils.TAG_PROFILEABLE.equals(parser.getName())) {
for (int i = 0; i < attrs.getAttributeCount(); ++i) { profilableByShell = parser.getAttributeBooleanValue(ANDROID_RES_NAMESPACE,
final String attr = attrs.getAttributeName(i); "shell", profilableByShell);
if ("shell".equals(attr)) {
profilableByShell = attrs.getAttributeBooleanValue(i,
profilableByShell);
}
}
} }
} }
} else if (ParsingPackageUtils.TAG_OVERLAY.equals(parser.getName())) { } else if (ParsingPackageUtils.TAG_OVERLAY.equals(parser.getName())) {
for (int i = 0; i < attrs.getAttributeCount(); ++i) { requiredSystemPropertyName = parser.getAttributeValue(ANDROID_RES_NAMESPACE,
final String attr = attrs.getAttributeName(i); "requiredSystemPropertyName");
if ("requiredSystemPropertyName".equals(attr)) { requiredSystemPropertyValue = parser.getAttributeValue(ANDROID_RES_NAMESPACE,
requiredSystemPropertyName = attrs.getAttributeValue(i); "requiredSystemPropertyValue");
} else if ("requiredSystemPropertyValue".equals(attr)) { targetPackage = parser.getAttributeValue(ANDROID_RES_NAMESPACE, "targetPackage");
requiredSystemPropertyValue = attrs.getAttributeValue(i); overlayIsStatic = parser.getAttributeBooleanValue(ANDROID_RES_NAMESPACE, "isStatic",
} else if ("targetPackage".equals(attr)) { false);
targetPackage = attrs.getAttributeValue(i);; overlayPriority = parser.getAttributeIntValue(ANDROID_RES_NAMESPACE, "priority", 0);
} else if ("isStatic".equals(attr)) {
overlayIsStatic = attrs.getAttributeBooleanValue(i, false);
} else if ("priority".equals(attr)) {
overlayPriority = attrs.getAttributeIntValue(i, 0);
}
}
} else if (ParsingPackageUtils.TAG_USES_SPLIT.equals(parser.getName())) { } else if (ParsingPackageUtils.TAG_USES_SPLIT.equals(parser.getName())) {
if (usesSplitName != null) { if (usesSplitName != null) {
Slog.w(TAG, "Only one <uses-split> permitted. Ignoring others."); Slog.w(TAG, "Only one <uses-split> permitted. Ignoring others.");
continue; continue;
} }
usesSplitName = attrs.getAttributeValue(PackageParser.ANDROID_RESOURCES, "name"); usesSplitName = parser.getAttributeValue(ANDROID_RES_NAMESPACE, "name");
if (usesSplitName == null) { if (usesSplitName == null) {
return input.error(PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, return input.error(PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
"<uses-split> tag requires 'android:name' attribute"); "<uses-split> tag requires 'android:name' attribute");
} }
} else if (ParsingPackageUtils.TAG_USES_SDK.equals(parser.getName())) { } else if (ParsingPackageUtils.TAG_USES_SDK.equals(parser.getName())) {
for (int i = 0; i < attrs.getAttributeCount(); ++i) { // Mirrors ParsingPackageUtils#parseUsesSdk until lite and full parsing is combined
final String attr = attrs.getAttributeName(i); String minSdkVersionString = parser.getAttributeValue(ANDROID_RES_NAMESPACE,
if ("targetSdkVersion".equals(attr)) { "minSdkVersion");
targetSdkVersion = attrs.getAttributeIntValue(i, String targetSdkVersionString = parser.getAttributeValue(ANDROID_RES_NAMESPACE,
DEFAULT_TARGET_SDK_VERSION); "targetSdkVersion");
}
if ("minSdkVersion".equals(attr)) { int minVer = DEFAULT_MIN_SDK_VERSION;
minSdkVersion = attrs.getAttributeIntValue(i, 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<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, public static ParseResult<Pair<String, String>> parsePackageSplitNames(ParseInput input,
XmlPullParser parser, AttributeSet attrs) throws IOException, XmlPullParserException { XmlResourceParser parser) throws IOException, XmlPullParserException {
int type; int type;
while ((type = parser.next()) != XmlPullParser.START_TAG while ((type = parser.next()) != XmlPullParser.START_TAG
&& type != XmlPullParser.END_DOCUMENT) { && type != XmlPullParser.END_DOCUMENT) {
@@ -556,7 +544,7 @@ public class ApkLiteParseUtils {
"No <manifest> tag"); "No <manifest> tag");
} }
final String packageName = attrs.getAttributeValue(null, "package"); final String packageName = parser.getAttributeValue(null, "package");
if (!"android".equals(packageName)) { if (!"android".equals(packageName)) {
final ParseResult<?> nameResult = validateName(input, packageName, true, true); final ParseResult<?> nameResult = validateName(input, packageName, true, true);
if (nameResult.isError()) { 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 != null) {
if (splitName.length() == 0) { if (splitName.length() == 0) {
splitName = null; splitName = null;
@@ -583,22 +571,8 @@ public class ApkLiteParseUtils {
} }
public static VerifierInfo parseVerifier(AttributeSet attrs) { public static VerifierInfo parseVerifier(AttributeSet attrs) {
String packageName = null; String packageName = attrs.getAttributeValue(ANDROID_RES_NAMESPACE, "name");
String encodedPublicKey = null; String encodedPublicKey = attrs.getAttributeValue(ANDROID_RES_NAMESPACE, "publicKey");
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;
}
}
if (packageName == null || packageName.length() == 0) { if (packageName == null || packageName.length() == 0) {
Slog.i(TAG, "verifier package name was null; skipping"); Slog.i(TAG, "verifier package name was null; skipping");

View File

@@ -356,7 +356,7 @@ public class ParsingPackageImpl implements ParsingPackage, Parcelable {
private float minAspectRatio; private float minAspectRatio;
@Nullable @Nullable
private SparseIntArray minExtensionVersions; private SparseIntArray minExtensionVersions;
private int minSdkVersion; private int minSdkVersion = ParsingUtils.DEFAULT_MIN_SDK_VERSION;
private int networkSecurityConfigRes; private int networkSecurityConfigRes;
@Nullable @Nullable
private CharSequence nonLocalizedLabel; private CharSequence nonLocalizedLabel;
@@ -369,7 +369,7 @@ public class ParsingPackageImpl implements ParsingPackage, Parcelable {
private int requiresSmallestWidthDp; private int requiresSmallestWidthDp;
private int roundIconRes; private int roundIconRes;
private int targetSandboxVersion; private int targetSandboxVersion;
private int targetSdkVersion; private int targetSdkVersion = ParsingUtils.DEFAULT_TARGET_SDK_VERSION;
@Nullable @Nullable
@DataClass.ParcelWith(ForInternedString.class) @DataClass.ParcelWith(ForInternedString.class)
private String taskAffinity; private String taskAffinity;

View File

@@ -582,12 +582,12 @@ public class ParsingPackageUtils {
*/ */
private ParseResult<ParsingPackage> parseBaseApk(ParseInput input, String apkPath, private ParseResult<ParsingPackage> parseBaseApk(ParseInput input, String apkPath,
String codePath, Resources res, XmlResourceParser parser, int flags) String codePath, Resources res, XmlResourceParser parser, int flags)
throws XmlPullParserException, IOException, PackageParserException { throws XmlPullParserException, IOException {
final String splitName; final String splitName;
final String pkgName; final String pkgName;
ParseResult<Pair<String, String>> packageSplitResult = ParseResult<Pair<String, String>> packageSplitResult =
ApkLiteParseUtils.parsePackageSplitNames(input, parser, parser); ApkLiteParseUtils.parsePackageSplitNames(input, parser);
if (packageSplitResult.isError()) { if (packageSplitResult.isError()) {
return input.error(packageSplitResult); return input.error(packageSplitResult);
} }
@@ -1460,9 +1460,9 @@ public class ParsingPackageUtils {
if (SDK_VERSION > 0) { if (SDK_VERSION > 0) {
TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestUsesSdk); TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestUsesSdk);
try { try {
int minVers = 1; int minVers = ParsingUtils.DEFAULT_MIN_SDK_VERSION;
String minCode = null; String minCode = null;
int targetVers = 0; int targetVers = ParsingUtils.DEFAULT_TARGET_SDK_VERSION;
String targetCode = null; String targetCode = null;
TypedValue val = sa.peekValue(R.styleable.AndroidManifestUsesSdk_minSdkVersion); TypedValue val = sa.peekValue(R.styleable.AndroidManifestUsesSdk_minSdkVersion);

View File

@@ -35,6 +35,11 @@ public class ParsingUtils {
public static final String TAG = "PackageParsing"; 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 @Nullable
public static String buildClassName(String pkg, CharSequence clsSeq) { public static String buildClassName(String pkg, CharSequence clsSeq) {
if (clsSeq == null || clsSeq.length() <= 0) { if (clsSeq == null || clsSeq.length() <= 0) {