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:
@@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user