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_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);
}
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<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");

View File

@@ -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;

View File

@@ -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);

View File

@@ -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) {