由Adb Emulator问题谈起
0,问题描述
进入RK3288平台,执行adb devices会有一个emulator-5554的模拟器的连接。
1,复现步骤
reboot rk3288
C:\Users\koffuxu>adb tcpip 5555
C:\Users\koffuxu>adb shell
shell@firefly:/ # adb devices
* daemon not running. starting it now on port 5038 *
* daemon started successfully *
List of devices attached
emulator-5554 device
or:
setprop service.adb.tcp.port 5555; stop adbd; start adbd;
2,port status

127.0.0.1的41114端口(adb),连接上了5555端口(adbd),认为有一个模拟器的存在。
从而可以获得产生该问题的原因:
先启动adbd进程,监听127.0.0.1的5555端口;
再启动adb中的server,会去获得usb或者tcp链接上的adb状态,当有5555端口有响应的时候,认为有android device设备连接了,当对方的IP地址为127.0.0.1的话,就认为是emulator设备,即显示出来这个模拟器了。
3,打开调试
--- a/system/core/adb/adb_trace.h
+++ b/system/core/adb/adb_trace.h
@@ -64,7 +64,7 @@ extern int adb_trace_mask;
extern unsigned char adb_trace_output_count;
void adb_trace_init(void);
-# define ADB_TRACING ((adb_trace_mask & (1 << TRACE_TAG)) != 0)
+# define ADB_TRACING 1// ((adb_trace_mask & (1 << TRACE_TAG)) != 0)
4,修正方案
第一次尝试:注册127.0.0.1:*<->127.0.0.1:5555的连接到transport_list全局链表时的时候,把类型由local转为非local型。

结果:几番adb kill-server /start-server之后还是会有emulator出现
第二次尝试:不把与5555的连接注册到全局链表中。

结果:emulaotr没有添加到全局链表中,但连接是存在的,netstat 还是可以看与127.0.0.1有连接,仍有风险。
第三次尝试:不与5555进行连接

结果:没有本地的5555的连接,emulator也没有产生,其它连接也不受影响。
其它功能测试如下:
- PC通过usb或者网线连接RK3288的adbd
- RK3288的通过usb或者网线连接手机I9300的adbd

socket的连接情况

.105 =RK3288的IP.55 =I9300手机的IP.239 =PC的IP
5,复盘
Overview

5.1,2种Service:
Host Service:不需要与device进行通讯,直接在本地查询服务,比如版本号查询服务
Local Service:需要与Device进行通信,比如adb shell服务
ADB SERVER的各种类型参考SERVICES.txt,包含Host Service和Local Service
5.2,2个监听端口:
ADB Server监听TCP:localhost:5038,是用于等待Client的命令传输,指定127.0.0.1的连接
ADBD 监听TCP:0.0.0.0:5555,是用于监听TCP/IP的adb连接请求服务,任何IP皆可以连接 ,包括127.0.0.1
5.3,2种传输媒介:
USB:只限与物理设备的传输连接
TCP/IP:包括物理设备的连接,也包括本地adb与adbd的连接(这就是产生emualtor-5554的原因)
6,adb devices命令执行流程
ADB_HOST=1表示编译进adb可执行文件,否则为adbd可执行文件
adb devices
由services.txt可知,adb devices描述如下:
host:devices host:devices-l Ask to return the list of available Android devices and their
state. devices-l includes the device paths in the state.
After the OKAY, this is followed by a 4-byte hex len,
and a string that will be dumped as-is by the client, then
the connection is closed
执行adb命令,首先进入main()
main()@adb.c
=>//adb_commandline()@commandline.c
system/core/adb/adb.c::main():Handling commandline()
=>进行一些参数判断之后,进入qury_adb()函数
if(!strcmp(argv[0], "devices")) {
...
tmp = adb_query(buf);
if(tmp) {
printf("List of devices attached \n");
printf("%s\n", tmp);
return 0;
=>//adb_query()@adb_client.c打印如下
system/core/adb/adb_client.c::adb_query():adb_query: host:devices
=>
第一步,执行host:version命令
system/core/adb/adb_client.c::_adb_connect():_adb_connect: host:version //_adb_connect()@adb_client.c
adb_connect之前,先进行adb version查询,通过Socket的方式查询SOCK_STREAM。初次会返回为负值,需要自己启动。如果已经启动就会接下来读取版本。
=>
此段打印,检查adb_connecet是否已经启动。
//调用writex(fd, tmp, 4) || writex(fd, service, len)
system/core/adb/transport.c::writex():writex: fd=3 len=4: 30303063 000c
system/core/adb/transport.c::writex():writex: fd=3 len=12: 686f73743a76657273696f6e host:version
//接收server的数据:adb_status(fd)
system/core/adb/transport.c::readx():readx: fd=3 wanted=4
system/core/adb/transport.c::readx():readx: fd=3 wanted=4 got=4
4f4b4159 OKAY
//连接成功,正常则返回!
system/core/adb/adb_client.c::_adb_connect():_adb_connect: return fd 3
//D(“adb_connect: service %s\n”, service);打印
system/core/adb/adb_client.c::adb_connect():adb_connect: service host:devices
第二步,读取版本号进行比较
//因为fd>0走else流程,开始进行版本比较
//if(readx(fd, buf, 4)) goto error; 读取前面4个字节,即本次buf的长度
system/core/adb/transport.c::readx():readx: fd=3 wanted=4
system/core/adb/transport.c::readx():readx: fd=3 wanted=4 got=4
30303034 0004
//readx(fd, buf, n) 读取整个buf的长度,获取Version号
system/core/adb/transport.c::readx():readx: fd=3 wanted=4
system/core/adb/transport.c::readx():readx: fd=3 wanted=4 got=4
30303230 0020
第三步,执行host:devices命令
//版本比对成功之后,开始执行host:devices
system/core/adb/adb_client.c::_adb_connect():_adb_connect: host:devices//打印来自fd = _adb_connect(service);
//给Service写数据,包含长度的命令writex(fd, tmp, 4) || writex(fd, service, len)
//整个帧的格式[][][][]+[……]
system/core/adb/transport.c::writex():writex: fd=3 len=4: 30303063 000c//host:devices刚好为12个字节
system/core/adb/transport.c::writex():writex: fd=3 len=12: 686f73743a64657669636573 host:devices//再写命令
////接收server的数据:adb_status(fd)
system/core/adb/transport.c::readx():readx: fd=3 wanted=4
system/core/adb/transport.c::readx():readx: fd=3 wanted=4 got=4
4f4b4159 OKAY
//命令已经写给Server了,_adb_connect正常返回
system/core/adb/adb_client.c::_adb_connect():_adb_connect: return fd 3
//adb_connect()也正常返回,打印来自 D(“adb_connect: return fd %d\n”, fd);进入adb_query
system/core/adb/adb_client.c::adb_connect():adb_connect: return fd 3
第四步,读取host:devices的返回数据
//返回到adb_query()@adb_client.c
//再读buf,第一次读buf的的前面4个字节,即长度 if(readx(fd, buf, 4))
system/core/adb/transport.c::readx():readx: fd=3 wanted=4
system/core/adb/transport.c::readx():readx: fd=3 wanted=4 got=4
//读取的buf长度为0,即没有device连接,符合打印。
30303030 0000
system/core/adb/transport.c::readx():readx: fd=3 wanted=0
system/core/adb/transport.c::readx():readx: fd=3 wanted=0 got=0
List of devices attached
有模拟器的打印,就很容易分析其中的流程
1|shell@firefly:/ $ adb devices
system/core/adb/adb.c::main():Handling commandline()
system/core/adb/adb_client.c::adb_query():adb_query: host:devices
//写host:version命令
system/core/adb/adb_client.c::_adb_connect():_adb_connect: host:version
system/core/adb/transport.c::writex():writex: fd=3 len=4: 30303063 000c
system/core/adb/transport.c::writex():writex: fd=3 len=12: 686f73743a76657273696f6e host:version
system/core/adb/transport.c::readx():readx: fd=3 wanted=4
system/core/adb/transport.c::readx():readx: fd=3 wanted=4 got=4
4f4b4159 OKAY
system/core/adb/adb_client.c::_adb_connect():_adb_connect: return fd 3
system/core/adb/adb_client.c::adb_connect():adb_connect: service host:devices
//读取版本号
system/core/adb/transport.c::readx():readx: fd=3 wanted=4
system/core/adb/transport.c::readx():readx: fd=3 wanted=4 got=4
30303034 0004
system/core/adb/transport.c::readx():readx: fd=3 wanted=4
system/core/adb/transport.c::readx():readx: fd=3 wanted=4 got=4
30303230 0020
//版本比对成功,写host:device命令
system/core/adb/adb_client.c::_adb_connect():_adb_connect: host:devices
system/core/adb/transport.c::writex():writex: fd=3 len=4: 30303063 000c
system/core/adb/transport.c::writex():writex: fd=3 len=12: 686f73743a64657669636573 host:devices
system/core/adb/transport.c::readx():readx: fd=3 wanted=4
system/core/adb/transport.c::readx():readx: fd=3 wanted=4 got=4
4f4b4159 OKAY
system/core/adb/adb_client.c::_adb_connect():_adb_connect: return fd 3
system/core/adb/adb_client.c::adb_connect():adb_connect: return fd 3
//成功返回之后,读取buf信息
system/core/adb/transport.c::readx():readx: fd=3 wanted=4
system/core/adb/transport.c::readx():readx: fd=3 wanted=4 got=4
30303135 0015
system/core/adb/transport.c::readx():readx: fd=3 wanted=21
system/core/adb/transport.c::readx():readx: fd=3 wanted=21 got=21//读取21个字节即emulator-5554.de[vices]
656d756c61746f722d35353534096465 emulator-5554.de
List of devices attached
//获得连接数据
emulator-5554 device
7,解决思路
设备以及状态是在server中检测和连接,在Service.c中屏蔽对127.0.0.1:5555的连接。
或者,让Server不去连接127.0.0.1:5555端口。【最终就是采用这种方法】
首先要弄懂
- adbd是如何通过5555端口来检测是否有设备接入的。【fdevent机制:transport_registration_func】
- adb的Server端是如何去连接5555端口的。【socket机制:local_init()@transport_local.c】
socket_loopback_client(adb_port, SOCK_STREAM),会去连接local:5555端口。
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
s = socket(AF_INET, type, 0);
- adb的Server与adbd的5555号端口连接,这种连接是谁先发起的?
从以下注释可以看到一些端倪
client_socket_thread()@transport_local.c
/* try to connect to any number of running emulator instances */
/* this is only done when ADB starts up. later, each new emulator */
/* will send a message to ADB to indicate that is is starting up */
for ( ; count > 0; count--, port += 2 ) {
(void) local_connect(port);
}
看来是新的模拟器先发消息给adb的,也就是adbd发起的??!!
7.1,adb start-server在Server端的处理
adb start-server是在adb_connect的时候执行host:version命令时就执行了,并未传递到Server端。
代码段为
_adb_connect()@adb_client.c,
fd = socket_loopback_client(__adb_server_port, SOCK_STREAM);
=>根据Unix Socket通信模型,此处即创建一个lopback地址(即127.0.0.1)端口号为5038的socket client,并进行连接。
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
s = socket(AF_INET, type, 0);
connect(s, (struct sockaddr *) &addr, sizeof(addr))
那么这个Socket的Server端是在哪里创建的?
main()@adb.c->adb_main()
...
local_init(DEFAULT_ADB_LOCAL_TRANSPORT_PORT);//
DEFAULT_ADB_LOCAL_TRANSPORT_PORT=5555...
char local_name[30];
build_local_name(local_name, sizeof(local_name), server_port);//
server_port=5038 if(install_listener(local_name, "*smartsocket*", NULL, 0)) {
exit(1);
}
local_init是初始化5555端口的socket,在local_init里面,会根据HOST的值,是创建一个监听5555的socket server(for adbd)还是连接5555端口的socket client?
//port = 5555
void local_init(int port)
{
...
if(HOST) {
func = client_socket_thread;//在adb进程,属于soekct client
} else {
func = server_socket_thread;//在adbd进程,属于socket server
...
adb_thread_create(&thr, func, (void *) (uintptr_t) port))
...
}
接着,install_listener(local_name, “*smartsocket*”, NULL, 0)则是创建一个监听5038端口socket server。
7.2,adb devices命令在Server的处理
处理是在handle_host_request()@adb.c
// return a list of all connected devices
if (!strncmp(service, "devices", 7)) {
char buffer[4096];
int use_long = !strcmp(service+7, "-l");
if (use_long || service[7] == 0) {
memset(buffer, 0, sizeof(buffer));
D("Getting device list \n");
list_transports(buffer, sizeof(buffer), use_long);
D("Wrote device list \n");
send_msg_with_okay(reply_fd, buffer, strlen(buffer));
return 0;
}
}
list_transports()方法
for(t = transport_list.next; t != &transport_list; t = t->next) {
len = format_transport(t, p, end - p, long_listing);
if (p + len >= end) {
/* discard last line if buffer is too short */
break;
}
主要是从transport_list这个全局链表中取出来。
这个链接是在transport_registration_func()@transport.c这个函数里添加元素的
static void transport_registration_func(int _fd, unsigned ev, void *data)
{
...
/* put us on the master device list */
t->next = &transport_list;
t->prev = transport_list.prev;
t->next->prev = t;
t->prev->next = t;
}
这个transport_registration_func()被void init_transport_registration(void)调用,注册为fdevent
host:devices host:devices-l Ask to return the list of available Android devices and their
state. devices-l includes the device paths in the state.
After the OKAY, this is followed by a 4-byte hex len,
and a string that will be dumped as-is by the client, then
the connection is closed
执行adb命令,首先进入main()
=>//adb_commandline()@commandline.c
system/core/adb/adb.c::main():Handling commandline()
=>进行一些参数判断之后,进入qury_adb()函数
if(!strcmp(argv[0], "devices")) {
...
tmp = adb_query(buf);
if(tmp) {
printf("List of devices attached \n");
printf("%s\n", tmp);
return 0;
=>//adb_query()@adb_client.c打印如下
system/core/adb/adb_client.c::adb_query():adb_query: host:devices
=>
第一步,执行host:version命令
system/core/adb/adb_client.c::_adb_connect():_adb_connect: host:version //_adb_connect()@adb_client.c
adb_connect之前,先进行adb version查询,通过Socket的方式查询SOCK_STREAM。初次会返回为负值,需要自己启动。如果已经启动就会接下来读取版本。
=>
此段打印,检查adb_connecet是否已经启动。
//调用writex(fd, tmp, 4) || writex(fd, service, len)
system/core/adb/transport.c::writex():writex: fd=3 len=4: 30303063 000c
system/core/adb/transport.c::writex():writex: fd=3 len=12: 686f73743a76657273696f6e host:version
//接收server的数据:adb_status(fd)
system/core/adb/transport.c::readx():readx: fd=3 wanted=4
system/core/adb/transport.c::readx():readx: fd=3 wanted=4 got=4
4f4b4159 OKAY
//连接成功,正常则返回!
system/core/adb/adb_client.c::_adb_connect():_adb_connect: return fd 3
//D(“adb_connect: service %s\n”, service);打印
system/core/adb/adb_client.c::adb_connect():adb_connect: service host:devices
第二步,读取版本号进行比较
//因为fd>0走else流程,开始进行版本比较
//if(readx(fd, buf, 4)) goto error; 读取前面4个字节,即本次buf的长度
system/core/adb/transport.c::readx():readx: fd=3 wanted=4
system/core/adb/transport.c::readx():readx: fd=3 wanted=4 got=4
30303034 0004
//readx(fd, buf, n) 读取整个buf的长度,获取Version号
system/core/adb/transport.c::readx():readx: fd=3 wanted=4
system/core/adb/transport.c::readx():readx: fd=3 wanted=4 got=4
30303230 0020
第三步,执行host:devices命令
//版本比对成功之后,开始执行host:devices
system/core/adb/adb_client.c::_adb_connect():_adb_connect: host:devices//打印来自fd = _adb_connect(service);
//给Service写数据,包含长度的命令writex(fd, tmp, 4) || writex(fd, service, len)
//整个帧的格式[][][][]+[……]
system/core/adb/transport.c::writex():writex: fd=3 len=4: 30303063 000c//host:devices刚好为12个字节
system/core/adb/transport.c::writex():writex: fd=3 len=12: 686f73743a64657669636573 host:devices//再写命令
////接收server的数据:adb_status(fd)
system/core/adb/transport.c::readx():readx: fd=3 wanted=4
system/core/adb/transport.c::readx():readx: fd=3 wanted=4 got=4
4f4b4159 OKAY
//命令已经写给Server了,_adb_connect正常返回
system/core/adb/adb_client.c::_adb_connect():_adb_connect: return fd 3
//adb_connect()也正常返回,打印来自 D(“adb_connect: return fd %d\n”, fd);进入adb_query
system/core/adb/adb_client.c::adb_connect():adb_connect: return fd 3
第四步,读取host:devices的返回数据
//返回到adb_query()@adb_client.c
//再读buf,第一次读buf的的前面4个字节,即长度 if(readx(fd, buf, 4))
system/core/adb/transport.c::readx():readx: fd=3 wanted=4
system/core/adb/transport.c::readx():readx: fd=3 wanted=4 got=4
//读取的buf长度为0,即没有device连接,符合打印。
30303030 0000
system/core/adb/transport.c::readx():readx: fd=3 wanted=0
system/core/adb/transport.c::readx():readx: fd=3 wanted=0 got=0
List of devices attached
1|shell@firefly:/ $ adb devices
system/core/adb/adb.c::main():Handling commandline()
system/core/adb/adb_client.c::adb_query():adb_query: host:devices
//写host:version命令
system/core/adb/adb_client.c::_adb_connect():_adb_connect: host:version
system/core/adb/transport.c::writex():writex: fd=3 len=4: 30303063 000c
system/core/adb/transport.c::writex():writex: fd=3 len=12: 686f73743a76657273696f6e host:version
system/core/adb/transport.c::readx():readx: fd=3 wanted=4
system/core/adb/transport.c::readx():readx: fd=3 wanted=4 got=4
4f4b4159 OKAY
system/core/adb/adb_client.c::_adb_connect():_adb_connect: return fd 3
system/core/adb/adb_client.c::adb_connect():adb_connect: service host:devices
//读取版本号
system/core/adb/transport.c::readx():readx: fd=3 wanted=4
system/core/adb/transport.c::readx():readx: fd=3 wanted=4 got=4
30303034 0004
system/core/adb/transport.c::readx():readx: fd=3 wanted=4
system/core/adb/transport.c::readx():readx: fd=3 wanted=4 got=4
30303230 0020
//版本比对成功,写host:device命令
system/core/adb/adb_client.c::_adb_connect():_adb_connect: host:devices
system/core/adb/transport.c::writex():writex: fd=3 len=4: 30303063 000c
system/core/adb/transport.c::writex():writex: fd=3 len=12: 686f73743a64657669636573 host:devices
system/core/adb/transport.c::readx():readx: fd=3 wanted=4
system/core/adb/transport.c::readx():readx: fd=3 wanted=4 got=4
4f4b4159 OKAY
system/core/adb/adb_client.c::_adb_connect():_adb_connect: return fd 3
system/core/adb/adb_client.c::adb_connect():adb_connect: return fd 3
//成功返回之后,读取buf信息
system/core/adb/transport.c::readx():readx: fd=3 wanted=4
system/core/adb/transport.c::readx():readx: fd=3 wanted=4 got=4
30303135 0015
system/core/adb/transport.c::readx():readx: fd=3 wanted=21
system/core/adb/transport.c::readx():readx: fd=3 wanted=21 got=21//读取21个字节即emulator-5554.de[vices]
656d756c61746f722d35353534096465 emulator-5554.de
List of devices attached
//获得连接数据
emulator-5554 device
7,解决思路
设备以及状态是在server中检测和连接,在Service.c中屏蔽对127.0.0.1:5555的连接。
或者,让Server不去连接127.0.0.1:5555端口。【最终就是采用这种方法】
首先要弄懂
- adbd是如何通过5555端口来检测是否有设备接入的。【fdevent机制:transport_registration_func】
- adb的Server端是如何去连接5555端口的。【socket机制:local_init()@transport_local.c】
socket_loopback_client(adb_port, SOCK_STREAM),会去连接local:5555端口。
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
s = socket(AF_INET, type, 0);
- adb的Server与adbd的5555号端口连接,这种连接是谁先发起的?
从以下注释可以看到一些端倪
client_socket_thread()@transport_local.c
/* try to connect to any number of running emulator instances */
/* this is only done when ADB starts up. later, each new emulator */
/* will send a message to ADB to indicate that is is starting up */
for ( ; count > 0; count--, port += 2 ) {
(void) local_connect(port);
}
看来是新的模拟器先发消息给adb的,也就是adbd发起的??!!
7.1,adb start-server在Server端的处理
adb start-server是在adb_connect的时候执行host:version命令时就执行了,并未传递到Server端。
代码段为
_adb_connect()@adb_client.c,
fd = socket_loopback_client(__adb_server_port, SOCK_STREAM);
=>根据Unix Socket通信模型,此处即创建一个lopback地址(即127.0.0.1)端口号为5038的socket client,并进行连接。
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
s = socket(AF_INET, type, 0);
connect(s, (struct sockaddr *) &addr, sizeof(addr))
那么这个Socket的Server端是在哪里创建的?
main()@adb.c->adb_main()
...
local_init(DEFAULT_ADB_LOCAL_TRANSPORT_PORT);//
DEFAULT_ADB_LOCAL_TRANSPORT_PORT=5555...
char local_name[30];
build_local_name(local_name, sizeof(local_name), server_port);//
server_port=5038 if(install_listener(local_name, "*smartsocket*", NULL, 0)) {
exit(1);
}
local_init是初始化5555端口的socket,在local_init里面,会根据HOST的值,是创建一个监听5555的socket server(for adbd)还是连接5555端口的socket client?
//port = 5555
void local_init(int port)
{
...
if(HOST) {
func = client_socket_thread;//在adb进程,属于soekct client
} else {
func = server_socket_thread;//在adbd进程,属于socket server
...
adb_thread_create(&thr, func, (void *) (uintptr_t) port))
...
}
接着,install_listener(local_name, “*smartsocket*”, NULL, 0)则是创建一个监听5038端口socket server。
7.2,adb devices命令在Server的处理
处理是在handle_host_request()@adb.c
// return a list of all connected devices
if (!strncmp(service, "devices", 7)) {
char buffer[4096];
int use_long = !strcmp(service+7, "-l");
if (use_long || service[7] == 0) {
memset(buffer, 0, sizeof(buffer));
D("Getting device list \n");
list_transports(buffer, sizeof(buffer), use_long);
D("Wrote device list \n");
send_msg_with_okay(reply_fd, buffer, strlen(buffer));
return 0;
}
}
list_transports()方法
for(t = transport_list.next; t != &transport_list; t = t->next) {
len = format_transport(t, p, end - p, long_listing);
if (p + len >= end) {
/* discard last line if buffer is too short */
break;
}
主要是从transport_list这个全局链表中取出来。
这个链接是在transport_registration_func()@transport.c这个函数里添加元素的
static void transport_registration_func(int _fd, unsigned ev, void *data)
{
...
/* put us on the master device list */
t->next = &transport_list;
t->prev = transport_list.prev;
t->next->prev = t;
t->prev->next = t;
}
这个transport_registration_func()被void init_transport_registration(void)调用,注册为fdevent
- adbd是如何通过5555端口来检测是否有设备接入的。【fdevent机制:transport_registration_func】
- adb的Server端是如何去连接5555端口的。【socket机制:local_init()@transport_local.c】
socket_loopback_client(adb_port, SOCK_STREAM),会去连接local:5555端口。
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
s = socket(AF_INET, type, 0);
- adb的Server与adbd的5555号端口连接,这种连接是谁先发起的?
从以下注释可以看到一些端倪
/* try to connect to any number of running emulator instances */
/* this is only done when ADB starts up. later, each new emulator */
/* will send a message to ADB to indicate that is is starting up */
for ( ; count > 0; count--, port += 2 ) {
(void) local_connect(port);
}
看来是新的模拟器先发消息给adb的,也就是adbd发起的??!!
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
s = socket(AF_INET, type, 0);
connect(s, (struct sockaddr *) &addr, sizeof(addr))
那么这个Socket的Server端是在哪里创建的?
...
local_init(DEFAULT_ADB_LOCAL_TRANSPORT_PORT);//
DEFAULT_ADB_LOCAL_TRANSPORT_PORT=5555...
char local_name[30];
build_local_name(local_name, sizeof(local_name), server_port);//
server_port=5038if(install_listener(local_name, "*smartsocket*", NULL, 0)) {
exit(1);
}
local_init是初始化5555端口的socket,在local_init里面,会根据HOST的值,是创建一个监听5555的socket server(for adbd)还是连接5555端口的socket client?
//port = 5555
void local_init(int port)
{
...
if(HOST) {
func = client_socket_thread;//在adb进程,属于soekct client
} else {
func = server_socket_thread;//在adbd进程,属于socket server
...
adb_thread_create(&thr, func, (void *) (uintptr_t) port))
...
}
接着,install_listener(local_name, “*smartsocket*”, NULL, 0)则是创建一个监听5038端口socket server。
// return a list of all connected devices
if (!strncmp(service, "devices", 7)) {
char buffer[4096];
int use_long = !strcmp(service+7, "-l");
if (use_long || service[7] == 0) {
memset(buffer, 0, sizeof(buffer));
D("Getting device list \n");
list_transports(buffer, sizeof(buffer), use_long);
D("Wrote device list \n");
send_msg_with_okay(reply_fd, buffer, strlen(buffer));
return 0;
}
}
list_transports()方法
for(t = transport_list.next; t != &transport_list; t = t->next) {
len = format_transport(t, p, end - p, long_listing);
if (p + len >= end) {
/* discard last line if buffer is too short */
break;
}
主要是从transport_list这个全局链表中取出来。
这个链接是在transport_registration_func()@transport.c这个函数里添加元素的
static void transport_registration_func(int _fd, unsigned ev, void *data)
{
...
/* put us on the master device list */
t->next = &transport_list;
t->prev = transport_list.prev;
t->next->prev = t;
t->prev->next = t;
}
这个transport_registration_func()被void init_transport_registration(void)调用,注册为fdevent
void init_transport_registration(void)
{
int s[2];
if(adb_socketpair(s)){
fatal_errno("cannot open transport registration socketpair");
}
transport_registration_send = s[0];
transport_registration_recv = s[1];
fdevent_install(&transport_registration_fde,
transport_registration_recv,
transport_registration_func,
0);
fdevent_set(&transport_registration_fde, FDE_READ);
}
按照道理,只要读某个socket fd,就会有回到全局链表中。
而init_transport_registration();由adb_main()调用,相当于adbd进程。
简而言之,在adbd进程,如果有其它进程读它的socket节点,将触发fdevent,会把访问它的client记录在全局列表transprot_list链表中,即devices的列表。
7.3,adb connect在Server端的处理
8,adb Server与adbd处理“客户端”的循环
8.1,在adb的Server端的处理,是在handle_host_request()@adb.c里面处理command line发过来的命令的。
由来:
在adb_main()的install_listener(local_name, “*smartsocket*”, NULL, 0)函数中,会创建一个名为*smartsocket*,监听端口为5028的socket server,同时还是注册监听事件
=>
//install_listener("TCP:5038", "*smartsocket*", NULL, 0)
static install_status_t install_listener(const char *local_name,
const char *connect_to,
atransport* transport,
int no_rebind)
{
alistener *l;
//1,填充l结构体
if((l = calloc(1, sizeof(alistener))) == 0) goto nomem;
if((l->local_name = strdup(local_name)) == 0) goto nomem;
if((l->connect_to = strdup(connect_to)) == 0) goto nomem;
//2,local_name_to_fd会调用socet()和bin(),初始化socket server
l->fd = local_name_to_fd(local_name);
//3,开始install listen,用于响应客户端
if(!strcmp(l->connect_to, "*smartsocket*")) {
fdevent_install(&l->fde, l->fd, ss_listener_event_func, l);
}
fdevent_set(&l->fde, FDE_READ);
//4,添加到listener_list全局链表中。
l->next = &listener_list;
l->prev = listener_list.prev;
l->next->prev = l;
l->prev->next = l;
l->transport = transport;
}
以上4步就完成adb server的socket server(*smartsocket*)的创建,其中第3步,安装了listen的处理,处理函数是ss_listener_event_func,继续深挖goon!
static void ss_listener_event_func(int _fd, unsigned ev, void *_l)
{
asocket *s;
...
s = create_local_socket(fd);
if(s) {
connect_to_smartsocket(s);
return;
}
}
先创建asocket类型的s,然后调用connect_to_smartsocket进行连接
=>
create_smart_socket()
=>
s->enqueue = smart_socket_enqueue;
=>
if(handle_host_request(service, ttype, serial, s->peer->fd, s) == 0)
就调到handle_host_request函数里面了。DONE!
举例:比如说host:version的处理逻辑
// returns our value for ADB_SERVER_VERSION
if (!strcmp(service, “version”)) {
char version[12];
snprintf(version, sizeof version, “%04x”, ADB_SERVER_VERSION);
send_msg_with_okay(reply_fd, version, strlen(version));
return 0;
}
8.2在adbd中,是在fdevent_loop()@fdevent.c处理客户端的请求;
for(;;) {
D("--- ---- waiting for events\n");
fdevent_process();
while((fde = fdevent_plist_dequeue())) {
fdevent_call_fdfunc(fde);
}
}
死循环处理的,fdevent_loop()是在adb_main()@adb.c即adbd初始化的时候调用到。