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

转载:http://blog.csdn.net/kc58236582/article/details/51132674


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

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

一、adb主函数

我们先来看下主函数:

[java]  view plain  copy
  1. int main(int argc, char **argv) {  
  2. #if ADB_HOST  
  3.     // adb client/server  
  4.     adb_sysdeps_init();  
  5.     adb_trace_init();  
  6.     D("Handling commandline()\n");  
  7.     return adb_commandline(argc - 1, const_cast<const char**>(argv + 1));  
  8. #else  
  9.     // adbd  
  10.     while (true) {  
  11.         static struct option opts[] = {  
  12.             {"root_seclabel", required_argument, nullptr, 's'},  
  13.             {"device_banner", required_argument, nullptr, 'b'},  
  14.             {"version", no_argument, nullptr, 'v'},  
  15.         };  
  16.   
  17.         int option_index = 0;  
  18.         int c = getopt_long(argc, argv, "", opts, &option_index);  
  19.         if (c == -1)  
  20.             break;  
  21.         switch (c) {  
  22.         case 's':  
  23.             root_seclabel = optarg;  
  24.             break;  
  25.         case 'b':  
  26.             adb_device_banner = optarg;  
  27.             break;  
  28.         case 'v':  
  29.             printf("Android Debug Bridge Daemon version %d.%d.%d %s\n",  
  30.                    ADB_VERSION_MAJOR, ADB_VERSION_MINOR, ADB_SERVER_VERSION,  
  31.                    ADB_REVISION);  
  32.             return 0;  
  33.         default:  
  34.             break;  
  35.         }  
  36.     }  
  37.   
  38.     close_stdin();  
  39.   
  40.     adb_trace_init();  
  41.   
  42.     /* If adbd runs inside the emulator this will enable adb tracing via 
  43.      * adb-debug qemud service in the emulator. */  
  44.     adb_qemu_trace_init();  
  45.   
  46.     D("Handling main()\n");  
  47.     return adb_main(0, DEFAULT_ADB_PORT);  
  48. #endif  

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

adbd主要调用了adb_main方法

[java]  view plain  copy
  1. int adb_main(int is_daemon, int server_port)  
  2. {  
  3. #if !ADB_HOST  
  4.     int port;  
  5.     char value[PROPERTY_VALUE_MAX];  
  6.   
  7.     umask(000);  
  8. #endif  
  9.   
  10.     atexit(adb_cleanup);  
  11. #if defined(_WIN32)  
  12.     SetConsoleCtrlHandler( ctrlc_handler, TRUE );  
  13. #else  
  14.     // No SIGCHLD. Let the service subproc handle its children.  
  15.     signal(SIGPIPE, SIG_IGN);  
  16. #endif  
  17.   
  18.     init_transport_registration();  
  19.   
  20. #if ADB_HOST  
  21.     HOST = 1;  
  22.   
  23. #ifdef WORKAROUND_BUG6558362  
  24.     if(is_daemon) adb_set_affinity();  
  25. #endif  
  26.     usb_init();  
看下adb_main代码我们先看下init_transport_registration函数

[java]  view plain  copy
  1. void init_transport_registration(void)  
  2. {  
  3.     int s[2];  
  4.   
  5.     if(adb_socketpair(s)){//socketpair  
  6.         fatal_errno("cannot open transport registration socketpair");  
  7.     }  
  8.     D("socketpair: (%d,%d)", s[0], s[1]);  
  9.   
  10.     transport_registration_send = s[0];  
  11.     transport_registration_recv = s[1];  
  12.   
  13.     fdevent_install(&transport_registration_fde,  
  14.                     transport_registration_recv,  
  15.                     transport_registration_func,  
  16.                     0);  
  17.   
  18.     fdevent_set(&transport_registration_fde, FDE_READ);  
  19. }  

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


二、usb、adb的驱动初始化

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

继续看上面adb_main的usb_init函数:

[java]  view plain  copy
  1. void usb_init()  
  2. {  
  3.     if (access(USB_FFS_ADB_EP0, F_OK) == 0)  
  4.         usb_ffs_init();  
  5.     else  
  6.         usb_adb_init();  
  7. }  

我们这边调用的是usb_adb_init()

[java]  view plain  copy
  1. static void usb_adb_init()  
  2. {  
  3.     usb_handle* h = reinterpret_cast<usb_handle*>(calloc(1, sizeof(usb_handle)));  
  4.     if (h == nullptr) fatal("couldn't allocate usb_handle");  
  5.   
  6.     h->write = usb_adb_write;  
  7.     h->read = usb_adb_read;  
  8.     h->kick = usb_adb_kick;  
  9.     h->fd = -1;  
  10.   
  11.     adb_cond_init(&h->notify, 0);  
  12.     adb_mutex_init(&h->lock, 0);  
  13.   
  14.     // Open the file /dev/android_adb_enable to trigger  
  15.     // the enabling of the adb USB function in the kernel.  
  16.     // We never touch this file again - just leave it open  
  17.     // indefinitely so the kernel will know when we are running  
  18.     // and when we are not.  
  19.     int fd = unix_open("/dev/android_adb_enable", O_RDWR);//打开android_adb_enable节点只是enableadb usb而已  
  20.     if (fd < 0) {  
  21.        D("failed to open /dev/android_adb_enable\n");  
  22.     } else {  
  23.         close_on_exec(fd);  
  24.     }  
  25.   
  26.     D("[ usb_init - starting thread ]\n");  
  27.     adb_thread_t tid;  
  28.     if(adb_thread_create(&tid, usb_adb_open_thread, h)){  
  29.         fatal_errno("cannot create usb thread");  
  30.     }  
  31. }  

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

[java]  view plain  copy
  1. static void *usb_adb_open_thread(void *x)  
  2. {  
  3.     struct usb_handle *usb = (struct usb_handle *)x;  
  4.     int fd;  
  5.   
  6.     while (true) {  
  7.         // wait until the USB device needs opening  
  8.         adb_mutex_lock(&usb->lock);  
  9.         while (usb->fd != -1)  
  10.             adb_cond_wait(&usb->notify, &usb->lock);  
  11.         adb_mutex_unlock(&usb->lock);  
  12.   
  13.         D("[ usb_thread - opening device ]\n");  
  14.         do {  
  15.             /* XXX use inotify? */  
  16.             fd = unix_open("/dev/android_adb", O_RDWR);//打开adb节点  
  17.             if (fd < 0) {  
  18.                 // to support older kernels  
  19.                 fd = unix_open("/dev/android", O_RDWR);  
  20.             }  
  21.             if (fd < 0) {  
  22.                 adb_sleep_ms(1000);  
  23.             }  
  24.         } while (fd < 0);  
  25.   
  26.         close_on_exec(fd);  
  27.         usb->fd = fd;//节点赋给usb  
  28.   
  29.         D("[ usb_thread - registering device ]\n");  
  30.         register_usb_transport(usb, 001);  
  31.     }  
  32.   
  33.     // never gets here  
  34.     return 0;  
  35. }  

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

[java]  view plain  copy
  1. void register_usb_transport(usb_handle *usb, const char *serial, const char *devpath, unsigned writeable)  
  2. {  
  3.     atransport *t = reinterpret_cast<atransport*>(calloc(1, sizeof(atransport)));  
  4.     if (t == nullptr) fatal("cannot allocate USB atransport");  
  5.     D("transport: %p init'ing for usb_handle %p (sn='%s')\n", t, usb,  
  6.       serial ? serial : "");  
  7.     init_usb_transport(t, usb, (writeable ? CS_OFFLINE : CS_NOPERM));  
  8.     if(serial) {  
  9.         t->serial = strdup(serial);  
  10.     }  
  11.     if(devpath) {  
  12.         t->devpath = strdup(devpath);  
  13.     }  
  14.   
  15.     adb_mutex_lock(&transport_lock);  
  16.     t->next = &pending_list;  
  17.     t->prev = pending_list.prev;  
  18.     t->next->prev = t;  
  19.     t->prev->next = t;  
  20.     adb_mutex_unlock(&transport_lock);  
  21.   
  22.     register_transport(t);  
  23. }  

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

[java]  view plain  copy
  1. static void register_transport(atransport *transport)  
  2. {  
  3.     tmsg m;  
  4.     m.transport = transport;  
  5.     m.action = 1;  
  6.     D("transport: %s registered\n", transport->serial);  
  7.     if(transport_write_action(transport_registration_send, &m)) {  
  8.         fatal_errno("cannot write transport registration socket\n");  
  9.     }  
  10. }  

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

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

[java]  view plain  copy
  1. static int  
  2. transport_write_action(int  fd, struct tmsg*  m)  
  3. {  
  4.     char *p   = (char*)m;  
  5.     int   len = sizeof(*m);  
  6.     int   r;  
  7.   
  8.     while(len > 0) {  
  9.         r = adb_write(fd, p, len);  
  10.         if(r > 0) {  
  11.             len -= r;  
  12.             p   += r;  
  13.         } else {  
  14.             if((r < 0) && (errno == EINTR)) continue;  
  15.             D("transport_write_action: on fd %d, error %d: %s\n",  
  16.               fd, errno, strerror(errno));  
  17. #if !ADB_HOST  
  18.             __android_log_print(ANDROID_LOG_INFO, __FUNCTION__,  
  19.                    "transport_write_action: on fd %d, error %d: %s\n",  
  20.                    fd, errno, strerror(errno));  
  21. #endif  
  22.             return -1;  
  23.         }  
  24.     }  
  25.     return 0;  
  26. }  

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


三、开启线程接受adb数据

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

[java]  view plain  copy
  1. void init_transport_registration(void)  
  2. {  
  3.     int s[2];  
  4.   
  5.     if(adb_socketpair(s)){  
  6.         fatal_errno("cannot open transport registration socketpair");  
  7.     }  
  8.     D("socketpair: (%d,%d)", s[0], s[1]);  
  9.   
  10.     transport_registration_send = s[0];  
  11.     transport_registration_recv = s[1];  
  12.   
  13.     fdevent_install(&transport_registration_fde,  
  14.                     transport_registration_recv,  
  15.                     transport_registration_func,  
  16.                     0);  
  17.   
  18.     fdevent_set(&transport_registration_fde, FDE_READ);  
  19. }  
我们来看下transport_registration_func这个函数

[java]  view plain  copy
  1. static void transport_registration_func(int _fd, unsigned ev, void *data)  
  2. {  
  3.     tmsg m;  
  4.     adb_thread_t output_thread_ptr;  
  5.     adb_thread_t input_thread_ptr;  
  6.     int s[2];  
  7.     atransport *t;  
  8.   
  9.     if(!(ev & FDE_READ)) {  
  10.         return;  
  11.     }  
  12.   
  13.     if(transport_read_action(_fd, &m)) {  
  14.         fatal_errno("cannot read transport registration socket");  
  15.     }  
  16.   
  17.     t = m.transport;  

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

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

[java]  view plain  copy
  1. if (t->connection_state != CS_NOPERM) {  
  2.     /* initial references are the two threads */  
  3.     t->ref_count = 2;  
  4.   
  5.     if(adb_socketpair(s)) {//建立一对socketpair  
  6.         fatal_errno("cannot open transport socketpair");  
  7.     }  
  8.   
  9.     D("transport: %s socketpair: (%d,%d) starting", t->serial, s[0], s[1]);  
  10.   
  11.     t->transport_socket = s[0];  
  12.     t->fd = s[1];  
  13.   
  14.     fdevent_install(&(t->transport_fde),  
  15.                     t->transport_socket,//当transport_socket有数据时,调用transport_socket_events函数  
  16.                     transport_socket_events,  
  17.                     t);  
  18.   
  19.     fdevent_set(&(t->transport_fde), FDE_READ);  
  20.   
  21.     if(adb_thread_create(&input_thread_ptr, input_thread, t)){  
  22.         fatal_errno("cannot create input thread");  
  23.     }  
  24.   
  25.     if(adb_thread_create(&output_thread_ptr, output_thread, t)){  
  26.         fatal_errno("cannot create output thread");  
  27.     }  
  28. }  

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


3.1 output_thread收adb驱动数据

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

[java]  view plain  copy
  1. static void *output_thread(void *_t)  
  2. {  
  3.     atransport *t = reinterpret_cast<atransport*>(_t);  
  4.     apacket *p;  
  5.   
  6.     D("%s: starting transport output thread on fd %d, SYNC online (%d)\n",  
  7.        t->serial, t->fd, t->sync_token + 1);  
  8.     p = get_apacket();  
  9.     p->msg.command = A_SYNC;  
  10.     p->msg.arg0 = 1;  
  11.     p->msg.arg1 = ++(t->sync_token);  
  12.     p->msg.magic = A_SYNC ^ 0xffffffff;  
  13.     if(write_packet(t->fd, t->serial, &p)) {  
  14.         put_apacket(p);  
  15.         D("%s: failed to write SYNC packet\n", t->serial);  
  16.         goto oops;  
  17.     }  
  18.   
  19.     D("%s: data pump started\n", t->serial);  
  20.     for(;;) {  
  21.         p = get_apacket();//这个函数只是分配内存  
  22.         if(t->read_from_remote(p, t) == 0){//这里是从adb驱动读取数据  
  23.   
  24.             if(write_packet(t->fd, t->serial, &p)){//这是是socketpair的一端写数据  
  25.                 put_apacket(p);  
  26.                 D("%s: failed to write apacket to transport\n", t->serial);  
  27.                 goto oops;  
  28.             }  
  29.         } else {  
  30.             D("%s: remote read failed for transport\n", t->serial);  
  31.             put_apacket(p);//出现异常,释放内存,跳出线程循环  
  32.             break;  
  33.         }  
  34.     }  
  35.   
  36.     D("%s: SYNC offline for transport\n", t->serial);  
  37.     p = get_apacket();  
  38.     p->msg.command = A_SYNC;//读取adb节点异常退出线程  
  39.     p->msg.arg0 = 0;  
  40.     p->msg.arg1 = 0;  
  41.     p->msg.magic = A_SYNC ^ 0xffffffff;  
  42.     if(write_packet(t->fd, t->serial, &p)) {  
  43.         put_apacket(p);  
  44.         D("%s: failed to write SYNC apacket to transport", t->serial);  
  45.     }  
  46.   
  47. oops:  
  48.     D("%s: transport output thread is exiting\n", t->serial);  
  49.     kick_transport(t);  
  50.     transport_unref(t);  
  51.     return 0;  
  52. }  

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

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

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

[java]  view plain  copy
  1. void init_usb_transport(atransport *t, usb_handle *h, int state)  
  2. {  
  3.     D("transport: usb\n");  
  4.     t->close = remote_close;  
  5.     t->kick = remote_kick;  
  6.     t->read_from_remote = remote_read;  
  7.     t->write_to_remote = remote_write;  
  8.     t->sync_token = 1;  
  9.     t->connection_state = state;  
  10.     t->type = kTransportUsb;  
  11.     t->usb = h;  
  12.   
  13. #if ADB_HOST  
  14.     HOST = 1;  
  15. #else  
  16.     HOST = 0;  
  17. #endif  
  18. }  
read_from_remote 函数也就是remote_read函数:

[java]  view plain  copy
  1. static int remote_read(apacket *p, atransport *t)  
  2. {  
  3.     if(usb_read(t->usb, &p->msg, sizeof(amessage))){//这里就是从adb驱动读数据了  
  4.         D("remote usb: read terminated (message)\n");  
  5.         return -1;  
  6.     }  
  7.   
  8.     if(check_header(p)) {//检查头部  
  9.         D("remote usb: check_header failed\n");  
  10.         return -1;  
  11.     }  
  12.   
  13.     if(p->msg.data_length) {  
  14.         if(usb_read(t->usb, p->data, p->msg.data_length)){  
  15.             D("remote usb: terminated (data)\n");  
  16.             return -1;  
  17.         }  
  18.     }  
  19.   
  20.     if(check_data(p)) {//查数据  
  21.         D("remote usb: check_data failed\n");  
  22.         return -1;  
  23.     }  
  24.   
  25.   
  26.     return 0;  
  27. }  

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

[java]  view plain  copy
  1. static void usb_adb_init()  
  2. {  
  3.     usb_handle* h = reinterpret_cast<usb_handle*>(calloc(1, sizeof(usb_handle)));  
  4.     if (h == nullptr) fatal("couldn't allocate usb_handle");  
  5.   
  6.     h->write = usb_adb_write;  
  7.     h->read = usb_adb_read;  
  8.     h->kick = usb_adb_kick;  
  9.     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驱动节点)

[cpp]  view plain  copy
  1. static int usb_adb_read(usb_handle *h, void *data, int len)  
  2. {  
  3.     int n;  
  4.   
  5.     D("about to read (fd=%d, len=%d)\n", h->fd, len);  
  6.     n = adb_read(h->fd, data, len);  
  7.     if(n != len) {  
  8.         D("ERROR: fd = %d, n = %d, errno = %d (%s)\n",  
  9.             h->fd, n, errno, strerror(errno));  
  10.         for (int i = 0; i < n; i++) {  
  11.             char print = (char)*((char*)data + i);  
  12.             LOG("%x ", print);  
  13.         }  
  14.         return -1;  
  15.     }  
  16.     D("[ done fd=%d ]\n", h->fd);  
  17.     return 0;  
  18. }  


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

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

这会导致socketpair的另一侧有数据,另一侧有数据会调用transport_socket_events函数来处理数据

[java]  view plain  copy
  1. static void transport_socket_events(int fd, unsigned events, void *_t)  
  2. {  
  3.     atransport *t = reinterpret_cast<atransport*>(_t);  
  4.     D("transport_socket_events(fd=%d, events=%04x,...)\n", fd, events);  
  5.     if(events & FDE_READ){  
  6.         apacket *p = 0;  
  7.         if(read_packet(fd, t->serial, &p)){  
  8.             D("%s: failed to read packet from transport socket on fd %d\n", t->serial, fd);  
  9.         } else {  
  10.             handle_packet(p, (atransport *) _t);  
  11.         }  
  12.     }  
  13. }  


四、总结

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

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

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值