diff --git a/services/tests/PackageManagerServiceTests/apks/install_target_sdk_22/Android.bp b/services/tests/PackageManagerServiceTests/apks/install_target_sdk_22/Android.bp
new file mode 100644
index 0000000000000..69b26cc30214d
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/apks/install_target_sdk_22/Android.bp
@@ -0,0 +1,15 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
+android_test_helper_app {
+ name: "FrameworksServicesTests_install_target_sdk_22",
+ defaults: ["FrameworksServicesTests_apks_defaults"],
+
+ srcs: ["**/*.java"],
+}
diff --git a/services/tests/PackageManagerServiceTests/apks/install_target_sdk_22/AndroidManifest.xml b/services/tests/PackageManagerServiceTests/apks/install_target_sdk_22/AndroidManifest.xml
new file mode 100644
index 0000000000000..45cf7693d7099
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/apks/install_target_sdk_22/AndroidManifest.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
diff --git a/services/tests/PackageManagerServiceTests/apks/install_target_sdk_22/res/values/strings.xml b/services/tests/PackageManagerServiceTests/apks/install_target_sdk_22/res/values/strings.xml
new file mode 100644
index 0000000000000..984152fb5fa73
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/apks/install_target_sdk_22/res/values/strings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+ placeholder
+
diff --git a/services/tests/PackageManagerServiceTests/apks/install_target_sdk_23/Android.bp b/services/tests/PackageManagerServiceTests/apks/install_target_sdk_23/Android.bp
new file mode 100644
index 0000000000000..e3154dba785ce
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/apks/install_target_sdk_23/Android.bp
@@ -0,0 +1,15 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
+android_test_helper_app {
+ name: "FrameworksServicesTests_install_target_sdk_23",
+ defaults: ["FrameworksServicesTests_apks_defaults"],
+
+ srcs: ["**/*.java"],
+}
diff --git a/services/tests/PackageManagerServiceTests/apks/install_target_sdk_23/AndroidManifest.xml b/services/tests/PackageManagerServiceTests/apks/install_target_sdk_23/AndroidManifest.xml
new file mode 100644
index 0000000000000..725188b8c77d6
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/apks/install_target_sdk_23/AndroidManifest.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
diff --git a/services/tests/PackageManagerServiceTests/apks/install_target_sdk_23/res/values/strings.xml b/services/tests/PackageManagerServiceTests/apks/install_target_sdk_23/res/values/strings.xml
new file mode 100644
index 0000000000000..984152fb5fa73
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/apks/install_target_sdk_23/res/values/strings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+ placeholder
+
diff --git a/services/tests/PackageManagerServiceTests/server/Android.bp b/services/tests/PackageManagerServiceTests/server/Android.bp
index ebd6b649c4a8c..f7efcd156db22 100644
--- a/services/tests/PackageManagerServiceTests/server/Android.bp
+++ b/services/tests/PackageManagerServiceTests/server/Android.bp
@@ -146,6 +146,8 @@ java_genrule {
":FrameworksServicesTests_keyset_sb_ub",
":FrameworksServicesTests_keyset_splat_api",
":FrameworksServicesTests_keyset_splata_api",
+ ":FrameworksServicesTests_install_target_sdk_22",
+ ":FrameworksServicesTests_install_target_sdk_23",
],
out: ["PackageManagerServiceServerTests_apks_as_resources.res.zip"],
tools: ["soong_zip"],
diff --git a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerTests.java b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerTests.java
index 92bdd64f28036..fd31b2211b7ad 100644
--- a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerTests.java
+++ b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerTests.java
@@ -57,6 +57,7 @@ import android.os.RemoteException;
import android.os.StatFs;
import android.os.SystemClock;
import android.platform.test.annotations.Presubmit;
+import android.provider.DeviceConfig;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
import android.system.ErrnoException;
@@ -69,11 +70,10 @@ import androidx.test.filters.LargeTest;
import androidx.test.filters.SmallTest;
import androidx.test.filters.Suppress;
-import com.android.server.pm.test.service.server.R;
import com.android.internal.content.InstallLocationUtils;
import com.android.server.pm.parsing.pkg.ParsedPackage;
-import com.android.server.pm.pkg.parsing.ParsingPackage;
import com.android.server.pm.pkg.parsing.ParsingPackageUtils;
+import com.android.server.pm.test.service.server.R;
import dalvik.system.VMRuntime;
@@ -113,6 +113,9 @@ public class PackageManagerTests extends AndroidTestCase {
private static final int APP_INSTALL_SDCARD = InstallLocationUtils.APP_INSTALL_EXTERNAL;
+ private static final int DEFAULT_INSTALL_FLAGS =
+ PackageManager.INSTALL_BYPASS_LOW_TARGET_SDK_BLOCK;
+
void failStr(String errMsg) {
Log.w(TAG, "errMsg=" + errMsg);
fail(errMsg);
@@ -1874,12 +1877,13 @@ public class PackageManagerTests extends AndroidTestCase {
private InstallParams replaceCerts(int apk1, int apk2, boolean cleanUp, boolean fail,
int retCode) throws Exception {
- int rFlags = PackageManager.INSTALL_REPLACE_EXISTING;
+ int rFlags = DEFAULT_INSTALL_FLAGS | PackageManager.INSTALL_REPLACE_EXISTING;
String apk1Name = "install1.apk";
String apk2Name = "install2.apk";
var pkg1 = getParsedPackage(apk1Name, apk1);
try {
- InstallParams ip = installFromRawResource(apk1Name, apk1, 0, false,
+ InstallParams ip = installFromRawResource(apk1Name, apk1,
+ DEFAULT_INSTALL_FLAGS, false,
false, -1, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
installFromRawResource(apk2Name, apk2, rFlags, false,
fail, retCode, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
@@ -1963,7 +1967,7 @@ public class PackageManagerTests extends AndroidTestCase {
InstallParams ip = replaceCerts(APP1_CERT1, APP1_CERT1_CERT2, false, true,
PackageInstaller.STATUS_FAILURE_CONFLICT);
try {
- int rFlags = PackageManager.INSTALL_REPLACE_EXISTING;
+ int rFlags = DEFAULT_INSTALL_FLAGS | PackageManager.INSTALL_REPLACE_EXISTING;
installFromRawResource("install.apk", APP1_CERT1, rFlags, false,
false, -1,
PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
@@ -2466,7 +2470,8 @@ public class PackageManagerTests extends AndroidTestCase {
String apk1Name = "install1.apk";
String apk2Name = "install2.apk";
- final InstallParams ip = installFromRawResource(apk1Name, apk1, 0, false,
+ final InstallParams ip = installFromRawResource(apk1Name, apk1,
+ DEFAULT_INSTALL_FLAGS, false,
false, -1, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
try {
PackageManager pm = mContext.getPackageManager();
@@ -2552,13 +2557,13 @@ public class PackageManagerTests extends AndroidTestCase {
// Clean up before testing first.
cleanUpInstall(pkg1.getPackageName());
cleanUpInstall(pkg2.getPackageName());
- installFromRawResource(apk1Name, apk1, 0, false, false, -1,
+ installFromRawResource(apk1Name, apk1, DEFAULT_INSTALL_FLAGS, false, false, -1,
PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
if (fail) {
- installFromRawResource(apk2Name, apk2, 0, false, true, retCode,
+ installFromRawResource(apk2Name, apk2, DEFAULT_INSTALL_FLAGS, false, true, retCode,
PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
} else {
- installFromRawResource(apk2Name, apk2, 0, false, false, -1,
+ installFromRawResource(apk2Name, apk2, DEFAULT_INSTALL_FLAGS, false, false, -1,
PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
// TODO: All checkSignatures tests should return the same result regardless of
// querying by package name or uid; however if there are any edge cases where
@@ -2638,7 +2643,7 @@ public class PackageManagerTests extends AndroidTestCase {
InstallParams ip1 = null;
try {
- ip1 = installFromRawResource(apk1Name, apk1, 0, false,
+ ip1 = installFromRawResource(apk1Name, apk1, DEFAULT_INSTALL_FLAGS, false,
false, -1, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
PackageManager pm = mContext.getPackageManager();
// Delete app2
@@ -2683,9 +2688,10 @@ public class PackageManagerTests extends AndroidTestCase {
int apk2 = SHARED2_CERT1_CERT2;
int rapk1 = SHARED1_CERT1;
boolean fail = true;
+ int flags = DEFAULT_INSTALL_FLAGS | PackageManager.INSTALL_REPLACE_EXISTING;
int retCode = PackageInstaller.STATUS_FAILURE_CONFLICT;
checkSharedSignatures(apk1, apk2, false, false, -1, PackageManager.SIGNATURE_MATCH);
- installFromRawResource("install.apk", rapk1, PackageManager.INSTALL_REPLACE_EXISTING, true,
+ installFromRawResource("install.apk", rapk1, flags, true,
fail, retCode, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
}
@@ -2695,9 +2701,10 @@ public class PackageManagerTests extends AndroidTestCase {
int apk2 = SHARED2_CERT1_CERT2;
int rapk2 = SHARED2_CERT1;
boolean fail = true;
+ int flags = DEFAULT_INSTALL_FLAGS | PackageManager.INSTALL_REPLACE_EXISTING;
int retCode = PackageInstaller.STATUS_FAILURE_CONFLICT;
checkSharedSignatures(apk1, apk2, false, false, -1, PackageManager.SIGNATURE_MATCH);
- installFromRawResource("install.apk", rapk2, PackageManager.INSTALL_REPLACE_EXISTING, true,
+ installFromRawResource("install.apk", rapk2, flags, true,
fail, retCode, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
}
@@ -2707,9 +2714,10 @@ public class PackageManagerTests extends AndroidTestCase {
int apk2 = SHARED2_CERT1;
int rapk1 = SHARED1_CERT2;
boolean fail = true;
+ int flags = DEFAULT_INSTALL_FLAGS | PackageManager.INSTALL_REPLACE_EXISTING;
int retCode = PackageInstaller.STATUS_FAILURE_CONFLICT;
checkSharedSignatures(apk1, apk2, false, false, -1, PackageManager.SIGNATURE_MATCH);
- installFromRawResource("install.apk", rapk1, PackageManager.INSTALL_REPLACE_EXISTING, true,
+ installFromRawResource("install.apk", rapk1, flags, true,
fail, retCode, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
}
@@ -2719,9 +2727,10 @@ public class PackageManagerTests extends AndroidTestCase {
int apk2 = SHARED2_CERT1;
int rapk2 = SHARED2_CERT2;
boolean fail = true;
+ int flags = DEFAULT_INSTALL_FLAGS | PackageManager.INSTALL_REPLACE_EXISTING;
int retCode = PackageInstaller.STATUS_FAILURE_CONFLICT;
checkSharedSignatures(apk1, apk2, false, false, -1, PackageManager.SIGNATURE_MATCH);
- installFromRawResource("install.apk", rapk2, PackageManager.INSTALL_REPLACE_EXISTING, true,
+ installFromRawResource("install.apk", rapk2, flags, true,
fail, retCode, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
}
@@ -2731,9 +2740,10 @@ public class PackageManagerTests extends AndroidTestCase {
int apk2 = SHARED2_CERT1;
int rapk1 = SHARED1_CERT1_CERT2;
boolean fail = true;
+ int flags = DEFAULT_INSTALL_FLAGS | PackageManager.INSTALL_REPLACE_EXISTING;
int retCode = PackageInstaller.STATUS_FAILURE_CONFLICT;
checkSharedSignatures(apk1, apk2, false, false, -1, PackageManager.SIGNATURE_MATCH);
- installFromRawResource("install.apk", rapk1, PackageManager.INSTALL_REPLACE_EXISTING, true,
+ installFromRawResource("install.apk", rapk1, flags, true,
fail, retCode, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
}
@@ -2743,9 +2753,10 @@ public class PackageManagerTests extends AndroidTestCase {
int apk2 = SHARED2_CERT1;
int rapk2 = SHARED2_CERT1_CERT2;
boolean fail = true;
+ int flags = DEFAULT_INSTALL_FLAGS | PackageManager.INSTALL_REPLACE_EXISTING;
int retCode = PackageInstaller.STATUS_FAILURE_CONFLICT;
checkSharedSignatures(apk1, apk2, false, false, -1, PackageManager.SIGNATURE_MATCH);
- installFromRawResource("install.apk", rapk2, PackageManager.INSTALL_REPLACE_EXISTING, true,
+ installFromRawResource("install.apk", rapk2, flags, true,
fail, retCode, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
}
@@ -2995,6 +3006,58 @@ public class PackageManagerTests extends AndroidTestCase {
getPm().registerDexModule(nonExistentApk, null);
}
+ @LargeTest
+ public void testMinInstallableTargetSdkPass() throws Exception {
+ // Test installing a package that meets the minimum installable sdk requirement
+ setMinInstallableTargetSdkFeatureFlags();
+ int flags = PackageManager.INSTALL_BYPASS_LOW_TARGET_SDK_BLOCK;
+ installFromRawResource("install.apk", R.raw.install_target_sdk_23, flags,
+ true, false /* fail */, -1, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
+ }
+
+ @LargeTest
+ public void testMinInstallableTargetSdkFail() throws Exception {
+ // Test installing a package that doesn't meet the minimum installable sdk requirement
+ setMinInstallableTargetSdkFeatureFlags();
+ int flags = 0;
+ // Expect install to fail
+ installFromRawResource("install.apk", R.raw.install_target_sdk_22, flags,
+ true, true /* fail */, PackageInstaller.STATUS_FAILURE_INCOMPATIBLE,
+ PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
+ }
+
+ @LargeTest
+ public void testMinInstallableTargetSdkBypass() throws Exception {
+ // Test installing a package that doesn't meet the minimum installable sdk requirement
+ setMinInstallableTargetSdkFeatureFlags();
+ int flags = PackageManager.INSTALL_BYPASS_LOW_TARGET_SDK_BLOCK;
+ installFromRawResource("install.apk", R.raw.install_target_sdk_22, flags,
+ true, false /* fail */, -1, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
+ }
+
+ private void setMinInstallableTargetSdkFeatureFlags() {
+ DeviceConfig.setProperty(
+ DeviceConfig.NAMESPACE_PACKAGE_MANAGER_SERVICE,
+ "MinInstallableTargetSdk__install_block_enabled",
+ "true",
+ false);
+ DeviceConfig.setProperty(
+ DeviceConfig.NAMESPACE_PACKAGE_MANAGER_SERVICE,
+ "MinInstallableTargetSdk__min_installable_target_sdk",
+ "23",
+ false);
+ DeviceConfig.setProperty(
+ DeviceConfig.NAMESPACE_PACKAGE_MANAGER_SERVICE,
+ "MinInstallableTargetSdk__install_block_strict_mode_enabled",
+ "true",
+ false);
+ DeviceConfig.setProperty(
+ DeviceConfig.NAMESPACE_PACKAGE_MANAGER_SERVICE,
+ "MinInstallableTargetSdk__strict_mode_target_sdk",
+ "23",
+ false);
+ }
+
// Copied from com.android.server.pm.InstructionSets because we don't have access to it here.
private static String[] getAppDexInstructionSets(ApplicationInfo info) {
if (info.primaryCpuAbi != null) {