您的位置:首页 > 移动开发 > Android开发

android6.0 adbd深入分析(一)adb驱动初始化、读取adb节点线程

2016-04-12 16:12 1026 查看
adbd之前看过一次,觉得代码太复杂然后,又是adb client  adb server adbd交织在一起感觉看起来太累,最近项目需要把它大致看完了,梳理下,感觉从adbd能学到很多东西,在此总结下,adbd的代码。

我只分析我看懂了,不可能面面俱到。而且主要注重在通信方面,以及一些命令处理等。

一、adb主函数

我们先来看下主函数:

int main(int argc, char **argv) {
#if ADB_HOST
// adb client/server
adb_sysdeps_init();
adb_trace_init();
D("Handling commandline()\n");
return adb_commandline(argc - 1, const_cast<const char**>(argv + 1));
#else
// adbd
while (true) {
static struct option opts[] = {
{"root_seclabel", required_argument, nullptr, 's'},
{"device_banner", required_argument, nullptr, 'b'},
{"version", no_argument, nullptr, 'v'},
};

int option_index = 0;
int c = getopt_long(argc, argv, "", opts, &option_index);
if (c == -1)
break;
switch (c) {
case 's':
root_seclabel = optarg;
break;
case 'b':
adb_device_banner = optarg;
break;
case 'v':
printf("Android Debug Bridge Daemon version %d.%d.%d %s\n",
ADB_VERSION_MAJOR, ADB_VERSION_MINOR, ADB_SERVER_VERSION,
ADB_REVISION);
return 0;
default:
break;
}
}

close_stdin();

adb_trace_init();

/* If adbd runs inside the emulator this will enable adb tracing via
* adb-debug qemud service in the emulator. */
adb_qemu_trace_init();

D("Handling main()\n");
return adb_main(0, DEFAULT_ADB_PORT);
#endif

ADB_HOST宏直接用来区分是pc上的还是手机上的,pc上的直接用adb_commandline函数处理各种命令,我们就不看了,我们主要分析adbd。

adbd主要调用了adb_main方法

int adb_main(int is_daemon, int server_port)
{
#if !ADB_HOST
int port;
char value[PROPERTY_VALUE_MAX];

umask(000);
#endif

atexit(adb_cleanup);
#if defined(_WIN32)
SetConsoleCtrlHandler( ctrlc_handler, TRUE );
#else
// No SIGCHLD. Let the service subproc handle its children.
signal(SIGPIPE, SIG_IGN);
#endif

init_transport_registration();

#if ADB_HOST
HOST = 1;

#ifdef WORKAROUND_BUG6558362
if(is_daemon) adb_set_affinity();
#endif
usb_init();看下adb_main代码我们先看下init_transport_registration函数

void init_transport_registration(void)
{
int s[2];

if(adb_socketpair(s)){//socketpair
fatal_errno("cannot open transport registration socketpair");
}
D("socketpair: (%d,%d)", s[0], s[1]);

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);
}

调用了socketpair,一端有数据后会调用transport_registration_func函数,我们先来看下什么时候transport_registration_recv会有数据过来,也就要看下transport_registration_send 什么时候会有数据发送。

二、usb、adb的驱动初始化

下面我们再来看下adb驱动的节点的初始化

继续看上面adb_main的usb_init函数:

void usb_init()
{
if (access(USB_FFS_ADB_EP0, F_OK) == 0)
usb_ffs_init();
else
usb_adb_init();
}

我们这边调用的是usb_adb_init()

static void usb_adb_init()
{
usb_handle* h = reinterpret_cast<usb_handle*>(calloc(1, sizeof(usb_handle)));
if (h == nullptr) fatal("couldn't allocate usb_handle");

h->write = usb_adb_write;
h->read = usb_adb_read;
h->kick = usb_adb_kick;
h->fd = -1;

adb_cond_init(&h->notify, 0);
adb_mutex_init(&h->lock, 0);

// Open the file /dev/android_adb_enable to trigger
// the enabling of the adb USB function in the kernel.
// We never touch this file again - just leave it open
// indefinitely so the kernel will know when we are running
// and when we are not.
int fd = unix_open("/dev/android_adb_enable", O_RDWR);//打开android_adb_enable节点只是enableadb usb而已
if (fd < 0) {
D("failed to open /dev/android_adb_enable\n");
} else {
close_on_exec(fd);
}

D("[ usb_init - starting thread ]\n");
adb_thread_t tid;
if(adb_thread_create(&tid, usb_adb_open_thread, h)){
fatal_errno("cannot create usb thread");
}
}

这个函数中打开android_adb_enable节点只是enableadb usb而已,之后开了一个线程调用usb_adb_open_thread

static void *usb_adb_open_thread(void *x)
{
struct usb_handle *usb = (struct usb_handle *)x;
int fd;

while (true) {
// wait until the USB device needs opening
adb_mutex_lock(&usb->lock);
while (usb->fd != -1)
adb_cond_wait(&usb->notify, &usb->lock);
adb_mutex_unlock(&usb->lock);

D("[ usb_thread - opening device ]\n");
do {
/* XXX use inotify? */
fd = unix_open("/dev/android_adb", O_RDWR);//打开adb节点
if (fd < 0) {
// to support older kernels
fd = unix_open("/dev/android", O_RDWR);
}
if (fd < 0) {
adb_sleep_ms(1000);
}
} while (fd < 0);

close_on_exec(fd);
usb->fd = fd;//节点赋给usb

D("[ usb_thread - registering device ]\n");
register_usb_transport(usb, 0, 0, 1);
}

// never gets here
return 0;
}

这个函数中主要打开adb节点,调用register_usb_transport函数来注册usb传输。

void register_usb_transport(usb_handle *usb, const char *serial, const char *devpath, unsigned writeable)
{
atransport *t = reinterpret_cast<atransport*>(calloc(1, sizeof(atransport)));
if (t == nullptr) fatal("cannot allocate USB atransport");
D("transport: %p init'ing for usb_handle %p (sn='%s')\n", t, usb,
serial ? serial : "");
init_usb_transport(t, usb, (writeable ? CS_OFFLINE : CS_NOPERM));
if(serial) {
t->serial = strdup(serial);
}
if(devpath) {
t->devpath = strdup(devpath);
}

adb_mutex_lock(&transport_lock);
t->next = &pending_list;
t->prev = pending_list.prev;
t->next->prev = t;
t->prev->next = t;
adb_mutex_unlock(&transport_lock);

register_transport(t);
}

这个函数先调用了init_usb_transport函数,把atransport初始化了,并且把usb_handle也赋给它了,我们主要看下register_transport函数。

static void register_transport(atransport *transport)
{
tmsg m;
m.transport = transport;
m.action = 1;
D("transport: %s registered\n", transport->serial);
if(transport_write_action(transport_registration_send, &m)) {
fatal_errno("cannot write transport registration socket\n");
}
}

这个函数把atransport 封装起来,传出去了,我们来看下transport_write_action函数,我们注意看第一个参数transport_registration_send就是我们之前的sockpair的send端

transport_write_action函数就是把transport发给transport_registration_recv端。

static int
transport_write_action(int  fd, struct tmsg*  m)
{
char *p   = (char*)m;
int   len = sizeof(*m);
int   r;

while(len > 0) {
r = adb_write(fd, p, len);
if(r > 0) {
len -= r;
p   += r;
} else {
if((r < 0) && (errno == EINTR)) continue;
D("transport_write_action: on fd %d, error %d: %s\n",
fd, errno, strerror(errno));
#if !ADB_HOST
__android_log_print(ANDROID_LOG_INFO, __FUNCTION__,
"transport_write_action: on fd %d, error %d: %s\n",
fd, errno, strerror(errno));
#endif
return -1;
}
}
return 0;
}

这样当读到adb驱动节点后,会把驱动传输的transport传给transport_registration_recv端,接下来我们就看下这块代码。

三、开启线程接受adb数据

还记得我们前面分析的这个函数嘛,当transport_registration_recv有数据时,就会调用transport_registration_func函数

void init_transport_registration(void)
{
int s[2];

if(adb_socketpair(s)){
fatal_errno("cannot open transport registration socketpair");
}
D("socketpair: (%d,%d)", s[0], s[1]);

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);
}我们来看下transport_registration_func这个函数

static void transport_registration_func(int _fd, unsigned ev, void *data)
{
tmsg m;
adb_thread_t output_thread_ptr;
adb_thread_t input_thread_ptr;
int s[2];
atransport *t;

if(!(ev & FDE_READ)) {
return;
}

if(transport_read_action(_fd, &m)) {
fatal_errno("cannot read transport registration socket");
}

t = m.transport;

它先调用了transport_read_action来读取transport_registration_recv的数据,也就是之前transport_registration_send发来的adb驱动节点的数据。然后把它保存在t这个变量中。

下面我们再来看看transport_registration_func函数中的另一段代码

if (t->connection_state != CS_NOPERM) {
/* initial references are the two threads */
t->ref_count = 2;

if(adb_socketpair(s)) {//建立一对socketpair
fatal_errno("cannot open transport socketpair");
}

D("transport: %s socketpair: (%d,%d) starting", t->serial, s[0], s[1]);

t->transport_socket = s[0];
t->fd = s[1];

fdevent_install(&(t->transport_fde),
t->transport_socket,//当transport_socket有数据时,调用transport_socket_events函数
transport_socket_events,
t);

fdevent_set(&(t->transport_fde), FDE_READ);

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");
}
}

上面这段代码建立了一对socketpair,然后开启了两个线程,我们来看下这两个线程

3.1 output_thread收adb驱动数据

我们先来看下output_thread这个线程:

static void *output_thread(void *_t)
{
atransport *t = reinterpret_cast<atransport*>(_t);
apacket *p;

D("%s: starting transport output thread on fd %d, SYNC online (%d)\n",
t->serial, t->fd, t->sync_token + 1);
p = get_apacket();
p->msg.command = A_SYNC;
p->msg.arg0 = 1;
p->msg.arg1 = ++(t->sync_token);
p->msg.magic = A_SYNC ^ 0xffffffff;
if(write_packet(t->fd, t->serial, &p)) {
put_apacket(p);
D("%s: failed to write SYNC packet\n", t->serial);
goto oops;
}

D("%s: data pump started\n", t->serial);
for(;;) {
p = get_apacket();//这个函数只是分配内存
if(t->read_from_remote(p, t) == 0){//这里是从adb驱动读取数据

if(write_packet(t->fd, t->serial, &p)){//这是是socketpair的一端写数据
put_apacket(p);
D("%s: failed to write apacket to transport\n", t->serial);
goto oops;
}
} else {
D("%s: remote read failed for transport\n", t->serial);
put_apacket(p);//出现异常,释放内存,跳出线程循环
break;
}
}

D("%s: SYNC offline for transport\n", t->serial);
p = get_apacket();
p->msg.command = A_SYNC;//读取adb节点异常退出线程
p->msg.arg0 = 0;
p->msg.arg1 = 0;
p->msg.magic = A_SYNC ^ 0xffffffff;
if(write_packet(t->fd, t->serial, &p)) {
put_apacket(p);
D("%s: failed to write SYNC apacket to transport", t->serial);
}

oops:
D("%s: transport output thread is exiting\n", t->serial);
kick_transport(t);
transport_unref(t);
return 0;
}

这个线程主要是从adb驱动读取数据,然后让socketpair的一端写入 从adb驱动读取的数据。

我们先看下read_from_remote这个函数,跟下如何从adb驱动读取数据的

在之前register_usb_transport的时候先调用了init_usb_transport,来初始化transport的一些函数等。

void init_usb_transport(atransport *t, usb_handle *h, int state)
{
D("transport: usb\n");
t->close = remote_close;
t->kick = remote_kick;
t->read_from_remote = remote_read;
t->write_to_remote = remote_write;
t->sync_token = 1;
t->connection_state = state;
t->type = kTransportUsb;
t->usb = h;

#if ADB_HOST
HOST = 1;
#else
HOST = 0;
#endif
}read_from_remote 函数也就是remote_read函数:

static int remote_read(apacket *p, atransport *t)
{
if(usb_read(t->usb, &p->msg, sizeof(amessage))){//这里就是从adb驱动读数据了
D("remote usb: read terminated (message)\n");
return -1;
}

if(check_header(p)) {//检查头部
D("remote usb: check_header failed\n");
return -1;
}

if(p->msg.data_length) {
if(usb_read(t->usb, p->data, p->msg.data_length)){
D("remote usb: terminated (data)\n");
return -1;
}
}

if(check_data(p)) {//查数据
D("remote usb: check_data failed\n");
return -1;
}

return 0;
}

在之前usb_adb_init函数中有如下代码:

static void usb_adb_init()
{
usb_handle* h = reinterpret_cast<usb_handle*>(calloc(1, sizeof(usb_handle)));
if (h == nullptr) fatal("couldn't allocate usb_handle");

h->write = usb_adb_write;
h->read = usb_adb_read;
h->kick = usb_adb_kick;
h->fd = -1;

因此最后调用read是调用了usb_adb_read函数,也就是读adb驱动里的内容。

usb_adb_read函数就是调用adb_read读取adb驱动数据,而adb_read就是从h->fd中去读取adb驱动数据。这个h->fd就是前面usb_adb_open_thread函数中打开/dev/android_adb(adb驱动节点)。

static int usb_adb_read(usb_handle *h, void *data, int len)
{
int n;

D("about to read (fd=%d, len=%d)\n", h->fd, len);
n = adb_read(h->fd, data, len);
if(n != len) {
D("ERROR: fd = %d, n = %d, errno = %d (%s)\n",
h->fd, n, errno, strerror(errno));
for (int i = 0; i < n; i++) {
char print = (char)*((char*)data + i);
LOG("%x ", print);
}
return -1;
}
D("[ done fd=%d ]\n", h->fd);
return 0;
}

3.2 output_thread数据发送数据后,处理数据

在output_thread中,读取了adb驱动的数据后,就调用write_packet(t->fd, t->serial, &p)函数,把数据网socketpair的一侧写。

这会导致socketpair的另一侧有数据,另一侧有数据会调用transport_socket_events函数来处理数据

static void transport_socket_events(int fd, unsigned events, void *_t)
{
atransport *t = reinterpret_cast<atransport*>(_t);
D("transport_socket_events(fd=%d, events=%04x,...)\n", fd, events);
if(events & FDE_READ){
apacket *p = 0;
if(read_packet(fd, t->serial, &p)){
D("%s: failed to read packet from transport socket on fd %d\n", t->serial, fd);
} else {
handle_packet(p, (atransport *) _t);
}
}
}


四、总结

我们主要分析了adb驱动节点初始化,驱动节点开启成功后会开启线程读取adb驱动节点的内容。

处理数据部分我们在下篇博客继续分析。



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  adbd