android2.3-adb源码分析
jopen
13年前
<span style="font-family:'Microsoft YaHei';font-size:16px;">ADB是android debug bridge的缩写,负责计算机与Android设备的几乎所有通信和协作,可以认为是连接两者的桥梁。<br /> <br /> 其完整源代码路径:system\core\adb<br /> <br /> 1、首先查看其Android.mk文件,确认会生成哪此文件。<br /> <br /> 可执行进程由两部分组成:<br /> </span> <p> </p> <p>LOCAL_MODULE := adb</p> include $(BUILD_HOST_EXECUTABLE) <br /> adb或adb.exe,运行于PC端,包括Linux、Windows、Mac OS等系统之中,通常是x86架构上 <br /> <br /> LOCAL_MODULE := adbd <br /> ifeq ($(TARGET_SIMULATOR),true) <br /> include $(BUILD_HOST_EXECUTABLE) <br /> else <br /> include $(BUILD_EXECUTABLE) <br /> endif <br /> adbd,运行于Android设备的底层Linux平台上,或者运行于虚拟机平台上 <br /> <br /> <br /> 盒子上如此运行:init.rc 脚本添加: <br /> service adbd /sbin/adbd <br /> disabled <br /> <br /> <br /> 利用ADB_HOST宏定义编译不同的代码 <br /> <br /> <br /> 2、主体介绍一下 <br /> 现在分析一下整个adb通讯由哪些模块或组件构成呢? <br /> <br /> 一、adb server 服务端: <br /> 这是一个守护进程长期运行于后台(runs on the host machine),没有控制台界面. <br /> 其主要工作有两部分: <br /> <br /> <br /> 1):管理PC中的Android模拟器,以及通过USB线连接到PC的Android设备,负责维持运行于其中的 <br /> adbd进程与自身的数据通道; <br /> 2):实现PC与设备/模拟器之间的数据拷贝。 <br /> <br /> 主要代码文件: <br /> <br /> 二、adb client 客户端: <br /> 提供给用户的命令行工具,对用户暴露了上述install、push、shell等接口,与用户交互 <br /> 其主要工作是解析这些命令的参数,做必要预处理,然后转移为指令或数据,发送给adb服务端。 <br /> adb服务端再将指令数据转发到模拟器或设备中,由adbd处理,产生结果,再通过adb服务端接收回来。 <br /> <br /> <br /> 三、adb service 服务: <br /> 由此服务给adbd提供功能,即由这个模块完成,主要分为Host Services及 Local Services两类 <br /> <br /> <br /> 四、ADB daemon (adbd) 守护进程 <br /> 作为后台进程运行于Android device or emulated system,提供连接 ADB server的功能 <br /> (through USB for devices, through TCP for emulators) <br /> <br /> 其通讯典型结构如下: <br /> <img alt="" src="https://simg.open-open.com/show/da54024516efd6c2c27ec948167d5330.bmp" /> <br /> 3、以常用命令为实例 <br /> 常用的指令如下: <br /> adb push <local> <remote> - copy file/dir to device <br /> adb pull <remote> [<local>] - copy file/dir from device <br /> adb shell - run remote shell interactively <br /> adb install [-l] [-r] [-s] <file> - push this package file to the device and install it <br /> adb kill-server - kill the server if it is running <br /> connect <host>[:<port>] - connect to a device via TCP/IP <br /> Port 5555 is used by default if no port number is specified. <br /> <br /> <br /> 所有这些cmd处理函数都在:\system\core\adb\Commandline.c 中: <br /> int adb_commandline(int argc, char **argv) <br /> <br /> 为了更好的理解这些命令,有必须找到代码理解一下这些命令的处理主要函数: <br /> <br /> 函数启动点: adb.c 中的main函数,根据ADB_HOST决定执行哪些代码: <br /> int main(int argc, char **argv) <br /> { <br /> ... <br /> adb_trace_init(); <br /> #if ADB_HOST <br /> adb_sysdeps_init(); <br /> return adb_commandline(argc - 1, argv + 1); //这里运行PC端,用于命令发送 <br /> #else <br /> start_device_log(); <br /> return adb_main(0, DEFAULT_ADB_PORT); //运行于android系统的盒子或设备上,用于命令接收及反馈 <br /> #endif <br /> } <br /> <br /> 先分析PC端这边: <br /> a、首先建立adb server: <br /> 有两种方式, <br /> 手工建立:adb fork-server server 调用:adb_main(is_daemon, server_port); <br /> 默认5037端口,也可以设置:service.adb.tcp.port 这个属性获取 <br /> 自动建立:调用 launch_server(server_port),利用 CreateProcess 或者fork建立后台进程进行运行 <br /> // child process <br /> int result = execl(path, "adb", "fork-server", "server", NULL); <br /> 这个进程利用fdevent_loop();处理所有数据及消息 <br /> <br /> b、ADB command-line client即发送命令界面: <br /> 主要处理函数:int adb_commandline(int argc, char **argv) <br /> 主要利用如下几个函数: <br /> adb_query 查询 <br /> adb_connect 连接 <br /> adb_status 获取状态 <br /> <br /> 命令发送格式: <br /> 1. A 4-byte hexadecimal string giving the length of the payload <br /> 2. Followed by the payload itself. <span style="white-space:pre;"> </span> <br /> <br /> <br /> 服务端收到后回复: <br /> 1. For success, the 4-byte "OKAY" string <br /> 2. For failure, the 4-byte "FAIL" string, followed by a <br /> 4-byte hex length, followed by a string giving the reason <br /> for failure. <br /> 3. As a special exception, for 'host:version', a 4-byte <br /> hex string corresponding to the server's internal version number <br /> <br /> 以上两者通讯利用socket进行数据传递 <br /> <br /> 然后分析设备服务端: <br /> 主要集中在函数:fdevent_loop(); <br /> <br /> <br /> 主要分析一下数据transport这块,文件Transport.c <br /> <br /> void init_transport_registration(void) <br /> { <br /> adb_socketpair(s) //创建socket pair用于处理异步注册事件 <br /> <br /> transport_registration_send = s[0]; <br /> transport_registration_recv = s[1]; <br /> <br /> <br /> // 在transport_registration_recv上安装一个transport_registration_func异步事情回调函数 <br /> fdevent_install(&transport_registration_fde, <br /> transport_registration_recv, <br /> transport_registration_func, <br /> 0); <br /> <br /> ... <span style="white-space:pre;"> </span> <br /> } <br /> <br /> 异步如何触发的呢? <br /> register_transport <br /> -->transport_write_action(transport_registration_send, &m) <br /> <br /> remove_transport <br /> -->transport_write_action(transport_registration_send, &m) <br /> <br /> <br /> 此时会将事件写入socket pair的写入端,而接收端: <br /> <br /> void fdevent_loop() <br /> { <br /> ... <br /> <br /> for(;;) { <br /> <br /> while((fde = fdevent_plist_dequeue())) { <br /> unsigned events = fde->events; <br /> fde->events = 0; <br /> fde->state &= (~FDE_PENDING); <br /> dump_fde(fde, "callback"); <br /> <br /> //这个回调函数是在:fdevent_install 函数中注册的:fde->func = func; <br /> fde->func(fde->fd, events, fde->arg); <br /> } <br /> } <br /> } <br /> <br /> 然后利用transport_read_action读取异步事情,那么数据处理在哪里呢? <br /> <br /> transport_registration_func <br /> --> <br /> /* don't create transport threads for inaccessible devices */ <br /> if (t->connection_state != CS_NOPERM) { <br /> <br /> if(adb_thread_create(&input_thread_ptr, input_thread, t)){ <br /> fatal_errno("cannot create input thread"); <br /> } <br /> <br /> <br /> if(adb_thread_create(&output_thread_ptr, output_thread, t)){ <br /> fatal_errno("cannot create output thread"); <br /> } <br /> } <br /> <br /> 在这里会创建两个线程 output thread和 input thread用于做异步 IO, <br /> ============================================================================= <br /> 根据 adb的文档说明, output线程和 input线程的引人主要是为了解决 USB endpoint不支持非 <br /> 阻塞读写,所以就专门为 usb读操作开一个output线程,为usb写操作创建一个input线程。 <br /> 所以,数据流方向是远程连接->output线程->主线程->input线程->远程连接。刚开始时, <br /> output线程会发一个 SYNC消息给input线程,启动这个transport。 <br /> <br /> <br /> static void *input_thread(void *_t) <br /> { <br /> D("to_remote: starting input_thread for %p, reading from fd %d\n",t, t->fd); <br /> for(;;){ <br /> read_packet(t->fd, &p); <br /> <br /> t->write_to_remote(p, t); <span style="white-space:pre;"> </span> <br /> } <br /> } <br /> <br /> <br /> static void *output_thread(void *_t) <br /> { <br /> D("from_remote: data pump for transport %p\n", t); <br /> for(;;) { <br /> p = get_apacket(); <br /> <br /> t->read_from_remote(p, t); <br /> <br /> write_packet(t->fd, &p); <br /> } <br /> } <br /> ============================================================================= <br /> <br /> 说一下我开始疑惑的问题解决: <br /> adb shell 命令处理: <br /> if(!strcmp(argv[0], "shell")) { <br /> if(argc < 2) { <br /> <span style="white-space:pre;"> </span>return interactive_shell(); <br /> } <span style="white-space:pre;"> </span> <br /> } <br /> <br /> <br /> int interactive_shell(void) <br /> { <br /> fd = adb_connect("shell:"); <br /> <br /> adb_thread_create(&thr, stdin_read_thread, fds); <br /> } <br /> <br /> <br /> 而服务端处理: <br /> <br /> #if ADB_HOST <br /> #define SHELL_COMMAND "/bin/sh" <br /> #else <br /> #define SHELL_COMMAND "/system/bin/sh" <br /> #endif <br /> <br /> int service_to_fd(const char *name) <br /> { <br /> if(!HOST && !strncmp(name, "shell:", 6)) { <br /> if(name[6]) { <br /> ret = create_subprocess(SHELL_COMMAND, "-c", name + 6); <br /> } else { <br /> ret = create_subprocess(SHELL_COMMAND, "-", 0); <br /> } <br /> } <br /> <br /> ... <br /> } <br /> <br /> <br /> 单独创建出一个进程进行处理shell命令 <br /> static int create_subprocess(const char *cmd, const char *arg0, const char *arg1) <br /> { <br /> pid = fork(); <br /> <br /> if(pid == 0){ <br /> execl(cmd, cmd, arg0, arg1, NULL); <br /> }else <br /> ... <br /> } <br /> <br /> <br /> adb install xxx.apk 处理方式: <br /> if(!strcmp(argv[0], "install")) { <br /> if (argc < 2) return usage(); <br /> return install_app(ttype, serial, argc, argv); <br /> } <br /> <br /> <br /> if(!strcmp(argv[0], "uninstall")) { <br /> if (argc < 2) return usage(); <br /> return uninstall_app(ttype, serial, argc, argv); <br /> } <br /> <br /> 安装apk: <br /> int install_app(transport_type transport, char* serial, int argc, char** argv) <br /> { <br /> //下载路径 <br /> const char *const DATA_DEST = "/data/local/tmp/%s"; <br /> const char *const SD_DEST = "/sdcard/tmp/%s"; <br /> const char* where = DATA_DEST; <br /> <br /> <br /> //将apk文件写入到to目录下 <br /> if (!(err = do_sync_push(filename, to, 1 /* verify APK */))) { <br /> /* file in place; tell the Package Manager to install it */ <br /> argv[argc - 1] = to; /* destination name, not source location */ <br /> pm_command(transport, serial, argc, argv); <br /> delete_file(transport, serial, to); <br /> } <br /> ... <br /> } <br /> <br /> 通知android系统进行安装apk包 <br /> static int pm_command(transport_type transport, char* serial, <br /> int argc, char** argv) <br /> { <br /> snprintf(buf, sizeof(buf), "shell:pm"); <br /> <br /> //通知包管理器安装apk应用,即使用pm命令安装应用 <br /> send_shellcommand(transport, serial, buf); <br /> return 0; <br /> } <br /> <br /> usage: pm [list|path|install|uninstall] <br /> pm list packages [-f] <br /> pm list permission-groups <br /> pm list permissions [-g] [-f] [-d] [-u] [GROUP] <br /> pm list instrumentation [-f] [TARGET-PACKAGE] <br /> pm list features <br /> pm path PACKAGE <br /> pm install [-l] [-r] [-t] [-i INSTALLER_PACKAGE_NAME] [-s] [-f] PATH <br /> pm uninstall [-k] PACKAGE <br /> pm enable PACKAGE_OR_COMPONENT <br /> pm disable PACKAGE_OR_COMPONENT <br /> pm setInstallLocation [0/auto] [1/internal] [2/external] <br /> <br /> 最后: <br /> <p>源码的OVERVIEW.txt文件中对它们的关系进行了描述。而protocol.txt描述了各模块之间通信协作的协议格式。</p>