Merge "Explicit init .rc user."
diff --git a/TEST_MAPPING b/TEST_MAPPING
index 3217ee1..d17b434 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -4,6 +4,9 @@
"name": "MicrodroidHostTestCases"
},
{
+ "name": "ComposHostTestCases"
+ },
+ {
"name": "MicrodroidTestApp"
},
{
@@ -33,9 +36,6 @@
"name": "ComposBenchmarkApp"
},
{
- "name": "ComposHostTestCases"
- },
- {
"name": "AVFHostTestCases"
}
],
diff --git a/authfs/tests/benchmarks/Android.bp b/authfs/tests/benchmarks/Android.bp
index 38ece79..b30ecdd 100644
--- a/authfs/tests/benchmarks/Android.bp
+++ b/authfs/tests/benchmarks/Android.bp
@@ -24,6 +24,7 @@
":CtsApkVerityTestPrebuiltFiles",
":MicrodroidTestApp",
],
+ required: ["MicrodroidTestPreparer"],
}
cc_binary {
diff --git a/authfs/tests/benchmarks/AndroidTest.xml b/authfs/tests/benchmarks/AndroidTest.xml
index 7ca3a80..9216006 100644
--- a/authfs/tests/benchmarks/AndroidTest.xml
+++ b/authfs/tests/benchmarks/AndroidTest.xml
@@ -49,6 +49,8 @@
value="/data/local/tmp/authfs/input.apk.fsv_sig" />
</target_preparer>
+ <target_preparer class="com.android.microdroid.test.preparer.DisableMicrodroidDebugPolicyPreparer" />
+
<target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
<option name="throw-if-cmd-fail" value="true" />
<!-- Now that the files are pushed to the device, enable fs-verity for the targeting file.
diff --git a/compos/benchmark/Android.bp b/compos/benchmark/Android.bp
index 12b3ae8..dc0c01c 100644
--- a/compos/benchmark/Android.bp
+++ b/compos/benchmark/Android.bp
@@ -18,4 +18,6 @@
sdk_version: "test_current",
use_embedded_native_libs: true,
compile_multilib: "64",
+
+ host_required: ["MicrodroidTestPreparer"],
}
diff --git a/compos/benchmark/AndroidTest.xml b/compos/benchmark/AndroidTest.xml
index f98b743..8c65187 100644
--- a/compos/benchmark/AndroidTest.xml
+++ b/compos/benchmark/AndroidTest.xml
@@ -27,6 +27,8 @@
<option name="force-root" value="true" />
</target_preparer>
+ <target_preparer class="com.android.microdroid.test.preparer.DisableMicrodroidDebugPolicyPreparer" />
+
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="com.android.compos.benchmark" />
<option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
diff --git a/compos/tests/java/android/compos/test/ComposTestCase.java b/compos/tests/java/android/compos/test/ComposTestCase.java
index eb2e072..8c7aeeb 100644
--- a/compos/tests/java/android/compos/test/ComposTestCase.java
+++ b/compos/tests/java/android/compos/test/ComposTestCase.java
@@ -23,6 +23,8 @@
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
+import static org.junit.Assume.assumeFalse;
+
import android.platform.test.annotations.RootPermissionTest;
import com.android.microdroid.test.host.CommandRunner;
@@ -81,6 +83,8 @@
@Before
public void setUp() throws Exception {
assumeDeviceIsCapable(getDevice());
+ // We get a very high level of (apparently bogus) OOM errors on Cuttlefish (b/264496291).
+ assumeFalse("Skipping test on Cuttlefish", isCuttlefish());
String value = getDevice().getProperty(SYSTEM_SERVER_COMPILER_FILTER_PROP_NAME);
if (value == null) {
diff --git a/pvmfw/README.md b/pvmfw/README.md
index 6fc2fd6..4e93648 100644
--- a/pvmfw/README.md
+++ b/pvmfw/README.md
@@ -271,6 +271,53 @@
For details about device tree properties for debug policies, see
[microdroid's debugging policy guide](../microdroid/README.md#option-1-running-microdroid-on-avf-debug-policy-configured-device).
+### Platform Requirements
+
+pvmfw is intended to run in a virtualized environment according to the `crosvm`
+[memory layout][crosvm-mem] for protected VMs and so it expects to have been
+loaded at address `0x7fc0_0000` and uses the 2MiB region at address
+`0x7fe0_0000` as scratch memory. It makes use of the virtual PCI bus to obtain a
+virtio interface to the host and prints its logs through the 16550 UART (address
+`0x3f8`).
+
+At boot, pvmfw discovers the running hypervisor in order to select the
+appropriate hypervisor calls to share/unshare memory, mark IPA regions as MMIO,
+obtain trusted true entropy, and reboot the virtual machine. In particular, it
+makes use of the following hypervisor calls:
+
+- Arm [SMC Calling Convention][smccc] v1.1 or above:
+
+ - `SMCCC_VERSION`
+ - Vendor Specific Hypervisor Service Call UID Query
+
+- Arm [Power State Coordination Interface][psci] v1.0 or above:
+
+ - `PSCI_VERSION`
+ - `PSCI_FEATURES`
+ - `PSCI_SYSTEM_RESET`
+ - `PSCI_SYSTEM_SHUTDOWN`
+
+- Arm [True Random Number Generator Firmware Interface][smccc-trng] v1.0:
+
+ - `TRNG_VERSION`
+ - `TRNG_FEATURES`
+ - `TRNG_RND`
+
+- When running under KVM, the pKVM-specific hypervisor interface must provide:
+
+ - `MEMINFO` (function ID `0xc6000002`)
+ - `MEM_SHARE` (function ID `0xc6000003`)
+ - `MEM_UNSHARE` (function ID `0xc6000004`)
+ - `MMIO_GUARD_INFO` (function ID `0xc6000005`)
+ - `MMIO_GUARD_ENROLL` (function ID `0xc6000006`)
+ - `MMIO_GUARD_MAP` (function ID `0xc6000007`)
+ - `MMIO_GUARD_UNMAP` (function ID `0xc6000008`)
+
+[crosvm-mem]: https://crosvm.dev/book/appendix/memory_layout.html
+[psci]: https://developer.arm.com/documentation/den0022
+[smccc]: https://developer.arm.com/documentation/den0028
+[smccc-trng]: https://developer.arm.com/documentation/den0098
+
## Booting Protected Virtual Machines
### Boot Protocol
diff --git a/pvmfw/src/debug_policy.rs b/pvmfw/src/debug_policy.rs
deleted file mode 100644
index bbf7e04..0000000
--- a/pvmfw/src/debug_policy.rs
+++ /dev/null
@@ -1,78 +0,0 @@
-// Copyright 2023, The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-//! Support for the debug policy overlay in pvmfw
-
-use core::fmt;
-use libfdt::FdtError;
-
-#[derive(Debug, Clone)]
-pub enum DebugPolicyError {
- /// The provided baseline FDT was invalid or malformed, so cannot access certain node/prop
- Fdt(&'static str, FdtError),
- /// The provided debug policy FDT was invalid or malformed.
- DebugPolicyFdt(&'static str, FdtError),
- /// The overlaid result FDT is invalid or malformed, and may be corrupted.
- OverlaidFdt(&'static str, FdtError),
-}
-
-impl fmt::Display for DebugPolicyError {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- match self {
- Self::Fdt(s, e) => write!(f, "Invalid baseline FDT. {s}: {e}"),
- Self::DebugPolicyFdt(s, e) => write!(f, "Invalid overlay FDT. {s}: {e}"),
- Self::OverlaidFdt(s, e) => write!(f, "Invalid overlaid FDT. {s}: {e}"),
- }
- }
-}
-
-/// Applies the debug policy device tree overlay to the pVM DT.
-///
-/// # Safety
-///
-/// When an error is returned by this function, the input `Fdt` should be
-/// discarded as it may have have been partially corrupted during the overlay
-/// application process.
-unsafe fn apply_debug_policy(
- fdt: &mut libfdt::Fdt,
- debug_policy: &mut [u8],
-) -> Result<(), DebugPolicyError> {
- let overlay = libfdt::Fdt::from_mut_slice(debug_policy)
- .map_err(|e| DebugPolicyError::DebugPolicyFdt("Failed to load debug policy overlay", e))?;
-
- fdt.unpack().map_err(|e| DebugPolicyError::Fdt("Failed to unpack", e))?;
-
- let fdt = fdt
- .apply_overlay(overlay)
- .map_err(|e| DebugPolicyError::DebugPolicyFdt("Failed to apply overlay", e))?;
-
- fdt.pack().map_err(|e| DebugPolicyError::OverlaidFdt("Failed to re-pack", e))
-}
-
-/// Handles debug policies.
-///
-/// # Safety
-///
-/// This may corrupt the input `Fdt` when overlaying debug policy or applying
-/// ramdump configuration.
-pub unsafe fn handle_debug_policy(
- fdt: &mut libfdt::Fdt,
- debug_policy: Option<&mut [u8]>,
-) -> Result<(), DebugPolicyError> {
- if let Some(dp) = debug_policy {
- apply_debug_policy(fdt, dp)?;
- }
-
- Ok(())
-}
diff --git a/pvmfw/src/entry.rs b/pvmfw/src/entry.rs
index ffbc4a8..00f0e9b 100644
--- a/pvmfw/src/entry.rs
+++ b/pvmfw/src/entry.rs
@@ -16,7 +16,6 @@
use crate::config;
use crate::crypto;
-use crate::debug_policy::{handle_debug_policy, DebugPolicyError};
use crate::fdt;
use crate::heap;
use crate::helpers;
@@ -54,16 +53,6 @@
SecretDerivationError,
}
-impl From<DebugPolicyError> for RebootReason {
- fn from(error: DebugPolicyError) -> Self {
- match error {
- DebugPolicyError::Fdt(_, _) => RebootReason::InvalidFdt,
- DebugPolicyError::DebugPolicyFdt(_, _) => RebootReason::InvalidConfig,
- DebugPolicyError::OverlaidFdt(_, _) => RebootReason::InternalError,
- }
- }
-}
-
main!(start);
/// Entry point for pVM firmware.
@@ -237,19 +226,11 @@
})?;
// This wrapper allows main() to be blissfully ignorant of platform details.
- crate::main(slices.fdt, slices.kernel, slices.ramdisk, bcc_slice, &mut memory)?;
+ crate::main(slices.fdt, slices.kernel, slices.ramdisk, bcc_slice, debug_policy, &mut memory)?;
helpers::flushed_zeroize(bcc_slice);
helpers::flush(slices.fdt.as_slice());
- // SAFETY - As we `?` the result, there is no risk of using a bad `slices.fdt`.
- unsafe {
- handle_debug_policy(slices.fdt, debug_policy).map_err(|e| {
- error!("Unexpected error when handling debug policy: {e:?}");
- RebootReason::from(e)
- })?;
- }
-
info!("Expecting a bug making MMIO_GUARD_UNMAP return NOT_SUPPORTED on success");
memory.mmio_unmap_all().map_err(|e| {
error!("Failed to unshare MMIO ranges: {e}");
diff --git a/pvmfw/src/fdt.rs b/pvmfw/src/fdt.rs
index 7d88455..d15eaba 100644
--- a/pvmfw/src/fdt.rs
+++ b/pvmfw/src/fdt.rs
@@ -22,6 +22,7 @@
use crate::memory::MAX_ADDR;
use crate::RebootReason;
use alloc::ffi::CString;
+use alloc::vec::Vec;
use core::cmp::max;
use core::cmp::min;
use core::ffi::CStr;
@@ -36,6 +37,7 @@
use libfdt::FdtNode;
use log::debug;
use log::error;
+use log::info;
use tinyvec::ArrayVec;
/// Extract from /config the address range containing the pre-loaded kernel. Absence of /config is
@@ -672,6 +674,7 @@
bcc: &[u8],
new_instance: bool,
strict_boot: bool,
+ debug_policy: Option<&mut [u8]>,
) -> libfdt::Result<()> {
fdt.unpack()?;
@@ -680,6 +683,13 @@
set_or_clear_chosen_flag(fdt, cstr!("avf,strict-boot"), strict_boot)?;
set_or_clear_chosen_flag(fdt, cstr!("avf,new-instance"), new_instance)?;
+ if let Some(debug_policy) = debug_policy {
+ apply_debug_policy(fdt, debug_policy)?;
+ info!("Debug policy applied.");
+ } else {
+ info!("No debug policy found.");
+ }
+
fdt.pack()?;
Ok(())
@@ -712,3 +722,26 @@
Ok(())
}
+
+fn apply_debug_policy(fdt: &mut Fdt, debug_policy: &mut [u8]) -> libfdt::Result<()> {
+ let backup_fdt = Vec::from(fdt.as_slice());
+
+ let overlay = match Fdt::from_mut_slice(debug_policy) {
+ Ok(overlay) => overlay,
+ Err(e) => {
+ info!("Corrupted debug policy found: {e}. Not applying.");
+ return Ok(());
+ }
+ };
+ let backup_overlay = Vec::from(overlay.as_slice());
+
+ // SAFETY - on failure, the corrupted fdts are discarded and are restored using the backups.
+ if let Err(e) = unsafe { fdt.apply_overlay(overlay) } {
+ error!("Failed to apply debug policy: {e}. Recovering...");
+ fdt.copy_from_slice(backup_fdt.as_slice())?;
+ overlay.copy_from_slice(backup_overlay.as_slice())?;
+ // A successful restoration is considered success because an invalid debug policy
+ // shouldn't DOS the pvmfw
+ }
+ Ok(())
+}
diff --git a/pvmfw/src/main.rs b/pvmfw/src/main.rs
index 00ff61f..06cc81e 100644
--- a/pvmfw/src/main.rs
+++ b/pvmfw/src/main.rs
@@ -21,7 +21,6 @@
mod config;
mod crypto;
-mod debug_policy;
mod dice;
mod entry;
mod exceptions;
@@ -65,6 +64,7 @@
signed_kernel: &[u8],
ramdisk: Option<&[u8]>,
current_bcc_handover: &[u8],
+ debug_policy: Option<&mut [u8]>,
memory: &mut MemoryTracker,
) -> Result<(), RebootReason> {
info!("pVM firmware");
@@ -122,7 +122,7 @@
flush(next_bcc);
let strict_boot = true;
- modify_for_next_stage(fdt, next_bcc, new_instance, strict_boot).map_err(|e| {
+ modify_for_next_stage(fdt, next_bcc, new_instance, strict_boot, debug_policy).map_err(|e| {
error!("Failed to configure device tree: {e}");
RebootReason::InternalError
})?;
diff --git a/tests/benchmark/Android.bp b/tests/benchmark/Android.bp
index dac4993..9c512bf 100644
--- a/tests/benchmark/Android.bp
+++ b/tests/benchmark/Android.bp
@@ -26,6 +26,7 @@
sdk_version: "test_current",
use_embedded_native_libs: true,
compile_multilib: "64",
+ host_required: ["MicrodroidTestPreparer"],
}
cc_library_shared {
diff --git a/tests/benchmark/AndroidTest.xml b/tests/benchmark/AndroidTest.xml
index 29bc95a..8c8bfbe 100644
--- a/tests/benchmark/AndroidTest.xml
+++ b/tests/benchmark/AndroidTest.xml
@@ -30,6 +30,7 @@
<option name="post-push" value="chmod 755 /data/local/tmp/perf-setup.sh;/data/local/tmp/perf-setup.sh" />
<option name="cleanup" value="true" />
</target_preparer>
+ <target_preparer class="com.android.microdroid.test.preparer.DisableMicrodroidDebugPolicyPreparer" />
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="com.android.microdroid.benchmark" />
<option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
diff --git a/tests/benchmark_hostside/AndroidTest.xml b/tests/benchmark_hostside/AndroidTest.xml
index 5161269..7a998b1 100644
--- a/tests/benchmark_hostside/AndroidTest.xml
+++ b/tests/benchmark_hostside/AndroidTest.xml
@@ -18,7 +18,9 @@
<option name="force-root" value="true" />
</target_preparer>
+ <target_preparer class="com.android.microdroid.test.preparer.DisableMicrodroidDebugPolicyPreparer" />
+
<test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
<option name="jar" value="AVFHostTestCases.jar" />
</test>
-</configuration>
\ No newline at end of file
+</configuration>
diff --git a/tests/helper/Android.bp b/tests/helper/Android.bp
index f36a15d..6f07efd 100644
--- a/tests/helper/Android.bp
+++ b/tests/helper/Android.bp
@@ -21,3 +21,15 @@
],
sdk_version: "test_current",
}
+
+java_test_helper_library {
+ name: "MicrodroidTestPreparer",
+ srcs: ["src/java/com/android/microdroid/test/preparer/*.java"],
+ libs: ["tradefed"],
+ test_suites: [
+ "cts",
+ "general-tests",
+ ],
+ host_supported: true,
+ device_supported: false,
+}
diff --git a/tests/helper/src/java/com/android/microdroid/test/device/MicrodroidDeviceTestBase.java b/tests/helper/src/java/com/android/microdroid/test/device/MicrodroidDeviceTestBase.java
index cf17e5b..4e1d238 100644
--- a/tests/helper/src/java/com/android/microdroid/test/device/MicrodroidDeviceTestBase.java
+++ b/tests/helper/src/java/com/android/microdroid/test/device/MicrodroidDeviceTestBase.java
@@ -97,15 +97,6 @@
}
}
- public final boolean getDebugPolicyBoolean(String debugPolicy) throws IOException {
- Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
- UiAutomation uiAutomation = instrumentation.getUiAutomation();
- String debugPolicyFilePath = "/proc/device-tree" + debugPolicy;
- String cmd = "su root xxd -p " + debugPolicyFilePath;
- String dp = runInShell(TAG, uiAutomation, cmd).trim();
- return "00000001".equals(dp);
- }
-
private Context mCtx;
private boolean mProtectedVm;
diff --git a/tests/helper/src/java/com/android/microdroid/test/preparer/DisableMicrodroidDebugPolicyPreparer.java b/tests/helper/src/java/com/android/microdroid/test/preparer/DisableMicrodroidDebugPolicyPreparer.java
new file mode 100644
index 0000000..47be8b8
--- /dev/null
+++ b/tests/helper/src/java/com/android/microdroid/test/preparer/DisableMicrodroidDebugPolicyPreparer.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.microdroid.test.preparer;
+
+import com.android.tradefed.config.Option;
+import com.android.tradefed.config.OptionClass;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.invoker.TestInformation;
+import com.android.tradefed.log.LogUtil.CLog;
+import com.android.tradefed.targetprep.BaseTargetPreparer;
+import com.android.tradefed.targetprep.BuildError;
+import com.android.tradefed.targetprep.TargetSetupError;
+
+/**
+ * Target preparer that disables microdroid's device policy for future VMs. This requires adb root
+ * for configuring the relevant sysprop.
+ *
+ * <p>Will restore back to original value on tear down. adb will be also unrooted if it wasn't root.
+ */
+@OptionClass(alias = "disable-microdroid-debug-policy-preparer")
+public final class DisableMicrodroidDebugPolicyPreparer extends BaseTargetPreparer {
+ private static final String SYSPROP_CUSTOM_DEBUG_POLICY_PATH =
+ "hypervisor.virtualizationmanager.debug_policy.path";
+
+ private boolean mWasRoot = false;
+ private String mOldDebugPolicyPath;
+
+ @Option(
+ name = "debug-policy-path",
+ description = "Debug policy path for sysprop " + SYSPROP_CUSTOM_DEBUG_POLICY_PATH)
+ private String mDebugPolicyPath = "/data/local/tmp/virt/stub_debug_policy.dts";
+
+ @Override
+ public void setUp(TestInformation testInfo)
+ throws TargetSetupError, BuildError, DeviceNotAvailableException {
+ ITestDevice device = testInfo.getDevice();
+ mWasRoot = device.isAdbRoot();
+ if (!mWasRoot && !device.enableAdbRoot()) {
+ throw new TargetSetupError("Failed to adb root device", device.getDeviceDescriptor());
+ }
+
+ try {
+ CLog.d("Bypassing micrdroid debug policy");
+ mOldDebugPolicyPath = device.getProperty(SYSPROP_CUSTOM_DEBUG_POLICY_PATH);
+ boolean result = device.setProperty(SYSPROP_CUSTOM_DEBUG_POLICY_PATH, mDebugPolicyPath);
+ if (!result) {
+ throw new TargetSetupError(
+ "Bypassing microdroid debug policy failed", device.getDeviceDescriptor());
+ }
+ } finally {
+ if (!mWasRoot) {
+ device.disableAdbRoot();
+ }
+ }
+ }
+
+ @Override
+ public void tearDown(TestInformation testInfo, Throwable e) throws DeviceNotAvailableException {
+ ITestDevice device = testInfo.getDevice();
+ if (e instanceof DeviceNotAvailableException) {
+ CLog.d("device not available: skipping teardown");
+ return;
+ }
+
+ if (!mWasRoot) {
+ device.enableAdbRoot();
+ }
+
+ CLog.d("Resetting microdroid debug policy");
+ device.setProperty(
+ SYSPROP_CUSTOM_DEBUG_POLICY_PATH,
+ mOldDebugPolicyPath == null ? "" : mOldDebugPolicyPath);
+
+ if (!mWasRoot) {
+ device.disableAdbRoot();
+ }
+ }
+}
diff --git a/tests/hostside/Android.bp b/tests/hostside/Android.bp
index 248755f..c71a8ec 100644
--- a/tests/hostside/Android.bp
+++ b/tests/hostside/Android.bp
@@ -75,4 +75,5 @@
"libsparse",
"libz",
],
+ required: ["MicrodroidTestPreparer"],
}
diff --git a/tests/hostside/AndroidTest.xml b/tests/hostside/AndroidTest.xml
index 18728ad..429d910 100644
--- a/tests/hostside/AndroidTest.xml
+++ b/tests/hostside/AndroidTest.xml
@@ -25,6 +25,8 @@
<option name="force-root" value="false"/>
</target_preparer>
+ <target_preparer class="com.android.microdroid.test.preparer.DisableMicrodroidDebugPolicyPreparer" />
+
<test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
<option name="jar" value="MicrodroidHostTestCases.jar" />
</test>
diff --git a/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java b/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java
index 7044ae7..38bc485 100644
--- a/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java
+++ b/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java
@@ -28,13 +28,15 @@
import static com.google.common.truth.Truth.assertWithMessage;
import static com.google.common.truth.TruthJUnit.assume;
import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
-import static org.junit.Assume.assumeFalse;
+import static org.junit.Assume.assumeTrue;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
import com.google.common.base.Strings;
import com.google.common.truth.BooleanSubject;
+import android.app.Instrumentation;
+import android.app.UiAutomation;
import android.content.ComponentName;
import android.content.Context;
import android.content.ContextWrapper;
@@ -54,7 +56,8 @@
import android.system.virtualmachine.VirtualMachineDescriptor;
import android.system.virtualmachine.VirtualMachineException;
import android.system.virtualmachine.VirtualMachineManager;
-import android.util.Log;
+
+import androidx.test.platform.app.InstrumentationRegistry;
import com.android.compatibility.common.util.CddTest;
import com.android.compatibility.common.util.VsrTest;
@@ -1583,22 +1586,6 @@
}
}
- private boolean isConsoleOutputEnabledByDebugPolicy() {
- if (isUserBuild()) {
- Log.i(
- TAG,
- "Debug policy is inaccessible in user build. Assumes that console output is"
- + " disabled");
- return false;
- }
- try {
- return getDebugPolicyBoolean("/avf/guest/common/log");
- } catch (IOException e) {
- Log.w(TAG, "Fail to read debug policy. Assumes false", e);
- return false;
- }
- }
-
private boolean checkVmOutputIsRedirectedToLogcat(boolean debuggable) throws Exception {
String time =
LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"));
@@ -1632,21 +1619,33 @@
@Test
public void outputIsRedirectedToLogcatIfNotCaptured() throws Exception {
assumeSupportedDevice();
- assumeFalse(
- "Debug policy would turn on console output. Perhaps userdebug build?",
- isConsoleOutputEnabledByDebugPolicy());
assertThat(checkVmOutputIsRedirectedToLogcat(true)).isTrue();
}
+ private boolean setSystemProperties(String name, String value) {
+ Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
+ UiAutomation uiAutomation = instrumentation.getUiAutomation();
+ String cmd = "setprop " + name + " " + (value.isEmpty() ? "\"\"" : value);
+ return runInShellWithStderr(TAG, uiAutomation, cmd).trim().isEmpty();
+ }
+
@Test
public void outputIsNotRedirectedToLogcatIfNotDebuggable() throws Exception {
assumeSupportedDevice();
- assumeFalse(
- "Debug policy would turn on console output. Perhaps userdebug build?",
- isConsoleOutputEnabledByDebugPolicy());
- assertThat(checkVmOutputIsRedirectedToLogcat(false)).isFalse();
+ // Disable debug policy to ensure no log output.
+ String sysprop = "hypervisor.virtualizationmanager.debug_policy.path";
+ String old = SystemProperties.get(sysprop);
+ assumeTrue(
+ "Can't disable debug policy. Perhapse user build?",
+ setSystemProperties(sysprop, ""));
+
+ try {
+ assertThat(checkVmOutputIsRedirectedToLogcat(false)).isFalse();
+ } finally {
+ assertThat(setSystemProperties(sysprop, old)).isTrue();
+ }
}
@Test
diff --git a/virtualizationmanager/src/atom.rs b/virtualizationmanager/src/atom.rs
index 02d46ec..d6eb141 100644
--- a/virtualizationmanager/src/atom.rs
+++ b/virtualizationmanager/src/atom.rs
@@ -93,6 +93,7 @@
}
/// Write the stats of VMCreation to statsd
+/// The function creates a separate thread which waits for statsd to start to push atom
pub fn write_vm_creation_stats(
config: &VirtualMachineConfig,
is_protected: bool,
@@ -158,7 +159,7 @@
}
/// Write the stats of VM boot to statsd
-/// The function creates a separate thread which waits fro statsd to start to push atom
+/// The function creates a separate thread which waits for statsd to start to push atom
pub fn write_vm_booted_stats(
uid: i32,
vm_identifier: &str,
@@ -182,8 +183,7 @@
}
/// Write the stats of VM exit to statsd
-/// The function creates a separate thread which waits fro statsd to start to push atom
-pub fn write_vm_exited_stats(
+pub fn write_vm_exited_stats_sync(
uid: i32,
vm_identifier: &str,
reason: DeathReason,
@@ -207,9 +207,7 @@
};
info!("Writing VmExited atom into statsd.");
- thread::spawn(move || {
- GLOBAL_SERVICE.atomVmExited(&atom).unwrap_or_else(|e| {
- warn!("Failed to write VmExited atom: {e}");
- });
+ GLOBAL_SERVICE.atomVmExited(&atom).unwrap_or_else(|e| {
+ warn!("Failed to write VmExited atom: {e}");
});
}
diff --git a/virtualizationmanager/src/crosvm.rs b/virtualizationmanager/src/crosvm.rs
index a8cad94..60dd4cf 100644
--- a/virtualizationmanager/src/crosvm.rs
+++ b/virtualizationmanager/src/crosvm.rs
@@ -15,7 +15,7 @@
//! Functions for running instances of `crosvm`.
use crate::aidl::{remove_temporary_files, Cid, VirtualMachineCallbacks};
-use crate::atom::{get_num_cpus, write_vm_exited_stats};
+use crate::atom::{get_num_cpus, write_vm_exited_stats_sync};
use crate::debug_config::DebugConfig;
use anyhow::{anyhow, bail, Context, Error, Result};
use command_fds::CommandFdExt;
@@ -381,7 +381,7 @@
self.callbacks.callback_on_died(self.cid, death_reason);
let vm_metric = self.vm_metric.lock().unwrap();
- write_vm_exited_stats(
+ write_vm_exited_stats_sync(
self.requester_uid as i32,
&self.name,
death_reason,