Merge "Fix ApkLite attribute parsing" into sc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
4662093318
@@ -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");
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user