android6.0 adbd深入分析(二)adb驱动数据的处理、写数据到adb驱动节点



上篇博客最后讲到在output_thread中。读取了adb驱动的数据后。就调用write_packet(t->fd, t->serial, &p)函数,把数据网socketpair的一側写。

这会导致socketpair的还有一側有数据,还有一側有数据会调用transport_socket_events函数来处理数据。


一、处理驱动读取的数据

我们如今来看看transport_socket_events函数:

static void transport_socket_events(int fd, unsigned events, void *_t)
{
    atransport *t = reinterpret_cast<atransport*>(_t);
    D("transport_socket_events(fd=%d, events=%04x,...)
", fd, events);
    if(events & FDE_READ){
        apacket *p = 0;
        if(read_packet(fd, t->serial, &p)){
            D("%s: failed to read packet from transport socket on fd %d
", t->serial, fd);
        } else {
            handle_packet(p, (atransport *) _t);
        }
    }
}

我们先把socketpair一端的数据读取出来,然后调用handle_packet来处理。

void handle_packet(apacket *p, atransport *t)
{
    asocket *s;

    switch(p->msg.command){//依据从驱动读取内容msg的命令
	......

    case A_OPEN: /* OPEN(local-id, 0, "destination") */
        if (t->online && p->msg.arg0 != 0 && p->msg.arg1 == 0) {
            char *name = (char*) p->data;
            name[p->msg.data_length > 0 ? p->msg.data_length - 1 : 0] = 0;
            s = create_local_service_socket(name);//创建一个本地的socket
            if(s == 0) {
                send_close(0, p->msg.arg0, t);
            } else {
                s->peer = create_remote_socket(p->msg.arg0, t);
                s->peer->peer = s;
                send_ready(s->id, s->peer->id, t);
                s->ready(s);
            }
        }
        break;
	......

    case A_WRTE: /* WRITE(local-id, remote-id, <data>) */
        if (t->online && p->msg.arg0 != 0 && p->msg.arg1 != 0) {
            if((s = find_local_socket(p->msg.arg1, p->msg.arg0))) {
                unsigned rid = p->msg.arg0;
                p->len = p->msg.data_length;

                if(s->enqueue(s, p) == 0) {
                    D("Enqueue the socket
");
                    send_ready(s->id, rid, t);
                }
                return;
            }
        }
        break;

    default:
        printf("handle_packet: what is %08x?

! ", p->msg.command); } put_apacket(p); }


上面是处理驱动的数据。我们先来看下处理open命令中一个create_local_service_socket函数

asocket *create_local_service_socket(const char *name)
{
#if !ADB_HOST
    if (!strcmp(name,"jdwp")) {
        return create_jdwp_service_socket();
    }
    if (!strcmp(name,"track-jdwp")) {
        return create_jdwp_tracker_service_socket();
    }
#endif
    int fd = service_to_fd(name);//获取fd
    if(fd < 0) return 0;

    asocket* s = create_local_socket(fd);//创建socket
    D("LS(%d): bound to '%s' via %d
", s->id, name, fd);

#if !ADB_HOST
    char debug[PROPERTY_VALUE_MAX];
    if (!strncmp(name, "root:", 5))
        property_get("ro.debuggable", debug, "");

    if ((!strncmp(name, "root:", 5) && getuid() != 0 && strcmp(debug, "1") == 0)
        || (!strncmp(name, "unroot:", 7) && getuid() == 0)
        || !strncmp(name, "usb:", 4)
        || !strncmp(name, "tcpip:", 6)) {
        D("LS(%d): enabling exit_on_close
", s->id);
        s->exit_on_close = 1;
    }
#endif

    return s;
}

我们先来看看service_to_fd函数:

int service_to_fd(const char *name)
{
    int ret = -1;

    if(!strncmp(name, "tcp:", 4)) {
        int port = atoi(name + 4);
        name = strchr(name + 4, ':');
        if(name == 0) {
            ret = socket_loopback_client(port, SOCK_STREAM);
            if (ret >= 0)
                disable_tcp_nagle(ret);
        } else {
#if ADB_HOST
            ret = socket_network_client(name + 1, port, SOCK_STREAM);
#else
            return -1;
#endif
        }
#ifndef HAVE_WINSOCK   /* winsock doesn't implement unix domain sockets */
    } else if(!strncmp(name, "local:", 6)) {
        ret = socket_local_client(name + 6,
                ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
    } else if(!strncmp(name, "localreserved:", 14)) {
        ret = socket_local_client(name + 14,
                ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
    } else if(!strncmp(name, "localabstract:", 14)) {
        ret = socket_local_client(name + 14,
                ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);
    } else if(!strncmp(name, "localfilesystem:", 16)) {
        ret = socket_local_client(name + 16,
                ANDROID_SOCKET_NAMESPACE_FILESYSTEM, SOCK_STREAM);
#endif
#if !ADB_HOST
    } else if(!strncmp("dev:", name, 4)) {
        ret = unix_open(name + 4, O_RDWR | O_CLOEXEC);
    } else if(!strncmp(name, "framebuffer:", 12)) {
        ret = create_service_thread(framebuffer_service, 0);
    } else if (!strncmp(name, "jdwp:", 5)) {
        ret = create_jdwp_connection_fd(atoi(name+5));
    } else if(!HOST && !strncmp(name, "shell:", 6)) {//adb shell
        ret = create_subproc_thread(name + 6, SUBPROC_PTY);
    } else if(!HOST && !strncmp(name, "exec:", 5)) {
        ret = create_subproc_thread(name + 5, SUBPROC_RAW);
    } else if(!strncmp(name, "sync:", 5)) {
    	D("kangchen service_to_fd file_sync_service");
        ret = create_service_thread(file_sync_service, NULL);
    } else if(!strncmp(name, "remount:", 8)) {
        ret = create_service_thread(remount_service, NULL);
    } else if(!strncmp(name, "reboot:", 7)) {
        void* arg = strdup(name + 7);
        if (arg == NULL) return -1;
        ret = create_service_thread(reboot_service, arg);
    } else if(!strncmp(name, "root:", 5)) {//adb root
        ret = create_service_thread(restart_root_service, NULL);
这里我们主要看下adb root和adb shell,其它的以后自己慢慢研究:

1.2 adb root的处理过程

我们先来看下adb root的处理过程,serverice_to_fd函数先调用了create_service_thread函数:

static int create_service_thread(void (*func)(int, void *), void *cookie)
{
    int s[2];
    if (adb_socketpair(s)) {//建立一对socketpair
        printf("cannot create service socket pair
");
        return -1;
    }
    D("socketpair: (%d,%d)", s[0], s[1]);

    stinfo* sti = reinterpret_cast<stinfo*>(malloc(sizeof(stinfo)));
    if (sti == nullptr) {
        fatal("cannot allocate stinfo");
    }
    sti->func = func;
    sti->cookie = cookie;
    sti->fd = s[1];

    adb_thread_t t;
    if (adb_thread_create(&t, service_bootstrap_func, sti)) {
        free(sti);
        adb_close(s[0]);
        adb_close(s[1]);
        printf("cannot create service thread
");
        return -1;
    }

    D("service thread started, %d:%d
",s[0], s[1]);
    return s[0];//返回一端的socketpair
}

我们再来看看service_bootstrap_func函数:

void *service_bootstrap_func(void *x)
{
    stinfo* sti = reinterpret_cast<stinfo*>(x);
    sti->func(sti->fd, sti->cookie);
    free(sti);
    return 0;
}

终于还是调用了create_service_thread传进来的func函数
而adb root传入的是restart_root_service函数:

void restart_root_service(int fd, void *cookie) {
    if (getuid() == 0) {//已经root
        WriteFdExactly(fd, "adbd is already running as root
");
        adb_close(fd);
    } else {
    	D("kangchen restart_root_service.
");
        char value[PROPERTY_VALUE_MAX];
        property_get("ro.debuggable", value, "");
        if (strcmp(value, "1") != 0) {
            WriteFdExactly(fd, "adbd cannot run as root in production builds
");
            adb_close(fd);
            return;
        }

        property_set("service.adb.root", "1");//设置root
        WriteFdExactly(fd, "restarting adbd as root
");//这是写入pc端的数据
        adb_close(fd);
    }
}

由于前面是sockpair。那这边写入的数据,会在另外一端的sockpair有反应。

而另外一端的sockpair终于是作为service_to_fd函数的返回值,那我们继续看下create_local_service_socket函数

asocket *create_local_service_socket(const char *name)
{
#if !ADB_HOST
    if (!strcmp(name,"jdwp")) {
        return create_jdwp_service_socket();
    }
    if (!strcmp(name,"track-jdwp")) {
        return create_jdwp_tracker_service_socket();
    }
#endif
    int fd = service_to_fd(name);//得到sockpair的一端
    if(fd < 0) return 0;

    asocket* s = create_local_socket(fd);//创建localsocket
    D("LS(%d): bound to '%s' via %d
", s->id, name, fd);

#if !ADB_HOST
    char debug[PROPERTY_VALUE_MAX];
    if (!strncmp(name, "root:", 5))
        property_get("ro.debuggable", debug, "");

    if ((!strncmp(name, "root:", 5) && getuid() != 0 && strcmp(debug, "1") == 0)
        || (!strncmp(name, "unroot:", 7) && getuid() == 0)
        || !strncmp(name, "usb:", 4)
        || !strncmp(name, "tcpip:", 6)) {
        D("LS(%d): enabling exit_on_close
", s->id);
        s->exit_on_close = 1;
    }
#endif

    return s;
}

我们再来看看create_local_socket函数

asocket *create_local_socket(int fd)
{
    asocket *s = reinterpret_cast<asocket*>(calloc(1, sizeof(asocket)));
    if (s == NULL) fatal("cannot allocate socket");
    s->fd = fd;
    s->enqueue = local_socket_enqueue;
    s->ready = local_socket_ready;
    s->shutdown = NULL;
    s->close = local_socket_close;
    install_local_socket(s);

    fdevent_install(&s->fde, fd, local_socket_event_func, s);
    D("LS(%d): created (fd=%d)
", s->id, s->fd);
    return s;
}

这个函数也是给socket赋各种函数等,然后当socket的这个fd有数据,这个fd就是前面service_to_fd返回的fd,当这个fd有数据会触发local_socket_func函数,我们来看下这个函数:

static void local_socket_event_func(int fd, unsigned ev, void* _s)
{
    asocket* s = reinterpret_cast<asocket*>(_s);
    D("LS(%d): event_func(fd=%d(==%d), ev=%04x)
", s->id, s->fd, fd, ev);

.....

    if (ev & FDE_READ) {
        apacket *p = get_apacket();
        unsigned char *x = p->data;
        size_t avail = MAX_PAYLOAD;
        int r;
        int is_eof = 0;

        while (avail > 0) {
            r = adb_read(fd, x, avail);//获取从sockpair一側传来的数据
            D("LS(%d): post adb_read(fd=%d,...) r=%d (errno=%d) avail=%zu
",
              s->id, s->fd, r, r < 0 ?

errno : 0, avail); if (r == -1) { if (errno == EAGAIN) { break; } } else if (r > 0) { avail -= r; x += r; continue; } /* r = 0 or unhandled error */ is_eof = 1; break; } D("LS(%d): fd=%d post avail loop. r=%d is_eof=%d forced_eof=%d ", s->id, s->fd, r, is_eof, s->fde.force_eof); if ((avail == MAX_PAYLOAD) || (s->peer == 0)) { put_apacket(p); } else { p->len = MAX_PAYLOAD - avail; r = s->peer->enqueue(s->peer, p);//往t->transport_socket的一端写值,这样input_thread线程就有数据读取了 D("LS(%d): fd=%d post peer->enqueue(). r=%d ", s->id, s->fd, r); if (r < 0) { /* error return means they closed us as a side-effect ** and we must return immediately. ** ** note that if we still have buffered packets, the ** socket will be placed on the closing socket list. ** this handler function will be called again ** to process FDE_WRITE events. */ return; } if (r > 0) { /* if the remote cannot accept further events, ** we disable notification of READs. They'll ** be enabled again when we get a call to ready() */ fdevent_del(&s->fde, FDE_READ); } } /* Don't allow a forced eof if data is still there */ if ((s->fde.force_eof && !r) || is_eof) { D(" closing because is_eof=%d r=%d s->fde.force_eof=%d ", is_eof, r, s->fde.force_eof); s->close(s); } } ...... }

比方当我们adb root 处理之后,会发送类似adb restart root之类的信息给adb 驱动,这时候就会触发local_socket_event_func函数。这个函数先去读取你要发的信息。然后往t->transport_socket的一端写值。这样input_thread线程就有数据读取了。而这个是通过s->peer->enqueue来实现的。

我们再来看看这块。

在处理open命令的之后,还创建了remotesocket

    case A_OPEN: /* OPEN(local-id, 0, "destination") */
        if (t->online && p->msg.arg0 != 0 && p->msg.arg1 == 0) {
            char *name = (char*) p->data;
            name[p->msg.data_length > 0 ? p->msg.data_length - 1 : 0] = 0;
            s = create_local_service_socket(name);
            if(s == 0) {
                send_close(0, p->msg.arg0, t);
            } else {
                s->peer = create_remote_socket(p->msg.arg0, t);
                s->peer->peer = s;
                send_ready(s->id, s->peer->id, t);
                s->ready(s);
            }
        }
        break;

我们来看看create_remote_socket函数

asocket *create_remote_socket(unsigned id, atransport *t)
{
    if (id == 0) fatal("invalid remote socket id (0)");
    asocket* s = reinterpret_cast<asocket*>(calloc(1, sizeof(aremotesocket)));
    adisconnect* dis = &reinterpret_cast<aremotesocket*>(s)->disconnect;

    if (s == NULL) fatal("cannot allocate socket");
    s->id = id;
    s->enqueue = remote_socket_enqueue;
    s->ready = remote_socket_ready;
    s->shutdown = remote_socket_shutdown;
    s->close = remote_socket_close;
    s->transport = t;

    dis->func   = remote_socket_disconnect;
    dis->opaque = s;
    add_transport_disconnect( t, dis );
    D("RS(%d): created
", s->id);
    return s;
}

这里我们主要看下remote_socket_enqueue函数:

static int remote_socket_enqueue(asocket *s, apacket *p)
{
    D("kangchen entered remote_socket_enqueue RS(%d) WRITE fd=%d peer.fd=%d
",
      s->id, s->fd, s->peer->fd);
    p->msg.command = A_WRTE;
    p->msg.arg0 = s->peer->id;
    p->msg.arg1 = s->id;
    p->msg.data_length = p->len;
    send_packet(p, s->transport);
    return 1;
}
再来看看send_packet函数

void send_packet(apacket *p, atransport *t)
{
    unsigned char *x;
    unsigned sum;
    unsigned count;

    p->msg.magic = p->msg.command ^ 0xffffffff;

    count = p->msg.data_length;
    x = (unsigned char *) p->data;
    sum = 0;
    while(count-- > 0){
        sum += *x++;
    }
    p->msg.data_check = sum;

    print_packet("send", p);

    if (t == NULL) {
        D("Transport is null 
");
        // Zap errno because print_packet() and other stuff have errno effect.
        errno = 0;
        fatal_errno("Transport is null");
    }
    if(write_packet(t->transport_socket, t->serial, &p)){
        fatal_errno("cannot enqueue packet on transport socket");
    }
}

send_packet函数终于是往t->transport_socket写入,这也意味着input_thread会从socketpair的还有一側读取数据,最后再往adb驱动写入数据。

这样整个adb root就比較清楚了。

static void *input_thread(void *_t)
{
    atransport *t = reinterpret_cast<atransport*>(_t);
    apacket *p;
    int active = 0;

    D("%s: starting transport input thread, reading from fd %d
",
       t->serial, t->fd);

    for(;;){
        if(read_packet(t->fd, t->serial, &p)) {//读取socket数据
            D("%s: failed to read apacket from transport on fd %d
",
               t->serial, t->fd );
            LOG("%s:%s: failed to read apacket from transport on fd %d
", __FUNCTION__, t->serial, t->fd );
            break;
        }
        if(p->msg.command == A_SYNC){
            if(p->msg.arg0 == 0) {
                D("%s: transport SYNC offline
", t->serial);
                put_apacket(p);
                LOG("%s:%s: transport SYNC offline
", __FUNCTION__, t->serial);
                break;
            } else {
                if(p->msg.arg1 == t->sync_token) {
                    D("%s: transport SYNC online
", t->serial);
                    LOG("%s:%s: transport SYNC online
", __FUNCTION__, t->serial);
                    active = 1;
                } else {
                    D("%s: transport ignoring SYNC %d != %d
",
                      t->serial, p->msg.arg1, t->sync_token);
                    LOG("%s:%s: transport ignoring SYNC
", __FUNCTION__, t->serial);
                }
            }
        } else {
            if(active) {
                D("%s: transport got packet, sending to remote
", t->serial);
                t->write_to_remote(p, t);//写入adb驱动
            } else {
                D("%s: transport ignoring packet while offline
", t->serial);
            }
        }

        put_apacket(p);
    }


1.2 adb shell 流程

以下我们再来看下adb shell的流程,会和adb root有点不一样。也会更复杂些。

相同adb shell的处理流程也是先到handle _packet函数:

    case A_OPEN: /* OPEN(local-id, 0, "destination") */
        if (t->online && p->msg.arg0 != 0 && p->msg.arg1 == 0) {
            char *name = (char*) p->data;
            name[p->msg.data_length > 0 ?

p->msg.data_length - 1 : 0] = 0; s = create_local_service_socket(name); if(s == 0) { send_close(0, p->msg.arg0, t); } else { s->peer = create_remote_socket(p->msg.arg0, t); s->peer->peer = s; send_ready(s->id, s->peer->id, t); s->ready(s); } } break;

一样的我们就直接看service_to_fd函数了,当中截取以下这段代码:

    } else if(!HOST && !strncmp(name, "shell:", 6)) {
        ret = create_subproc_thread(name + 6, SUBPROC_PTY);

我们来看看create_subproc_thread函数:

static int create_subproc_thread(const char *name, const subproc_mode mode)
{
    adb_thread_t t;
    int ret_fd;
    pid_t pid = -1;

    const char *arg0, *arg1;
    if (name == 0 || *name == 0) {
        arg0 = "-"; arg1 = 0;
    } else {
        arg0 = "-c"; arg1 = name;
    }

    switch (mode) {
    case SUBPROC_PTY:
        ret_fd = create_subproc_pty(SHELL_COMMAND, arg0, arg1, &pid);//我们是调用了这函数
        break;
    case SUBPROC_RAW:
        ret_fd = create_subproc_raw(SHELL_COMMAND, arg0, arg1, &pid);
        break;
    default:
        fprintf(stderr, "invalid subproc_mode %d
", mode);
        return -1;
    }
    D("create_subproc ret_fd=%d pid=%d
", ret_fd, pid);

    stinfo* sti = reinterpret_cast<stinfo*>(malloc(sizeof(stinfo)));
    if(sti == 0) fatal("cannot allocate stinfo");
    sti->func = subproc_waiter_service;
    sti->cookie = (void*) (uintptr_t) pid;
    sti->fd = ret_fd;

    if (adb_thread_create(&t, service_bootstrap_func, sti)) {
        free(sti);
        adb_close(ret_fd);
        fprintf(stderr, "cannot create service thread
");
        return -1;
    }

    D("service thread started, fd=%d pid=%d
", ret_fd, pid);
    return ret_fd;
}
我们先来看看create_subproc_pty函数:

static int create_subproc_pty(const char *cmd, const char *arg0, const char *arg1, pid_t *pid)
{
    int ptm;

    ptm = unix_open("/dev/ptmx", O_RDWR | O_CLOEXEC); // | O_NOCTTY);//返回的fd
    if(ptm < 0){
        printf("[ cannot open /dev/ptmx - %s ]
",strerror(errno));
        return -1;
    }

    char devname[64];
    if(grantpt(ptm) || unlockpt(ptm) || ptsname_r(ptm, devname, sizeof(devname)) != 0) {
        printf("[ trouble with /dev/ptmx - %s ]
", strerror(errno));
        adb_close(ptm);
        return -1;
    }

    *pid = fork();//fork进程
    if(*pid < 0) {
        printf("- fork failed: %s -
", strerror(errno));
        adb_close(ptm);
        return -1;
    }

    if (*pid == 0) {//子进程
        init_subproc_child();

        int pts = unix_open(devname, O_RDWR | O_CLOEXEC);
        if (pts < 0) {
            fprintf(stderr, "child failed to open pseudo-term slave: %s
", devname);
            exit(-1);
        }

        dup2(pts, STDIN_FILENO);//标准输入、输出、错误都指向这个fd
        dup2(pts, STDOUT_FILENO);
        dup2(pts, STDERR_FILENO);

        adb_close(pts);
        adb_close(ptm);

        execl(cmd, cmd, arg0, arg1, NULL);//然后应该一直运行system/bin/shell命令
		D("kangchen create_subproc_pty(cmd=%s, arg0=%s, arg1=%s)
", cmd, arg0, arg1);
        fprintf(stderr, "- exec '%s' failed: %s (%d) -
",
                cmd, strerror(errno), errno);
        exit(-1);
    } else {
        return ptm;
    }
#endif /* !defined(_WIN32) */
}

这个函数中,ptm和pts两个节点肯定有某种联系。pts然后把标准输入、输出、错误都指向了它。也就是当有输入、输出、错误数据都会到pts这个fd。终于肯定回到ptm这个fd。

也就是当外面有数据来的时候,ptm这个fd会有值,然后到pts,再到标准输入。经过dup2后进程A的不论什么目标为STDOUT_FILENO的I/O操作如printf等。其数据都将流入pts这个fd中。

而标准输入有值,会到pts。然后到ptm。最后数据就到input_thread了。事实上这个pts和ptm类似socketpair的一对。

我们再来看看subproc_waiter_service

static void subproc_waiter_service(int fd, void *cookie)
{
    pid_t pid = (pid_t) (uintptr_t) cookie;

    D("entered. fd=%d of pid=%d
", fd, pid);
    while (true) {
        int status;
        pid_t p = waitpid(pid, &status, 0);
        if (p == pid) {
            D("fd=%d, post waitpid(pid=%d) status=%04x
", fd, p, status);
            if (WIFSIGNALED(status)) {
                D("*** Killed by signal %d
", WTERMSIG(status));
                break;
            } else if (!WIFEXITED(status)) {
                D("*** Didn't exit!!. status %d
", status);
                break;
            } else if (WEXITSTATUS(status) >= 0) {
                D("*** Exit code %d
", WEXITSTATUS(status));
                break;
            }
         }
    }
    D("shell exited fd=%d of pid=%d err=%d
", fd, pid, errno);
    if (SHELL_EXIT_NOTIFY_FD >=0) {
      int res;
      res = WriteFdExactly(SHELL_EXIT_NOTIFY_FD, &fd, sizeof(fd)) ?

0 : -1; D("notified shell exit via fd=%d for pid=%d res=%d errno=%d ", SHELL_EXIT_NOTIFY_FD, pid, res, errno); } }

这个函数开启了一线线程,仅仅是在一直waitpid的出错信号。

当adb shell有命令进来比方“ls”,它先到handle_packet函数的A_WRTE命令

    case A_WRTE: /* WRITE(local-id, remote-id, <data>) */
        if (t->online && p->msg.arg0 != 0 && p->msg.arg1 != 0) {
            if((s = find_local_socket(p->msg.arg1, p->msg.arg0))) {//先找到local_socket
                unsigned rid = p->msg.arg0;
                p->len = p->msg.data_length;

                if(s->enqueue(s, p) == 0) {//调用enqueue函数
                    D("Enqueue the socket
");
                    send_ready(s->id, rid, t);
                }
                return;
            }
        }
        break;

enqueue函数就是local_socket_enqueue函数,这个函数就是往service_to_fd写数据

static int local_socket_enqueue(asocket *s, apacket *p)
{
    D("LS(%d): enqueue %d
", s->id, p->len);

    p->ptr = p->data;

        /* if there is already data queue'd, we will receive
        ** events when it's time to write.  just add this to
        ** the tail
        */
    if(s->pkt_first) {
        goto enqueue;
    }

        /* write as much as we can, until we
        ** would block or there is an error/eof
        */
    while(p->len > 0) {
        int r = adb_write(s->fd, p->ptr, p->len);
        if(r > 0) {
            p->len -= r;
            p->ptr += r;
            continue;
        }
        if((r == 0) || (errno != EAGAIN)) {
            D( "LS(%d): not ready, errno=%d: %s
", s->id, errno, strerror(errno) );
            s->close(s);
            return 1; /* not ready (error) */
        } else {
            break;
        }
    }

    if(p->len == 0) {
        put_apacket(p);
        return 0; /* ready for more data */
    }

enqueue:
    p->next = 0;
    if(s->pkt_first) {
        s->pkt_last->next = p;
    } else {
        s->pkt_first = p;
    }
    s->pkt_last = p;

        /* make sure we are notified when we can drain the queue */
    fdevent_add(&s->fde, FDE_WRITE);

    return 1; /* not ready (backlog) */
}

比方"ls"命令就往service_to_fd写。这样create_subproc_pty函数的子进程就标准输入就有数据了,就能够运行cmd命令了

        dup2(pts, STDIN_FILENO);
        dup2(pts, STDOUT_FILENO);
        dup2(pts, STDERR_FILENO);

        adb_close(pts);
        adb_close(ptm);

        execl(cmd, cmd, arg0, arg1, NULL);

运行命令后,又有输出。就到ptm的fd中,也就是service_to_fd中。最后再到Input_thread中读取。


事实上create_subproc_raw函数,使用socketpair更好理解。

static int create_subproc_raw(const char *cmd, const char *arg0, const char *arg1, pid_t *pid)
{
    D("create_subproc_raw(cmd=%s, arg0=%s, arg1=%s)
", cmd, arg0, arg1);
#if defined(_WIN32)
    fprintf(stderr, "error: create_subproc_raw not implemented on Win32 (%s %s %s)
", cmd, arg0, arg1);
    return -1;
#else

    // 0 is parent socket, 1 is child socket
    int sv[2];
    if (adb_socketpair(sv) < 0) {
        printf("[ cannot create socket pair - %s ]
", strerror(errno));
        return -1;
    }
    D("socketpair: (%d,%d)", sv[0], sv[1]);

    *pid = fork();
    if (*pid < 0) {
        printf("- fork failed: %s -
", strerror(errno));
        adb_close(sv[0]);
        adb_close(sv[1]);
        return -1;
    }

    if (*pid == 0) {
        adb_close(sv[0]);
        init_subproc_child();

        dup2(sv[1], STDIN_FILENO);
        dup2(sv[1], STDOUT_FILENO);
        dup2(sv[1], STDERR_FILENO);

        adb_close(sv[1]);

        execl(cmd, cmd, arg0, arg1, NULL);

		D("kangchen create_subproc_raw(cmd=%s, arg0=%s, arg1=%s)
", cmd, arg0, arg1);
		
        fprintf(stderr, "- exec '%s' failed: %s (%d) -
",
                cmd, strerror(errno), errno);
        exit(-1);
    } else {
        adb_close(sv[1]);
        return sv[0];
    }
#endif /* !defined(_WIN32) */
}


二、Input_thread读取local socket的数据,再写入adb驱动


service_to_fd有数据后,会触发函数local_socket_event_func。在这个函数中调用了s->peer->enqueue。然后调用remote_socket_enqueue函数

static int remote_socket_enqueue(asocket *s, apacket *p)
{
    p->msg.command = A_WRTE;
    p->msg.arg0 = s->peer->id;
    p->msg.arg1 = s->id;
    p->msg.data_length = p->len;
    send_packet(p, s->transport);
    return 1;
}

终于调用send_packet函数

void send_packet(apacket *p, atransport *t)
{
    unsigned char *x;
    unsigned sum;
    unsigned count;

    p->msg.magic = p->msg.command ^ 0xffffffff;

    count = p->msg.data_length;
    x = (unsigned char *) p->data;
    sum = 0;
    while(count-- > 0){
        sum += *x++;
    }
    p->msg.data_check = sum;

    print_packet("send", p);

    if (t == NULL) {
        D("Transport is null 
");
        // Zap errno because print_packet() and other stuff have errno effect.
        errno = 0;
        fatal_errno("Transport is null");
    }
    if(write_packet(t->transport_socket, t->serial, &p)){
        fatal_errno("cannot enqueue packet on transport socket");
    }
}

终于还是往transport_socket写数据,然后我们再来看看input_thread线程。

static void *input_thread(void *_t)
{
    atransport *t = reinterpret_cast<atransport*>(_t);
    apacket *p;
    int active = 0;

    D("%s: starting transport input thread, reading from fd %d
",
       t->serial, t->fd);

    for(;;){
        if(read_packet(t->fd, t->serial, &p)) {//transport_socket的还有一端读取数据
            D("%s: failed to read apacket from transport on fd %d
",
               t->serial, t->fd );//出错直接跳出循环,线程结束
            break;
        }
        if(p->msg.command == A_SYNC){
            if(p->msg.arg0 == 0) {
                D("%s: transport SYNC offline
", t->serial);
                put_apacket(p);
                break;
            } else {
                if(p->msg.arg1 == t->sync_token) {
                    D("%s: transport SYNC online
", t->serial);
                    active = 1;
                } else {
                    D("%s: transport ignoring SYNC %d != %d
",
                      t->serial, p->msg.arg1, t->sync_token);
                }
            }
        } else {
            if(active) {
                t->write_to_remote(p, t);//往驱动写
            } else {
                D("%s: transport ignoring packet while offline
", t->serial);
            }
        }

        put_apacket(p);
    }

    // this is necessary to avoid a race condition that occured when a transport closes
    // while a client socket is still active.
    close_all_sockets(t);

    D("%s: transport input thread is exiting, fd %d
", t->serial, t->fd);
    kick_transport(t);
    transport_unref(t);
    return 0;
}

write_to_remote调用的是remote_write函数。来看下remote_write函数:

static int remote_write(apacket *p, atransport *t)
{
    unsigned size = p->msg.data_length;
	
    if(usb_write(t->usb, &p->msg, sizeof(amessage))) {
        D("remote usb: 1 - write terminated
");
        return -1;
    }
    if(p->msg.data_length == 0) return 0;

    if(usb_write(t->usb, &p->data, size)) {
        D("remote usb: 2 - write terminated
");
        return -1;
    }

    return 0;
}

usb_write函数

int usb_write(usb_handle *h, const void *data, int len)
{
    return h->write(h, data, len);
}

然后调用的是usb_adb_write函数:

static int usb_adb_write(usb_handle *h, const void *data, int len)
{
    int n;

    D("about to write (fd=%d, len=%d)
", h->fd, len);
    n = adb_write(h->fd, data, len);
    if(n != len) {
        D("ERROR: fd = %d, n = %d, errno = %d (%s)
",
            h->fd, n, errno, strerror(errno));
        return -1;
    }
    D("[ done fd=%d ]
", h->fd);
    return 0;
}

终于就写入的adb节点的驱动中去了。


三、总结

这篇博客分析了,处理pc端过来的数据,adb驱动中的数据。以及adb root 、adb shell这两个过程。最后再由input_thread写入adb 驱动发送到pc端。


原文地址:https://www.cnblogs.com/wzjhoutai/p/7275765.html