Add min extension versions to AndroidPackage.

The <extension-sdk> manifest tag was added in ag/1004614 to
allow apps to specify the minimum versions they need of
extension SDKs.

This adds the min extension versions to ParsingPackage.

This will be needed to allow us to perform checks that rollbacks do
not violate the min extension versions of installed apps (see
go/sdk-extensions-and-rollback).

Bug: 152737927
Test: atest PackageParserLegacyCoreTest#testUsesSdk
Change-Id: I2e080e46aaea6de489766dac0d323d7d2c7302ca
This commit is contained in:
Oli Lan
2020-04-14 16:50:41 +01:00
parent 42987638f5
commit 72ae4476d4
5 changed files with 59 additions and 5 deletions

View File

@@ -34,6 +34,7 @@ import android.content.pm.parsing.component.ParsedProvider;
import android.content.pm.parsing.component.ParsedService;
import android.os.Bundle;
import android.util.SparseArray;
import android.util.SparseIntArray;
import java.security.PublicKey;
import java.util.Map;
@@ -258,6 +259,8 @@ public interface ParsingPackage extends ParsingPackageRead {
ParsingPackage setManageSpaceActivityName(String manageSpaceActivityName);
ParsingPackage setMinExtensionVersions(@Nullable SparseIntArray minExtensionVersions);
ParsingPackage setMinSdkVersion(int minSdkVersion);
ParsingPackage setNetworkSecurityConfigRes(int networkSecurityConfigRes);

View File

@@ -51,6 +51,7 @@ import android.text.TextUtils;
import android.util.ArraySet;
import android.util.Pair;
import android.util.SparseArray;
import android.util.SparseIntArray;
import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
@@ -340,6 +341,8 @@ public class ParsingPackageImpl implements ParsingPackage, Parcelable {
private String manageSpaceActivityName;
private float maxAspectRatio;
private float minAspectRatio;
@Nullable
private SparseIntArray minExtensionVersions;
private int minSdkVersion;
private int networkSecurityConfigRes;
@Nullable
@@ -1100,6 +1103,7 @@ public class ParsingPackageImpl implements ParsingPackage, Parcelable {
dest.writeBoolean(this.preserveLegacyExternalStorage);
dest.writeArraySet(this.mimeGroups);
dest.writeInt(this.gwpAsanMode);
dest.writeSparseIntArray(this.minExtensionVersions);
}
public ParsingPackageImpl(Parcel in) {
@@ -1259,6 +1263,7 @@ public class ParsingPackageImpl implements ParsingPackage, Parcelable {
this.preserveLegacyExternalStorage = in.readBoolean();
this.mimeGroups = (ArraySet<String>) in.readArraySet(boot);
this.gwpAsanMode = in.readInt();
this.minExtensionVersions = in.readSparseIntArray();
}
public static final Parcelable.Creator<ParsingPackageImpl> CREATOR =
@@ -1767,6 +1772,12 @@ public class ParsingPackageImpl implements ParsingPackage, Parcelable {
return minAspectRatio;
}
@Nullable
@Override
public SparseIntArray getMinExtensionVersions() {
return minExtensionVersions;
}
@Override
public int getMinSdkVersion() {
return minSdkVersion;
@@ -2214,6 +2225,12 @@ public class ParsingPackageImpl implements ParsingPackage, Parcelable {
return this;
}
@Override
public ParsingPackageImpl setMinExtensionVersions(@Nullable SparseIntArray value) {
minExtensionVersions = value;
return this;
}
@Override
public ParsingPackageImpl setMinSdkVersion(int value) {
minSdkVersion = value;

View File

@@ -41,6 +41,7 @@ import android.os.Parcelable;
import android.util.ArraySet;
import android.util.Pair;
import android.util.SparseArray;
import android.util.SparseIntArray;
import com.android.internal.R;
@@ -608,6 +609,13 @@ public interface ParsingPackageRead extends Parcelable {
@Nullable
String getManageSpaceActivityName();
/**
* @see ApplicationInfo#minExtensionVersions
* @see R.styleable#AndroidManifestExtensionSdk
*/
@Nullable
SparseIntArray getMinExtensionVersions();
/**
* @see ApplicationInfo#minSdkVersion
* @see R.styleable#AndroidManifestUsesSdk_minSdkVersion

View File

@@ -95,6 +95,7 @@ import android.util.DisplayMetrics;
import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseIntArray;
import android.util.TypedValue;
import android.util.apk.ApkSignatureVerifier;
@@ -1255,6 +1256,7 @@ public class ParsingPackageUtils {
int type;
final int innerDepth = parser.getDepth();
SparseIntArray minExtensionVersions = null;
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
&& (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
@@ -1263,7 +1265,10 @@ public class ParsingPackageUtils {
final ParseResult result;
if (parser.getName().equals("extension-sdk")) {
result = parseExtensionSdk(input, pkg, res, parser);
if (minExtensionVersions == null) {
minExtensionVersions = new SparseIntArray();
}
result = parseExtensionSdk(input, res, parser, minExtensionVersions);
XmlUtils.skipCurrentTag(parser);
} else {
result = ParsingUtils.unknownTag("<uses-sdk>", pkg, parser, input);
@@ -1273,6 +1278,7 @@ public class ParsingPackageUtils {
return input.error(result);
}
}
pkg.setMinExtensionVersions(exactSizedCopyOfSparseArray(minExtensionVersions));
} finally {
sa.recycle();
}
@@ -1280,8 +1286,21 @@ public class ParsingPackageUtils {
return input.success(pkg);
}
private static ParseResult parseExtensionSdk(ParseInput input, ParsingPackage pkg,
Resources res, XmlResourceParser parser) {
@Nullable
private static SparseIntArray exactSizedCopyOfSparseArray(@Nullable SparseIntArray input) {
if (input == null) {
return null;
}
SparseIntArray output = new SparseIntArray(input.size());
for (int i = 0; i < input.size(); i++) {
output.put(input.keyAt(i), input.valueAt(i));
}
return output;
}
private static ParseResult<SparseIntArray> parseExtensionSdk(
ParseInput input, Resources res, XmlResourceParser parser,
SparseIntArray minExtensionVersions) {
int sdkVersion;
int minVersion;
TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestExtensionSdk);
@@ -1316,7 +1335,8 @@ public class ParsingPackageUtils {
PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
"Specified sdkVersion " + sdkVersion + " is not valid");
}
return input.success(pkg);
minExtensionVersions.put(sdkVersion, minVersion);
return input.success(minExtensionVersions);
}
/**

View File

@@ -35,6 +35,7 @@ import android.os.Build;
import android.os.Bundle;
import android.os.FileUtils;
import android.platform.test.annotations.Presubmit;
import android.util.SparseIntArray;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
@@ -542,7 +543,12 @@ public class PackageParserLegacyCoreTest {
@Test
public void testUsesSdk() throws Exception {
parsePackage("install_uses_sdk.apk_r0", R.raw.install_uses_sdk_r0, x -> x);
ParsedPackage pkg =
parsePackage("install_uses_sdk.apk_r0", R.raw.install_uses_sdk_r0, x -> x);
SparseIntArray minExtVers = pkg.getMinExtensionVersions();
assertEquals(1, minExtVers.size());
assertEquals(0, minExtVers.get(10000, -1));
try {
parsePackage("install_uses_sdk.apk_r5", R.raw.install_uses_sdk_r5, x -> x);
fail("Expected parsing exception due to incompatible extension SDK version");