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

Commit 7ef81043 authored by shafik's avatar shafik Committed by Bill Lin
Browse files

Test Native Watchdog triggers RollbackManager rollback

Test flow:
    * Staged install com.google.android.modulemetadata
    * Crash a native process (apexd) enough times to trigger a rollback
    * Wait for device reboot (automatically)
    * Assert rollback of com.google.android.modulemetadata has been
    committed

Test: atest StagedRollbackTest#testNativeWatchdogTriggersRollback
Bug: 135864628
Change-Id: I5176cc7890e251e7ccc10abdfcfee3a5190721b2
Merged-In: Ibe726c140939190adb3db9c18b3b442ba59548a3
parent b9f15217
Loading
Loading
Loading
Loading
+63 −4
Original line number Diff line number Diff line
@@ -21,14 +21,19 @@ import static com.android.cts.rollback.lib.RollbackUtils.getUniqueRollbackInfoFo

import static com.google.common.truth.Truth.assertThat;

import static org.junit.Assert.fail;

import android.Manifest;
import android.annotation.Nullable;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageInstaller;
import android.content.rollback.RollbackInfo;
import android.content.rollback.RollbackManager;
import android.text.TextUtils;

import androidx.test.InstrumentationRegistry;

@@ -39,8 +44,7 @@ import com.android.cts.install.lib.TestApp;
import com.android.cts.install.lib.Uninstall;
import com.android.cts.rollback.lib.Rollback;
import com.android.cts.rollback.lib.RollbackUtils;

import static org.junit.Assert.fail;
import com.android.internal.R;

import org.junit.After;
import org.junit.Before;
@@ -59,10 +63,11 @@ import org.junit.runners.JUnit4;
@RunWith(JUnit4.class)
public class StagedRollbackTest {

    private static final String TAG = "RollbackTest";
    private static final String NETWORK_STACK_CONNECTOR_CLASS =
            "android.net.INetworkStackConnector";

    private static final String MODULE_META_DATA_PACKAGE = getModuleMetadataPackageName();

    /**
     * Adopts common shell permissions needed for rollback tests.
     */
@@ -182,6 +187,21 @@ public class StagedRollbackTest {
                        networkStack)).isNull();
    }

    @Test
    public void installModuleMetadataPackage() throws Exception {
        resetModuleMetadataPackage();
        Context context = InstrumentationRegistry.getContext();
        PackageInfo metadataPackageInfo = context.getPackageManager().getPackageInfo(
                MODULE_META_DATA_PACKAGE, 0);
        String metadataApkPath = metadataPackageInfo.applicationInfo.sourceDir;
        assertThat(metadataApkPath).isNotNull();
        assertThat(metadataApkPath).isNotEqualTo("");

        runShellCommand("pm install "
                + "-r --enable-rollback --staged --wait "
                + metadataApkPath);
    }

    @Test
    public void assertNetworkStackRollbackAvailable() throws Exception {
        RollbackManager rm = RollbackUtils.getRollbackManager();
@@ -203,6 +223,20 @@ public class StagedRollbackTest {
                        getNetworkStackPackageName())).isNull();
    }

    @Test
    public void assertModuleMetadataRollbackAvailable() throws Exception {
        RollbackManager rm = RollbackUtils.getRollbackManager();
        assertThat(getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(),
                        MODULE_META_DATA_PACKAGE)).isNotNull();
    }

    @Test
    public void assertModuleMetadataRollbackCommitted() throws Exception {
        RollbackManager rm = RollbackUtils.getRollbackManager();
        assertThat(getUniqueRollbackInfoForPackage(rm.getRecentlyCommittedRollbacks(),
                        MODULE_META_DATA_PACKAGE)).isNotNull();
    }

    private String getNetworkStackPackageName() {
        Intent intent = new Intent(NETWORK_STACK_CONNECTOR_CLASS);
        ComponentName comp = intent.resolveSystemService(
@@ -245,4 +279,29 @@ public class StagedRollbackTest {
        InstallUtils.processUserData(TestApp.A);
        Uninstall.packages(TestApp.A);
    }

    @Nullable
    private static String getModuleMetadataPackageName() {
        String packageName = InstrumentationRegistry.getContext().getResources().getString(
                R.string.config_defaultModuleMetadataProvider);
        if (TextUtils.isEmpty(packageName)) {
            return null;
        }
        return packageName;
    }

    private void resetModuleMetadataPackage() {
        RollbackManager rm = RollbackUtils.getRollbackManager();

        assertThat(MODULE_META_DATA_PACKAGE).isNotNull();
        rm.expireRollbackForPackage(MODULE_META_DATA_PACKAGE);

        assertThat(getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(),
                MODULE_META_DATA_PACKAGE)).isNull();
    }

    private void runShellCommand(String cmd) {
        InstrumentationRegistry.getInstrumentation().getUiAutomation()
                .executeShellCommand(cmd);
    }
}
+39 −0
Original line number Diff line number Diff line
@@ -34,6 +34,8 @@ import org.junit.runner.RunWith;
 */
@RunWith(DeviceJUnit4ClassRunner.class)
public class StagedRollbackTest extends BaseHostJUnit4Test {
    private static final int NATIVE_CRASHES_THRESHOLD = 5;

    /**
     * Runs the given phase of a test by calling into the device.
     * Throws an exception if the test phase fails.
@@ -84,6 +86,29 @@ public class StagedRollbackTest extends BaseHostJUnit4Test {
        runPhase("testBadApkOnlyConfirmRollback");
    }

    @Test
    public void testNativeWatchdogTriggersRollback() throws Exception {
        //Stage install ModuleMetadata package - this simulates a Mainline module update
        runPhase("installModuleMetadataPackage");

        // Reboot device to activate staged package
        getDevice().reboot();
        getDevice().waitForDeviceAvailable();

        runPhase("assertModuleMetadataRollbackAvailable");

        // 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
        assertTrue(getDevice().waitForDeviceNotAvailable(60000));
        getDevice().waitForDeviceAvailable();

        // verify rollback committed
        runPhase("assertModuleMetadataRollbackCommitted");
    }

    /**
     * Tests failed network health check triggers watchdog staged rollbacks.
     */
@@ -179,6 +204,20 @@ public class StagedRollbackTest extends BaseHostJUnit4Test {
        runPhase("testPreviouslyAbandonedRollbacksCheckUserdataRollback");
    }

    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 String getNetworkStackPath() throws DeviceNotAvailableException {
        // Find the NetworkStack path (can be NetworkStack.apk or NetworkStackNext.apk)
        return getDevice().executeShellCommand("ls /system/priv-app/NetworkStack*/*.apk");