system/core/adb/
Android Debug Bridge (ADB) 这个命令对于android开发者最熟悉不过了, 他的主要功能就是联上模拟器或者真机进行开发和调试.
而市面上的pc版手机助手应用其实就是调用了这个东东来实现在pc上对手机管理的操作.可见他是android对外的一个最主要途径.
连接方式由两种
1.usb物理数据线连接 (真机链接)
2.TCP/IP连接,也就是网络连接 (模拟器链接)
ADB组成的组件
1. ADB server (adb)
主要在宿主上提供监测发现usb端口附加或移除和模拟器的启动关闭
2.ADB daemon (adbd)
主要在android设备上提供小量的本地功能服务, 例如调用shell去执行某些命令,这是常驻进程,跟着系统一起启动.
3.ADB command-line client (adb)
主要在宿主上输入命令脚本命令.刚开始的时候不知道1和3组件有什么不同,大家的程序名称都是adb,很昏惑!!??
后来在什么都不连接的情况下(就是宿主上没有连接usb和启动模拟器),在宿主的终端上
输入adb install xxxx.apk
应该大家都熟悉这个命令吧,就是把相关apk包安装上设备上(就是安装android应用的命令)
然后终端会打印
* daemon not running. starting it now on port 5037 *
* daemon started successfully *
error: device not found
- waiting for device -
这个时候,在另外的终端下
输入ps aux|grep adb
然后终端会打印
xxxx 3492 0.0 0.0 4752 1028 pts/2 S+ 14:02 0:00 adb install xxxx.apk
xxxx 3493 0.2 0.0 22164 1424 pts/2 Sl+ 14:02 0:00 adb -P 5037 fork-server server
xxxx 3503 0.0 0.0 8100 892 pts/1 S+ 14:03 0:00 grep --color=auto adb
看到了没有,原来adb自身会fork出另外一个adb进程来的,只是这时的adb是带有特定的参数启动的
所以说其实组件3就是
xxxx 3492 0.0 0.0 4752 1028 pts/2 S+ 14:02 0:00 adb install xxxx.apk
组件1就是
xxxx 3493 0.2 0.0 22164 1424 pts/2 Sl+ 14:02 0:00 adb -P 5037 fork-server server
同一名称应用程序可能会分身出不同版本的程序功能,确实会给刚刚入门的人带来概念上的昏惑,明明说有两种东西在,却找来找去只有一样东西的感觉,不过这招不要以为只有这个地方才有.在android代码其他地方也使用了(例如是java层上的system进程和android应用进程的创建等等)
简要说一下adb工作的流程
组件3(主机) -----> 组件1(主机) <--> socket文件(主机/设备/模拟器)<--> 组件2 (设备/模拟器)
好了,说了这么多现在开始进入代码分析的环节,在这里用一个简单命令例子进行分析,就是上面提到的adb install [-lrtsd] <file>,这是个应用程序安装的命令。
首先看一下adb程序的main入口代码
system/core/adb/adb.c:1688
这里有ADB_HOST宏的定义,用来编译时分别编译成adb和adbd的程序,在分析代码时,大家首先要有一个c/s的概念,就是client/server,有这个前提下理解起来就容易多了。
其实就是在客户端发adb送预定好的指令,然后服务端adb/adbd接受指令,处理相关指令,然后返回结果的一个c/s的简单过程,把命令的发送和命令的处理通过socket独立起来了。
先来看看client客户端代码的流程是怎样走的
1.输入 adb install <file> 命令
2.adb_commandline()
这里就是adb 命令所有参数解释的地方,这时我们只关心解释install参数,find一下他
1626 if (!strcmp(argv[0], "install")) {
1627 if (argc < 2) return usage();
1628 return install_app(ttype, serial, argc, argv);
1629 }
这里的代码比较简单,直接跳过
3.install_app()
这里就是应用安装的代码,其实这里做了两件事情
第一就是把apk文件推送到设备上
第二就是调用shell命令启动pm命令去安装设备上的apk安装包
看到这,你是不是想说,其实我也可以使用adb push 把文件上传到设备
然后adb shell进入终端,在终端上直接pm命令安装应用,对的就是这个模样,只不过adb install 把这些命令都封装到一个命令里,使用起来方便了很多
先在设备上找个可以放东西的临时地方
1896 static const char *const DATA_DEST = "/data/local/tmp/%s"; 这是设备内部存储
1897 static const char *const SD_DEST = "/sdcard/tmp/%s";这是外设存储sd卡
至于选择哪个看有没有 -s 的参数
检查apk包的路径和后缀是否正确
然后到正真传文件的地方do_sync_push()
4.do_sync_push()
adb_connect("sync:")通知adbd做好同步的准备
检查要传送的文件是否存在
把文件读入内存,然后将内存的数据写入了socket里
最后读取socket获取结果是否成功,传送完成了
5.pm_command()
向socket写入”shell:pm“指令,让adbd启动pm命令
这里面有个方法
219 int adb_connect(const char *service)
这里比较重点,是连接服务端获取socket fd,如果adb组件1没有启动,随便在这里一起启动了
详情请看代码,应为全部都是对socket读写的操作,只不过就是写入预先定义好的指令命令
再来看看server服务端代码的流程是怎样走的
提示这里所说的服务端是组建2(adbd),假设真实设备或模拟器已经启动并链接上的
1.跟随android系统一起启动并且是守护进程的adbd
2.adb_main()
后台进程的入口点
3.init_transport_registration()
4.void init_transport_registration(void)
5.transport_registration_func()
6.transport_socket_events()
7.handle_packet()
8.create_local_service_socket()
9.service_to_fd()
10.file_sync_service()
以上都是fd事件注册的大概流程,其实本质就是使用了epoll,它是是Linux内核为处理大批量文件描述符而作了改进的epoll,是Linux下多路复用IO接口select/poll的增强版本,
详情用法不详细说,作用就是检测文件的变化状态而通知对应处理
11.do_recv()
这里就是以上客户端例子中的4.do_sync_push() 真正接收保存apk文件的地方,先会从socket里读数据,然后再写入指定路径上
12.fdevent_loop()
13.fdevent_process()
14.fdevent_plist_dequeue()
以上是fd事件不断处理的无限循环的地方,从队列里拿到事件然后逐个处理
15.fdevent_call_fdfunc()
这里其实调用的就是5.transport_registration_func()
这就是服务端传送文件的流程,至于执行shell pm命令流程与之类似就忽略了