Enable microdroid console output with debug level or debug policy
With this CL, pvmfw will add kernel.print.devkmsg and console to
bootargs with hardcoded value from microdroid's debuggable bootconfig.
Test: manually start protected/unprotected VMs \
with various debug levels and debug policies.
Change-Id: I31600f0d337ff47edfb5cfea60f5e6a010c85ab5
diff --git a/tests/hostside/Android.bp b/tests/hostside/Android.bp
index f1e5054..d217c00 100644
--- a/tests/hostside/Android.bp
+++ b/tests/hostside/Android.bp
@@ -22,6 +22,20 @@
out: ["avf_debug_policy_without_ramdump.dtbo"],
}
+genrule {
+ name: "test_avf_debug_policy_with_console_output",
+ defaults: ["test_avf_debug_policy_overlay"],
+ srcs: ["assets/avf_debug_policy_with_console_output.dts"],
+ out: ["avf_debug_policy_with_console_output.dtbo"],
+}
+
+genrule {
+ name: "test_avf_debug_policy_without_console_output",
+ defaults: ["test_avf_debug_policy_overlay"],
+ srcs: ["assets/avf_debug_policy_without_console_output.dts"],
+ out: ["avf_debug_policy_without_console_output.dtbo"],
+}
+
java_test_host {
name: "MicrodroidHostTestCases",
srcs: ["java/**/*.java"],
@@ -48,6 +62,8 @@
":pvmfw_test",
":test_avf_debug_policy_with_ramdump",
":test_avf_debug_policy_without_ramdump",
+ ":test_avf_debug_policy_with_console_output",
+ ":test_avf_debug_policy_without_console_output",
"assets/bcc.dat",
],
data_native_bins: [
diff --git a/tests/hostside/assets/avf_debug_policy_with_console_output.dts b/tests/hostside/assets/avf_debug_policy_with_console_output.dts
new file mode 100644
index 0000000..8cf19d6
--- /dev/null
+++ b/tests/hostside/assets/avf_debug_policy_with_console_output.dts
@@ -0,0 +1,18 @@
+/dts-v1/;
+/plugin/;
+
+/ {
+ fragment@avf {
+ target-path = "/";
+
+ __overlay__ {
+ avf {
+ guest {
+ common {
+ log = <1>;
+ };
+ };
+ };
+ };
+ };
+};
\ No newline at end of file
diff --git a/tests/hostside/assets/avf_debug_policy_without_console_output.dts b/tests/hostside/assets/avf_debug_policy_without_console_output.dts
new file mode 100644
index 0000000..da6400c
--- /dev/null
+++ b/tests/hostside/assets/avf_debug_policy_without_console_output.dts
@@ -0,0 +1,18 @@
+/dts-v1/;
+/plugin/;
+
+/ {
+ fragment@avf {
+ target-path = "/";
+
+ __overlay__ {
+ avf {
+ guest {
+ common {
+ log = <0>;
+ };
+ };
+ };
+ };
+ };
+};
\ No newline at end of file
diff --git a/tests/hostside/java/com/android/microdroid/test/PvmfwDebugPolicyHostTests.java b/tests/hostside/java/com/android/microdroid/test/PvmfwDebugPolicyHostTests.java
index bda52dd..1ada5a1 100644
--- a/tests/hostside/java/com/android/microdroid/test/PvmfwDebugPolicyHostTests.java
+++ b/tests/hostside/java/com/android/microdroid/test/PvmfwDebugPolicyHostTests.java
@@ -19,6 +19,7 @@
import static com.android.tradefed.device.TestDevice.MicrodroidBuilder;
import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
import static org.junit.Assume.assumeTrue;
@@ -32,6 +33,7 @@
import com.android.tradefed.device.TestDevice;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.util.CommandResult;
import com.android.tradefed.util.FileUtil;
import org.junit.After;
@@ -41,6 +43,7 @@
import java.io.File;
import java.util.Objects;
+import java.util.concurrent.TimeUnit;
import java.io.FileNotFoundException;
/** Tests debug policy of pvmfw.bin with custom debug policy */
@@ -50,13 +53,16 @@
@NonNull private static final String BCC_FILE_NAME = "bcc.dat";
@NonNull private static final String PACKAGE_FILE_NAME = "MicrodroidTestApp.apk";
@NonNull private static final String PACKAGE_NAME = "com.android.microdroid.test";
- @NonNull private static final String MICRODROID_DEBUG_LEVEL = "full";
+ @NonNull private static final String MICRODROID_DEBUG_FULL = "full";
@NonNull private static final String MICRODROID_CONFIG_PATH = "assets/vm_config_apex.json";
- private static final int BOOT_COMPLETE_TIMEOUT = 30000; // 30 seconds
+ @NonNull private static final String MICRODROID_LOG_PATH = TEST_ROOT + "log.txt";
+ @NonNull private static final String MICRODROID_CONSOLE_PATH = TEST_ROOT + "console.txt";
+ private static final int BOOT_COMPLETE_TIMEOUT_MS = 30000; // 30 seconds
+ private static final int CONSOLE_OUTPUT_WAIT_MS = 5000; // 5 seconds
@NonNull private static final String CUSTOM_PVMFW_FILE_PREFIX = "pvmfw";
@NonNull private static final String CUSTOM_PVMFW_FILE_SUFFIX = ".bin";
- @NonNull private static final String CUSTOM_PVMFW_IMG_PATH = TEST_ROOT + "/" + PVMFW_FILE_NAME;
+ @NonNull private static final String CUSTOM_PVMFW_IMG_PATH = TEST_ROOT + PVMFW_FILE_NAME;
@NonNull private static final String CUSTOM_PVMFW_IMG_PATH_PROP = "hypervisor.pvmfw.path";
@NonNull private static final String MICRODROID_CMDLINE_PATH = "/proc/cmdline";
@@ -162,6 +168,30 @@
.isEqualTo(HEX_STRING_ZERO);
}
+ @Test
+ public void testConsoleOutput() throws Exception {
+ Pvmfw pvmfw = createPvmfw("avf_debug_policy_with_console_output.dtbo");
+ pvmfw.serialize(mCustomPvmfwBinFileOnHost);
+
+ CommandResult result = tryLaunchProtectedNonDebuggableVm();
+
+ assertWithMessage("Microdroid's console message should have been enabled")
+ .that(hasConsoleOutput(result))
+ .isTrue();
+ }
+
+ @Test
+ public void testNoConsoleOutput() throws Exception {
+ Pvmfw pvmfw = createPvmfw("avf_debug_policy_without_console_output.dtbo");
+ pvmfw.serialize(mCustomPvmfwBinFileOnHost);
+
+ CommandResult result = tryLaunchProtectedNonDebuggableVm();
+
+ assertWithMessage("Microdroid's console message shouldn't have been disabled")
+ .that(hasConsoleOutput(result))
+ .isFalse();
+ }
+
@NonNull
private String readMicrodroidFileAsString(@NonNull String path)
throws DeviceNotAvailableException {
@@ -184,18 +214,50 @@
.build();
}
+ @NonNull
+ private boolean hasConsoleOutput(CommandResult result) throws DeviceNotAvailableException {
+ return result.getStdout().contains("Run /init as init process");
+ }
+
private ITestDevice launchProtectedVmAndWaitForBootCompleted()
throws DeviceNotAvailableException {
mMicrodroidDevice =
MicrodroidBuilder.fromDevicePath(
getPathForPackage(PACKAGE_NAME), MICRODROID_CONFIG_PATH)
- .debugLevel(MICRODROID_DEBUG_LEVEL)
+ .debugLevel(MICRODROID_DEBUG_FULL)
.protectedVm(/* protectedVm= */ true)
.addBootFile(mCustomPvmfwBinFileOnHost, PVMFW_FILE_NAME)
.build(mAndroidDevice);
- assertThat(mMicrodroidDevice.waitForBootComplete(BOOT_COMPLETE_TIMEOUT)).isTrue();
+ assertThat(mMicrodroidDevice.waitForBootComplete(BOOT_COMPLETE_TIMEOUT_MS)).isTrue();
assertThat(mMicrodroidDevice.enableAdbRoot()).isTrue();
-
return mMicrodroidDevice;
}
+
+ // Try to launch protected non-debuggable VM for a while and quit.
+ // Non-debuggable VM doesn't enable adb, so there's no ITestDevice instance of it.
+ private CommandResult tryLaunchProtectedNonDebuggableVm() throws DeviceNotAvailableException {
+ // Can't use MicrodroidBuilder because it expects adb connection
+ // but non-debuggable VM doesn't enable adb.
+ CommandRunner runner = new CommandRunner(mAndroidDevice);
+ runner.run("mkdir", "-p", TEST_ROOT);
+ mAndroidDevice.pushFile(mCustomPvmfwBinFileOnHost, TEST_ROOT + PVMFW_FILE_NAME);
+
+ // This will fail because app wouldn't finish itself.
+ // But let's run the app once and get logs.
+ String command =
+ String.join(
+ " ",
+ "/apex/com.android.virt/bin/vm",
+ "run-app",
+ "--log",
+ MICRODROID_LOG_PATH,
+ "--protected",
+ getPathForPackage(PACKAGE_NAME),
+ TEST_ROOT + "idsig",
+ TEST_ROOT + "instance.img",
+ "--config-path",
+ MICRODROID_CONFIG_PATH);
+ return mAndroidDevice.executeShellV2Command(
+ command, CONSOLE_OUTPUT_WAIT_MS, TimeUnit.MILLISECONDS, /* retryAttempts= */ 0);
+ }
}