本篇以“adb devices"命令为例,跟踪代码的执行流程。
(1) main()->
(2)adb_commandline()->
adb_commandline()中的相关源码:
if(!strcmp(argv[0], "devices")) { char *tmp; char *listopt; if (argc < 2) listopt = ""; else if (argc == 2 && !strcmp(argv[1], "-l")) listopt = argv[1]; else { fprintf(stderr, "Usage: adb devices [-l]\n"); return 1; } snprintf(buf, sizeof buf, "host:%s%s", argv[0], listopt); tmp = adb_query(buf); //传递的buf=”host:devices” if(tmp) { //命令执行成功,打印出信息 printf("List of devices attached \n"); printf("%s\n", tmp); return 0; } else {///失败 return 1; } }(3) adb_query():adb_query: host:devices ->
char *adb_query(const char *service) //函数返回设备信息字符串 { char buf[5]; unsigned n; char *tmp; D("adb_query: %s\n", service); int fd = adb_connect(service); //连接adbserver,返回fd if(fd < 0) { fprintf(stderr,"error: %s\n", __adb_error); return 0; } if(readx(fd, buf, 4)) goto oops; //读取数据长度,如果失败则返回错误 buf[4] = 0; n = strtoul(buf, 0, 16); //转换成数值 if(n > 1024) goto oops; tmp = malloc(n + 1); //申请空间 if(tmp == 0) goto oops; if(readx(fd, tmp, n) == 0) { //读取信息并返回 tmp[n] = 0; adb_close(fd); return tmp; } free(tmp); oops: adb_close(fd); return 0; }
(4) adb_connect()->
这个函数的作用是连接adb server,如果adb server没有启动则先启动它。
int adb_connect(const char *service) { // first query the adb server's version int fd = _adb_connect("host:version"); //查询adb server的版本信息,用来判断它是否启动。 D("adb_connect: service %s\n", service); if(fd == -2) { //查询不到adb server fprintf(stdout,"* daemon not running. starting it now on port %d *\n", __adb_server_port); start_server: //启动adb server if(launch_server(__adb_server_port)) { //启动adb server失败 fprintf(stderr,"* failed to start daemon *\n"); return -1; } else { fprintf(stdout,"* daemon started successfully *\n"); } /* give the server some time to start properly and detect devices */ adb_sleep_ms(3000); // fall through to _adb_connect } else {//查询到adb server版本信息,说明adb server 已经启动 // if server was running, check its version to make sure it is not out of date char buf[100]; int n; int version = ADB_SERVER_VERSION - 1; // if we have a file descriptor, then parse version result if(fd >= 0) { if(readx(fd, buf, 4)) goto error; //读取版本信息的长度 buf[4] = 0; n = strtoul(buf, 0, 16); if(n > (int)sizeof(buf)) goto error; if(readx(fd, buf, n)) goto error;//读取版本信息 adb_close(fd); if (sscanf(buf, "%04x", &version) != 1) goto error;//转换字符串的版本为数值型 } else { //fd返回的值表示adb server可能不支持读取版本信息 // if fd is -1, then check for "unknown host service", // which would indicate a version of adb that does not support the version command if (strcmp(__adb_error, "unknown host service") != 0) return fd; //返回错误。 } if(version != ADB_SERVER_VERSION) { printf("adb server is out of date. killing...\n"); fd = _adb_connect("host:kill"); adb_close(fd); /* XXX can we better detect its death? */ adb_sleep_ms(2000); goto start_server; //版本信息过期则关闭adb server并重新启动。 } } // if the command is start-server, we are done. if (!strcmp(service, "host:start-server")) //如果命令是start-server,执行到这就可以了 return 0; //下面的代码连接adb server并返回fd。 fd = _adb_connect(service); //连接adb server 并返回fd。 if(fd == -2) { fprintf(stderr,"** daemon still not running"); } D("adb_connect: return fd %d\n", fd); return fd; error: adb_close(fd); return -1; }
(5) launch_server()
#if ADB_HOST int launch_server(int server_port) { #ifdef HAVE_WIN32_PROC /* we need to start the server in the background */ /* we create a PIPE that will be used to wait for the server's "OK" */ /* message since the pipe handles must be inheritable, we use a */ /* security attribute */ HANDLE pipe_read, pipe_write; SECURITY_ATTRIBUTES sa; STARTUPINFO startup; PROCESS_INFORMATION pinfo; char program_path[ MAX_PATH ]; int ret; sa.nLength = sizeof(sa); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = TRUE; /* create pipe, and ensure its read handle isn't inheritable */ ret = CreatePipe( &pipe_read, &pipe_write, &sa, 0 ); if (!ret) { fprintf(stderr, "CreatePipe() failure, error %ld\n", GetLastError() ); return -1; } SetHandleInformation( pipe_read, HANDLE_FLAG_INHERIT, 0 ); ZeroMemory( &startup, sizeof(startup) ); startup.cb = sizeof(startup); startup.hStdInput = GetStdHandle( STD_INPUT_HANDLE ); startup.hStdOutput = pipe_write; startup.hStdError = GetStdHandle( STD_ERROR_HANDLE ); startup.dwFlags = STARTF_USESTDHANDLES; ZeroMemory( &pinfo, sizeof(pinfo) ); /* get path of current program */ GetModuleFileName( NULL, program_path, sizeof(program_path) ); //创建进程“adb fork-server server”,并把startup信息传给新进程。 ret = CreateProcess( program_path, /* program path */ "adb fork-server server", /* the fork-server argument will set the debug = 2 in the child */ NULL, /* process handle is not inheritable */ NULL, /* thread handle is not inheritable */ TRUE, /* yes, inherit some handles */ DETACHED_PROCESS, /* the new process doesn't have a console */ NULL, /* use parent's environment block */ NULL, /* use parent's starting directory */ &startup, /* startup info, i.e. std handles */ &pinfo ); CloseHandle( pipe_write ); if (!ret) { fprintf(stderr, "CreateProcess failure, error %ld\n", GetLastError() ); CloseHandle( pipe_read ); return -1; } CloseHandle( pinfo.hProcess ); CloseHandle( pinfo.hThread ); /* wait for the "OK\n" message */ { char temp[3]; DWORD count; //等待新进程发送“OK”到pipe_read管道。 ret = ReadFile( pipe_read, temp, 3, &count, NULL ); CloseHandle( pipe_read ); if ( !ret ) { fprintf(stderr, "could not read ok from ADB Server, error = %ld\n", GetLastError() ); return -1; } if (count != 3 || temp[0] != 'O' || temp[1] != 'K' || temp[2] != '\n') { fprintf(stderr, "ADB server didn't ACK\n" ); return -1; } } #elif defined(HAVE_FORKEXEC) char path[PATH_MAX]; int fd[2]; // set up a pipe so the child can tell us when it is ready. // fd[0] will be parent's end, and fd[1] will get mapped to stderr in the child. if (pipe(fd)) { fprintf(stderr, "pipe failed in launch_server, errno: %d\n", errno); return -1; } get_my_path(path, PATH_MAX); pid_t pid = fork(); if(pid < 0) return -1; if (pid == 0) { //下面的代码在子进程中运行 // child side of the fork // redirect stderr to the pipe // we use stderr instead of stdout due to stdout's buffering behavior. adb_close(fd[0]); dup2(fd[1], STDERR_FILENO); //重定向新进程的错误信息给fd[1] adb_close(fd[1]); // child process 运行”adb fok-server server”程序。 int result = execl(path, "adb", "fork-server", "server", NULL); // this should not return fprintf(stderr, "OOPS! execl returned %d, errno: %d\n", result, errno); } else {//下面的代码还是在这个进程中执行 // parent side of the fork char temp[3]; temp[0] = 'A'; temp[1] = 'B'; temp[2] = 'C'; // wait for the "OK\n" message adb_close(fd[1]); int ret = adb_read(fd[0], temp, 3); //等待新进程发送“OK”字符串。 int saved_errno = errno; adb_close(fd[0]); if (ret < 0) { fprintf(stderr, "could not read ok from ADB Server, errno = %d\n", saved_errno); return -1; } if (ret != 3 || temp[0] != 'O' || temp[1] != 'K' || temp[2] != '\n') {//接收字符错误。 fprintf(stderr, "ADB server didn't ACK\n" ); return -1; } setsid(); } #else #error "cannot implement background server start on this platform" #endif return 0; } #endif
再来看看”adb fork-server server”的运行。
(1) main()->adb_commandline();
/* modifiers and flags */ while(argc > 0) { if(!strcmp(argv[0],"server")) { is_server = 1; } else if(!strcmp(argv[0],"nodaemon")) { no_daemon = 1; } else if (!strcmp(argv[0], "fork-server")) { /* this is a special flag used only when the ADB client launches the ADB Server */ is_daemon = 1; } else if(!strcmp(argv[0],"persist")) { persist = 1; } else if(!strncmp(argv[0], "-p", 2)) { const char *product = NULL; if (argv[0][2] == '\0') { if (argc < 2) return usage(); product = argv[1]; argc--; argv++; } else { product = argv[0] + 2; } gProductOutPath = find_product_out_path(product); if (gProductOutPath == NULL) { fprintf(stderr, "adb: could not resolve \"-p %s\"\n", product); return usage(); } } else if (argv[0][0]=='-' && argv[0][1]=='s') { if (isdigit(argv[0][2])) { serial = argv[0] + 2; } else { if(argc < 2 || argv[0][2] != '\0') return usage(); serial = argv[1]; argc--; argv++; } } else if (!strcmp(argv[0],"-d")) { ttype = kTransportUsb; } else if (!strcmp(argv[0],"-e")) { ttype = kTransportLocal; } else { /* out of recognized modifiers and flags */ break; } argc--; argv++; } adb_set_transport(ttype, serial); adb_set_tcp_specifics(server_port); if (is_server) { if (no_daemon || is_daemon) { r = adb_main(is_daemon, server_port); } else { r = launch_server(server_port); } if(r) { fprintf(stderr,"* could not start server *\n"); } return r; }这里将is_daemon和is_server都置为1,并调用adb_main(1, 5037);
(2) adb_main()
int adb_main(int is_daemon, int server_port) { #if ADB_HOST HOST = 1; usb_vendors_init(); usb_init(); //监听USB端口数据 local_init(DEFAULT_ADB_LOCAL_TRANSPORT_PORT); //初始化建立5555网口信道 adb_auth_init(); char local_name[30]; build_local_name(local_name, sizeof(local_name), server_port); //监听5037端口 if(install_listener(local_name, "*smartsocket*", NULL)) { exit(1); } #else … #endif if (is_daemon) { // inform our parent that we are up and running. //发送“OK”给父进程 #ifdef HAVE_WIN32_PROC DWORD count; WriteFile( GetStdHandle( STD_OUTPUT_HANDLE ), "OK\n", 3, &count, NULL ); #elif defined(HAVE_FORKEXEC) fprintf(stderr, "OK\n"); #endif start_logging(); } D("Event loop starting\n"); fdevent_loop(); usb_cleanup(); return 0; }
(3) usb_linux.c中的usb_init()
void usb_init() { adb_thread_t tid; struct sigaction actions; memset(&actions, 0, sizeof(actions)); sigemptyset(&actions.sa_mask); actions.sa_flags = 0; actions.sa_handler = sigalrm_handler; sigaction(SIGALRM,& actions, NULL); if(adb_thread_create(&tid, device_poll_thread, NULL)){ fatal_errno("cannot create input thread"); } } void* device_poll_thread(void* unused) { D("Created device thread\n"); for(;;) { /* XXX use inotify */ find_usb_device("/dev/bus/usb", register_device); kick_disconnected_devices(); sleep(1); } return NULL; }在register_device()函数中最终会调用register_usb_transport()。
(4) install_listener(local_name, "*smartsocket*", NULL)
if(!strcmp(l->connect_to, "*smartsocket*")) { fdevent_install(&l->fde, l->fd, ss_listener_event_func, l); } else { fdevent_install(&l->fde, l->fd, listener_event_func, l); } fdevent_set(&l->fde, FDE_READ);
(5) ss_listener_event_func分析
static void ss_listener_event_func(int _fd, unsigned ev, void *_l) { asocket *s; if(ev & FDE_READ) { struct sockaddr addr; socklen_t alen; int fd; alen = sizeof(addr); fd = adb_socket_accept(_fd, &addr, &alen); //接受客户端的连接 if(fd < 0) return; adb_socket_setbufsize(fd, CHUNK_SIZE); s = create_local_socket(fd); if(s) { connect_to_smartsocket(s); return; } adb_close(fd); } }
(6) 执行connect_to_smartsocket(s)
void connect_to_smartsocket(asocket *s) { D("Connecting to smart socket \n"); asocket *ss = create_smart_socket(smart_socket_action); s->peer = ss; ss->peer = s; s->ready(s); }
(7) 执行create_smart_socket
static int smart_socket_enqueue(asocket *s, apacket *p) { unsigned len; #if ADB_HOST char *service = NULL; char* serial = NULL; transport_type ttype = kTransportAny; #endif D("SS(%d): enqueue %d\n", s->id, p->len); if(s->pkt_first == 0) { s->pkt_first = p; s->pkt_last = p; } else { if((s->pkt_first->len + p->len) > MAX_PAYLOAD) { D("SS(%d): overflow\n", s->id); put_apacket(p); goto fail; } memcpy(s->pkt_first->data + s->pkt_first->len, p->data, p->len); s->pkt_first->len += p->len; put_apacket(p); p = s->pkt_first; } /* don't bother if we can't decode the length */ if(p->len < 4) return 0; len = unhex(p->data, 4); if((len < 1) || (len > 1024)) { D("SS(%d): bad size (%d)\n", s->id, len); goto fail; } D("SS(%d): len is %d\n", s->id, len ); /* can't do anything until we have the full header */ if((len + 4) > p->len) { D("SS(%d): waiting for %d more bytes\n", s->id, len+4 - p->len); return 0; } p->data[len + 4] = 0; D("SS(%d): '%s'\n", s->id, (char*) (p->data + 4)); #if ADB_HOST service = (char *)p->data + 4; if(!strncmp(service, "host-serial:", strlen("host-serial:"))) { char* serial_end; service += strlen("host-serial:"); // serial number should follow "host:" and could be a host:port string. serial_end = skip_host_serial(service); if (serial_end) { *serial_end = 0; // terminate string serial = service; service = serial_end + 1; } } else if (!strncmp(service, "host-usb:", strlen("host-usb:"))) { ttype = kTransportUsb; service += strlen("host-usb:"); } else if (!strncmp(service, "host-local:", strlen("host-local:"))) { ttype = kTransportLocal; service += strlen("host-local:"); } else if (!strncmp(service, "host:", strlen("host:"))) { ttype = kTransportAny; service += strlen("host:"); } else { service = NULL; } if (service) { asocket *s2; /* some requests are handled immediately -- in that ** case the handle_host_request() routine has sent ** the OKAY or FAIL message and all we have to do ** is clean up. */ if(handle_host_request(service, ttype, serial, s->peer->fd, s) == 0) { /* XXX fail message? */ D( "SS(%d): handled host service '%s'\n", s->id, service ); goto fail; } if (!strncmp(service, "transport", strlen("transport"))) { D( "SS(%d): okay transport\n", s->id ); p->len = 0; return 0; } /* try to find a local service with this name. ** if no such service exists, we'll fail out ** and tear down here. */ s2 = create_host_service_socket(service, serial); if(s2 == 0) { D( "SS(%d): couldn't create host service '%s'\n", s->id, service ); sendfailmsg(s->peer->fd, "unknown host service"); goto fail; } /* we've connected to a local host service, ** so we make our peer back into a regular ** local socket and bind it to the new local ** service socket, acknowledge the successful ** connection, and close this smart socket now ** that its work is done. */ adb_write(s->peer->fd, "OKAY", 4); s->peer->ready = local_socket_ready; s->peer->close = local_socket_close; s->peer->peer = s2; s2->peer = s->peer; s->peer = 0; D( "SS(%d): okay\n", s->id ); s->close(s); /* initial state is "ready" */ s2->ready(s2); return 0; } #else /* !ADB_HOST */ if (s->transport == NULL) { char* error_string = "unknown failure"; s->transport = acquire_one_transport (CS_ANY, kTransportAny, NULL, &error_string); if (s->transport == NULL) { sendfailmsg(s->peer->fd, error_string); goto fail; } } #endif if(!(s->transport) || (s->transport->connection_state == CS_OFFLINE)) { /* if there's no remote we fail the connection ** right here and terminate it */ sendfailmsg(s->peer->fd, "device offline (x)"); goto fail; } /* instrument our peer to pass the success or fail ** message back once it connects or closes, then ** detach from it, request the connection, and ** tear down */ s->peer->ready = local_socket_ready_notify; s->peer->close = local_socket_close_notify; s->peer->peer = 0; /* give him our transport and upref it */ s->peer->transport = s->transport; connect_to_remote(s->peer, (char*) (p->data + 4)); s->peer = 0; s->close(s); return 1; fail: /* we're going to close our peer as a side-effect, so ** return -1 to signal that state to the local socket ** who is enqueueing against us */ s->close(s); return -1; }
(8) 执行handle_host_request
int handle_host_request(char *service, transport_type ttype, char* serial, int reply_fd, asocket *s) { // return a list of all connected devices if (!strncmp(service, "devices", 7)) { //执行adb devices,返回结果 char buffer[4096]; int use_long = !strcmp(service+7, "-l"); if (use_long || service[7] == 0) { memset(buf, 0, sizeof(buf)); memset(buffer, 0, sizeof(buffer)); D("Getting device list \n"); list_transports(buffer, sizeof(buffer), use_long); snprintf(buf, sizeof(buf), "OKAY%04x%s",(unsigned)strlen(buffer),buffer); D("Wrote device list \n"); writex(reply_fd, buf, strlen(buf)); return 0; } } }