Move jdwp connection abstraction from ART apex to adbd apex.

Test: ./art/tools/run-jdwp-tests.sh
Change-Id: I3114b8403f3548700a45df5d7bb72ebe727adec1
diff --git a/Android.mk b/Android.mk
index 6e41516..fc44da4 100644
--- a/Android.mk
+++ b/Android.mk
@@ -537,7 +537,6 @@
 
 PRIVATE_ART_APEX_DEPENDENCY_LIBS := \
   lib/libadbconnectiond.so \
-  lib/libadbconnection_server.so \
   lib/libadbconnection.so \
   lib/libandroidicu.so \
   lib/libandroidio.so \
@@ -591,7 +590,6 @@
   lib/libziparchive.so \
   lib/libz.so \
   lib64/libadbconnectiond.so \
-  lib64/libadbconnection_server.so \
   lib64/libadbconnection.so \
   lib64/libandroidicu.so \
   lib64/libandroidio.so \
diff --git a/adbconnection/Android.bp b/adbconnection/Android.bp
index b2503e1..b03cd0d 100644
--- a/adbconnection/Android.bp
+++ b/adbconnection/Android.bp
@@ -28,6 +28,7 @@
 
     shared_libs: [
         "libbase",
+        "libadbconnection_client",
     ],
     target: {
         host: {
@@ -59,32 +60,6 @@
     ],
 }
 
-// We export a library to do the server-side socket handling that gets loaded
-// by adbd from the art apex, so that we can update the socket handling
-// independently from the adbd apex.
-cc_library {
-    name: "libadbconnection_server",
-    srcs: ["adbconnection_server.cc"],
-
-    export_include_dirs: ["include"],
-
-    stl: "libc++_static",
-    shared_libs: ["liblog"],
-    whole_static_libs: ["libbase"],
-
-    defaults: ["art_defaults"],
-    visibility: [
-        "//system/core/adb",
-    ],
-    stubs: {
-        symbol_file: "libadbconnection_server.map.txt",
-        versions: ["1"],
-    },
-
-    host_supported: true,
-    recovery_available: true,
-}
-
 art_cc_library {
     name: "libadbconnectiond",
     defaults: [
diff --git a/adbconnection/adbconnection.cc b/adbconnection/adbconnection.cc
index 0824eb4..2234ce4 100644
--- a/adbconnection/adbconnection.cc
+++ b/adbconnection/adbconnection.cc
@@ -15,16 +15,17 @@
  */
 
 #include <array>
+#include <iterator>
 
 #include "adbconnection.h"
 
+#include "adbconnection/client.h"
 #include "android-base/endian.h"
 #include "android-base/stringprintf.h"
 #include "base/file_utils.h"
 #include "base/logging.h"
 #include "base/macros.h"
 #include "base/mutex.h"
-#include "base/socket_peer_is_trusted.h"
 #include "jni/java_vm_ext.h"
 #include "jni/jni_env_ext.h"
 #include "mirror/throwable.h"
@@ -66,7 +67,6 @@
 
 static constexpr int kEventfdLocked = 0;
 static constexpr int kEventfdUnlocked = 1;
-static constexpr int kControlSockSendTimeout = 10;
 
 static constexpr size_t kPacketHeaderLen = 11;
 static constexpr off_t kPacketSizeOff = 0;
@@ -125,7 +125,7 @@
     controller_(this),
     ddm_callback_(this),
     sleep_event_fd_(-1),
-    control_sock_(-1),
+    control_ctx_(nullptr, adbconnection_client_destroy),
     local_agent_control_sock_(-1),
     remote_agent_control_sock_(-1),
     adb_connection_socket_(-1),
@@ -447,57 +447,18 @@
 }
 
 android::base::unique_fd AdbConnectionState::ReadFdFromAdb() {
-  // We don't actually care about the data that is sent. We do need to receive something though.
-  char dummy = '!';
-  union {
-    cmsghdr cm;
-    char buffer[CMSG_SPACE(sizeof(int))];
-  } cm_un;
-
-  iovec iov;
-  iov.iov_base       = &dummy;
-  iov.iov_len        = 1;
-
-  msghdr msg;
-  msg.msg_name       = nullptr;
-  msg.msg_namelen    = 0;
-  msg.msg_iov        = &iov;
-  msg.msg_iovlen     = 1;
-  msg.msg_flags      = 0;
-  msg.msg_control    = cm_un.buffer;
-  msg.msg_controllen = sizeof(cm_un.buffer);
-
-  cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);
-  cmsg->cmsg_len   = msg.msg_controllen;
-  cmsg->cmsg_level = SOL_SOCKET;
-  cmsg->cmsg_type  = SCM_RIGHTS;
-  (reinterpret_cast<int*>(CMSG_DATA(cmsg)))[0] = -1;
-
-  int rc = TEMP_FAILURE_RETRY(recvmsg(control_sock_, &msg, 0));
-
-  if (rc <= 0) {
-    return android::base::unique_fd(-1);
-  } else {
-    VLOG(jdwp) << "Fds have been received from ADB!";
-  }
-
-  return android::base::unique_fd((reinterpret_cast<int*>(CMSG_DATA(cmsg)))[0]);
+  return android::base::unique_fd(adbconnection_client_receive_jdwp_fd(control_ctx_.get()));
 }
 
 bool AdbConnectionState::SetupAdbConnection() {
-  int        sleep_ms     = 500;
-  const int  sleep_max_ms = 2*1000;
+  int sleep_ms = 500;
+  const int sleep_max_ms = 2 * 1000;
 
-  android::base::unique_fd sock(socket(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC, 0));
-  if (sock < 0) {
-    PLOG(ERROR) << "Could not create ADB control socket";
-    return false;
-  }
-  struct timeval timeout;
-  timeout.tv_sec = kControlSockSendTimeout;
-  timeout.tv_usec = 0;
-  setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout));
-  int32_t pid = getpid();
+  const AdbConnectionClientInfo infos[] = {
+    {.type = AdbConnectionClientInfoType::pid, .data.pid = static_cast<uint64_t>(getpid())},
+    {.type = AdbConnectionClientInfoType::debuggable, .data.debuggable = true},
+  };
+  const AdbConnectionClientInfo* info_ptrs[] = {&infos[0], &infos[1]};
 
   while (!shutting_down_) {
     // If adbd isn't running, because USB debugging was disabled or
@@ -511,39 +472,20 @@
     // of battery life, we should consider timing out and giving
     // up after a few minutes in case somebody ships an app with
     // the debuggable flag set.
-    int ret = connect(sock, &control_addr_.controlAddrPlain, control_addr_len_);
-    if (ret == 0) {
-      bool trusted = sock >= 0 && art::SocketPeerIsTrusted(sock);
-      if (!trusted) {
-        LOG(ERROR) << "adb socket is not trusted. Aborting connection.";
-        if (sock >= 0 && shutdown(sock, SHUT_RDWR)) {
-          PLOG(ERROR) << "trouble shutting down socket";
-        }
-        return false;
-      }
-      /* now try to send our pid to the ADB daemon */
-      ret = TEMP_FAILURE_RETRY(send(sock, &pid, sizeof(pid), 0));
-      if (ret == sizeof(pid)) {
-        VLOG(jdwp) << "PID " << pid << " sent to adb";
-        control_sock_ = std::move(sock);
-        return true;
-      } else {
-        PLOG(ERROR) << "Weird, can't send JDWP process pid to ADB. Aborting connection.";
-        return false;
-      }
-    } else {
-      if (VLOG_IS_ON(jdwp)) {
-        PLOG(ERROR) << "Can't connect to ADB control socket. Will retry.";
-      }
+    control_ctx_.reset(adbconnection_client_new(info_ptrs, std::size(infos)));
+    if (control_ctx_) {
+      return true;
+    }
 
-      usleep(sleep_ms * 1000);
+    // We failed to connect.
+    usleep(sleep_ms * 1000);
 
-      sleep_ms += (sleep_ms >> 1);
-      if (sleep_ms > sleep_max_ms) {
-        sleep_ms = sleep_max_ms;
-      }
+    sleep_ms += (sleep_ms >> 1);
+    if (sleep_ms > sleep_max_ms) {
+      sleep_ms = sleep_max_ms;
     }
   }
+
   return false;
 }
 
@@ -554,12 +496,12 @@
   self->SetState(art::kWaitingInMainDebuggerLoop);
   // shutting_down_ set by StopDebuggerThreads
   while (!shutting_down_) {
-    // First get the control_sock_ from adb if we don't have one. We only need to do this once.
-    if (control_sock_ == -1 && !SetupAdbConnection()) {
+    // First, connect to adbd if we haven't already.
+    if (!control_ctx_ && !SetupAdbConnection()) {
       LOG(ERROR) << "Failed to setup adb connection.";
       return;
     }
-    while (!shutting_down_ && control_sock_ != -1) {
+    while (!shutting_down_ && control_ctx_) {
       bool should_listen_on_connection = !agent_has_socket_ && !sent_agent_fds_;
       struct pollfd pollfds[4] = {
         { sleep_event_fd_, POLLIN, 0 },
@@ -567,7 +509,8 @@
         { (agent_loaded_ ? local_agent_control_sock_ : -1), POLLIN, 0 },
         // Check for the control_sock_ actually going away. Only do this if we don't have an active
         // connection.
-        { (adb_connection_socket_ == -1 ? control_sock_ : -1), POLLIN | POLLRDHUP, 0 },
+        { (adb_connection_socket_ == -1 ? adbconnection_client_pollfd(control_ctx_.get()) : -1),
+          POLLIN | POLLRDHUP, 0 },
         // if we have not loaded the agent either the adb_connection_socket_ is -1 meaning we don't
         // have a real connection yet or the socket through adb needs to be listened to for incoming
         // data that the agent or this plugin can handle.
@@ -617,10 +560,10 @@
         {
           // Hold onto this lock so that concurrent ddm publishes don't try to use an illegal fd.
           ScopedEventFdLock sefdl(adb_write_event_fd_);
-          android::base::unique_fd new_fd(ReadFdFromAdb());
+          android::base::unique_fd new_fd(adbconnection_client_receive_jdwp_fd(control_ctx_.get()));
           if (new_fd == -1) {
             // Something went wrong. We need to retry getting the control socket.
-            control_sock_.reset();
+            control_ctx_.reset();
             break;
           } else if (adb_connection_socket_ != -1) {
             // We already have a connection.
@@ -645,7 +588,7 @@
         // Reset the connection since we don't have an active socket through the adb server.
         DCHECK(!agent_has_socket_) << "We shouldn't be doing anything if there is already a "
                                    << "connection active";
-        control_sock_.reset();
+        control_ctx_.reset();
         break;
       } else if (FlagsSet(adb_socket_poll.revents, POLLIN)) {
         DCHECK(!agent_has_socket_);
diff --git a/adbconnection/adbconnection.h b/adbconnection/adbconnection.h
index c51f981..f9b0928 100644
--- a/adbconnection/adbconnection.h
+++ b/adbconnection/adbconnection.h
@@ -18,10 +18,12 @@
 #define ART_ADBCONNECTION_ADBCONNECTION_H_
 
 #include <stdint.h>
+#include <memory>
 #include <vector>
 #include <limits>
 
 #include "android-base/unique_fd.h"
+#include "adbconnection/client.h"
 
 #include "base/mutex.h"
 #include "base/array_ref.h"
@@ -127,8 +129,8 @@
   // Eventfd used to allow the StopDebuggerThreads function to wake up sleeping threads
   android::base::unique_fd sleep_event_fd_;
 
-  // Socket that we use to talk to adbd.
-  android::base::unique_fd control_sock_;
+  // Context which wraps the socket which we use to talk to adbd.
+  std::unique_ptr<AdbConnectionClientContext, void(*)(AdbConnectionClientContext*)> control_ctx_;
 
   // Socket that we use to talk to the agent (if it's loaded).
   android::base::unique_fd local_agent_control_sock_;
diff --git a/adbconnection/adbconnection_server.cc b/adbconnection/adbconnection_server.cc
deleted file mode 100644
index f69f4a7..0000000
--- a/adbconnection/adbconnection_server.cc
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Copyright (C) 2019 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 "adbconnection/server.h"
-
-#include <sys/epoll.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <unistd.h>
-
-#include <algorithm>
-#include <array>
-#include <vector>
-
-#include <android-base/logging.h>
-#include <android-base/unique_fd.h>
-
-using android::base::unique_fd;
-
-#define JDWP_CONTROL_NAME "\0jdwp-control"
-#define JDWP_CONTROL_NAME_LEN (sizeof(JDWP_CONTROL_NAME) - 1)
-
-static_assert(JDWP_CONTROL_NAME_LEN <=
-              sizeof(reinterpret_cast<sockaddr_un*>(0)->sun_path));
-
-// Listen for incoming jdwp clients forever.
-void adbconnection_listen(void (*callback)(int fd, pid_t pid)) {
-  sockaddr_un addr = {};
-  socklen_t addrlen = JDWP_CONTROL_NAME_LEN + sizeof(addr.sun_family);
-
-  addr.sun_family = AF_UNIX;
-  memcpy(addr.sun_path, JDWP_CONTROL_NAME, JDWP_CONTROL_NAME_LEN);
-
-  unique_fd s(socket(AF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK | SOCK_CLOEXEC, 0));
-  if (s < 0) {
-    PLOG(ERROR) << "failed to create JDWP control socket";
-    return;
-  }
-
-  if (bind(s.get(), reinterpret_cast<sockaddr*>(&addr), addrlen) < 0) {
-    PLOG(ERROR) << "failed to bind JDWP control socket";
-    return;
-  }
-
-  if (listen(s.get(), 4) < 0) {
-    PLOG(ERROR) << "failed to listen on JDWP control socket";
-    return;
-  }
-
-  std::vector<unique_fd> pending_connections;
-
-  unique_fd epfd(epoll_create1(EPOLL_CLOEXEC));
-  std::array<epoll_event, 16> events;
-
-  events[0].events = EPOLLIN;
-  events[0].data.fd = -1;
-  if (epoll_ctl(epfd.get(), EPOLL_CTL_ADD, s.get(), &events[0]) != 0) {
-    LOG(FATAL) << "failed to register event with epoll fd";
-  }
-
-  while (true) {
-    int epoll_rc = TEMP_FAILURE_RETRY(epoll_wait(epfd.get(), events.data(), events.size(), -1));
-    if (epoll_rc == -1) {
-      PLOG(FATAL) << "epoll_wait failed";
-    }
-
-    for (int i = 0; i < epoll_rc; ++i) {
-      const epoll_event& event = events[i];
-      if (event.data.fd == -1) {
-        unique_fd client(TEMP_FAILURE_RETRY(
-            accept4(s.get(), nullptr, nullptr, SOCK_NONBLOCK | SOCK_CLOEXEC)));
-
-        if (client == -1) {
-          PLOG(WARNING) << "failed to accept client on JDWP control socket";
-          continue;
-        }
-
-        epoll_event register_event;
-        register_event.events = EPOLLIN;
-        register_event.data.fd = client.get();
-
-        if (epoll_ctl(epfd.get(), EPOLL_CTL_ADD, client.get(),
-                      &register_event) != 0) {
-          PLOG(FATAL) << "failed to register JDWP client with epoll";
-        }
-
-        pending_connections.emplace_back(std::move(client));
-      } else {
-        // n^2, but the backlog should be short.
-        auto it = std::find_if(
-            pending_connections.begin(), pending_connections.end(),
-            [&](const unique_fd& fd) { return fd.get() == event.data.fd; });
-
-        if (it == pending_connections.end()) {
-          LOG(FATAL) << "failed to find JDWP client (" << event.data.fd
-                     << ") in pending connections";
-        }
-
-        // Massively oversized buffer: we're expecting an int32_t from the other end.
-        char buf[32];
-        int rc = TEMP_FAILURE_RETRY(recv(it->get(), buf, sizeof(buf), MSG_DONTWAIT));
-        if (rc != 4) {
-          LOG(ERROR)
-              << "received data of incorrect size from JDWP client: read " << rc
-              << ", expected 4";
-        } else {
-          int32_t pid;
-          memcpy(&pid, buf, sizeof(pid));
-          callback(it->release(), static_cast<pid_t>(pid));
-        }
-
-        if (epoll_ctl(epfd.get(), EPOLL_CTL_DEL, event.data.fd, nullptr) != 0) {
-          LOG(FATAL) << "failed to delete fd from JDWP epoll fd";
-        }
-
-        pending_connections.erase(it);
-      }
-    }
-  }
-}
diff --git a/adbconnection/include/adbconnection/server.h b/adbconnection/include/adbconnection/server.h
deleted file mode 100644
index 8d1d69a..0000000
--- a/adbconnection/include/adbconnection/server.h
+++ /dev/null
@@ -1,30 +0,0 @@
-#ifndef ART_ADBCONNECTION_INCLUDE_ADBCONNECTION_SERVER_H_
-#define ART_ADBCONNECTION_INCLUDE_ADBCONNECTION_SERVER_H_
-
-/*
- * Copyright (C) 2019 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 <sys/types.h>
-
-#include <android-base/unique_fd.h>
-
-extern "C" {
-
-void adbconnection_listen(void (*callback)(int fd, pid_t pid));
-
-}
-
-#endif  // ART_ADBCONNECTION_INCLUDE_ADBCONNECTION_SERVER_H_
diff --git a/adbconnection/libadbconnection_server.map.txt b/adbconnection/libadbconnection_server.map.txt
deleted file mode 100644
index b631581..0000000
--- a/adbconnection/libadbconnection_server.map.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-#
-# Copyright (C) 2019 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.
-#
-
-LIBADBCONNECTION_SERVER_1 {
-  global:
-    adbconnection_listen;
-  local:
-    *;
-};
diff --git a/build/apex/Android.bp b/build/apex/Android.bp
index 70e4988..738a870 100644
--- a/build/apex/Android.bp
+++ b/build/apex/Android.bp
@@ -27,7 +27,6 @@
 // the ART APEX.
 art_runtime_base_native_shared_libs = [
     // External API (having APEX stubs).
-    "libadbconnection_server",
     "libdexfile_external",
     "libnativebridge",
     "libnativehelper",
diff --git a/build/apex/art_apex_test.py b/build/apex/art_apex_test.py
index 4062676..f2ec6e4 100755
--- a/build/apex/art_apex_test.py
+++ b/build/apex/art_apex_test.py
@@ -492,7 +492,6 @@
     self._checker.check_native_library('libnativebridge')
     self._checker.check_native_library('libnativehelper')
     self._checker.check_native_library('libnativeloader')
-    self._checker.check_native_library('libadbconnection_server')
 
     # Check internal libraries for ART.
     self._checker.check_native_library('libadbconnection')
diff --git a/build/apex/ld.config.txt b/build/apex/ld.config.txt
index b2eefcf..4121e9f 100644
--- a/build/apex/ld.config.txt
+++ b/build/apex/ld.config.txt
@@ -8,15 +8,16 @@
 dir.art = /apex/com.android.art/bin/
 
 [art]
-additional.namespaces = platform,conscrypt,art,neuralnetworks
+additional.namespaces = platform,conscrypt,art,neuralnetworks,adbd
 
 # The default namespace here only links to other namespaces, in particular "art"
 # where the real library loading takes place. Any outgoing links from "art" also
 # need to be present here.
 namespace.default.isolated = true
-namespace.default.links = art,platform
+namespace.default.links = art,platform,adbd
 namespace.default.link.art.allow_all_shared_libs = true
 namespace.default.link.platform.allow_all_shared_libs = true
+namespace.default.link.adbd.shared_libs = libadbconnection_client.so
 
 ###############################################################################
 # "art" APEX namespace
@@ -47,13 +48,14 @@
 # the APEX namespaces, because searching of the libs are NOT done in
 # /system/lib, but in /apex/<module>/lib directory.
 namespace.art.permitted.paths += /system/${LIB}
-namespace.art.links = platform,neuralnetworks
+namespace.art.links = platform,neuralnetworks,adbd
 # Need allow_all_shared_libs because libart.so can dlopen oat files in
 # /system/framework and /data.
 # TODO(b/130340935): Use a dynamically created linker namespace similar to
 # classloader-namespace for oat files, and tighten this up.
 namespace.art.link.platform.allow_all_shared_libs = true
 namespace.art.link.neuralnetworks.shared_libs = libneuralnetworks.so
+namespace.art.link.adbd.shared_libs = libadbconnection_client.so
 
 ###############################################################################
 # "platform" namespace
@@ -155,3 +157,20 @@
 namespace.neuralnetworks.link.platform.shared_libs += libneuralnetworks_packageinfo.so
 namespace.neuralnetworks.link.platform.shared_libs += libsync.so
 namespace.neuralnetworks.link.platform.shared_libs += libvndksupport.so
+
+###############################################################################
+# "adbd" APEX namespace
+#
+# This namespace is for libraries within the adbd APEX.
+###############################################################################
+
+namespace.adbd.isolated = true
+namespace.adbd.visible = true
+
+namespace.adbd.search.paths = /apex/com.android.adbd/${LIB}
+namespace.adbd.asan.search.paths = /apex/com.android.adbd/${LIB}
+namespace.adbd.links = platform
+namespace.adbd.link.platform.shared_libs  = libc.so
+namespace.adbd.link.platform.shared_libs += libm.so
+namespace.adbd.link.platform.shared_libs += libdl.so
+namespace.adbd.link.platform.shared_libs += liblog.so