Merge changes from topic "apex-installers-restriction" into sc-dev

* changes:
  Reject non-staged APEX install if there is staged install of same APEX
  Restrict what APEXes different installers can update
This commit is contained in:
Nikita Ioffe
2021-07-22 16:53:05 +00:00
committed by Android (Google) Code Review
8 changed files with 383 additions and 14 deletions

View File

@@ -241,7 +241,11 @@ public class SystemConfig {
private final ArraySet<String> mRollbackWhitelistedPackages = new ArraySet<>(); private final ArraySet<String> mRollbackWhitelistedPackages = new ArraySet<>();
private final ArraySet<String> mWhitelistedStagedInstallers = new ArraySet<>(); private final ArraySet<String> mWhitelistedStagedInstallers = new ArraySet<>();
private final ArraySet<String> mAllowedVendorApexes = new ArraySet<>(); // A map from package name of vendor APEXes that can be updated to an installer package name
// allowed to install updates for it.
private final ArrayMap<String, String> mAllowedVendorApexes = new ArrayMap<>();
private String mModulesInstallerPackageName;
/** /**
* Map of system pre-defined, uniquely named actors; keys are namespace, * Map of system pre-defined, uniquely named actors; keys are namespace,
@@ -412,10 +416,14 @@ public class SystemConfig {
return mWhitelistedStagedInstallers; return mWhitelistedStagedInstallers;
} }
public Set<String> getAllowedVendorApexes() { public Map<String, String> getAllowedVendorApexes() {
return mAllowedVendorApexes; return mAllowedVendorApexes;
} }
public String getModulesInstallerPackageName() {
return mModulesInstallerPackageName;
}
public ArraySet<String> getAppDataIsolationWhitelistedApps() { public ArraySet<String> getAppDataIsolationWhitelistedApps() {
return mAppDataIsolationWhitelistedApps; return mAppDataIsolationWhitelistedApps;
} }
@@ -1210,12 +1218,21 @@ public class SystemConfig {
case "whitelisted-staged-installer": { case "whitelisted-staged-installer": {
if (allowAppConfigs) { if (allowAppConfigs) {
String pkgname = parser.getAttributeValue(null, "package"); String pkgname = parser.getAttributeValue(null, "package");
boolean isModulesInstaller = XmlUtils.readBooleanAttribute(
parser, "isModulesInstaller", false);
if (pkgname == null) { if (pkgname == null) {
Slog.w(TAG, "<" + name + "> without package in " + permFile Slog.w(TAG, "<" + name + "> without package in " + permFile
+ " at " + parser.getPositionDescription()); + " at " + parser.getPositionDescription());
} else { } else {
mWhitelistedStagedInstallers.add(pkgname); mWhitelistedStagedInstallers.add(pkgname);
} }
if (isModulesInstaller) {
if (mModulesInstallerPackageName != null) {
throw new IllegalStateException(
"Multiple modules installers");
}
mModulesInstallerPackageName = pkgname;
}
} else { } else {
logNotAllowedInPartition(name, permFile, parser); logNotAllowedInPartition(name, permFile, parser);
} }
@@ -1224,11 +1241,18 @@ public class SystemConfig {
case "allowed-vendor-apex": { case "allowed-vendor-apex": {
if (allowVendorApex) { if (allowVendorApex) {
String pkgName = parser.getAttributeValue(null, "package"); String pkgName = parser.getAttributeValue(null, "package");
String installerPkgName = parser.getAttributeValue(
null, "installerPackage");
if (pkgName == null) { if (pkgName == null) {
Slog.w(TAG, "<" + name + "> without package in " + permFile Slog.w(TAG, "<" + name + "> without package in " + permFile
+ " at " + parser.getPositionDescription()); + " at " + parser.getPositionDescription());
} else { }
mAllowedVendorApexes.add(pkgName); if (installerPkgName == null) {
Slog.w(TAG, "<" + name + "> without installerPackage in " + permFile
+ " at " + parser.getPositionDescription());
}
if (pkgName != null && installerPkgName != null) {
mAllowedVendorApexes.put(pkgName, installerPkgName);
} }
} else { } else {
logNotAllowedInPartition(name, permFile, parser); logNotAllowedInPartition(name, permFile, parser);

View File

@@ -2252,12 +2252,29 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
(params.installFlags & PackageManager.INSTALL_DISABLE_ALLOWED_APEX_UPDATE_CHECK) (params.installFlags & PackageManager.INSTALL_DISABLE_ALLOWED_APEX_UPDATE_CHECK)
== 0; == 0;
synchronized (mLock) { synchronized (mLock) {
if (checkApexUpdateAllowed && !isApexUpdateAllowed(mPackageName)) { if (checkApexUpdateAllowed && !isApexUpdateAllowed(mPackageName,
mInstallSource.installerPackageName)) {
onSessionValidationFailure(PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE, onSessionValidationFailure(PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE,
"Update of APEX package " + mPackageName + " is not allowed"); "Update of APEX package " + mPackageName + " is not allowed for "
+ mInstallSource.installerPackageName);
return; return;
} }
} }
if (!params.isStaged) {
// For non-staged APEX installs also check if there is a staged session that
// contains the same APEX. If that's the case, we should fail this session.
synchronized (mLock) {
int sessionId = mStagingManager.getSessionIdByPackageName(mPackageName);
if (sessionId != -1) {
onSessionValidationFailure(
PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE,
"Staged session " + sessionId + " already contains "
+ mPackageName);
return;
}
}
}
} }
if (params.isStaged) { if (params.isStaged) {
@@ -2798,9 +2815,23 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
return sessionContains((s) -> !s.isApexSession()); return sessionContains((s) -> !s.isApexSession());
} }
private boolean isApexUpdateAllowed(String apexPackageName) { private boolean isApexUpdateAllowed(String apexPackageName, String installerPackageName) {
return mPm.getModuleInfo(apexPackageName, 0) != null if (mPm.getModuleInfo(apexPackageName, 0) != null) {
|| SystemConfig.getInstance().getAllowedVendorApexes().contains(apexPackageName); final String modulesInstaller =
SystemConfig.getInstance().getModulesInstallerPackageName();
if (modulesInstaller == null) {
Slog.w(TAG, "No modules installer defined");
return false;
}
return modulesInstaller.equals(installerPackageName);
}
final String vendorApexInstaller =
SystemConfig.getInstance().getAllowedVendorApexes().get(apexPackageName);
if (vendorApexInstaller == null) {
Slog.w(TAG, apexPackageName + " is not allowed to be updated");
return false;
}
return vendorApexInstaller.equals(installerPackageName);
} }
/** /**

View File

@@ -777,6 +777,26 @@ public class StagingManager {
} }
} }
/**
* Returns id of a committed and non-finalized stated session that contains same
* {@code packageName}, or {@code -1} if no sessions have this {@code packageName} staged.
*/
int getSessionIdByPackageName(@NonNull String packageName) {
synchronized (mStagedSessions) {
for (int i = 0; i < mStagedSessions.size(); i++) {
StagedSession stagedSession = mStagedSessions.valueAt(i);
if (!stagedSession.isCommitted() || stagedSession.isDestroyed()
|| stagedSession.isInTerminalState()) {
continue;
}
if (stagedSession.getPackageName().equals(packageName)) {
return stagedSession.sessionId();
}
}
}
return -1;
}
@VisibleForTesting @VisibleForTesting
void createSession(@NonNull StagedSession sessionInfo) { void createSession(@NonNull StagedSession sessionInfo) {
synchronized (mStagedSessions) { synchronized (mStagedSessions) {

View File

@@ -459,6 +459,66 @@ public class StagingManagerTest {
assertThat(apkSession.getErrorMessage()).isEqualTo("Another apex session failed"); assertThat(apkSession.getErrorMessage()).isEqualTo("Another apex session failed");
} }
@Test
public void getSessionIdByPackageName() throws Exception {
FakeStagedSession session = new FakeStagedSession(239);
session.setCommitted(true);
session.setSessionReady();
session.setPackageName("com.foo");
mStagingManager.createSession(session);
assertThat(mStagingManager.getSessionIdByPackageName("com.foo")).isEqualTo(239);
}
@Test
public void getSessionIdByPackageName_appliedSession_ignores() throws Exception {
FakeStagedSession session = new FakeStagedSession(37);
session.setCommitted(true);
session.setSessionApplied();
session.setPackageName("com.foo");
mStagingManager.createSession(session);
assertThat(mStagingManager.getSessionIdByPackageName("com.foo")).isEqualTo(-1);
}
@Test
public void getSessionIdByPackageName_failedSession_ignores() throws Exception {
FakeStagedSession session = new FakeStagedSession(73);
session.setCommitted(true);
session.setSessionFailed(1, "whatevs");
session.setPackageName("com.foo");
mStagingManager.createSession(session);
assertThat(mStagingManager.getSessionIdByPackageName("com.foo")).isEqualTo(-1);
}
@Test
public void getSessionIdByPackageName_destroyedSession_ignores() throws Exception {
FakeStagedSession session = new FakeStagedSession(23);
session.setCommitted(true);
session.setDestroyed(true);
session.setPackageName("com.foo");
mStagingManager.createSession(session);
assertThat(mStagingManager.getSessionIdByPackageName("com.foo")).isEqualTo(-1);
}
@Test
public void getSessionIdByPackageName_noSessions() throws Exception {
assertThat(mStagingManager.getSessionIdByPackageName("com.foo")).isEqualTo(-1);
}
@Test
public void getSessionIdByPackageName_noSessionHasThisPackage() throws Exception {
FakeStagedSession session = new FakeStagedSession(37);
session.setCommitted(true);
session.setSessionApplied();
session.setPackageName("com.foo");
mStagingManager.createSession(session);
assertThat(mStagingManager.getSessionIdByPackageName("com.bar")).isEqualTo(-1);
}
private StagingManager.StagedSession createSession(int sessionId, String packageName, private StagingManager.StagedSession createSession(int sessionId, String packageName,
long committedMillis) { long committedMillis) {
PackageInstaller.SessionParams params = new PackageInstaller.SessionParams( PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(

View File

@@ -19,6 +19,7 @@ package com.android.server.systemconfig;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.testng.Assert.expectThrows;
import android.platform.test.annotations.Presubmit; import android.platform.test.annotations.Presubmit;
import android.util.ArrayMap; import android.util.ArrayMap;
@@ -200,6 +201,46 @@ public class SystemConfigTest {
assertThat(mSysConfig.getWhitelistedStagedInstallers()) assertThat(mSysConfig.getWhitelistedStagedInstallers())
.containsExactly("com.android.package1"); .containsExactly("com.android.package1");
assertThat(mSysConfig.getModulesInstallerPackageName()).isNull();
}
@Test
public void readPermissions_parsesStagedInstallerWhitelist_modulesInstaller()
throws IOException {
final String contents =
"<config>\n"
+ " <whitelisted-staged-installer package=\"com.android.package1\" "
+ " isModulesInstaller=\"true\" />\n"
+ "</config>";
final File folder = createTempSubfolder("folder");
createTempFile(folder, "staged-installer-whitelist.xml", contents);
mSysConfig.readPermissions(folder, /* Grant all permission flags */ ~0);
assertThat(mSysConfig.getWhitelistedStagedInstallers())
.containsExactly("com.android.package1");
assertThat(mSysConfig.getModulesInstallerPackageName())
.isEqualTo("com.android.package1");
}
@Test
public void readPermissions_parsesStagedInstallerWhitelist_multipleModulesInstallers()
throws IOException {
final String contents =
"<config>\n"
+ " <whitelisted-staged-installer package=\"com.android.package1\" "
+ " isModulesInstaller=\"true\" />\n"
+ " <whitelisted-staged-installer package=\"com.android.package2\" "
+ " isModulesInstaller=\"true\" />\n"
+ "</config>";
final File folder = createTempSubfolder("folder");
createTempFile(folder, "staged-installer-whitelist.xml", contents);
IllegalStateException e = expectThrows(
IllegalStateException.class,
() -> mSysConfig.readPermissions(folder, /* Grant all permission flags */ ~0));
assertThat(e).hasMessageThat().contains("Multiple modules installers");
} }
/** /**
@@ -230,14 +271,16 @@ public class SystemConfigTest {
throws IOException { throws IOException {
final String contents = final String contents =
"<config>\n" "<config>\n"
+ " <allowed-vendor-apex package=\"com.android.apex1\" />\n" + " <allowed-vendor-apex package=\"com.android.apex1\" "
+ "installerPackage=\"com.installer\" />\n"
+ "</config>"; + "</config>";
final File folder = createTempSubfolder("folder"); final File folder = createTempSubfolder("folder");
createTempFile(folder, "vendor-apex-allowlist.xml", contents); createTempFile(folder, "vendor-apex-allowlist.xml", contents);
mSysConfig.readPermissions(folder, /* Grant all permission flags */ ~0); mSysConfig.readPermissions(folder, /* Grant all permission flags */ ~0);
assertThat(mSysConfig.getAllowedVendorApexes()).containsExactly("com.android.apex1"); assertThat(mSysConfig.getAllowedVendorApexes())
.containsExactly("com.android.apex1", "com.installer");
} }
/** /**

View File

@@ -32,6 +32,7 @@ android_test_helper_app {
test_suites: ["general-tests"], test_suites: ["general-tests"],
java_resources: [ java_resources: [
":com.android.apex.apkrollback.test_v2", ":com.android.apex.apkrollback.test_v2",
":StagedInstallTestApexV2",
":StagedInstallTestApexV2_WrongSha", ":StagedInstallTestApexV2_WrongSha",
":test.rebootless_apex_v1", ":test.rebootless_apex_v1",
":test.rebootless_apex_v2", ":test.rebootless_apex_v2",

View File

@@ -55,8 +55,11 @@ public class StagedInstallInternalTest {
private static final TestApp TEST_APEX_WITH_APK_V2 = new TestApp("TestApexWithApkV2", private static final TestApp TEST_APEX_WITH_APK_V2 = new TestApp("TestApexWithApkV2",
APK_IN_APEX_TESTAPEX_NAME, 2, /*isApex*/true, APK_IN_APEX_TESTAPEX_NAME + "_v2.apex"); APK_IN_APEX_TESTAPEX_NAME, 2, /*isApex*/true, APK_IN_APEX_TESTAPEX_NAME + "_v2.apex");
private static final TestApp APEX_WRONG_SHA_V2 = new TestApp( private static final TestApp APEX_WRONG_SHA_V2 = new TestApp(
"ApexWrongSha2", SHIM_APEX_PACKAGE_NAME, 2, /*isApex*/true, "ApexWrongSha2", SHIM_APEX_PACKAGE_NAME, 2, /* isApex= */ true,
"com.android.apex.cts.shim.v2_wrong_sha.apex"); "com.android.apex.cts.shim.v2_wrong_sha.apex");
private static final TestApp APEX_V2 = new TestApp(
"ApexV2", SHIM_APEX_PACKAGE_NAME, 2, /* isApex= */ true,
"com.android.apex.cts.shim.v2.apex");
private File mTestStateFile = new File( private File mTestStateFile = new File(
InstrumentationRegistry.getInstrumentation().getContext().getFilesDir(), InstrumentationRegistry.getInstrumentation().getContext().getFilesDir(),
@@ -236,6 +239,96 @@ public class StagedInstallInternalTest {
assertThat(InstallUtils.getInstalledVersion(SHIM_APEX_PACKAGE_NAME)).isEqualTo(1); assertThat(InstallUtils.getInstalledVersion(SHIM_APEX_PACKAGE_NAME)).isEqualTo(1);
} }
@Test
public void testApexInstallerNotInAllowListCanNotInstall_staged() throws Exception {
assertThat(InstallUtils.getInstalledVersion(SHIM_APEX_PACKAGE_NAME)).isEqualTo(1);
// We don't really care which APEX we are trying to install here, since the session creation
// should fail immediately.
InstallUtils.commitExpectingFailure(
SecurityException.class,
"Installer not allowed to commit staged install",
Install.single(APEX_WRONG_SHA_V2).setBypassStangedInstallerCheck(false)
.setStaged());
}
@Test
public void testApexInstallerNotInAllowListCanNotInstall_nonStaged() throws Exception {
assertThat(InstallUtils.getInstalledVersion(SHIM_APEX_PACKAGE_NAME)).isEqualTo(1);
// We don't really care which APEX we are trying to install here, since the session creation
// should fail immediately.
InstallUtils.commitExpectingFailure(
SecurityException.class,
"Installer not allowed to commit non-staged APEX install",
Install.single(APEX_WRONG_SHA_V2).setBypassStangedInstallerCheck(false));
}
@Test
public void testApexNotInAllowListCanNotInstall_staged() throws Exception {
assertThat(InstallUtils.getInstalledVersion("test.apex.rebootless")).isEqualTo(1);
TestApp apex = new TestApp("apex", "test.apex.rebootless", 2,
/* isApex= */ true, "test.rebootless_apex_v2.apex");
InstallUtils.commitExpectingFailure(
AssertionError.class,
"Update of APEX package test.apex.rebootless is not allowed "
+ "for com.android.tests.stagedinstallinternal",
Install.single(apex).setBypassAllowedApexUpdateCheck(false).setStaged());
}
@Test
public void testApexNotInAllowListCanNotInstall_nonStaged() throws Exception {
assertThat(InstallUtils.getInstalledVersion("test.apex.rebootless")).isEqualTo(1);
TestApp apex = new TestApp("apex", "test.apex.rebootless", 2,
/* isApex= */ true, "test.rebootless_apex_v2.apex");
InstallUtils.commitExpectingFailure(
AssertionError.class,
"Update of APEX package test.apex.rebootless is not allowed "
+ "for com.android.tests.stagedinstallinternal",
Install.single(apex).setBypassAllowedApexUpdateCheck(false));
}
@Test
public void testVendorApexWrongInstaller_staged() throws Exception {
assertThat(InstallUtils.getInstalledVersion("test.apex.rebootless")).isEqualTo(1);
TestApp apex = new TestApp("apex", "test.apex.rebootless", 2,
/* isApex= */ true, "test.rebootless_apex_v2.apex");
InstallUtils.commitExpectingFailure(
AssertionError.class,
"Update of APEX package test.apex.rebootless is not allowed "
+ "for com.android.tests.stagedinstallinternal",
Install.single(apex).setBypassAllowedApexUpdateCheck(false).setStaged());
}
@Test
public void testVendorApexWrongInstaller_nonStaged() throws Exception {
assertThat(InstallUtils.getInstalledVersion("test.apex.rebootless")).isEqualTo(1);
TestApp apex = new TestApp("apex", "test.apex.rebootless", 2,
/* isApex= */ true, "test.rebootless_apex_v2.apex");
InstallUtils.commitExpectingFailure(
AssertionError.class,
"Update of APEX package test.apex.rebootless is not allowed "
+ "for com.android.tests.stagedinstallinternal",
Install.single(apex).setBypassAllowedApexUpdateCheck(false));
}
@Test
public void testVendorApexCorrectInstaller_staged() throws Exception {
assertThat(InstallUtils.getInstalledVersion("test.apex.rebootless")).isEqualTo(1);
TestApp apex = new TestApp("apex", "test.apex.rebootless", 2,
/* isApex= */ true, "test.rebootless_apex_v2.apex");
int sessionId =
Install.single(apex).setBypassAllowedApexUpdateCheck(false).setStaged().commit();
InstallUtils.getPackageInstaller().abandonSession(sessionId);
}
@Test
public void testVendorApexCorrectInstaller_nonStaged() throws Exception {
assertThat(InstallUtils.getInstalledVersion("test.apex.rebootless")).isEqualTo(1);
TestApp apex = new TestApp("apex", "test.apex.rebootless", 2,
/* isApex= */ true, "test.rebootless_apex_v2.apex");
Install.single(apex).setBypassAllowedApexUpdateCheck(false).commit();
assertThat(InstallUtils.getInstalledVersion("test.apex.rebootless")).isEqualTo(2);
}
@Test @Test
public void testRebootlessUpdates() throws Exception { public void testRebootlessUpdates() throws Exception {
InstallUtils.dropShellPermissionIdentity(); InstallUtils.dropShellPermissionIdentity();
@@ -298,6 +391,19 @@ public class StagedInstallInternalTest {
} }
} }
@Test
public void testRebootlessUpdate_hasStagedSessionWithSameApex_fails() throws Exception {
assertThat(InstallUtils.getInstalledVersion(SHIM_APEX_PACKAGE_NAME)).isEqualTo(1);
int sessionId = Install.single(APEX_V2).setStaged().commit();
assertSessionReady(sessionId);
InstallUtils.commitExpectingFailure(
AssertionError.class,
"Staged session " + sessionId + " already contains " + SHIM_APEX_PACKAGE_NAME,
Install.single(APEX_V2));
}
private static void assertSessionApplied(int sessionId) { private static void assertSessionApplied(int sessionId) {
assertSessionState(sessionId, (session) -> { assertSessionState(sessionId, (session) -> {
assertThat(session.isStagedSessionApplied()).isTrue(); assertThat(session.isStagedSessionApplied()).isTrue();

View File

@@ -43,7 +43,9 @@ import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import java.io.BufferedWriter;
import java.io.File; import java.io.File;
import java.io.FileWriter;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@@ -60,6 +62,9 @@ public class StagedInstallInternalTest extends BaseHostJUnit4Test {
private static final String APK_A = "TestAppAv1.apk"; private static final String APK_A = "TestAppAv1.apk";
private static final String APK_IN_APEX_TESTAPEX_NAME = "com.android.apex.apkrollback.test"; private static final String APK_IN_APEX_TESTAPEX_NAME = "com.android.apex.apkrollback.test";
private static final String TEST_VENDOR_APEX_ALLOW_LIST =
"/vendor/etc/sysconfig/test-vendor-apex-allow-list.xml";
private final InstallUtilsHost mHostUtils = new InstallUtilsHost(this); private final InstallUtilsHost mHostUtils = new InstallUtilsHost(this);
/** /**
@@ -87,7 +92,8 @@ public class StagedInstallInternalTest extends BaseHostJUnit4Test {
"/data/apex/active/" + APK_IN_APEX_TESTAPEX_NAME + "*.apex", "/data/apex/active/" + APK_IN_APEX_TESTAPEX_NAME + "*.apex",
"/data/apex/active/" + SHIM_APEX_PACKAGE_NAME + "*.apex", "/data/apex/active/" + SHIM_APEX_PACKAGE_NAME + "*.apex",
"/system/apex/test.rebootless_apex_v1.apex", "/system/apex/test.rebootless_apex_v1.apex",
"/data/apex/active/test.apex.rebootless*.apex"); "/data/apex/active/test.apex.rebootless*.apex",
TEST_VENDOR_APEX_ALLOW_LIST);
} }
@Before @Before
@@ -134,7 +140,23 @@ public class StagedInstallInternalTest extends BaseHostJUnit4Test {
} }
getDevice().remountSystemWritable(); getDevice().remountSystemWritable();
assertTrue(getDevice().pushFile(apex, "/system/apex/" + fileName)); assertTrue(getDevice().pushFile(apex, "/system/apex/" + fileName));
getDevice().reboot(); }
private void pushTestVendorApexAllowList(String installerPackageName) throws Exception {
if (!getDevice().isAdbRoot()) {
getDevice().enableAdbRoot();
}
getDevice().remountSystemWritable();
File file = File.createTempFile("test-vendor-apex-allow-list", ".xml");
try (BufferedWriter writer = new BufferedWriter(new FileWriter(file))) {
final String fmt =
"<config>\n"
+ " <allowed-vendor-apex package=\"test.apex.rebootless\" "
+ " installerPackage=\"%s\" />\n"
+ "</config>";
writer.write(String.format(fmt, installerPackageName));
}
getDevice().pushFile(file, TEST_VENDOR_APEX_ALLOW_LIST);
} }
/** /**
@@ -144,6 +166,8 @@ public class StagedInstallInternalTest extends BaseHostJUnit4Test {
@LargeTest @LargeTest
public void testDuplicateApkInApexShouldFail() throws Exception { public void testDuplicateApkInApexShouldFail() throws Exception {
pushTestApex(APK_IN_APEX_TESTAPEX_NAME + "_v1.apex"); pushTestApex(APK_IN_APEX_TESTAPEX_NAME + "_v1.apex");
getDevice().reboot();
runPhase("testDuplicateApkInApexShouldFail_Commit"); runPhase("testDuplicateApkInApexShouldFail_Commit");
getDevice().reboot(); getDevice().reboot();
runPhase("testDuplicateApkInApexShouldFail_Verify"); runPhase("testDuplicateApkInApexShouldFail_Verify");
@@ -388,12 +412,72 @@ public class StagedInstallInternalTest extends BaseHostJUnit4Test {
runPhase("testApexIsNotActivatedIfNotInCheckpointMode_VerifyPostReboot"); runPhase("testApexIsNotActivatedIfNotInCheckpointMode_VerifyPostReboot");
} }
@Test
public void testApexInstallerNotInAllowListCanNotInstall() throws Exception {
assumeTrue("Device does not support updating APEX",
mHostUtils.isApexUpdateSupported());
runPhase("testApexInstallerNotInAllowListCanNotInstall_staged");
runPhase("testApexInstallerNotInAllowListCanNotInstall_nonStaged");
}
@Test
@LargeTest
public void testApexNotInAllowListCanNotInstall() throws Exception {
assumeTrue("Device does not support updating APEX",
mHostUtils.isApexUpdateSupported());
pushTestApex("test.rebootless_apex_v1.apex");
getDevice().reboot();
runPhase("testApexNotInAllowListCanNotInstall_staged");
runPhase("testApexNotInAllowListCanNotInstall_nonStaged");
}
@Test
@LargeTest
public void testVendorApexWrongInstaller() throws Exception {
assumeTrue("Device does not support updating APEX",
mHostUtils.isApexUpdateSupported());
pushTestVendorApexAllowList("com.wrong.installer");
pushTestApex("test.rebootless_apex_v1.apex");
getDevice().reboot();
runPhase("testVendorApexWrongInstaller_staged");
runPhase("testVendorApexWrongInstaller_nonStaged");
}
@Test
@LargeTest
public void testVendorApexCorrectInstaller() throws Exception {
assumeTrue("Device does not support updating APEX",
mHostUtils.isApexUpdateSupported());
pushTestVendorApexAllowList("com.android.tests.stagedinstallinternal");
pushTestApex("test.rebootless_apex_v1.apex");
getDevice().reboot();
runPhase("testVendorApexCorrectInstaller_staged");
runPhase("testVendorApexCorrectInstaller_nonStaged");
}
@Test @Test
public void testRebootlessUpdates() throws Exception { public void testRebootlessUpdates() throws Exception {
pushTestApex("test.rebootless_apex_v1.apex"); pushTestApex("test.rebootless_apex_v1.apex");
getDevice().reboot();
runPhase("testRebootlessUpdates"); runPhase("testRebootlessUpdates");
} }
@Test
public void testRebootlessUpdate_hasStagedSessionWithSameApex_fails() throws Exception {
assumeTrue("Device does not support updating APEX",
mHostUtils.isApexUpdateSupported());
runPhase("testRebootlessUpdate_hasStagedSessionWithSameApex_fails");
}
private List<String> getStagingDirectories() throws DeviceNotAvailableException { private List<String> getStagingDirectories() throws DeviceNotAvailableException {
String baseDir = "/data/app-staging"; String baseDir = "/data/app-staging";
try { try {