Merge changes I10355143,I85adb8c3 into rvc-dev

* changes:
  Run expiration when rollback lifetime is changed. DO NOT MERGE
  Add logs for debugging
This commit is contained in:
JW Wang
2020-04-01 02:49:40 +00:00
committed by Android (Google) Code Review
2 changed files with 68 additions and 27 deletions

View File

@@ -137,6 +137,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
private final Installer mInstaller; private final Installer mInstaller;
private final RollbackPackageHealthObserver mPackageHealthObserver; private final RollbackPackageHealthObserver mPackageHealthObserver;
private final AppDataRollbackHelper mAppDataRollbackHelper; private final AppDataRollbackHelper mAppDataRollbackHelper;
private final Runnable mRunExpiration = this::runExpiration;
// The # of milli-seconds to sleep for each received ACTION_PACKAGE_ENABLE_ROLLBACK. // The # of milli-seconds to sleep for each received ACTION_PACKAGE_ENABLE_ROLLBACK.
// Used by #blockRollbackManager to test timeout in enabling rollbacks. // Used by #blockRollbackManager to test timeout in enabling rollbacks.
@@ -515,6 +516,8 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
if (mRollbackLifetimeDurationInMillis < 0) { if (mRollbackLifetimeDurationInMillis < 0) {
mRollbackLifetimeDurationInMillis = DEFAULT_ROLLBACK_LIFETIME_DURATION_MILLIS; mRollbackLifetimeDurationInMillis = DEFAULT_ROLLBACK_LIFETIME_DURATION_MILLIS;
} }
Slog.d(TAG, "mRollbackLifetimeDurationInMillis=" + mRollbackLifetimeDurationInMillis);
runExpiration();
} }
@AnyThread @AnyThread
@@ -643,6 +646,8 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
// Schedules future expiration as appropriate. // Schedules future expiration as appropriate.
@WorkerThread @WorkerThread
private void runExpiration() { private void runExpiration() {
getHandler().removeCallbacks(mRunExpiration);
Instant now = Instant.now(); Instant now = Instant.now();
Instant oldest = null; Instant oldest = null;
synchronized (mLock) { synchronized (mLock) {
@@ -656,9 +661,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
if (!now.isBefore( if (!now.isBefore(
rollbackTimestamp rollbackTimestamp
.plusMillis(mRollbackLifetimeDurationInMillis))) { .plusMillis(mRollbackLifetimeDurationInMillis))) {
if (LOCAL_LOGV) { Slog.i(TAG, "runExpiration id=" + rollback.info.getRollbackId());
Slog.v(TAG, "runExpiration id=" + rollback.info.getRollbackId());
}
iter.remove(); iter.remove();
rollback.delete(mAppDataRollbackHelper); rollback.delete(mAppDataRollbackHelper);
} else if (oldest == null || oldest.isAfter(rollbackTimestamp)) { } else if (oldest == null || oldest.isAfter(rollbackTimestamp)) {
@@ -668,20 +671,12 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
} }
if (oldest != null) { if (oldest != null) {
scheduleExpiration(now.until(oldest.plusMillis(mRollbackLifetimeDurationInMillis), long delay = now.until(
ChronoUnit.MILLIS)); oldest.plusMillis(mRollbackLifetimeDurationInMillis), ChronoUnit.MILLIS);
getHandler().postDelayed(mRunExpiration, delay);
} }
} }
/**
* Schedules an expiration check to be run after the given duration in
* milliseconds has gone by.
*/
@AnyThread
private void scheduleExpiration(long duration) {
getHandler().postDelayed(() -> runExpiration(), duration);
}
@AnyThread @AnyThread
private Handler getHandler() { private Handler getHandler() {
return mHandlerThread.getThreadHandler(); return mHandlerThread.getThreadHandler();
@@ -1170,9 +1165,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
@WorkerThread @WorkerThread
@GuardedBy("rollback.getLock") @GuardedBy("rollback.getLock")
private void makeRollbackAvailable(Rollback rollback) { private void makeRollbackAvailable(Rollback rollback) {
if (LOCAL_LOGV) { Slog.i(TAG, "makeRollbackAvailable id=" + rollback.info.getRollbackId());
Slog.v(TAG, "makeRollbackAvailable id=" + rollback.info.getRollbackId());
}
rollback.makeAvailable(); rollback.makeAvailable();
// TODO(zezeozue): Provide API to explicitly start observing instead // TODO(zezeozue): Provide API to explicitly start observing instead
@@ -1182,7 +1175,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
// prepare to rollback if packages crashes too frequently. // prepare to rollback if packages crashes too frequently.
mPackageHealthObserver.startObservingHealth(rollback.getPackageNames(), mPackageHealthObserver.startObservingHealth(rollback.getPackageNames(),
mRollbackLifetimeDurationInMillis); mRollbackLifetimeDurationInMillis);
scheduleExpiration(mRollbackLifetimeDurationInMillis); runExpiration();
} }
/* /*

View File

@@ -434,6 +434,53 @@ public class RollbackTest {
} }
} }
/**
* 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 * Test that changing time on device does not affect the duration of time that we keep
* rollback available * rollback available
@@ -487,23 +534,24 @@ public class RollbackTest {
// Wait until rollback for app A has expired // Wait until rollback for app A has expired
// This will trigger an expiration run that should expire app A but not B // This will trigger an expiration run that should expire app A but not B
Thread.sleep(expirationTime / 2); Thread.sleep(expirationTime / 2);
RollbackInfo rollback = RollbackInfo rollbackA =
getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(), TestApp.A); getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(), TestApp.A);
assertThat(rollback).isNull(); Log.i(TAG, "Checking if the rollback for TestApp.A is null");
// Rollback for app B should not be expired // Rollback for app B should not be expired
rollback = getUniqueRollbackInfoForPackage( RollbackInfo rollbackB1 = getUniqueRollbackInfoForPackage(
rm.getAvailableRollbacks(), TestApp.B); rm.getAvailableRollbacks(), TestApp.B);
assertThat(rollback).isNotNull();
assertThat(rollback).packagesContainsExactly(
Rollback.from(TestApp.B2).to(TestApp.B1));
// Wait until rollback for app B has expired // Wait until rollback for app B has expired
Thread.sleep(expirationTime / 2); Thread.sleep(expirationTime / 2);
rollback = getUniqueRollbackInfoForPackage( RollbackInfo rollbackB2 = getUniqueRollbackInfoForPackage(
rm.getAvailableRollbacks(), TestApp.B); rm.getAvailableRollbacks(), TestApp.B);
// Rollback should be expired by now
assertThat(rollback).isNull(); assertThat(rollbackA).isNull();
assertThat(rollbackB1).isNotNull();
assertThat(rollbackB1).packagesContainsExactly(
Rollback.from(TestApp.B2).to(TestApp.B1));
assertThat(rollbackB2).isNull();
} finally { } finally {
RollbackUtils.forwardTimeBy(-expirationTime); RollbackUtils.forwardTimeBy(-expirationTime);
} }