android6.0 adbd深入分析(一)adb驱动初始化、读取adb节点线程
2016-04-12 16:12
1026 查看
adbd之前看过一次,觉得代码太复杂然后,又是adb client adb server adbd交织在一起感觉看起来太累,最近项目需要把它大致看完了,梳理下,感觉从adbd能学到很多东西,在此总结下,adbd的代码。
我只分析我看懂了,不可能面面俱到。而且主要注重在通信方面,以及一些命令处理等。
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函数
调用了socketpair,一端有数据后会调用transport_registration_func函数,我们先来看下什么时候transport_registration_recv会有数据过来,也就要看下transport_registration_send 什么时候会有数据发送。
继续看上面adb_main的usb_init函数:
我们这边调用的是usb_adb_init()
这个函数中打开android_adb_enable节点只是enableadb usb而已,之后开了一个线程调用usb_adb_open_thread
这个函数中主要打开adb节点,调用register_usb_transport函数来注册usb传输。
这个函数先调用了init_usb_transport函数,把atransport初始化了,并且把usb_handle也赋给它了,我们主要看下register_transport函数。
这个函数把atransport 封装起来,传出去了,我们来看下transport_write_action函数,我们注意看第一个参数transport_registration_send就是我们之前的sockpair的send端
transport_write_action函数就是把transport发给transport_registration_recv端。
这样当读到adb驱动节点后,会把驱动传输的transport传给transport_registration_recv端,接下来我们就看下这块代码。
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这个函数
它先调用了transport_read_action来读取transport_registration_recv的数据,也就是之前transport_registration_send发来的adb驱动节点的数据。然后把它保存在t这个变量中。
下面我们再来看看transport_registration_func函数中的另一段代码
上面这段代码建立了一对socketpair,然后开启了两个线程,我们来看下这两个线程
这个线程主要是从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函数:
在之前usb_adb_init函数中有如下代码:
因此最后调用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;
}
这会导致socketpair的另一侧有数据,另一侧有数据会调用transport_socket_events函数来处理数据
处理数据部分我们在下篇博客继续分析。
我只分析我看懂了,不可能面面俱到。而且主要注重在通信方面,以及一些命令处理等。
一、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驱动节点的内容。处理数据部分我们在下篇博客继续分析。
相关文章推荐
- adb无线调试真机
- ADB运行框架原理解析
- recovery user版本adbd具有root权限
- android6.0 adbd深入分析(五)adbd处理adb root的一个bug
- android6.0 adbd深入分析(四)adbd usb线拔掉再连接的过程
- android6.0 adbd深入分析(三)adb root重启adbd流程
- android6.0 adbd深入分析(二)adb驱动数据的处理、写数据到adb驱动节点
- Android ADB工具 adb,adbd,client,server之间的关系
- Android 源码集合
- Android-ClockView
- android shape的使用
- android studio 安装(mac)
- android(NDK+JNI)---NDK 编译和使用静态库、动态库
- Android Studio 使用
- Fragment创建多个fragment实例
- Android中的Intent Filter匹配规则简介
- Android性能优化
- Android 自定义Cursor详解
- android(NDK+JNI)---NDK开发 环境配置
- Java(Android)线程池