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

Commit 80b53bd6 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

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

parents 6b268152 e77a3e1d
Loading
Loading
Loading
Loading
+1 −1
Original line number Original line Diff line number Diff line
@@ -95,7 +95,7 @@ android_test {
        ":RollbackTestAppASplitV2",
        ":RollbackTestAppASplitV2",
    ],
    ],
    test_config: "RollbackTest.xml",
    test_config: "RollbackTest.xml",
    sdk_version: "test_current",
    // TODO: sdk_version: "test_current" when Intent#resolveSystemservice is TestApi
}
}


java_test_host {
java_test_host {
+24 −5
Original line number Original line Diff line number Diff line
@@ -28,6 +28,7 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Context;
import android.content.Intent;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageInstaller;
import android.content.pm.PackageInstaller;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager;
@@ -82,13 +83,31 @@ class RollbackTestUtils {
     * Returns -1 if the package is not currently installed.
     * Returns -1 if the package is not currently installed.
     */
     */
    static long getInstalledVersion(String packageName) {
    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();
        Context context = InstrumentationRegistry.getContext();
        PackageManager pm = context.getPackageManager();
        PackageManager pm = context.getPackageManager();
        try {
        try {
            PackageInfo info = pm.getPackageInfo(packageName, PackageManager.MATCH_APEX);
            return pm.getPackageInfo(packageName, PackageManager.MATCH_APEX);
            return info.getLongVersionCode();
        } catch (PackageManager.NameNotFoundException e) {
        } catch (PackageManager.NameNotFoundException e) {
            return -1;
            return null;
        }
        }
    }
    }


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


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


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


import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
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.assertTrue;
import static org.junit.Assert.fail;
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 = "com.android.tests.rollback.testapp.A";
    private static final String TEST_APP_A_V1 = "RollbackTestAppAv1.apk";
    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 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.
     * Adopts common shell permissions needed for rollback tests.
@@ -157,4 +163,44 @@ public class StagedRollbackTest {
        assertTrue(rollback.isStaged());
        assertTrue(rollback.isStaged());
        assertNotEquals(-1, rollback.getCommittedSessionId());
        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 Original line 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.DeviceJUnit4ClassRunner;
import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;


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


@@ -43,6 +45,20 @@ public class StagedRollbackTest extends BaseHostJUnit4Test {
                    phase));
                    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.
     * Tests watchdog triggered staged rollbacks involving only apks.
     */
     */
@@ -63,6 +79,90 @@ public class StagedRollbackTest extends BaseHostJUnit4Test {
        }
        }


        getDevice().waitForDeviceAvailable();
        getDevice().waitForDeviceAvailable();

        runPhase("testBadApkOnlyConfirmRollback");
        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");
    }
}
}