Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 56d33633 authored by Josh Gao's avatar Josh Gao Committed by android-build-merger
Browse files

Merge "adbd: move jdwp listening logic into ART."

am: d1940130

Change-Id: I71949e1588a30c697cd40064c2a8f93b2e5682df
parents 3e3cbb77 d1940130
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -344,6 +344,7 @@ cc_library_static {
    generated_headers: ["platform_tools_version"],

    static_libs: [
        "libadbconnection_server",
        "libdiagnose_usb",
    ],

@@ -395,6 +396,7 @@ cc_library {
    ],

    static_libs: [
        "libadbconnection_server",
        "libadbd_core",
        "libdiagnose_usb",
    ],
@@ -531,6 +533,7 @@ cc_binary {
    },

    static_libs: [
        "libadbconnection_server",
        "libadbd",
        "libadbd_services",
        "libasyncio",
+2 −0
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@
 * limitations under the License.
 */

#include <linux/usb/functionfs.h>

#include <atomic>
#include <condition_variable>
#include <mutex>
+32 −126
Original line number Diff line number Diff line
@@ -30,15 +30,21 @@

#include <list>
#include <memory>
#include <thread>
#include <vector>

#include <adbconnection/server.h>
#include <android-base/cmsg.h>
#include <android-base/unique_fd.h>

#include "adb.h"
#include "adb_io.h"
#include "adb_unique_fd.h"
#include "adb_utils.h"

using android::base::borrowed_fd;
using android::base::unique_fd;

/* here's how these things work.

   when adbd starts, it creates a unix server socket
@@ -133,16 +139,16 @@ struct JdwpProcess;
static auto& _jdwp_list = *new std::list<std::unique_ptr<JdwpProcess>>();

struct JdwpProcess {
    explicit JdwpProcess(int socket) {
    JdwpProcess(unique_fd socket, pid_t pid) {
        CHECK(pid != 0);

        this->socket = socket;
        this->fde = fdevent_create(socket, jdwp_process_event, this);
        this->pid = pid;
        this->fde = fdevent_create(socket.release(), jdwp_process_event, this);

        if (!this->fde) {
            LOG(FATAL) << "could not create fdevent for new JDWP process";
        }

        /* start by waiting for the PID */
        fdevent_add(this->fde, FDE_READ);
    }

    ~JdwpProcess() {
@@ -160,18 +166,12 @@ struct JdwpProcess {
    }

    void RemoveFromList() {
        if (this->pid >= 0) {
            D("removing pid %d from jdwp process list", this->pid);
        } else {
            D("removing transient JdwpProcess from list");
        }

        auto pred = [this](const auto& proc) { return proc.get() == this; };
        _jdwp_list.remove_if(pred);
    }

    borrowed_fd socket = -1;
    int32_t pid = -1;
    int socket = -1;
    fdevent* fde = nullptr;

    std::vector<unique_fd> out_fds;
@@ -181,11 +181,6 @@ static size_t jdwp_process_list(char* buffer, size_t bufferlen) {
    std::string temp;

    for (auto& proc : _jdwp_list) {
        /* skip transient connections */
        if (proc->pid < 0) {
            continue;
        }

        std::string next = std::to_string(proc->pid) + "\n";
        if (temp.length() + next.length() > bufferlen) {
            D("truncating JDWP process list (max len = %zu)", bufferlen);
@@ -214,25 +209,13 @@ static size_t jdwp_process_list_msg(char* buffer, size_t bufferlen) {

static void jdwp_process_event(int socket, unsigned events, void* _proc) {
    JdwpProcess* proc = reinterpret_cast<JdwpProcess*>(_proc);
    CHECK_EQ(socket, proc->socket);
    CHECK_EQ(socket, proc->socket.get());

    if (events & FDE_READ) {
        if (proc->pid < 0) {
            ssize_t rc = TEMP_FAILURE_RETRY(recv(socket, &proc->pid, sizeof(proc->pid), 0));
            if (rc != sizeof(proc->pid)) {
                D("failed to read jdwp pid: rc = %zd, errno = %s", rc, strerror(errno));
                goto CloseProcess;
            }

            /* all is well, keep reading to detect connection closure */
            D("Adding pid %d to jdwp process list", proc->pid);
            jdwp_process_list_updated();
        } else {
        // We already have the PID, if we can read from the socket, we've probably hit EOF.
        D("terminating JDWP connection %d", proc->pid);
        goto CloseProcess;
    }
    }

    if (events & FDE_WRITE) {
        D("trying to send fd to JDWP process (count = %zu)", proc->out_fds.size());
@@ -284,98 +267,6 @@ unique_fd create_jdwp_connection_fd(int pid) {
    return unique_fd{};
}

/**  VM DEBUG CONTROL SOCKET
 **
 **  we do implement a custom asocket to receive the data
 **/

/* name of the debug control Unix socket */
#define JDWP_CONTROL_NAME "\0jdwp-control"
#define JDWP_CONTROL_NAME_LEN (sizeof(JDWP_CONTROL_NAME) - 1)

struct JdwpControl {
    int listen_socket;
    fdevent* fde;
};

static JdwpControl _jdwp_control;

static void jdwp_control_event(int s, unsigned events, void* user);

static int jdwp_control_init(JdwpControl* control, const char* sockname, int socknamelen) {
    sockaddr_un addr;
    socklen_t addrlen;
    int maxpath = sizeof(addr.sun_path);
    int pathlen = socknamelen;

    if (pathlen >= maxpath) {
        D("vm debug control socket name too long (%d extra chars)", pathlen + 1 - maxpath);
        return -1;
    }

    memset(&addr, 0, sizeof(addr));
    addr.sun_family = AF_UNIX;
    memcpy(addr.sun_path, sockname, socknamelen);

    unique_fd s(socket(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC, 0));
    if (s < 0) {
        D("could not create vm debug control socket. %d: %s", errno, strerror(errno));
        return -1;
    }

    addrlen = pathlen + sizeof(addr.sun_family);

    if (bind(s.get(), reinterpret_cast<sockaddr*>(&addr), addrlen) < 0) {
        D("could not bind vm debug control socket: %d: %s", errno, strerror(errno));
        return -1;
    }

    if (listen(s.get(), 4) < 0) {
        D("listen failed in jdwp control socket: %d: %s", errno, strerror(errno));
        return -1;
    }

    control->listen_socket = s.release();
    control->fde = fdevent_create(control->listen_socket, jdwp_control_event, control);
    if (control->fde == nullptr) {
        D("could not create fdevent for jdwp control socket");
        return -1;
    }

    /* only wait for incoming connections */
    fdevent_add(control->fde, FDE_READ);

    D("jdwp control socket started (%d)", control->listen_socket);
    return 0;
}

static void jdwp_control_event(int fd, unsigned events, void* _control) {
    JdwpControl* control = (JdwpControl*)_control;

    CHECK_EQ(fd, control->listen_socket);
    if (events & FDE_READ) {
        int s = adb_socket_accept(control->listen_socket, nullptr, nullptr);
        if (s < 0) {
            if (errno == ECONNABORTED) {
                /* oops, the JDWP process died really quick */
                D("oops, the JDWP process died really quick");
                return;
            } else {
                /* the socket is probably closed ? */
                D("weird accept() failed on jdwp control socket: %s", strerror(errno));
                return;
            }
        }

        auto proc = std::make_unique<JdwpProcess>(s);
        if (!proc) {
            LOG(FATAL) << "failed to allocate JdwpProcess";
        }

        _jdwp_list.emplace_back(std::move(proc));
    }
}

/** "jdwp" local service implementation
 ** this simply returns the list of known JDWP process pids
 **/
@@ -526,7 +417,22 @@ asocket* create_jdwp_tracker_service_socket(void) {
}

int init_jdwp(void) {
    return jdwp_control_init(&_jdwp_control, JDWP_CONTROL_NAME, JDWP_CONTROL_NAME_LEN);
    std::thread([]() {
        adb_thread_setname("jdwp control");
        adbconnection_listen([](int fd, pid_t pid) {
            LOG(INFO) << "jdwp connection from " << pid;
            fdevent_run_on_main_thread([fd, pid] {
                unique_fd ufd(fd);
                auto proc = std::make_unique<JdwpProcess>(std::move(ufd), pid);
                if (!proc) {
                    LOG(FATAL) << "failed to allocate JdwpProcess";
                }
                _jdwp_list.emplace_back(std::move(proc));
                jdwp_process_list_updated();
            });
        });
    }).detach();
    return 0;
}

#endif /* !ADB_HOST */