VirtualUsmManager runs in its own process

Bug: 110532566
Test: local & gce
Change-Id: Ia0f6d15389574f4d226b380390428ede5c52e368
diff --git a/host/commands/Android.bp b/host/commands/Android.bp
index 15f7b2f..8c4b898 100644
--- a/host/commands/Android.bp
+++ b/host/commands/Android.bp
@@ -19,4 +19,5 @@
     "stop_cvd",
     "ivserver",
     "record_audio",
+    "virtual_usb_manager",
 ]
diff --git a/host/commands/launch/Android.bp b/host/commands/launch/Android.bp
index 9d8a8e4..af99652 100644
--- a/host/commands/launch/Android.bp
+++ b/host/commands/launch/Android.bp
@@ -40,8 +40,6 @@
         "libcuttlefish_host_config",
         "libcuttlefish_vm_manager",
         "libivserver",
-        "libvadb",
-        "libusbip",
         "libgflags",
         "libxml2",
         "libjsoncpp",
diff --git a/host/commands/launch/launcher_defs.h b/host/commands/launch/launcher_defs.h
index a6d3372..2732fdf 100644
--- a/host/commands/launch/launcher_defs.h
+++ b/host/commands/launch/launcher_defs.h
@@ -33,6 +33,7 @@
   kProcessGroupError = 12,
   kMonitorCreationFailed = 13,
   kServerError = 14,
+  kUsbV1SocketError = 15,
 };
 
 // Actions supported by the launcher server
diff --git a/host/commands/launch/main.cc b/host/commands/launch/main.cc
index e3a4caf..f3bc1e0 100644
--- a/host/commands/launch/main.cc
+++ b/host/commands/launch/main.cc
@@ -32,6 +32,7 @@
 #include <memory>
 #include <sstream>
 #include <string>
+#include <thread>
 #include <vector>
 
 #include <gflags/gflags.h>
@@ -52,8 +53,6 @@
 #include "host/commands/launch/vsoc_shared_memory.h"
 #include "host/libs/config/cuttlefish_config.h"
 #include "host/libs/monitor/kernel_log_server.h"
-#include "host/libs/usbip/server.h"
-#include "host/libs/vadb/virtual_adb_server.h"
 #include "host/libs/vm_manager/vm_manager.h"
 #include "host/libs/vm_manager/libvirt_manager.h"
 #include "host/libs/vm_manager/qemu_manager.h"
@@ -122,6 +121,9 @@
 DEFINE_string(vnc_server_binary,
               vsoc::DefaultHostArtifactsPath("bin/vnc_server"),
               "Location of the vnc server binary.");
+DEFINE_string(virtual_usb_manager_binary,
+              vsoc::DefaultHostArtifactsPath("bin/virtual_usb_manager"),
+              "Location of the virtual usb manager binary.");
 DEFINE_string(ivserver_binary,
               vsoc::DefaultHostArtifactsPath("bin/ivserver"),
               "Location of the ivshmem server binary.");
@@ -171,47 +173,6 @@
 constexpr char kAdbModeTunnel[] = "tunnel";
 constexpr char kAdbModeUsb[] = "usb";
 
-// VirtualUSBManager manages virtual USB device presence for Cuttlefish.
-class VirtualUSBManager {
- public:
-  VirtualUSBManager(const std::string& usbsocket, int vhci_port,
-                    const std::string& android_usbipsocket)
-      : adb_{usbsocket, vhci_port, android_usbipsocket},
-        usbip_{android_usbipsocket, adb_.Pool()} {}
-
-  ~VirtualUSBManager() = default;
-
-  // Initialize Virtual USB and start USB management thread.
-  void Start() {
-    CHECK(adb_.Init()) << "Could not initialize Virtual ADB server";
-    CHECK(usbip_.Init()) << "Could not start USB/IP server";
-    std::thread([this] { Thread(); }).detach();
-  }
-
- private:
-  void Thread() {
-    for (;;) {
-      cvd::SharedFDSet fd_read;
-      fd_read.Zero();
-
-      adb_.BeforeSelect(&fd_read);
-      usbip_.BeforeSelect(&fd_read);
-
-      int ret = cvd::Select(&fd_read, nullptr, nullptr, nullptr);
-      if (ret <= 0) continue;
-
-      adb_.AfterSelect(fd_read);
-      usbip_.AfterSelect(fd_read);
-    }
-  }
-
-  vadb::VirtualADBServer adb_;
-  vadb::usbip::Server usbip_;
-
-  VirtualUSBManager(const VirtualUSBManager&) = delete;
-  VirtualUSBManager& operator=(const VirtualUSBManager&) = delete;
-};
-
 // KernelLogMonitor receives and monitors kernel log for Cuttlefish.
 class KernelLogMonitor {
  public:
@@ -367,6 +328,32 @@
   return FLAGS_run_adb_connector && AdbTunnelEnabled();
 }
 
+void LaunchUsbServerIfEnabled(vsoc::CuttlefishConfig* config) {
+  if (!AdbUsbEnabled()) {
+    return;
+  }
+  auto socket_name = config->usb_v1_socket_name();
+  auto usb_v1_server = cvd::SharedFD::SocketLocalServer(
+      socket_name.c_str(), false, SOCK_STREAM, 0666);
+  if (!usb_v1_server->IsOpen()) {
+    LOG(ERROR) << "Unable to create USB v1 server socket: "
+               << usb_v1_server->StrError();
+    std::exit(cvd::LauncherExitCodes::kUsbV1SocketError);
+  }
+  int server_fd = usb_v1_server->UNMANAGED_Dup();
+  if (server_fd < 0) {
+    LOG(ERROR) << "Unable to dup USB v1 server socket file descriptor: "
+               << strerror(errno);
+    std::exit(cvd::LauncherExitCodes::kUsbV1SocketError);
+  }
+
+  cvd::subprocess({FLAGS_virtual_usb_manager_binary,
+                   "-usb_v1_fd=" + std::to_string(server_fd),
+                   GetConfigFileArg()});
+
+  close(server_fd);
+}
+
 void LaunchIvServer(vsoc::CuttlefishConfig* config) {
   // Resize gralloc region
   auto actual_width = cvd::AlignToPowerOf2(FLAGS_x_res * 4, 4);  // align to 16
@@ -946,11 +933,7 @@
 
   kmon.Start();
 
-  // Start the usb manager
-  VirtualUSBManager vadb(config->usb_v1_socket_name(), config->vhci_port(),
-                         config->usb_ip_socket_name());
-  vadb.Start();
-
+  LaunchUsbServerIfEnabled(config);
   LaunchIvServer(config);
 
   // Initialize the regions that require so before the VM starts.
diff --git a/host/commands/virtual_usb_manager/Android.bp b/host/commands/virtual_usb_manager/Android.bp
new file mode 100644
index 0000000..19c3dc6
--- /dev/null
+++ b/host/commands/virtual_usb_manager/Android.bp
@@ -0,0 +1,39 @@
+//
+// Copyright (C) 2017 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.
+
+cc_binary_host {
+    name: "virtual_usb_manager",
+    srcs: [
+        "main.cc",
+    ],
+    header_libs: [
+        "cuttlefish_glog",
+    ],
+    shared_libs: [
+        "vsoc_lib",
+        "libcuttlefish_fs",
+        "libcuttlefish_utils",
+        "cuttlefish_auto_resources",
+        "libbase",
+    ],
+    static_libs: [
+        "libcuttlefish_host_config",
+        "libvadb",
+        "libusbip",
+        "libgflags",
+        "libjsoncpp",
+    ],
+    defaults: ["cuttlefish_host_only"],
+}
diff --git a/host/commands/virtual_usb_manager/main.cc b/host/commands/virtual_usb_manager/main.cc
new file mode 100644
index 0000000..0bcb5bb
--- /dev/null
+++ b/host/commands/virtual_usb_manager/main.cc
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#include <string>
+#include <thread>
+
+#include <gflags/gflags.h>
+#include <glog/logging.h>
+
+#include "common/libs/fs/shared_fd.h"
+#include "common/libs/fs/shared_select.h"
+#include "host/libs/config/cuttlefish_config.h"
+#include "host/libs/usbip/server.h"
+#include "host/libs/vadb/virtual_adb_server.h"
+
+DEFINE_int32(
+    usb_v1_fd, -1,
+    "A file descriptor pointing to the USB v1 open socket or -1 to create it");
+
+int main(int argc, char** argv) {
+  ::android::base::InitLogging(argv, android::base::StderrLogger);
+  google::ParseCommandLineFlags(&argc, &argv, true);
+
+  auto config = vsoc::CuttlefishConfig::Get();
+  if (!config) {
+    LOG(ERROR) << "Unable to get config object";
+    return 1;
+  }
+
+  cvd::SharedFD usb_v1_server;
+
+  if (FLAGS_usb_v1_fd < 0) {
+    auto socket_name = config->usb_v1_socket_name();
+    LOG(INFO) << "Starting server at " << socket_name;
+    usb_v1_server = cvd::SharedFD::SocketLocalServer(socket_name.c_str(), false,
+                                                     SOCK_STREAM, 0666);
+  } else {
+    usb_v1_server = cvd::SharedFD::Dup(FLAGS_usb_v1_fd);
+  }
+
+  if (!usb_v1_server->IsOpen()) {
+    LOG(ERROR) << "Error openning USB v1 server: " << usb_v1_server->StrError();
+    return 2;
+  }
+
+  vadb::VirtualADBServer adb_{usb_v1_server, config->vhci_port(),
+                              config->usb_ip_socket_name()};
+  vadb::usbip::Server usbip_{config->usb_ip_socket_name(), adb_.Pool()};
+
+  CHECK(usbip_.Init()) << "Could not start USB/IP server";
+
+  for (;;) {
+    cvd::SharedFDSet fd_read;
+    fd_read.Zero();
+
+    adb_.BeforeSelect(&fd_read);
+    usbip_.BeforeSelect(&fd_read);
+
+    int ret = cvd::Select(&fd_read, nullptr, nullptr, nullptr);
+    if (ret <= 0) continue;
+
+    adb_.AfterSelect(fd_read);
+    usbip_.AfterSelect(fd_read);
+  }
+
+  return 0;
+}
diff --git a/host/libs/vadb/virtual_adb_server.cpp b/host/libs/vadb/virtual_adb_server.cpp
index fae84d2..86838c0 100644
--- a/host/libs/vadb/virtual_adb_server.cpp
+++ b/host/libs/vadb/virtual_adb_server.cpp
@@ -18,22 +18,6 @@
 
 namespace vadb {
 
-bool VirtualADBServer::Init() {
-  if (name_.empty()) {
-    LOG(INFO) << "name_ empty, not starting server socket";
-    return true;
-  }
-  LOG(INFO) << "Starting server socket: " << name_;
-
-  server_ =
-      cvd::SharedFD::SocketLocalServer(name_.c_str(), false, SOCK_STREAM, 0666);
-  if (!server_->IsOpen()) {
-    LOG(ERROR) << "Could not create socket: " << server_->StrError();
-    return false;
-  }
-  return true;
-}
-
 void VirtualADBServer::BeforeSelect(cvd::SharedFDSet* fd_read) const {
   fd_read->Set(server_);
   for (const auto& client : clients_) {
diff --git a/host/libs/vadb/virtual_adb_server.h b/host/libs/vadb/virtual_adb_server.h
index 6e09ef7..231ccde 100644
--- a/host/libs/vadb/virtual_adb_server.h
+++ b/host/libs/vadb/virtual_adb_server.h
@@ -26,18 +26,14 @@
 // VirtualADBServer manages incoming VirtualUSB/ADB connections from QEmu.
 class VirtualADBServer {
  public:
-  VirtualADBServer(const std::string& usb_socket_name, int vhci_port,
+  VirtualADBServer(cvd::SharedFD usb_v1_socket, int vhci_port,
                    const std::string& usbip_socket_name)
-      : name_(usb_socket_name),
-        vhci_port_{vhci_port},
-        usbip_name_(usbip_socket_name) {}
+      : vhci_port_{vhci_port},
+        usbip_name_(usbip_socket_name),
+        server_(usb_v1_socket) {}
 
   ~VirtualADBServer() = default;
 
-  // Initialize this instance of Server.
-  // Returns true, if initialization was successful.
-  bool Init();
-
   // Pool of USB devices available to export.
   const usbip::DevicePool& Pool() const { return pool_; };
 
@@ -53,7 +49,6 @@
   void HandleIncomingConnection();
 
   usbip::DevicePool pool_;
-  std::string name_;
   int vhci_port_{};
   std::string usbip_name_;
   cvd::SharedFD server_;