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

Commit 9e57ecb5 authored by Zimuzo's avatar Zimuzo Committed by Zimuzo Ezeozue
Browse files

Allow non-mainline package rollbacks

If3aaf8f2c454f45b9d79c9dae5a21d356e4cf029 prevented rolling back
packages that were not part of a mainline update. This made it
difficult to test and the auto PackageWatchdog test was ignored in the
meantime. We are now allowing non-mainling package rollbacks and
re-enabling the test.

I8dd7e6d1e144251830108c58f4a752c411d7295b introduced a refactoring bug
when rolling back packages, the module metadata provider was rolled
back instead. This was not caught because the test was ignored.

Test: atest RollbackTest
Bug: 120598832

Change-Id: I8fcc9492a05f0b3788ba4762ad3e3e5ac086d43b
parent 12d08fd3
Loading
Loading
Loading
Loading
+36 −29
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import android.content.rollback.RollbackManager;
import android.os.Handler;
import android.os.HandlerThread;
import android.text.TextUtils;
import android.util.Pair;
import android.util.Slog;
import android.util.StatsLog;

@@ -64,10 +65,8 @@ public final class RollbackPackageHealthObserver implements PackageHealthObserve
            return PackageHealthObserverImpact.USER_IMPACT_NONE;
        }

        RollbackInfo rollback =
                getAvailableMainlineRollback(mContext.getSystemService(RollbackManager.class),
                        failedPackage, moduleMetadataPackage);
        if (rollback == null) {
        if (getAvailableRollback(mContext.getSystemService(RollbackManager.class),
                        failedPackage, moduleMetadataPackage) == null) {
            // Don't handle the notification, no rollbacks available for the package
            return PackageHealthObserverImpact.USER_IMPACT_NONE;
        }
@@ -84,20 +83,27 @@ public final class RollbackPackageHealthObserver implements PackageHealthObserve
        }

        RollbackManager rollbackManager = mContext.getSystemService(RollbackManager.class);
        RollbackInfo rollback = getAvailableMainlineRollback(rollbackManager,
        Pair<RollbackInfo, Boolean> rollbackPair = getAvailableRollback(rollbackManager,
                failedPackage, moduleMetadataPackage);
        if (rollback == null) {
            Slog.w(TAG, "Expected rollback but no mainline rollback found for package: [ "
        if (rollbackPair == null) {
            Slog.w(TAG, "Expected rollback but no valid rollback found for package: [ "
                    + failedPackage.getPackageName() + "] with versionCode: ["
                    + failedPackage.getVersionCode() + "]");
            return false;
        }
        RollbackInfo rollback = rollbackPair.first;
        // We only log mainline package rollbacks, so check if rollback contains the
        // module metadata provider, if it does, the rollback is a mainline rollback
        boolean hasModuleMetadataPackage = rollbackPair.second;

        if (hasModuleMetadataPackage) {
            StatsLog.write(StatsLog.WATCHDOG_ROLLBACK_OCCURRED,
                    StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_INITIATE,
                    moduleMetadataPackage.getPackageName(),
                    moduleMetadataPackage.getVersionCode());
        }
        LocalIntentReceiver rollbackReceiver = new LocalIntentReceiver((Intent result) -> {
            if (hasModuleMetadataPackage) {
                int status = result.getIntExtra(RollbackManager.EXTRA_STATUS,
                        RollbackManager.STATUS_FAILURE);
                if (status == RollbackManager.STATUS_SUCCESS) {
@@ -111,11 +117,12 @@ public final class RollbackPackageHealthObserver implements PackageHealthObserve
                            moduleMetadataPackage.getPackageName(),
                            moduleMetadataPackage.getVersionCode());
                }
            }
        });

        mHandler.post(() ->
                rollbackManager.commitRollback(rollback.getRollbackId(),
                    Collections.singletonList(moduleMetadataPackage),
                    Collections.singletonList(failedPackage),
                    rollbackReceiver.getIntentSender()));
        // Assume rollback executed successfully
        return true;
@@ -134,7 +141,7 @@ public final class RollbackPackageHealthObserver implements PackageHealthObserve
        PackageWatchdog.getInstance(mContext).startObservingHealth(this, packages, durationMs);
    }

    private RollbackInfo getAvailableMainlineRollback(RollbackManager rollbackManager,
    private Pair<RollbackInfo, Boolean> getAvailableRollback(RollbackManager rollbackManager,
            VersionedPackage failedPackage, VersionedPackage moduleMetadataPackage) {
        for (RollbackInfo rollback : rollbackManager.getAvailableRollbacks()) {
            // We only rollback mainline packages, so check if rollback contains the
@@ -149,8 +156,8 @@ public final class RollbackPackageHealthObserver implements PackageHealthObserve
                        && packageRollback.getVersionRolledBackFrom().getVersionCode()
                        == failedPackage.getVersionCode();
            }
            if (hasModuleMetadataPackage && hasFailedPackage) {
                return rollback;
            if (hasFailedPackage) {
                return new Pair<RollbackInfo, Boolean>(rollback, hasModuleMetadataPackage);
            }
        }
        return null;
@@ -159,7 +166,7 @@ public final class RollbackPackageHealthObserver implements PackageHealthObserve
    private VersionedPackage getModuleMetadataPackage() {
        String packageName = mContext.getResources().getString(
                R.string.config_defaultModuleMetadataProvider);
        if (!TextUtils.isEmpty(packageName)) {
        if (TextUtils.isEmpty(packageName)) {
            return null;
        }

+0 −4
Original line number Diff line number Diff line
@@ -37,7 +37,6 @@ import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.fail;

import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
@@ -629,12 +628,9 @@ public class RollbackTest {
        assertEquals(versionRolledBackTo, info.getVersionRolledBackTo().getLongVersionCode());
    }

    // TODO: Allow installing test app along atomically with module metadata package so that
    // a failed test app will be flagged as a failed mainline app
    /**
     * Test bad update automatic rollback.
     */
    @Ignore
    @Test
    public void testBadUpdateRollback() throws Exception {
        BroadcastReceiver crashCountReceiver = null;