Merge "Ensure that VMs are stopped before exiting the concurrent VM test" into main
diff --git a/docs/custom_vm.md b/docs/custom_vm.md
index 945798f..fce6da2 100644
--- a/docs/custom_vm.md
+++ b/docs/custom_vm.md
@@ -63,15 +63,23 @@
 As of today (April 2024), ChromiumOS is the only officially supported guest
 payload. We will be adding more OSes in the future.
 
-#### Download from build server
+#### Download ChromiumOS from build server
 
-Here's the link the comprehensive artifacts
-https://pantheon.corp.google.com/storage/browser/chromiumos-image-archive/ferrochrome-public
+Download
+https://storage.googleapis.com/chromiumos-image-archive/ferrochrome-public/R128-15926.0.0/chromiumos_test_image.tar.xz.
+The above will download ferrochrome test image with version `R128-15926.0.0`.
 
-Pick a build, download, and untar `chromiumos_test_image.tar.xz`. We'll boot with `chromiumos_test_image.bin` in it.
+To download latest version, use following code.
 
-To find the latest green build, check following:
-https://pantheon.corp.google.com/storage/browser/_details/chromiumos-image-archive/ferrochrome-public/LATEST-main
+```sh
+URL=https://storage.googleapis.com/chromiumos-image-archive/ferrochrome-public
+LATEST_VERSION=$(curl -s ${URL}/LATEST-main)
+curl -O ${URL}/${LATEST_VERSION}/chromiumos_test_image.tar.xz
+```
+
+To navigate build server artifacts,
+[install gsutil](https://cloud.google.com/storage/docs/gsutil_install).
+`gs://chromiumos-image-archive/ferrochrome-public` is the top level directory for ferrochrome build.
 
 #### Build ChromiumOS for VM
 
diff --git a/ferrochrome_app/Android.bp b/ferrochrome_app/Android.bp
index 182d289..b3998a7 100644
--- a/ferrochrome_app/Android.bp
+++ b/ferrochrome_app/Android.bp
@@ -13,6 +13,9 @@
     init_rc: ["custom_vm_setup.rc"],
     required: ["custom_vm_setup"],
     certificate: "platform",
+    static_libs: [
+        "apache-commons-compress",
+    ],
 }
 
 sh_binary {
diff --git a/ferrochrome_app/java/com/android/virtualization/ferrochrome/FerrochromeActivity.java b/ferrochrome_app/java/com/android/virtualization/ferrochrome/FerrochromeActivity.java
index 2cc0e11..d9e5229 100644
--- a/ferrochrome_app/java/com/android/virtualization/ferrochrome/FerrochromeActivity.java
+++ b/ferrochrome_app/java/com/android/virtualization/ferrochrome/FerrochromeActivity.java
@@ -20,6 +20,7 @@
 import android.app.ActivityManager;
 import android.content.Intent;
 import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
 import android.os.Bundle;
 import android.os.Environment;
 import android.os.SystemProperties;
@@ -27,6 +28,10 @@
 import android.view.WindowManager;
 import android.widget.TextView;
 
+import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
+import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
+import org.apache.commons.compress.compressors.xz.XZCompressorInputStream;
+
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
@@ -35,14 +40,14 @@
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.StandardCopyOption;
+import java.util.List;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipInputStream;
 
 public class FerrochromeActivity extends Activity {
     ExecutorService executorService = Executors.newSingleThreadExecutor();
     private static final String TAG = "FerrochromeActivity";
+    private static final String ACTION_VM_LAUNCHER = "android.virtualization.VM_LAUNCHER";
     private static final String FERROCHROME_VERSION = "R128-15926.0.0";
     private static final String EXTERNAL_STORAGE_DIR =
             Environment.getExternalStorageDirectory().getPath() + File.separator;
@@ -58,9 +63,19 @@
         setContentView(R.layout.activity_ferrochrome);
         getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
 
+        // Find VM Launcher
+        Intent intent = new Intent(ACTION_VM_LAUNCHER);
+        PackageManager pm = getPackageManager();
+        List<ResolveInfo> resolveInfos =
+                pm.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
+        if (resolveInfos == null || resolveInfos.size() != 1) {
+            updateStatus("Failed to resolve VM Launcher");
+            return;
+        }
+
         // Clean up the existing vm launcher process if there is
         ActivityManager am = getSystemService(ActivityManager.class);
-        am.killBackgroundProcesses(getVmLauncherAppPackageName());
+        am.killBackgroundProcesses(resolveInfos.get(0).activityInfo.packageName);
 
         executorService.execute(
                 () -> {
@@ -94,33 +109,10 @@
                     }
                     updateStatus("Done.");
                     updateStatus("Starting Ferrochrome...");
-                    runOnUiThread(
-                            () ->
-                                    startActivity(
-                                            new Intent()
-                                                    .setClassName(
-                                                            getVmLauncherAppPackageName(),
-                                                            "com.android.virtualization.vmlauncher.MainActivity")));
+                    runOnUiThread(() -> startActivity(intent));
                 });
     }
 
-    private String getVmLauncherAppPackageName() {
-        PackageManager pm = getPackageManager();
-        for (String packageName :
-                new String[] {
-                    "com.android.virtualization.vmlauncher",
-                    "com.google.android.virtualization.vmlauncher"
-                }) {
-            try {
-                pm.getPackageInfo(packageName, 0);
-                return packageName;
-            } catch (PackageManager.NameNotFoundException e) {
-                continue;
-            }
-        }
-        return null;
-    }
-
     private void updateStatus(String line) {
         Log.d(TAG, line);
         runOnUiThread(
@@ -159,16 +151,17 @@
         String urlString =
                 "https://storage.googleapis.com/chromiumos-image-archive/ferrochrome-public/"
                         + version
-                        + "/image.zip";
+                        + "/chromiumos_test_image.tar.xz";
         try (InputStream is = (new URL(urlString)).openStream();
-                ZipInputStream zis = new ZipInputStream(is)) {
-            ZipEntry entry;
-            while ((entry = zis.getNextEntry()) != null) {
+                XZCompressorInputStream xz = new XZCompressorInputStream(is);
+                TarArchiveInputStream tar = new TarArchiveInputStream(xz)) {
+            TarArchiveEntry entry;
+            while ((entry = tar.getNextTarEntry()) != null) {
                 if (!entry.getName().contains("chromiumos_test_image.bin")) {
                     continue;
                 }
                 updateStatus("copy " + entry.getName() + " start");
-                Files.copy(zis, IMAGE_PATH, StandardCopyOption.REPLACE_EXISTING);
+                Files.copy(tar, IMAGE_PATH, StandardCopyOption.REPLACE_EXISTING);
                 updateStatus("copy " + entry.getName() + " done");
                 updateVersionInfo(version);
                 break;
diff --git a/vmlauncher_app/AndroidManifest.xml b/vmlauncher_app/AndroidManifest.xml
index 4f95086..bae3227 100644
--- a/vmlauncher_app/AndroidManifest.xml
+++ b/vmlauncher_app/AndroidManifest.xml
@@ -13,6 +13,11 @@
                   android:configChanges="orientation|screenSize|keyboard|keyboardHidden|navigation|uiMode"
                   android:theme="@style/MyTheme"
                   android:exported="true">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <action android:name="android.virtualization.VM_LAUNCHER" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
         </activity>
         <activity-alias android:name=".MainActivityAlias"
                 android:targetActivity="com.android.virtualization.vmlauncher.MainActivity"