Remove tests (13/n)
Remove tests that have been migrated to CTS-root/CTS. * RollbackTest#testMultipleRollbackAvailable is removed. The test is no longer needed as the API it tests (RollbackManager#getAvailableRollback(String packageName)) is removed by ag/6153954. Bug: 194971428 Test: m StagedRollbackTest RollbackTest Change-Id: I044f24427c94e2037defe203655c1f8ec25fa6c6
This commit is contained in:
@@ -16,7 +16,6 @@
|
||||
|
||||
package com.android.tests.rollback;
|
||||
|
||||
import static com.android.cts.install.lib.InstallUtils.processUserData;
|
||||
import static com.android.cts.rollback.lib.RollbackInfoSubject.assertThat;
|
||||
import static com.android.cts.rollback.lib.RollbackUtils.getUniqueRollbackInfoForPackage;
|
||||
import static com.android.cts.rollback.lib.RollbackUtils.waitForAvailableRollback;
|
||||
@@ -34,7 +33,6 @@ import android.content.IntentFilter;
|
||||
import android.content.rollback.RollbackInfo;
|
||||
import android.content.rollback.RollbackManager;
|
||||
import android.os.UserManager;
|
||||
import android.provider.DeviceConfig;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.test.InstrumentationRegistry;
|
||||
@@ -69,12 +67,6 @@ public class RollbackTest {
|
||||
|
||||
private static final String INSTRUMENTED_APP = "com.android.tests.rollback";
|
||||
|
||||
// copied from PackageManagerService#PROPERTY_ENABLE_ROLLBACK_TIMEOUT_MILLIS
|
||||
// TODO: find a better place for the property so that it can be imported in tests
|
||||
// maybe android.content.pm.PackageManager?
|
||||
private static final String PROPERTY_ENABLE_ROLLBACK_TIMEOUT_MILLIS =
|
||||
"enable_rollback_timeout";
|
||||
|
||||
private static boolean hasRollbackInclude(List<RollbackInfo> rollbacks, String packageName) {
|
||||
return rollbacks.stream().anyMatch(
|
||||
ri -> ri.getPackages().stream().anyMatch(
|
||||
@@ -201,355 +193,6 @@ public class RollbackTest {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the scheduling aspect of rollback expiration.
|
||||
*/
|
||||
@Test
|
||||
public void testRollbackExpiresAfterLifetime() throws Exception {
|
||||
long expirationTime = TimeUnit.SECONDS.toMillis(30);
|
||||
long defaultExpirationTime = TimeUnit.HOURS.toMillis(48);
|
||||
RollbackManager rm = RollbackUtils.getRollbackManager();
|
||||
|
||||
try {
|
||||
InstallUtils.adoptShellPermissionIdentity(
|
||||
Manifest.permission.INSTALL_PACKAGES,
|
||||
Manifest.permission.DELETE_PACKAGES,
|
||||
Manifest.permission.TEST_MANAGE_ROLLBACKS,
|
||||
Manifest.permission.WRITE_DEVICE_CONFIG);
|
||||
|
||||
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ROLLBACK_BOOT,
|
||||
RollbackManager.PROPERTY_ROLLBACK_LIFETIME_MILLIS,
|
||||
Long.toString(expirationTime), false /* makeDefault*/);
|
||||
|
||||
// Uninstall TestApp.A
|
||||
Uninstall.packages(TestApp.A);
|
||||
assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(-1);
|
||||
|
||||
// Install v1 of the app (without rollbacks enabled).
|
||||
Install.single(TestApp.A1).commit();
|
||||
assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1);
|
||||
|
||||
// Upgrade from v1 to v2, with rollbacks enabled.
|
||||
Install.single(TestApp.A2).setEnableRollback().commit();
|
||||
assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2);
|
||||
|
||||
// Check that the rollback data has not expired
|
||||
Thread.sleep(1000);
|
||||
RollbackInfo rollback = waitForAvailableRollback(TestApp.A);
|
||||
assertThat(rollback).packagesContainsExactly(
|
||||
Rollback.from(TestApp.A2).to(TestApp.A1));
|
||||
|
||||
// Give it a little more time, but still not long enough to expire
|
||||
Thread.sleep(expirationTime / 2);
|
||||
rollback = getUniqueRollbackInfoForPackage(
|
||||
rm.getAvailableRollbacks(), TestApp.A);
|
||||
assertThat(rollback).isNotNull();
|
||||
assertThat(rollback).packagesContainsExactly(
|
||||
Rollback.from(TestApp.A2).to(TestApp.A1));
|
||||
|
||||
// Check that the data has expired after the expiration time (with a buffer of 1 second)
|
||||
Thread.sleep(expirationTime / 2);
|
||||
rollback = getUniqueRollbackInfoForPackage(
|
||||
rm.getAvailableRollbacks(), TestApp.A);
|
||||
assertThat(rollback).isNull();
|
||||
|
||||
} finally {
|
||||
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ROLLBACK_BOOT,
|
||||
RollbackManager.PROPERTY_ROLLBACK_LIFETIME_MILLIS,
|
||||
Long.toString(defaultExpirationTime), false /* makeDefault*/);
|
||||
InstallUtils.dropShellPermissionIdentity();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that available rollbacks should expire correctly when the property
|
||||
* {@link RollbackManager#PROPERTY_ROLLBACK_LIFETIME_MILLIS} is changed
|
||||
*/
|
||||
@Test
|
||||
public void testRollbackExpiresWhenLifetimeChanges() throws Exception {
|
||||
long defaultExpirationTime = TimeUnit.HOURS.toMillis(48);
|
||||
RollbackManager rm = RollbackUtils.getRollbackManager();
|
||||
|
||||
try {
|
||||
InstallUtils.adoptShellPermissionIdentity(
|
||||
Manifest.permission.INSTALL_PACKAGES,
|
||||
Manifest.permission.DELETE_PACKAGES,
|
||||
Manifest.permission.TEST_MANAGE_ROLLBACKS,
|
||||
Manifest.permission.WRITE_DEVICE_CONFIG);
|
||||
|
||||
Uninstall.packages(TestApp.A);
|
||||
assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(-1);
|
||||
Install.single(TestApp.A1).commit();
|
||||
assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1);
|
||||
Install.single(TestApp.A2).setEnableRollback().commit();
|
||||
assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2);
|
||||
RollbackInfo rollback = waitForAvailableRollback(TestApp.A);
|
||||
assertThat(rollback).packagesContainsExactly(Rollback.from(TestApp.A2).to(TestApp.A1));
|
||||
|
||||
// Change the lifetime to 0 which should expire rollbacks immediately
|
||||
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ROLLBACK_BOOT,
|
||||
RollbackManager.PROPERTY_ROLLBACK_LIFETIME_MILLIS,
|
||||
Long.toString(0), false /* makeDefault*/);
|
||||
|
||||
// Keep polling until device config changes has happened (which might take more than
|
||||
// 5 sec depending how busy system_server is) and rollbacks have expired
|
||||
for (int i = 0; i < 30; ++i) {
|
||||
if (hasRollbackInclude(rm.getAvailableRollbacks(), TestApp.A)) {
|
||||
Thread.sleep(1000);
|
||||
}
|
||||
}
|
||||
rollback = getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(), TestApp.A);
|
||||
assertThat(rollback).isNull();
|
||||
} finally {
|
||||
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ROLLBACK_BOOT,
|
||||
RollbackManager.PROPERTY_ROLLBACK_LIFETIME_MILLIS,
|
||||
Long.toString(defaultExpirationTime), false /* makeDefault*/);
|
||||
InstallUtils.dropShellPermissionIdentity();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that changing time on device does not affect the duration of time that we keep
|
||||
* rollback available
|
||||
*/
|
||||
@Test
|
||||
public void testTimeChangeDoesNotAffectLifetime() throws Exception {
|
||||
long expirationTime = TimeUnit.SECONDS.toMillis(30);
|
||||
long defaultExpirationTime = TimeUnit.HOURS.toMillis(48);
|
||||
RollbackManager rm = RollbackUtils.getRollbackManager();
|
||||
|
||||
try {
|
||||
InstallUtils.adoptShellPermissionIdentity(
|
||||
Manifest.permission.INSTALL_PACKAGES,
|
||||
Manifest.permission.DELETE_PACKAGES,
|
||||
Manifest.permission.TEST_MANAGE_ROLLBACKS,
|
||||
Manifest.permission.WRITE_DEVICE_CONFIG,
|
||||
Manifest.permission.SET_TIME);
|
||||
|
||||
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ROLLBACK_BOOT,
|
||||
RollbackManager.PROPERTY_ROLLBACK_LIFETIME_MILLIS,
|
||||
Long.toString(expirationTime), false /* makeDefault*/);
|
||||
|
||||
// Install app A with rollback enabled
|
||||
Uninstall.packages(TestApp.A);
|
||||
Install.single(TestApp.A1).commit();
|
||||
Install.single(TestApp.A2).setEnableRollback().commit();
|
||||
assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2);
|
||||
|
||||
Thread.sleep(expirationTime / 2);
|
||||
|
||||
// Install app B with rollback enabled
|
||||
Uninstall.packages(TestApp.B);
|
||||
Install.single(TestApp.B1).commit();
|
||||
Install.single(TestApp.B2).setEnableRollback().commit();
|
||||
assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(2);
|
||||
|
||||
// 1 second buffer
|
||||
Thread.sleep(1000);
|
||||
|
||||
try {
|
||||
// Change the time
|
||||
RollbackUtils.forwardTimeBy(expirationTime);
|
||||
|
||||
// 1 second buffer to allow Rollback Manager to handle time change before loading
|
||||
// persisted data
|
||||
Thread.sleep(1000);
|
||||
|
||||
// Load timestamps from storage
|
||||
rm.reloadPersistedData();
|
||||
|
||||
// Wait until rollback for app A has expired
|
||||
// This will trigger an expiration run that should expire app A but not B
|
||||
Thread.sleep(expirationTime / 2);
|
||||
RollbackInfo rollbackA =
|
||||
getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(), TestApp.A);
|
||||
Log.i(TAG, "Checking if the rollback for TestApp.A is null");
|
||||
|
||||
// Rollback for app B should not be expired
|
||||
RollbackInfo rollbackB1 = getUniqueRollbackInfoForPackage(
|
||||
rm.getAvailableRollbacks(), TestApp.B);
|
||||
|
||||
// Wait until rollback for app B has expired
|
||||
Thread.sleep(expirationTime / 2);
|
||||
RollbackInfo rollbackB2 = getUniqueRollbackInfoForPackage(
|
||||
rm.getAvailableRollbacks(), TestApp.B);
|
||||
|
||||
assertThat(rollbackA).isNull();
|
||||
assertThat(rollbackB1).isNotNull();
|
||||
assertThat(rollbackB1).packagesContainsExactly(
|
||||
Rollback.from(TestApp.B2).to(TestApp.B1));
|
||||
assertThat(rollbackB2).isNull();
|
||||
} finally {
|
||||
RollbackUtils.forwardTimeBy(-expirationTime);
|
||||
}
|
||||
} finally {
|
||||
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ROLLBACK_BOOT,
|
||||
RollbackManager.PROPERTY_ROLLBACK_LIFETIME_MILLIS,
|
||||
Long.toString(defaultExpirationTime), false /* makeDefault*/);
|
||||
InstallUtils.dropShellPermissionIdentity();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test explicit expiration of rollbacks.
|
||||
* Does not test the scheduling aspects of rollback expiration.
|
||||
*/
|
||||
@Test
|
||||
public void testRollbackExpiration() throws Exception {
|
||||
try {
|
||||
InstallUtils.adoptShellPermissionIdentity(
|
||||
Manifest.permission.INSTALL_PACKAGES,
|
||||
Manifest.permission.DELETE_PACKAGES,
|
||||
Manifest.permission.TEST_MANAGE_ROLLBACKS);
|
||||
|
||||
RollbackManager rm = RollbackUtils.getRollbackManager();
|
||||
Uninstall.packages(TestApp.A);
|
||||
Install.single(TestApp.A1).commit();
|
||||
Install.single(TestApp.A2).setEnableRollback().commit();
|
||||
assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2);
|
||||
|
||||
// The app should now be available for rollback.
|
||||
RollbackInfo rollback = waitForAvailableRollback(TestApp.A);
|
||||
assertThat(rollback).packagesContainsExactly(
|
||||
Rollback.from(TestApp.A2).to(TestApp.A1));
|
||||
|
||||
// Expire the rollback.
|
||||
rm.expireRollbackForPackage(TestApp.A);
|
||||
|
||||
// The rollback should no longer be available.
|
||||
assertThat(getUniqueRollbackInfoForPackage(
|
||||
rm.getAvailableRollbacks(), TestApp.A)).isNull();
|
||||
} finally {
|
||||
InstallUtils.dropShellPermissionIdentity();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that app user data is rolled back.
|
||||
*/
|
||||
@Test
|
||||
public void testUserDataRollback() throws Exception {
|
||||
try {
|
||||
InstallUtils.adoptShellPermissionIdentity(
|
||||
Manifest.permission.INSTALL_PACKAGES,
|
||||
Manifest.permission.DELETE_PACKAGES,
|
||||
Manifest.permission.TEST_MANAGE_ROLLBACKS);
|
||||
|
||||
Uninstall.packages(TestApp.A);
|
||||
Install.single(TestApp.A1).commit();
|
||||
processUserData(TestApp.A);
|
||||
Install.single(TestApp.A2).setEnableRollback().commit();
|
||||
processUserData(TestApp.A);
|
||||
|
||||
RollbackInfo rollback = waitForAvailableRollback(TestApp.A);
|
||||
RollbackUtils.rollback(rollback.getRollbackId());
|
||||
processUserData(TestApp.A);
|
||||
} finally {
|
||||
InstallUtils.dropShellPermissionIdentity();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test rollback of apks involving splits.
|
||||
*/
|
||||
@Test
|
||||
public void testRollbackWithSplits() throws Exception {
|
||||
try {
|
||||
InstallUtils.adoptShellPermissionIdentity(
|
||||
Manifest.permission.INSTALL_PACKAGES,
|
||||
Manifest.permission.DELETE_PACKAGES,
|
||||
Manifest.permission.TEST_MANAGE_ROLLBACKS);
|
||||
|
||||
Uninstall.packages(TestApp.A);
|
||||
Install.single(TestApp.ASplit1).commit();
|
||||
processUserData(TestApp.A);
|
||||
|
||||
Install.single(TestApp.ASplit2).setEnableRollback().commit();
|
||||
processUserData(TestApp.A);
|
||||
|
||||
RollbackInfo rollback = waitForAvailableRollback(TestApp.A);
|
||||
RollbackUtils.rollback(rollback.getRollbackId());
|
||||
processUserData(TestApp.A);
|
||||
} finally {
|
||||
InstallUtils.dropShellPermissionIdentity();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test restrictions on rollback broadcast sender.
|
||||
* A random app should not be able to send a ROLLBACK_COMMITTED broadcast.
|
||||
*/
|
||||
@Test
|
||||
public void testRollbackBroadcastRestrictions() throws Exception {
|
||||
RollbackBroadcastReceiver broadcastReceiver = new RollbackBroadcastReceiver();
|
||||
Intent broadcast = new Intent(Intent.ACTION_ROLLBACK_COMMITTED);
|
||||
try {
|
||||
InstrumentationRegistry.getContext().sendBroadcast(broadcast);
|
||||
fail("Succeeded in sending restricted broadcast from app context.");
|
||||
} catch (SecurityException se) {
|
||||
// Expected behavior.
|
||||
}
|
||||
|
||||
// Confirm that we really haven't received the broadcast.
|
||||
// TODO: How long to wait for the expected timeout?
|
||||
assertThat(broadcastReceiver.poll(5, TimeUnit.SECONDS)).isNull();
|
||||
|
||||
// TODO: Do we need to do this? Do we need to ensure this is always
|
||||
// called, even when the test fails?
|
||||
broadcastReceiver.unregister();
|
||||
}
|
||||
|
||||
/**
|
||||
* Regression test for rollback in the case when multiple apps are
|
||||
* available for rollback at the same time.
|
||||
*/
|
||||
@Test
|
||||
public void testMultipleRollbackAvailable() throws Exception {
|
||||
try {
|
||||
InstallUtils.adoptShellPermissionIdentity(
|
||||
Manifest.permission.INSTALL_PACKAGES,
|
||||
Manifest.permission.DELETE_PACKAGES,
|
||||
Manifest.permission.TEST_MANAGE_ROLLBACKS);
|
||||
|
||||
// Prep installation of the test apps.
|
||||
Uninstall.packages(TestApp.A);
|
||||
Install.single(TestApp.A1).commit();
|
||||
Install.single(TestApp.A2).setEnableRollback().commit();
|
||||
assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2);
|
||||
|
||||
Uninstall.packages(TestApp.B);
|
||||
Install.single(TestApp.B1).commit();
|
||||
Install.single(TestApp.B2).setEnableRollback().commit();
|
||||
assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(2);
|
||||
|
||||
// Both test apps should now be available for rollback, and the
|
||||
// RollbackInfo returned for the rollbacks should be correct.
|
||||
RollbackInfo rollbackA = waitForAvailableRollback(TestApp.A);
|
||||
assertThat(rollbackA).packagesContainsExactly(
|
||||
Rollback.from(TestApp.A2).to(TestApp.A1));
|
||||
|
||||
RollbackInfo rollbackB = waitForAvailableRollback(TestApp.B);
|
||||
assertThat(rollbackB).packagesContainsExactly(
|
||||
Rollback.from(TestApp.B2).to(TestApp.B1));
|
||||
|
||||
// Executing rollback should roll back the correct package.
|
||||
RollbackUtils.rollback(rollbackA.getRollbackId());
|
||||
assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1);
|
||||
assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(2);
|
||||
|
||||
Uninstall.packages(TestApp.A);
|
||||
Install.single(TestApp.A1).commit();
|
||||
Install.single(TestApp.A2).setEnableRollback().commit();
|
||||
assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2);
|
||||
|
||||
RollbackUtils.rollback(rollbackB.getRollbackId());
|
||||
assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2);
|
||||
assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(1);
|
||||
} finally {
|
||||
InstallUtils.dropShellPermissionIdentity();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore("b/120200473")
|
||||
/**
|
||||
@@ -687,90 +330,4 @@ public class RollbackTest {
|
||||
InstallUtils.dropShellPermissionIdentity();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEnableRollbackTimeoutFailsRollback() throws Exception {
|
||||
try {
|
||||
InstallUtils.adoptShellPermissionIdentity(
|
||||
Manifest.permission.INSTALL_PACKAGES,
|
||||
Manifest.permission.DELETE_PACKAGES,
|
||||
Manifest.permission.TEST_MANAGE_ROLLBACKS,
|
||||
Manifest.permission.MANAGE_ROLLBACKS,
|
||||
Manifest.permission.WRITE_DEVICE_CONFIG);
|
||||
|
||||
//setting the timeout to a very short amount that will definitely be triggered
|
||||
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ROLLBACK,
|
||||
PROPERTY_ENABLE_ROLLBACK_TIMEOUT_MILLIS,
|
||||
Long.toString(0), false /* makeDefault*/);
|
||||
RollbackManager rm = RollbackUtils.getRollbackManager();
|
||||
|
||||
Uninstall.packages(TestApp.A);
|
||||
Install.single(TestApp.A1).commit();
|
||||
waitForUnavailableRollback(TestApp.A);
|
||||
|
||||
// Block the RollbackManager to make extra sure it will not be
|
||||
// able to enable the rollback in time.
|
||||
rm.blockRollbackManager(TimeUnit.SECONDS.toMillis(1));
|
||||
Install.single(TestApp.A2).setEnableRollback().commit();
|
||||
|
||||
assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2);
|
||||
|
||||
// Give plenty of time for RollbackManager to unblock and attempt
|
||||
// to make the rollback available before asserting that the
|
||||
// rollback was not made available.
|
||||
Thread.sleep(TimeUnit.SECONDS.toMillis(2));
|
||||
assertThat(
|
||||
getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(), TestApp.A)).isNull();
|
||||
} finally {
|
||||
//setting the timeout back to default
|
||||
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ROLLBACK,
|
||||
PROPERTY_ENABLE_ROLLBACK_TIMEOUT_MILLIS,
|
||||
null, false /* makeDefault*/);
|
||||
InstallUtils.dropShellPermissionIdentity();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEnableRollbackTimeoutFailsRollback_MultiPackage() throws Exception {
|
||||
try {
|
||||
InstallUtils.adoptShellPermissionIdentity(
|
||||
Manifest.permission.INSTALL_PACKAGES,
|
||||
Manifest.permission.DELETE_PACKAGES,
|
||||
Manifest.permission.TEST_MANAGE_ROLLBACKS,
|
||||
Manifest.permission.MANAGE_ROLLBACKS,
|
||||
Manifest.permission.WRITE_DEVICE_CONFIG);
|
||||
|
||||
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ROLLBACK,
|
||||
PROPERTY_ENABLE_ROLLBACK_TIMEOUT_MILLIS,
|
||||
Long.toString(5000), false /* makeDefault*/);
|
||||
RollbackManager rm = RollbackUtils.getRollbackManager();
|
||||
|
||||
Uninstall.packages(TestApp.A, TestApp.B);
|
||||
Install.multi(TestApp.A1, TestApp.B1).commit();
|
||||
waitForUnavailableRollback(TestApp.A);
|
||||
|
||||
// Block the 2nd session for 10s so it will not be able to enable the rollback in time.
|
||||
rm.blockRollbackManager(TimeUnit.SECONDS.toMillis(0));
|
||||
rm.blockRollbackManager(TimeUnit.SECONDS.toMillis(10));
|
||||
Install.multi(TestApp.A2, TestApp.B2).setEnableRollback().commit();
|
||||
|
||||
assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2);
|
||||
assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(2);
|
||||
|
||||
// Give plenty of time for RollbackManager to unblock and attempt
|
||||
// to make the rollback available before asserting that the
|
||||
// rollback was not made available.
|
||||
Thread.sleep(TimeUnit.SECONDS.toMillis(2));
|
||||
|
||||
List<RollbackInfo> available = rm.getAvailableRollbacks();
|
||||
assertThat(getUniqueRollbackInfoForPackage(available, TestApp.A)).isNull();
|
||||
assertThat(getUniqueRollbackInfoForPackage(available, TestApp.B)).isNull();
|
||||
} finally {
|
||||
//setting the timeout back to default
|
||||
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ROLLBACK,
|
||||
PROPERTY_ENABLE_ROLLBACK_TIMEOUT_MILLIS,
|
||||
null, false /* makeDefault*/);
|
||||
InstallUtils.dropShellPermissionIdentity();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,12 +22,10 @@ import static com.android.cts.rollback.lib.RollbackUtils.getUniqueRollbackInfoFo
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import android.Manifest;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageInstaller;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.rollback.RollbackInfo;
|
||||
import android.content.rollback.RollbackManager;
|
||||
import android.os.storage.StorageManager;
|
||||
import android.provider.DeviceConfig;
|
||||
|
||||
import androidx.test.platform.app.InstrumentationRegistry;
|
||||
@@ -82,155 +80,6 @@ public class StagedRollbackTest {
|
||||
InstallUtils.dropShellPermissionIdentity();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test rollbacks of staged installs involving only apks with bad update.
|
||||
* Enable rollback phase.
|
||||
*/
|
||||
@Test
|
||||
public void testBadApkOnly_Phase1_Install() throws Exception {
|
||||
assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(-1);
|
||||
|
||||
Install.single(TestApp.A1).commit();
|
||||
assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1);
|
||||
InstallUtils.processUserData(TestApp.A);
|
||||
|
||||
Install.single(TestApp.ACrashing2).setEnableRollback().setStaged().commit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test rollbacks of staged installs involving only apks with bad update.
|
||||
* Confirm that rollback was successfully enabled.
|
||||
*/
|
||||
@Test
|
||||
public void testBadApkOnly_Phase2_VerifyInstall() throws Exception {
|
||||
assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2);
|
||||
InstallUtils.processUserData(TestApp.A);
|
||||
|
||||
RollbackManager rm = RollbackUtils.getRollbackManager();
|
||||
RollbackInfo rollback = getUniqueRollbackInfoForPackage(
|
||||
rm.getAvailableRollbacks(), TestApp.A);
|
||||
assertThat(rollback).isNotNull();
|
||||
assertThat(rollback).packagesContainsExactly(
|
||||
Rollback.from(TestApp.A2).to(TestApp.A1));
|
||||
assertThat(rollback.isStaged()).isTrue();
|
||||
|
||||
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ROLLBACK,
|
||||
PROPERTY_WATCHDOG_TRIGGER_FAILURE_COUNT,
|
||||
Integer.toString(5), false);
|
||||
RollbackUtils.sendCrashBroadcast(TestApp.A, 4);
|
||||
// Sleep for a while to make sure we don't trigger rollback
|
||||
Thread.sleep(TimeUnit.SECONDS.toMillis(30));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test rollbacks of staged installs involving only apks.
|
||||
* Confirm rollback phase.
|
||||
*/
|
||||
@Test
|
||||
public void testBadApkOnly_Phase3_VerifyRollback() throws Exception {
|
||||
assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1);
|
||||
InstallUtils.processUserData(TestApp.A);
|
||||
|
||||
RollbackManager rm = RollbackUtils.getRollbackManager();
|
||||
RollbackInfo rollback = getUniqueRollbackInfoForPackage(
|
||||
rm.getRecentlyCommittedRollbacks(), TestApp.A);
|
||||
assertThat(rollback).isNotNull();
|
||||
assertThat(rollback).packagesContainsExactly(
|
||||
Rollback.from(TestApp.A2).to(TestApp.A1));
|
||||
assertThat(rollback).causePackagesContainsExactly(TestApp.ACrashing2);
|
||||
assertThat(rollback).isStaged();
|
||||
assertThat(rollback.getCommittedSessionId()).isNotEqualTo(-1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stage install an apk with rollback that will be later triggered by unattributable crash.
|
||||
*/
|
||||
@Test
|
||||
public void testNativeWatchdogTriggersRollback_Phase1_Install() throws Exception {
|
||||
Install.single(TestApp.A1).commit();
|
||||
assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1);
|
||||
|
||||
Install.single(TestApp.A2).setEnableRollback().setStaged().commit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify the rollback is available.
|
||||
*/
|
||||
@Test
|
||||
public void testNativeWatchdogTriggersRollback_Phase2_VerifyInstall() throws Exception {
|
||||
assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2);
|
||||
RollbackManager rm = RollbackUtils.getRollbackManager();
|
||||
assertThat(getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(),
|
||||
TestApp.A)).isNotNull();
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify the rollback is committed after crashing.
|
||||
*/
|
||||
@Test
|
||||
public void testNativeWatchdogTriggersRollback_Phase3_VerifyRollback() throws Exception {
|
||||
assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1);
|
||||
RollbackManager rm = RollbackUtils.getRollbackManager();
|
||||
assertThat(getUniqueRollbackInfoForPackage(rm.getRecentlyCommittedRollbacks(),
|
||||
TestApp.A)).isNotNull();
|
||||
}
|
||||
|
||||
/**
|
||||
* Stage install an apk with rollback that will be later triggered by unattributable crash.
|
||||
*/
|
||||
@Test
|
||||
public void testNativeWatchdogTriggersRollbackForAll_Phase1_InstallA() throws Exception {
|
||||
Install.single(TestApp.A1).commit();
|
||||
assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1);
|
||||
|
||||
Install.single(TestApp.A2).setEnableRollback().setStaged().commit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify the rollback is available and then install another package with rollback.
|
||||
*/
|
||||
@Test
|
||||
public void testNativeWatchdogTriggersRollbackForAll_Phase2_InstallB() throws Exception {
|
||||
assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2);
|
||||
RollbackManager rm = RollbackUtils.getRollbackManager();
|
||||
assertThat(getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(),
|
||||
TestApp.A)).isNotNull();
|
||||
|
||||
// Install another package with rollback
|
||||
Install.single(TestApp.B1).commit();
|
||||
assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(1);
|
||||
|
||||
Install.single(TestApp.B2).setEnableRollback().setStaged().commit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify the rollbacks are available.
|
||||
*/
|
||||
@Test
|
||||
public void testNativeWatchdogTriggersRollbackForAll_Phase3_VerifyInstall() throws Exception {
|
||||
assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2);
|
||||
assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(2);
|
||||
RollbackManager rm = RollbackUtils.getRollbackManager();
|
||||
assertThat(getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(),
|
||||
TestApp.A)).isNotNull();
|
||||
assertThat(getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(),
|
||||
TestApp.B)).isNotNull();
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify the rollbacks are committed after crashing.
|
||||
*/
|
||||
@Test
|
||||
public void testNativeWatchdogTriggersRollbackForAll_Phase4_VerifyRollback() throws Exception {
|
||||
assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1);
|
||||
assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(1);
|
||||
RollbackManager rm = RollbackUtils.getRollbackManager();
|
||||
assertThat(getUniqueRollbackInfoForPackage(rm.getRecentlyCommittedRollbacks(),
|
||||
TestApp.A)).isNotNull();
|
||||
assertThat(getUniqueRollbackInfoForPackage(rm.getRecentlyCommittedRollbacks(),
|
||||
TestApp.B)).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPreviouslyAbandonedRollbacks_Phase1_InstallAndAbandon() throws Exception {
|
||||
Install.single(TestApp.A1).commit();
|
||||
@@ -315,51 +164,6 @@ public class StagedRollbackTest {
|
||||
"TestApexWithApkV2Crashing", APK_IN_APEX_TESTAPEX_NAME, 2, /*isApex*/true,
|
||||
APK_IN_APEX_TESTAPEX_NAME + "_v2Crashing.apex");
|
||||
|
||||
@Test
|
||||
public void testRollbackApexWithApk_Phase1_Install() throws Exception {
|
||||
assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1);
|
||||
InstallUtils.processUserData(TestApp.A);
|
||||
|
||||
int sessionId = Install.single(TEST_APEX_WITH_APK_V2).setStaged().setEnableRollback()
|
||||
.commit();
|
||||
InstallUtils.waitForSessionReady(sessionId);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRollbackApexWithApk_Phase2_Rollback() throws Exception {
|
||||
assertThat(InstallUtils.getInstalledVersion(APK_IN_APEX_TESTAPEX_NAME)).isEqualTo(2);
|
||||
assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2);
|
||||
InstallUtils.processUserData(TestApp.A);
|
||||
|
||||
RollbackInfo available = RollbackUtils.getAvailableRollback(APK_IN_APEX_TESTAPEX_NAME);
|
||||
assertThat(available).isStaged();
|
||||
assertThat(available).packagesContainsExactly(
|
||||
Rollback.from(TEST_APEX_WITH_APK_V2).to(TEST_APEX_WITH_APK_V1),
|
||||
Rollback.from(TestApp.A, 0).to(TestApp.A1));
|
||||
|
||||
RollbackUtils.rollback(available.getRollbackId(), TEST_APEX_WITH_APK_V2);
|
||||
RollbackInfo committed = RollbackUtils.getCommittedRollbackById(available.getRollbackId());
|
||||
assertThat(committed).isNotNull();
|
||||
assertThat(committed).isStaged();
|
||||
assertThat(committed).packagesContainsExactly(
|
||||
Rollback.from(TEST_APEX_WITH_APK_V2).to(TEST_APEX_WITH_APK_V1),
|
||||
Rollback.from(TestApp.A, 0).to(TestApp.A1));
|
||||
assertThat(committed).causePackagesContainsExactly(TEST_APEX_WITH_APK_V2);
|
||||
assertThat(committed.getCommittedSessionId()).isNotEqualTo(-1);
|
||||
|
||||
// Note: The app is not rolled back until after the rollback is staged
|
||||
// and the device has been rebooted.
|
||||
InstallUtils.waitForSessionReady(committed.getCommittedSessionId());
|
||||
assertThat(InstallUtils.getInstalledVersion(APK_IN_APEX_TESTAPEX_NAME)).isEqualTo(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRollbackApexWithApk_Phase3_VerifyRollback() throws Exception {
|
||||
assertThat(InstallUtils.getInstalledVersion(APK_IN_APEX_TESTAPEX_NAME)).isEqualTo(1);
|
||||
assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1);
|
||||
InstallUtils.processUserData(TestApp.A);
|
||||
}
|
||||
|
||||
/**
|
||||
* Installs an apex with an apk that can crash.
|
||||
*/
|
||||
@@ -397,52 +201,6 @@ public class StagedRollbackTest {
|
||||
assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRollbackApexDataDirectories_Phase1_Install() throws Exception {
|
||||
int sessionId = Install.single(TEST_APEX_WITH_APK_V2).setStaged().setEnableRollback()
|
||||
.commit();
|
||||
InstallUtils.waitForSessionReady(sessionId);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRollbackApexDataDirectories_Phase2_Rollback() throws Exception {
|
||||
RollbackInfo available = RollbackUtils.getAvailableRollback(APK_IN_APEX_TESTAPEX_NAME);
|
||||
|
||||
RollbackUtils.rollback(available.getRollbackId(), TEST_APEX_WITH_APK_V2);
|
||||
RollbackInfo committed = RollbackUtils.getCommittedRollbackById(available.getRollbackId());
|
||||
|
||||
// Note: The app is not rolled back until after the rollback is staged
|
||||
// and the device has been rebooted.
|
||||
InstallUtils.waitForSessionReady(committed.getCommittedSessionId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRollbackApkDataDirectories_Phase1_InstallV1() throws Exception {
|
||||
assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(-1);
|
||||
Install.single(TestApp.A1).commit();
|
||||
assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRollbackApkDataDirectories_Phase2_InstallV2() throws Exception {
|
||||
Install.single(TestApp.A2).setStaged().setEnableRollback().commit();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRollbackApkDataDirectories_Phase3_Rollback() throws Exception {
|
||||
RollbackInfo available = RollbackUtils.getAvailableRollback(TestApp.A);
|
||||
RollbackUtils.rollback(available.getRollbackId(), TestApp.A2);
|
||||
RollbackInfo committed = RollbackUtils.getCommittedRollbackById(available.getRollbackId());
|
||||
InstallUtils.waitForSessionReady(committed.getCommittedSessionId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isCheckpointSupported() {
|
||||
Context context = InstrumentationRegistry.getInstrumentation().getContext();
|
||||
StorageManager sm = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
|
||||
assertThat(sm.isCheckpointSupported()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWatchdogMonitorsAcrossReboots_Phase1_Install() throws Exception {
|
||||
assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(-1);
|
||||
@@ -482,33 +240,6 @@ public class StagedRollbackTest {
|
||||
assertThat(rollback.getCommittedSessionId()).isNotEqualTo(-1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExpireSession_Phase1_Install() throws Exception {
|
||||
assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(-1);
|
||||
Install.single(TestApp.A1).commit();
|
||||
assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1);
|
||||
Install.single(TestApp.A2).setEnableRollback().setStaged().commit();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExpireSession_Phase2_VerifyInstall() throws Exception {
|
||||
assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2);
|
||||
RollbackManager rm = RollbackUtils.getRollbackManager();
|
||||
RollbackInfo rollback = getUniqueRollbackInfoForPackage(
|
||||
rm.getAvailableRollbacks(), TestApp.A);
|
||||
assertThat(rollback).isNotNull();
|
||||
assertThat(rollback).packagesContainsExactly(Rollback.from(TestApp.A2).to(TestApp.A1));
|
||||
assertThat(rollback.isStaged()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExpireSession_Phase3_VerifyRollback() throws Exception {
|
||||
RollbackManager rm = RollbackUtils.getRollbackManager();
|
||||
RollbackInfo rollback = getUniqueRollbackInfoForPackage(
|
||||
rm.getAvailableRollbacks(), TestApp.A);
|
||||
assertThat(rollback).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hasMainlineModule() throws Exception {
|
||||
String pkgName = getModuleMetadataPackageName();
|
||||
|
||||
@@ -21,13 +21,9 @@ import static com.android.tests.rollback.host.WatchdogEventLogger.Subject.assert
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static com.google.common.truth.Truth.assertWithMessage;
|
||||
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.junit.Assume.assumeTrue;
|
||||
|
||||
import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
|
||||
import com.android.ddmlib.Log;
|
||||
import com.android.tradefed.device.DeviceNotAvailableException;
|
||||
import com.android.tradefed.device.IFileEntry;
|
||||
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
|
||||
import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
|
||||
import com.android.tradefed.util.CommandResult;
|
||||
@@ -40,12 +36,7 @@ import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.io.File;
|
||||
import java.time.Instant;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Runs the staged rollback tests.
|
||||
@@ -72,17 +63,6 @@ public class StagedRollbackTest extends BaseHostJUnit4Test {
|
||||
private static final String APK_IN_APEX_TESTAPEX_NAME = "com.android.apex.apkrollback.test";
|
||||
private static final String TESTAPP_A = "com.android.cts.install.lib.testapp.A";
|
||||
|
||||
private static final String TEST_SUBDIR = "/subdir/";
|
||||
|
||||
private static final String TEST_FILENAME_1 = "test_file.txt";
|
||||
private static final String TEST_STRING_1 = "hello this is a test";
|
||||
private static final String TEST_FILENAME_2 = "another_file.txt";
|
||||
private static final String TEST_STRING_2 = "this is a different file";
|
||||
private static final String TEST_FILENAME_3 = "also.xyz";
|
||||
private static final String TEST_STRING_3 = "also\n a\n test\n string";
|
||||
private static final String TEST_FILENAME_4 = "one_more.test";
|
||||
private static final String TEST_STRING_4 = "once more unto the test";
|
||||
|
||||
private static final String REASON_APP_CRASH = "REASON_APP_CRASH";
|
||||
private static final String REASON_NATIVE_CRASH = "REASON_NATIVE_CRASH";
|
||||
|
||||
@@ -152,98 +132,6 @@ public class StagedRollbackTest extends BaseHostJUnit4Test {
|
||||
.that(getDevice().waitForDeviceNotAvailable(unit.toMillis(timeout))).isTrue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests watchdog triggered staged rollbacks involving only apks.
|
||||
*/
|
||||
@Test
|
||||
public void testBadApkOnly() throws Exception {
|
||||
runPhase("testBadApkOnly_Phase1_Install");
|
||||
getDevice().reboot();
|
||||
runPhase("testBadApkOnly_Phase2_VerifyInstall");
|
||||
|
||||
// Launch the app to crash to trigger rollback
|
||||
startActivity(TESTAPP_A);
|
||||
// Wait for reboot to happen
|
||||
waitForDeviceNotAvailable(2, TimeUnit.MINUTES);
|
||||
|
||||
getDevice().waitForDeviceAvailable();
|
||||
|
||||
runPhase("testBadApkOnly_Phase3_VerifyRollback");
|
||||
|
||||
assertThat(mLogger).eventOccurred(ROLLBACK_INITIATE, null, REASON_APP_CRASH, TESTAPP_A);
|
||||
assertThat(mLogger).eventOccurred(ROLLBACK_BOOT_TRIGGERED, null, null, null);
|
||||
assertThat(mLogger).eventOccurred(ROLLBACK_SUCCESS, null, null, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNativeWatchdogTriggersRollback() throws Exception {
|
||||
runPhase("testNativeWatchdogTriggersRollback_Phase1_Install");
|
||||
|
||||
// Reboot device to activate staged package
|
||||
getDevice().reboot();
|
||||
|
||||
runPhase("testNativeWatchdogTriggersRollback_Phase2_VerifyInstall");
|
||||
|
||||
// crash system_server enough times to trigger a rollback
|
||||
crashProcess("system_server", NATIVE_CRASHES_THRESHOLD);
|
||||
|
||||
// Rollback should be committed automatically now.
|
||||
// Give time for rollback to be committed. This could take a while,
|
||||
// because we need all of the following to happen:
|
||||
// 1. system_server comes back up and boot completes.
|
||||
// 2. Rollback health observer detects updatable crashing signal.
|
||||
// 3. Staged rollback session becomes ready.
|
||||
// 4. Device actually reboots.
|
||||
// So we give a generous timeout here.
|
||||
waitForDeviceNotAvailable(5, TimeUnit.MINUTES);
|
||||
getDevice().waitForDeviceAvailable();
|
||||
|
||||
// verify rollback committed
|
||||
runPhase("testNativeWatchdogTriggersRollback_Phase3_VerifyRollback");
|
||||
|
||||
assertThat(mLogger).eventOccurred(ROLLBACK_INITIATE, null, REASON_NATIVE_CRASH, null);
|
||||
assertThat(mLogger).eventOccurred(ROLLBACK_BOOT_TRIGGERED, null, null, null);
|
||||
assertThat(mLogger).eventOccurred(ROLLBACK_SUCCESS, null, null, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNativeWatchdogTriggersRollbackForAll() throws Exception {
|
||||
// This test requires committing multiple staged rollbacks
|
||||
assumeTrue(isCheckpointSupported());
|
||||
|
||||
// Install a package with rollback enabled.
|
||||
runPhase("testNativeWatchdogTriggersRollbackForAll_Phase1_InstallA");
|
||||
getDevice().reboot();
|
||||
|
||||
// Once previous staged install is applied, install another package
|
||||
runPhase("testNativeWatchdogTriggersRollbackForAll_Phase2_InstallB");
|
||||
getDevice().reboot();
|
||||
|
||||
// Verify the new staged install has also been applied successfully.
|
||||
runPhase("testNativeWatchdogTriggersRollbackForAll_Phase3_VerifyInstall");
|
||||
|
||||
// crash system_server enough times to trigger a rollback
|
||||
crashProcess("system_server", NATIVE_CRASHES_THRESHOLD);
|
||||
|
||||
// Rollback should be committed automatically now.
|
||||
// Give time for rollback to be committed. This could take a while,
|
||||
// because we need all of the following to happen:
|
||||
// 1. system_server comes back up and boot completes.
|
||||
// 2. Rollback health observer detects updatable crashing signal.
|
||||
// 3. Staged rollback session becomes ready.
|
||||
// 4. Device actually reboots.
|
||||
// So we give a generous timeout here.
|
||||
waitForDeviceNotAvailable(5, TimeUnit.MINUTES);
|
||||
getDevice().waitForDeviceAvailable();
|
||||
|
||||
// verify all available rollbacks have been committed
|
||||
runPhase("testNativeWatchdogTriggersRollbackForAll_Phase4_VerifyRollback");
|
||||
|
||||
assertThat(mLogger).eventOccurred(ROLLBACK_INITIATE, null, REASON_NATIVE_CRASH, null);
|
||||
assertThat(mLogger).eventOccurred(ROLLBACK_BOOT_TRIGGERED, null, null, null);
|
||||
assertThat(mLogger).eventOccurred(ROLLBACK_SUCCESS, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests rolling back user data where there are multiple rollbacks for that package.
|
||||
*/
|
||||
@@ -267,19 +155,6 @@ public class StagedRollbackTest extends BaseHostJUnit4Test {
|
||||
runPhase("testRollbackAllowlistedApp_Phase2_VerifyInstall");
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that userdata of apk-in-apex is restored when apex is rolled back.
|
||||
*/
|
||||
@Test
|
||||
public void testRollbackApexWithApk() throws Exception {
|
||||
pushTestApex();
|
||||
runPhase("testRollbackApexWithApk_Phase1_Install");
|
||||
getDevice().reboot();
|
||||
runPhase("testRollbackApexWithApk_Phase2_Rollback");
|
||||
getDevice().reboot();
|
||||
runPhase("testRollbackApexWithApk_Phase3_VerifyRollback");
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that RollbackPackageHealthObserver is observing apk-in-apex.
|
||||
*/
|
||||
@@ -305,242 +180,6 @@ public class StagedRollbackTest extends BaseHostJUnit4Test {
|
||||
assertThat(mLogger).eventOccurred(ROLLBACK_SUCCESS, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that data in DE_sys apex data directory is restored when apex is rolled back.
|
||||
*/
|
||||
@Test
|
||||
public void testRollbackApexDataDirectories_DeSys() throws Exception {
|
||||
List<String> before = getSnapshotDirectories("/data/misc/apexrollback");
|
||||
pushTestApex();
|
||||
|
||||
// Push files to apex data directory
|
||||
String oldFilePath1 = apexDataDirDeSys(APK_IN_APEX_TESTAPEX_NAME) + "/" + TEST_FILENAME_1;
|
||||
String oldFilePath2 =
|
||||
apexDataDirDeSys(APK_IN_APEX_TESTAPEX_NAME) + TEST_SUBDIR + TEST_FILENAME_2;
|
||||
runAsRoot(() -> {
|
||||
pushString(TEST_STRING_1, oldFilePath1);
|
||||
pushString(TEST_STRING_2, oldFilePath2);
|
||||
});
|
||||
|
||||
// Install new version of the APEX with rollback enabled
|
||||
runPhase("testRollbackApexDataDirectories_Phase1_Install");
|
||||
getDevice().reboot();
|
||||
|
||||
// Replace files in data directory
|
||||
String newFilePath3 = apexDataDirDeSys(APK_IN_APEX_TESTAPEX_NAME) + "/" + TEST_FILENAME_3;
|
||||
String newFilePath4 =
|
||||
apexDataDirDeSys(APK_IN_APEX_TESTAPEX_NAME) + TEST_SUBDIR + TEST_FILENAME_4;
|
||||
runAsRoot(() -> {
|
||||
getDevice().deleteFile(oldFilePath1);
|
||||
getDevice().deleteFile(oldFilePath2);
|
||||
pushString(TEST_STRING_3, newFilePath3);
|
||||
pushString(TEST_STRING_4, newFilePath4);
|
||||
});
|
||||
|
||||
// Roll back the APEX
|
||||
runPhase("testRollbackApexDataDirectories_Phase2_Rollback");
|
||||
getDevice().reboot();
|
||||
|
||||
// Verify that old files have been restored and new files are gone
|
||||
runAsRoot(() -> {
|
||||
assertFileContents(TEST_STRING_1, oldFilePath1);
|
||||
assertFileContents(TEST_STRING_2, oldFilePath2);
|
||||
assertFileNotExists(newFilePath3);
|
||||
assertFileNotExists(newFilePath4);
|
||||
});
|
||||
|
||||
// Verify snapshots are deleted after restoration
|
||||
List<String> after = getSnapshotDirectories("/data/misc/apexrollback");
|
||||
// Only check directories newly created during the test
|
||||
after.removeAll(before);
|
||||
// There should be only one /data/misc/apexrollback/<rollbackId> created during test
|
||||
assertThat(after).hasSize(1);
|
||||
assertDirectoryIsEmpty(after.get(0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that data in DE (user) apex data directory is restored when apex is rolled back.
|
||||
*/
|
||||
@Test
|
||||
public void testRollbackApexDataDirectories_DeUser() throws Exception {
|
||||
List<String> before = getSnapshotDirectories("/data/misc_de/0/apexrollback");
|
||||
pushTestApex();
|
||||
|
||||
// Push files to apex data directory
|
||||
String oldFilePath1 = apexDataDirDeUser(
|
||||
APK_IN_APEX_TESTAPEX_NAME, 0) + "/" + TEST_FILENAME_1;
|
||||
String oldFilePath2 =
|
||||
apexDataDirDeUser(APK_IN_APEX_TESTAPEX_NAME, 0) + TEST_SUBDIR + TEST_FILENAME_2;
|
||||
runAsRoot(() -> {
|
||||
pushString(TEST_STRING_1, oldFilePath1);
|
||||
pushString(TEST_STRING_2, oldFilePath2);
|
||||
});
|
||||
|
||||
// Install new version of the APEX with rollback enabled
|
||||
runPhase("testRollbackApexDataDirectories_Phase1_Install");
|
||||
getDevice().reboot();
|
||||
|
||||
// Replace files in data directory
|
||||
String newFilePath3 =
|
||||
apexDataDirDeUser(APK_IN_APEX_TESTAPEX_NAME, 0) + "/" + TEST_FILENAME_3;
|
||||
String newFilePath4 =
|
||||
apexDataDirDeUser(APK_IN_APEX_TESTAPEX_NAME, 0) + TEST_SUBDIR + TEST_FILENAME_4;
|
||||
runAsRoot(() -> {
|
||||
getDevice().deleteFile(oldFilePath1);
|
||||
getDevice().deleteFile(oldFilePath2);
|
||||
pushString(TEST_STRING_3, newFilePath3);
|
||||
pushString(TEST_STRING_4, newFilePath4);
|
||||
});
|
||||
|
||||
// Roll back the APEX
|
||||
runPhase("testRollbackApexDataDirectories_Phase2_Rollback");
|
||||
getDevice().reboot();
|
||||
|
||||
// Verify that old files have been restored and new files are gone
|
||||
runAsRoot(() -> {
|
||||
assertFileContents(TEST_STRING_1, oldFilePath1);
|
||||
assertFileContents(TEST_STRING_2, oldFilePath2);
|
||||
assertFileNotExists(newFilePath3);
|
||||
assertFileNotExists(newFilePath4);
|
||||
});
|
||||
|
||||
// Verify snapshots are deleted after restoration
|
||||
List<String> after = getSnapshotDirectories("/data/misc_de/0/apexrollback");
|
||||
// Only check directories newly created during the test
|
||||
after.removeAll(before);
|
||||
// There should be only one /data/misc_de/0/apexrollback/<rollbackId> created during test
|
||||
assertThat(after).hasSize(1);
|
||||
assertDirectoryIsEmpty(after.get(0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that data in CE apex data directory is restored when apex is rolled back.
|
||||
*/
|
||||
@Test
|
||||
public void testRollbackApexDataDirectories_Ce() throws Exception {
|
||||
List<String> before = getSnapshotDirectories("/data/misc_ce/0/apexrollback");
|
||||
pushTestApex();
|
||||
|
||||
// Push files to apex data directory
|
||||
String oldFilePath1 = apexDataDirCe(APK_IN_APEX_TESTAPEX_NAME, 0) + "/" + TEST_FILENAME_1;
|
||||
String oldFilePath2 =
|
||||
apexDataDirCe(APK_IN_APEX_TESTAPEX_NAME, 0) + TEST_SUBDIR + TEST_FILENAME_2;
|
||||
runAsRoot(() -> {
|
||||
pushString(TEST_STRING_1, oldFilePath1);
|
||||
pushString(TEST_STRING_2, oldFilePath2);
|
||||
});
|
||||
|
||||
// Install new version of the APEX with rollback enabled
|
||||
runPhase("testRollbackApexDataDirectories_Phase1_Install");
|
||||
getDevice().reboot();
|
||||
|
||||
// Replace files in data directory
|
||||
String newFilePath3 = apexDataDirCe(APK_IN_APEX_TESTAPEX_NAME, 0) + "/" + TEST_FILENAME_3;
|
||||
String newFilePath4 =
|
||||
apexDataDirCe(APK_IN_APEX_TESTAPEX_NAME, 0) + TEST_SUBDIR + TEST_FILENAME_4;
|
||||
runAsRoot(() -> {
|
||||
getDevice().deleteFile(oldFilePath1);
|
||||
getDevice().deleteFile(oldFilePath2);
|
||||
pushString(TEST_STRING_3, newFilePath3);
|
||||
pushString(TEST_STRING_4, newFilePath4);
|
||||
});
|
||||
|
||||
// Roll back the APEX
|
||||
runPhase("testRollbackApexDataDirectories_Phase2_Rollback");
|
||||
getDevice().reboot();
|
||||
|
||||
// Verify that old files have been restored and new files are gone
|
||||
runAsRoot(() -> {
|
||||
assertFileContents(TEST_STRING_1, oldFilePath1);
|
||||
assertFileContents(TEST_STRING_2, oldFilePath2);
|
||||
assertFileNotExists(newFilePath3);
|
||||
assertFileNotExists(newFilePath4);
|
||||
});
|
||||
|
||||
// Verify snapshots are deleted after restoration
|
||||
List<String> after = getSnapshotDirectories("/data/misc_ce/0/apexrollback");
|
||||
// Only check directories newly created during the test
|
||||
after.removeAll(before);
|
||||
// There should be only one /data/misc_ce/0/apexrollback/<rollbackId> created during test
|
||||
assertThat(after).hasSize(1);
|
||||
assertDirectoryIsEmpty(after.get(0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that data in DE apk data directory is restored when apk is rolled back.
|
||||
*/
|
||||
@Test
|
||||
public void testRollbackApkDataDirectories_De() throws Exception {
|
||||
// Install version 1 of TESTAPP_A
|
||||
runPhase("testRollbackApkDataDirectories_Phase1_InstallV1");
|
||||
|
||||
// Push files to apk data directory
|
||||
String oldFilePath1 = apkDataDirDe(TESTAPP_A, 0) + "/" + TEST_FILENAME_1;
|
||||
String oldFilePath2 = apkDataDirDe(TESTAPP_A, 0) + TEST_SUBDIR + TEST_FILENAME_2;
|
||||
runAsRoot(() -> {
|
||||
pushString(TEST_STRING_1, oldFilePath1);
|
||||
pushString(TEST_STRING_2, oldFilePath2);
|
||||
});
|
||||
|
||||
// Install version 2 of TESTAPP_A with rollback enabled
|
||||
runPhase("testRollbackApkDataDirectories_Phase2_InstallV2");
|
||||
getDevice().reboot();
|
||||
|
||||
// Replace files in data directory
|
||||
String newFilePath3 = apkDataDirDe(TESTAPP_A, 0) + "/" + TEST_FILENAME_3;
|
||||
String newFilePath4 = apkDataDirDe(TESTAPP_A, 0) + TEST_SUBDIR + TEST_FILENAME_4;
|
||||
runAsRoot(() -> {
|
||||
getDevice().deleteFile(oldFilePath1);
|
||||
getDevice().deleteFile(oldFilePath2);
|
||||
pushString(TEST_STRING_3, newFilePath3);
|
||||
pushString(TEST_STRING_4, newFilePath4);
|
||||
});
|
||||
|
||||
// Roll back the APK
|
||||
runPhase("testRollbackApkDataDirectories_Phase3_Rollback");
|
||||
getDevice().reboot();
|
||||
|
||||
// Verify that old files have been restored and new files are gone
|
||||
runAsRoot(() -> {
|
||||
assertFileContents(TEST_STRING_1, oldFilePath1);
|
||||
assertFileContents(TEST_STRING_2, oldFilePath2);
|
||||
assertFileNotExists(newFilePath3);
|
||||
assertFileNotExists(newFilePath4);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExpireApexRollback() throws Exception {
|
||||
List<String> before = getSnapshotDirectories("/data/misc_ce/0/apexrollback");
|
||||
pushTestApex();
|
||||
|
||||
// Push files to apex data directory
|
||||
String oldFilePath1 = apexDataDirCe(APK_IN_APEX_TESTAPEX_NAME, 0) + "/" + TEST_FILENAME_1;
|
||||
String oldFilePath2 =
|
||||
apexDataDirCe(APK_IN_APEX_TESTAPEX_NAME, 0) + TEST_SUBDIR + TEST_FILENAME_2;
|
||||
runAsRoot(() -> {
|
||||
pushString(TEST_STRING_1, oldFilePath1);
|
||||
pushString(TEST_STRING_2, oldFilePath2);
|
||||
});
|
||||
|
||||
// Install new version of the APEX with rollback enabled
|
||||
runPhase("testRollbackApexDataDirectories_Phase1_Install");
|
||||
getDevice().reboot();
|
||||
|
||||
List<String> after = getSnapshotDirectories("/data/misc_ce/0/apexrollback");
|
||||
// Only check directories newly created during the test
|
||||
after.removeAll(before);
|
||||
// There should be only one /data/misc_ce/0/apexrollback/<rollbackId> created during test
|
||||
assertThat(after).hasSize(1);
|
||||
// Expire all rollbacks and check CE snapshot directories are deleted
|
||||
runPhase("expireRollbacks");
|
||||
runAsRoot(() -> {
|
||||
for (String dir : after) {
|
||||
assertFileNotExists(dir);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that packages are monitored across multiple reboots.
|
||||
*/
|
||||
@@ -565,27 +204,6 @@ public class StagedRollbackTest extends BaseHostJUnit4Test {
|
||||
runPhase("testWatchdogMonitorsAcrossReboots_Phase3_VerifyRollback");
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests an available rollback shouldn't be deleted when its session expires.
|
||||
*/
|
||||
@Test
|
||||
public void testExpireSession() throws Exception {
|
||||
runPhase("testExpireSession_Phase1_Install");
|
||||
getDevice().reboot();
|
||||
runPhase("testExpireSession_Phase2_VerifyInstall");
|
||||
|
||||
// Advance system clock by 7 days to expire the staged session
|
||||
Instant t1 = Instant.ofEpochMilli(getDevice().getDeviceDate());
|
||||
Instant t2 = t1.plusMillis(TimeUnit.DAYS.toMillis(7));
|
||||
runAsRoot(() -> getDevice().setDate(Date.from(t2)));
|
||||
|
||||
// Somehow we need to wait for a while before reboot. Otherwise the change to the
|
||||
// system clock will be reset after reboot.
|
||||
Thread.sleep(3000);
|
||||
getDevice().reboot();
|
||||
runPhase("testExpireSession_Phase3_VerifyRollback");
|
||||
}
|
||||
|
||||
private void pushTestApex() throws Exception {
|
||||
CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(getBuild());
|
||||
final String fileName = APK_IN_APEX_TESTAPEX_NAME + "_v1.apex";
|
||||
@@ -600,101 +218,20 @@ public class StagedRollbackTest extends BaseHostJUnit4Test {
|
||||
getDevice().reboot();
|
||||
}
|
||||
|
||||
private void pushString(String contents, String path) throws Exception {
|
||||
assertWithMessage("Failed to push file to device, content=%s path=%s", contents, path)
|
||||
.that(getDevice().pushString(contents, path)).isTrue();
|
||||
}
|
||||
|
||||
private void assertFileContents(String expectedContents, String path) throws Exception {
|
||||
String actualContents = getDevice().pullFileContents(path);
|
||||
assertWithMessage("Failed to retrieve file=%s", path).that(actualContents).isNotNull();
|
||||
assertWithMessage("Mismatched file contents, path=%s", path)
|
||||
.that(actualContents).isEqualTo(expectedContents);
|
||||
}
|
||||
|
||||
private void assertFileNotExists(String path) throws Exception {
|
||||
assertWithMessage("File shouldn't exist, path=%s", path)
|
||||
.that(getDevice().getFileEntry(path)).isNull();
|
||||
}
|
||||
|
||||
private static String apexDataDirDeSys(String apexName) {
|
||||
return String.format("/data/misc/apexdata/%s", apexName);
|
||||
}
|
||||
|
||||
private static String apexDataDirDeUser(String apexName, int userId) {
|
||||
return String.format("/data/misc_de/%d/apexdata/%s", userId, apexName);
|
||||
}
|
||||
|
||||
private static String apexDataDirCe(String apexName, int userId) {
|
||||
return String.format("/data/misc_ce/%d/apexdata/%s", userId, apexName);
|
||||
}
|
||||
|
||||
private static String apkDataDirDe(String apexName, int userId) {
|
||||
return String.format("/data/user_de/%d/%s", userId, apexName);
|
||||
}
|
||||
|
||||
private List<String> getSnapshotDirectories(String baseDir) throws Exception {
|
||||
try {
|
||||
getDevice().enableAdbRoot();
|
||||
IFileEntry f = getDevice().getFileEntry(baseDir);
|
||||
if (f == null) {
|
||||
Log.d(TAG, "baseDir doesn't exist: " + baseDir);
|
||||
return Collections.EMPTY_LIST;
|
||||
}
|
||||
List<String> list = f.getChildren(false)
|
||||
.stream().filter(entry -> entry.getName().matches("\\d+(-prerestore)?"))
|
||||
.map(entry -> entry.getFullPath())
|
||||
.collect(Collectors.toList());
|
||||
Log.d(TAG, "getSnapshotDirectories=" + list);
|
||||
return list;
|
||||
} finally {
|
||||
getDevice().disableAdbRoot();
|
||||
}
|
||||
}
|
||||
|
||||
private void assertDirectoryIsEmpty(String path) throws Exception {
|
||||
try {
|
||||
getDevice().enableAdbRoot();
|
||||
IFileEntry file = getDevice().getFileEntry(path);
|
||||
assertWithMessage("Not a directory: " + path).that(file.isDirectory()).isTrue();
|
||||
assertWithMessage("Directory not empty: " + path)
|
||||
.that(file.getChildren(false)).isEmpty();
|
||||
} catch (DeviceNotAvailableException e) {
|
||||
fail("Can't access directory: " + path);
|
||||
} finally {
|
||||
getDevice().disableAdbRoot();
|
||||
}
|
||||
}
|
||||
|
||||
private void startActivity(String packageName) throws Exception {
|
||||
String cmd = "am start -S -a android.intent.action.MAIN "
|
||||
+ "-c android.intent.category.LAUNCHER " + packageName;
|
||||
getDevice().executeShellCommand(cmd);
|
||||
}
|
||||
|
||||
private void crashProcess(String processName, int numberOfCrashes) throws Exception {
|
||||
String pid = "";
|
||||
String lastPid = "invalid";
|
||||
for (int i = 0; i < numberOfCrashes; ++i) {
|
||||
// This condition makes sure before we kill the process, the process is running AND
|
||||
// the last crash was finished.
|
||||
while ("".equals(pid) || lastPid.equals(pid)) {
|
||||
pid = getDevice().executeShellCommand("pidof " + processName);
|
||||
}
|
||||
getDevice().executeShellCommand("kill " + pid);
|
||||
lastPid = pid;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isCheckpointSupported() throws Exception {
|
||||
try {
|
||||
runPhase("isCheckpointSupported");
|
||||
return true;
|
||||
} catch (AssertionError ignore) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* True if this build has mainline modules installed.
|
||||
*/
|
||||
@@ -706,18 +243,4 @@ public class StagedRollbackTest extends BaseHostJUnit4Test {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
private interface ExceptionalRunnable {
|
||||
void run() throws Exception;
|
||||
}
|
||||
|
||||
private void runAsRoot(ExceptionalRunnable runnable) throws Exception {
|
||||
try {
|
||||
getDevice().enableAdbRoot();
|
||||
runnable.run();
|
||||
} finally {
|
||||
getDevice().disableAdbRoot();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user