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:
@@ -241,7 +241,11 @@ public class SystemConfig {
|
||||
|
||||
private final ArraySet<String> mRollbackWhitelistedPackages = 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,
|
||||
@@ -412,10 +416,14 @@ public class SystemConfig {
|
||||
return mWhitelistedStagedInstallers;
|
||||
}
|
||||
|
||||
public Set<String> getAllowedVendorApexes() {
|
||||
public Map<String, String> getAllowedVendorApexes() {
|
||||
return mAllowedVendorApexes;
|
||||
}
|
||||
|
||||
public String getModulesInstallerPackageName() {
|
||||
return mModulesInstallerPackageName;
|
||||
}
|
||||
|
||||
public ArraySet<String> getAppDataIsolationWhitelistedApps() {
|
||||
return mAppDataIsolationWhitelistedApps;
|
||||
}
|
||||
@@ -1210,12 +1218,21 @@ public class SystemConfig {
|
||||
case "whitelisted-staged-installer": {
|
||||
if (allowAppConfigs) {
|
||||
String pkgname = parser.getAttributeValue(null, "package");
|
||||
boolean isModulesInstaller = XmlUtils.readBooleanAttribute(
|
||||
parser, "isModulesInstaller", false);
|
||||
if (pkgname == null) {
|
||||
Slog.w(TAG, "<" + name + "> without package in " + permFile
|
||||
+ " at " + parser.getPositionDescription());
|
||||
} else {
|
||||
mWhitelistedStagedInstallers.add(pkgname);
|
||||
}
|
||||
if (isModulesInstaller) {
|
||||
if (mModulesInstallerPackageName != null) {
|
||||
throw new IllegalStateException(
|
||||
"Multiple modules installers");
|
||||
}
|
||||
mModulesInstallerPackageName = pkgname;
|
||||
}
|
||||
} else {
|
||||
logNotAllowedInPartition(name, permFile, parser);
|
||||
}
|
||||
@@ -1224,11 +1241,18 @@ public class SystemConfig {
|
||||
case "allowed-vendor-apex": {
|
||||
if (allowVendorApex) {
|
||||
String pkgName = parser.getAttributeValue(null, "package");
|
||||
String installerPkgName = parser.getAttributeValue(
|
||||
null, "installerPackage");
|
||||
if (pkgName == null) {
|
||||
Slog.w(TAG, "<" + name + "> without package in " + permFile
|
||||
+ " 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 {
|
||||
logNotAllowedInPartition(name, permFile, parser);
|
||||
|
||||
@@ -2252,12 +2252,29 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
||||
(params.installFlags & PackageManager.INSTALL_DISABLE_ALLOWED_APEX_UPDATE_CHECK)
|
||||
== 0;
|
||||
synchronized (mLock) {
|
||||
if (checkApexUpdateAllowed && !isApexUpdateAllowed(mPackageName)) {
|
||||
if (checkApexUpdateAllowed && !isApexUpdateAllowed(mPackageName,
|
||||
mInstallSource.installerPackageName)) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
@@ -2798,9 +2815,23 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
||||
return sessionContains((s) -> !s.isApexSession());
|
||||
}
|
||||
|
||||
private boolean isApexUpdateAllowed(String apexPackageName) {
|
||||
return mPm.getModuleInfo(apexPackageName, 0) != null
|
||||
|| SystemConfig.getInstance().getAllowedVendorApexes().contains(apexPackageName);
|
||||
private boolean isApexUpdateAllowed(String apexPackageName, String installerPackageName) {
|
||||
if (mPm.getModuleInfo(apexPackageName, 0) != null) {
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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
|
||||
void createSession(@NonNull StagedSession sessionInfo) {
|
||||
synchronized (mStagedSessions) {
|
||||
|
||||
@@ -459,6 +459,66 @@ public class StagingManagerTest {
|
||||
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,
|
||||
long committedMillis) {
|
||||
PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(
|
||||
|
||||
@@ -19,6 +19,7 @@ package com.android.server.systemconfig;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.testng.Assert.expectThrows;
|
||||
|
||||
import android.platform.test.annotations.Presubmit;
|
||||
import android.util.ArrayMap;
|
||||
@@ -200,6 +201,46 @@ public class SystemConfigTest {
|
||||
|
||||
assertThat(mSysConfig.getWhitelistedStagedInstallers())
|
||||
.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 {
|
||||
final String contents =
|
||||
"<config>\n"
|
||||
+ " <allowed-vendor-apex package=\"com.android.apex1\" />\n"
|
||||
+ " <allowed-vendor-apex package=\"com.android.apex1\" "
|
||||
+ "installerPackage=\"com.installer\" />\n"
|
||||
+ "</config>";
|
||||
final File folder = createTempSubfolder("folder");
|
||||
createTempFile(folder, "vendor-apex-allowlist.xml", contents);
|
||||
|
||||
mSysConfig.readPermissions(folder, /* Grant all permission flags */ ~0);
|
||||
|
||||
assertThat(mSysConfig.getAllowedVendorApexes()).containsExactly("com.android.apex1");
|
||||
assertThat(mSysConfig.getAllowedVendorApexes())
|
||||
.containsExactly("com.android.apex1", "com.installer");
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -32,6 +32,7 @@ android_test_helper_app {
|
||||
test_suites: ["general-tests"],
|
||||
java_resources: [
|
||||
":com.android.apex.apkrollback.test_v2",
|
||||
":StagedInstallTestApexV2",
|
||||
":StagedInstallTestApexV2_WrongSha",
|
||||
":test.rebootless_apex_v1",
|
||||
":test.rebootless_apex_v2",
|
||||
|
||||
@@ -55,8 +55,11 @@ public class StagedInstallInternalTest {
|
||||
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");
|
||||
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");
|
||||
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(
|
||||
InstrumentationRegistry.getInstrumentation().getContext().getFilesDir(),
|
||||
@@ -236,6 +239,96 @@ public class StagedInstallInternalTest {
|
||||
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
|
||||
public void testRebootlessUpdates() throws Exception {
|
||||
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) {
|
||||
assertSessionState(sessionId, (session) -> {
|
||||
assertThat(session.isStagedSessionApplied()).isTrue();
|
||||
|
||||
@@ -43,7 +43,9 @@ import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.util.List;
|
||||
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_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);
|
||||
|
||||
/**
|
||||
@@ -87,7 +92,8 @@ public class StagedInstallInternalTest extends BaseHostJUnit4Test {
|
||||
"/data/apex/active/" + APK_IN_APEX_TESTAPEX_NAME + "*.apex",
|
||||
"/data/apex/active/" + SHIM_APEX_PACKAGE_NAME + "*.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
|
||||
@@ -134,7 +140,23 @@ public class StagedInstallInternalTest extends BaseHostJUnit4Test {
|
||||
}
|
||||
getDevice().remountSystemWritable();
|
||||
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
|
||||
public void testDuplicateApkInApexShouldFail() throws Exception {
|
||||
pushTestApex(APK_IN_APEX_TESTAPEX_NAME + "_v1.apex");
|
||||
getDevice().reboot();
|
||||
|
||||
runPhase("testDuplicateApkInApexShouldFail_Commit");
|
||||
getDevice().reboot();
|
||||
runPhase("testDuplicateApkInApexShouldFail_Verify");
|
||||
@@ -388,12 +412,72 @@ public class StagedInstallInternalTest extends BaseHostJUnit4Test {
|
||||
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
|
||||
public void testRebootlessUpdates() throws Exception {
|
||||
pushTestApex("test.rebootless_apex_v1.apex");
|
||||
getDevice().reboot();
|
||||
|
||||
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 {
|
||||
String baseDir = "/data/app-staging";
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user