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

Commit 22c98da7 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

am: 56d33633

Change-Id: I40666175760849bd27a94437422559f7b9caba7f
parents 4133da35 56d33633
Loading
Loading
Loading
Loading
+3 −0
Original line number Original line Diff line number Diff line
@@ -344,6 +344,7 @@ cc_library_static {
    generated_headers: ["platform_tools_version"],
    generated_headers: ["platform_tools_version"],


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


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


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


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


#include <linux/usb/functionfs.h>

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


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


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


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


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

/* here's how these things work.
/* here's how these things work.


   when adbd starts, it creates a unix server socket
   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>>();
static auto& _jdwp_list = *new std::list<std::unique_ptr<JdwpProcess>>();


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

        this->socket = socket;
        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) {
        if (!this->fde) {
            LOG(FATAL) << "could not create fdevent for new JDWP process";
            LOG(FATAL) << "could not create fdevent for new JDWP process";
        }
        }

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


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


    void RemoveFromList() {
    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; };
        auto pred = [this](const auto& proc) { return proc.get() == this; };
        _jdwp_list.remove_if(pred);
        _jdwp_list.remove_if(pred);
    }
    }


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


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


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

        std::string next = std::to_string(proc->pid) + "\n";
        std::string next = std::to_string(proc->pid) + "\n";
        if (temp.length() + next.length() > bufferlen) {
        if (temp.length() + next.length() > bufferlen) {
            D("truncating JDWP process list (max len = %zu)", 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) {
static void jdwp_process_event(int socket, unsigned events, void* _proc) {
    JdwpProcess* proc = reinterpret_cast<JdwpProcess*>(_proc);
    JdwpProcess* proc = reinterpret_cast<JdwpProcess*>(_proc);
    CHECK_EQ(socket, proc->socket);
    CHECK_EQ(socket, proc->socket.get());


    if (events & FDE_READ) {
    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.
        // We already have the PID, if we can read from the socket, we've probably hit EOF.
        D("terminating JDWP connection %d", proc->pid);
        D("terminating JDWP connection %d", proc->pid);
        goto CloseProcess;
        goto CloseProcess;
    }
    }
    }


    if (events & FDE_WRITE) {
    if (events & FDE_WRITE) {
        D("trying to send fd to JDWP process (count = %zu)", proc->out_fds.size());
        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{};
    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
/** "jdwp" local service implementation
 ** this simply returns the list of known JDWP process pids
 ** 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) {
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 */
#endif /* !ADB_HOST */