Merge "The test app built from AOSP is installable to T devices"
diff --git a/TEST_MAPPING b/TEST_MAPPING
index 11648c4..ea81bc4 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -28,9 +28,6 @@
},
{
"name": "ComposBenchmarkApp"
- },
- {
- "name": "AVFHostTestCases"
}
],
"imports": [
diff --git a/tests/benchmark_hostside/Android.bp b/tests/benchmark_hostside/Android.bp
deleted file mode 100644
index 354a260..0000000
--- a/tests/benchmark_hostside/Android.bp
+++ /dev/null
@@ -1,19 +0,0 @@
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-java_test_host {
- name: "AVFHostTestCases",
- srcs: ["java/**/*.java"],
- libs: [
- "tradefed",
- "compatibility-tradefed",
- "compatibility-host-util",
- ],
- static_libs: [
- "MicrodroidHostTestHelper",
- ],
- test_suites: [
- "general-tests",
- ],
-}
diff --git a/tests/benchmark_hostside/AndroidTest.xml b/tests/benchmark_hostside/AndroidTest.xml
deleted file mode 100644
index 5161269..0000000
--- a/tests/benchmark_hostside/AndroidTest.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-<configuration description="Tests for AVF">
- <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer">
- <option name="force-root" value="true" />
- </target_preparer>
-
- <test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
- <option name="jar" value="AVFHostTestCases.jar" />
- </test>
-</configuration>
\ No newline at end of file
diff --git a/tests/benchmark_hostside/java/android/avf/test/AVFHostTestCase.java b/tests/benchmark_hostside/java/android/avf/test/AVFHostTestCase.java
deleted file mode 100644
index cbc7188..0000000
--- a/tests/benchmark_hostside/java/android/avf/test/AVFHostTestCase.java
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
- * 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.
- */
-
-package android.avf.test;
-
-import android.platform.test.annotations.RootPermissionTest;
-
-import static com.android.tradefed.testtype.DeviceJUnit4ClassRunner.TestMetrics;
-
-import static com.google.common.truth.Truth.assertWithMessage;
-
-import com.android.microdroid.test.CommandRunner;
-import com.android.microdroid.test.MicrodroidHostTestCaseBase;
-import com.android.tradefed.log.LogUtil.CLog;
-import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.tradefed.util.CommandResult;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-@RootPermissionTest
-@RunWith(DeviceJUnit4ClassRunner.class)
-public final class AVFHostTestCase extends MicrodroidHostTestCaseBase {
-
- private static final String COMPOSD_CMD_BIN = "/apex/com.android.compos/bin/composd_cmd";
-
- // Files that define the "test" instance of CompOS
- private static final String COMPOS_TEST_ROOT = "/data/misc/apexdata/com.android.compos/test/";
-
- private static final String SYSTEM_SERVER_COMPILER_FILTER_PROP_NAME =
- "dalvik.vm.systemservercompilerfilter";
- private String mBackupSystemServerCompilerFilter;
-
- /** Boot time test related variables */
- private static final int BOOT_COMPLETE_TIMEOUT_MS = 10 * 60 * 1000;
- private static final int DEVICE_AVAILABLE_WAIT_TIMEOUT_MS = 3 * 60 * 1000;
- private static final double NANOS_IN_SEC = 1_000_000_000.0;
- private static final int ROUND_COUNT = 3;
- private static final String METRIC_PREFIX = "avf_perf/compos/";
-
- @Before
- public void setUp() throws Exception {
- testIfDeviceIsCapable(getDevice());
-
- String value = getDevice().getProperty(SYSTEM_SERVER_COMPILER_FILTER_PROP_NAME);
- if (value == null) {
- mBackupSystemServerCompilerFilter = "";
- } else {
- mBackupSystemServerCompilerFilter = value;
- }
-
- getDevice().setProperty(SYSTEM_SERVER_COMPILER_FILTER_PROP_NAME, "speed");
- }
-
- @After
- public void tearDown() throws Exception {
- CommandRunner android = new CommandRunner(getDevice());
-
- // Clear up any CompOS instance files we created
- android.tryRun("rm", "-rf", COMPOS_TEST_ROOT);
-
- if (mBackupSystemServerCompilerFilter != null) {
- CLog.d("Restore dalvik.vm.systemservercompilerfilter to "
- + mBackupSystemServerCompilerFilter);
- getDevice().setProperty(SYSTEM_SERVER_COMPILER_FILTER_PROP_NAME,
- mBackupSystemServerCompilerFilter);
- }
- }
-
- @Test
- public void testBootWithAndWithoutCompOS() throws Exception {
-
- double[] bootWithCompOsTime = new double[ROUND_COUNT];
- double[] bootWithoutCompOsTime = new double[ROUND_COUNT];
-
- for (int round = 0; round < ROUND_COUNT; ++round) {
-
- // Boot time with compilation OS test.
- getDevice().waitForDeviceAvailable(DEVICE_AVAILABLE_WAIT_TIMEOUT_MS);
- reInstallApex();
- compileStagedApex();
- long start = System.nanoTime();
- rebootAndWaitBootCompleted();
- long elapsedWithCompOS = System.nanoTime() - start;
- double elapsedSec = elapsedWithCompOS / NANOS_IN_SEC;
- bootWithCompOsTime[round] = elapsedSec;
- CLog.i("Boot time with compilation OS took " + elapsedSec + "s");
-
- // Boot time without compilation OS test.
- getDevice().waitForDeviceAvailable(DEVICE_AVAILABLE_WAIT_TIMEOUT_MS);
- reInstallApex();
- start = System.nanoTime();
- rebootAndWaitBootCompleted();
- long elapsedWithoutCompOS = System.nanoTime() - start;
- elapsedSec = elapsedWithoutCompOS / NANOS_IN_SEC;
- bootWithoutCompOsTime[round] = elapsedSec;
- CLog.i("Boot time without compilation OS took " + elapsedSec + "s");
-
- assertWithMessage("Boot time with compilation OS is higher than without")
- .that(elapsedWithCompOS).isLessThan(elapsedWithoutCompOS);
- }
-
- reportMetric("boot_time_with_compos", "s", bootWithCompOsTime);
- reportMetric("boot_time_without_compos", "s", bootWithoutCompOsTime);
- }
-
- private void reportMetric(String name, String unit, double[] values) {
- double sum = 0;
- double min = Double.MAX_VALUE;
- double max = Double.MIN_VALUE;
-
- for (double val : values) {
- sum += val;
- min = val < min ? val : min;
- max = val > max ? val : max;
- }
-
- double average = sum / values.length;
-
- double variance = 0;
- for (double val : values) {
- final double tmp = val - average;
- variance += tmp * tmp;
- }
- double stdev = Math.sqrt(variance / (double) (values.length - 1));
-
- TestMetrics metrics = new TestMetrics();
- metrics.addTestMetric(METRIC_PREFIX + name + "_average_" + unit, Double.toString(average));
- metrics.addTestMetric(METRIC_PREFIX + name + "_min_" + unit, Double.toString(min));
- metrics.addTestMetric(METRIC_PREFIX + name + "_max_" + unit, Double.toString(max));
- metrics.addTestMetric(METRIC_PREFIX + name + "_stdev_" + unit, Double.toString(stdev));
- }
-
- private void rebootAndWaitBootCompleted() throws Exception {
- getDevice().nonBlockingReboot();
- getDevice().waitForDeviceOnline();
- getDevice().waitForBootComplete(BOOT_COMPLETE_TIMEOUT_MS);
- }
-
- private void compileStagedApex() throws Exception {
- CommandRunner android = new CommandRunner(getDevice());
-
- String result = android.run(
- COMPOSD_CMD_BIN + " staged-apex-compile");
- assertWithMessage("Failed to compile staged apex. Reason: " + result)
- .that(result).ignoringCase().contains("all ok");
- }
-
- private void reInstallApex() throws Exception {
- CommandRunner android = new CommandRunner(getDevice());
-
- String packagesOutput =
- android.run("pm list packages -f --apex-only");
-
- Pattern p = Pattern.compile(
- "package:(.*)=(com(?:\\.google)?\\.android\\.art)$", Pattern.MULTILINE);
- Matcher m = p.matcher(packagesOutput);
- assertWithMessage("ART module not found. Packages are:\n" + packagesOutput)
- .that(m.find())
- .isTrue();
-
- String artApexPath = m.group(1);
-
- CommandResult result = android.runForResult(
- "pm install --apex " + artApexPath);
- assertWithMessage("Failed to install APEX. Reason: " + result.toString())
- .that(result.getExitCode()).isEqualTo(0);
- }
-}
diff --git a/virtualizationservice/src/aidl.rs b/virtualizationservice/src/aidl.rs
index bba75ac..5bc646f 100644
--- a/virtualizationservice/src/aidl.rs
+++ b/virtualizationservice/src/aidl.rs
@@ -14,6 +14,7 @@
//! Implementation of the AIDL interface of the VirtualizationService.
+use crate::atom::write_vm_creation_stats;
use crate::composite::make_composite_image;
use crate::crosvm::{CrosvmConfig, DiskFile, PayloadState, VmInstance, VmState};
use crate::payload::add_microdroid_images;
@@ -48,11 +49,10 @@
use binder_common::rpc_server::run_rpc_server_with_factory;
use disk::QcowFile;
use idsig::{HashAlgorithm, V4Signature};
-use log::{debug, error, info, warn, trace};
+use log::{debug, error, info, warn};
use microdroid_payload_config::VmPayloadConfig;
use rustutils::system_properties;
use semver::VersionReq;
-use statslog_virtualization_rust::vm_creation_requested::{stats_write, Hypervisor};
use std::convert::TryInto;
use std::ffi::CStr;
use std::fs::{create_dir, File, OpenOptions};
@@ -131,23 +131,7 @@
) -> binder::Result<Strong<dyn IVirtualMachine>> {
let mut is_protected = false;
let ret = self.create_vm_internal(config, console_fd, log_fd, &mut is_protected);
- match ret {
- Ok(_) => {
- let ok_status = Status::ok();
- write_vm_creation_stats(
- is_protected,
- /*creation_succeeded*/ true,
- ok_status.exception_code() as i32,
- );
- }
- Err(ref e) => {
- write_vm_creation_stats(
- is_protected,
- /*creation_succeeded*/ false,
- e.exception_code() as i32,
- );
- }
- }
+ write_vm_creation_stats(config, is_protected, &ret);
ret
}
@@ -506,16 +490,6 @@
}
}
-/// Write the stats of VMCreation to statsd
-fn write_vm_creation_stats(is_protected: bool, creation_succeeded: bool, exception_code: i32) {
- match stats_write(Hypervisor::Pkvm, is_protected, creation_succeeded, exception_code) {
- Err(e) => {
- warn!("statslog_rust failed with error: {}", e);
- }
- Ok(_) => trace!("statslog_rust succeeded for virtualization service"),
- }
-}
-
/// Waits for incoming connections from VM. If a new connection is made, stores the stream in the
/// corresponding `VmInstance`.
fn handle_stream_connection_from_vm(state: Arc<Mutex<State>>) -> Result<()> {
@@ -1003,7 +977,7 @@
}
/// Converts a `&ParcelFileDescriptor` to a `File` by cloning the file.
-fn clone_file(file: &ParcelFileDescriptor) -> Result<File, Status> {
+pub fn clone_file(file: &ParcelFileDescriptor) -> Result<File, Status> {
file.as_ref().try_clone().map_err(|e| {
Status::new_exception_str(
ExceptionCode::BAD_PARCELABLE,
diff --git a/virtualizationservice/src/atom.rs b/virtualizationservice/src/atom.rs
new file mode 100644
index 0000000..960eaa7
--- /dev/null
+++ b/virtualizationservice/src/atom.rs
@@ -0,0 +1,114 @@
+// 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.
+
+//! Functions for creating and collecting atoms.
+
+use crate::aidl::clone_file;
+use android_system_virtualizationservice::aidl::android::system::virtualizationservice::{
+ IVirtualMachine::IVirtualMachine, VirtualMachineAppConfig::VirtualMachineAppConfig,
+ VirtualMachineConfig::VirtualMachineConfig,
+};
+use android_system_virtualizationservice::binder::{Status, Strong};
+use anyhow::{anyhow, Result};
+use log::{trace, warn};
+use microdroid_payload_config::VmPayloadConfig;
+use statslog_virtualization_rust::vm_creation_requested;
+use zip::ZipArchive;
+
+fn get_vm_payload_config(config: &VirtualMachineAppConfig) -> Result<VmPayloadConfig> {
+ let apk = config.apk.as_ref().ok_or_else(|| anyhow!("APK is none"))?;
+ let apk_file = clone_file(apk)?;
+ let mut apk_zip = ZipArchive::new(&apk_file)?;
+ let config_file = apk_zip.by_name(&config.configPath)?;
+ let vm_payload_config: VmPayloadConfig = serde_json::from_reader(config_file)?;
+ Ok(vm_payload_config)
+}
+
+/// Write the stats of VMCreation to statsd
+pub fn write_vm_creation_stats(
+ config: &VirtualMachineConfig,
+ is_protected: bool,
+ ret: &binder::Result<Strong<dyn IVirtualMachine>>,
+) {
+ let creation_succeeded;
+ let binder_exception_code;
+ match ret {
+ Ok(_) => {
+ creation_succeeded = true;
+ binder_exception_code = Status::ok().exception_code() as i32;
+ }
+ Err(ref e) => {
+ creation_succeeded = false;
+ binder_exception_code = e.exception_code() as i32;
+ }
+ }
+
+ let config_type;
+ let num_cpus;
+ let cpu_affinity;
+ let memory_mib;
+ let apexes;
+ match config {
+ VirtualMachineConfig::AppConfig(config) => {
+ config_type = vm_creation_requested::ConfigType::VirtualMachineAppConfig;
+ num_cpus = config.numCpus;
+ cpu_affinity = config.cpuAffinity.clone().unwrap_or_default();
+ memory_mib = config.memoryMib;
+
+ let vm_payload_config = get_vm_payload_config(config);
+ if let Ok(vm_payload_config) = vm_payload_config {
+ apexes = vm_payload_config
+ .apexes
+ .iter()
+ .map(|x| x.name.clone())
+ .collect::<Vec<String>>()
+ .join(":");
+ } else {
+ apexes = "INFO: Can't get VmPayloadConfig".into();
+ }
+ }
+ VirtualMachineConfig::RawConfig(config) => {
+ config_type = vm_creation_requested::ConfigType::VirtualMachineRawConfig;
+ num_cpus = config.numCpus;
+ cpu_affinity = config.cpuAffinity.clone().unwrap_or_default();
+ memory_mib = config.memoryMib;
+ apexes = String::new();
+ }
+ }
+
+ let empty_string = String::new();
+ let vm_creation_requested = vm_creation_requested::VmCreationRequested {
+ // TODO(seungjaeyoo) Implement sending proper data about uid & vm_identifier
+ uid: -1,
+ vm_identifier: &empty_string,
+ hypervisor: vm_creation_requested::Hypervisor::Pkvm,
+ is_protected,
+ creation_succeeded,
+ binder_exception_code,
+ config_type,
+ num_cpus,
+ cpu_affinity: &cpu_affinity,
+ memory_mib,
+ apexes: &apexes,
+ // TODO(seungjaeyoo) Fill information about task_profile
+ // TODO(seungjaeyoo) Fill information about disk_image for raw config
+ };
+
+ match vm_creation_requested.stats_write() {
+ Err(e) => {
+ warn!("statslog_rust failed with error: {}", e);
+ }
+ Ok(_) => trace!("statslog_rust succeeded for virtualization service"),
+ }
+}
diff --git a/virtualizationservice/src/main.rs b/virtualizationservice/src/main.rs
index 3b0adb9..93a5966 100644
--- a/virtualizationservice/src/main.rs
+++ b/virtualizationservice/src/main.rs
@@ -15,6 +15,7 @@
//! Android VirtualizationService
mod aidl;
+mod atom;
mod composite;
mod crosvm;
mod payload;