Merge "Use chromiumos_test_image.tar.xz instead of image.zip" into main
diff --git a/docs/custom_vm.md b/docs/custom_vm.md
index 077d388..945798f 100644
--- a/docs/custom_vm.md
+++ b/docs/custom_vm.md
@@ -65,25 +65,20 @@
#### Download from build server
- - Step 1) Go to the link https://ci.chromium.org/ui/p/chromeos/builders/chromiumos/ferrochrome-public-main/
- - Note: I 'searched' the ferrochrome target with builder search.
- - Step 2) Click a build number
- - Step 3) Expand steps and find `48. upload artifacts`.
- - Step 4) Click `gs upload dir`. You'll see Cloud storage with comprehensive artifacts (e.g. [Here](https://pantheon.corp.google.com/storage/browser/chromiumos-image-archive/ferrochrome-public/R126-15883.0.0) is the initial build of ferrochrome)
- - Step 5) Download `image.zip`, which contains working vmlinuz.
- - Note: DO NOT DOWNLOAD `vmlinuz.tar.xz` from the CI.
- - Step 6) Uncompress `image.zip`, and boot with `chromiumos_test_image.bin` and `boot_images/vmlinuz`.
- - Note: DO NOT USE `vmlinuz.bin`.
+Here's the link the comprehensive artifacts
+https://pantheon.corp.google.com/storage/browser/chromiumos-image-archive/ferrochrome-public
-IMPORTANT: DO NOT USE `vmlinuz.bin` for passing to crosvm. It doesn't pick-up the correct `init` process (picks `/init` instead of `/sbin/init`, and `cfg80211` keeps crashing (i.e. no network)
+Pick a build, download, and untar `chromiumos_test_image.tar.xz`. We'll boot with `chromiumos_test_image.bin` in it.
+To find the latest green build, check following:
+https://pantheon.corp.google.com/storage/browser/_details/chromiumos-image-archive/ferrochrome-public/LATEST-main
#### Build ChromiumOS for VM
First, check out source code from the ChromiumOS and Chromium projects.
+* Checking out Chromium: https://www.chromium.org/developers/how-tos/get-the-code/
* Checking out ChromiumOS: https://www.chromium.org/chromium-os/developer-library/guides/development/developer-guide/
-* Checking out Chromium: https://g3doc.corp.google.com/chrome/chromeos/system_services_team/dev_instructions/g3doc/setup_checkout.md?cl=head
Important: When you are at the step “Set up gclient args” in the Chromium checkout instruction, configure .gclient as follows.
@@ -95,9 +90,7 @@
"url": "https://chromium.googlesource.com/chromium/src.git",
"managed": False,
"custom_deps": {},
- "custom_vars": {
- "checkout_src_internal": True,
- },
+ "custom_vars": {},
},
]
target_os = ['chromeos']
@@ -162,10 +155,7 @@
Don’t forget to call `build-image` afterwards.
-You need two outputs:
-
-* ChromiumOS disk image: ~/chromiumos/src/build/images/ferrochrome/latest/chromiumos_test_image.bin
-* The kernel: ~/chromiumos/src/build/images/ferrochrome/latest/boot_images/vmlinuz
+You need ChromiumOS disk image: ~/chromiumos/src/build/images/ferrochrome/latest/chromiumos_test_image.bin
### Create a guest VM configuration
@@ -173,7 +163,6 @@
```
$ adb push ~/chromiumos/src/build/images/ferrochrome/latest/chromiumos_test_image.bin /data/local/tmp/
-$ adb push ~/chromiumos/out/build/ferrochrome/boot/vmlinuz /data/local/tmp/kernel
```
Create a VM config file as below.
@@ -182,7 +171,6 @@
$ cat > vm_config.json; adb push vm_config.json /data/local/tmp
{
"name": "cros",
- "kernel": "/data/local/tmp/kernel",
"disks": [
{
"image": "/data/local/tmp/chromiumos_test_image.bin",
diff --git a/ferrochrome_app/java/com/android/virtualization/ferrochrome/FerrochromeActivity.java b/ferrochrome_app/java/com/android/virtualization/ferrochrome/FerrochromeActivity.java
index 769e74f..8ca39eb 100644
--- a/ferrochrome_app/java/com/android/virtualization/ferrochrome/FerrochromeActivity.java
+++ b/ferrochrome_app/java/com/android/virtualization/ferrochrome/FerrochromeActivity.java
@@ -45,7 +45,7 @@
public class FerrochromeActivity extends Activity {
ExecutorService executorService = Executors.newSingleThreadExecutor();
private static final String TAG = "FerrochromeActivity";
- private static final String FERROCHROME_VERSION = "R127-15916.0.0";
+ private static final String FERROCHROME_VERSION = "R128-15926.0.0";
private static final String EXTERNAL_STORAGE_DIR =
Environment.getExternalStorageDirectory().getPath() + File.separator;
private static final Path IMAGE_PATH =
@@ -68,20 +68,23 @@
() -> {
if (Files.notExists(IMAGE_PATH)
|| !FERROCHROME_VERSION.equals(getVersionInfo())) {
- updateStatus("image doesn't exist");
- updateStatus("download image");
+ updateStatus("Starting first-time setup.");
+ updateStatus(
+ "Downloading Ferrochrome image. This can take about 5 to 10"
+ + " minutes, depending on your network speed.");
if (download(FERROCHROME_VERSION)) {
- updateStatus("download done");
+ updateStatus("Done.");
} else {
- updateStatus("download failed, check internet connection and retry");
+ updateStatus(
+ "Download failed. Check the internet connection and retry.");
return;
}
} else {
- updateStatus("there are already downloaded images");
+ updateStatus("Ferrochrome is already downloaded.");
}
- updateStatus("write down vm config");
+ updateStatus("Updating VM config.");
copyVmConfigJson();
- updateStatus("custom_vm_setup: copy files to /data/local/tmp");
+ updateStatus("Updating VM images. This may take a few minutes.");
SystemProperties.set("debug.custom_vm_setup.start", "true");
while (!SystemProperties.getBoolean("debug.custom_vm_setup.done", false)) {
// Wait for custom_vm_setup
@@ -90,10 +93,9 @@
} catch (Exception e) {
Log.d(TAG, e.toString());
}
- updateStatus("wait for custom_vm_setup");
}
- updateStatus("enable vmlauncher");
- updateStatus("ready for ferrochrome");
+ updateStatus("Done.");
+ updateStatus("Starting Ferrochrome...");
runOnUiThread(
() ->
startActivity(
@@ -131,9 +133,6 @@
}
private void copyVmConfigJson() {
- if (Files.exists(VM_CONFIG_PATH)) {
- return;
- }
try (InputStream is = getResources().openRawResource(R.raw.vm_config)) {
Files.copy(is, VM_CONFIG_PATH, StandardCopyOption.REPLACE_EXISTING);
} catch (IOException e) {
diff --git a/java/framework/src/android/system/virtualmachine/VirtualMachine.java b/java/framework/src/android/system/virtualmachine/VirtualMachine.java
index 195c538..bca36a4 100644
--- a/java/framework/src/android/system/virtualmachine/VirtualMachine.java
+++ b/java/framework/src/android/system/virtualmachine/VirtualMachine.java
@@ -1137,7 +1137,9 @@
/**
* Runs this virtual machine. The returning of this method however doesn't mean that the VM has
* actually started running or the OS has booted there. Such events can be notified by
- * registering a callback using {@link #setCallback} before calling {@code run()}.
+ * registering a callback using {@link #setCallback} before calling {@code run()}. There is no
+ * limit other than available memory that limits the number of virtual machines that can run at
+ * the same time.
*
* <p>NOTE: This method may block and should not be called on the main thread.
*
diff --git a/tests/ferrochrome/ferrochrome.sh b/tests/ferrochrome/ferrochrome.sh
index 5638b34..92702ee 100755
--- a/tests/ferrochrome/ferrochrome.sh
+++ b/tests/ferrochrome/ferrochrome.sh
@@ -100,13 +100,9 @@
# DISCLAIMER: Image is too large (1.5G+ for compressed, 6.5G+ for uncompressed), so can't submit.
fecr_dir=$(mktemp -d)
- echo "Downloading ferrochrome image to ${fecr_dir}"
+ echo "Downloading & extracting ferrochrome image to ${fecr_dir}"
fecr_version=${fecr_version:-${FECR_DEFAULT_VERSION}}
- curl --output-dir ${fecr_dir} -O ${FECR_GS_URL}/${fecr_version}/chromiumos_test_image.tar.xz
- fi
- if [[ ! -f "${fecr_dir}/chromiumos_test_image.bin" ]]; then
- echo "Extrating ferrochrome image"
- tar xvf ${fecr_dir}/chromiumos_test_image.tar.xz -C ${fecr_dir} > /dev/null
+ curl ${FECR_GS_URL}/${fecr_version}/chromiumos_test_image.tar.xz | tar xfJ - -C ${fecr_dir}
fi
echo "Pushing ferrochrome image to ${FECR_DEVICE_DIR}"
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 55badcc..5b67083 100644
--- a/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java
+++ b/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java
@@ -37,6 +37,7 @@
import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
import static java.util.stream.Collectors.toList;
+import android.app.ActivityManager;
import android.app.Instrumentation;
import android.app.UiAutomation;
import android.content.ComponentName;
@@ -2512,6 +2513,41 @@
}
}
+ @Test
+ public void concurrentVms() throws Exception {
+ final long vmSize = minMemoryRequired();
+ final int numVMs = 8;
+ final long availableMem = getAvailableMemory();
+
+ // Let's not use more than half of the available memory
+ assume().withMessage("Available memory (" + availableMem + " bytes) too small")
+ .that((numVMs * vmSize) <= (availableMem / 2))
+ .isTrue();
+
+ VirtualMachine[] vms = new VirtualMachine[numVMs];
+ for (int i = 0; i < numVMs; i++) {
+ VirtualMachineConfig config =
+ newVmConfigBuilderWithPayloadBinary("MicrodroidIdleNativeLib.so")
+ .setDebugLevel(DEBUG_LEVEL_NONE)
+ .setMemoryBytes(vmSize)
+ .build();
+
+ vms[i] = forceCreateNewVirtualMachine("test_concurrent_vms_" + i, config);
+ vms[i].run();
+ }
+
+ for (VirtualMachine vm : vms) {
+ assertThat(vm.getStatus()).isEqualTo(VirtualMachine.STATUS_RUNNING);
+ }
+ }
+
+ private long getAvailableMemory() {
+ ActivityManager am = getContext().getSystemService(ActivityManager.class);
+ ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
+ am.getMemoryInfo(memoryInfo);
+ return memoryInfo.availMem;
+ }
+
private VirtualMachineDescriptor toParcelFromParcel(VirtualMachineDescriptor descriptor) {
Parcel parcel = Parcel.obtain();
descriptor.writeToParcel(parcel, 0);
diff --git a/virtualizationservice/src/aidl.rs b/virtualizationservice/src/aidl.rs
index af80998..acdb53a 100644
--- a/virtualizationservice/src/aidl.rs
+++ b/virtualizationservice/src/aidl.rs
@@ -34,7 +34,7 @@
LazyServiceGuard, ParcelFileDescriptor, Status, Strong,
};
use lazy_static::lazy_static;
-use libc::VMADDR_CID_HOST;
+use libc::{VMADDR_CID_HOST, VMADDR_CID_HYPERVISOR, VMADDR_CID_LOCAL};
use log::{error, info, warn};
use nix::unistd::{chown, Uid};
use openssl::x509::X509;
@@ -878,11 +878,21 @@
for incoming_stream in listener.incoming() {
let mut incoming_stream = match incoming_stream {
Err(e) => {
- warn!("invalid incoming connection: {:?}", e);
+ warn!("invalid incoming connection: {e:?}");
continue;
}
Ok(s) => s,
};
+ if let Ok(addr) = incoming_stream.peer_addr() {
+ let cid = addr.cid();
+ match cid {
+ VMADDR_CID_LOCAL | VMADDR_CID_HOST | VMADDR_CID_HYPERVISOR => {
+ warn!("Rejecting non-guest tombstone vsock connection from cid={cid}");
+ continue;
+ }
+ _ => info!("Vsock Stream connected to cid={cid} for tombstones"),
+ }
+ }
std::thread::spawn(move || {
if let Err(e) = handle_tombstone(&mut incoming_stream) {
error!("Failed to write tombstone- {:?}", e);
@@ -893,9 +903,6 @@
}
fn handle_tombstone(stream: &mut VsockStream) -> Result<()> {
- if let Ok(addr) = stream.peer_addr() {
- info!("Vsock Stream connected to cid={} for tombstones", addr.cid());
- }
let tb_connection =
TombstonedConnection::connect(std::process::id() as i32, DebuggerdDumpType::Tombstone)
.context("Failed to connect to tombstoned")?;
diff --git a/vmlauncher_app/AndroidManifest.xml b/vmlauncher_app/AndroidManifest.xml
index ecfef86..4f95086 100644
--- a/vmlauncher_app/AndroidManifest.xml
+++ b/vmlauncher_app/AndroidManifest.xml
@@ -15,7 +15,7 @@
android:exported="true">
</activity>
<activity-alias android:name=".MainActivityAlias"
- android:targetActivity=".MainActivity"
+ android:targetActivity="com.android.virtualization.vmlauncher.MainActivity"
android:exported="true"
android:enabled="false">
<intent-filter>