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

Commit 9af18e83 authored by Victor Hsieh's avatar Victor Hsieh Committed by Android (Google) Code Review
Browse files

Merge "Add tests to verify job scheduling on events"

parents 51d58191 3e6ee946
Loading
Loading
Loading
Loading
+3 −8
Original line number Diff line number Diff line
@@ -96,7 +96,6 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;

/**
@@ -287,7 +286,7 @@ public class BinaryTransparencyService extends SystemService {
         * - dynamically installed mobile bundled apps (MBAs) (new in Android U)
         */
        public void recordMeasurementsForAllPackages() {
            // check if we should record the resulting measurements
            // check if we should measure and record
            long currentTimeMs = System.currentTimeMillis();
            if ((currentTimeMs - mMeasurementsLastRecordedMs) < RECORD_MEASUREMENTS_COOLDOWN_MS) {
                Slog.d(TAG, "Skip measurement since the last measurement was only taken at "
@@ -1230,10 +1229,8 @@ public class BinaryTransparencyService extends SystemService {
     * JobService to measure all covered binaries and record result to Westworld.
     */
    public static class UpdateMeasurementsJobService extends JobService {
        private static AtomicBoolean sScheduled = new AtomicBoolean();
        private static long sTimeLastRanMs = 0;
        private static final int DO_BINARY_MEASUREMENTS_JOB_ID =
                UpdateMeasurementsJobService.class.hashCode();
        private static final int DO_BINARY_MEASUREMENTS_JOB_ID = 1740526926;

        @Override
        public boolean onStartJob(JobParameters params) {
@@ -1256,7 +1253,6 @@ public class BinaryTransparencyService extends SystemService {
                    return;
                }
                sTimeLastRanMs = System.currentTimeMillis();
                sScheduled.set(false);
                jobFinished(params, false);
            }).start();

@@ -1277,7 +1273,7 @@ public class BinaryTransparencyService extends SystemService {
                return;
            }

            if (sScheduled.get()) {
            if (jobScheduler.getPendingJob(DO_BINARY_MEASUREMENTS_JOB_ID) != null) {
                Slog.d(TAG, "A measurement job has already been scheduled.");
                return;
            }
@@ -1303,7 +1299,6 @@ public class BinaryTransparencyService extends SystemService {
                Slog.e(TAG, "Failed to schedule job to measure binaries.");
                return;
            }
            sScheduled.set(true);
            Slog.d(TAG, TextUtils.formatSimple(
                    "Job %d to measure binaries was scheduled successfully.",
                    DO_BINARY_MEASUREMENTS_JOB_ID));
+1 −0
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@ java_test_host {
    data: [
        ":BinaryTransparencyTestApp",
        ":EasterEgg",
        ":com.android.apex.cts.shim.v2_rebootless_prebuilt",
    ],
    test_suites: [
        "general-tests",
+74 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package android.transparency.test;

import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -29,14 +30,22 @@ import org.junit.After;
import org.junit.Test;
import org.junit.runner.RunWith;

import java.util.concurrent.TimeUnit;

// TODO: Add @Presubmit
@RunWith(DeviceJUnit4ClassRunner.class)
public final class BinaryTransparencyHostTest extends BaseHostJUnit4Test {
    private static final String PACKAGE_NAME = "android.transparency.test.app";

    private static final String JOB_ID = "1740526926";

    /** Waiting time for the job to be scheduled */
    private static final int JOB_CREATION_MAX_SECONDS = 5;

    @After
    public void tearDown() throws Exception {
        uninstallPackage("com.android.egg");
        uninstallRebootlessApex();
    }

    @Test
@@ -63,6 +72,28 @@ public final class BinaryTransparencyHostTest extends BaseHostJUnit4Test {
        runDeviceTest("testCollectAllUpdatedPreloadInfo");
    }

    @Test
    public void testRebootlessApexUpdateTriggersJobScheduling() throws Exception {
        cancelPendingJob();
        installRebootlessApex();

        // Verify
        expectJobToBeScheduled();
        // Just cancel since we can't verifying very meaningfully.
        cancelPendingJob();
    }

    @Test
    public void testPreloadUpdateTriggersJobScheduling() throws Exception {
        cancelPendingJob();
        installPackage("EasterEgg.apk");

        // Verify
        expectJobToBeScheduled();
        // Just cancel since we can't verifying very meaningfully.
        cancelPendingJob();
    }

    @Test
    public void testMeasureMbas() throws Exception {
        // TODO(265244016): figure out a way to install an MBA
@@ -74,4 +105,47 @@ public final class BinaryTransparencyHostTest extends BaseHostJUnit4Test {
        options.setTestMethodName(method);
        runDeviceTests(options);
    }

    private void cancelPendingJob() throws DeviceNotAvailableException {
        CommandResult result = getDevice().executeShellV2Command(
                "cmd jobscheduler cancel android " + JOB_ID);
        assertTrue(result.getStatus() == CommandStatus.SUCCESS);
    }

    private void expectJobToBeScheduled() throws Exception {
        for (int i = 0; i < JOB_CREATION_MAX_SECONDS; i++) {
            CommandResult result = getDevice().executeShellV2Command(
                    "cmd jobscheduler get-job-state android " + JOB_ID);
            String state = result.getStdout().toString();
            if (state.startsWith("unknown")) {
                // The job hasn't been scheduled yet. So try again.
                TimeUnit.SECONDS.sleep(1);
            } else if (result.getExitCode() != 0) {
                fail("Failing due to unexpected job state: " + result);
            } else {
                // The job exists, which is all we care about here
                return;
            }
        }
        fail("Timed out waiting for the job to be scheduled");
    }

    private void installRebootlessApex() throws Exception {
        installPackage("com.android.apex.cts.shim.v2_rebootless.apex", "--force-non-staged");
    }

    private void uninstallRebootlessApex() throws DeviceNotAvailableException {
        // Reboot only if the APEX is not the pre-install one.
        CommandResult result = getDevice().executeShellV2Command(
                "pm list packages -f --apex-only |grep com.android.apex.cts.shim");
        assertTrue(result.getStatus() == CommandStatus.SUCCESS);
        if (result.getStdout().contains("/data/apex/active/")) {
            uninstallPackage("com.android.apex.cts.shim");
            getDevice().reboot();

            // Reboot enforces SELinux. Make it permissive again.
            CommandResult runResult = getDevice().executeShellV2Command("setenforce 0");
            assertTrue(runResult.getStatus() == CommandStatus.SUCCESS);
        }
    }
}