`
hyshucom
  • 浏览: 824852 次
文章分类
社区版块
存档分类
最新评论

android2.3-adb源码分析

 
阅读更多
android2.3-adb源码分析


ADB是android debug bridge的缩写,负责计算机与Android设备的几乎所有通信和协作,可以认为是连接两者的桥梁。

其完整源代码路径:system\core\adb

1、首先查看其Android.mk文件,确认会生成哪此文件。

可执行进程由两部分组成:


LOCAL_MODULE := adb

include $(BUILD_HOST_EXECUTABLE)
adb或adb.exe,运行于PC端,包括Linux、Windows、Mac OS等系统之中,通常是x86架构上

LOCAL_MODULE := adbd
ifeq ($(TARGET_SIMULATOR),true)
include $(BUILD_HOST_EXECUTABLE)
else
include $(BUILD_EXECUTABLE)
endif
adbd,运行于Android设备的底层Linux平台上,或者运行于虚拟机平台上


盒子上如此运行:init.rc 脚本添加:
service adbd /sbin/adbd
disabled


利用ADB_HOST宏定义编译不同的代码


2、主体介绍一下
现在分析一下整个adb通讯由哪些模块或组件构成呢?

一、adb server 服务端:
这是一个守护进程长期运行于后台(runs on the host machine),没有控制台界面.
其主要工作有两部分:


1):管理PC中的Android模拟器,以及通过USB线连接到PC的Android设备,负责维持运行于其中的
adbd进程与自身的数据通道;
2):实现PC与设备/模拟器之间的数据拷贝。

主要代码文件:

二、adb client 客户端:
提供给用户的命令行工具,对用户暴露了上述install、push、shell等接口,与用户交互
其主要工作是解析这些命令的参数,做必要预处理,然后转移为指令或数据,发送给adb服务端。
adb服务端再将指令数据转发到模拟器或设备中,由adbd处理,产生结果,再通过adb服务端接收回来。


三、adb service 服务:
由此服务给adbd提供功能,即由这个模块完成,主要分为Host Services及 Local Services两类


四、ADB daemon (adbd) 守护进程
作为后台进程运行于Android device or emulated system,提供连接 ADB server的功能
(through USB for devices, through TCP for emulators)

其通讯典型结构如下:

3、以常用命令为实例
常用的指令如下:
adb push <local> <remote> - copy file/dir to device
adb pull <remote> [<local>] - copy file/dir from device
adb shell - run remote shell interactively
adb install [-l] [-r] [-s] <file> - push this package file to the device and install it
adb kill-server - kill the server if it is running
connect <host>[:<port>] - connect to a device via TCP/IP
Port 5555 is used by default if no port number is specified.


所有这些cmd处理函数都在:\system\core\adb\Commandline.c 中:
int adb_commandline(int argc, char **argv)

为了更好的理解这些命令,有必须找到代码理解一下这些命令的处理主要函数:

函数启动点: adb.c 中的main函数,根据ADB_HOST决定执行哪些代码:
int main(int argc, char **argv)
{
...
adb_trace_init();
#if ADB_HOST
adb_sysdeps_init();
return adb_commandline(argc - 1, argv + 1); //这里运行PC端,用于命令发送
#else
start_device_log();
return adb_main(0, DEFAULT_ADB_PORT); //运行于android系统的盒子或设备上,用于命令接收及反馈
#endif
}

先分析PC端这边:
a、首先建立adb server:
有两种方式,
手工建立:adb fork-server server 调用:adb_main(is_daemon, server_port);
默认5037端口,也可以设置:service.adb.tcp.port 这个属性获取
自动建立:调用 launch_server(server_port),利用 CreateProcess 或者fork建立后台进程进行运行
// child process
int result = execl(path, "adb", "fork-server", "server", NULL);
这个进程利用fdevent_loop();处理所有数据及消息

b、ADB command-line client即发送命令界面:
主要处理函数:int adb_commandline(int argc, char **argv)
主要利用如下几个函数:
adb_query 查询
adb_connect 连接
adb_status 获取状态

命令发送格式:
1. A 4-byte hexadecimal string giving the length of the payload
2. Followed by the payload itself.


服务端收到后回复:
1. For success, the 4-byte "OKAY" string
2. For failure, the 4-byte "FAIL" string, followed by a
4-byte hex length, followed by a string giving the reason
for failure.
3. As a special exception, for 'host:version', a 4-byte
hex string corresponding to the server's internal version number

以上两者通讯利用socket进行数据传递

然后分析设备服务端:
主要集中在函数:fdevent_loop();


主要分析一下数据transport这块,文件Transport.c

void init_transport_registration(void)
{
adb_socketpair(s) //创建socket pair用于处理异步注册事件

transport_registration_send = s[0];
transport_registration_recv = s[1];


// 在transport_registration_recv上安装一个transport_registration_func异步事情回调函数
fdevent_install(&transport_registration_fde,
transport_registration_recv,
transport_registration_func,
0);

...
}

异步如何触发的呢?
register_transport
-->transport_write_action(transport_registration_send, &m)

remove_transport
-->transport_write_action(transport_registration_send, &m)


此时会将事件写入socket pair的写入端,而接收端:

void fdevent_loop()
{
...

for(;;) {

while((fde = fdevent_plist_dequeue())) {
unsigned events = fde->events;
fde->events = 0;
fde->state &= (~FDE_PENDING);
dump_fde(fde, "callback");

//这个回调函数是在:fdevent_install 函数中注册的:fde->func = func;
fde->func(fde->fd, events, fde->arg);
}
}
}

然后利用transport_read_action读取异步事情,那么数据处理在哪里呢?

transport_registration_func
-->
/* don't create transport threads for inaccessible devices */
if (t->connection_state != CS_NOPERM) {

if(adb_thread_create(&input_thread_ptr, input_thread, t)){
fatal_errno("cannot create input thread");
}


if(adb_thread_create(&output_thread_ptr, output_thread, t)){
fatal_errno("cannot create output thread");
}
}

在这里会创建两个线程 output thread和 input thread用于做异步 IO,
=============================================================================
根据 adb的文档说明, output线程和 input线程的引人主要是为了解决 USB endpoint不支持非
阻塞读写,所以就专门为 usb读操作开一个output线程,为usb写操作创建一个input线程。
所以,数据流方向是远程连接->output线程->主线程->input线程->远程连接。刚开始时,
output线程会发一个 SYNC消息给input线程,启动这个transport。


static void *input_thread(void *_t)
{
D("to_remote: starting input_thread for %p, reading from fd %d\n",t, t->fd);
for(;;){
read_packet(t->fd, &p);

t->write_to_remote(p, t);
}
}


static void *output_thread(void *_t)
{
D("from_remote: data pump for transport %p\n", t);
for(;;) {
p = get_apacket();

t->read_from_remote(p, t);

write_packet(t->fd, &p);
}
}
=============================================================================

说一下我开始疑惑的问题解决:
adb shell 命令处理:
if(!strcmp(argv[0], "shell")) {
if(argc < 2) {
return interactive_shell();
}
}


int interactive_shell(void)
{
fd = adb_connect("shell:");

adb_thread_create(&thr, stdin_read_thread, fds);
}


而服务端处理:

#if ADB_HOST
#define SHELL_COMMAND "/bin/sh"
#else
#define SHELL_COMMAND "/system/bin/sh"
#endif

int service_to_fd(const char *name)
{
if(!HOST && !strncmp(name, "shell:", 6)) {
if(name[6]) {
ret = create_subprocess(SHELL_COMMAND, "-c", name + 6);
} else {
ret = create_subprocess(SHELL_COMMAND, "-", 0);
}
}

...
}


单独创建出一个进程进行处理shell命令
static int create_subprocess(const char *cmd, const char *arg0, const char *arg1)
{
pid = fork();

if(pid == 0){
execl(cmd, cmd, arg0, arg1, NULL);
}else
...
}


adb install xxx.apk 处理方式:
if(!strcmp(argv[0], "install")) {
if (argc < 2) return usage();
return install_app(ttype, serial, argc, argv);
}


if(!strcmp(argv[0], "uninstall")) {
if (argc < 2) return usage();
return uninstall_app(ttype, serial, argc, argv);
}

安装apk:
int install_app(transport_type transport, char* serial, int argc, char** argv)
{
//下载路径
const char *const DATA_DEST = "/data/local/tmp/%s";
const char *const SD_DEST = "/sdcard/tmp/%s";
const char* where = DATA_DEST;


//将apk文件写入到to目录下
if (!(err = do_sync_push(filename, to, 1 /* verify APK */))) {
/* file in place; tell the Package Manager to install it */
argv[argc - 1] = to; /* destination name, not source location */
pm_command(transport, serial, argc, argv);
delete_file(transport, serial, to);
}
...
}

通知android系统进行安装apk包
static int pm_command(transport_type transport, char* serial,
int argc, char** argv)
{
snprintf(buf, sizeof(buf), "shell:pm");

//通知包管理器安装apk应用,即使用pm命令安装应用
send_shellcommand(transport, serial, buf);
return 0;
}

usage: pm [list|path|install|uninstall]
pm list packages [-f]
pm list permission-groups
pm list permissions [-g] [-f] [-d] [-u] [GROUP]
pm list instrumentation [-f] [TARGET-PACKAGE]
pm list features
pm path PACKAGE
pm install [-l] [-r] [-t] [-i INSTALLER_PACKAGE_NAME] [-s] [-f] PATH
pm uninstall [-k] PACKAGE
pm enable PACKAGE_OR_COMPONENT
pm disable PACKAGE_OR_COMPONENT
pm setInstallLocation [0/auto] [1/internal] [2/external]

最后:

源码的OVERVIEW.txt文件中对它们的关系进行了描述。而protocol.txt描述了各模块之间通信协作的协议格式。

分享到:
评论

相关推荐

    android系统2.3源码(2)

    Android 2.3引入了新的开发者工具,如Android Debug Bridge (ADB)、DDMS(Dalvik Debug Monitor Service),以及改进的Eclipse集成开发环境,便于开发者调试和测试应用。 7. **第三方库支持**: `org`目录可能...

    安卓Android源码——TD2.3.zip

    10. **性能优化**:源码分析有助于理解系统性能瓶颈,如内存管理、CPU调度等,从而进行针对性的优化。 总之,分析“TD2.3”这样的Android源码压缩包,不仅可以提升开发者对系统的深入理解,还能提供无尽的创新机会...

    Android代码-gnirehtet

    This project provides reverse tethering over adb for Android: it allows devices to use the internet connection of the computer they are plugged on. It does not require any root access (neither on the ...

    Android应用程序开发宝典-基于TE&OK6410;.pdf

    - **2-1-1 编译ANDROID2.3形成文件系统** 在Ubuntu 10.10环境下编译Android 2.3的源码,是构建Android开发环境的基础步骤之一。这一步骤主要包括下载源码、配置编译环境、执行编译命令等环节。成功完成这一步后,...

    TE/OK6410 Android应用程序开发指南 - 飞凌嵌入式.pdf

    - Ubuntu10.10系统上编译Android源码的过程,包括生成Android 2.3的文件系统和SDK开发包。 - 提供了Ubunt9.10(32位)和Ubuntu10.10(64位)两个版本的源代码,方便开发者根据自己的Linux开发环境选择合适的版本。...

    Android群英传-前言.md

    **2.3 ADB命令使用技巧** - **基础**:ADB(Android Debug Bridge)是一个命令行工具,用于与Android设备通信。 - **常用命令**:如adb install、adb shell、adb logcat等。 **2.4 模拟器使用和配置** - **功能**...

    Android开发入门文档

    ##### 2.3 编译Android中的Linux内核 - **获取.config文件**: 可以从模拟器中获取.config文件。 1. **启动模拟器**,打开SDK的Tools目录。 2. **使用adb命令**: `&gt; adb pull /proc/config.gz d:\`,将文件保存到`...

    疯狂Android讲义源码

     1.3.4 Android Debug Bridge(ADB)  的用法 16  1.3.5 使用DX编译Android应用 18  1.3.6 使用Android Asset Packaging  Tool(AAPT)打包资源 19  1.3.7 使用mksdcard管理虚拟SD卡 19  1.4 开始第一个...

    Android开发案例驱动教程 配套代码

    2.3 Android开发模拟器 11 2.3.1 创建模拟器 11 2.3.2 启动模拟器 13 2.3.3 键盘映射与模拟器控制 13 2.3.4 横屏与竖屏切换 14 第3章 第一个Android程序 15 3.1 HelloAndroid 15 3.1.1 在Eclipse中创建项目 ...

    Android底层开发技术实战详解--内核、移植和驱动.(电子工业.王振丽).part3

    2.3 分析并编译Android源代码 35 2.3.1 Android源代码的结构 35 2.3.2 编译Android源代码 40 2.3.3 运行Android源代码 42 2.3.4 实践演练——演示编译Android程序的两种方法 43 2.4 编译...

    《深入理解Android》卷Ⅱ

    4.4.1 adb install分析 4.4.2 pm分析 4.4.3 installPackageWithVerification函数分析 4.4.4 APK 安装流程总结 4.4.5 Verification介绍 4.5 queryIntentActivities分析 4.5.1 Intent及IntentFilter介绍 4.5.2...

    x3399 开发文档

    根据提供的文档信息,我们可以总结出以下关键知识点,主要聚焦于X3399 Android平台的开发环境搭建、工具使用、源码管理与编译、以及最终的映像文件烧录等几个方面。 ### 1. 开发平台的搭建 #### 1.1 使用U盘安装...

    Android底层开发技术实战详解--内核、移植和驱动.(电子工业.王振丽).part1

    2.3 分析并编译Android源代码 35 2.3.1 Android源代码的结构 35 2.3.2 编译Android源代码 40 2.3.3 运行Android源代码 42 2.3.4 实践演练——演示编译Android程序的两种方法 43 2.4 编译...

    Android底层开发技术实战详解--内核、移植和驱动.(电子工业.王振丽).part2

    2.3 分析并编译Android源代码 35 2.3.1 Android源代码的结构 35 2.3.2 编译Android源代码 40 2.3.3 运行Android源代码 42 2.3.4 实践演练——演示编译Android程序的两种方法 43 2.4 编译...

    在android模拟器中调试Launcher模块代码

    4.1 Android Studio中的Logcat工具可以帮助你查看应用程序的日志输出,这对于跟踪问题和分析行为非常有用。 4.2 在运行时,通过输出特定标签或关键字的Log信息,可以了解程序的状态和运行情况。 **步骤5:特殊调试...

Global site tag (gtag.js) - Google Analytics