Merge "Run resigning Microdroid tests in a background process"
diff --git a/OWNERS b/OWNERS
index ecd24ed..310add7 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,5 +1,7 @@
 # Welcome to Android KVM!
 #
+# Bug component: 867125
+#
 # If you are not a member of the project please send review requests
 # to one of those listed below.
 dbrazdil@google.com
diff --git a/apex/Android.bp b/apex/Android.bp
index 2d6c757..4e64e50 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -57,6 +57,9 @@
     bootclasspath_fragments: [
         "com.android.virt-bootclasspath-fragment",
     ],
+    jni_libs: [
+        "libvirtualmachine_jni",
+    ],
 }
 
 apex_defaults {
@@ -87,9 +90,6 @@
         "fd_server",
         "vm",
     ],
-    jni_libs: [
-        "libvirtualmachine_jni",
-    ],
     prebuilts: [
         "com.android.virt.init.rc",
         "features_com.android.virt.xml",
diff --git a/authfs/aidl/com/android/virt/fs/IAuthFsService.aidl b/authfs/aidl/com/android/virt/fs/IAuthFsService.aidl
index b349db2..30cc281 100644
--- a/authfs/aidl/com/android/virt/fs/IAuthFsService.aidl
+++ b/authfs/aidl/com/android/virt/fs/IAuthFsService.aidl
@@ -21,6 +21,8 @@
 
 /** @hide */
 interface IAuthFsService {
+    const String AUTHFS_SERVICE_SOCKET_NAME = "authfs_service";
+
     /**
      * Creates an AuthFS mount given the config. Returns the binder object that represent the AuthFS
      * instance. The AuthFS setup is deleted once the lifetime of the returned binder object ends.
diff --git a/authfs/service/Android.bp b/authfs/service/Android.bp
index e9eec1e..de6326d 100644
--- a/authfs/service/Android.bp
+++ b/authfs/service/Android.bp
@@ -16,6 +16,7 @@
         "liblibc",
         "liblog_rust",
         "libnix",
+        "librpcbinder_rs",
         "libshared_child",
     ],
     prefer_rlib: true,
diff --git a/authfs/service/authfs_service.rc b/authfs/service/authfs_service.rc
index 9ad0ce6..7edb1ca 100644
--- a/authfs/service/authfs_service.rc
+++ b/authfs/service/authfs_service.rc
@@ -1,2 +1,3 @@
 service authfs_service /system/bin/authfs_service
     disabled
+    socket authfs_service stream 0666 root system
diff --git a/authfs/service/src/main.rs b/authfs/service/src/main.rs
index 77cac9a..671c06a 100644
--- a/authfs/service/src/main.rs
+++ b/authfs/service/src/main.rs
@@ -22,8 +22,9 @@
 
 mod authfs;
 
-use anyhow::{bail, Context, Result};
+use anyhow::{bail, Result};
 use log::*;
+use rpcbinder::run_init_unix_domain_rpc_server;
 use std::ffi::OsString;
 use std::fs::{create_dir, read_dir, remove_dir_all, remove_file};
 use std::sync::atomic::{AtomicUsize, Ordering};
@@ -31,13 +32,10 @@
 use authfs_aidl_interface::aidl::com::android::virt::fs::AuthFsConfig::AuthFsConfig;
 use authfs_aidl_interface::aidl::com::android::virt::fs::IAuthFs::IAuthFs;
 use authfs_aidl_interface::aidl::com::android::virt::fs::IAuthFsService::{
-    BnAuthFsService, IAuthFsService,
+    BnAuthFsService, IAuthFsService, AUTHFS_SERVICE_SOCKET_NAME,
 };
-use binder::{
-    self, add_service, BinderFeatures, ExceptionCode, Interface, ProcessState, Status, Strong,
-};
+use binder::{self, BinderFeatures, ExceptionCode, Interface, Status, Strong};
 
-const SERVICE_NAME: &str = "authfs_service";
 const SERVICE_ROOT: &str = "/data/misc/authfs";
 
 /// Implementation of `IAuthFsService`.
@@ -117,15 +115,17 @@
 
     clean_up_working_directory()?;
 
-    ProcessState::start_thread_pool();
-
     let service = AuthFsService::new_binder(debuggable).as_binder();
-    add_service(SERVICE_NAME, service)
-        .with_context(|| format!("Failed to register service {}", SERVICE_NAME))?;
-    debug!("{} is running", SERVICE_NAME);
-
-    ProcessState::join_thread_pool();
-    bail!("Unexpected exit after join_thread_pool")
+    debug!("{} is starting as a rpc service.", AUTHFS_SERVICE_SOCKET_NAME);
+    let retval = run_init_unix_domain_rpc_server(service, AUTHFS_SERVICE_SOCKET_NAME, || {
+        info!("The RPC server '{}' is running.", AUTHFS_SERVICE_SOCKET_NAME);
+    });
+    if retval {
+        info!("The RPC server at '{}' has shut down gracefully.", AUTHFS_SERVICE_SOCKET_NAME);
+        Ok(())
+    } else {
+        bail!("Premature termination of the RPC server '{}'.", AUTHFS_SERVICE_SOCKET_NAME)
+    }
 }
 
 fn main() {
diff --git a/compos/src/compsvc.rs b/compos/src/compsvc.rs
index 0e8b9f5..40d14d8 100644
--- a/compos/src/compsvc.rs
+++ b/compos/src/compsvc.rs
@@ -30,14 +30,16 @@
 use crate::artifact_signer::ArtifactSigner;
 use crate::compilation::odrefresh;
 use crate::compos_key;
+use authfs_aidl_interface::aidl::com::android::virt::fs::IAuthFsService::{
+    IAuthFsService, AUTHFS_SERVICE_SOCKET_NAME,
+};
 use binder::{BinderFeatures, ExceptionCode, Interface, Result as BinderResult, Status, Strong};
 use compos_aidl_interface::aidl::com::android::compos::ICompOsService::{
     BnCompOsService, ICompOsService, OdrefreshArgs::OdrefreshArgs,
 };
 use compos_common::binder::to_binder_result;
 use compos_common::odrefresh::{is_system_property_interesting, ODREFRESH_PATH};
-
-const AUTHFS_SERVICE_NAME: &str = "authfs_service";
+use rpcbinder::get_unix_domain_rpc_interface;
 
 /// Constructs a binder object that implements ICompOsService.
 pub fn new_binder() -> Result<Strong<dyn ICompOsService>> {
@@ -127,8 +129,10 @@
 
 impl CompOsService {
     fn do_odrefresh(&self, args: &OdrefreshArgs) -> Result<i8> {
-        let authfs_service = binder::get_interface(AUTHFS_SERVICE_NAME)
-            .context("Unable to connect to AuthFS service")?;
+        log::debug!("Prepare to connect to {}", AUTHFS_SERVICE_SOCKET_NAME);
+        let authfs_service: Strong<dyn IAuthFsService> =
+            get_unix_domain_rpc_interface(AUTHFS_SERVICE_SOCKET_NAME)
+                .with_context(|| format!("Failed to connect to {}", AUTHFS_SERVICE_SOCKET_NAME))?;
         let exit_code = odrefresh(&self.odrefresh_path, args, authfs_service, |output_dir| {
             // authfs only shows us the files we created, so it's ok to just sign everything
             // under the output directory.
diff --git a/demo/Android.bp b/demo/Android.bp
index 5241e25..2b234a6 100644
--- a/demo/Android.bp
+++ b/demo/Android.bp
@@ -13,7 +13,10 @@
         "com.google.android.material_material",
     ],
     libs: [
-        "framework-virtualization",
+        // We need to compile against the .impl library which includes the hidden
+        // APIs. Once the APIs are promoted to @SystemApi we can switch to
+        // framework-virtualization, which contains API stubs.
+        "framework-virtualization.impl",
     ],
     jni_libs: ["MicrodroidTestNativeLib"],
     platform_apis: true,
diff --git a/javalib/Android.bp b/javalib/Android.bp
index 04ed273..9be0e9d 100644
--- a/javalib/Android.bp
+++ b/javalib/Android.bp
@@ -12,19 +12,10 @@
 
 java_sdk_library {
     name: "framework-virtualization",
-    installable: false,
-    compile_dex: true,
 
     // TODO(b/243512044): introduce non-updatable-framework-module-defaults
-
     defaults: ["framework-module-defaults"],
 
-    shared_library: false,
-
-    default_to_stubs: false,
-
-    dist_group: "android",
-
     jarjar_rules: "jarjar-rules.txt",
 
     srcs: ["src/**/*.java"],
@@ -43,43 +34,30 @@
         "com.android.system.virtualmachine.sysprop",
     ],
     errorprone: {
-        // We use @GuardedBy and we want a test failure if our locking isn't consistent with it.
         enabled: true,
         javacflags: [
+            // We use @GuardedBy and we want a test failure if our locking isn't consistent with it.
             "-Xep:GuardedBy:ERROR",
+            // JavaApiUsedByMainlineModule is quite spammy, and since we com.android.virt is not
+            // an updatable module we don't need it.
+            "-Xep:JavaApiUsedByMainlineModule:OFF",
         ],
     },
 
-    public: {
-        enabled: true,
-        sdk_version: "module_current",
-    },
-
-    system: {
-        enabled: true,
-        sdk_version: "module_current",
-    },
-
-    module_lib: {
-        enabled: true,
-        sdk_version: "module_current",
-    },
-
     test: {
         enabled: true,
         sdk_version: "module_current",
     },
 
     sdk_version: "core_platform",
-    platform_apis: true,
     impl_only_libs: [
         "framework",
     ],
     impl_library_visibility: [
-        "//frameworks/base",
+        "//packages/modules/Virtualization:__subpackages__",
     ],
 
-    // Temporary workaround, will be removed in a follow-up child cl.
+    // TODO(b/243512044): remove once we have API tracking files in prebuilts/sdk
     unsafe_ignore_missing_latest_api: true,
 }
 
diff --git a/javalib/src/android/system/virtualmachine/VirtualMachine.java b/javalib/src/android/system/virtualmachine/VirtualMachine.java
index c200d00..d9c75c0 100644
--- a/javalib/src/android/system/virtualmachine/VirtualMachine.java
+++ b/javalib/src/android/system/virtualmachine/VirtualMachine.java
@@ -76,7 +76,6 @@
 import java.io.InputStreamReader;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
-import java.lang.ref.WeakReference;
 import java.nio.channels.FileChannel;
 import java.nio.file.FileAlreadyExistsException;
 import java.nio.file.FileVisitResult;
@@ -86,10 +85,7 @@
 import java.nio.file.attribute.BasicFileAttributes;
 import java.util.ArrayList;
 import java.util.Collections;
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
-import java.util.WeakHashMap;
 import java.util.concurrent.Executor;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.function.Consumer;
@@ -107,11 +103,6 @@
  * @hide
  */
 public class VirtualMachine implements AutoCloseable {
-    /** Map from context to a map of all that context's VMs by name. */
-    @GuardedBy("sCreateLock")
-    private static final Map<Context, Map<String, WeakReference<VirtualMachine>>> sInstances =
-            new WeakHashMap<>();
-
     /** Name of the directory under the files directory where all VMs created for the app exist. */
     private static final String VM_DIR = "vm";
 
@@ -208,17 +199,10 @@
     private static final long INSTANCE_FILE_SIZE = 10 * 1024 * 1024;
 
     // A note on lock ordering:
-    // You can take mLock while holding sCreateLock, but not vice versa.
+    // You can take mLock while holding VirtualMachineManager.sCreateLock, but not vice versa.
     // We never take any other lock while holding mCallbackLock; therefore you can
     // take mCallbackLock while holding any other lock.
 
-    /**
-     * A lock used to synchronize the creation of virtual machines. It protects
-     * {@link #sInstances}, but is also held throughout VM creation / retrieval / deletion, to
-     * prevent these actions racing with each other.
-     */
-    static final Object sCreateLock = new Object();
-
     /** Lock protecting our mutable state (other than callbacks). */
     private final Object mLock = new Object();
 
@@ -281,12 +265,6 @@
         mExtraApks = setupExtraApks(context, config, thisVmDir);
     }
 
-    @GuardedBy("sCreateLock")
-    @NonNull
-    private static Map<String, WeakReference<VirtualMachine>> getInstancesMap(Context context) {
-        return sInstances.computeIfAbsent(context, unused -> new HashMap<>());
-    }
-
     /**
      * Builds a virtual machine from an {@link VirtualMachineDescriptor} object and associates it
      * with the given name.
@@ -297,7 +275,7 @@
      * #delete}. The imported virtual machine is in {@link #STATUS_STOPPED} state. To run the VM,
      * call {@link #run}.
      */
-    @GuardedBy("sCreateLock")
+    @GuardedBy("VirtualMachineManager.sCreateLock")
     @NonNull
     static VirtualMachine fromDescriptor(
             @NonNull Context context,
@@ -315,7 +293,6 @@
                 throw new VirtualMachineException("failed to create instance image", e);
             }
             vm.importInstanceFrom(vmDescriptor.getInstanceImgFd());
-            getInstancesMap(context).put(name, new WeakReference<>(vm));
             return vm;
         } catch (VirtualMachineException | RuntimeException e) {
             // If anything goes wrong, delete any files created so far and the VM's directory
@@ -333,7 +310,7 @@
      * it is persisted until it is deleted by calling {@link #delete}. The created virtual machine
      * is in {@link #STATUS_STOPPED} state. To run the VM, call {@link #run}.
      */
-    @GuardedBy("sCreateLock")
+    @GuardedBy("VirtualMachineManager.sCreateLock")
     @NonNull
     static VirtualMachine create(
             @NonNull Context context, @NonNull String name, @NonNull VirtualMachineConfig config)
@@ -365,9 +342,6 @@
             } catch (ServiceSpecificException | IllegalArgumentException e) {
                 throw new VirtualMachineException("failed to create instance partition", e);
             }
-
-            getInstancesMap(context).put(name, new WeakReference<>(vm));
-
             return vm;
         } catch (VirtualMachineException | RuntimeException e) {
             // If anything goes wrong, delete any files created so far and the VM's directory
@@ -381,10 +355,10 @@
     }
 
     /** Loads a virtual machine that is already created before. */
-    @GuardedBy("sCreateLock")
+    @GuardedBy("VirtualMachineManager.sCreateLock")
     @Nullable
-    static VirtualMachine load(
-            @NonNull Context context, @NonNull String name) throws VirtualMachineException {
+    static VirtualMachine load(@NonNull Context context, @NonNull String name)
+            throws VirtualMachineException {
         File thisVmDir = getVmDir(context, name);
         if (!thisVmDir.exists()) {
             // The VM doesn't exist.
@@ -392,51 +366,33 @@
         }
         File configFilePath = new File(thisVmDir, CONFIG_FILE);
         VirtualMachineConfig config = VirtualMachineConfig.from(configFilePath);
-        Map<String, WeakReference<VirtualMachine>> instancesMap = getInstancesMap(context);
-
-        VirtualMachine vm = null;
-        if (instancesMap.containsKey(name)) {
-            vm = instancesMap.get(name).get();
-        }
-        if (vm == null) {
-            vm = new VirtualMachine(context, name, config);
-        }
+        VirtualMachine vm = new VirtualMachine(context, name, config);
 
         if (!vm.mInstanceFilePath.exists()) {
             throw new VirtualMachineException("instance image missing");
         }
 
-        instancesMap.put(name, new WeakReference<>(vm));
-
         return vm;
     }
 
-    @GuardedBy("sCreateLock")
-    static void delete(Context context, String name) throws VirtualMachineException {
-        Map<String, WeakReference<VirtualMachine>> instancesMap = sInstances.get(context);
-        VirtualMachine vm;
-        if (instancesMap != null && instancesMap.containsKey(name)) {
-            vm = instancesMap.get(name).get();
-        } else {
-            vm = null;
+    @GuardedBy("VirtualMachineManager.sCreateLock")
+    void delete(Context context, String name) throws VirtualMachineException {
+        synchronized (mLock) {
+            checkStopped();
         }
 
-        if (vm != null) {
-            synchronized (vm.mLock) {
-                vm.checkStopped();
-            }
-        }
+        deleteVmDirectory(context, name);
+    }
 
+    static void deleteVmDirectory(Context context, String name) throws VirtualMachineException {
         try {
             deleteRecursively(getVmDir(context, name));
         } catch (IOException e) {
             throw new VirtualMachineException(e);
         }
-
-        if (instancesMap != null) instancesMap.remove(name);
     }
 
-    @GuardedBy("sCreateLock")
+    @GuardedBy("VirtualMachineManager.sCreateLock")
     @NonNull
     private static File createVmDir(@NonNull Context context, @NonNull String name)
             throws VirtualMachineException {
diff --git a/javalib/src/android/system/virtualmachine/VirtualMachineManager.java b/javalib/src/android/system/virtualmachine/VirtualMachineManager.java
index c357f50..098e3ca 100644
--- a/javalib/src/android/system/virtualmachine/VirtualMachineManager.java
+++ b/javalib/src/android/system/virtualmachine/VirtualMachineManager.java
@@ -25,6 +25,7 @@
 import android.annotation.SuppressLint;
 import android.content.Context;
 import android.sysprop.HypervisorProperties;
+import android.util.ArrayMap;
 
 import com.android.internal.annotations.GuardedBy;
 
@@ -47,6 +48,13 @@
  * @hide
  */
 public class VirtualMachineManager {
+    /**
+     * A lock used to synchronize the creation of virtual machines. It protects {@link #sInstances},
+     * but is also held throughout VM creation / retrieval / deletion, to prevent these actions
+     * racing with each other.
+     */
+    private static final Object sCreateLock = new Object();
+
     @NonNull private final Context mContext;
 
     private VirtualMachineManager(@NonNull Context context) {
@@ -57,6 +65,10 @@
     private static final Map<Context, WeakReference<VirtualMachineManager>> sInstances =
             new WeakHashMap<>();
 
+    @NonNull
+    @GuardedBy("sCreateLock")
+    private final Map<String, WeakReference<VirtualMachine>> mVmsByName = new ArrayMap<>();
+
     /**
      * Capabilities of the virtual machine implementation.
      *
@@ -136,11 +148,48 @@
     public VirtualMachine create(
             @NonNull String name, @NonNull VirtualMachineConfig config)
             throws VirtualMachineException {
-        synchronized (VirtualMachine.sCreateLock) {
-            return VirtualMachine.create(mContext, name, config);
+        synchronized (sCreateLock) {
+            return createLocked(name, config);
         }
     }
 
+    @NonNull
+    @GuardedBy("sCreateLock")
+    private VirtualMachine createLocked(String name, VirtualMachineConfig config)
+            throws VirtualMachineException {
+        VirtualMachine vm = VirtualMachine.create(mContext, name, config);
+        mVmsByName.put(name, new WeakReference<>(vm));
+        return vm;
+    }
+
+    /**
+     * Returns an existing {@link VirtualMachine} with the given name. Returns null if there is no
+     * such virtual machine.
+     *
+     * @throws VirtualMachineException if the virtual machine exists but could not be successfully
+     *     retrieved.
+     * @hide
+     */
+    @Nullable
+    public VirtualMachine get(@NonNull String name) throws VirtualMachineException {
+        synchronized (sCreateLock) {
+            return getLocked(name);
+        }
+    }
+
+    @Nullable
+    @GuardedBy("sCreateLock")
+    private VirtualMachine getLocked(String name) throws VirtualMachineException {
+        VirtualMachine vm = getVmByName(name);
+        if (vm != null) return vm;
+
+        vm = VirtualMachine.load(mContext, name);
+        if (vm != null) {
+            mVmsByName.put(name, new WeakReference<>(vm));
+        }
+        return vm;
+    }
+
     /**
      * Imports a virtual machine from an {@link VirtualMachineDescriptor} object and associates it
      * with the given name.
@@ -154,23 +203,10 @@
     public VirtualMachine importFromDescriptor(
             @NonNull String name, @NonNull VirtualMachineDescriptor vmDescriptor)
             throws VirtualMachineException {
-        synchronized (VirtualMachine.sCreateLock) {
-            return VirtualMachine.fromDescriptor(mContext, name, vmDescriptor);
-        }
-    }
-
-    /**
-     * Returns an existing {@link VirtualMachine} with the given name. Returns null if there is no
-     * such virtual machine.
-     *
-     * @throws VirtualMachineException if the virtual machine exists but could not be successfully
-     *                                 retrieved.
-     * @hide
-     */
-    @Nullable
-    public VirtualMachine get(@NonNull String name) throws VirtualMachineException {
-        synchronized (VirtualMachine.sCreateLock) {
-            return VirtualMachine.load(mContext, name);
+        synchronized (sCreateLock) {
+            VirtualMachine vm = VirtualMachine.fromDescriptor(mContext, name, vmDescriptor);
+            mVmsByName.put(name, new WeakReference<>(vm));
+            return vm;
         }
     }
 
@@ -185,14 +221,14 @@
     public VirtualMachine getOrCreate(
             @NonNull String name, @NonNull VirtualMachineConfig config)
             throws VirtualMachineException {
-        VirtualMachine vm;
-        synchronized (VirtualMachine.sCreateLock) {
-            vm = get(name);
-            if (vm == null) {
-                vm = create(name, config);
+        synchronized (sCreateLock) {
+            VirtualMachine vm = getLocked(name);
+            if (vm != null) {
+                return vm;
+            } else {
+                return createLocked(name, config);
             }
         }
-        return vm;
     }
 
     /**
@@ -208,8 +244,26 @@
      */
     public void delete(@NonNull String name) throws VirtualMachineException {
         requireNonNull(name);
-        synchronized (VirtualMachine.sCreateLock) {
-            VirtualMachine.delete(mContext, name);
+        synchronized (sCreateLock) {
+            VirtualMachine vm = getVmByName(name);
+            if (vm == null) {
+                VirtualMachine.deleteVmDirectory(mContext, name);
+            } else {
+                vm.delete(mContext, name);
+            }
+            mVmsByName.remove(name);
         }
     }
+
+    @GuardedBy("sCreateLock")
+    private VirtualMachine getVmByName(String name) {
+        WeakReference<VirtualMachine> weakReference = mVmsByName.get(name);
+        if (weakReference != null) {
+            VirtualMachine vm = weakReference.get();
+            if (vm != null && vm.getStatus() != VirtualMachine.STATUS_DELETED) {
+                return vm;
+            }
+        }
+        return null;
+    }
 }
diff --git a/microdroid/Android.bp b/microdroid/Android.bp
index c3e2692..91801ff 100644
--- a/microdroid/Android.bp
+++ b/microdroid/Android.bp
@@ -72,7 +72,6 @@
         "debuggerd",
         "linker",
         "linkerconfig",
-        "servicemanager.microdroid",
         "tombstoned.microdroid",
         "tombstone_transmit.microdroid",
         "cgroups.json",
diff --git a/microdroid/init.rc b/microdroid/init.rc
index 9c62782..71d7fe5 100644
--- a/microdroid/init.rc
+++ b/microdroid/init.rc
@@ -37,8 +37,6 @@
     chmod 0666 /dev/binderfs/binder
     chmod 0666 /dev/binderfs/vndbinder
 
-    start servicemanager
-
 on init
     mkdir /mnt/apk 0755 system system
     mkdir /mnt/extra-apk 0755 root root
diff --git a/microdroid_manager/src/main.rs b/microdroid_manager/src/main.rs
index 762a149..0ac4167 100644
--- a/microdroid_manager/src/main.rs
+++ b/microdroid_manager/src/main.rs
@@ -28,7 +28,10 @@
 use android_system_virtualmachineservice::aidl::android::system::virtualmachineservice::IVirtualMachineService::{
         IVirtualMachineService, VM_BINDER_SERVICE_PORT,
 };
-use android_system_virtualization_payload::aidl::android::system::virtualization::payload::IVmPayloadService::VM_APK_CONTENTS_PATH;
+use android_system_virtualization_payload::aidl::android::system::virtualization::payload::IVmPayloadService::{
+    VM_APK_CONTENTS_PATH,
+    VM_PAYLOAD_SERVICE_SOCKET_NAME,
+};
 use anyhow::{anyhow, bail, ensure, Context, Error, Result};
 use apkverify::{get_public_key_der, verify, V4Signature};
 use binder::Strong;
@@ -36,14 +39,16 @@
 use glob::glob;
 use itertools::sorted;
 use libc::VMADDR_CID_HOST;
-use log::{error, info};
+use log::{error, info, warn};
 use microdroid_metadata::{write_metadata, Metadata, PayloadMetadata};
 use microdroid_payload_config::{OsConfig, Task, TaskType, VmPayloadConfig};
+use nix::fcntl::{fcntl, F_SETFD, FdFlag};
 use nix::sys::signal::Signal;
 use openssl::sha::Sha512;
 use payload::{get_apex_data_from_payload, load_metadata, to_metadata};
 use rand::Fill;
 use rpcbinder::get_vsock_rpc_interface;
+use rustutils::sockets::android_get_control_socket;
 use rustutils::system_properties;
 use rustutils::system_properties::PropertyWatcher;
 use std::borrow::Cow::{Borrowed, Owned};
@@ -174,10 +179,22 @@
     })
 }
 
+fn set_cloexec_on_vm_payload_service_socket() -> Result<()> {
+    let fd = android_get_control_socket(VM_PAYLOAD_SERVICE_SOCKET_NAME)?;
+
+    fcntl(fd, F_SETFD(FdFlag::FD_CLOEXEC))?;
+
+    Ok(())
+}
+
 fn try_main() -> Result<()> {
     let _ = kernlog::init();
     info!("started.");
 
+    if let Err(e) = set_cloexec_on_vm_payload_service_socket() {
+        warn!("Failed to set cloexec on vm payload socket: {:?}", e);
+    }
+
     load_crashkernel_if_supported().context("Failed to load crashkernel")?;
 
     swap::init_swap().context("Failed to initialise swap")?;
@@ -726,8 +743,7 @@
     Ok(())
 }
 
-/// Executes the given task. Stdout of the task is piped into the vsock stream to the
-/// virtualizationservice in the host side.
+/// Executes the given task.
 fn exec_task(task: &Task, service: &Strong<dyn IVirtualMachineService>) -> Result<i32> {
     info!("executing main task {:?}...", task);
     let mut command = match task.type_ {
@@ -738,6 +754,7 @@
             command
         }
     };
+    command.stdin(Stdio::null()).stdout(Stdio::null()).stderr(Stdio::null());
 
     info!("notifying payload started");
     service.notifyPayloadStarted()?;
diff --git a/microdroid_manager/src/vm_payload_service.rs b/microdroid_manager/src/vm_payload_service.rs
index 249a2d8..126a8a9 100644
--- a/microdroid_manager/src/vm_payload_service.rs
+++ b/microdroid_manager/src/vm_payload_service.rs
@@ -106,8 +106,8 @@
     fn setup_payload_stdio_proxy(&self) -> Result<File> {
         // Instead of a predefined port in the host, we open up a port in the guest and have
         // the host connect to it. This makes it possible to have per-app instances of VS.
-        const ANY_PORT: u32 = 0;
-        let listener = VsockListener::bind_with_cid_port(libc::VMADDR_CID_HOST, ANY_PORT)
+        const ANY_PORT: u32 = u32::MAX; // (u32)-1
+        let listener = VsockListener::bind_with_cid_port(libc::VMADDR_CID_ANY, ANY_PORT)
             .context("Failed to create vsock listener")?;
         let addr = listener.local_addr().context("Failed to resolve listener port")?;
         self.virtual_machine_service
diff --git a/tests/benchmark/Android.bp b/tests/benchmark/Android.bp
index bccea6b..1747183 100644
--- a/tests/benchmark/Android.bp
+++ b/tests/benchmark/Android.bp
@@ -16,7 +16,10 @@
         "com.android.microdroid.testservice-java",
         "truth-prebuilt",
     ],
-    libs: ["framework-virtualization"],
+    // We need to compile against the .impl library which includes the hidden
+    // APIs. Once the APIs are promoted to @SystemApi we can switch to
+    // framework-virtualization, which contains API stubs.
+    libs: ["framework-virtualization.impl"],
     jni_libs: [
         "MicrodroidBenchmarkNativeLib",
         "MicrodroidIdleNativeLib",
diff --git a/tests/helper/Android.bp b/tests/helper/Android.bp
index bd92020..86af955 100644
--- a/tests/helper/Android.bp
+++ b/tests/helper/Android.bp
@@ -24,5 +24,8 @@
         "VirtualizationTestHelper",
         "truth-prebuilt",
     ],
-    libs: ["framework-virtualization"],
+    // We need to compile against the .impl library which includes the hidden
+    // APIs. Once the APIs are promoted to @SystemApi we can switch to
+    // framework-virtualization, which contains API stubs.
+    libs: ["framework-virtualization.impl"],
 }
diff --git a/tests/hostside/helper/java/com/android/microdroid/test/host/MicrodroidHostTestCaseBase.java b/tests/hostside/helper/java/com/android/microdroid/test/host/MicrodroidHostTestCaseBase.java
index 9bcd1d3..1deaced 100644
--- a/tests/hostside/helper/java/com/android/microdroid/test/host/MicrodroidHostTestCaseBase.java
+++ b/tests/hostside/helper/java/com/android/microdroid/test/host/MicrodroidHostTestCaseBase.java
@@ -49,10 +49,6 @@
     private static final String MICRODROID_SERIAL = "localhost:" + TEST_VM_ADB_PORT;
     private static final String INSTANCE_IMG = "instance.img";
 
-    // This is really slow on GCE (2m 40s) but fast on localhost or actual Android phones (< 10s).
-    // Then there is time to run the actual task. Set the maximum timeout value big enough.
-    private static final long MICRODROID_MAX_LIFETIME_MINUTES = 20;
-
     private static final long MICRODROID_ADB_CONNECT_TIMEOUT_MINUTES = 5;
     protected static final long MICRODROID_COMMAND_TIMEOUT_MILLIS = 30000;
     private static final long MICRODROID_COMMAND_RETRY_INTERVAL_MILLIS = 500;
@@ -196,17 +192,6 @@
         return pathLine.substring("package:".length());
     }
 
-    private static void forwardFileToLog(CommandRunner android, String path, String tag)
-            throws DeviceNotAvailableException {
-        android.runWithTimeout(
-                MICRODROID_MAX_LIFETIME_MINUTES * 60 * 1000,
-                "logwrapper",
-                "sh",
-                "-c",
-                "\"$'tail -f -n +0 " + path
-                        + " | sed \\'s/^/" + tag + ": /g\\''\""); // add tags in front of lines
-    }
-
     public static void shutdownMicrodroid(ITestDevice androidDevice, String cid)
             throws DeviceNotAvailableException {
         CommandRunner android = new CommandRunner(androidDevice);
diff --git a/tests/hostside/java/com/android/microdroid/test/MicrodroidHostTests.java b/tests/hostside/java/com/android/microdroid/test/MicrodroidHostTests.java
index 54f6782..4e9c501 100644
--- a/tests/hostside/java/com/android/microdroid/test/MicrodroidHostTests.java
+++ b/tests/hostside/java/com/android/microdroid/test/MicrodroidHostTests.java
@@ -640,6 +640,7 @@
         // Check that no denials have happened so far
         CommandRunner android = new CommandRunner(getDevice());
         assertThat(android.tryRun("egrep", "'avc:[[:space:]]{1,2}denied'", LOG_PATH)).isNull();
+        assertThat(android.tryRun("egrep", "'avc:[[:space:]]{1,2}denied'", CONSOLE_PATH)).isNull();
 
         assertThat(microdroid.run("cat /proc/cpuinfo | grep processor | wc -l"))
                 .isEqualTo(Integer.toString(NUM_VCPUS));
diff --git a/tests/testapk/Android.bp b/tests/testapk/Android.bp
index 8d49721..707dca1 100644
--- a/tests/testapk/Android.bp
+++ b/tests/testapk/Android.bp
@@ -19,7 +19,10 @@
         "truth-prebuilt",
         "compatibility-common-util-devicesidelib",
     ],
-    libs: ["framework-virtualization"],
+    // We need to compile against the .impl library which includes the hidden
+    // APIs. Once the APIs are promoted to @SystemApi we can switch to
+    // framework-virtualization, which contains API stubs.
+    libs: ["framework-virtualization.impl"],
     jni_libs: [
         "MicrodroidTestNativeLib",
         "MicrodroidIdleNativeLib",