android6.0 adbd深入分析(一)adb驱动初始化、读取adb节点线程

adbd之前看过一次,觉得代码太复杂然后,又是adb client  adb server adbd交织在一起感觉看起来太累,最近项目需要把它大致看完了,梳理下,感觉从adbd能学到很多东西,在此总结下,adbd的代码。

我只分析我看懂了,不可能面面俱到。而且主要注重在通信方面,以及一些命令处理等。

一、adb主函数

我们先来看下主函数:

int main(int argc, char **argv) {
#if ADB_HOST
    // adb client/server
    adb_sysdeps_init();
    adb_trace_init();
    D("Handling commandline()\n");
    return adb_commandline(argc - 1, const_cast<const char**>(argv + 1));
#else
    // adbd
    while (true) {
        static struct option opts[] = {
            {"root_seclabel", required_argument, nullptr, 's'},
            {"device_banner", required_argument, nullptr, 'b'},
            {"version", no_argument, nullptr, 'v'},
        };

        int option_index = 0;
        int c = getopt_long(argc, argv, "", opts, &option_index);
        if (c == -1)
            break;
        switch (c) {
        case 's':
            root_seclabel = optarg;
            break;
        case 'b':
            adb_device_banner = optarg;
            break;
        case 'v':
            printf("Android Debug Bridge Daemon version %d.%d.%d %s\n",
                   ADB_VERSION_MAJOR, ADB_VERSION_MINOR, ADB_SERVER_VERSION,
                   ADB_REVISION);
            return 0;
        default:
            break;
        }
    }

    close_stdin();

    adb_trace_init();

    /* If adbd runs inside the emulator this will enable adb tracing via
     * adb-debug qemud service in the emulator. */
    adb_qemu_trace_init();

    D("Handling main()\n");
    return adb_main(0, DEFAULT_ADB_PORT);
#endif

ADB_HOST宏直接用来区分是pc上的还是手机上的,pc上的直接用adb_commandline函数处理各种命令,我们就不看了,我们主要分析adbd。

adbd主要调用了adb_main方法

int adb_main(int is_daemon, int server_port)
{
#if !ADB_HOST
    int port;
    char value[PROPERTY_VALUE_MAX];

    umask(000);
#endif

    atexit(adb_cleanup);
#if defined(_WIN32)
    SetConsoleCtrlHandler( ctrlc_handler, TRUE );
#else
    // No SIGCHLD. Let the service subproc handle its children.
    signal(SIGPIPE, SIG_IGN);
#endif

    init_transport_registration();

#if ADB_HOST
    HOST = 1;

#ifdef WORKAROUND_BUG6558362
    if(is_daemon) adb_set_affinity();
#endif
    usb_init();
看下adb_main代码我们先看下init_transport_registration函数

void init_transport_registration(void)
{
    int s[2];

    if(adb_socketpair(s)){//socketpair
        fatal_errno("cannot open transport registration socketpair");
    }
    D("socketpair: (%d,%d)", s[0], s[1]);

    transport_registration_send = s[0];
    transport_registration_recv = s[1];

    fdevent_install(&transport_registration_fde,
                    transport_registration_recv,
                    transport_registration_func,
                    0);

    fdevent_set(&transport_registration_fde, FDE_READ);
}

调用了socketpair,一端有数据后会调用transport_registration_func函数,我们先来看下什么时候transport_registration_recv会有数据过来,也就要看下transport_registration_send 什么时候会有数据发送。


二、usb、adb的驱动初始化

下面我们再来看下adb驱动的节点的初始化

继续看上面adb_main的usb_init函数:

void usb_init()
{
    if (access(USB_FFS_ADB_EP0, F_OK) == 0)
        usb_ffs_init();
    else
        usb_adb_init();
}

我们这边调用的是usb_adb_init()

static void usb_adb_init()
{
    usb_handle* h = reinterpret_cast<usb_handle*>(calloc(1, sizeof(usb_handle)));
    if (h == nullptr) fatal("couldn't allocate usb_handle");

    h->write = usb_adb_write;
    h->read = usb_adb_read;
    h->kick = usb_adb_kick;
    h->fd = -1;

    adb_cond_init(&h->notify, 0);
    adb_mutex_init(&h->lock, 0);

    // Open the file /dev/android_adb_enable to trigger
    // the enabling of the adb USB function in the kernel.
    // We never touch this file again - just leave it open
    // indefinitely so the kernel will know when we are running
    // and when we are not.
    int fd = unix_open("/dev/android_adb_enable", O_RDWR);//打开android_adb_enable节点只是enableadb usb而已
    if (fd < 0) {
       D("failed to open /dev/android_adb_enable\n");
    } else {
        close_on_exec(fd);
    }

    D("[ usb_init - starting thread ]\n");
    adb_thread_t tid;
    if(adb_thread_create(&tid, usb_adb_open_thread, h)){
        fatal_errno("cannot create usb thread");
    }
}

这个函数中打开android_adb_enable节点只是enableadb usb而已,之后开了一个线程调用usb_adb_open_thread

static void *usb_adb_open_thread(void *x)
{
    struct usb_handle *usb = (struct usb_handle *)x;
    int fd;

    while (true) {
        // wait until the USB device needs opening
        adb_mutex_lock(&usb->lock);
        while (usb->fd != -1)
            adb_cond_wait(&usb->notify, &usb->lock);
        adb_mutex_unlock(&usb->lock);

        D("[ usb_thread - opening device ]\n");
        do {
            /* XXX use inotify? */
            fd = unix_open("/dev/android_adb", O_RDWR);//打开adb节点
            if (fd < 0) {
                // to support older kernels
                fd = unix_open("/dev/android", O_RDWR);
            }
            if (fd < 0) {
                adb_sleep_ms(1000);
            }
        } while (fd < 0);

        close_on_exec(fd);
        usb->fd = fd;//节点赋给usb

        D("[ usb_thread - registering device ]\n");
        register_usb_transport(usb, 0, 0, 1);
    }

    // never gets here
    return 0;
}

这个函数中主要打开adb节点,调用register_usb_transport函数来注册usb传输。

void register_usb_transport(usb_handle *usb, const char *serial, const char *devpath, unsigned writeable)
{
    atransport *t = reinterpret_cast<atransport*>(calloc(1, sizeof(atransport)));
    if (t == nullptr) fatal("cannot allocate USB atransport");
    D("transport: %p init'ing for usb_handle %p (sn='%s')\n", t, usb,
      serial ? serial : "");
    init_usb_transport(t, usb, (writeable ? CS_OFFLINE : CS_NOPERM));
    if(serial) {
        t->serial = strdup(serial);
    }
    if(devpath) {
        t->devpath = strdup(devpath);
    }

    adb_mutex_lock(&transport_lock);
    t->next = &pending_list;
    t->prev = pending_list.prev;
    t->next->prev = t;
    t->prev->next = t;
    adb_mutex_unlock(&transport_lock);

    register_transport(t);
}

这个函数先调用了init_usb_transport函数,把atransport初始化了,并且把usb_handle也赋给它了,我们主要看下register_transport函数。

static void register_transport(atransport *transport)
{
    tmsg m;
    m.transport = transport;
    m.action = 1;
    D("transport: %s registered\n", transport->serial);
    if(transport_write_action(transport_registration_send, &m)) {
        fatal_errno("cannot write transport registration socket\n");
    }
}

这个函数把atransport 封装起来,传出去了,我们来看下transport_write_action函数,我们注意看第一个参数transport_registration_send就是我们之前的sockpair的send端

transport_write_action函数就是把transport发给transport_registration_recv端。

static int
transport_write_action(int  fd, struct tmsg*  m)
{
    char *p   = (char*)m;
    int   len = sizeof(*m);
    int   r;

    while(len > 0) {
        r = adb_write(fd, p, len);
        if(r > 0) {
            len -= r;
            p   += r;
        } else {
            if((r < 0) && (errno == EINTR)) continue;
            D("transport_write_action: on fd %d, error %d: %s\n",
              fd, errno, strerror(errno));
#if !ADB_HOST
            __android_log_print(ANDROID_LOG_INFO, __FUNCTION__,
                   "transport_write_action: on fd %d, error %d: %s\n",
                   fd, errno, strerror(errno));
#endif
            return -1;
        }
    }
    return 0;
}

这样当读到adb驱动节点后,会把驱动传输的transport传给transport_registration_recv端,接下来我们就看下这块代码。


三、开启线程接受adb数据

还记得我们前面分析的这个函数嘛,当transport_registration_recv有数据时,就会调用transport_registration_func函数

void init_transport_registration(void)
{
    int s[2];

    if(adb_socketpair(s)){
        fatal_errno("cannot open transport registration socketpair");
    }
    D("socketpair: (%d,%d)", s[0], s[1]);

    transport_registration_send = s[0];
    transport_registration_recv = s[1];

    fdevent_install(&transport_registration_fde,
                    transport_registration_recv,
                    transport_registration_func,
                    0);

    fdevent_set(&transport_registration_fde, FDE_READ);
}
我们来看下transport_registration_func这个函数

static void transport_registration_func(int _fd, unsigned ev, void *data)
{
    tmsg m;
    adb_thread_t output_thread_ptr;
    adb_thread_t input_thread_ptr;
    int s[2];
    atransport *t;

    if(!(ev & FDE_READ)) {
        return;
    }

    if(transport_read_action(_fd, &m)) {
        fatal_errno("cannot read transport registration socket");
    }

    t = m.transport;

它先调用了transport_read_action来读取transport_registration_recv的数据,也就是之前transport_registration_send发来的adb驱动节点的数据。然后把它保存在t这个变量中。

下面我们再来看看transport_registration_func函数中的另一段代码

    if (t->connection_state != CS_NOPERM) {
        /* initial references are the two threads */
        t->ref_count = 2;

        if(adb_socketpair(s)) {//建立一对socketpair
            fatal_errno("cannot open transport socketpair");
        }

        D("transport: %s socketpair: (%d,%d) starting", t->serial, s[0], s[1]);

        t->transport_socket = s[0];
        t->fd = s[1];

        fdevent_install(&(t->transport_fde),
                        t->transport_socket,//当transport_socket有数据时,调用transport_socket_events函数
                        transport_socket_events,
                        t);

        fdevent_set(&(t->transport_fde), FDE_READ);

        if(adb_thread_create(&input_thread_ptr, input_thread, t)){
            fatal_errno("cannot create input thread");
        }

        if(adb_thread_create(&output_thread_ptr, output_thread, t)){
            fatal_errno("cannot create output thread");
        }
    }

上面这段代码建立了一对socketpair,然后开启了两个线程,我们来看下这两个线程


3.1 output_thread收adb驱动数据

我们先来看下output_thread这个线程:

static void *output_thread(void *_t)
{
    atransport *t = reinterpret_cast<atransport*>(_t);
    apacket *p;

    D("%s: starting transport output thread on fd %d, SYNC online (%d)\n",
       t->serial, t->fd, t->sync_token + 1);
    p = get_apacket();
    p->msg.command = A_SYNC;
    p->msg.arg0 = 1;
    p->msg.arg1 = ++(t->sync_token);
    p->msg.magic = A_SYNC ^ 0xffffffff;
    if(write_packet(t->fd, t->serial, &p)) {
        put_apacket(p);
        D("%s: failed to write SYNC packet\n", t->serial);
        goto oops;
    }

    D("%s: data pump started\n", t->serial);
    for(;;) {
        p = get_apacket();//这个函数只是分配内存
        if(t->read_from_remote(p, t) == 0){//这里是从adb驱动读取数据

            if(write_packet(t->fd, t->serial, &p)){//这是是socketpair的一端写数据
                put_apacket(p);
                D("%s: failed to write apacket to transport\n", t->serial);
                goto oops;
            }
        } else {
            D("%s: remote read failed for transport\n", t->serial);
            put_apacket(p);//出现异常,释放内存,跳出线程循环
            break;
        }
    }

    D("%s: SYNC offline for transport\n", t->serial);
    p = get_apacket();
    p->msg.command = A_SYNC;//读取adb节点异常退出线程
    p->msg.arg0 = 0;
    p->msg.arg1 = 0;
    p->msg.magic = A_SYNC ^ 0xffffffff;
    if(write_packet(t->fd, t->serial, &p)) {
        put_apacket(p);
        D("%s: failed to write SYNC apacket to transport", t->serial);
    }

oops:
    D("%s: transport output thread is exiting\n", t->serial);
    kick_transport(t);
    transport_unref(t);
    return 0;
}

这个线程主要是从adb驱动读取数据,然后让socketpair的一端写入 从adb驱动读取的数据。

我们先看下read_from_remote这个函数,跟下如何从adb驱动读取数据的

在之前register_usb_transport的时候先调用了init_usb_transport,来初始化transport的一些函数等。

void init_usb_transport(atransport *t, usb_handle *h, int state)
{
    D("transport: usb\n");
    t->close = remote_close;
    t->kick = remote_kick;
    t->read_from_remote = remote_read;
    t->write_to_remote = remote_write;
    t->sync_token = 1;
    t->connection_state = state;
    t->type = kTransportUsb;
    t->usb = h;

#if ADB_HOST
    HOST = 1;
#else
    HOST = 0;
#endif
}
read_from_remote 函数也就是remote_read函数:

static int remote_read(apacket *p, atransport *t)
{
    if(usb_read(t->usb, &p->msg, sizeof(amessage))){//这里就是从adb驱动读数据了
        D("remote usb: read terminated (message)\n");
        return -1;
    }

    if(check_header(p)) {//检查头部
        D("remote usb: check_header failed\n");
        return -1;
    }

    if(p->msg.data_length) {
        if(usb_read(t->usb, p->data, p->msg.data_length)){
            D("remote usb: terminated (data)\n");
            return -1;
        }
    }

    if(check_data(p)) {//查数据
        D("remote usb: check_data failed\n");
        return -1;
    }


    return 0;
}

在之前usb_adb_init函数中有如下代码:

static void usb_adb_init()
{
    usb_handle* h = reinterpret_cast<usb_handle*>(calloc(1, sizeof(usb_handle)));
    if (h == nullptr) fatal("couldn't allocate usb_handle");

    h->write = usb_adb_write;
    h->read = usb_adb_read;
    h->kick = usb_adb_kick;
    h->fd = -1;

因此最后调用read是调用了usb_adb_read函数,也就是读adb驱动里的内容。

usb_adb_read函数就是调用adb_read读取adb驱动数据,而adb_read就是从h->fd中去读取adb驱动数据。这个h->fd就是前面usb_adb_open_thread函数中打开/dev/android_adb(adb驱动节点)

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

    D("about to read (fd=%d, len=%d)\n", h->fd, len);
    n = adb_read(h->fd, data, len);
    if(n != len) {
        D("ERROR: fd = %d, n = %d, errno = %d (%s)\n",
            h->fd, n, errno, strerror(errno));
        for (int i = 0; i < n; i++) {
            char print = (char)*((char*)data + i);
            LOG("%x ", print);
        }
        return -1;
    }
    D("[ done fd=%d ]\n", h->fd);
    return 0;
}


3.2 output_thread数据发送数据后,处理数据

在output_thread中,读取了adb驱动的数据后,就调用write_packet(t->fd, t->serial, &p)函数,把数据网socketpair的一侧写。

这会导致socketpair的另一侧有数据,另一侧有数据会调用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,...)\n", 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\n", t->serial, fd);
        } else {
            handle_packet(p, (atransport *) _t);
        }
    }
}


四、总结

我们主要分析了adb驱动节点初始化,驱动节点开启成功后会开启线程读取adb驱动节点的内容。

处理数据部分我们在下篇博客继续分析。







  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值