Merge "Rename trusty_vm_launcher and move it to packages/modules/Virtualization" into main
diff --git a/android/TerminalApp/AndroidManifest.xml b/android/TerminalApp/AndroidManifest.xml
index 105e454..28b5436 100644
--- a/android/TerminalApp/AndroidManifest.xml
+++ b/android/TerminalApp/AndroidManifest.xml
@@ -9,6 +9,7 @@
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE"/>
+ <uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
<uses-feature android:name="android.software.virtualization_framework" android:required="true" />
diff --git a/android/TerminalApp/java/com/android/virtualization/terminal/MainActivity.java b/android/TerminalApp/java/com/android/virtualization/terminal/MainActivity.java
index 20b4c96..0a750e3 100644
--- a/android/TerminalApp/java/com/android/virtualization/terminal/MainActivity.java
+++ b/android/TerminalApp/java/com/android/virtualization/terminal/MainActivity.java
@@ -15,8 +15,17 @@
*/
package com.android.virtualization.terminal;
+import android.Manifest;
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.res.Configuration;
+import android.graphics.drawable.Icon;
+import android.graphics.fonts.FontStyle;
import android.net.http.SslError;
import android.os.Build;
import android.os.Bundle;
@@ -67,11 +76,13 @@
private static final String VM_ADDR = "192.168.0.2";
private static final int TTYD_PORT = 7681;
private static final int REQUEST_CODE_INSTALLER = 0x33;
+ private static final int FONT_SIZE_DEFAULT = 12;
private X509Certificate[] mCertificates;
private PrivateKey mPrivateKey;
private WebView mWebView;
private AccessibilityManager mAccessibilityManager;
+ private static final int POST_NOTIFICATIONS_PERMISSION_REQUEST_CODE = 101;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -88,6 +99,14 @@
.show();
}
+ checkAndRequestPostNotificationsPermission();
+
+ NotificationManager notificationManager = getSystemService(NotificationManager.class);
+ NotificationChannel notificationChannel =
+ new NotificationChannel(TAG, TAG, NotificationManager.IMPORTANCE_LOW);
+ assert notificationManager != null;
+ notificationManager.createNotificationChannel(notificationChannel);
+
setContentView(R.layout.activity_headless);
MaterialToolbar toolbar = (MaterialToolbar) findViewById(R.id.toolbar);
@@ -111,12 +130,20 @@
}
private URL getTerminalServiceUrl() {
- boolean needsAccessibility = mAccessibilityManager.isTouchExplorationEnabled();
- String file = "/";
- String query = needsAccessibility ? "?screenReaderMode=true" : "";
+ Configuration config = getResources().getConfiguration();
+
+ String query =
+ "?fontSize="
+ + (int) (config.fontScale * FONT_SIZE_DEFAULT)
+ + "&fontWeight="
+ + (FontStyle.FONT_WEIGHT_NORMAL + config.fontWeightAdjustment)
+ + "&fontWeightBold="
+ + (FontStyle.FONT_WEIGHT_BOLD + config.fontWeightAdjustment)
+ + "&screenReaderMode="
+ + mAccessibilityManager.isTouchExplorationEnabled();
try {
- return new URL("https", VM_ADDR, TTYD_PORT, file + query);
+ return new URL("https", VM_ADDR, TTYD_PORT, "/" + query);
} catch (MalformedURLException e) {
// this cannot happen
return null;
@@ -311,6 +338,15 @@
return;
}
+ private void checkAndRequestPostNotificationsPermission() {
+ if (getApplicationContext().checkSelfPermission(Manifest.permission.POST_NOTIFICATIONS)
+ != PackageManager.PERMISSION_GRANTED) {
+ requestPermissions(
+ new String[]{Manifest.permission.POST_NOTIFICATIONS},
+ POST_NOTIFICATIONS_PERMISSION_REQUEST_CODE);
+ }
+ }
+
@Override
protected void onDestroy() {
getSystemService(AccessibilityManager.class).removeTouchExplorationStateChangeListener(this);
@@ -393,7 +429,29 @@
if (!InstallUtils.isImageInstalled(this)) {
return;
}
+ // TODO: implement intent for setting, close and tap to the notification
+ // Currently mock a PendingIntent for notification.
+ Intent intent = new Intent();
+ PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent,
+ PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
+
+ Icon icon = Icon.createWithResource(getResources(), R.drawable.ic_launcher_foreground);
+ Notification notification = new Notification.Builder(this, TAG)
+ .setChannelId(TAG)
+ .setSmallIcon(R.drawable.ic_launcher_foreground)
+ .setContentTitle(getResources().getString(R.string.service_notification_title))
+ .setContentText(getResources().getString(R.string.service_notification_content))
+ .setContentIntent(pendingIntent)
+ .setOngoing(true)
+ .addAction(new Notification.Action.Builder(icon,
+ getResources().getString(R.string.service_notification_settings),
+ pendingIntent).build())
+ .addAction(new Notification.Action.Builder(icon,
+ getResources().getString(R.string.service_notification_quit_action),
+ pendingIntent).build())
+ .build();
+
android.os.Trace.beginAsyncSection("executeTerminal", 0);
- VmLauncherServices.startVmLauncherService(this, this);
+ VmLauncherServices.startVmLauncherService(this, this, notification);
}
}
diff --git a/android/TerminalApp/java/com/android/virtualization/terminal/SettingsPortForwardingActivity.kt b/android/TerminalApp/java/com/android/virtualization/terminal/SettingsPortForwardingActivity.kt
index 6c36cc8..7119225 100644
--- a/android/TerminalApp/java/com/android/virtualization/terminal/SettingsPortForwardingActivity.kt
+++ b/android/TerminalApp/java/com/android/virtualization/terminal/SettingsPortForwardingActivity.kt
@@ -15,12 +15,21 @@
*/
package com.android.virtualization.terminal
+import android.Manifest
+import android.app.Notification
+import android.app.NotificationManager
+import android.app.PendingIntent
+import android.content.Intent
+import android.content.pm.PackageManager
+import android.graphics.drawable.Icon
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
+import androidx.core.app.ActivityCompat
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
class SettingsPortForwardingActivity : AppCompatActivity() {
+ val TAG: String = "VmTerminalApp"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.settings_port_forwarding)
@@ -37,5 +46,43 @@
val recyclerView: RecyclerView = findViewById(R.id.settings_port_forwarding_recycler_view)
recyclerView.layoutManager = LinearLayoutManager(this)
recyclerView.adapter = settingsPortForwardingAdapter
+
+ // TODO: implement intent for accept, deny and tap to the notification
+ // Currently show a mock notification of a port opening
+ val terminalIntent = Intent()
+ val pendingIntent = PendingIntent.getActivity(
+ this, 0, terminalIntent,
+ PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
+ )
+ val notification =
+ Notification.Builder(this, TAG)
+ .setChannelId(TAG)
+ .setSmallIcon(R.drawable.ic_launcher_foreground)
+ .setContentTitle(resources.getString(R.string.settings_port_forwarding_notification_title))
+ .setContentText(resources.getString(R.string.settings_port_forwarding_notification_content, settingsPortForwardingItems[0].port))
+ .addAction(
+ Notification.Action.Builder(
+ Icon.createWithResource(resources, R.drawable.ic_launcher_foreground),
+ resources.getString(R.string.settings_port_forwarding_notification_accept),
+ pendingIntent
+ ).build()
+ )
+ .addAction(
+ Notification.Action.Builder(
+ Icon.createWithResource(resources, R.drawable.ic_launcher_foreground),
+ resources.getString(R.string.settings_port_forwarding_notification_deny),
+ pendingIntent
+ ).build()
+ )
+ .build()
+
+ with(NotificationManager.from(this)) {
+ if (ActivityCompat.checkSelfPermission(
+ this@SettingsPortForwardingActivity, Manifest.permission.POST_NOTIFICATIONS
+ ) == PackageManager.PERMISSION_GRANTED
+ ) {
+ notify(0, notification)
+ }
+ }
}
}
\ No newline at end of file
diff --git a/android/TerminalApp/res/values/strings.xml b/android/TerminalApp/res/values/strings.xml
index 1cbaee8..0cdb939 100644
--- a/android/TerminalApp/res/values/strings.xml
+++ b/android/TerminalApp/res/values/strings.xml
@@ -49,6 +49,14 @@
<string name="settings_port_forwarding_title">Port Forwarding</string>
<!-- Settings menu subtitle for 'port forwarding' [CHAR LIMIT=none] -->
<string name="settings_port_forwarding_sub_title">Configure port forwarding</string>
+ <!-- Notification title for new port forwarding [CHAR LIMIT=none] -->
+ <string name="settings_port_forwarding_notification_title">Terminal is trying to open a new port</string>
+ <!-- Notification content for new port forwarding [CHAR LIMIT=none] -->
+ <string name="settings_port_forwarding_notification_content">Port requested to be open: <xliff:g id="port_number" example="8080">%d</xliff:g></string>
+ <!-- Notification action accept [CHAR LIMIT=none] -->
+ <string name="settings_port_forwarding_notification_accept">Accept</string>
+ <!-- Notification action deny [CHAR LIMIT=none] -->
+ <string name="settings_port_forwarding_notification_deny">Deny</string>
<!-- Settings menu title for recoverying image [CHAR LIMIT=none] -->
<string name="settings_recovery_title">Recovery</string>
@@ -60,4 +68,13 @@
<string name="settings_recovery_reset_sub_title">Remove all</string>
<!-- Toast message for reset is completed [CHAR LIMIT=none] -->
<string name="settings_recovery_reset_message">VM reset</string>
+
+ <!-- Notification action button for settings [CHAR LIMIT=none] -->
+ <string name="service_notification_settings">Settings</string>
+ <!-- Notification title for foreground service notification [CHAR LIMIT=none] -->
+ <string name="service_notification_title">Terminal is running</string>
+ <!-- Notification content for foreground service notification [CHAR LIMIT=none] -->
+ <string name="service_notification_content">Click to open the terminal.</string>
+ <!-- Notification action button for closing the virtual machine [CHAR LIMIT=none] -->
+ <string name="service_notification_quit_action">Close</string>
</resources>
diff --git a/android/virtmgr/Android.bp b/android/virtmgr/Android.bp
index d0d7915..ad63995 100644
--- a/android/virtmgr/Android.bp
+++ b/android/virtmgr/Android.bp
@@ -37,6 +37,7 @@
"libbinder_rs",
"libcfg_if",
"libclap",
+ "libcrosvm_control_static",
"libcstr",
"libcommand_fds",
"libdisk",
@@ -62,7 +63,6 @@
"libstatslog_virtualization_rust",
"libtombstoned_client_rust",
"libvbmeta_rust",
- "libvm_control",
"libvmconfig",
"libzip",
"libvsock",
diff --git a/android/virtmgr/src/aidl.rs b/android/virtmgr/src/aidl.rs
index 23652d2..5dac07f 100644
--- a/android/virtmgr/src/aidl.rs
+++ b/android/virtmgr/src/aidl.rs
@@ -17,7 +17,7 @@
use crate::{get_calling_pid, get_calling_uid, get_this_pid};
use crate::atom::{write_vm_booted_stats, write_vm_creation_stats};
use crate::composite::make_composite_image;
-use crate::crosvm::{AudioConfig, CrosvmConfig, DiskFile, DisplayConfig, GpuConfig, InputDeviceOption, PayloadState, UsbConfig, VmContext, VmInstance, VmState};
+use crate::crosvm::{AudioConfig, CrosvmConfig, DiskFile, SharedPathConfig, DisplayConfig, GpuConfig, InputDeviceOption, PayloadState, UsbConfig, VmContext, VmInstance, VmState};
use crate::debug_config::DebugConfig;
use crate::dt_overlay::{create_device_tree_overlay, VM_DT_OVERLAY_MAX_SIZE, VM_DT_OVERLAY_PATH};
use crate::payload::{add_microdroid_payload_images, add_microdroid_system_images, add_microdroid_vendor_image};
@@ -32,6 +32,7 @@
AssignableDevice::AssignableDevice,
CpuTopology::CpuTopology,
DiskImage::DiskImage,
+ SharedPath::SharedPath,
InputDevice::InputDevice,
IVirtualMachine::{self, BnVirtualMachine},
IVirtualMachineCallback::IVirtualMachineCallback,
@@ -67,6 +68,7 @@
};
use cstr::cstr;
use glob::glob;
+use libc::{AF_VSOCK, sa_family_t, sockaddr_vm};
use log::{debug, error, info, warn};
use microdroid_payload_config::{ApkConfig, Task, TaskType, VmPayloadConfig};
use nix::unistd::pipe;
@@ -89,7 +91,7 @@
use std::sync::{Arc, Mutex, Weak, LazyLock};
use vbmeta::VbMetaImage;
use vmconfig::{VmConfig, get_debug_level};
-use vsock::{VsockAddr, VsockStream};
+use vsock::VsockStream;
use zip::ZipArchive;
/// The unique ID of a VM used (together with a port number) for vsock communication.
@@ -612,6 +614,8 @@
})
.collect::<Result<Vec<DiskFile>, _>>()?;
+ let shared_paths = assemble_shared_paths(&config.sharedPaths, &temporary_directory)?;
+
let (cpus, host_cpu_topology) = match config.cpuTopology {
CpuTopology::MATCH_HOST => (None, true),
CpuTopology::ONE_CPU => (NonZeroU32::new(1), false),
@@ -718,6 +722,7 @@
kernel,
initrd,
disks,
+ shared_paths,
params: config.params.to_owned(),
protected: *is_protected,
debug_config,
@@ -955,6 +960,32 @@
},
})
}
+
+fn assemble_shared_paths(
+ shared_paths: &[SharedPath],
+ temporary_directory: &Path,
+) -> Result<Vec<SharedPathConfig>, Status> {
+ if shared_paths.is_empty() {
+ return Ok(Vec::new()); // Return an empty vector if shared_paths is empty
+ }
+
+ shared_paths
+ .iter()
+ .map(|path| {
+ Ok(SharedPathConfig {
+ path: path.sharedPath.clone(),
+ host_uid: path.hostUid,
+ host_gid: path.hostGid,
+ guest_uid: path.guestUid,
+ guest_gid: path.guestGid,
+ mask: path.mask,
+ tag: path.tag.clone(),
+ socket_path: temporary_directory.join(&path.socket).to_string_lossy().to_string(),
+ })
+ })
+ .collect()
+}
+
/// Given the configuration for a disk image, assembles the `DiskFile` to pass to crosvm.
///
/// This may involve assembling a composite disk from a set of partition images.
@@ -1434,8 +1465,14 @@
));
}
let cid = self.instance.cid;
- let get_connection_info =
- move |_instance: &str| Some(ConnectionInfo::Vsock(VsockAddr::new(cid, port)));
+ let addr = sockaddr_vm {
+ svm_family: AF_VSOCK as sa_family_t,
+ svm_reserved1: 0,
+ svm_port: port,
+ svm_cid: cid,
+ svm_zero: [0u8; 4],
+ };
+ let get_connection_info = move |_instance: &str| Some(ConnectionInfo::Vsock(addr));
let accessor = Accessor::new(name, get_connection_info);
accessor
.as_binder()
diff --git a/android/virtmgr/src/crosvm.rs b/android/virtmgr/src/crosvm.rs
index 25271f8..86b3571 100644
--- a/android/virtmgr/src/crosvm.rs
+++ b/android/virtmgr/src/crosvm.rs
@@ -29,12 +29,14 @@
use shared_child::SharedChild;
use std::borrow::Cow;
use std::cmp::max;
+use std::ffi::CString;
use std::fmt;
use std::fs::{read_to_string, File};
use std::io::{self, Read};
use std::mem;
use std::num::{NonZeroU16, NonZeroU32};
use std::os::unix::io::{AsRawFd, OwnedFd};
+use std::os::unix::process::CommandExt;
use std::os::unix::process::ExitStatusExt;
use std::path::{Path, PathBuf};
use std::process::{Command, ExitStatus};
@@ -56,9 +58,6 @@
use tombstoned_client::{TombstonedConnection, DebuggerdDumpType};
use rpcbinder::RpcServer;
-/// external/crosvm
-use vm_control::{BalloonControlCommand, VmRequest, VmResponse};
-
const CROSVM_PATH: &str = "/apex/com.android.virt/bin/crosvm";
/// Version of the platform that crosvm currently implements. The format follows SemVer. This
@@ -108,6 +107,7 @@
pub kernel: Option<File>,
pub initrd: Option<File>,
pub disks: Vec<DiskFile>,
+ pub shared_paths: Vec<SharedPathConfig>,
pub params: Option<String>,
pub protected: bool,
pub debug_config: DebugConfig,
@@ -224,6 +224,19 @@
pub writable: bool,
}
+/// Shared path between host and guest VM.
+#[derive(Debug)]
+pub struct SharedPathConfig {
+ pub path: String,
+ pub host_uid: i32,
+ pub host_gid: i32,
+ pub guest_uid: i32,
+ pub guest_gid: i32,
+ pub mask: i32,
+ pub tag: String,
+ pub socket_path: String,
+}
+
/// virtio-input device configuration from `external/crosvm/src/crosvm/config.rs`
#[derive(Debug)]
#[allow(dead_code)]
@@ -306,6 +319,8 @@
let tap =
if let Some(tap_file) = &config.tap { Some(tap_file.try_clone()?) } else { None };
+ run_virtiofs(&config)?;
+
// If this fails and returns an error, `self` will be left in the `Failed` state.
let child =
Arc::new(run_vm(config, &instance.crosvm_control_socket_path, failure_pipe_write)?);
@@ -638,37 +653,34 @@
Ok(())
}
- /// Responds to memory-trimming notifications by inflating the virtio
- /// balloon to reclaim guest memory.
+ /// Returns current virtio-balloon size.
pub fn get_memory_balloon(&self) -> Result<u64, Error> {
- let request = VmRequest::BalloonCommand(BalloonControlCommand::Stats {});
- let result =
- match vm_control::client::handle_request(&request, &self.crosvm_control_socket_path) {
- Ok(VmResponse::BalloonStats { stats: _, balloon_actual }) => balloon_actual,
- Ok(VmResponse::Err(e)) => {
- // ENOTSUP is returned when the balloon protocol is not initialized. This
- // can occur for numerous reasons: Guest is still booting, guest doesn't
- // support ballooning, host doesn't support ballooning. We don't log or
- // raise an error in this case: trim is just a hint and we can ignore it.
- if e.errno() != libc::ENOTSUP {
- bail!("Errno return when requesting balloon stats: {}", e.errno())
- }
- 0
- }
- e => bail!("Error requesting balloon stats: {:?}", e),
- };
- Ok(result)
+ let socket_path_cstring = path_to_cstring(&self.crosvm_control_socket_path);
+ let mut balloon_actual = 0u64;
+ // SAFETY: Pointers are valid for the lifetime of the call. Null `stats` is valid.
+ let success = unsafe {
+ crosvm_control::crosvm_client_balloon_stats(
+ socket_path_cstring.as_ptr(),
+ /* stats= */ std::ptr::null_mut(),
+ &mut balloon_actual,
+ )
+ };
+ if !success {
+ bail!("Error requesting balloon stats");
+ }
+ Ok(balloon_actual)
}
- /// Responds to memory-trimming notifications by inflating the virtio
- /// balloon to reclaim guest memory.
+ /// Inflates the virtio-balloon by `num_bytes` to reclaim guest memory. Called in response to
+ /// memory-trimming notifications.
pub fn set_memory_balloon(&self, num_bytes: u64) -> Result<(), Error> {
- let command = BalloonControlCommand::Adjust { num_bytes, wait_for_success: false };
- if let Err(e) = vm_control::client::handle_request(
- &VmRequest::BalloonCommand(command),
- &self.crosvm_control_socket_path,
- ) {
- bail!("Error sending balloon adjustment: {:?}", e);
+ let socket_path_cstring = path_to_cstring(&self.crosvm_control_socket_path);
+ // SAFETY: Pointer is valid for the lifetime of the call.
+ let success = unsafe {
+ crosvm_control::crosvm_client_balloon_vms(socket_path_cstring.as_ptr(), num_bytes)
+ };
+ if !success {
+ bail!("Error sending balloon adjustment");
}
Ok(())
}
@@ -704,26 +716,28 @@
Ok(())
}
- /// Suspends the VM
+ /// Suspends the VM's vCPUs.
pub fn suspend(&self) -> Result<(), Error> {
- match vm_control::client::handle_request(
- &VmRequest::SuspendVcpus,
- &self.crosvm_control_socket_path,
- ) {
- Ok(VmResponse::Ok) => Ok(()),
- e => bail!("Failed to suspend VM: {e:?}"),
+ let socket_path_cstring = path_to_cstring(&self.crosvm_control_socket_path);
+ // SAFETY: Pointer is valid for the lifetime of the call.
+ let success =
+ unsafe { crosvm_control::crosvm_client_suspend_vm(socket_path_cstring.as_ptr()) };
+ if !success {
+ bail!("Failed to suspend VM");
}
+ Ok(())
}
- /// Resumes the suspended VM
+ /// Resumes the VM's vCPUs.
pub fn resume(&self) -> Result<(), Error> {
- match vm_control::client::handle_request(
- &VmRequest::ResumeVcpus,
- &self.crosvm_control_socket_path,
- ) {
- Ok(VmResponse::Ok) => Ok(()),
- e => bail!("Failed to resume: {e:?}"),
+ let socket_path_cstring = path_to_cstring(&self.crosvm_control_socket_path);
+ // SAFETY: Pointer is valid for the lifetime of the call.
+ let success =
+ unsafe { crosvm_control::crosvm_client_resume_vm(socket_path_cstring.as_ptr()) };
+ if !success {
+ bail!("Failed to resume VM");
}
+ Ok(())
}
}
@@ -884,6 +898,39 @@
}
}
+fn run_virtiofs(config: &CrosvmConfig) -> io::Result<()> {
+ for shared_path in &config.shared_paths {
+ let ugid_map_value = format!(
+ "{} {} {} {} {} /",
+ shared_path.guest_uid,
+ shared_path.guest_gid,
+ shared_path.host_uid,
+ shared_path.host_gid,
+ shared_path.mask,
+ );
+
+ let cfg_arg = format!("writeback=true,cache_policy=always,ugid_map='{}'", ugid_map_value);
+
+ let mut command = Command::new(CROSVM_PATH);
+ command
+ .arg("device")
+ .arg("fs")
+ .arg(format!("--socket={}", &shared_path.socket_path))
+ .arg(format!("--tag={}", &shared_path.tag))
+ .arg(format!("--shared-dir={}", &shared_path.path))
+ .arg("--cfg")
+ .arg(cfg_arg.as_str())
+ .arg("--disable-sandbox");
+
+ print_crosvm_args(&command);
+
+ let result = SharedChild::spawn(&mut command)?;
+ info!("Spawned virtiofs crosvm({})", result.id());
+ }
+
+ Ok(())
+}
+
/// Starts an instance of `crosvm` to manage a new VM.
fn run_vm(
config: CrosvmConfig,
@@ -893,6 +940,9 @@
validate_config(&config)?;
let mut command = Command::new(CROSVM_PATH);
+
+ let vm_name = "crosvm_".to_owned() + &config.name;
+ command.arg0(vm_name.clone());
// TODO(qwandor): Remove --disable-sandbox.
command
.arg("--extended-status")
@@ -901,6 +951,8 @@
.arg("--log-level")
.arg("info,disk=warn")
.arg("run")
+ .arg("--name")
+ .arg(vm_name)
.arg("--disable-sandbox")
.arg("--cid")
.arg(config.cid.to_string());
@@ -1062,6 +1114,9 @@
command.arg(add_preserved_fd(&mut preserved_fds, kernel));
}
+ #[cfg(target_arch = "aarch64")]
+ command.arg("--no-pmu");
+
let control_sock = create_crosvm_control_listener(crosvm_control_socket_path)
.context("failed to create control listener")?;
command.arg("--socket").arg(add_preserved_fd(&mut preserved_fds, control_sock));
@@ -1187,6 +1242,12 @@
command.arg(vfio_argument_for_platform_device(&device)?);
}
+ for shared_path in &config.shared_paths {
+ command
+ .arg("--vhost-user-fs")
+ .arg(format!("{},tag={}", &shared_path.socket_path, &shared_path.tag));
+ }
+
debug!("Preserving FDs {:?}", preserved_fds);
command.preserved_fds(preserved_fds);
@@ -1296,3 +1357,13 @@
socket::listen(&fd, socket::Backlog::new(127).unwrap()).context("listen failed")?;
Ok(fd)
}
+
+fn path_to_cstring(path: &Path) -> CString {
+ if let Some(s) = path.to_str() {
+ if let Ok(s) = CString::new(s) {
+ return s;
+ }
+ }
+ // The path contains invalid utf8 or a null, which should never happen.
+ panic!("bad path: {path:?}");
+}
diff --git a/android/virtualizationservice/aidl/android/system/virtualizationservice/SharedPath.aidl b/android/virtualizationservice/aidl/android/system/virtualizationservice/SharedPath.aidl
new file mode 100644
index 0000000..7be7a5f
--- /dev/null
+++ b/android/virtualizationservice/aidl/android/system/virtualizationservice/SharedPath.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2024 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.virtualizationservice;
+
+/** Shared directory path between host and guest */
+parcelable SharedPath {
+ /** Shared path between host and guest */
+ String sharedPath;
+
+ /** UID of the path on the host */
+ int hostUid;
+
+ /** GID of the path on the host */
+ int hostGid;
+
+ /** UID of the path on the guest */
+ int guestUid;
+
+ /** GID of the path on the guest */
+ int guestGid;
+
+ /** umask settings for the path */
+ int mask;
+
+ /** virtiofs unique tag per path */
+ String tag;
+
+ /** socket name for vhost-user-fs */
+ String socket;
+}
diff --git a/android/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineRawConfig.aidl b/android/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineRawConfig.aidl
index f559a71..9f2a23e 100644
--- a/android/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineRawConfig.aidl
+++ b/android/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineRawConfig.aidl
@@ -21,6 +21,7 @@
import android.system.virtualizationservice.DisplayConfig;
import android.system.virtualizationservice.GpuConfig;
import android.system.virtualizationservice.InputDevice;
+import android.system.virtualizationservice.SharedPath;
import android.system.virtualizationservice.UsbConfig;
/** Raw configuration for running a VM. */
@@ -52,6 +53,9 @@
/** Disk images to be made available to the VM. */
DiskImage[] disks;
+ /** Shared paths between host and guest */
+ SharedPath[] sharedPaths;
+
/** Whether the VM should be a protected VM. */
boolean protectedVm;
diff --git a/build/apex/Android.bp b/build/apex/Android.bp
index f794239..e485aa7 100644
--- a/build/apex/Android.bp
+++ b/build/apex/Android.bp
@@ -285,9 +285,11 @@
"libz",
],
data: [
- ":com.android.virt",
":test.com.android.virt.pem",
],
+ device_common_data: [
+ ":com.android.virt",
+ ],
test_suites: ["general-tests"],
}
diff --git a/build/debian/build.sh b/build/debian/build.sh
index 824d6c5..b4e8b2f 100755
--- a/build/debian/build.sh
+++ b/build/debian/build.sh
@@ -181,4 +181,4 @@
cp $(dirname $0)/vm_config.json.${arch} vm_config.json
# --sparse option isn't supported in apache-commons-compress
-tar czv -f ${KOKORO_ARTIFACTS_DIR}/images.tar.gz ${images[@]} vm_config.json
\ No newline at end of file
+tar czv -f images.tar.gz ${images[@]} vm_config.json
\ No newline at end of file
diff --git a/build/debian/kokoro/gcp_ubuntu_docker/aarch64/build.sh b/build/debian/kokoro/gcp_ubuntu_docker/aarch64/build.sh
index 07ec01c..7a1523a 100644
--- a/build/debian/kokoro/gcp_ubuntu_docker/aarch64/build.sh
+++ b/build/debian/kokoro/gcp_ubuntu_docker/aarch64/build.sh
@@ -6,6 +6,7 @@
sudo losetup -D
grep vmx /proc/cpuinfo || true
sudo ./build.sh
+sudo mv images.tar.gz ${KOKORO_ARTIFACTS_DIR} || true
mkdir -p ${KOKORO_ARTIFACTS_DIR}/logs
sudo cp -r /var/log/fai/* ${KOKORO_ARTIFACTS_DIR}/logs || true
diff --git a/build/debian/kokoro/gcp_ubuntu_docker/x86_64/build.sh b/build/debian/kokoro/gcp_ubuntu_docker/x86_64/build.sh
index cf8776a..66e3d64 100644
--- a/build/debian/kokoro/gcp_ubuntu_docker/x86_64/build.sh
+++ b/build/debian/kokoro/gcp_ubuntu_docker/x86_64/build.sh
@@ -6,6 +6,7 @@
sudo losetup -D
grep vmx /proc/cpuinfo || true
sudo ./build.sh -a x86_64
+sudo mv images.tar.gz ${KOKORO_ARTIFACTS_DIR} || true
mkdir -p ${KOKORO_ARTIFACTS_DIR}/logs
sudo cp -r /var/log/fai/* ${KOKORO_ARTIFACTS_DIR}/logs || true
diff --git a/build/debian/vm_config.json.aarch64 b/build/debian/vm_config.json.aarch64
index 658ecfc..9f9295c 100644
--- a/build/debian/vm_config.json.aarch64
+++ b/build/debian/vm_config.json.aarch64
@@ -7,9 +7,6 @@
"writable": true
}
],
- "kernel": "$PAYLOAD_DIR/vmlinuz",
- "initrd": "$PAYLOAD_DIR/initrd.img",
- "params": "root=/dev/vda1",
"protected": false,
"cpu_topology": "match_host",
"platform_version": "~1.0",
@@ -20,4 +17,3 @@
"console_input_device": "ttyS0",
"network": true
}
-
diff --git a/build/debian/vm_config.json.x86_64 b/build/debian/vm_config.json.x86_64
index c9a16bf..2fb9faa 100644
--- a/build/debian/vm_config.json.x86_64
+++ b/build/debian/vm_config.json.x86_64
@@ -7,6 +7,9 @@
"writable": true
}
],
+ "kernel": "$PAYLOAD_DIR/vmlinuz",
+ "initrd": "$PAYLOAD_DIR/initrd.img",
+ "params": "root=/dev/vda1",
"protected": false,
"cpu_topology": "match_host",
"platform_version": "~1.0",
@@ -17,4 +20,3 @@
"console_input_device": "ttyS0",
"network": true
}
-
diff --git a/build/microdroid/Android.bp b/build/microdroid/Android.bp
index 27d0246..abb97da 100644
--- a/build/microdroid/Android.bp
+++ b/build/microdroid/Android.bp
@@ -197,7 +197,7 @@
no_full_install: true,
}
-genrule {
+java_genrule {
name: "microdroid_build_prop_gen_x86_64",
srcs: [
"build.prop",
@@ -215,7 +215,7 @@
"echo ro.product.cpu.abi=x86_64) > $(out)",
}
-genrule {
+java_genrule {
name: "microdroid_build_prop_gen_arm64",
srcs: [
"build.prop",
@@ -597,6 +597,7 @@
// HACK: use cc_genrule for arch-specific properties
cc_genrule {
name: "microdroid_kernel_hashes_rs",
+ compile_multilib: "first",
srcs: [":microdroid_kernel"],
arch: {
arm64: {
@@ -621,6 +622,7 @@
rust_library_rlib {
name: "libmicrodroid_kernel_hashes",
+ compile_multilib: "first",
srcs: [":microdroid_kernel_hashes_rs"],
crate_name: "microdroid_kernel_hashes",
prefer_rlib: true,
diff --git a/build/microdroid/initrd/Android.bp b/build/microdroid/initrd/Android.bp
index 9904511..6d45417 100644
--- a/build/microdroid/initrd/Android.bp
+++ b/build/microdroid/initrd/Android.bp
@@ -30,7 +30,7 @@
srcs: ["gen_vbmeta_bootconfig.py"],
}
-genrule {
+java_genrule {
name: "microdroid_initrd_gen",
srcs: [
":microdroid_ramdisk",
@@ -40,7 +40,7 @@
cmd: "cat $(in) > $(out)",
}
-genrule {
+java_genrule {
name: "microdroid_gki-android15-6.6_initrd_gen_arm64",
srcs: [
":microdroid_ramdisk",
@@ -51,7 +51,7 @@
cmd: "cat $(in) > $(out)",
}
-genrule {
+java_genrule {
name: "microdroid_gki-android15-6.6_initrd_gen_x86_64",
srcs: [
":microdroid_ramdisk",
@@ -63,7 +63,7 @@
}
// This contains vbmeta hashes & related (boot)configs which are passed to kernel/init
-genrule {
+java_genrule {
name: "microdroid_vbmeta_bootconfig_gen",
srcs: [":microdroid_vbmeta"],
out: ["bootconfig_microdroid_vbmeta"],
@@ -84,7 +84,7 @@
":microdroid_vbmeta_bootconfig_gen",
]
-genrule {
+java_genrule {
name: "microdroid_initrd_debuggable_arm64",
tools: ["initrd_bootconfig"],
srcs: [
@@ -95,7 +95,7 @@
cmd: "$(location initrd_bootconfig) attach --output $(out) $(in)",
}
-genrule {
+java_genrule {
name: "microdroid_gki-android15-6.6_initrd_debuggable_arm64",
tools: ["initrd_bootconfig"],
srcs: [
@@ -106,7 +106,7 @@
cmd: "$(location initrd_bootconfig) attach --output $(out) $(in)",
}
-genrule {
+java_genrule {
name: "microdroid_initrd_debuggable_x86_64",
tools: ["initrd_bootconfig"],
srcs: [
@@ -117,7 +117,7 @@
cmd: "$(location initrd_bootconfig) attach --output $(out) $(in)",
}
-genrule {
+java_genrule {
name: "microdroid_gki-android15-6.6_initrd_debuggable_x86_64",
tools: ["initrd_bootconfig"],
srcs: [
@@ -128,7 +128,7 @@
cmd: "$(location initrd_bootconfig) attach --output $(out) $(in)",
}
-genrule {
+java_genrule {
name: "microdroid_initrd_normal_arm64",
tools: ["initrd_bootconfig"],
srcs: [
@@ -139,7 +139,7 @@
cmd: "$(location initrd_bootconfig) attach --output $(out) $(in)",
}
-genrule {
+java_genrule {
name: "microdroid_gki-android15-6.6_initrd_normal_arm64",
tools: ["initrd_bootconfig"],
srcs: [
@@ -150,7 +150,7 @@
cmd: "$(location initrd_bootconfig) attach --output $(out) $(in)",
}
-genrule {
+java_genrule {
name: "microdroid_initrd_normal_x86_64",
tools: ["initrd_bootconfig"],
srcs: [
@@ -161,7 +161,7 @@
cmd: "$(location initrd_bootconfig) attach --output $(out) $(in)",
}
-genrule {
+java_genrule {
name: "microdroid_gki-android15-6.6_initrd_normal_x86_64",
tools: ["initrd_bootconfig"],
srcs: [
diff --git a/guest/pvmfw/Android.bp b/guest/pvmfw/Android.bp
index bcd3e42..4586cca 100644
--- a/guest/pvmfw/Android.bp
+++ b/guest/pvmfw/Android.bp
@@ -18,7 +18,6 @@
"libciborium_io_nostd",
"libcstr",
"libdiced_open_dice_nostd",
- "libfdtpci",
"liblibfdt_nostd",
"liblog_rust_nostd",
"libpvmfw_avb_nostd",
diff --git a/guest/pvmfw/src/fdt.rs b/guest/pvmfw/src/fdt.rs
index 953fdae..0d934a6 100644
--- a/guest/pvmfw/src/fdt.rs
+++ b/guest/pvmfw/src/fdt.rs
@@ -30,8 +30,6 @@
use core::mem::size_of;
use core::ops::Range;
use cstr::cstr;
-use fdtpci::PciMemoryFlags;
-use fdtpci::PciRangeType;
use libfdt::AddressRange;
use libfdt::CellIterator;
use libfdt::Fdt;
@@ -45,6 +43,8 @@
use log::warn;
use static_assertions::const_assert;
use tinyvec::ArrayVec;
+use vmbase::fdt::pci::PciMemoryFlags;
+use vmbase::fdt::pci::PciRangeType;
use vmbase::fdt::SwiotlbInfo;
use vmbase::hyp;
use vmbase::layout::{crosvm::MEM_START, MAX_VIRT_ADDR};
diff --git a/guest/pvmfw/src/main.rs b/guest/pvmfw/src/main.rs
index 10f8549..1e88c4b 100644
--- a/guest/pvmfw/src/main.rs
+++ b/guest/pvmfw/src/main.rs
@@ -46,13 +46,13 @@
use core::ops::Range;
use cstr::cstr;
use diced_open_dice::{bcc_handover_parse, DiceArtifacts, Hidden};
-use fdtpci::{PciError, PciInfo};
use libfdt::{Fdt, FdtNode};
use log::{debug, error, info, trace, warn};
use pvmfw_avb::verify_payload;
use pvmfw_avb::Capability;
use pvmfw_avb::DebugLevel;
use pvmfw_embedded_key::PUBLIC_KEY;
+use vmbase::fdt::pci::{PciError, PciInfo};
use vmbase::heap;
use vmbase::memory::flush;
use vmbase::memory::MEMORY;
diff --git a/guest/rialto/Android.bp b/guest/rialto/Android.bp
index eeb5b2d..7bcfd54 100644
--- a/guest/rialto/Android.bp
+++ b/guest/rialto/Android.bp
@@ -14,7 +14,6 @@
"libciborium_nostd",
"libcstr",
"libdiced_open_dice_nostd",
- "libfdtpci",
"liblibfdt_nostd",
"liblog_rust_nostd",
"libservice_vm_comm_nostd",
diff --git a/guest/rialto/src/error.rs b/guest/rialto/src/error.rs
index 033159b..ba5f4b0 100644
--- a/guest/rialto/src/error.rs
+++ b/guest/rialto/src/error.rs
@@ -17,10 +17,11 @@
use aarch64_paging::MapError;
use core::{fmt, result};
use diced_open_dice::DiceError;
-use fdtpci::PciError;
use libfdt::FdtError;
use service_vm_comm::RequestProcessingError;
-use vmbase::{hyp::Error as HypervisorError, memory::MemoryTrackerError, virtio::pci};
+use vmbase::{
+ fdt::pci::PciError, hyp::Error as HypervisorError, memory::MemoryTrackerError, virtio::pci,
+};
pub type Result<T> = result::Result<T, Error>;
diff --git a/guest/rialto/src/main.rs b/guest/rialto/src/main.rs
index 9265775..f09cbd2 100644
--- a/guest/rialto/src/main.rs
+++ b/guest/rialto/src/main.rs
@@ -32,7 +32,6 @@
use core::num::NonZeroUsize;
use core::slice;
use diced_open_dice::{bcc_handover_parse, DiceArtifacts};
-use fdtpci::PciInfo;
use libfdt::FdtError;
use log::{debug, error, info};
use service_vm_comm::{ServiceVmRequest, VmType};
@@ -45,6 +44,7 @@
};
use vmbase::{
configure_heap,
+ fdt::pci::PciInfo,
fdt::SwiotlbInfo,
generate_image_header,
hyp::{get_mem_sharer, get_mmio_guard},
diff --git a/guest/vmbase_example/Android.bp b/guest/vmbase_example/Android.bp
index 49a6d69..09bd77c 100644
--- a/guest/vmbase_example/Android.bp
+++ b/guest/vmbase_example/Android.bp
@@ -11,7 +11,6 @@
"libaarch64_paging",
"libcstr",
"libdiced_open_dice_nostd",
- "libfdtpci",
"liblibfdt_nostd",
"liblog_rust_nostd",
"libvirtio_drivers",
diff --git a/guest/vmbase_example/src/main.rs b/guest/vmbase_example/src/main.rs
index 7a3f427..1466d1e 100644
--- a/guest/vmbase_example/src/main.rs
+++ b/guest/vmbase_example/src/main.rs
@@ -31,11 +31,12 @@
use core::mem;
use core::ptr::addr_of_mut;
use cstr::cstr;
-use fdtpci::PciInfo;
use libfdt::Fdt;
use log::{debug, error, info, trace, warn, LevelFilter};
use vmbase::{
- bionic, configure_heap, generate_image_header,
+ bionic, configure_heap,
+ fdt::pci::PciInfo,
+ generate_image_header,
layout::{crosvm::FDT_MAX_SIZE, rodata_range, scratch_range, text_range},
linker, logger, main,
memory::{PageTable, SIZE_64KB},
diff --git a/guest/vmbase_example/src/pci.rs b/guest/vmbase_example/src/pci.rs
index b838539..563f24a 100644
--- a/guest/vmbase_example/src/pci.rs
+++ b/guest/vmbase_example/src/pci.rs
@@ -17,7 +17,6 @@
use aarch64_paging::paging::MemoryRegion;
use alloc::alloc::{alloc_zeroed, dealloc, handle_alloc_error, Layout};
use core::{mem::size_of, ptr::NonNull};
-use fdtpci::PciInfo;
use log::{debug, info};
use virtio_drivers::{
device::console::VirtIOConsole,
@@ -27,7 +26,10 @@
},
BufferDirection, Error, Hal, PhysAddr, PAGE_SIZE,
};
-use vmbase::virtio::pci::{self, PciTransportIterator};
+use vmbase::{
+ fdt::pci::PciInfo,
+ virtio::pci::{self, PciTransportIterator},
+};
/// The standard sector size of a VirtIO block device, in bytes.
const SECTOR_SIZE_BYTES: usize = 512;
diff --git a/libs/fdtpci/Android.bp b/libs/fdtpci/Android.bp
deleted file mode 100644
index d7a5da3..0000000
--- a/libs/fdtpci/Android.bp
+++ /dev/null
@@ -1,19 +0,0 @@
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-rust_library_rlib {
- name: "libfdtpci",
- edition: "2021",
- no_stdlibs: true,
- host_supported: false,
- crate_name: "fdtpci",
- defaults: ["avf_build_flags_rust"],
- srcs: ["src/lib.rs"],
- rustlibs: [
- "liblibfdt_nostd",
- "liblog_rust_nostd",
- "libvirtio_drivers",
- ],
- apex_available: ["com.android.virt"],
-}
diff --git a/libs/fdtpci/TEST_MAPPING b/libs/fdtpci/TEST_MAPPING
deleted file mode 100644
index 192a7c6..0000000
--- a/libs/fdtpci/TEST_MAPPING
+++ /dev/null
@@ -1,9 +0,0 @@
-// When adding or removing tests here, don't forget to amend _all_modules list in
-// wireless/android/busytown/ath_config/configs/prod/avf/tests.gcl
-{
- "avf-presubmit": [
- {
- "name": "vmbase_example.integration_test"
- }
- ]
-}
diff --git a/libs/framework-virtualization/src/android/system/virtualmachine/VirtualMachineConfig.java b/libs/framework-virtualization/src/android/system/virtualmachine/VirtualMachineConfig.java
index de1b081..2bcb40b 100644
--- a/libs/framework-virtualization/src/android/system/virtualmachine/VirtualMachineConfig.java
+++ b/libs/framework-virtualization/src/android/system/virtualmachine/VirtualMachineConfig.java
@@ -40,6 +40,7 @@
import android.sysprop.HypervisorProperties;
import android.system.virtualizationservice.DiskImage;
import android.system.virtualizationservice.Partition;
+import android.system.virtualizationservice.SharedPath;
import android.system.virtualizationservice.UsbConfig;
import android.system.virtualizationservice.VirtualMachineAppConfig;
import android.system.virtualizationservice.VirtualMachinePayloadConfig;
@@ -712,6 +713,15 @@
config.disks[i].partitions = partitions.toArray(new Partition[0]);
}
+ config.sharedPaths =
+ new SharedPath
+ [Optional.ofNullable(customImageConfig.getSharedPaths())
+ .map(arr -> arr.length)
+ .orElse(0)];
+ for (int i = 0; i < config.sharedPaths.length; i++) {
+ config.sharedPaths[i] = customImageConfig.getSharedPaths()[i].toParcelable();
+ }
+
config.displayConfig =
Optional.ofNullable(customImageConfig.getDisplayConfig())
.map(dc -> dc.toParcelable())
diff --git a/libs/framework-virtualization/src/android/system/virtualmachine/VirtualMachineCustomImageConfig.java b/libs/framework-virtualization/src/android/system/virtualmachine/VirtualMachineCustomImageConfig.java
index 9774585..9b0709d 100644
--- a/libs/framework-virtualization/src/android/system/virtualmachine/VirtualMachineCustomImageConfig.java
+++ b/libs/framework-virtualization/src/android/system/virtualmachine/VirtualMachineCustomImageConfig.java
@@ -54,6 +54,7 @@
@Nullable private final String bootloaderPath;
@Nullable private final String[] params;
@Nullable private final Disk[] disks;
+ @Nullable private final SharedPath[] sharedPaths;
@Nullable private final DisplayConfig displayConfig;
@Nullable private final AudioConfig audioConfig;
private final boolean touch;
@@ -96,6 +97,11 @@
return params;
}
+ @Nullable
+ public SharedPath[] getSharedPaths() {
+ return sharedPaths;
+ }
+
public boolean useTouch() {
return touch;
}
@@ -132,6 +138,7 @@
String bootloaderPath,
String[] params,
Disk[] disks,
+ SharedPath[] sharedPaths,
DisplayConfig displayConfig,
boolean touch,
boolean keyboard,
@@ -149,6 +156,7 @@
this.bootloaderPath = bootloaderPath;
this.params = params;
this.disks = disks;
+ this.sharedPaths = sharedPaths;
this.displayConfig = displayConfig;
this.touch = touch;
this.keyboard = keyboard;
@@ -300,6 +308,91 @@
}
/** @hide */
+ public static final class SharedPath {
+ private final String path;
+ private final int hostUid;
+ private final int hostGid;
+ private final int guestUid;
+ private final int guestGid;
+ private final int mask;
+ private final String tag;
+ private final String socket;
+
+ public SharedPath(
+ String path,
+ int hostUid,
+ int hostGid,
+ int guestUid,
+ int guestGid,
+ int mask,
+ String tag,
+ String socket) {
+ this.path = path;
+ this.hostUid = hostUid;
+ this.hostGid = hostGid;
+ this.guestUid = guestUid;
+ this.guestGid = guestGid;
+ this.mask = mask;
+ this.tag = tag;
+ this.socket = socket;
+ }
+
+ android.system.virtualizationservice.SharedPath toParcelable() {
+ android.system.virtualizationservice.SharedPath parcelable =
+ new android.system.virtualizationservice.SharedPath();
+ parcelable.sharedPath = this.path;
+ parcelable.hostUid = this.hostUid;
+ parcelable.hostGid = this.hostGid;
+ parcelable.guestUid = this.guestUid;
+ parcelable.guestGid = this.guestGid;
+ parcelable.mask = this.mask;
+ parcelable.tag = this.tag;
+ parcelable.socket = this.socket;
+ return parcelable;
+ }
+
+ /** @hide */
+ public String getSharedPath() {
+ return path;
+ }
+
+ /** @hide */
+ public int getHostUid() {
+ return hostUid;
+ }
+
+ /** @hide */
+ public int getHostGid() {
+ return hostGid;
+ }
+
+ /** @hide */
+ public int getGuestUid() {
+ return guestUid;
+ }
+
+ /** @hide */
+ public int getGuestGid() {
+ return guestGid;
+ }
+
+ /** @hide */
+ public int getMask() {
+ return mask;
+ }
+
+ /** @hide */
+ public String getTag() {
+ return tag;
+ }
+
+ /** @hide */
+ public String getSocket() {
+ return socket;
+ }
+ }
+
+ /** @hide */
public static final class Disk {
private final boolean writable;
private final String imagePath;
@@ -366,6 +459,7 @@
private String bootloaderPath;
private List<String> params = new ArrayList<>();
private List<Disk> disks = new ArrayList<>();
+ private List<SharedPath> sharedPaths = new ArrayList<>();
private AudioConfig audioConfig;
private DisplayConfig displayConfig;
private boolean touch;
@@ -413,6 +507,12 @@
}
/** @hide */
+ public Builder addSharedPath(SharedPath path) {
+ this.sharedPaths.add(path);
+ return this;
+ }
+
+ /** @hide */
public Builder addParam(String param) {
this.params.add(param);
return this;
@@ -493,6 +593,7 @@
this.bootloaderPath,
this.params.toArray(new String[0]),
this.disks.toArray(new Disk[0]),
+ this.sharedPaths.toArray(new SharedPath[0]),
displayConfig,
touch,
keyboard,
diff --git a/libs/libservice_vm_fake_chain/Android.bp b/libs/libservice_vm_fake_chain/Android.bp
index 39f36eb..56fb22a 100644
--- a/libs/libservice_vm_fake_chain/Android.bp
+++ b/libs/libservice_vm_fake_chain/Android.bp
@@ -18,6 +18,7 @@
rust_defaults {
name: "libservice_vm_fake_chain_defaults",
+ compile_multilib: "first",
crate_name: "service_vm_fake_chain",
defaults: ["avf_build_flags_rust"],
srcs: ["src/lib.rs"],
diff --git a/libs/libservice_vm_requests/Android.bp b/libs/libservice_vm_requests/Android.bp
index 57da012..d87b087 100644
--- a/libs/libservice_vm_requests/Android.bp
+++ b/libs/libservice_vm_requests/Android.bp
@@ -4,6 +4,7 @@
rust_defaults {
name: "libservice_vm_requests_nostd_defaults",
+ compile_multilib: "first",
crate_name: "service_vm_requests",
defaults: ["avf_build_flags_rust"],
srcs: ["src/lib.rs"],
diff --git a/libs/libvmbase/Android.bp b/libs/libvmbase/Android.bp
index e634c18..206c4cb 100644
--- a/libs/libvmbase/Android.bp
+++ b/libs/libvmbase/Android.bp
@@ -80,7 +80,6 @@
"libaarch64_paging",
"libbuddy_system_allocator",
"libcstr",
- "libfdtpci",
"liblibfdt_nostd",
"liblog_rust_nostd",
"libonce_cell_nostd",
diff --git a/libs/libvmbase/src/arch.rs b/libs/libvmbase/src/arch.rs
index d8bb8b2..992ab27 100644
--- a/libs/libvmbase/src/arch.rs
+++ b/libs/libvmbase/src/arch.rs
@@ -91,3 +91,22 @@
}
}};
}
+
+/// Write with well-defined compiled behavior.
+///
+/// See https://github.com/rust-lang/rust/issues/131894
+///
+/// # Safety
+///
+/// `dst` must be valid for writes.
+pub unsafe fn write_volatile_u8(dst: *mut u8, src: u8) {
+ // SAFETY: strb only modifies *dst, which must be valid for writes.
+ unsafe {
+ core::arch::asm!(
+ "strb {value:w}, [{ptr}]",
+ value = in(reg) src,
+ ptr = in(reg) dst,
+ options(preserves_flags),
+ );
+ }
+}
diff --git a/libs/libvmbase/src/fdt.rs b/libs/libvmbase/src/fdt.rs
index 4101f7e..ff0eaf0 100644
--- a/libs/libvmbase/src/fdt.rs
+++ b/libs/libvmbase/src/fdt.rs
@@ -14,6 +14,8 @@
//! High-level FDT functions.
+pub mod pci;
+
use core::ops::Range;
use cstr::cstr;
use libfdt::{self, Fdt, FdtError};
diff --git a/libs/fdtpci/src/lib.rs b/libs/libvmbase/src/fdt/pci.rs
similarity index 99%
rename from libs/fdtpci/src/lib.rs
rename to libs/libvmbase/src/fdt/pci.rs
index bdd904f..ebaa671 100644
--- a/libs/fdtpci/src/lib.rs
+++ b/libs/libvmbase/src/fdt/pci.rs
@@ -14,8 +14,6 @@
//! Library for working with (VirtIO) PCI devices discovered from a device tree.
-#![no_std]
-
use core::{
ffi::CStr,
fmt::{self, Display, Formatter},
diff --git a/libs/libvmbase/src/uart.rs b/libs/libvmbase/src/uart.rs
index e35555d..427499b 100644
--- a/libs/libvmbase/src/uart.rs
+++ b/libs/libvmbase/src/uart.rs
@@ -15,6 +15,7 @@
//! Minimal driver for an 8250 UART. This only implements enough to work with the emulated 8250
//! provided by crosvm, and won't work with real hardware.
+use crate::arch::write_volatile_u8;
use core::fmt::{self, Write};
/// Minimal driver for an 8250 UART. This only implements enough to work with the emulated 8250
@@ -39,13 +40,7 @@
pub fn write_byte(&self, byte: u8) {
// SAFETY: We know that the base address points to the control registers of a UART device
// which is appropriately mapped.
- unsafe {
- core::arch::asm!(
- "strb {value:w}, [{ptr}]",
- value = in(reg) byte,
- ptr = in(reg) self.base_address,
- );
- }
+ unsafe { write_volatile_u8(self.base_address, byte) }
}
}
diff --git a/libs/libvmbase/src/virtio/pci.rs b/libs/libvmbase/src/virtio/pci.rs
index 1d05c18..72e648b 100644
--- a/libs/libvmbase/src/virtio/pci.rs
+++ b/libs/libvmbase/src/virtio/pci.rs
@@ -14,11 +14,13 @@
//! Functions to scan the PCI bus for VirtIO devices.
-use crate::memory::{MemoryTracker, MemoryTrackerError};
+use crate::{
+ fdt::pci::PciInfo,
+ memory::{MemoryTracker, MemoryTrackerError},
+};
use alloc::boxed::Box;
use core::fmt;
use core::marker::PhantomData;
-use fdtpci::PciInfo;
use log::debug;
use once_cell::race::OnceBox;
use virtio_drivers::{
diff --git a/libs/vbmeta/Android.bp b/libs/vbmeta/Android.bp
index 9a7375d..15c7b4a 100644
--- a/libs/vbmeta/Android.bp
+++ b/libs/vbmeta/Android.bp
@@ -31,7 +31,7 @@
"libanyhow",
"libtempfile",
],
- data: [
+ device_common_data: [
":avb_testkey_rsa2048",
":avb_testkey_rsa4096",
":avb_testkey_rsa8192",
diff --git a/libs/vm_launcher_lib/java/com/android/virtualization/vmlauncher/ConfigJson.java b/libs/vm_launcher_lib/java/com/android/virtualization/vmlauncher/ConfigJson.java
index 6d39b46..5d6b13f 100644
--- a/libs/vm_launcher_lib/java/com/android/virtualization/vmlauncher/ConfigJson.java
+++ b/libs/vm_launcher_lib/java/com/android/virtualization/vmlauncher/ConfigJson.java
@@ -17,6 +17,7 @@
package com.android.virtualization.vmlauncher;
import android.content.Context;
+import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.Rect;
import android.system.virtualmachine.VirtualMachineConfig;
import android.system.virtualmachine.VirtualMachineCustomImageConfig;
@@ -25,6 +26,7 @@
import android.system.virtualmachine.VirtualMachineCustomImageConfig.DisplayConfig;
import android.system.virtualmachine.VirtualMachineCustomImageConfig.GpuConfig;
import android.system.virtualmachine.VirtualMachineCustomImageConfig.Partition;
+import android.system.virtualmachine.VirtualMachineCustomImageConfig.SharedPath;
import android.util.DisplayMetrics;
import android.view.WindowManager;
import android.view.WindowMetrics;
@@ -34,6 +36,7 @@
import java.io.FileReader;
import java.util.Arrays;
+import java.util.Objects;
/** This class and its inner classes model vm_config.json. */
class ConfigJson {
@@ -60,6 +63,7 @@
private InputJson input;
private AudioJson audio;
private DiskJson[] disks;
+ private SharedPathJson[] sharedPath;
private DisplayJson display;
private GpuJson gpu;
@@ -141,9 +145,36 @@
Arrays.stream(disks).map(d -> d.toConfig()).forEach(builder::addDisk);
}
+ if (sharedPath != null) {
+ Arrays.stream(sharedPath)
+ .map(d -> d.toConfig(context))
+ .filter(Objects::nonNull)
+ .forEach(builder::addSharedPath);
+ }
return builder.build();
}
+ private static class SharedPathJson {
+ private SharedPathJson() {}
+
+ // Package ID of Terminal app.
+ private static final String TERMINAL_PACKAGE_ID =
+ "com.google.android.virtualization.terminal";
+ private String sharedPath;
+
+ private SharedPath toConfig(Context context) {
+ try {
+ int uid =
+ context.getPackageManager()
+ .getPackageUidAsUser(TERMINAL_PACKAGE_ID, context.getUserId());
+
+ return new SharedPath(sharedPath, uid, uid, 0, 0, 0007, "android", "android");
+ } catch (NameNotFoundException e) {
+ return null;
+ }
+ }
+ }
+
private static class InputJson {
private InputJson() {}
diff --git a/libs/vm_launcher_lib/java/com/android/virtualization/vmlauncher/VmLauncherService.java b/libs/vm_launcher_lib/java/com/android/virtualization/vmlauncher/VmLauncherService.java
index a59cc3d..849cc24 100644
--- a/libs/vm_launcher_lib/java/com/android/virtualization/vmlauncher/VmLauncherService.java
+++ b/libs/vm_launcher_lib/java/com/android/virtualization/vmlauncher/VmLauncherService.java
@@ -17,8 +17,6 @@
package com.android.virtualization.vmlauncher;
import android.app.Notification;
-import android.app.NotificationChannel;
-import android.app.NotificationManager;
import android.app.Service;
import android.content.Intent;
import android.os.Bundle;
@@ -39,6 +37,7 @@
import java.util.concurrent.Executors;
public class VmLauncherService extends Service implements DebianServiceImpl.DebianServiceCallback {
+ public static final String EXTRA_NOTIFICATION = "EXTRA_NOTIFICATION";
private static final String TAG = "VmLauncherService";
private static final int RESULT_START = 0;
@@ -57,18 +56,8 @@
return null;
}
- private void startForeground() {
- NotificationManager notificationManager = getSystemService(NotificationManager.class);
- NotificationChannel notificationChannel =
- new NotificationChannel(TAG, TAG, NotificationManager.IMPORTANCE_LOW);
- notificationManager.createNotificationChannel(notificationChannel);
- startForeground(
- this.hashCode(),
- new Notification.Builder(this, TAG)
- .setChannelId(TAG)
- .setSmallIcon(android.R.drawable.ic_dialog_info)
- .setContentText("A VM " + mVirtualMachine.getName() + " is running")
- .build());
+ private void startForeground(Notification notification) {
+ startForeground(this.hashCode(), notification);
}
@Override
@@ -110,7 +99,10 @@
Path logPath = getFileStreamPath(mVirtualMachine.getName() + ".log").toPath();
Logger.setup(mVirtualMachine, logPath, mExecutorService);
- startForeground();
+ Notification notification = intent.getParcelableExtra(EXTRA_NOTIFICATION,
+ Notification.class);
+
+ startForeground(notification);
mResultReceiver.send(RESULT_START, null);
diff --git a/libs/vm_launcher_lib/java/com/android/virtualization/vmlauncher/VmLauncherServices.java b/libs/vm_launcher_lib/java/com/android/virtualization/vmlauncher/VmLauncherServices.java
index 565b793..2fa0b32 100644
--- a/libs/vm_launcher_lib/java/com/android/virtualization/vmlauncher/VmLauncherServices.java
+++ b/libs/vm_launcher_lib/java/com/android/virtualization/vmlauncher/VmLauncherServices.java
@@ -16,6 +16,7 @@
package com.android.virtualization.vmlauncher;
+import android.app.Notification;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
@@ -64,7 +65,8 @@
context.stopService(i);
}
- public static void startVmLauncherService(Context context, VmLauncherServiceCallback callback) {
+ public static void startVmLauncherService(Context context, VmLauncherServiceCallback callback,
+ Notification notification) {
Intent i = buildVmLauncherServiceIntent(context);
if (i == null) {
return;
@@ -93,6 +95,7 @@
}
};
i.putExtra(Intent.EXTRA_RESULT_RECEIVER, getResultReceiverForIntent(resultReceiver));
+ i.putExtra(VmLauncherService.EXTRA_NOTIFICATION, notification);
context.startForegroundService(i);
}
diff --git a/tests/authfs/benchmarks/Android.bp b/tests/authfs/benchmarks/Android.bp
index 27a6af1..aad8d59 100644
--- a/tests/authfs/benchmarks/Android.bp
+++ b/tests/authfs/benchmarks/Android.bp
@@ -19,7 +19,7 @@
"open_then_run",
],
per_testcase_directory: true,
- data: [
+ device_common_data: [
":authfs_test_files",
":MicrodroidTestApp",
],
@@ -43,7 +43,7 @@
java_genrule {
name: "measure_io_as_jar",
out: ["measure_io.jar"],
- srcs: [
+ device_first_srcs: [
":measure_io",
],
tools: ["soong_zip"],
diff --git a/tests/authfs/hosttests/Android.bp b/tests/authfs/hosttests/Android.bp
index 83ef853..50dbc05 100644
--- a/tests/authfs/hosttests/Android.bp
+++ b/tests/authfs/hosttests/Android.bp
@@ -20,6 +20,8 @@
per_testcase_directory: true,
data: [
":authfs_test_files",
+ ],
+ device_common_data: [
":MicrodroidTestApp",
],
}
diff --git a/tests/benchmark_hostside/Android.bp b/tests/benchmark_hostside/Android.bp
index b613a8a..e91ac8f 100644
--- a/tests/benchmark_hostside/Android.bp
+++ b/tests/benchmark_hostside/Android.bp
@@ -18,7 +18,7 @@
test_suites: [
"general-tests",
],
- data: [
+ device_common_data: [
":MicrodroidTestApp",
],
}
diff --git a/tests/hostside/Android.bp b/tests/hostside/Android.bp
index d0838a6..0f2fe58 100644
--- a/tests/hostside/Android.bp
+++ b/tests/hostside/Android.bp
@@ -20,7 +20,7 @@
"microdroid_payload_metadata",
],
per_testcase_directory: true,
- data: [
+ device_common_data: [
":MicrodroidTestApp",
":MicrodroidTestAppUpdated",
":microdroid_general_sepolicy.conf",
diff --git a/tests/pvmfw/Android.bp b/tests/pvmfw/Android.bp
index 0483066..e124e55 100644
--- a/tests/pvmfw/Android.bp
+++ b/tests/pvmfw/Android.bp
@@ -45,13 +45,17 @@
],
per_testcase_directory: true,
data: [
+ "assets/bcc.dat",
+ ],
+ device_common_data: [
":MicrodroidTestApp",
- ":pvmfw_test",
":test_avf_debug_policy_with_ramdump",
":test_avf_debug_policy_without_ramdump",
":test_avf_debug_policy_with_adb",
":test_avf_debug_policy_without_adb",
- "assets/bcc.dat",
+ ],
+ device_first_data: [
+ ":pvmfw_test",
],
data_device_bins_first: ["dtc_static"],
}
diff --git a/tests/vendor_images/Android.bp b/tests/vendor_images/Android.bp
index 66f0219..0430eaa 100644
--- a/tests/vendor_images/Android.bp
+++ b/tests/vendor_images/Android.bp
@@ -2,19 +2,13 @@
default_applicable_licenses: ["Android-Apache-2.0"],
}
-prebuilt_etc {
- name: "vendor_sign_key",
- src: ":avb_testkey_rsa4096",
- installable: false,
-}
-
android_filesystem {
name: "test_microdroid_vendor_image",
partition_name: "microdroid-vendor",
type: "ext4",
file_contexts: ":microdroid_vendor_file_contexts.gen",
use_avb: true,
- avb_private_key: ":vendor_sign_key",
+ avb_private_key: ":avb_testkey_rsa4096",
rollback_index: 5,
}
@@ -24,7 +18,7 @@
type: "ext4",
file_contexts: ":microdroid_vendor_file_contexts.gen",
use_avb: true,
- avb_private_key: ":vendor_sign_key",
+ avb_private_key: ":avb_testkey_rsa4096",
}
android_filesystem {