Multiple adb connections over WiFi

来源:互联网 发布:node.js搭建 编辑:程序博客网 时间:2024/05/17 04:06

先放问题和解决方案吧。

问题:

We are two people and want to connect to a android devicefrom each respective notebook. When one person is connected, the other person gets a device is offline error.android device from multiple machines?

在stackoverflow上找到我的问题multiple-adb-connections-over-wifi,却没找到我需要的答案。

简单点描述就是我有多部电脑,希望通过adb tcpip连接到一部手机上,多部电脑连接的时候,发现只有一部电脑是可以操作手机的,其他电脑都是显示offline

解决方案

(系统级别的解决方案:直接修改android系统)

diff --git a/system/core/adb/transport.cpp b/system/core/adb/transport.cppindex 7350192527..8fe2e5a317 100644--- a/system/core/adb/transport.cpp+++ b/system/core/adb/transport.cpp@@ -938,7 +938,7 @@ int register_socket_transport(int s, const char *serial, int port, int local)             return -1;         }     }-+    #if ADB_HOST     for (n = transport_list.next; n != &transport_list; n = n->next) {         if (n->serial && !strcmp(serial, n->serial)) {             adb_mutex_unlock(&transport_lock);@@ -946,6 +946,7 @@ int register_socket_transport(int s, const char *serial, int port, int local)             return -1;         }     }+    #endif // ADB_HOST     t->next = &pending_list;     t->prev = pending_list.prev;

解决过程和方法

昨天编译了系统,顺利在VirtualBox上跑了起来,今天都在看adb部分的代码,代码目录是:

/system/core/adb

代码不多,就十几个文件。先是看了网上的一些分析,知道有 adbd adb(HOST)
adbd 就是在手机上运行的守护程序,adb(HOST) 就是在电脑上跑的adb服务端。一开始看了好久的分析,还是有点云里雾里的,后来想了一下,反正系统在我手里,边看日志边改吧。

开启日志

adb_trace.h

打日志就是这一段代码了

#  define ADB_TRACING  ((adb_trace_mask & (1 << TRACE_TAG)) != 0)/* you must define TRACE_TAG before using this macro */#if ADB_HOST#  define  D(...)                                      \        do {                                           \            if (ADB_TRACING) {                         \                int save_errno = errno;                \                adb_mutex_lock(&D_lock);               \                fprintf(stderr, "%16s: %5d:%5lu | ",   \                        __FUNCTION__,                  \                        getpid(), adb_thread_id());    \                errno = save_errno;                    \                fprintf(stderr, __VA_ARGS__ );         \                fflush(stderr);                        \                adb_mutex_unlock(&D_lock);             \                errno = save_errno;                    \           }                                           \        } while (0)#  define  DR(...)                                     \        do {                                           \            if (ADB_TRACING) {                         \                int save_errno = errno;                \                adb_mutex_lock(&D_lock);               \                errno = save_errno;                    \                fprintf(stderr, __VA_ARGS__ );         \                fflush(stderr);                        \                adb_mutex_unlock(&D_lock);             \                errno = save_errno;                    \           }                                           \        } while (0)#else#  define  D(...)                                      \        do {                                           \            if (ADB_TRACING) {                         \                __android_log_print(                   \                    ANDROID_LOG_INFO,                  \                    __FUNCTION__,                      \                    __VA_ARGS__ );                     \            }                                          \        } while (0)#  define  DR(...)                                     \        do {                                           \            if (ADB_TRACING) {                         \                __android_log_print(                   \                    ANDROID_LOG_INFO,                  \                    __FUNCTION__,                      \                    __VA_ARGS__ );                     \            }                                          \        } while (0)#endif /* ADB_HOST */

调试阶段,我直接把:

define ADB_TRACING ((adb_trace_mask & (1 << TRACE_TAG)) != 0)

改成了

define ADB_TRACING 1 // ((adb_trace_mask & (1 << TRACE_TAG)) != 0)

然后在系统上装个 Terminal 的应用,打开teriminal 输入 su ,拿到root权限之后输入 logcat ,然后就能看到日志打出来了。

切换到编译出来的out目录下,找到adb,用编译出来的adb作为服务端进行连接(即 ./adb connect 192.168.0.151

再换另外一部电脑进行adb connect 192.168.0.151

然后发现执行adb devices 手机terminal上没有log出来,所以adb devices 应该是本地操作,所以手机知道device offline 是在connect的时候就知道了的,看了下协议,才知道offline就是socket连接不上,电脑本地的报错信息,和手机端一点关系都没有。

顺带说一下adb的通讯协议,在

system/core/adb/protocol.txt

好长,不贴了,和我之前写长连接的东西好像,长连接那个我们是先定义了包结构,然后一开始匿名通讯,然后拿到密钥之后就开始加密通讯,看了下,adb 也是直接用tcp socket. 传输的,感觉亲切了不少。

然后对比了一下connect成功和connect失败的日志

成功的日志

这里写图片描述

失败的日志
这里写图片描述
找到对应的代码区域

int register_socket_transport(int s, const char *serial, int port, int local){    atransport *t = reinterpret_cast<atransport*>(calloc(1, sizeof(atransport)));    if (t == nullptr) {        return -1;    }    atransport *n;    char buff[32];    if (!serial) {        snprintf(buff, sizeof buff, "T-%p", t);        serial = buff;    }    D("transport: %s init'ing for socket %d, on port %d\n", serial, s, port);    if (init_socket_transport(t, s, port, local) < 0) {        free(t);        return -1;    }    adb_mutex_lock(&transport_lock);    for (n = pending_list.next; n != &pending_list; n = n->next) {        if (n->serial && !strcmp(serial, n->serial)) {            adb_mutex_unlock(&transport_lock);            free(t);            return -1;        }    }    for (n = transport_list.next; n != &transport_list; n = n->next) {        if (n->serial && !strcmp(serial, n->serial)) {            adb_mutex_unlock(&transport_lock);            free(t);            return -1;        }    }    t->next = &pending_list;    t->prev = pending_list.prev;    t->next->prev = t;    t->prev->next = t;    t->serial = strdup(serial);    adb_mutex_unlock(&transport_lock);    register_transport(t);    return 0;}

代码很简单,有两个出口,我都打了日志,重新编译之后就确定是transport_list这个链表出了问题,问题在于前一部机器注册了host这个键值,后面一部机器再注册就返回了,不管是什么机器serial的值在手机上都是host。

所以问题到这里就很清晰了,就是adbd在transport_list中保存了连接信息,发现重复了,就直接拒绝连接。所以第二部电脑连接的时候就offline了,offline是电脑本地的报错。

因为这份代码在adbdadb(HOST) 都有用到,所以我在前后加了条件编译,在手机上就不去重了,反正函数里面的信息都不足以判断重复。在电脑端(adb(HOST))这个要保留,不然同一部电脑会重复连接多次。

修改后自己验证的跑了几十次,确定没问题就提交代码了。

原创粉丝点击