本篇以“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;
}
}
}