Moves adb connection maintainer to its own process

Bug: 110903706
Test: local build and boot. Test with and without flag in crun
Change-Id: I75381614d4543c75bd6d8779b4bd5ebef1989425
diff --git a/common/frontend/socket_forward_proxy/Android.bp b/common/frontend/socket_forward_proxy/Android.bp
index 3a1a11d..81ba9c4 100644
--- a/common/frontend/socket_forward_proxy/Android.bp
+++ b/common/frontend/socket_forward_proxy/Android.bp
@@ -38,7 +38,6 @@
             static_libs: [
                 "libcuttlefish_host_config",
                 "libjsoncpp",
-                "libadb_connection_maintainer",
             ],
         },
     },
diff --git a/common/frontend/socket_forward_proxy/main.cpp b/common/frontend/socket_forward_proxy/main.cpp
index b2c16f6..944165a 100644
--- a/common/frontend/socket_forward_proxy/main.cpp
+++ b/common/frontend/socket_forward_proxy/main.cpp
@@ -36,7 +36,6 @@
 
 #ifdef CUTTLEFISH_HOST
 #include "host/libs/config/cuttlefish_config.h"
-#include "host/libs/adb_connection_maintainer/adb_connection_maintainer.h"
 #endif
 
 using vsoc::socket_forward::Packet;
@@ -178,10 +177,6 @@
 using SocketConnectionInfoCollection =
     std::array<SocketConnectionInfo, kNumHostThreads>;
 
-void LaunchConnectionMaintainer(int port) {
-  std::thread(cvd::EstablishAndMaintainConnection, port).detach();
-}
-
 void MarkAsFree(SocketConnectionInfo* conn) {
   std::lock_guard<std::mutex> guard{conn->lock};
   conn->socket = cvd::SharedFD{};
@@ -264,9 +259,6 @@
             << guest_port;
   auto server = cvd::SharedFD::SocketLocalServer(host_port, SOCK_STREAM);
   CHECK(server->IsOpen()) << "Could not start server on port " << host_port;
-  // Note: If generically forwarding ports, the adb connection maintainer should
-  // be disabled
-  LaunchConnectionMaintainer(host_port);
   while (true) {
     auto client_socket = cvd::SharedFD::Accept(*server);
     CHECK(client_socket->IsOpen()) << "error creating client socket";
diff --git a/host/commands/launch/main.cc b/host/commands/launch/main.cc
index b41de1f..58b3309 100644
--- a/host/commands/launch/main.cc
+++ b/host/commands/launch/main.cc
@@ -128,6 +128,13 @@
               "Mode for adb connection. Can be usb for usb forwarding, or "
               "tunnel for tcp connection. If using tunnel, you may have to "
               "run 'adb kill-server' to get the device to show up.");
+DEFINE_bool(run_adb_connector, true,
+            "Maintain adb connection by sending 'adb connect' commands to the "
+            "server. Only relevant with --adb_mode=tunnel");
+DEFINE_string(adb_connector_binary,
+              vsoc::DefaultHostArtifactsPath("bin/adb_connector"),
+              "Location of the adb_connector binary. Only relevant if "
+              "--run_adb_connector is true");
 DEFINE_int32(vhci_port, GetPerInstanceDefault(0), "VHCI port to use for usb");
 DEFINE_string(guest_mac_address,
               GetPerInstanceDefault("00:43:56:44:80:"), // 00:43:56:44:80:0x
@@ -359,6 +366,10 @@
   return std::string{"--host_ports="} + std::to_string(GetHostPort());
 }
 
+std::string GetAdbConnectorPortArg() {
+  return std::string{"--ports="} + std::to_string(GetHostPort());
+}
+
 void ValidateAdbModeFlag() {
   CHECK(FLAGS_adb_mode == kAdbModeUsb ||
         FLAGS_adb_mode == kAdbModeTunnel) << "invalid --adb_mode";
@@ -377,6 +388,10 @@
                                           0666)->UNMANAGED_Dup();
 }
 
+bool AdbConnectorEnabled() {
+  return FLAGS_run_adb_connector;
+}
+
 void LaunchIvServer() {
   auto config = vsoc::CuttlefishConfig::Get();
   // Resize gralloc region
@@ -406,6 +421,13 @@
   close(client_channel);
 }
 
+void LaunchAdbConnectorIfEnabled() {
+  if (AdbConnectorEnabled()) {
+    cvd::subprocess({FLAGS_adb_connector_binary,
+                     GetAdbConnectorPortArg()});
+  }
+}
+
 void LaunchSocketForwardProxyIfEnabled() {
   if (AdbTunnelEnabled()) {
     cvd::subprocess({FLAGS_socket_forward_proxy_binary,
@@ -669,6 +691,7 @@
 
   LaunchSocketForwardProxyIfEnabled();
   LaunchVNCServerIfEnabled();
+  LaunchAdbConnectorIfEnabled();
 
   pause();
 }
diff --git a/host/frontend/Android.bp b/host/frontend/Android.bp
index bf82b3c..8d78a9f 100644
--- a/host/frontend/Android.bp
+++ b/host/frontend/Android.bp
@@ -15,4 +15,5 @@
 
 subdirs = [
     "vnc_server",
+    "adb_connector",
 ]
diff --git a/host/frontend/adb_connector/Android.bp b/host/frontend/adb_connector/Android.bp
new file mode 100644
index 0000000..3af5ef1
--- /dev/null
+++ b/host/frontend/adb_connector/Android.bp
@@ -0,0 +1,35 @@
+//
+// Copyright (C) 2018 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: "adb_connector",
+    srcs: [
+        "main.cpp"
+    ],
+    header_libs: [
+        "cuttlefish_glog",
+    ],
+    static_libs: [
+        "libadb_connection_maintainer",
+        "libgflags",
+    ],
+    shared_libs: [
+        "libbase",
+        "libcuttlefish_fs",
+        "libcuttlefish_strings",
+        "liblog",
+    ],
+    defaults: ["cuttlefish_host_only"],
+}
diff --git a/host/frontend/adb_connector/main.cpp b/host/frontend/adb_connector/main.cpp
new file mode 100644
index 0000000..27574ee
--- /dev/null
+++ b/host/frontend/adb_connector/main.cpp
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2018 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 <algorithm>
+#include <iterator>
+#include <limits>
+#include <sstream>
+#include <thread>
+#include <vector>
+
+#include <glog/logging.h>
+#include <gflags/gflags.h>
+
+#include <unistd.h>
+
+#include "common/libs/strings/str_split.h"
+#include "host/libs/config/cuttlefish_config.h"
+#include "host/libs/adb_connection_maintainer/adb_connection_maintainer.h"
+
+DEFINE_string(ports, "", "Comma-separated list of ports to 'adb connect' to");
+
+namespace {
+void LaunchConnectionMaintainerThread(int port) {
+  std::thread(cvd::EstablishAndMaintainConnection, port).detach();
+}
+
+std::vector<int> ParsePortsList(std::string ports) {
+  std::replace(ports.begin(), ports.end(), ',', ' ');
+  std::istringstream port_stream{ports};
+  return {std::istream_iterator<int>{port_stream},
+          std::istream_iterator<int>{}};
+}
+
+[[noreturn]] void SleepForever() {
+  while (true) {
+    sleep(std::numeric_limits<unsigned int>::max());
+  }
+}
+}  // namespace
+
+int main(int argc, char* argv[]) {
+  gflags::ParseCommandLineFlags(&argc, &argv, true);
+  CHECK(!FLAGS_ports.empty()) << "Must specify --ports flag";
+
+  for (auto port : ParsePortsList(FLAGS_ports)) {
+    LaunchConnectionMaintainerThread(port);
+  }
+
+  SleepForever();
+}