Merge "Use ro.product.vendor.device to determine if running on Cuttlefish"
diff --git a/OWNERS b/OWNERS
index 5bd97f3..ecd24ed 100644
--- a/OWNERS
+++ b/OWNERS
@@ -9,6 +9,7 @@
# Other owners
alanstokes@google.com
+aliceywang@google.com
ardb@google.com
ascull@google.com
inseob@google.com
diff --git a/authfs/tests/Android.bp b/authfs/tests/Android.bp
index b662bee..0177254 100644
--- a/authfs/tests/Android.bp
+++ b/authfs/tests/Android.bp
@@ -23,6 +23,7 @@
":authfs_test_files",
":CtsApkVerityTestPrebuiltFiles",
":MicrodroidTestApp",
+ ":measure_io",
],
}
@@ -42,3 +43,13 @@
test_suites: ["general-tests"],
test_harness: false,
}
+
+cc_binary {
+ name: "measure_io",
+ srcs: [
+ "measure_io.cpp",
+ ],
+ shared_libs: [
+ "libbase",
+ ],
+}
diff --git a/authfs/tests/java/src/com/android/fs/AuthFsBenchmarks.java b/authfs/tests/java/src/com/android/fs/AuthFsBenchmarks.java
index 0dd4613..f84785b 100644
--- a/authfs/tests/java/src/com/android/fs/AuthFsBenchmarks.java
+++ b/authfs/tests/java/src/com/android/fs/AuthFsBenchmarks.java
@@ -18,6 +18,8 @@
import static com.android.tradefed.testtype.DeviceJUnit4ClassRunner.TestMetrics;
+import static com.google.common.truth.Truth.assertThat;
+
import android.platform.test.annotations.RootPermissionTest;
import com.android.microdroid.test.common.MetricsProcessor;
@@ -36,6 +38,7 @@
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@@ -44,8 +47,12 @@
@RunWith(DeviceJUnit4ClassRunner.class)
public class AuthFsBenchmarks extends BaseHostJUnit4Test {
private static final int TRIAL_COUNT = 5;
- private static final double NANO_SECS_PER_SEC = 1_000_000_000.;
- private static final double INPUT_SIZE_IN_MB = 4.;
+
+ /** Name of the measure_io binary on host. */
+ private static final String MEASURE_IO_BIN_NAME = "measure_io";
+
+ /** Path to measure_io on Microdroid. */
+ private static final String MEASURE_IO_BIN_PATH = "/data/local/tmp/measure_io";
/** fs-verity digest (sha256) of testdata/input.4m */
private static final String DIGEST_4M =
@@ -76,27 +83,69 @@
@Test
public void seqReadRemoteFile() throws Exception {
- List<Double> transferRates = new ArrayList<>(TRIAL_COUNT);
+ readRemoteFile("seq");
+ }
+
+ @Test
+ public void randReadRemoteFile() throws Exception {
+ readRemoteFile("rand");
+ }
+
+ @Test
+ public void seqWriteRemoteFile() throws Exception {
+ writeRemoteFile("seq");
+ }
+
+ @Test
+ public void randWriteRemoteFile() throws Exception {
+ writeRemoteFile("rand");
+ }
+
+ private void readRemoteFile(String mode) throws DeviceNotAvailableException {
+ pushMeasureIoBinToMicrodroid();
// Cache the file in memory for the host.
- String cmd = "cat " + mAuthFsTestRule.TEST_DIR + "/input.4m > /dev/null";
- mAuthFsTestRule.getAndroid().run(cmd);
+ mAuthFsTestRule
+ .getAndroid()
+ .run("cat " + mAuthFsTestRule.TEST_DIR + "/input.4m > /dev/null");
+
+ String filePath = mAuthFsTestRule.MOUNT_DIR + "/3";
+ int fileSizeMb = 4;
+ String cmd = MEASURE_IO_BIN_PATH + " " + filePath + " " + fileSizeMb + " " + mode + " r";
+ List<Double> rates = new ArrayList<>(TRIAL_COUNT);
for (int i = 0; i < TRIAL_COUNT + 1; ++i) {
mAuthFsTestRule.runFdServerOnAndroid(
"--open-ro 3:input.4m --open-ro 4:input.4m.fsv_meta", "--ro-fds 3:4");
mAuthFsTestRule.runAuthFsOnMicrodroid("--remote-ro-file 3:" + DIGEST_4M);
- double elapsedSeconds = measureSeqReadOnMicrodroid("3");
- transferRates.add(INPUT_SIZE_IN_MB / elapsedSeconds);
+
+ String rate = mAuthFsTestRule.getMicrodroid().run(cmd);
+ rates.add(Double.parseDouble(rate));
}
- reportMetrics(transferRates, "seq_read", "mb_per_sec");
+ reportMetrics(rates, mode + "_read", "mb_per_sec");
}
- private double measureSeqReadOnMicrodroid(String filename) throws DeviceNotAvailableException {
- String cmd = "cat " + mAuthFsTestRule.MOUNT_DIR + "/" + filename + " > /dev/null";
- // Ideally, we should measure the time in the VM to avoid the adb and host tests latency.
- double startTime = System.nanoTime();
- mAuthFsTestRule.getMicrodroid().run(cmd);
- double elapsedSeconds = (System.nanoTime() - startTime) / NANO_SECS_PER_SEC;
- return elapsedSeconds;
+ private void writeRemoteFile(String mode) throws DeviceNotAvailableException {
+ pushMeasureIoBinToMicrodroid();
+ String filePath = mAuthFsTestRule.MOUNT_DIR + "/5";
+ int fileSizeMb = 8;
+ String cmd = MEASURE_IO_BIN_PATH + " " + filePath + " " + fileSizeMb + " " + mode + " w";
+ List<Double> rates = new ArrayList<>(TRIAL_COUNT);
+ for (int i = 0; i < TRIAL_COUNT + 1; ++i) {
+ mAuthFsTestRule.runFdServerOnAndroid(
+ "--open-rw 5:" + mAuthFsTestRule.TEST_OUTPUT_DIR + "/out.file", "--rw-fds 5");
+ mAuthFsTestRule.runAuthFsOnMicrodroid("--remote-new-rw-file 5");
+
+ String rate = mAuthFsTestRule.getMicrodroid().run(cmd);
+ rates.add(Double.parseDouble(rate));
+ }
+ reportMetrics(rates, mode + "_write", "mb_per_sec");
+ }
+
+ private void pushMeasureIoBinToMicrodroid() throws DeviceNotAvailableException {
+ File measureReadBin = mAuthFsTestRule.findTestFile(getBuild(), MEASURE_IO_BIN_NAME);
+ assertThat(measureReadBin.exists()).isTrue();
+ mAuthFsTestRule.getMicrodroidDevice().pushFile(measureReadBin, MEASURE_IO_BIN_PATH);
+ assertThat(mAuthFsTestRule.getMicrodroid().run("ls " + MEASURE_IO_BIN_PATH))
+ .isEqualTo(MEASURE_IO_BIN_PATH);
}
private void reportMetrics(List<Double> metrics, String name, String unit) {
diff --git a/authfs/tests/java/src/com/android/fs/AuthFsHostTest.java b/authfs/tests/java/src/com/android/fs/AuthFsHostTest.java
index 2deb490..14dc88b 100644
--- a/authfs/tests/java/src/com/android/fs/AuthFsHostTest.java
+++ b/authfs/tests/java/src/com/android/fs/AuthFsHostTest.java
@@ -52,7 +52,7 @@
private static final String FSVERITY_BIN = "/data/local/tmp/fsverity";
/** Mount point of authfs on Microdroid during the test */
- private static final String MOUNT_DIR = "/data/local/tmp";
+ private static final String MOUNT_DIR = AuthFsTestRule.MOUNT_DIR;
/** Input manifest path in the VM. */
private static final String INPUT_MANIFEST_PATH = "/mnt/apk/assets/input_manifest.pb";
diff --git a/authfs/tests/java/src/com/android/fs/AuthFsTestRule.java b/authfs/tests/java/src/com/android/fs/AuthFsTestRule.java
index 34a403e..045ecc0 100644
--- a/authfs/tests/java/src/com/android/fs/AuthFsTestRule.java
+++ b/authfs/tests/java/src/com/android/fs/AuthFsTestRule.java
@@ -62,10 +62,10 @@
private static final String TEST_APK_NAME = "MicrodroidTestApp.apk";
/** Output directory where the test can generate output on Android */
- private static final String TEST_OUTPUT_DIR = "/data/local/tmp/authfs/output_dir";
+ static final String TEST_OUTPUT_DIR = "/data/local/tmp/authfs/output_dir";
/** Mount point of authfs on Microdroid during the test */
- static final String MOUNT_DIR = "/data/local/tmp";
+ static final String MOUNT_DIR = "/data/local/tmp/mnt";
/** VM's log file */
private static final String LOG_PATH = TEST_OUTPUT_DIR + "/log.txt";
@@ -85,6 +85,7 @@
private static final int VMADDR_CID_HOST = 2;
private static TestInformation sTestInfo;
+ private static ITestDevice sMicrodroidDevice;
private static CommandRunner sAndroid;
private static CommandRunner sMicrodroid;
@@ -110,18 +111,21 @@
// For each test case, boot and adb connect to a new Microdroid
CLog.i("Starting the shared VM");
- ITestDevice microdroidDevice =
+ sMicrodroidDevice =
MicrodroidBuilder.fromFile(
- findTestApk(testInfo.getBuildInfo()), VM_CONFIG_PATH_IN_APK)
+ findTestFile(testInfo.getBuildInfo(), TEST_APK_NAME),
+ VM_CONFIG_PATH_IN_APK)
.debugLevel("full")
.build((TestDevice) androidDevice);
// From this point on, we need to tear down the Microdroid instance
- sMicrodroid = new CommandRunner(microdroidDevice);
+ sMicrodroid = new CommandRunner(sMicrodroidDevice);
+
+ sMicrodroid.runForResult("mkdir -p " + MOUNT_DIR);
// Root because authfs (started from shell in this test) currently require root to open
// /dev/fuse and mount the FUSE.
- assertThat(microdroidDevice.enableAdbRoot()).isTrue();
+ assertThat(sMicrodroidDevice.enableAdbRoot()).isTrue();
}
static void tearDownClass(TestInformation testInfo) throws DeviceNotAvailableException {
@@ -148,6 +152,11 @@
return sMicrodroid;
}
+ static ITestDevice getMicrodroidDevice() {
+ assertThat(sMicrodroidDevice).isNotNull();
+ return sMicrodroidDevice;
+ }
+
@Override
public Statement apply(final Statement base, Description description) {
return super.apply(
@@ -205,11 +214,11 @@
}
}
- private static File findTestApk(IBuildInfo buildInfo) {
+ static File findTestFile(IBuildInfo buildInfo, String fileName) {
try {
- return (new CompatibilityBuildHelper(buildInfo)).getTestFile(TEST_APK_NAME);
+ return (new CompatibilityBuildHelper(buildInfo)).getTestFile(fileName);
} catch (FileNotFoundException e) {
- fail("Missing test file: " + TEST_APK_NAME);
+ fail("Missing test file: " + fileName);
return null;
}
}
diff --git a/authfs/tests/measure_io.cpp b/authfs/tests/measure_io.cpp
new file mode 100644
index 0000000..e1f2fb8
--- /dev/null
+++ b/authfs/tests/measure_io.cpp
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+
+#include <android-base/unique_fd.h>
+#include <assert.h>
+#include <err.h>
+#include <fcntl.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <algorithm>
+#include <iomanip>
+#include <iostream>
+#include <random>
+
+using android::base::unique_fd;
+
+constexpr int kBlockSizeBytes = 4096;
+constexpr int kNumBytesPerMB = 1024 * 1024;
+
+int main(int argc, const char *argv[]) {
+ if (argc != 5 || !(strcmp(argv[3], "rand") == 0 || strcmp(argv[3], "seq") == 0) ||
+ !(strcmp(argv[4], "r") == 0 || strcmp(argv[4], "w") == 0)) {
+ errx(EXIT_FAILURE, "Usage: %s <filename> <file_size_mb> <rand|seq> <r|w>", argv[0]);
+ }
+ int file_size_mb = std::stoi(argv[2]);
+ bool is_rand = (strcmp(argv[3], "rand") == 0);
+ bool is_read = (strcmp(argv[4], "r") == 0);
+ const int block_count = file_size_mb * kNumBytesPerMB / kBlockSizeBytes;
+ std::vector<int> offsets(block_count);
+ for (auto i = 0; i < block_count; ++i) {
+ offsets[i] = i * kBlockSizeBytes;
+ }
+ if (is_rand) {
+ std::mt19937 rd{std::random_device{}()};
+ std::shuffle(offsets.begin(), offsets.end(), rd);
+ }
+ unique_fd fd(open(argv[1], (is_read ? O_RDONLY : O_WRONLY) | O_CLOEXEC));
+ if (fd.get() == -1) {
+ errx(EXIT_FAILURE, "failed to open file: %s", argv[1]);
+ }
+
+ char buf[kBlockSizeBytes];
+ clock_t start = clock();
+ for (auto i = 0; i < block_count; ++i) {
+ auto bytes = is_read ? pread(fd, buf, kBlockSizeBytes, offsets[i])
+ : pwrite(fd, buf, kBlockSizeBytes, offsets[i]);
+ if (bytes == 0) {
+ errx(EXIT_FAILURE, "unexpected end of file");
+ } else if (bytes == -1) {
+ errx(EXIT_FAILURE, "failed to read");
+ }
+ }
+ if (!is_read) {
+ // Writes all the buffered modifications to the open file.
+ assert(syncfs(fd) == 0);
+ }
+ double elapsed_seconds = ((double)clock() - start) / CLOCKS_PER_SEC;
+ double rate = (double)file_size_mb / elapsed_seconds;
+ std::cout << std::setprecision(12) << rate << std::endl;
+
+ return EXIT_SUCCESS;
+}
diff --git a/docs/getting_started/index.md b/docs/getting_started/index.md
index 34a990d..8a1e6dd 100644
--- a/docs/getting_started/index.md
+++ b/docs/getting_started/index.md
@@ -33,7 +33,7 @@
### Pixel 6 and 6 Pro
If the device is running Android 12, join the [Android Beta
-Program](https://www.google.com/android/beta) to uprade to Android 13 Beta.
+Program](https://www.google.com/android/beta) to upgrade to Android 13 Beta.
Once upgraded to Android 13, execute the following command to enable pKVM.
@@ -66,11 +66,19 @@
```
Finally, if the `pvmfw` partition has been corrupted, both slots may be flashed
-using the [`pvmfw.img` pre-built](https://android.googlesource.com/platform/packages/modules/Virtualization/+/refs/heads/master/pvmfw/pvmfw.img)
+using the [`pvmfw.img` pre-built](https://android.googlesource.com/platform/packages/modules/Virtualization/+/08deac98acefd62e222edfa374d5292458cf97eb%5E/pvmfw/pvmfw.img)
as long as the bootloader remains unlocked. Otherwise, a fresh install of
Android 13 followed by the manual steps above for flashing the `other` slot
should be used as a last resort.
+Starting in Android 14, `pvmfw.img` can be built using the Android Build system:
+```
+lunch <target> # where PRODUCT_BUILD_PVMFW_IMAGE=true
+m pvmfwimage # partition image under ${ANDROID_PRODUCT_OUT}/pvmfw.img
+```
+Note that the result is not intended to be used in Android 13 as not
+backward-compatibility is guaranteed.
+
## Running demo app
The instruction is [here](../../demo/README.md).
diff --git a/libs/apkverify/Android.bp b/libs/apkverify/Android.bp
index 78192d2..1862820 100644
--- a/libs/apkverify/Android.bp
+++ b/libs/apkverify/Android.bp
@@ -33,6 +33,7 @@
name: "libapkverify.test",
defaults: ["libapkverify.defaults"],
test_suites: ["general-tests"],
+ rustlibs: ["libhex"],
data: ["tests/data/*"],
}
diff --git a/libs/apkverify/src/v4.rs b/libs/apkverify/src/v4.rs
index 715f742..6c085f6 100644
--- a/libs/apkverify/src/v4.rs
+++ b/libs/apkverify/src/v4.rs
@@ -312,10 +312,6 @@
const TEST_APK_PATH: &str = "tests/data/v4-digest-v3-Sha256withEC.apk";
- fn hexstring_from(s: &[u8]) -> String {
- s.iter().map(|byte| format!("{:02x}", byte)).reduce(|i, j| i + &j).unwrap_or_default()
- }
-
#[test]
fn parse_idsig_file() {
let parsed = V4Signature::from_idsig_path(format!("{}.idsig", TEST_APK_PATH)).unwrap();
@@ -325,22 +321,22 @@
let hi = parsed.hashing_info;
assert_eq!(HashAlgorithm::SHA256, hi.hash_algorithm);
assert_eq!(12, hi.log2_blocksize);
- assert_eq!("", hexstring_from(hi.salt.as_ref()));
+ assert_eq!("", hex::encode(hi.salt.as_ref()));
assert_eq!(
"77f063b48b63f846690fa76450a8d3b61a295b6158f50592e873f76dbeeb0201",
- hexstring_from(hi.raw_root_hash.as_ref())
+ hex::encode(hi.raw_root_hash.as_ref())
);
let si = parsed.signing_info;
assert_eq!(
"c02fe2eddeb3078801828b930de546ea4f98d37fb98b40c7c7ed169b0d713583",
- hexstring_from(si.apk_digest.as_ref())
+ hex::encode(si.apk_digest.as_ref())
);
- assert_eq!("", hexstring_from(si.additional_data.as_ref()));
+ assert_eq!("", hex::encode(si.additional_data.as_ref()));
assert_eq!(
"3046022100fb6383ba300dc7e1e6931a25b381398a16e5575baefd82afd12ba88660d9a6\
4c022100ebdcae13ab18c4e30bf6ae634462e526367e1ba26c2647a1d87a0f42843fc128",
- hexstring_from(si.signature.as_ref())
+ hex::encode(si.signature.as_ref())
);
assert_eq!(SignatureAlgorithmID::EcdsaWithSha256, si.signature_algorithm_id);
diff --git a/microdroid_manager/Android.bp b/microdroid_manager/Android.bp
index 4b06b3e..8741fb8 100644
--- a/microdroid_manager/Android.bp
+++ b/microdroid_manager/Android.bp
@@ -34,6 +34,7 @@
"libonce_cell",
"libopenssl",
"libprotobuf",
+ "libregex",
"librpcbinder_rs",
"librustutils",
"libscopeguard",
diff --git a/microdroid_manager/src/main.rs b/microdroid_manager/src/main.rs
index 78f8bb4..4326f5b 100644
--- a/microdroid_manager/src/main.rs
+++ b/microdroid_manager/src/main.rs
@@ -18,6 +18,7 @@
mod instance;
mod ioutil;
mod payload;
+mod procutil;
mod swap;
mod vm_payload_service;
@@ -25,8 +26,12 @@
use crate::instance::{ApexData, ApkData, InstanceDisk, MicrodroidData, RootHash};
use crate::vm_payload_service::register_vm_payload_service;
use android_system_virtualizationcommon::aidl::android::system::virtualizationcommon::ErrorCode::ErrorCode;
-use android_system_virtualmachineservice::aidl::android::system::virtualmachineservice::IVirtualMachineService::{
- VM_BINDER_SERVICE_PORT, VM_STREAM_SERVICE_PORT, IVirtualMachineService,
+use android_system_virtualmachineservice::aidl::android::system::virtualmachineservice::{
+ IVirtualMachineService::{
+ IVirtualMachineService, VM_BINDER_SERVICE_PORT, VM_STREAM_SERVICE_PORT,
+ },
+ VirtualMachineCpuStatus::VirtualMachineCpuStatus,
+ VirtualMachineMemStatus::VirtualMachineMemStatus,
};
use anyhow::{anyhow, bail, ensure, Context, Error, Result};
use apkverify::{get_public_key_der, verify, V4Signature};
@@ -36,13 +41,15 @@
use itertools::sorted;
use log::{error, info};
use microdroid_metadata::{write_metadata, Metadata, PayloadMetadata};
-use microdroid_payload_config::{Task, TaskType, VmPayloadConfig, OsConfig};
+use microdroid_payload_config::{OsConfig, Task, TaskType, VmPayloadConfig};
use openssl::sha::Sha512;
use payload::{get_apex_data_from_payload, load_metadata, to_metadata};
+use procutil::{get_cpu_time, get_mem_info};
use rand::Fill;
use rpcbinder::get_vsock_rpc_interface;
use rustutils::system_properties;
use rustutils::system_properties::PropertyWatcher;
+use std::borrow::Cow::{Borrowed, Owned};
use std::convert::TryInto;
use std::fs::{self, create_dir, File, OpenOptions};
use std::io::Write;
@@ -50,6 +57,7 @@
use std::path::Path;
use std::process::{Child, Command, Stdio};
use std::str;
+use std::thread;
use std::time::{Duration, SystemTime};
use vsock::VsockStream;
@@ -89,6 +97,42 @@
InvalidConfig(String),
}
+fn send_vm_status() -> Result<()> {
+ let service = get_vms_rpc_binder()
+ .context("cannot connect to VirtualMachineService")
+ .map_err(|e| MicrodroidError::FailedToConnectToVirtualizationService(e.to_string()))?;
+
+ let one_second = Duration::from_millis(1000);
+ loop {
+ // Collect VM CPU time information and creating VmCpuStatus atom for metrics.
+ let cpu_time = get_cpu_time()?;
+ let vm_cpu_status = VirtualMachineCpuStatus {
+ cpu_time_user: cpu_time.user,
+ cpu_time_nice: cpu_time.nice,
+ cpu_time_sys: cpu_time.sys,
+ cpu_time_idle: cpu_time.idle,
+ };
+ service
+ .notifyCpuStatus(&vm_cpu_status)
+ .expect("Can't send information about VM CPU status");
+
+ // Collect VM memory information and creating VmMemStatus atom for metrics.
+ let mem_info = get_mem_info()?;
+ let vm_mem_status = VirtualMachineMemStatus {
+ mem_total: mem_info.total,
+ mem_free: mem_info.free,
+ mem_available: mem_info.available,
+ mem_buffer: mem_info.buffer,
+ mem_cached: mem_info.cached,
+ };
+ service
+ .notifyMemStatus(&vm_mem_status)
+ .expect("Can't send information about VM memory status");
+
+ thread::sleep(one_second);
+ }
+}
+
fn translate_error(err: &Error) -> (ErrorCode, String) {
if let Some(e) = err.downcast_ref::<MicrodroidError>() {
match e {
@@ -112,7 +156,7 @@
fn write_death_reason_to_serial(err: &Error) -> Result<()> {
let death_reason = if let Some(e) = err.downcast_ref::<MicrodroidError>() {
- match e {
+ Borrowed(match e {
MicrodroidError::FailedToConnectToVirtualizationService(_) => {
"MICRODROID_FAILED_TO_CONNECT_TO_VIRTUALIZATION_SERVICE"
}
@@ -121,9 +165,12 @@
"MICRODROID_PAYLOAD_VERIFICATION_FAILED"
}
MicrodroidError::InvalidConfig(_) => "MICRODROID_INVALID_PAYLOAD_CONFIG",
- }
+ })
} else {
- "MICRODROID_UNKNOWN_RUNTIME_ERROR"
+ // Send context information back after a separator, to ease diagnosis.
+ // These errors occur before the payload runs, so this should not leak sensitive
+ // information.
+ Owned(format!("MICRODROID_UNKNOWN_RUNTIME_ERROR|{:?}", err))
};
let death_reason_bytes = death_reason.as_bytes();
@@ -177,6 +224,13 @@
let service = get_vms_rpc_binder()
.context("cannot connect to VirtualMachineService")
.map_err(|e| MicrodroidError::FailedToConnectToVirtualizationService(e.to_string()))?;
+
+ thread::spawn(move || {
+ if let Err(e) = send_vm_status() {
+ error!("failed to get virtual machine status: {:?}", e);
+ }
+ });
+
match try_run_payload(&service) {
Ok(code) => {
info!("notifying payload finished");
@@ -351,7 +405,7 @@
)
.context("Failed to run zipfuse")?;
- let config = load_config(payload_metadata)?;
+ let config = load_config(payload_metadata).context("Failed to load payload metadata")?;
let task = config
.task
@@ -386,10 +440,12 @@
// Wait until zipfuse has mounted the APK so we can access the payload
wait_for_property_true(APK_MOUNT_DONE_PROP).context("Failed waiting for APK mount done")?;
- system_properties::write("dev.bootcomplete", "1").context("set dev.bootcomplete")?;
register_vm_payload_service(service.clone(), dice)?;
ProcessState::start_thread_pool();
- exec_task(task, service)
+
+ system_properties::write("dev.bootcomplete", "1").context("set dev.bootcomplete")?;
+
+ exec_task(task, service).context("Failed to run payload")
}
fn control_service(action: &str, service: &str) -> Result<()> {
@@ -674,7 +730,8 @@
PayloadMetadata::config_path(path) => {
let path = Path::new(&path);
info!("loading config from {:?}...", path);
- let file = ioutil::wait_for_file(path, WAIT_TIMEOUT)?;
+ let file = ioutil::wait_for_file(path, WAIT_TIMEOUT)
+ .with_context(|| format!("Failed to read {:?}", path))?;
Ok(serde_json::from_reader(file)?)
}
PayloadMetadata::config(payload_config) => {
@@ -769,7 +826,7 @@
let abi = value.split(',').next().ok_or_else(|| anyhow!("no abilist"))?;
let path = format!("/mnt/apk/lib/{}/{}", abi, name);
- let metadata = fs::metadata(&path)?;
+ let metadata = fs::metadata(&path).with_context(|| format!("Unable to access {}", path))?;
if !metadata.is_file() {
bail!("{} is not a file", &path);
}
diff --git a/microdroid_manager/src/procutil.rs b/microdroid_manager/src/procutil.rs
new file mode 100644
index 0000000..b323ca9
--- /dev/null
+++ b/microdroid_manager/src/procutil.rs
@@ -0,0 +1,125 @@
+// Copyright 2022, 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.
+
+use anyhow::{Context, Result};
+use libc::{sysconf, _SC_CLK_TCK};
+use regex::Regex;
+use std::fs::{self, File};
+use std::io::{BufRead, BufReader};
+
+const MILLIS_PER_SEC: i64 = 1000;
+
+pub struct CpuTime {
+ pub user: i64,
+ pub nice: i64,
+ pub sys: i64,
+ pub idle: i64,
+}
+
+pub struct MemInfo {
+ pub total: i64,
+ pub free: i64,
+ pub available: i64,
+ pub buffer: i64,
+ pub cached: i64,
+}
+
+// Get CPU time information from /proc/stat
+//
+// /proc/stat example(omitted):
+// cpu 24790952 21104390 10771070 10480973587 1700955 0 410931 0 316532 0
+// cpu0 169636 141307 61153 81785791 9605 0 183524 0 1345 0
+// cpu1 182431 198327 68273 81431817 10445 0 32392 0 2616 0
+// cpu2 183209 174917 68591 81933935 12239 0 10042 0 2415 0
+// cpu3 183413 177758 69908 81927474 13354 0 5853 0 2491 0
+// intr 7913477443 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+// ctxt 10326710014
+// btime 1664123605
+// processes 9225712
+// procs_running 1
+// procs_blocked 0
+// softirq 2683914305 14595298 304837101 1581 327291100 16397051 0 208857783 1024640365 787932 786506094
+//
+// expected output:
+// user: 24790952
+// nice: 21104390
+// sys: 10771070
+// idle: 10480973587
+pub fn get_cpu_time() -> Result<CpuTime> {
+ let re = Regex::new(r"^cpu\s+([\d]+)\s([\d]+)\s([\d]+)\s([\d]+)").unwrap();
+
+ let mut proc_stat = BufReader::new(File::open("/proc/stat")?);
+ let mut line = String::new();
+ proc_stat.read_line(&mut line)?;
+ let data_list = re.captures(&line).context("Failed to capture values")?;
+
+ let ticks_per_sec = unsafe { sysconf(_SC_CLK_TCK) } as i64;
+ let cpu_time = CpuTime {
+ user: data_list.get(1).unwrap().as_str().parse::<i64>()? * MILLIS_PER_SEC / ticks_per_sec,
+ nice: data_list.get(2).unwrap().as_str().parse::<i64>()? * MILLIS_PER_SEC / ticks_per_sec,
+ sys: data_list.get(3).unwrap().as_str().parse::<i64>()? * MILLIS_PER_SEC / ticks_per_sec,
+ idle: data_list.get(4).unwrap().as_str().parse::<i64>()? * MILLIS_PER_SEC / ticks_per_sec,
+ };
+ Ok(cpu_time)
+}
+
+// Get memory information from /proc/meminfo
+//
+// /proc/meminfo example(omitted):
+// MemTotal: 263742736 kB
+// MemFree: 37144204 kB
+// MemAvailable: 249168700 kB
+// Buffers: 10231296 kB
+// Cached: 189502836 kB
+// SwapCached: 113848 kB
+// Active: 132266424 kB
+// Inactive: 73587504 kB
+// Active(anon): 1455240 kB
+// Inactive(anon): 6993584 kB
+// Active(file): 130811184 kB
+// Inactive(file): 66593920 kB
+// Unevictable: 56436 kB
+// Mlocked: 56436 kB
+// SwapTotal: 255123452 kB
+// SwapFree: 254499068 kB
+// Dirty: 596 kB
+// Writeback: 0 kB
+// AnonPages: 5295864 kB
+// Mapped: 3512608 kB
+//
+// expected output:
+// total: 263742736
+// free: 37144204
+// available: 249168700
+// buffer: 10231296
+// cached: 189502836
+pub fn get_mem_info() -> Result<MemInfo> {
+ let re = Regex::new(r"^.*?:\s+([0-9]+)\skB").unwrap();
+
+ let proc_mem_info = fs::read_to_string("/proc/meminfo")?;
+ let data_list: Vec<_> = proc_mem_info
+ .trim()
+ .splitn(6, '\n')
+ .map(|s| re.captures(s).context("Failed to capture values").ok()?.get(1))
+ .collect();
+
+ let mem_info = MemInfo {
+ total: data_list[0].unwrap().as_str().parse::<i64>()?,
+ free: data_list[1].unwrap().as_str().parse::<i64>()?,
+ available: data_list[2].unwrap().as_str().parse::<i64>()?,
+ buffer: data_list[3].unwrap().as_str().parse::<i64>()?,
+ cached: data_list[4].unwrap().as_str().parse::<i64>()?,
+ };
+ Ok(mem_info)
+}
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 51c145e..466acc7 100644
--- a/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java
+++ b/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java
@@ -418,6 +418,19 @@
}
@Test
+ public void bootFailsWhenBinaryPathIsInvalid() throws Exception {
+ VirtualMachineConfig.Builder builder = mInner.newVmConfigBuilder()
+ .setPayloadBinaryPath("DoesNotExist.so");
+ VirtualMachineConfig normalConfig = builder.setDebugLevel(DEBUG_LEVEL_FULL).build();
+ mInner.forceCreateNewVirtualMachine("test_vm_invalid_binary_path", normalConfig);
+
+ BootResult bootResult = tryBootVm(TAG, "test_vm_invalid_binary_path");
+ assertThat(bootResult.payloadStarted).isFalse();
+ assertThat(bootResult.deathReason).isEqualTo(
+ VirtualMachineCallback.STOP_REASON_MICRODROID_UNKNOWN_RUNTIME_ERROR);
+ }
+
+ @Test
public void sameInstancesShareTheSameVmObject() throws Exception {
VirtualMachineConfig config = mInner.newVmConfigBuilder()
.setPayloadBinaryPath("MicrodroidTestNativeLib.so")
diff --git a/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineDebugInfo.aidl b/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineDebugInfo.aidl
index bed4097..424eec1 100644
--- a/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineDebugInfo.aidl
+++ b/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineDebugInfo.aidl
@@ -28,9 +28,6 @@
/** The UID of the process which requested the VM. */
int requesterUid;
- /** The SID of the process which requested the VM. */
- @utf8InCpp String requesterSid;
-
/**
* The PID of the process which requested the VM. Note that this process may no longer exist and
* the PID may have been reused for a different process, so this should not be trusted.
diff --git a/virtualizationservice/aidl/android/system/virtualmachineservice/IVirtualMachineService.aidl b/virtualizationservice/aidl/android/system/virtualmachineservice/IVirtualMachineService.aidl
index e8c1724..4fa5fa0 100644
--- a/virtualizationservice/aidl/android/system/virtualmachineservice/IVirtualMachineService.aidl
+++ b/virtualizationservice/aidl/android/system/virtualmachineservice/IVirtualMachineService.aidl
@@ -16,6 +16,8 @@
package android.system.virtualmachineservice;
import android.system.virtualizationcommon.ErrorCode;
+import android.system.virtualmachineservice.VirtualMachineCpuStatus;
+import android.system.virtualmachineservice.VirtualMachineMemStatus;
/** {@hide} */
interface IVirtualMachineService {
@@ -56,4 +58,14 @@
* Notifies that an error has occurred inside the VM..
*/
void notifyError(ErrorCode errorCode, in String message);
+
+ /**
+ * Notifies the current CPU status of the VM.
+ */
+ void notifyCpuStatus(in VirtualMachineCpuStatus cpuStatus);
+
+ /**
+ * Notifies the current memory status of the VM.
+ */
+ void notifyMemStatus(in VirtualMachineMemStatus memStatus);
}
diff --git a/virtualizationservice/aidl/android/system/virtualmachineservice/VirtualMachineCpuStatus.aidl b/virtualizationservice/aidl/android/system/virtualmachineservice/VirtualMachineCpuStatus.aidl
new file mode 100644
index 0000000..307c3f9
--- /dev/null
+++ b/virtualizationservice/aidl/android/system/virtualmachineservice/VirtualMachineCpuStatus.aidl
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2022 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 android.system.virtualmachineservice;
+
+parcelable VirtualMachineCpuStatus {
+ long cpu_time_user;
+ long cpu_time_nice;
+ long cpu_time_sys;
+ long cpu_time_idle;
+}
diff --git a/virtualizationservice/aidl/android/system/virtualmachineservice/VirtualMachineMemStatus.aidl b/virtualizationservice/aidl/android/system/virtualmachineservice/VirtualMachineMemStatus.aidl
new file mode 100644
index 0000000..3de57c6
--- /dev/null
+++ b/virtualizationservice/aidl/android/system/virtualmachineservice/VirtualMachineMemStatus.aidl
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2022 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 android.system.virtualmachineservice;
+
+parcelable VirtualMachineMemStatus {
+ long mem_total;
+ long mem_free;
+ long mem_available;
+ long mem_buffer;
+ long mem_cached;
+}
diff --git a/virtualizationservice/src/aidl.rs b/virtualizationservice/src/aidl.rs
index f956062..eb2bac4 100644
--- a/virtualizationservice/src/aidl.rs
+++ b/virtualizationservice/src/aidl.rs
@@ -14,13 +14,17 @@
//! Implementation of the AIDL interface of the VirtualizationService.
-use crate::atom::{write_vm_booted_stats, write_vm_creation_stats};
+use crate::atom::{
+ write_vm_booted_stats, write_vm_cpu_status_stats, write_vm_creation_stats,
+ write_vm_mem_status_stats,
+};
use crate::composite::make_composite_image;
use crate::crosvm::{CrosvmConfig, DiskFile, PayloadState, VmInstance, VmState};
use crate::payload::{add_microdroid_payload_images, add_microdroid_system_images};
+use crate::selinux::{getfilecon, SeContext};
use crate::{Cid, FIRST_GUEST_CID, SYSPROP_LAST_CID};
-use crate::selinux::{SeContext, getfilecon};
use android_os_permissions_aidl::aidl::android::os::IPermissionController;
+use android_system_virtualizationcommon::aidl::android::system::virtualizationcommon::ErrorCode::ErrorCode;
use android_system_virtualizationservice::aidl::android::system::virtualizationservice::{
DeathReason::DeathReason,
DiskImage::DiskImage,
@@ -29,39 +33,42 @@
IVirtualizationService::IVirtualizationService,
Partition::Partition,
PartitionType::PartitionType,
- VirtualMachineAppConfig::{VirtualMachineAppConfig, Payload::Payload},
+ VirtualMachineAppConfig::{Payload::Payload, VirtualMachineAppConfig},
VirtualMachineConfig::VirtualMachineConfig,
VirtualMachineDebugInfo::VirtualMachineDebugInfo,
VirtualMachinePayloadConfig::VirtualMachinePayloadConfig,
VirtualMachineRawConfig::VirtualMachineRawConfig,
VirtualMachineState::VirtualMachineState,
};
+use android_system_virtualmachineservice::aidl::android::system::virtualmachineservice::{
+ IVirtualMachineService::{
+ BnVirtualMachineService, IVirtualMachineService, VM_BINDER_SERVICE_PORT,
+ VM_STREAM_SERVICE_PORT, VM_TOMBSTONES_SERVICE_PORT,
+ },
+ VirtualMachineCpuStatus::VirtualMachineCpuStatus,
+ VirtualMachineMemStatus::VirtualMachineMemStatus,
+};
+use anyhow::{anyhow, bail, Context, Result};
+use apkverify::{HashAlgorithm, V4Signature};
use binder::{
self, BinderFeatures, ExceptionCode, Interface, LazyServiceGuard, ParcelFileDescriptor,
SpIBinder, Status, StatusCode, Strong, ThreadState,
};
-use android_system_virtualmachineservice::aidl::android::system::virtualmachineservice::IVirtualMachineService::{
- BnVirtualMachineService, IVirtualMachineService, VM_BINDER_SERVICE_PORT,
- VM_STREAM_SERVICE_PORT, VM_TOMBSTONES_SERVICE_PORT,
-};
-use android_system_virtualizationcommon::aidl::android::system::virtualizationcommon::ErrorCode::ErrorCode;
-use anyhow::{anyhow, bail, Context, Result};
-use rpcbinder::run_rpc_server_with_factory;
use disk::QcowFile;
-use apkverify::{HashAlgorithm, V4Signature};
use log::{debug, error, info, warn};
-use microdroid_payload_config::{VmPayloadConfig, OsConfig, Task, TaskType};
+use microdroid_payload_config::{OsConfig, Task, TaskType, VmPayloadConfig};
+use rpcbinder::run_rpc_server_with_factory;
use rustutils::system_properties;
use semver::VersionReq;
use std::convert::TryInto;
use std::ffi::CStr;
use std::fs::{create_dir, File, OpenOptions};
-use std::io::{Error, ErrorKind, Write, Read};
+use std::io::{Error, ErrorKind, Read, Write};
use std::num::NonZeroU32;
use std::os::unix::io::{FromRawFd, IntoRawFd};
use std::path::{Path, PathBuf};
use std::sync::{Arc, Mutex, Weak};
-use tombstoned_client::{TombstonedConnection, DebuggerdDumpType};
+use tombstoned_client::{DebuggerdDumpType, TombstonedConnection};
use vmconfig::VmConfig;
use vsock::{VsockListener, VsockStream};
use zip::ZipArchive;
@@ -111,8 +118,6 @@
.or(Err(StatusCode::UNKNOWN_ERROR))?;
writeln!(file, "\trequester_uid: {}", vm.requester_uid)
.or(Err(StatusCode::UNKNOWN_ERROR))?;
- writeln!(file, "\trequester_sid: {}", vm.requester_sid)
- .or(Err(StatusCode::UNKNOWN_ERROR))?;
writeln!(file, "\trequester_debug_pid: {}", vm.requester_debug_pid)
.or(Err(StatusCode::UNKNOWN_ERROR))?;
}
@@ -217,7 +222,6 @@
cid: vm.cid as i32,
temporaryDirectory: vm.temporary_directory.to_string_lossy().to_string(),
requesterUid: vm.requester_uid as i32,
- requesterSid: vm.requester_sid.clone(),
requesterPid: vm.requester_debug_pid,
state: get_state(&vm),
})
@@ -346,7 +350,6 @@
let console_fd = console_fd.map(clone_file).transpose()?;
let log_fd = log_fd.map(clone_file).transpose()?;
let requester_uid = ThreadState::get_calling_uid();
- let requester_sid = get_calling_sid()?;
let requester_debug_pid = ThreadState::get_calling_pid();
let cid = next_cid().or(Err(ExceptionCode::ILLEGAL_STATE))?;
@@ -466,20 +469,14 @@
detect_hangup: is_app_config,
};
let instance = Arc::new(
- VmInstance::new(
- crosvm_config,
- temporary_directory,
- requester_uid,
- requester_sid,
- requester_debug_pid,
- )
- .map_err(|e| {
- error!("Failed to create VM with config {:?}: {:?}", config, e);
- Status::new_service_specific_error_str(
- -1,
- Some(format!("Failed to create VM: {:?}", e)),
- )
- })?,
+ VmInstance::new(crosvm_config, temporary_directory, requester_uid, requester_debug_pid)
+ .map_err(|e| {
+ error!("Failed to create VM with config {:?}: {:?}", config, e);
+ Status::new_service_specific_error_str(
+ -1,
+ Some(format!("Failed to create VM: {:?}", e)),
+ )
+ })?,
);
state.add_vm(Arc::downgrade(&instance));
Ok(VirtualMachine::create(instance))
@@ -705,27 +702,6 @@
footer: PathBuf,
}
-/// Gets the calling SID of the current Binder thread.
-fn get_calling_sid() -> Result<String, Status> {
- ThreadState::with_calling_sid(|sid| {
- if let Some(sid) = sid {
- match sid.to_str() {
- Ok(sid) => Ok(sid.to_owned()),
- Err(e) => {
- error!("SID was not valid UTF-8: {}", e);
- Err(Status::new_exception_str(
- ExceptionCode::ILLEGAL_ARGUMENT,
- Some(format!("SID was not valid UTF-8: {}", e)),
- ))
- }
- }
- } else {
- error!("Missing SID on createVm");
- Err(Status::new_exception_str(ExceptionCode::SECURITY, Some("Missing SID on createVm")))
- }
- })
-}
-
/// Checks whether the caller has a specific permission
fn check_permission(perm: &str) -> binder::Result<()> {
let calling_pid = ThreadState::get_calling_pid();
@@ -1168,6 +1144,36 @@
))
}
}
+
+ fn notifyCpuStatus(&self, status: &VirtualMachineCpuStatus) -> binder::Result<()> {
+ let cid = self.cid;
+ if let Some(vm) = self.state.lock().unwrap().get_vm(cid) {
+ info!("VM having CID {} encountered an error", cid);
+ write_vm_cpu_status_stats(vm.requester_uid as i32, &vm.name, status);
+ Ok(())
+ } else {
+ error!("notifyCurrentStatus is called from an unknown CID {}", cid);
+ Err(Status::new_service_specific_error_str(
+ -1,
+ Some(format!("cannot find a VM with CID {}", cid)),
+ ))
+ }
+ }
+
+ fn notifyMemStatus(&self, status: &VirtualMachineMemStatus) -> binder::Result<()> {
+ let cid = self.cid;
+ if let Some(vm) = self.state.lock().unwrap().get_vm(cid) {
+ info!("VM having CID {} encountered an error", cid);
+ write_vm_mem_status_stats(vm.requester_uid as i32, &vm.name, status);
+ Ok(())
+ } else {
+ error!("notifyCurrentStatus is called from an unknown CID {}", cid);
+ Err(Status::new_service_specific_error_str(
+ -1,
+ Some(format!("cannot find a VM with CID {}", cid)),
+ ))
+ }
+ }
}
impl VirtualMachineService {
diff --git a/virtualizationservice/src/atom.rs b/virtualizationservice/src/atom.rs
index eabb4cc..8c46ac5 100644
--- a/virtualizationservice/src/atom.rs
+++ b/virtualizationservice/src/atom.rs
@@ -22,11 +22,17 @@
VirtualMachineConfig::VirtualMachineConfig,
};
use android_system_virtualizationservice::binder::{Status, Strong};
+use android_system_virtualmachineservice::aidl::android::system::virtualmachineservice::{
+ VirtualMachineCpuStatus::VirtualMachineCpuStatus,
+ VirtualMachineMemStatus::VirtualMachineMemStatus,
+};
use anyhow::{anyhow, Result};
use binder::{ParcelFileDescriptor, ThreadState};
use log::{trace, warn};
use microdroid_payload_config::VmPayloadConfig;
-use statslog_virtualization_rust::{vm_booted, vm_creation_requested, vm_exited};
+use statslog_virtualization_rust::{
+ vm_booted, vm_cpu_status_reported, vm_creation_requested, vm_exited, vm_mem_status_reported,
+};
use std::time::{Duration, SystemTime};
use zip::ZipArchive;
@@ -206,3 +212,48 @@
Ok(_) => trace!("statslog_rust succeeded for virtualization service"),
}
}
+
+/// Write the stats of VM cpu status to statsd
+pub fn write_vm_cpu_status_stats(
+ uid: i32,
+ vm_identifier: &String,
+ cpu_status: &VirtualMachineCpuStatus,
+) {
+ let vm_cpu_status_reported = vm_cpu_status_reported::VmCpuStatusReported {
+ uid,
+ vm_identifier,
+ cpu_time_user_millis: cpu_status.cpu_time_user,
+ cpu_time_nice_millis: cpu_status.cpu_time_nice,
+ cpu_time_sys_millis: cpu_status.cpu_time_sys,
+ cpu_time_idle_millis: cpu_status.cpu_time_idle,
+ };
+ match vm_cpu_status_reported.stats_write() {
+ Err(e) => {
+ warn!("statslog_rust failed with error: {}", e);
+ }
+ Ok(_) => trace!("statslog_rust succeeded for virtualization service"),
+ }
+}
+
+/// Write the stats of VM memory status to statsd
+pub fn write_vm_mem_status_stats(
+ uid: i32,
+ vm_identifier: &String,
+ mem_status: &VirtualMachineMemStatus,
+) {
+ let vm_mem_status_reported = vm_mem_status_reported::VmMemStatusReported {
+ uid,
+ vm_identifier,
+ mem_total_kb: mem_status.mem_total,
+ mem_free_kb: mem_status.mem_free,
+ mem_available_kb: mem_status.mem_available,
+ mem_buffer_kb: mem_status.mem_buffer,
+ mem_cached_kb: mem_status.mem_cached,
+ };
+ match vm_mem_status_reported.stats_write() {
+ Err(e) => {
+ warn!("statslog_rust failed with error: {}", e);
+ }
+ Ok(_) => trace!("statslog_rust succeeded for virtualization service"),
+ }
+}
diff --git a/virtualizationservice/src/crosvm.rs b/virtualizationservice/src/crosvm.rs
index 54cdeb6..749970c 100644
--- a/virtualizationservice/src/crosvm.rs
+++ b/virtualizationservice/src/crosvm.rs
@@ -185,8 +185,6 @@
pub temporary_directory: PathBuf,
/// The UID of the process which requested the VM.
pub requester_uid: u32,
- /// The SID of the process which requested the VM.
- pub requester_sid: String,
/// The PID of the process which requested the VM. Note that this process may no longer exist
/// and the PID may have been reused for a different process, so this should not be trusted.
pub requester_debug_pid: i32,
@@ -210,7 +208,6 @@
config: CrosvmConfig,
temporary_directory: PathBuf,
requester_uid: u32,
- requester_sid: String,
requester_debug_pid: i32,
) -> Result<VmInstance, Error> {
validate_config(&config)?;
@@ -224,7 +221,6 @@
protected,
temporary_directory,
requester_uid,
- requester_sid,
requester_debug_pid,
callbacks: Default::default(),
stream: Mutex::new(None),
@@ -395,7 +391,12 @@
}
}
-fn death_reason(result: &Result<ExitStatus, io::Error>, failure_reason: &str) -> DeathReason {
+fn death_reason(result: &Result<ExitStatus, io::Error>, mut failure_reason: &str) -> DeathReason {
+ if let Some(position) = failure_reason.find('|') {
+ // Separator indicates extra context information is present after the failure name.
+ error!("Failure info: {}", &failure_reason[(position + 1)..]);
+ failure_reason = &failure_reason[..position];
+ }
if let Ok(status) = result {
match failure_reason {
"PVM_FIRMWARE_PUBLIC_KEY_MISMATCH" => {
diff --git a/virtualizationservice/src/main.rs b/virtualizationservice/src/main.rs
index cb10eff..327a45d 100644
--- a/virtualizationservice/src/main.rs
+++ b/virtualizationservice/src/main.rs
@@ -50,10 +50,7 @@
clear_temporary_files().expect("Failed to delete old temporary files");
let service = VirtualizationService::init();
- let service = BnVirtualizationService::new_binder(
- service,
- BinderFeatures { set_requesting_sid: true, ..BinderFeatures::default() },
- );
+ let service = BnVirtualizationService::new_binder(service, BinderFeatures::default());
register_lazy_service(BINDER_SERVICE_IDENTIFIER, service.as_binder()).unwrap();
info!("Registered Binder service, joining threadpool.");
ProcessState::join_thread_pool();