Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 72f8a2e2 authored by JW Wang's avatar JW Wang Committed by Automerger Merge Worker
Browse files

Run expiration when rollback lifetime is changed. DO NOT MERGE am: 9f8407b0 am: 8121699d

Change-Id: I552c794a34477ad11aaf952de0cdce8b77e6bf4c
parents 3939238e 8121699d
Loading
Loading
Loading
Loading
+8 −12
Original line number Diff line number Diff line
@@ -137,6 +137,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
    private final Installer mInstaller;
    private final RollbackPackageHealthObserver mPackageHealthObserver;
    private final AppDataRollbackHelper mAppDataRollbackHelper;
    private final Runnable mRunExpiration = this::runExpiration;

    // The # of milli-seconds to sleep for each received ACTION_PACKAGE_ENABLE_ROLLBACK.
    // Used by #blockRollbackManager to test timeout in enabling rollbacks.
@@ -516,6 +517,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
            mRollbackLifetimeDurationInMillis = DEFAULT_ROLLBACK_LIFETIME_DURATION_MILLIS;
        }
        Slog.d(TAG, "mRollbackLifetimeDurationInMillis=" + mRollbackLifetimeDurationInMillis);
        runExpiration();
    }

    @AnyThread
@@ -644,6 +646,8 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
    // Schedules future expiration as appropriate.
    @WorkerThread
    private void runExpiration() {
        getHandler().removeCallbacks(mRunExpiration);

        Instant now = Instant.now();
        Instant oldest = null;
        synchronized (mLock) {
@@ -667,20 +671,12 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
        }

        if (oldest != null) {
            scheduleExpiration(now.until(oldest.plusMillis(mRollbackLifetimeDurationInMillis),
                        ChronoUnit.MILLIS));
            long delay = now.until(
                    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
    private Handler getHandler() {
        return mHandlerThread.getThreadHandler();
@@ -1179,7 +1175,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
        // prepare to rollback if packages crashes too frequently.
        mPackageHealthObserver.startObservingHealth(rollback.getPackageNames(),
                mRollbackLifetimeDurationInMillis);
        scheduleExpiration(mRollbackLifetimeDurationInMillis);
        runExpiration();
    }

    /*
+47 −0
Original line number Diff line number Diff line
@@ -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
     * rollback available