android adb源码分析(5)【转】
本文转载自:http://blog.csdn.net/xgbing/article/details/52096880
本篇以“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;
- }
- }
- }
android adb源码分析(5)【转】的更多相关文章
- android adb源码分析(1)
ADB是Android debug bridge的缩写,它使用PC机可以通过USB或网络与android设备通讯. adb的源码位于system/core/adb目录下,先来看下编译脚本Android ...
- Appium Android Bootstrap源码分析之启动运行
通过前面的两篇文章<Appium Android Bootstrap源码分析之控件AndroidElement>和<Appium Android Bootstrap源码分析之命令解析 ...
- ADB 源码分析(一) ——ADB模块简述【转】
ADB源码分析(一)——ADB模块简述 1.Adb 源码路径(system/core/adb). 2.要想很快的了解一个模块的基本情况,最直接的就是查看该模块的Android.mk文件,下面就来看看a ...
- Appium Android Bootstrap源码分析之命令解析执行
通过上一篇文章<Appium Android Bootstrap源码分析之控件AndroidElement>我们知道了Appium从pc端发送过来的命令如果是控件相关的话,最终目标控件在b ...
- Appium Android Bootstrap源码分析之控件AndroidElement
通过上一篇文章<Appium Android Bootstrap源码分析之简介>我们对bootstrap的定义以及其在appium和uiautomator处于一个什么样的位置有了一个初步的 ...
- Android HandlerThread 源码分析
HandlerThread 简介: 我们知道Thread线程是一次性消费品,当Thread线程执行完一个耗时的任务之后,线程就会被自动销毁了.如果此时我又有一 个耗时任务需要执行,我们不得不重新创建线 ...
- Android Choreographer 源码分析
Choreographer 的作用主要是配合 Vsync ,给上层 App 的渲染提供一个稳定的 Message 处理的时机,也就是 Vsync 到来的时候 ,系统通过对 Vsync 信号周期的调整, ...
- Appium Android Bootstrap源码分析之简介
在上一个系列中我们分析了UiAutomator的核心源码,对UiAutomator是怎么运行的原理有了根本的了解.今天我们会开始另外一个在安卓平台上基于UiAutomator的新起之秀--Appium ...
- Android base-adapter-helper 源码分析与扩展
转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/44014941,本文出自:[张鸿洋的博客] 本篇博客是我加入Android 开源项 ...
随机推荐
- 转载:CMarkUp使用简介
转载地址:http://blog.csdn.net/jonathandj/article/details/4320725 最近正在研究C++下的XML分析工具CMarkup.初次和XML相遇是基于C# ...
- 转 CListCtrl::InsertColumn、InsertItem、SetItemText;
将数据写入到CListCtrl 向CListCtrl中写入数据,一般使用3个成员方法: CListCtrl::InsertColumn; CListCtrl::InsertItem; CListCtr ...
- cf21D Traveling Graph
You are given undirected weighted graph. Find the length of the shortest cycle which starts from the ...
- robotframework使用
下面是ui自动化的使用,关于接口自动化的使用参照此博客:http://blog.csdn.net/wuxiaobingandbob/article/details/50747125 1.使用pytho ...
- 【jquery创建元素添加元素】
使用jquery创建新元素的方法为:$(html标签),例如 $("<p></p>")创建了一个段落.注意此时只是创建了对象,尚未添加到文档节点中去:以下四 ...
- Java 学习(3):java 对象和类
目录: --- 对象 --- 类 --- 源文件的声明规则 --- Java 包 对象: 对象是类的一个实例(对象不是找个女朋友),有状态和行为.例如,一条狗是一个对象,它的状态有:颜色.名字.品种: ...
- JS设置页面中方法执行一次的思想
思想:在JS中定义一全局变量,在方法执行的时候根据全局变量的值判断是否需要执行,在方法中修改全局变量的值,可以使得方法只执行一次.: 例如: 定义全局变量: var isLoad = false;// ...
- spring 容器bean
bean配置信息----> 读取bean的配置信息到bean的注册表中---> 根据注册表的信息实例化bean---> 将bean的实例放到spring的容器中---> 应用程 ...
- WEB学习-基础知识:列表、表单、div和span、注释、字符实体、HTML废弃标签介绍
列表 无序列表 无序列表,用来表示一个列表的语义,并且每个项目和每个项目之间,是不分先后的. ul就是英语unordered list,“无序列表”的意思. li 就是英语list item , “列 ...
- AC日记——[网络流24题]方格取数问题 cogs 734
734. [网络流24题] 方格取数问题 ★★☆ 输入文件:grid.in 输出文件:grid.out 简单对比时间限制:1 s 内存限制:128 MB «问题描述: 在一个有m*n ...