Make adb connector wait for adb daemon to start on the guest

This avoids a race in the kernel where attempts to connect to a
vsocket before the modules are completely loaded cause a null pointer
dereference.

Bug: 131864854
Bug: 131184297
Test: run locally
Change-Id: I042a2cb1f41619a9a6e062daaa843c4c17b07de2
Merged-In: I042a2cb1f41619a9a6e062daaa843c4c17b07de2
diff --git a/host/commands/kernel_log_monitor/kernel_log_server.cc b/host/commands/kernel_log_monitor/kernel_log_server.cc
index 0ecf5fe..84b2694 100644
--- a/host/commands/kernel_log_monitor/kernel_log_server.cc
+++ b/host/commands/kernel_log_monitor/kernel_log_server.cc
@@ -39,6 +39,8 @@
      monitor::BootEvent::MobileNetworkConnected},
     {"VIRTUAL_DEVICE_NETWORK_WIFI_CONNECTED",
      monitor::BootEvent::WifiNetworkConnected},
+    // TODO(b/131864854): Replace this with a string less likely to change
+    {"init: starting service 'adbd'", monitor::BootEvent::AdbdStarted},
 };
 
 void ProcessSubscriptions(
diff --git a/host/commands/kernel_log_monitor/kernel_log_server.h b/host/commands/kernel_log_monitor/kernel_log_server.h
index 0cc8920..f71ebb7 100644
--- a/host/commands/kernel_log_monitor/kernel_log_server.h
+++ b/host/commands/kernel_log_monitor/kernel_log_server.h
@@ -32,6 +32,7 @@
   BootFailed = 2,
   WifiNetworkConnected = 3,
   MobileNetworkConnected = 4,
+  AdbdStarted = 5,
 };
 
 enum class SubscriptionAction {
diff --git a/host/commands/launch/launch.cc b/host/commands/launch/launch.cc
index b4de6ae..bc57025 100644
--- a/host/commands/launch/launch.cc
+++ b/host/commands/launch/launch.cc
@@ -135,20 +135,27 @@
 // subscription to boot events from the kernel log monitor will be created and
 // events will appear on *boot_events_pipe
 cvd::Command GetKernelLogMonitorCommand(const vsoc::CuttlefishConfig& config,
-                                        cvd::SharedFD* boot_events_pipe) {
+                                        cvd::SharedFD* boot_events_pipe,
+                                        cvd::SharedFD* adbd_events_pipe) {
   auto log_name = config.kernel_log_socket_name();
   auto server = cvd::SharedFD::SocketLocalServer(log_name.c_str(), false,
                                                  SOCK_STREAM, 0666);
   cvd::Command kernel_log_monitor(config.kernel_log_monitor_binary());
   kernel_log_monitor.AddParameter("-log_server_fd=", server);
-  if (boot_events_pipe) {
-    cvd::SharedFD pipe_write_end;
-    if (!cvd::SharedFD::Pipe(boot_events_pipe, &pipe_write_end)) {
-      LOG(ERROR) << "Unable to create boot events pipe: " << strerror(errno);
-      std::exit(LauncherExitCodes::kPipeIOError);
-    }
-    kernel_log_monitor.AddParameter("-subscriber_fds=", pipe_write_end);
+
+  cvd::SharedFD boot_pipe_write_end;
+  if (!cvd::SharedFD::Pipe(boot_events_pipe, &boot_pipe_write_end)) {
+    LOG(ERROR) << "Unable to create boot events pipe: " << strerror(errno);
+    std::exit(LauncherExitCodes::kPipeIOError);
   }
+  cvd::SharedFD adbd_pipe_write_end;
+  if (!cvd::SharedFD::Pipe(adbd_events_pipe, &adbd_pipe_write_end)) {
+    LOG(ERROR) << "Unable to create adbd events pipe: " << strerror(errno);
+    std::exit(LauncherExitCodes::kPipeIOError);
+  }
+  kernel_log_monitor.AddParameter("-subscriber_fds=", boot_pipe_write_end, ",",
+                                  adbd_pipe_write_end);
+
   return kernel_log_monitor;
 }
 
@@ -250,16 +257,22 @@
 }
 
 void LaunchAdbConnectorIfEnabled(cvd::ProcessMonitor* process_monitor,
-                                 const vsoc::CuttlefishConfig& config) {
+                                 const vsoc::CuttlefishConfig& config,
+                                 cvd::SharedFD adbd_events_pipe) {
+  bool launch = false;
+  cvd::Command adb_connector(config.adb_connector_binary());
+  adb_connector.AddParameter("-adbd_events_fd=", adbd_events_pipe);
+
   if (AdbTcpConnectorEnabled(config)) {
-    cvd::Command adb_connector(config.adb_connector_binary());
+    launch = true;
     adb_connector.AddParameter(GetAdbConnectorTcpArg());
-    process_monitor->StartSubprocess(std::move(adb_connector),
-                                     GetOnSubprocessExitCallback(config));
   }
   if (AdbVsockConnectorEnabled(config)) {
-    cvd::Command adb_connector(config.adb_connector_binary());
+    launch = true;
     adb_connector.AddParameter(GetAdbConnectorVsockArg(config));
+  }
+
+  if (launch) {
     process_monitor->StartSubprocess(std::move(adb_connector),
                                      GetOnSubprocessExitCallback(config));
   }
diff --git a/host/commands/launch/launch.h b/host/commands/launch/launch.h
index 550ce02..ae79de2 100644
--- a/host/commands/launch/launch.h
+++ b/host/commands/launch/launch.h
@@ -12,7 +12,8 @@
 
 cvd::Command GetIvServerCommand(const vsoc::CuttlefishConfig& config);
 cvd::Command GetKernelLogMonitorCommand(const vsoc::CuttlefishConfig& config,
-                                        cvd::SharedFD* boot_events_pipe);
+                                        cvd::SharedFD* boot_events_pipe,
+                                        cvd::SharedFD* adbd_events_pipe);
 void LaunchLogcatReceiverIfEnabled(const vsoc::CuttlefishConfig& config,
                                    cvd::ProcessMonitor* process_monitor);
 void LaunchUsbServerIfEnabled(const vsoc::CuttlefishConfig& config,
@@ -24,7 +25,8 @@
                                 cvd::ProcessMonitor* process_monitor,
                                 std::function<bool(cvd::MonitorEntry*)> callback);
 void LaunchAdbConnectorIfEnabled(cvd::ProcessMonitor* process_monitor,
-                                 const vsoc::CuttlefishConfig& config);
+                                 const vsoc::CuttlefishConfig& config,
+                                 cvd::SharedFD adbd_events_pipe);
 void LaunchSocketForwardProxyIfEnabled(cvd::ProcessMonitor* process_monitor,
                                  const vsoc::CuttlefishConfig& config);
 void LaunchSocketVsockProxyIfEnabled(cvd::ProcessMonitor* process_monitor,
diff --git a/host/commands/launch/main.cc b/host/commands/launch/main.cc
index ff2c7dd..9c0e3c3 100644
--- a/host/commands/launch/main.cc
+++ b/host/commands/launch/main.cc
@@ -413,12 +413,10 @@
   cvd::ProcessMonitor process_monitor;
 
   cvd::SharedFD boot_events_pipe;
+  cvd::SharedFD adbd_events_pipe;
   // Only subscribe to boot events if running as daemon
   process_monitor.StartSubprocess(
-      GetKernelLogMonitorCommand(*config,
-                                 config->run_as_daemon()
-                                   ? &boot_events_pipe
-                                   : nullptr),
+      GetKernelLogMonitorCommand(*config, &boot_events_pipe, &adbd_events_pipe),
       GetOnSubprocessExitCallback(*config));
 
   SetUpHandlingOfBootEvents(&process_monitor, boot_events_pipe,
@@ -443,7 +441,7 @@
                            GetOnSubprocessExitCallback(*config));
   LaunchStreamAudioIfEnabled(*config, &process_monitor,
                              GetOnSubprocessExitCallback(*config));
-  LaunchAdbConnectorIfEnabled(&process_monitor, *config);
+  LaunchAdbConnectorIfEnabled(&process_monitor, *config, adbd_events_pipe);
 
   ServerLoop(launcher_monitor_socket, vm_manager); // Should not return
   LOG(ERROR) << "The server loop returned, it should never happen!!";
diff --git a/host/frontend/adb_connector/main.cpp b/host/frontend/adb_connector/main.cpp
index e046b3d..93a929d 100644
--- a/host/frontend/adb_connector/main.cpp
+++ b/host/frontend/adb_connector/main.cpp
@@ -25,12 +25,18 @@
 #include <gflags/gflags.h>
 
 #include <unistd.h>
+#include <host/commands/kernel_log_monitor/kernel_log_server.h>
 
+#include "common/libs/fs/shared_fd.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(addresses, "", "Comma-separated list of addresses to 'adb connect' to");
+DEFINE_string(addresses, "", "Comma-separated list of addresses to "
+                             "'adb connect' to");
+DEFINE_int32(adbd_events_fd, -1, "A file descriptor. If set it will wait for "
+                                 "AdbdStarted boot event from the kernel log "
+                                 "monitor before trying to connect adb");
 
 namespace {
 void LaunchConnectionMaintainerThread(const std::string& address) {
@@ -49,12 +55,36 @@
     sleep(std::numeric_limits<unsigned int>::max());
   }
 }
+
+void WaitForAdbdToBeStarted(int events_fd) {
+  auto evt_shared_fd = cvd::SharedFD::Dup(events_fd);
+  close(events_fd);
+  while (evt_shared_fd->IsOpen()) {
+    monitor::BootEvent event;
+    auto bytes_read = evt_shared_fd->Read(&event, sizeof(event));
+    if (bytes_read != sizeof(event)) {
+      LOG(ERROR) << "Fail to read a complete event, read " << bytes_read
+                 << " bytes only instead of the expected " << sizeof(event);
+      // The file descriptor can't be trusted anymore, stop waiting and try to
+      // connect
+      return;
+    }
+    if (event == monitor::BootEvent::AdbdStarted) {
+      LOG(INFO) << "Adbd has started in the guest, connecting adb";
+      return;
+    }
+  }
+}
 }  // namespace
 
 int main(int argc, char* argv[]) {
   gflags::ParseCommandLineFlags(&argc, &argv, true);
   CHECK(!FLAGS_addresses.empty()) << "Must specify --addresses flag";
 
+  if (FLAGS_adbd_events_fd >= 0) {
+    WaitForAdbdToBeStarted(FLAGS_adbd_events_fd);
+  }
+
   for (auto address : ParseAddressList(FLAGS_addresses)) {
     LaunchConnectionMaintainerThread(address);
   }