Merge "Implement create/release_audio_patch API in audio HAL for cuttlefish."
diff --git a/OWNERS b/OWNERS
index 9594320..1944029 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,8 +1,11 @@
+# Current team members
 adelva@google.com
-ghartman@google.com
 jemoreira@google.com
 malchev@google.com
 muntsinger@google.com
 natsu@google.com
 rammuthiah@google.com
 schuffelen@google.com
+
+# Former team members
+ghartman@google.com
diff --git a/common/libs/fs/shared_fd.cpp b/common/libs/fs/shared_fd.cpp
index 2f6d100..b85cf7c 100644
--- a/common/libs/fs/shared_fd.cpp
+++ b/common/libs/fs/shared_fd.cpp
@@ -17,6 +17,8 @@
 
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <sys/mman.h>
+#include <sys/syscall.h>
 #include <cstddef>
 #include <errno.h>
 #include <fcntl.h>
@@ -52,6 +54,34 @@
     }
   }
 }
+
+/*
+ * Android currently has host prebuilts of glibc 2.15 and 2.17, but
+ * memfd_create was only added in glibc 2.27. It was defined in Linux 3.17,
+ * so we consider it safe to use the low-level arbitrary syscall wrapper.
+ */
+#ifndef __NR_memfd_create
+# if defined(__x86_64__)
+#  define __NR_memfd_create 319
+# elif defined(__i386__)
+#  define __NR_memfd_create 356
+# elif defined(__aarch64__)
+#  define __NR_memfd_create 279
+# else
+/* No interest in other architectures. */
+#  error "Unknown architecture."
+# endif
+#endif
+
+int memfd_create_wrapper(const char* name, unsigned int flags) {
+#ifdef CUTTLEFISH_HOST
+  // TODO(schuffelen): Use memfd_create with a newer host libc.
+  return syscall(__NR_memfd_create, name, flags);
+#else
+  return memfd_create(name, flags);
+#endif
+}
+
 }  // namespace
 
 namespace cvd {
@@ -256,6 +286,12 @@
   return std::shared_ptr<FileInstance>(new FileInstance(fd, errno));
 }
 
+SharedFD SharedFD::MemfdCreate(const char* name, unsigned int flags) {
+  int fd = memfd_create_wrapper(name, flags);
+  int error_num = errno;
+  return std::shared_ptr<FileInstance>(new FileInstance(fd, error_num));
+}
+
 bool SharedFD::SocketPair(int domain, int type, int protocol,
                           SharedFD* fd0, SharedFD* fd1) {
   int fds[2];
diff --git a/common/libs/fs/shared_fd.h b/common/libs/fs/shared_fd.h
index eec17b1..044c7cc 100644
--- a/common/libs/fs/shared_fd.h
+++ b/common/libs/fs/shared_fd.h
@@ -145,6 +145,7 @@
   static bool Pipe(SharedFD* fd0, SharedFD* fd1);
   static SharedFD Event(int initval = 0, int flags = 0);
   static SharedFD Epoll(int flags = 0);
+  static SharedFD MemfdCreate(const char* name, unsigned int flags = 0);
   static bool SocketPair(int domain, int type, int protocol, SharedFD* fd0,
                          SharedFD* fd1);
   static SharedFD Socket(int domain, int socket_type, int protocol);
diff --git a/guest/hals/ril/cuttlefish_ril.cpp b/guest/hals/ril/cuttlefish_ril.cpp
index e5a120f..d3c3817 100644
--- a/guest/hals/ril/cuttlefish_ril.cpp
+++ b/guest/hals/ril/cuttlefish_ril.cpp
@@ -2269,7 +2269,7 @@
   return;
 }
 
-// New functions after Q
+// New functions after Q.
 static void request_set_signal_strength_reporting_criteria_1_5(int /*request*/, void* /*data*/,
                                                                size_t /*datalen*/, RIL_Token t) {
   ALOGV("request_set_signal_strength_reporting_criteria_1_5 - void");
diff --git a/guest/hals/ril/libril/ril.h b/guest/hals/ril/libril/ril.h
index fd8553c..fde868c 100644
--- a/guest/hals/ril/libril/ril.h
+++ b/guest/hals/ril/libril/ril.h
@@ -2040,6 +2040,8 @@
     RIL_APN_TYPE_EMERGENCY    = 0x200,        // APN type for Emergency PDN. This is not an IA apn,
                                               // but is used for access to carrier services in an
                                               // emergency call situation.
+    RIL_APN_TYPE_MCX          = 0x400,        // APN type for Mission Critical Service
+    RIL_APN_TYPE_XCAP         = 0x800,        // APN type for XCAP
     RIL_APN_TYPE_ALL          = 0xFFFFFFFF    // All APN types
 } RIL_ApnTypes;
 
diff --git a/guest/hals/ril/libril/ril_service.cpp b/guest/hals/ril/libril/ril_service.cpp
index ae46c3f..dcfafc8 100755
--- a/guest/hals/ril/libril/ril_service.cpp
+++ b/guest/hals/ril/libril/ril_service.cpp
@@ -541,6 +541,15 @@
             const hidl_vec<::android::hardware::radio::V1_5::RadioAccessSpecifier>& specifiers);
     Return<void> startNetworkScan_1_5(int32_t serial,
             const ::android::hardware::radio::V1_5::NetworkScanRequest& request);
+    Return<void> setupDataCall_1_5(int32_t serial,
+            ::android::hardware::radio::V1_5::AccessNetwork accessNetwork,
+            const ::android::hardware::radio::V1_5::DataProfileInfo& dataProfileInfo,
+            bool roamingAllowed, ::android::hardware::radio::V1_2::DataRequestReason reason,
+            const hidl_vec<hidl_string>& addresses, const hidl_vec<hidl_string>& dnses);
+    Return<void> setInitialAttachApn_1_5(int32_t serial,
+            const ::android::hardware::radio::V1_5::DataProfileInfo& dataProfileInfo);
+    Return<void> setDataProfile_1_5(int32_t serial,
+            const hidl_vec<::android::hardware::radio::V1_5::DataProfileInfo>& profiles);
 };
 
 struct OemHookImpl : public IOemHook {
@@ -3579,7 +3588,7 @@
     return Void();
 }
 
-// Methods from ::android::hardware::radio::IRadio::V1_5 follow.
+// Methods from ::android::hardware::radio::V1_5::IRadio follow.
 Return<void> RadioImpl_1_5::setSignalStrengthReportingCriteria_1_5(int32_t /* serial */,
         const ::android::hardware::radio::V1_5::SignalThresholdInfo& /* signalThresholdInfo */,
         const ::android::hardware::radio::V1_5::AccessNetwork /* accessNetwork */) {
@@ -3642,6 +3651,102 @@
     return Void();
 }
 
+Return<void> RadioImpl_1_5::setupDataCall_1_5(int32_t serial ,
+        ::android::hardware::radio::V1_5::AccessNetwork /* accessNetwork */,
+        const ::android::hardware::radio::V1_5::DataProfileInfo& dataProfileInfo,
+        bool roamingAllowed, ::android::hardware::radio::V1_2::DataRequestReason /* reason */,
+        const hidl_vec<hidl_string>& /* addresses */, const hidl_vec<hidl_string>& /* dnses */) {
+
+#if VDBG
+    RLOGD("setupDataCall_1_5: serial %d", serial);
+#endif
+
+    char *mvnoTypeStr = NULL;
+    if (!convertMvnoTypeToString(MvnoType::IMSI, mvnoTypeStr)) {
+        RequestInfo *pRI = android::addRequestToList(serial, mSlotId,
+                RIL_REQUEST_SETUP_DATA_CALL);
+        if (pRI != NULL) {
+            sendErrorResponse(pRI, RIL_E_INVALID_ARGUMENTS);
+        }
+        return Void();
+    }
+    dispatchStrings(serial, mSlotId, RIL_REQUEST_SETUP_DATA_CALL, true, 15,
+        std::to_string((int) RadioTechnology::UNKNOWN + 2).c_str(),
+        std::to_string((int) dataProfileInfo.base.profileId).c_str(),
+        dataProfileInfo.base.apn.c_str(),
+        dataProfileInfo.base.user.c_str(),
+        dataProfileInfo.base.password.c_str(),
+        std::to_string((int) dataProfileInfo.base.authType).c_str(),
+        getProtocolString(dataProfileInfo.base.protocol),
+        getProtocolString(dataProfileInfo.base.roamingProtocol),
+        std::to_string(dataProfileInfo.supportedApnTypesBitmap).c_str(),
+        std::to_string(dataProfileInfo.base.bearerBitmap).c_str(),
+        dataProfileInfo.base.persistent ? "1" : "0",
+        std::to_string(dataProfileInfo.base.mtu).c_str(),
+        mvnoTypeStr,
+        "302720x94",
+        roamingAllowed ? "1" : "0");
+    return Void();
+}
+
+Return<void> RadioImpl_1_5::setInitialAttachApn_1_5(int32_t  serial ,
+        const ::android::hardware::radio::V1_5::DataProfileInfo& dataProfileInfo) {
+    RequestInfo *pRI = android::addRequestToList(serial, mSlotId,
+            RIL_REQUEST_SET_INITIAL_ATTACH_APN);
+    if (pRI == NULL) {
+        return Void();
+    }
+
+    RadioResponseInfo responseInfo = {};
+    populateResponseInfo(responseInfo, serial, RESPONSE_SOLICITED, RIL_E_SUCCESS);
+
+    if (radioService[mSlotId]->mRadioResponseV1_5 != NULL) {
+        Return<void> retStatus
+                = radioService[mSlotId]->mRadioResponseV1_5->setInitialAttachApnResponse(responseInfo);
+    } else if (radioService[mSlotId]->mRadioResponseV1_4 != NULL) {
+        Return<void> retStatus
+                = radioService[mSlotId]->mRadioResponseV1_4->setInitialAttachApnResponse(responseInfo);
+        radioService[mSlotId]->checkReturnStatus(retStatus);
+    } else if (radioService[mSlotId]->mRadioResponse != NULL) {
+        Return<void> retStatus
+                = radioService[mSlotId]->mRadioResponse->setInitialAttachApnResponse(responseInfo);
+        radioService[mSlotId]->checkReturnStatus(retStatus);
+    } else {
+        RLOGE("setInitialAttachApnResponse: radioService[%d]->mRadioResponse == NULL", mSlotId);
+    }
+
+    return Void();
+}
+
+Return<void> RadioImpl_1_5::setDataProfile_1_5(int32_t  serial ,
+        const hidl_vec<::android::hardware::radio::V1_5::DataProfileInfo>& /* profiles */) {
+    RequestInfo *pRI = android::addRequestToList(serial, mSlotId,
+            RIL_REQUEST_SET_DATA_PROFILE);
+    if (pRI == NULL) {
+        return Void();
+    }
+
+    RadioResponseInfo responseInfo = {};
+    populateResponseInfo(responseInfo, serial, RESPONSE_SOLICITED, RIL_E_SUCCESS);
+
+    if (radioService[mSlotId]->mRadioResponseV1_5 != NULL) {
+        Return<void> retStatus
+                = radioService[mSlotId]->mRadioResponseV1_5->setDataProfileResponse(responseInfo);
+    } else if (radioService[mSlotId]->mRadioResponseV1_4 != NULL) {
+        Return<void> retStatus
+                = radioService[mSlotId]->mRadioResponseV1_4->setDataProfileResponse(responseInfo);
+        radioService[mSlotId]->checkReturnStatus(retStatus);
+    } else if (radioService[mSlotId]->mRadioResponse != NULL) {
+        Return<void> retStatus
+                = radioService[mSlotId]->mRadioResponse->setDataProfileResponse(responseInfo);
+        radioService[mSlotId]->checkReturnStatus(retStatus);
+    } else {
+        RLOGE("setDataProfileResponse: radioService[%d]->mRadioResponse == NULL", mSlotId);
+    }
+
+    return Void();
+}
+
 // OEM hook methods:
 Return<void> OemHookImpl::setResponseFunctions(
         const ::android::sp<IOemHookResponse>& oemHookResponseParam,
@@ -4836,14 +4941,36 @@
 #if VDBG
     RLOGD("setupDataCallResponse: serial %d", serial);
 #endif
-
-    if (radioService[slotId]->mRadioResponseV1_4 != NULL) {
+    if (radioService[slotId]->mRadioResponseV1_5 != NULL) {
         RadioResponseInfo responseInfo = {};
         populateResponseInfo(responseInfo, serial, responseType, e);
         ::android::hardware::radio::V1_4::SetupDataCallResult result;
         if (response == NULL || (responseLen % sizeof(RIL_Data_Call_Response_v11)) != 0) {
             if (response != NULL) {
-                RLOGE("setupDataCallResponse: Invalid response");
+                RLOGE("setupDataCallResponse_1_5: Invalid response");
+                if (e == RIL_E_SUCCESS) responseInfo.error = RadioError::INVALID_RESPONSE;
+            }
+            result.cause = ::android::hardware::radio::V1_4::DataCallFailCause::ERROR_UNSPECIFIED;
+            result.type = ::android::hardware::radio::V1_4::PdpProtocolType::UNKNOWN;
+            result.ifname = hidl_string();
+            result.addresses = hidl_vec<hidl_string>();
+            result.dnses = hidl_vec<hidl_string>();
+            result.gateways = hidl_vec<hidl_string>();
+            result.pcscf = hidl_vec<hidl_string>();
+        } else {
+            convertRilDataCallToHal((RIL_Data_Call_Response_v11 *) response, result);
+        }
+
+        Return<void> retStatus = radioService[slotId]->mRadioResponseV1_5->setupDataCallResponse_1_5(
+                responseInfo, result);
+        radioService[slotId]->checkReturnStatus(retStatus);
+    } else if (radioService[slotId]->mRadioResponseV1_4 != NULL) {
+        RadioResponseInfo responseInfo = {};
+        populateResponseInfo(responseInfo, serial, responseType, e);
+        ::android::hardware::radio::V1_4::SetupDataCallResult result;
+        if (response == NULL || (responseLen % sizeof(RIL_Data_Call_Response_v11)) != 0) {
+            if (response != NULL) {
+                RLOGE("setupDataCallResponse_1_4: Invalid response");
                 if (e == RIL_E_SUCCESS) responseInfo.error = RadioError::INVALID_RESPONSE;
             }
             result.cause = ::android::hardware::radio::V1_4::DataCallFailCause::ERROR_UNSPECIFIED;
@@ -6740,7 +6867,13 @@
     RLOGD("setInitialAttachApnResponse: serial %d", serial);
 #endif
 
-    if (radioService[slotId]->mRadioResponse != NULL) {
+    if (radioService[slotId]->mRadioResponseV1_5 != NULL) {
+        RadioResponseInfo responseInfo = {};
+        populateResponseInfo(responseInfo, serial, responseType, e);
+        Return<void> retStatus
+                = radioService[slotId]->mRadioResponseV1_5->setInitialAttachApnResponse_1_5(
+                responseInfo);
+    } else if (radioService[slotId]->mRadioResponse != NULL) {
         RadioResponseInfo responseInfo = {};
         populateResponseInfo(responseInfo, serial, responseType, e);
         Return<void> retStatus
@@ -7100,7 +7233,13 @@
     RLOGD("setDataProfileResponse: serial %d", serial);
 #endif
 
-    if (radioService[slotId]->mRadioResponse != NULL) {
+    if (radioService[slotId]->mRadioResponseV1_5 != NULL) {
+        RadioResponseInfo responseInfo = {};
+        populateResponseInfo(responseInfo, serial, responseType, e);
+        Return<void> retStatus
+                = radioService[slotId]->mRadioResponseV1_5->setDataProfileResponse_1_5(
+                responseInfo);
+    } else if (radioService[slotId]->mRadioResponse != NULL) {
         RadioResponseInfo responseInfo = {};
         populateResponseInfo(responseInfo, serial, responseType, e);
         Return<void> retStatus
diff --git a/host/commands/assemble_cvd/flags.cc b/host/commands/assemble_cvd/flags.cc
index da1082d..21781bf 100644
--- a/host/commands/assemble_cvd/flags.cc
+++ b/host/commands/assemble_cvd/flags.cc
@@ -171,8 +171,6 @@
               "Binary for the configuration server");
 DEFINE_int32(config_server_port, vsoc::GetPerInstanceDefault(4680),
              "The (vsock) port for the configuration server");
-DEFINE_int32(frames_vsock_port, vsoc::GetPerInstanceDefault(5580),
-             "The vsock port to receive frames from the guest on");
 DEFINE_bool(enable_tombstone_receiver, true, "Enables the tombstone logger on "
             "both the guest and the host");
 DEFINE_string(tombstone_receiver_binary,
@@ -180,10 +178,6 @@
               "Binary for the tombstone server");
 DEFINE_int32(tombstone_receiver_port, vsoc::GetPerInstanceDefault(5630),
              "The vsock port for tombstones");
-DEFINE_int32(keyboard_server_port, GetPerInstanceDefault(5540),
-             "The port on which the vsock keyboard server should listen");
-DEFINE_int32(touch_server_port, GetPerInstanceDefault(5640),
-             "The port on which the vsock touch server should listen");
 DEFINE_bool(use_bootloader, false, "Boots the device using a bootloader");
 DEFINE_string(bootloader, "", "Bootloader binary path");
 DEFINE_string(boot_slot, "", "Force booting into the given slot. If empty, "
@@ -400,15 +394,11 @@
   tmp_config_obj.set_logcat_mode(FLAGS_logcat_mode);
   tmp_config_obj.set_logcat_vsock_port(FLAGS_logcat_vsock_port);
   tmp_config_obj.set_config_server_port(FLAGS_config_server_port);
-  tmp_config_obj.set_frames_vsock_port(FLAGS_frames_vsock_port);
 
   tmp_config_obj.set_enable_tombstone_receiver(FLAGS_enable_tombstone_receiver);
   tmp_config_obj.set_tombstone_receiver_port(FLAGS_tombstone_receiver_port);
   tmp_config_obj.set_tombstone_receiver_binary(FLAGS_tombstone_receiver_binary);
 
-  tmp_config_obj.set_touch_socket_port(FLAGS_touch_server_port);
-  tmp_config_obj.set_keyboard_socket_port(FLAGS_keyboard_server_port);
-
   tmp_config_obj.set_use_bootloader(FLAGS_use_bootloader);
   tmp_config_obj.set_bootloader(FLAGS_bootloader);
 
diff --git a/host/commands/fetcher/fetch_cvd.cc b/host/commands/fetcher/fetch_cvd.cc
index 5e314c8..abaede1 100644
--- a/host/commands/fetcher/fetch_cvd.cc
+++ b/host/commands/fetcher/fetch_cvd.cc
@@ -23,6 +23,7 @@
 #include "gflags/gflags.h"
 #include <glog/logging.h>
 
+#include "common/libs/fs/shared_fd.h"
 #include "common/libs/utils/archive.h"
 #include "common/libs/utils/files.h"
 #include "common/libs/utils/subprocess.h"
@@ -390,15 +391,9 @@
     return 0;
   }
 
-  if (chdir(target_dir.c_str()) != 0) {
-    int error_num = errno;
-    LOG(FATAL) << "Could not change directory to \"" << target_dir << "\"."
-        << "errno was " << error_num << " \"" << strerror(error_num) << "\"";
-  }
-
   // Ignore return code. We want to make sure there is no running instance,
   // and stop_cvd will exit with an error code if there is already no running instance.
-  cvd::Command stop_cmd("bin/stop_cvd");
+  cvd::Command stop_cmd(target_dir + "/bin/stop_cvd");
   stop_cmd.RedirectStdIO(cvd::Subprocess::StdIOChannel::kStdOut,
                          cvd::Subprocess::StdIOChannel::kStdErr);
   stop_cmd.Start().Wait();
@@ -406,9 +401,35 @@
   // gflags::ParseCommandLineFlags will remove fetch_cvd's flags from this.
   // This depends the remove_flags argument (3rd) is "true".
 
+  auto filelist_fd = cvd::SharedFD::MemfdCreate("files_list");
+  if (!filelist_fd->IsOpen()) {
+    LOG(FATAL) << "Unable to create temp file to write file list. "
+               << filelist_fd->StrError() << " (" << filelist_fd->GetErrno() << ")";
+  }
+
+  for (const auto& file : config.get_cvd_files()) {
+    std::string file_entry = file.second.file_path + "\n";
+    auto chars_written = filelist_fd->Write(file_entry.c_str(), file_entry.size());
+    if (chars_written != file_entry.size()) {
+      LOG(FATAL) << "Unable to write entry to file list. Expected to write "
+                 << file_entry.size() << " but wrote " << chars_written << ". "
+                 << filelist_fd->StrError() << " (" << filelist_fd->GetErrno() << ")";
+    }
+  }
+  auto seek_result = filelist_fd->LSeek(0, SEEK_SET);
+  if (seek_result != 0) {
+    LOG(FATAL) << "Unable to seek on file list file. Expected 0, received " << seek_result
+               << filelist_fd->StrError() << " (" << filelist_fd->GetErrno() << ")";
+  }
+
+  if (filelist_fd->UNMANAGED_Dup2(0) == -1) {
+    LOG(FATAL) << "Unable to set file list to stdin. "
+               << filelist_fd->StrError() << " (" << filelist_fd->GetErrno() << ")";
+  }
+
   // TODO(b/139199114): Go into assemble_cvd when the interface is stable and implemented.
 
-  std::string next_stage = "bin/launch_cvd";
+  std::string next_stage = target_dir + "/bin/launch_cvd";
   std::vector<const char*> next_stage_argv = {"launch_cvd"};
   LOG(INFO) << "Running " << next_stage;
   for (int i = 1; i < argc; i++) {
diff --git a/host/commands/run_cvd/launch.cc b/host/commands/run_cvd/launch.cc
index e4eb858..0d8aace 100644
--- a/host/commands/run_cvd/launch.cc
+++ b/host/commands/run_cvd/launch.cc
@@ -210,60 +210,63 @@
   return server;
 }
 
-cvd::SharedFD CreateVsockVncInputServer(int port) {
-  auto server = cvd::SharedFD::VsockServer(port, SOCK_STREAM);
-  if (!server->IsOpen()) {
-    LOG(ERROR) << "Unable to create vsock input server: "
-               << server->StrError();
-    return cvd::SharedFD();
+VncServerPorts LaunchVNCServerIfEnabled(
+    const vsoc::CuttlefishConfig& config,
+    cvd::ProcessMonitor* process_monitor,
+    std::function<bool(MonitorEntry*)> callback) {
+  VncServerPorts server_ret;
+  if (!config.enable_vnc_server()) {
+    return {};
   }
-  return server;
-}
-
-bool LaunchVNCServerIfEnabled(const vsoc::CuttlefishConfig& config,
-                              cvd::ProcessMonitor* process_monitor,
-                              std::function<bool(MonitorEntry*)> callback) {
-  if (config.enable_vnc_server()) {
-    // Launch the vnc server, don't wait for it to complete
-    auto port_options = "-port=" + std::to_string(config.vnc_server_port());
-    cvd::Command vnc_server(config.vnc_server_binary());
-    vnc_server.AddParameter(port_options);
-    if (config.vm_manager() == vm_manager::QemuManager::name()) {
-      vnc_server.AddParameter("-write_virtio_input");
-    }
-    // When the ivserver is not enabled, the vnc touch_server needs to serve
-    // on sockets and send input events to whoever connects to it (the VMM).
-    auto touch_server =
-        config.vm_manager() == vm_manager::CrosvmManager::name()
-            ? CreateUnixVncInputServer(config.touch_socket_path())
-            : CreateVsockVncInputServer(config.touch_socket_port());
-    if (!touch_server->IsOpen()) {
-      return false;
-    }
-    vnc_server.AddParameter("-touch_fd=", touch_server);
-
-    auto keyboard_server =
-        config.vm_manager() == vm_manager::CrosvmManager::name()
-            ? CreateUnixVncInputServer(config.keyboard_socket_path())
-            : CreateVsockVncInputServer(config.keyboard_socket_port());
-    if (!keyboard_server->IsOpen()) {
-      return false;
-    }
-    vnc_server.AddParameter("-keyboard_fd=", keyboard_server);
-    // TODO(b/128852363): This should be handled through the wayland mock
-    //  instead.
-    // Additionally it receives the frame updates from a virtual socket
-    // instead
-    auto frames_server =
-        cvd::SharedFD::VsockServer(config.frames_vsock_port(), SOCK_STREAM);
-    if (!frames_server->IsOpen()) {
-      return false;
-    }
-    vnc_server.AddParameter("-frame_server_fd=", frames_server);
-    process_monitor->StartSubprocess(std::move(vnc_server), callback);
-    return true;
+  std::set<std::string> extra_kernel_args;
+  // Launch the vnc server, don't wait for it to complete
+  auto port_options = "-port=" + std::to_string(config.vnc_server_port());
+  cvd::Command vnc_server(config.vnc_server_binary());
+  vnc_server.AddParameter(port_options);
+  if (config.vm_manager() == vm_manager::QemuManager::name()) {
+    vnc_server.AddParameter("-write_virtio_input");
   }
-  return false;
+  // When the ivserver is not enabled, the vnc touch_server needs to serve
+  // on sockets and send input events to whoever connects to it (the VMM).
+  cvd::SharedFD touch_server;
+  if (config.vm_manager() == vm_manager::CrosvmManager::name()) {
+    touch_server = CreateUnixVncInputServer(config.touch_socket_path());
+  } else {
+    touch_server = cvd::SharedFD::VsockServer(SOCK_STREAM);
+    server_ret.touch_server_vsock_port = touch_server->VsockServerPort();
+  }
+  if (!touch_server->IsOpen()) {
+    LOG(ERROR) << "Could not open touch server: " << touch_server->StrError();
+    return {};
+  }
+  vnc_server.AddParameter("-touch_fd=", touch_server);
+
+  cvd::SharedFD keyboard_server;
+  if (config.vm_manager() == vm_manager::CrosvmManager::name()) {
+    keyboard_server = CreateUnixVncInputServer(config.keyboard_socket_path());
+  } else {
+    keyboard_server = cvd::SharedFD::VsockServer(SOCK_STREAM);
+    server_ret.keyboard_server_vsock_port = keyboard_server->VsockServerPort();
+  }
+  if (!keyboard_server->IsOpen()) {
+    LOG(ERROR) << "Could not open keyboard server: " << keyboard_server->StrError();
+    return {};
+  }
+  vnc_server.AddParameter("-keyboard_fd=", keyboard_server);
+  // TODO(b/128852363): This should be handled through the wayland mock
+  //  instead.
+  // Additionally it receives the frame updates from a virtual socket
+  // instead
+  auto frames_server = cvd::SharedFD::VsockServer(SOCK_STREAM);
+  server_ret.frames_server_vsock_port = frames_server->VsockServerPort();
+  if (!frames_server->IsOpen()) {
+    LOG(ERROR) << "Could not open frames server: " << frames_server->StrError();
+    return {};
+  }
+  vnc_server.AddParameter("-frame_server_fd=", frames_server);
+  process_monitor->StartSubprocess(std::move(vnc_server), callback);
+
+  return server_ret;
 }
 
 void LaunchAdbConnectorIfEnabled(cvd::ProcessMonitor* process_monitor,
diff --git a/host/commands/run_cvd/launch.h b/host/commands/run_cvd/launch.h
index 4db6e12..42eed0d 100644
--- a/host/commands/run_cvd/launch.h
+++ b/host/commands/run_cvd/launch.h
@@ -1,7 +1,10 @@
 #pragma once
 
 #include <functional>
+#include <set>
+#include <string>
 
+#include "common/libs/fs/shared_fd.h"
 #include "common/libs/utils/subprocess.h"
 #include "host/commands/run_cvd/process_monitor.h"
 #include "host/libs/config/cuttlefish_config.h"
@@ -16,9 +19,6 @@
                         cvd::ProcessMonitor* process_monitor);
 void LaunchUsbServerIfEnabled(const vsoc::CuttlefishConfig& config,
                               cvd::ProcessMonitor* process_monitor);
-bool LaunchVNCServerIfEnabled(const vsoc::CuttlefishConfig& config,
-                              cvd::ProcessMonitor* process_monitor,
-                              std::function<bool(cvd::MonitorEntry*)> callback);
 void LaunchAdbConnectorIfEnabled(cvd::ProcessMonitor* process_monitor,
                                  const vsoc::CuttlefishConfig& config,
                                  cvd::SharedFD adbd_events_pipe);
@@ -26,3 +26,13 @@
                                  const vsoc::CuttlefishConfig& config);
 void LaunchTombstoneReceiverIfEnabled(const vsoc::CuttlefishConfig& config,
                                       cvd::ProcessMonitor* process_monitor);
+
+struct VncServerPorts {
+  std::optional<int> frames_server_vsock_port;
+  std::optional<int> touch_server_vsock_port;
+  std::optional<int> keyboard_server_vsock_port;
+};
+VncServerPorts LaunchVNCServerIfEnabled(
+    const vsoc::CuttlefishConfig& config,
+    cvd::ProcessMonitor* process_monitor,
+    std::function<bool(cvd::MonitorEntry*)> callback);
diff --git a/host/commands/run_cvd/main.cc b/host/commands/run_cvd/main.cc
index 486a0db..470c0d5 100644
--- a/host/commands/run_cvd/main.cc
+++ b/host/commands/run_cvd/main.cc
@@ -302,9 +302,6 @@
   if (config.logcat_mode() == cvd::kLogcatVsockMode) {
     kernel_cmdline.push_back(concat("androidboot.vsock_logcat_port=", config.logcat_vsock_port()));
   }
-  if (config.enable_vnc_server()) {
-    kernel_cmdline.push_back(concat("androidboot.vsock_frames_port=", config.frames_vsock_port()));
-  }
   if (config.enable_tombstone_receiver()) {
     kernel_cmdline.push_back("androidboot.tombstone_transmit=1");
     kernel_cmdline.push_back(concat(
@@ -328,11 +325,6 @@
     }
     kernel_cmdline.push_back(concat("androidboot.slot_suffix=", slot_suffix));
   }
-  if (config.vm_manager() == vm_manager::QemuManager::name()) {
-    kernel_cmdline.push_back(concat("androidboot.vsock_touch_port=", config.touch_socket_port()));
-    kernel_cmdline.push_back(concat(
-        "androidboot.vsock_keyboard_port=", config.keyboard_socket_port()));
-  }
   kernel_cmdline.push_back(concat("loop.max_part=", config.loop_max_part()));
   if (config.guest_enforce_security()) {
     kernel_cmdline.push_back("enforcing=1");
@@ -350,6 +342,22 @@
 
   return kernel_cmdline;
 }
+std::vector<std::string> KernelCommandLineFromVnc(const VncServerPorts& vnc_ports) {
+  std::vector<std::string> kernel_args;
+  if (vnc_ports.frames_server_vsock_port) {
+    kernel_args.push_back(concat("androidboot.vsock_frames_port=",
+                                 *vnc_ports.frames_server_vsock_port));
+  }
+  if (vnc_ports.touch_server_vsock_port) {
+    kernel_args.push_back(concat("androidboot.vsock_touch_port=",
+                                 *vnc_ports.touch_server_vsock_port));
+  }
+  if (vnc_ports.keyboard_server_vsock_port) {
+    kernel_args.push_back(concat("androidboot.vsock_keyboard_port=",
+                                 *vnc_ports.keyboard_server_vsock_port));
+  }
+  return kernel_args;
+}
 
 }  // namespace
 
@@ -472,6 +480,8 @@
   cvd::SharedFD adbd_events_pipe = event_pipes[1];
   event_pipes.clear();
 
+  std::set<std::string> extra_kernel_cmdline;
+
   SetUpHandlingOfBootEvents(&process_monitor, boot_events_pipe,
                             boot_state_machine);
 
@@ -486,12 +496,15 @@
   // The vnc server needs to be launched after the ivserver because it connects
   // to it when using qemu. It needs to launch before the VMM because it serves
   // on several sockets (input devices, vsock frame server) when using crosvm.
-  auto frontend_enabled = LaunchVNCServerIfEnabled(
+  auto vnc_server_config = LaunchVNCServerIfEnabled(
       *config, &process_monitor, GetOnSubprocessExitCallback(*config));
+  auto vnc_kernel_args = KernelCommandLineFromVnc(vnc_server_config);
+
+  auto kernel_args = KernelCommandLineFromConfig(*config);
+  kernel_args.insert(kernel_args.end(), vnc_kernel_args.begin(), vnc_kernel_args.end());
 
   // Start the guest VM
-  vm_manager->WithFrontend(frontend_enabled);
-  auto kernel_args = KernelCommandLineFromConfig(*config);
+  vm_manager->WithFrontend(vnc_kernel_args.size() > 0);
   vm_manager->WithKernelCommandLine(android::base::Join(kernel_args, " "));
   auto vmm_commands = vm_manager->StartCommands();
   for (auto& vmm_cmd: vmm_commands) {
diff --git a/host/libs/config/cuttlefish_config.cpp b/host/libs/config/cuttlefish_config.cpp
index 3b223d9..4b2451c 100644
--- a/host/libs/config/cuttlefish_config.cpp
+++ b/host/libs/config/cuttlefish_config.cpp
@@ -143,7 +143,6 @@
 const char* kLogcatMode = "logcat_mode";
 const char* kLogcatVsockPort = "logcat_vsock_port";
 const char* kConfigServerPort = "config_server_port";
-const char* kFramesVsockPort = "frames_vsock_port";
 const char* kLogcatReceiverBinary = "logcat_receiver_binary";
 const char* kConfigServerBinary = "config_server_binary";
 
@@ -156,9 +155,6 @@
 
 const char* kBootSlot = "boot_slot";
 
-const char* kTouchSocketPort = "touch_socket_port";
-const char* kKeyboardSocketPort = "keyboard_socket_port";
-
 const char* kLoopMaxPart = "loop_max_part";
 const char* kGuestEnforceSecurity = "guest_enforce_security";
 const char* kGuestAuditSecurity = "guest_audit_security";
@@ -718,14 +714,6 @@
   return (*dictionary_)[kConfigServerPort].asInt();
 }
 
-void CuttlefishConfig::set_frames_vsock_port(int port) {
-  (*dictionary_)[kFramesVsockPort] = port;
-}
-
-int CuttlefishConfig::frames_vsock_port() const {
-  return (*dictionary_)[kFramesVsockPort].asInt();
-}
-
 void CuttlefishConfig::set_logcat_receiver_binary(const std::string& binary) {
   SetPath(kLogcatReceiverBinary, binary);
 }
@@ -798,22 +786,6 @@
   return PerInstanceInternalPath("keyboard.sock");
 }
 
-void CuttlefishConfig::set_touch_socket_port(int port) {
-  (*dictionary_)[kTouchSocketPort] = port;
-}
-
-int CuttlefishConfig::touch_socket_port() const {
-  return (*dictionary_)[kTouchSocketPort].asInt();
-}
-
-void CuttlefishConfig::set_keyboard_socket_port(int port) {
-  (*dictionary_)[kKeyboardSocketPort] = port;
-}
-
-int CuttlefishConfig::keyboard_socket_port() const {
-  return (*dictionary_)[kKeyboardSocketPort].asInt();
-}
-
 void CuttlefishConfig::set_loop_max_part(int loop_max_part) {
   (*dictionary_)[kLoopMaxPart] = loop_max_part;
 }
diff --git a/host/libs/config/cuttlefish_config.h b/host/libs/config/cuttlefish_config.h
index bf3d231..d6a162a 100644
--- a/host/libs/config/cuttlefish_config.h
+++ b/host/libs/config/cuttlefish_config.h
@@ -288,9 +288,6 @@
   void set_config_server_port(int port);
   int config_server_port() const;
 
-  void set_frames_vsock_port(int port);
-  int frames_vsock_port() const;
-
   void set_enable_tombstone_receiver(bool enable_tombstone_receiver);
   bool enable_tombstone_receiver() const;
 
@@ -312,12 +309,6 @@
   std::string touch_socket_path() const;
   std::string keyboard_socket_path() const;
 
-  void set_touch_socket_port(int touch_socket_port);
-  int touch_socket_port() const;
-
-  void set_keyboard_socket_port(int keyboard_socket_port);
-  int keyboard_socket_port() const;
-
   void set_loop_max_part(int loop_max_part);
   int loop_max_part() const;
 
diff --git a/host/libs/vm_manager/vm_manager.cpp b/host/libs/vm_manager/vm_manager.cpp
index 2ab4157..40fa828 100644
--- a/host/libs/vm_manager/vm_manager.cpp
+++ b/host/libs/vm_manager/vm_manager.cpp
@@ -44,32 +44,20 @@
         {
           QemuManager::name(),
           {
-            [](const vsoc::CuttlefishConfig* config) {
-              return GetManagerSingleton<QemuManager>(config);
-            },
-            []() { return vsoc::HostSupportsQemuCli(); },
-            [](const std::string& gpu_mode) {
-              return QemuManager::ConfigureGpu(gpu_mode);
-            },
-            []() {
-              return QemuManager::ConfigureBootDevices();
-            }
+            GetManagerSingleton<QemuManager>,
+            vsoc::HostSupportsQemuCli,
+            QemuManager::ConfigureGpu,
+            QemuManager::ConfigureBootDevices,
           },
         },
         {
           CrosvmManager::name(),
           {
-            [](const vsoc::CuttlefishConfig* config) {
-              return GetManagerSingleton<CrosvmManager>(config);
-            },
+            GetManagerSingleton<CrosvmManager>,
             // Same as Qemu for the time being
-            []() { return vsoc::HostSupportsQemuCli(); },
-            [](const std::string& gpu_mode) {
-              return CrosvmManager::ConfigureGpu(gpu_mode);
-            },
-            []() {
-              return CrosvmManager::ConfigureBootDevices();
-            }
+            vsoc::HostSupportsQemuCli,
+            CrosvmManager::ConfigureGpu,
+            CrosvmManager::ConfigureBootDevices,
           }
         }
     };
diff --git a/shared/device.mk b/shared/device.mk
index 8c6748a..1e52385 100644
--- a/shared/device.mk
+++ b/shared/device.mk
@@ -35,7 +35,7 @@
 # Properties that are not vendor-specific. These will go in the product
 # partition, instead of the vendor partition, and do not need vendor
 # sepolicy
-PRODUCT_PRODUCT_PROPERTIES := \
+PRODUCT_PRODUCT_PROPERTIES += \
     persist.adb.tcp.port=5555 \
     persist.traced.enable=1 \
     ro.com.google.locationfeatures=1 \
diff --git a/shared/sepolicy/vendor/priv_app.te b/shared/sepolicy/vendor/priv_app.te
index 7de36ab..05c9e47 100644
--- a/shared/sepolicy/vendor/priv_app.te
+++ b/shared/sepolicy/vendor/priv_app.te
@@ -1,6 +1 @@
 gpu_access(priv_app)
-get_prop(priv_app, hal_camera_prop)
-# b/142672293: No other priv-app should need this allow rule now and GMS core runs in its own domain.
-userdebug_or_eng(`
-  auditallow priv_app hal_camera_prop:file { getattr open read map };
-')