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

Commit c1a694dd authored by Zimuzo's avatar Zimuzo Committed by android-build-merger
Browse files

Merge "Add network health check watchdog triggered rollback tests" into qt-dev

am: 80b53bd6

Change-Id: I760b8f0d948702a51b96c3aaffa6ccb268b891fe
parents cc3bf641 80b53bd6
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -95,7 +95,7 @@ android_test {
        ":RollbackTestAppASplitV2",
    ],
    test_config: "RollbackTest.xml",
    sdk_version: "test_current",
    // TODO: sdk_version: "test_current" when Intent#resolveSystemservice is TestApi
}

java_test_host {
+24 −5
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageInstaller;
import android.content.pm.PackageManager;
@@ -82,13 +83,31 @@ class RollbackTestUtils {
     * Returns -1 if the package is not currently installed.
     */
    static long getInstalledVersion(String packageName) {
        PackageInfo pi = getPackageInfo(packageName);
        if (pi == null) {
            return -1;
        } else {
            return pi.getLongVersionCode();
        }
    }

    private static boolean isSystemAppWithoutUpdate(String packageName) {
        PackageInfo pi = getPackageInfo(packageName);
        if (pi == null) {
            return false;
        } else {
            return ((pi.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0)
                    && ((pi.applicationInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) == 0);
        }
    }

    private static PackageInfo getPackageInfo(String packageName) {
        Context context = InstrumentationRegistry.getContext();
        PackageManager pm = context.getPackageManager();
        try {
            PackageInfo info = pm.getPackageInfo(packageName, PackageManager.MATCH_APEX);
            return info.getLongVersionCode();
            return pm.getPackageInfo(packageName, PackageManager.MATCH_APEX);
        } catch (PackageManager.NameNotFoundException e) {
            return -1;
            return null;
        }
    }

@@ -109,8 +128,8 @@ class RollbackTestUtils {
     * @throws AssertionError if package can't be uninstalled.
     */
    static void uninstall(String packageName) throws InterruptedException, IOException {
        // No need to uninstall if the package isn't installed.
        if (getInstalledVersion(packageName) == -1) {
        // No need to uninstall if the package isn't installed or is installed on /system.
        if (getInstalledVersion(packageName) == -1 || isSystemAppWithoutUpdate(packageName)) {
            return;
        }

+46 −0
Original line number Diff line number Diff line
@@ -21,7 +21,9 @@ import static com.android.tests.rollback.RollbackTestUtils.getUniqueRollbackInfo

import android.Manifest;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.VersionedPackage;
import android.content.rollback.RollbackInfo;
import android.content.rollback.RollbackManager;
@@ -30,6 +32,8 @@ import androidx.test.InstrumentationRegistry;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

@@ -54,6 +58,8 @@ public class StagedRollbackTest {
    private static final String TEST_APP_A = "com.android.tests.rollback.testapp.A";
    private static final String TEST_APP_A_V1 = "RollbackTestAppAv1.apk";
    private static final String TEST_APP_A_CRASHING_V2 = "RollbackTestAppACrashingV2.apk";
    private static final String NETWORK_STACK_CONNECTOR_CLASS =
            "android.net.INetworkStackConnector";

    /**
     * Adopts common shell permissions needed for rollback tests.
@@ -157,4 +163,44 @@ public class StagedRollbackTest {
        assertTrue(rollback.isStaged());
        assertNotEquals(-1, rollback.getCommittedSessionId());
    }

    @Test
    public void resetNetworkStack() throws Exception {
        RollbackManager rm = RollbackTestUtils.getRollbackManager();
        String networkStack = getNetworkStackPackageName();

        rm.expireRollbackForPackage(networkStack);
        RollbackTestUtils.uninstall(networkStack);

        assertNull(getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(),
                        networkStack));
    }

    @Test
    public void assertNetworkStackRollbackAvailable() throws Exception {
        RollbackManager rm = RollbackTestUtils.getRollbackManager();
        assertNotNull(getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(),
                        getNetworkStackPackageName()));
    }

    @Test
    public void assertNetworkStackRollbackCommitted() throws Exception {
        RollbackManager rm = RollbackTestUtils.getRollbackManager();
        assertNotNull(getUniqueRollbackInfoForPackage(rm.getRecentlyCommittedRollbacks(),
                        getNetworkStackPackageName()));
    }

    @Test
    public void assertNoNetworkStackRollbackCommitted() throws Exception {
        RollbackManager rm = RollbackTestUtils.getRollbackManager();
        assertNull(getUniqueRollbackInfoForPackage(rm.getRecentlyCommittedRollbacks(),
                        getNetworkStackPackageName()));
    }

    private String getNetworkStackPackageName() {
        Intent intent = new Intent(NETWORK_STACK_CONNECTOR_CLASS);
        ComponentName comp = intent.resolveSystemService(
                InstrumentationRegistry.getContext().getPackageManager(), 0);
        return comp.getPackageName();
    }
}
+100 −0
Original line number Diff line number Diff line
@@ -23,6 +23,8 @@ import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

@@ -43,6 +45,20 @@ public class StagedRollbackTest extends BaseHostJUnit4Test {
                    phase));
    }

    @Before
    public void setUp() throws Exception {
        // Disconnect internet so we can test network health triggered rollbacks
        getDevice().executeShellCommand("svc wifi disable");
        getDevice().executeShellCommand("svc data disable");
    }

    @After
    public void tearDown() throws Exception {
        // Reconnect internet after testing network health triggered rollbacks
        getDevice().executeShellCommand("svc wifi enable");
        getDevice().executeShellCommand("svc data enable");
    }

    /**
     * Tests watchdog triggered staged rollbacks involving only apks.
     */
@@ -63,6 +79,90 @@ public class StagedRollbackTest extends BaseHostJUnit4Test {
        }

        getDevice().waitForDeviceAvailable();

        runPhase("testBadApkOnlyConfirmRollback");
    }

    /**
     * Tests failed network health check triggers watchdog staged rollbacks.
     */
    @Test
    public void testNetworkFailedRollback() throws Exception {
        // Remove available rollbacks and uninstall NetworkStack on /data/
        runPhase("resetNetworkStack");
        // Reduce health check deadline
        getDevice().executeShellCommand("device_config put rollback "
                + "watchdog_request_timeout_millis 300000");
        // Simulate re-installation of new NetworkStack with rollbacks enabled
        getDevice().executeShellCommand("pm install -r --staged --enable-rollback "
                + "/system/priv-app/NetworkStack/NetworkStack.apk");

        // Sleep to allow writes to disk before reboot
        Thread.sleep(5000);
        // Reboot device to activate staged package
        getDevice().reboot();
        getDevice().waitForDeviceAvailable();

        // Verify rollback was enabled
        runPhase("assertNetworkStackRollbackAvailable");

        // Sleep for < health check deadline
        Thread.sleep(5000);
        // Verify rollback was not executed before health check deadline
        runPhase("assertNoNetworkStackRollbackCommitted");
        try {
            // This is expected to fail due to the device being rebooted out
            // from underneath the test. If this fails for reasons other than
            // the device reboot, those failures should result in failure of
            // the assertNetworkStackExecutedRollback phase.
            CLog.logAndDisplay(LogLevel.INFO, "Sleep and expect to fail while sleeping");
            // Sleep for > health check deadline
            Thread.sleep(260000);
        } catch (AssertionError e) {
            // AssertionError is expected.
        }

        getDevice().waitForDeviceAvailable();
        // Verify rollback was executed after health check deadline
        runPhase("assertNetworkStackRollbackCommitted");
    }

    /**
     * Tests passed network health check does not trigger watchdog staged rollbacks.
     */
    @Test
    public void testNetworkPassedDoesNotRollback() throws Exception {
        // Remove available rollbacks and uninstall NetworkStack on /data/
        runPhase("resetNetworkStack");
        // Reduce health check deadline, here unlike the network failed case, we use
        // a longer deadline because joining a network can take a much longer time for
        // reasons external to the device than 'not joining'
        getDevice().executeShellCommand("device_config put rollback "
                + "watchdog_request_timeout_millis 300000");
        // Simulate re-installation of new NetworkStack with rollbacks enabled
        getDevice().executeShellCommand("pm install -r --staged --enable-rollback "
                + "/system/priv-app/NetworkStack/NetworkStack.apk");

        // Sleep to allow writes to disk before reboot
        Thread.sleep(5000);
        // Reboot device to activate staged package
        getDevice().reboot();
        getDevice().waitForDeviceAvailable();

        // Verify rollback was enabled
        runPhase("assertNetworkStackRollbackAvailable");

        // Connect to internet so network health check passes
        getDevice().executeShellCommand("svc wifi enable");
        getDevice().executeShellCommand("svc data enable");

        // Wait for device available because emulator device may restart after turning
        // on mobile data
        getDevice().waitForDeviceAvailable();

        // Sleep for > health check deadline
        Thread.sleep(310000);
        // Verify rollback was not executed after health check deadline
        runPhase("assertNoNetworkStackRollbackCommitted");
    }
}