您的位置:首页 > 移动开发 > Android开发

android adb源码分析(5)【转】

2018-01-02 09:59 441 查看
本文转载自:http://blog.csdn.net/xgbing/article/details/52096880

本篇以“adb devices"命令为例,跟踪代码的执行流程。

(1) main()->
(2)adb_commandline()->
adb_commandline()中的相关源码:

[cpp] view plain copy

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 ->

[cpp] view plain copy

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
= 0;

adb_close(fd);

return tmp;

}

free(tmp);

oops:

adb_close(fd);

return 0;

}

(4) adb_connect()->
这个函数的作用是连接adb server,如果adb server没有启动则先启动它。

[cpp] view plain copy

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()

[cpp] view plain copy

#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();

[cpp] view plain copy

/* 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()

[cpp] view plain copy

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()

[cpp] view plain copy

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)

[cpp] view plain copy

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分析

[cpp] view plain copy

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)

[cpp] view plain copy

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

[cpp] view plain copy

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

[cpp] view plain copy

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;

}

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: