adb源码分析

本文深入解析了ADB(Android Debug Bridge)的工作原理和技术细节,包括ADB的编译配置、主要源码文件的功能、ADB守护进程adbd及客户端adb的启动流程、USB及网络通信的初始化过程等。特别关注ADB如何通过USB或网络与Android设备通信,以及ADB命令的执行流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

ADB是Android debug bridge的缩写,它使用PC机可以通过USB或网络与android设备通讯。
adb的源码位于system/core/adb目录下,先来看下编译脚本Android.mk:

# Copyright 2005 The Android Open Source Project  
#  
# Android.mk for adb  
#  

LOCAL_PATH:= $(call my-dir)  

# adb host tool  
# =========================================================  
include $(CLEAR_VARS)  

# Default to a virtual (sockets) usb interface  
USB_SRCS :=  
EXTRA_SRCS :=  

ifeq ($(HOST_OS),linux)  
  USB_SRCS := usb_linux.c  
  EXTRA_SRCS := get_my_path_linux.c  
  LOCAL_LDLIBS += -lrt -ldl -lpthread  
  LOCAL_CFLAGS += -DWORKAROUND_BUG6558362  
endif  

ifeq ($(HOST_OS),darwin)  
  USB_SRCS := usb_osx.c  
  EXTRA_SRCS := get_my_path_darwin.c  
  LOCAL_LDLIBS += -lpthread -framework CoreFoundation -framework IOKit -framework Carbon  
endif  

ifeq ($(HOST_OS),freebsd)  
  USB_SRCS := usb_libusb.c  
  EXTRA_SRCS := get_my_path_freebsd.c  
  LOCAL_LDLIBS += -lpthread -lusb  
endif  

ifeq ($(HOST_OS),windows)  
  USB_SRCS := usb_windows.c  
  EXTRA_SRCS := get_my_path_windows.c ../libcutils/list.c  
  EXTRA_STATIC_LIBS := AdbWinApi  
  ifneq ($(strip $(USE_CYGWIN)),)  
    # Pure cygwin case  
    LOCAL_LDLIBS += -lpthread -lgdi32  
    LOCAL_C_INCLUDES += /usr/include/w32api/ddk  
  endif  
  ifneq ($(strip $(USE_MINGW)),)  
    # MinGW under Linux case  
    LOCAL_LDLIBS += -lws2_32 -lgdi32  
    USE_SYSDEPS_WIN32 := 1  
    LOCAL_C_INCLUDES += /usr/i586-mingw32msvc/include/ddk  
  endif  
  LOCAL_C_INCLUDES += development/host/windows/usb/api/  
endif  

LOCAL_SRC_FILES := \  
    adb.c \  
    console.c \  
    transport.c \  
    transport_local.c \  
    transport_usb.c \  
    commandline.c \  
    adb_client.c \  
    adb_auth_host.c \  
    sockets.c \  
    services.c \  
    file_sync_client.c \  
    $(EXTRA_SRCS) \  
    $(USB_SRCS) \  
    usb_vendors.c  

LOCAL_C_INCLUDES += external/openssl/include  

ifneq ($(USE_SYSDEPS_WIN32),)  
  LOCAL_SRC_FILES += sysdeps_win32.c  
else  
  LOCAL_SRC_FILES += fdevent.c  
endif  

LOCAL_CFLAGS += -O2 -g -DADB_HOST=1  -Wall -Wno-unused-parameter  
LOCAL_CFLAGS += -D_XOPEN_SOURCE -D_GNU_SOURCE  
LOCAL_MODULE := adb  
LOCAL_MODULE_TAGS := debug  

LOCAL_STATIC_LIBRARIES := libzipfile libunz libcrypto_static $(EXTRA_STATIC_LIBS)  
ifeq ($(USE_SYSDEPS_WIN32),)  
    LOCAL_STATIC_LIBRARIES += libcutils  
endif  

include $(BUILD_HOST_EXECUTABLE)  

$(call dist-for-goals,dist_files sdk,$(LOCAL_BUILT_MODULE))  

ifeq ($(HOST_OS),windows)  
$(LOCAL_INSTALLED_MODULE): \  
    $(HOST_OUT_EXECUTABLES)/AdbWinApi.dll \  
    $(HOST_OUT_EXECUTABLES)/AdbWinUsbApi.dll  
endif  


# adbd device daemon  
# =========================================================  

include $(CLEAR_VARS)  

LOCAL_SRC_FILES := \  
    adb.c \  
    backup_service.c \  
    fdevent.c \  
    transport.c \  
    transport_local.c \  
    transport_usb.c \  
    adb_auth_client.c \  
    sockets.c \  
    services.c \  
    file_sync_service.c \  
    jdwp_service.c \  
    framebuffer_service.c \  
    remount_service.c \  
    usb_linux_client.c \  
    log_service.c  

LOCAL_CFLAGS := -O2 -g -DADB_HOST=0 -Wall -Wno-unused-parameter  
LOCAL_CFLAGS += -D_XOPEN_SOURCE -D_GNU_SOURCE  

ifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT)))  
LOCAL_CFLAGS += -DALLOW_ADBD_ROOT=1  
endif  

LOCAL_MODULE := adbd  

LOCAL_FORCE_STATIC_EXECUTABLE := true  
LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT_SBIN)  
LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_SBIN_UNSTRIPPED)  

LOCAL_STATIC_LIBRARIES := liblog libcutils libc libmincrypt  
include $(BUILD_EXECUTABLE)  


# adb host tool for device-as-host  
# =========================================================  
ifneq ($(SDK_ONLY),true)  
include $(CLEAR_VARS)  

LOCAL_LDLIBS := -lrt -ldl -lpthread  

LOCAL_SRC_FILES := \  
    adb.c \  
    console.c \  
    transport.c \  
    transport_local.c \  
    transport_usb.c \  
    commandline.c \  
    adb_client.c \  
    adb_auth_host.c \  
    sockets.c \  
    services.c \  
    file_sync_client.c \  
    get_my_path_linux.c \  
    usb_linux.c \  
    usb_vendors.c \  
    fdevent.c  

LOCAL_CFLAGS := \  
    -O2 \  
    -g \  
    -DADB_HOST=1 \  
    -DADB_HOST_ON_TARGET=1 \  
    -Wall \  
    -Wno-unused-parameter \  
    -D_XOPEN_SOURCE \  
    -D_GNU_SOURCE  

LOCAL_C_INCLUDES += external/openssl/include  

LOCAL_MODULE := adb  

LOCAL_STATIC_LIBRARIES := libzipfile libunz libcutils  

LOCAL_SHARED_LIBRARIES := libcrypto  

include $(BUILD_EXECUTABLE)  
endif  

可以看到,最终会有3个执行文件被生成,adbd和两个adb程序。adbd是手机终的守护进程;adb一个是windows、linux、darwin或freebsd运行的程序,另一个是目标机上运行的程序。
ADB_HOST用于区分是PC端程序还是目标机端的程序。宏ADB_HOST_ON_TARGET用于区分adb程序是否是在目标机上运行。这3个程序使用的是同一份源码,在内部,使用这些宏来区别不同的程序。
程序的入口在adb.c的main()函数:

int main(int argc, char **argv)  
{  
#if ADB_HOST  
    adb_sysdeps_init();  
    adb_trace_init();  
    D("Handling commandline()\n");  
    return adb_commandline(argc - 1, argv + 1);  
#else  
    /* If adbd runs inside the emulator this will enable adb tracing via 
     * adb-debug qemud service in the emulator. */  
    adb_qemu_trace_init();  
    if((argc > 1) && (!strcmp(argv[1],"recovery"))) {  
        adb_device_banner = "recovery";  
        recovery_mode = 1;  
    }  

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

先来看adbd程序,此时宏的设置是ADB_HOST=0。上面代码中start_device_log()是log的初始化操作,可以重定向输出的log信息,接着进入adb_main()函数。先来看下它的参数DEFAULT_ADB_PORT

#if ADB_HOST_ON_TARGET  
/* adb and adbd are coexisting on the target, so use 5038 for adb 
 * to avoid conflicting with adbd's usage of 5037 
 */  
#  define DEFAULT_ADB_PORT 5038  
#else  
#  define DEFAULT_ADB_PORT 5037  
#endif  

如果是目标机程序,它的值是5038,否则它的值是5037。这里没有定义ADB_HOST_ON_TARGET, 所以它是5037。
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);  
#ifdef HAVE_WIN32_PROC  
    SetConsoleCtrlHandler( ctrlc_handler, TRUE );  
#elif defined(HAVE_FORKEXEC)  
    // No SIGCHLD. Let the service subproc handle its children.  
    signal(SIGPIPE, SIG_IGN);  
#endif  

    init_transport_registration();  

#if ADB_HOST  
    HOST = 1;  
    usb_vendors_init();  
    usb_init();  
    local_init(DEFAULT_ADB_LOCAL_TRANSPORT_PORT);  
    adb_auth_init();  

    char local_name[30];  
    build_local_name(local_name, sizeof(local_name), server_port);  
    if(install_listener(local_name, "*smartsocket*", NULL)) {  
        exit(1);  
    }  
#else  
    property_get("ro.adb.secure", value, "0");  
    auth_enabled = !strcmp(value, "1");  
    if (auth_enabled)  
        adb_auth_init();  

    // Our external storage path may be different than apps, since  
    // we aren't able to bind mount after dropping root.  
    const char* adb_external_storage = getenv("ADB_EXTERNAL_STORAGE");  
    if (NULL != adb_external_storage) {  
        setenv("EXTERNAL_STORAGE", adb_external_storage, 1);  
    } else {  
        D("Warning: ADB_EXTERNAL_STORAGE is not set.  Leaving EXTERNAL_STORAGE"  
          " unchanged.\n");  
    }  

    /* don't listen on a port (default 5037) if running in secure mode */  
    /* don't run as root if we are running in secure mode */  
    if (should_drop_privileges()) {  
        struct __user_cap_header_struct header;  
        struct __user_cap_data_struct cap;  

        if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) != 0) {  
            exit(1);  
        }  

        /* add extra groups: 
        ** AID_ADB to access the USB driver 
        ** AID_LOG to read system logs (adb logcat) 
        ** AID_INPUT to diagnose input issues (getevent) 
        ** AID_INET to diagnose network issues (netcfg, ping) 
        ** AID_GRAPHICS to access the frame buffer 
        ** AID_NET_BT and AID_NET_BT_ADMIN to diagnose bluetooth (hcidump) 
        ** AID_SDCARD_R to allow reading from the SD card 
        ** AID_SDCARD_RW to allow writing to the SD card 
        ** AID_MOUNT to allow unmounting the SD card before rebooting 
        ** AID_NET_BW_STATS to read out qtaguid statistics 
        */  
        gid_t groups[] = { AID_ADB, AID_LOG, AID_INPUT, AID_INET, AID_GRAPHICS,  
                           AID_NET_BT, AID_NET_BT_ADMIN, AID_SDCARD_R, AID_SDCARD_RW,  
                           AID_MOUNT, AID_NET_BW_STATS };  
        if (setgroups(sizeof(groups)/sizeof(groups[0]), groups) != 0) {  
            exit(1);  
        }  

        /* then switch user and group to "shell" */  
        if (setgid(AID_SHELL) != 0) {  
            exit(1);  
        }  
        if (setuid(AID_SHELL) != 0) {  
            exit(1);  
        }  

        /* set CAP_SYS_BOOT capability, so "adb reboot" will succeed */  
        header.version = _LINUX_CAPABILITY_VERSION;  
        header.pid = 0;  
        cap.effective = cap.permitted = (1 << CAP_SYS_BOOT);  
        cap.inheritable = 0;  
        capset(&header, &cap);  

        D("Local port disabled\n");  
    } else {  
        char local_name[30];  
        build_local_name(local_name, sizeof(local_name), server_port);  
        if(install_listener(local_name, "*smartsocket*", NULL)) {  
            exit(1);  
        }  
    }  

    int usb = 0;  
    if (access(USB_ADB_PATH, F_OK) == 0 || access(USB_FFS_ADB_EP0, F_OK) == 0) {  
        // listen on USB  
        usb_init();  
        usb = 1;  
    }  

    // If one of these properties is set, also listen on that port  
    // If one of the properties isn't set and we couldn't listen on usb,  
    // listen on the default port.  
    property_get("service.adb.tcp.port", value, "");  
    if (!value[0]) {  
        property_get("persist.adb.tcp.port", value, "");  
    }  
    if (sscanf(value, "%d", &port) == 1 && port > 0) {  
        printf("using port=%d\n", port);  
        // listen on TCP port specified by service.adb.tcp.port property  
        local_init(port);  
    } else if (!usb) {  
        // listen on default port  
        local_init(DEFAULT_ADB_LOCAL_TRANSPORT_PORT);  
    }  

    D("adb_main(): pre init_jdwp()\n");  
    init_jdwp();  
    D("adb_main(): post init_jdwp()\n");  
#endif  

    if (is_daemon)  
    {  
        // inform our parent that we are up and running.  
#ifdef HAVE_WIN32_PROC  
        DWORD  count;  
        WriteFile( GetStdHandle( STD_OUTPUT_HANDLE ), "OK\n", 3, &count, NULL );  
#elif defined(HAVE_FORKEXEC)  
        fprintf(stderr, "OK\n");  
#endif  
        start_logging();  
    }  
    D("Event loop starting\n");  

    fdevent_loop();  

    usb_cleanup();  

    return 0;  
}  

(1) init_transport_registration()初始化fevent transport_registration_fde
(2) 判断系统属性ro.adb.secure,目标板没有设置这个宏;
(3) 没有定义环境变量adb_external_storage
(4)should_drop_privileges()根据android编译环境should_drop_privileges返回不同的值,如果它的值是userdebug或eng,宏ALLOW_ADBD_ROOT的值被定义为1,执行install_listener(),否则不会定义,这种情况下,由于adbd运行在root下,为保证它的安全性,它需要降级运行;
(5) 判断是否存在设备文件USB_ADB_PATHUSB_FFS_ADB_EP0,存在则执行usb_init()
(6) 读取属性service.adb.tcp.portpersist.adb.tcp.port(目标板均未定义),执行local_init(),它内部会创建adb thread
(7) 执行init_jdwp(),jdwp是Java调试体系中的一种,具体可百度;
(8) 调用fdevent_loop()监听fdevent并处理;
(9) 程序结束。

再来看adb程序的执行:
在main()中调用return adb_commandline(argc - 1, argv + 1)

int adb_commandline(int argc, char **argv)  
{  
    char buf[4096];  
    int no_daemon = 0;  
    int is_daemon = 0;  
    int is_server = 0;  
    int persist = 0;  
    int r;  
    int quote;  
    transport_type ttype = kTransportAny;  
    char* serial = NULL;  
    char* server_port_str = NULL;  

        /* If defined, this should be an absolute path to 
         * the directory containing all of the various system images 
         * for a particular product.  If not defined, and the adb 
         * command requires this information, then the user must 
         * specify the path using "-p". 
         */  
    gProductOutPath = getenv("ANDROID_PRODUCT_OUT");  
    if (gProductOutPath == NULL || gProductOutPath[0] == '\0') {  
        gProductOutPath = NULL;  
    }  
    // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint  

    serial = getenv("ANDROID_SERIAL");  

    /* Validate and assign the server port */  
    server_port_str = getenv("ANDROID_ADB_SERVER_PORT");  
    int server_port = DEFAULT_ADB_PORT;  
    if (server_port_str && strlen(server_port_str) > 0) {  
        server_port = (int) strtol(server_port_str, NULL, 0);  
        if (server_port <= 0) {  
            fprintf(stderr,  
                    "adb: Env var ANDROID_ADB_SERVER_PORT must be a positive number. Got \"%s\"\n",  
                    server_port_str);  
            return usage();  
        }  
    }  

    /* modifiers and flags */  
    while(argc > 0) {  
        if(!strcmp(argv[0],"server")) {  
            is_server = 1;  
        } else if(!strcmp(argv[0],"nodaemon")) {  
            no_daemon = 1;  
        } else if (!strcmp(argv[0], "fork-server")) {  
            /* this is a special flag used only when the ADB client launches the ADB Server */  
            is_daemon = 1;  
        } else if(!strcmp(argv[0],"persist")) {  
            persist = 1;  
        } else if(!strncmp(argv[0], "-p", 2)) {  
            const char *product = NULL;  
            if (argv[0][2] == '\0') {  
                if (argc < 2) return usage();  
                product = argv[1];  
                argc--;  
                argv++;  
            } else {  
                product = argv[0] + 2;  
            }  
            gProductOutPath = find_product_out_path(product);  
            if (gProductOutPath == NULL) {  
                fprintf(stderr, "adb: could not resolve \"-p %s\"\n",  
                        product);  
                return usage();  
            }  
        } else if (argv[0][0]=='-' && argv[0][1]=='s') {  
            if (isdigit(argv[0][2])) {  
                serial = argv[0] + 2;  
            } else {  
                if(argc < 2 || argv[0][2] != '\0') return usage();  
                serial = argv[1];  
                argc--;  
                argv++;  
            }  
        } else if (!strcmp(argv[0],"-d")) {  
            ttype = kTransportUsb;  
        } else if (!strcmp(argv[0],"-e")) {  
            ttype = kTransportLocal;  
        } else {  
                /* out of recognized modifiers and flags */  
            break;  
        }  
        argc--;  
        argv++;  
    }  

    adb_set_transport(ttype, serial);  
    adb_set_tcp_specifics(server_port);  

    if (is_server) {  
        if (no_daemon || is_daemon) {  
            r = adb_main(is_daemon, server_port);  
        } else {  
            r = launch_server(server_port);  
        }  
        if(r) {  
            fprintf(stderr,"* could not start server *\n");  
        }  
        return r;  
    }  

top:  
    if(argc == 0) {  
        return usage();  
    }  

    /* adb_connect() commands */  

    if(!strcmp(argv[0], "devices")) {  
        char *tmp;  
        char *listopt;  
        if (argc < 2)  
            listopt = "";  
        else if (argc == 2 && !strcmp(argv[1], "-l"))  
            listopt = argv[1];  
        else {  
            fprintf(stderr, "Usage: adb devices [-l]\n");  
            return 1;  
        }  
        snprintf(buf, sizeof buf, "host:%s%s", argv[0], listopt);  
        tmp = adb_query(buf);  
        if(tmp) {  
            printf("List of devices attached \n");  
            printf("%s\n", tmp);  
            return 0;  
        } else {  
            return 1;  
        }  
    }  

    if(!strcmp(argv[0], "connect")) {  
        char *tmp;  
        if (argc != 2) {  
            fprintf(stderr, "Usage: adb connect <host>[:<port>]\n");  
            return 1;  
        }  
        snprintf(buf, sizeof buf, "host:connect:%s", argv[1]);  
        tmp = adb_query(buf);  
        if(tmp) {  
            printf("%s\n", tmp);  
            return 0;  
        } else {  
            return 1;  
        }  
    }  

    if(!strcmp(argv[0], "disconnect")) {  
        char *tmp;  
        if (argc > 2) {  
            fprintf(stderr, "Usage: adb disconnect [<host>[:<port>]]\n");  
            return 1;  
        }  
        if (argc == 2) {  
            snprintf(buf, sizeof buf, "host:disconnect:%s", argv[1]);  
        } else {  
            snprintf(buf, sizeof buf, "host:disconnect:");  
        }  
        tmp = adb_query(buf);  
        if(tmp) {  
            printf("%s\n", tmp);  
            return 0;  
        } else {  
            return 1;  
        }  
    }  

    if (!strcmp(argv[0], "emu")) {  
        return adb_send_emulator_command(argc, argv);  
    }  

    if(!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) {  
        int r;  
        int fd;  

        char h = (argv[0][0] == 'h');  

        if (h) {  
            printf("\x1b[41;33m");  
            fflush(stdout);  
        }  

        if(argc < 2) {  
            D("starting interactive shell\n");  
            r = interactive_shell();  
            if (h) {  
                printf("\x1b[0m");  
                fflush(stdout);  
            }  
            return r;  
        }  

        snprintf(buf, sizeof buf, "shell:%s", argv[1]);  
        argc -= 2;  
        argv += 2;  
        while(argc-- > 0) {  
            strcat(buf, " ");  

            /* quote empty strings and strings with spaces */  
            quote = (**argv == 0 || strchr(*argv, ' '));  
            if (quote)  
                strcat(buf, "\"");  
            strcat(buf, *argv++);  
            if (quote)  
                strcat(buf, "\"");  
        }  

        for(;;) {  
            D("interactive shell loop. buff=%s\n", buf);  
            fd = adb_connect(buf);  
            if(fd >= 0) {  
                D("about to read_and_dump(fd=%d)\n", fd);  
                read_and_dump(fd);  
                D("read_and_dump() done.\n");  
                adb_close(fd);  
                r = 0;  
            } else {  
                fprintf(stderr,"error: %s\n", adb_error());  
                r = -1;  
            }  

            if(persist) {  
                fprintf(stderr,"\n- waiting for device -\n");  
                adb_sleep_ms(1000);  
                do_cmd(ttype, serial, "wait-for-device", 0);  
            } else {  
                if (h) {  
                    printf("\x1b[0m");  
                    fflush(stdout);  
                }  
                D("interactive shell loop. return r=%d\n", r);  
                return r;  
            }  
        }  
    }  

    if(!strcmp(argv[0], "kill-server")) {  
        int fd;  
        fd = _adb_connect("host:kill");  
        if(fd == -1) {  
            fprintf(stderr,"* server not running *\n");  
            return 1;  
        }  
        return 0;  
    }  

    if(!strcmp(argv[0], "sideload")) {  
        if(argc != 2) return usage();  
        if(adb_download("sideload", argv[1], 1)) {  
            return 1;  
        } else {  
            return 0;  
        }  
    }  

    if(!strcmp(argv[0], "remount") || !strcmp(argv[0], "reboot")  
            || !strcmp(argv[0], "reboot-bootloader")  
            || !strcmp(argv[0], "tcpip") || !strcmp(argv[0], "usb")  
            || !strcmp(argv[0], "root")) {  
        char command[100];  
        if (!strcmp(argv[0], "reboot-bootloader"))  
            snprintf(command, sizeof(command), "reboot:bootloader");  
        else if (argc > 1)  
            snprintf(command, sizeof(command), "%s:%s", argv[0], argv[1]);  
        else  
            snprintf(command, sizeof(command), "%s:", argv[0]);  
        int fd = adb_connect(command);  
        if(fd >= 0) {  
            read_and_dump(fd);  
            adb_close(fd);  
            return 0;  
        }  
        fprintf(stderr,"error: %s\n", adb_error());  
        return 1;  
    }  

    if(!strcmp(argv[0], "bugreport")) {  
        if (argc != 1) return usage();  
        do_cmd(ttype, serial, "shell", "bugreport", 0);  
        return 0;  
    }  

    /* adb_command() wrapper commands */  

    if(!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {  
        char* service = argv[0];  
        if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) {  
            if (ttype == kTransportUsb) {  
                service = "wait-for-usb";  
            } else if (ttype == kTransportLocal) {  
                service = "wait-for-local";  
            } else {  
                service = "wait-for-any";  
            }  
        }  

        format_host_command(buf, sizeof buf, service, ttype, serial);  

        if (adb_command(buf)) {  
            D("failure: %s *\n",adb_error());  
            fprintf(stderr,"error: %s\n", adb_error());  
            return 1;  
        }  

        /* Allow a command to be run after wait-for-device, 
            * e.g. 'adb wait-for-device shell'. 
            */  
        if(argc > 1) {  
            argc--;  
            argv++;  
            goto top;  
        }  
        return 0;  
    }  

    if(!strcmp(argv[0], "forward")) {  
        if(argc != 3) return usage();  
        if (serial) {  
            snprintf(buf, sizeof buf, "host-serial:%s:forward:%s;%s",serial, argv[1], argv[2]);  
        } else if (ttype == kTransportUsb) {  
            snprintf(buf, sizeof buf, "host-usb:forward:%s;%s", argv[1], argv[2]);  
        } else if (ttype == kTransportLocal) {  
            snprintf(buf, sizeof buf, "host-local:forward:%s;%s", argv[1], argv[2]);  
        } else {  
            snprintf(buf, sizeof buf, "host:forward:%s;%s", argv[1], argv[2]);  
        }  
        if(adb_command(buf)) {  
            fprintf(stderr,"error: %s\n", adb_error());  
            return 1;  
        }  
        return 0;  
    }  

    /* do_sync_*() commands */  

    if(!strcmp(argv[0], "ls")) {  
        if(argc != 2) return usage();  
        return do_sync_ls(argv[1]);  
    }  

    if(!strcmp(argv[0], "push")) {  
        if(argc != 3) return usage();  
        return do_sync_push(argv[1], argv[2], 0 /* no verify APK */);  
    }  

    if(!strcmp(argv[0], "pull")) {  
        if (argc == 2) {  
            return do_sync_pull(argv[1], ".");  
        } else if (argc == 3) {  
            return do_sync_pull(argv[1], argv[2]);  
        } else {  
            return usage();  
        }  
    }  

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

    if(!strcmp(argv[0], "sync")) {  
        char *srcarg, *android_srcpath, *data_srcpath;  
        int listonly = 0;  

        int ret;  
        if(argc < 2) {  
            /* No local path was specified. */  
            srcarg = NULL;  
        } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {  
            listonly = 1;  
            if (argc == 3) {  
                srcarg = argv[2];  
            } else {  
                srcarg = NULL;  
            }  
        } else if(argc == 2) {  
            /* A local path or "android"/"data" arg was specified. */  
            srcarg = argv[1];  
        } else {  
            return usage();  
        }  
        ret = find_sync_dirs(srcarg, &android_srcpath, &data_srcpath);  
        if(ret != 0) return usage();  

        if(android_srcpath != NULL)  
            ret = do_sync_sync(android_srcpath, "/system", listonly);  
        if(ret == 0 && data_srcpath != NULL)  
            ret = do_sync_sync(data_srcpath, "/data", listonly);  

        free(android_srcpath);  
        free(data_srcpath);  
        return ret;  
    }  

    /* passthrough commands */  

    if(!strcmp(argv[0],"get-state") ||  
        !strcmp(argv[0],"get-serialno") ||  
        !strcmp(argv[0],"get-devpath"))  
    {  
        char *tmp;  

        format_host_command(buf, sizeof buf, argv[0], ttype, serial);  
        tmp = adb_query(buf);  
        if(tmp) {  
            printf("%s\n", tmp);  
            return 0;  
        } else {  
            return 1;  
        }  
    }  

    /* other commands */  

    if(!strcmp(argv[0],"status-window")) {  
        status_window(ttype, serial);  
        return 0;  
    }  

    if(!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {  
        return logcat(ttype, serial, argc, argv);  
    }  

    if(!strcmp(argv[0],"ppp")) {  
        return ppp(argc, argv);  
    }  

    if (!strcmp(argv[0], "start-server")) {  
        return adb_connect("host:start-server");  
    }  

    if (!strcmp(argv[0], "backup")) {  
        return backup(argc, argv);  
    }  

    if (!strcmp(argv[0], "restore")) {  
        return restore(argc, argv);  
    }  

    if (!strcmp(argv[0], "jdwp")) {  
        int  fd = adb_connect("jdwp");  
        if (fd >= 0) {  
            read_and_dump(fd);  
            adb_close(fd);  
            return 0;  
        } else {  
            fprintf(stderr, "error: %s\n", adb_error());  
            return -1;  
        }  
    }  

    /* "adb /?" is a common idiom under Windows */  
    if(!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {  
        help();  
        return 0;  
    }  

    if(!strcmp(argv[0], "version")) {  
        version(stdout);  
        return 0;  
    }  

    usage();  
    return 1;  
}  

它的代码有点长,但可以很容易看明白它根据命令的参数执行不同的功能。adb程序可能以服务的方式或命令行客户端的方式运行。
以上就是main()函数的执行过程

usb_linux_client.c中的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;  
    adb_thread_t tid;  
    int fd;  

    h = calloc(1, sizeof(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.  
    fd = unix_open("/dev/android_adb_enable", O_RDWR);  
    if (fd < 0) {  
       D("failed to open /dev/android_adb_enable\n");  
    } else {  
        close_on_exec(fd);  
    }  

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

它初始化了usb_handle,并把它作为参数创建usb_adb_open_thread()线程。这里不能打开/dev/android_adb_enableh->fd的值会在线程usb_adb_open_thread中赋值,并把它做为h->write(),h->read(), h->kick()的文件句柄,h->kick()函数功能是把h->fd置为-1。
usb_adb_open_thread的代码如下:

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

    while (1) {  
        // 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);  
            if (fd < 0) {  
                // to support older kernels  
                fd = unix_open("/dev/android", O_RDWR);  
            }  
            if (fd < 0) {  
                adb_sleep_ms(1000);  
            }  
        } while (fd < 0);  
        D("[ opening device succeeded ]\n");  

        close_on_exec(fd);  
        usb->fd = fd;  

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

    // never gets here  
    return 0;  
}  

这个线程的作用是一进入立即打开/dev/android_adb/dev/Android,如果成功,则调用register_usb_transport()后再次循环,并阻塞在以下代码处

while(usb->fd != -1)
   adb_cond_wait(&usb->notify, &usb->lock);

usb->kick()调用后fd的值被赋为-1,并发送cond唤醒上面的代码。

分析 fdevent.c的源代码。
这个源代码文件的工作时创建、监听和处理读写事件。

static fdevent **fd_table = 0;  
static int fd_table_max = 0;  

fd_table保存的是以fdevent->fd为索引保存的fdevent指针,即
the_fdevent的值等于fd_table[the_fdevent->fd]

static void fdevent_register(fdevent *fde)  //即将fde添加到fd_table  
{  
    if(fde->fd < 0) {  
        FATAL("bogus negative fd (%d)\n", fde->fd);  
    }  

    if(fde->fd >= fd_table_max) {  //这段代码即初始化或自动增长fd_table  
        int oldmax = fd_table_max;  
        if(fde->fd > 32000) {  
            FATAL("bogus huuuuge fd (%d)\n", fde->fd);  
        }  
        if(fd_table_max == 0) {  
            fdevent_init();  
            fd_table_max = 256;  
        }  
        while(fd_table_max <= fde->fd) {  
            fd_table_max *= 2;  
        }  
        fd_table = realloc(fd_table, sizeof(fdevent*) * fd_table_max);  
        if(fd_table == 0) {  
            FATAL("could not expand fd_table to %d entries\n", fd_table_max);  
        }  
        memset(fd_table + oldmax, 0, sizeof(int) * (fd_table_max - oldmax));  
    }  

    fd_table[fde->fd] = fde;   //将fde添加到fd_table  
}  

static void fdevent_unregister(fdevent *fde) //这个函数即将fde从fd_table中删除  
{  
    if((fde->fd < 0) || (fde->fd >= fd_table_max)) {  
        FATAL("fd out of range (%d)\n", fde->fd);  
    }  

    if(fd_table[fde->fd] != fde) {  
        FATAL("fd_table out of sync [%d]\n", fde->fd);  
    }  

    fd_table[fde->fd] = 0;  

    if(!(fde->state & FDE_DONT_CLOSE)) { //如果fde->fd打开了并没有关闭,需要执行关闭操作  
        dump_fde(fde, "close");  
        adb_close(fde->fd);  
    }  
}  

fdevent是代码处理事件的载体,它的定义如下:

struct fdevent   
{  
    fdevent *next;     //循环链表  
    fdevent *prev;  

    int fd;         //句柄  
    int force_eof;  

    unsigned short state;     //低8位表示事件,高8位表示状态  
    unsigned short events;    //需要处理的事件  

    fd_func func;         //事件处理回调函数  
    void *arg;            //参数  
};  

其中事件可以是:

#define FDE_READ              0x0001  
#define FDE_WRITE             0x0002  
#define FDE_ERROR             0x0004  
#define FDE_TIMEOUT           0x0008  
#define FDE_DONT_CLOSE       0x0080  

//掩码  
#define FDE_EVENTMASK  0x00ff  

状态可以是:

#define FDE_ACTIVE     0x0100  
#define FDE_PENDING    0x0200  
#define FDE_CREATED    0x0400  

//掩码  
#define FDE_STATEMASK  0xff00  

注意,这些状态是可以同时存在的。
当调用fdevent_create()后,FDE_CREATED标志被设置,当调用fdevent_install()后, FDE_CREATED标志被设置,但在fdevent_create()内部调用了fdevent_install(),所以调用fdevent_create()都被设置了。当有事件在调用select发生后,相应的事件state会设置为FDE_PENDING,当事件处理完后这个标志又被删除。相应的代码是:

void fdevent_loop()  
{  
    fdevent *fde;  
    fdevent_subproc_setup();  

    for(;;) {  
        D("--- ---- waiting for events\n");  

        fdevent_process(); //在这个函数中调用select,当有事件发生时,state被设置为FDE_PENDING,event也会被设置。所有的pending事件都会被保存在全局变量list_pending中。  

        while((fde = fdevent_plist_dequeue())) {   //处理list_pending变量的事件  
            fdevent_call_fdfunc(fde);  
        }  
    }  
}  

list_pending的相关代码:

//变量定义和初始化  
static fdevent list_pending = {  
    .next = &list_pending,  
    .prev = &list_pending,  
};  

//添加一个元素  
static void fdevent_plist_enqueue(fdevent *node)  
{  
    fdevent *list = &list_pending;  

    node->next = list;  
    node->prev = list->prev;  
    node->prev->next = node;  
    list->prev = node;  
}  

//删除一个指定元素  
static void fdevent_plist_remove(fdevent *node)  
{  
    node->prev->next = node->next;  
    node->next->prev = node->prev;  
    node->next = 0;  
    node->prev = 0;  
}  

//从list中取出一个元素  
static fdevent *fdevent_plist_dequeue(void)  
{  
    fdevent *list = &list_pending;  
    fdevent *node = list->next;  

    if(node == list) return 0;  

    list->next = node->next;  
    list->next->prev = list;  
    node->next = 0;  
    node->prev = 0;  

    return node;  
}  

事件的处理是阻塞方式的,可以有两种代码实现方法。定义宏CRAPTASTIC表示使用epoll的方式,否则使用select方式。我这里只讲select的处理方式:

static fd_set read_fds;        //读事件集合  
static fd_set write_fds;       //写事件集合  
static fd_set error_fds;       //发生错误事件集合  

static int select_n = 0;  

static void fdevent_init(void)  //初始化  
{  
    FD_ZERO(&read_fds);  
    FD_ZERO(&write_fds);  
    FD_ZERO(&error_fds);  
}  

static void fdevent_connect(fdevent *fde)   //添加  
{  
    if(fde->fd >= select_n) {  
        select_n = fde->fd + 1;  
    }  
}  

static void fdevent_disconnect(fdevent *fde)  //从所有事件集合删除fde  
{  
    int i, n;  

    FD_CLR(fde->fd, &read_fds);  
    FD_CLR(fde->fd, &write_fds);  
    FD_CLR(fde->fd, &error_fds);  

    for(n = 0, i = 0; i < select_n; i++) {  
        if(fd_table[i] != 0) n = i;  
    }  
    select_n = n + 1;  
}  

static void fdevent_update(fdevent *fde, unsigned events)//根据events设置事件集合  
{  
    if(events & FDE_READ) {  
        FD_SET(fde->fd, &read_fds);  
    } else {  
        FD_CLR(fde->fd, &read_fds);  
    }  
    if(events & FDE_WRITE) {  
        FD_SET(fde->fd, &write_fds);  
    } else {  
        FD_CLR(fde->fd, &write_fds);  
    }  
    if(events & FDE_ERROR) {  
        FD_SET(fde->fd, &error_fds);  
    } else {  
        FD_CLR(fde->fd, &error_fds);  
    }  

    fde->state = (fde->state & FDE_STATEMASK) | events;  
}  

/* Looks at fd_table[] for bad FDs and sets bit in fds. 
** Returns the number of bad FDs. 
*/  
static int fdevent_fd_check(fd_set *fds) //通过调用fcntl来判断是否是一个有效的fdevent  
{  
    int i, n = 0;  
    fdevent *fde;  

    for(i = 0; i < select_n; i++) {  
        fde = fd_table[i];  
        if(fde == 0) continue;  
        if(fcntl(i, F_GETFL, NULL) < 0) {  
            FD_SET(i, fds);  
            n++;  
            // fde->state |= FDE_DONT_CLOSE;  

        }  
    }  
    return n;  
} 

分析transport.c。
transport的原理是使用了fevent机制进行数据传输,atransport的定义如下:

struct atransport  
{  
    atransport *next;  
    atransport *prev;  

    int (*read_from_remote)(apacket *p, atransport *t);  
    int (*write_to_remote)(apacket *p, atransport *t);  
    void (*close)(atransport *t);  
    void (*kick)(atransport *t);  

    int fd;  
    int transport_socket;  
    fdevent transport_fde;  
    int ref_count;  
    unsigned sync_token;  
    int connection_state;  
    int online;  
    transport_type type;  

        /* usb handle or socket fd as needed */  
    usb_handle *usb;  
    int sfd;  

        /* used to identify transports for clients */  
    char *serial;  
    char *product;  
    char *model;  
    char *device;  
    char *devpath;  
    int adb_port; // Use for emulators (local transport)  

        /* a list of adisconnect callbacks called when the transport is kicked */  
    int          kicked;  
    adisconnect  disconnects;  

    void *key;  
    unsigned char token[TOKEN_SIZE];  
    fdevent auth_fde;  
    unsigned failed_auth_attempts;  
};  

它是一个双向链表,所有的实体都保存在全局数据transport_list中:

static atransport transport_list = {  
    .next = &transport_list,  
    .prev = &transport_list,  
};  

atransport的数据传输的两个函数是:

static int  
read_packet(int  fd, const char* name, apacket** ppacket)  
{  
    char *p = (char*)ppacket;  /* really read a packet address */  
    int   r;  
    int   len = sizeof(*ppacket);  
    char  buff[8];  
    if (!name) {  
        snprintf(buff, sizeof buff, "fd=%d", fd);  
        name = buff;  
    }  
    while(len > 0) {  
        r = adb_read(fd, p, len);  
        if(r > 0) {  
            len -= r;  
            p   += r;  
        } else {  
            D("%s: read_packet (fd=%d), error ret=%d errno=%d: %s\n", name, fd, r, errno, strerror(errno));  
            if((r < 0) && (errno == EINTR)) continue;  
            return -1;  
        }  
    }  

#if ADB_TRACE  
    if (ADB_TRACING) {  
        dump_packet(name, "from remote", *ppacket);  
    }  
#endif  
    return 0;  
}  

static int  
write_packet(int  fd, const char* name, apacket** ppacket)  
{  
    char *p = (char*) ppacket;  /* we really write the packet address */  
    int r, len = sizeof(ppacket);  
    char buff[8];  
    if (!name) {  
        snprintf(buff, sizeof buff, "fd=%d", fd);  
        name = buff;  
    }  

#if ADB_TRACE  
    if (ADB_TRACING) {  
        dump_packet(name, "to remote", *ppacket);  
    }  
#endif  
    len = sizeof(ppacket);  
    while(len > 0) {  
        r = adb_write(fd, p, len);  
        if(r > 0) {  
            len -= r;  
            p += r;  
        } else {  
            D("%s: write_packet (fd=%d) error ret=%d errno=%d: %s\n", name, fd, r, errno, strerror(errno));  
            if((r < 0) && (errno == EINTR)) continue;  
            return -1;  
        }  
    }  
    return 0;  
}  

这是它的内部传输接口,注意传输的是apacket的数据内部。
外部接口的数据传输接口是:

static void transport_socket_events(int fd, unsigned events, void *_t)  
{  
    atransport *t = _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);  
        }  
    }  
}  

void send_packet(apacket *p, atransport *t)  
{  
    unsigned char *x;  
    unsigned sum;  
    unsigned count;  

    p->msg.magic = p->msg.command ^ 0xffffffff;  

    count = p->msg.data_length;  
    x = (unsigned char *) p->data;  
    sum = 0;  
    while(count-- > 0){  
        sum += *x++;  
    }  
    p->msg.data_check = sum;  

    print_packet("send", p);  

    if (t == NULL) {  
        D("Transport is null \n");  
        // Zap errno because print_packet() and other stuff have errno effect.  
        errno = 0;  
        fatal_errno("Transport is null");  
    }  

    if(write_packet(t->transport_socket, t->serial, &p)){  
        fatal_errno("cannot enqueue packet on transport socket");  
    }  
}  

物理接口到atransport的接口是:

/* The transport is opened by transport_register_func before 
** the input and output threads are started. 
** 
** The output thread issues a SYNC(1, token) message to let 
** the input thread know to start things up.  In the event 
** of transport IO failure, the output thread will post a 
** SYNC(0,0) message to ensure shutdown. 
** 
** The transport will not actually be closed until both 
** threads exit, but the input thread will kick the transport 
** on its way out to disconnect the underlying device. 
*/  

static void *output_thread(void *_t)  
{  
    atransport *t = _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){  
            D("%s: received remote packet, sending to transport\n",  
              t->serial);  
            if(write_packet(t->fd, t->serial, &p)){  
                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;  
    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;  
}  

static void *input_thread(void *_t)  
{  
    atransport *t = _t;  
    apacket *p;  
    int active = 0;  

    D("%s: starting transport input thread, reading from fd %d\n",  
       t->serial, t->fd);  

    for(;;){  
        if(read_packet(t->fd, t->serial, &p)) {  
            D("%s: failed to read apacket from transport on fd %d\n",  
               t->serial, t->fd );  
            break;  
        }  
        if(p->msg.command == A_SYNC){  
            if(p->msg.arg0 == 0) {  
                D("%s: transport SYNC offline\n", t->serial);  
                put_apacket(p);  
                break;  
            } else {  
                if(p->msg.arg1 == t->sync_token) {  
                    D("%s: transport SYNC online\n", t->serial);  
                    active = 1;  
                } else {  
                    D("%s: transport ignoring SYNC %d != %d\n",  
                      t->serial, p->msg.arg1, t->sync_token);  
                }  
            }  
        } else {  
            if(active) {  
                D("%s: transport got packet, sending to remote\n", t->serial);  
                t->write_to_remote(p, t);  
            } else {  
                D("%s: transport ignoring packet while offline\n", t->serial);  
            }  
        }  

        put_apacket(p);  
    }  

    // this is necessary to avoid a race condition that occured when a transport closes  
    // while a client socket is still active.  
    close_all_sockets(t);  

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

这里,源码做了一个物理到抽象的转换。最上层还有一层是tmsg的传输(作者为什么要这么绕,实在是看得不明白):

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

/* the fdevent select pump is single threaded */  
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");  
    }  
}  

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

tmsg的作用是用于atransport的管理。

以“adb devices”命令为例,跟踪代码的执行流程。
(1) main()->
(2)adb_commandline()->
adb_commandline()中的相关源码:

if(!strcmp(argv[0], "devices")) {  
    char *tmp;  
    char *listopt;  
    if (argc < 2)  
        listopt = "";  
    else if (argc == 2 && !strcmp(argv[1], "-l"))  
        listopt = argv[1];  
    else {  
        fprintf(stderr, "Usage: adb devices [-l]\n");  
        return 1;  
    }  
    snprintf(buf, sizeof buf, "host:%s%s", argv[0], listopt);  
    tmp = adb_query(buf); //传递的buf=”host:devices”  
    if(tmp) { //命令执行成功,打印出信息  
        printf("List of devices attached \n");  
        printf("%s\n", tmp);  
        return 0;  
    } else {///失败  
        return 1;  
    }  
} 

(3)adb_query():adb_query: host:devices ->

char *adb_query(const char *service) //函数返回设备信息字符串  
{  
    char buf[5];  
    unsigned n;  
    char *tmp;  

    D("adb_query: %s\n", service);  
    int fd = adb_connect(service);  //连接adbserver,返回fd  
    if(fd < 0) {  
        fprintf(stderr,"error: %s\n", __adb_error);  
        return 0;  
    }  

    if(readx(fd, buf, 4)) goto oops;   //读取数据长度,如果失败则返回错误  

    buf[4] = 0;  
    n = strtoul(buf, 0, 16);      //转换成数值  
    if(n > 1024) goto oops;  

    tmp = malloc(n + 1);     //申请空间  
    if(tmp == 0) goto oops;  

    if(readx(fd, tmp, n) == 0) {   //读取信息并返回  
        tmp[n] = 0;  
        adb_close(fd);  
        return tmp;  
    }  
    free(tmp);  

oops:  
    adb_close(fd);  
    return 0;  
}  

(4) adb_connect()->
这个函数的作用是连接adb server,如果adb server没有启动则先启动它。

int adb_connect(const char *service)  
{  
    // first query the adb server's version  
    int fd = _adb_connect("host:version");  //查询adb server的版本信息,用来判断它是否启动。  

    D("adb_connect: service %s\n", service);  
    if(fd == -2) { //查询不到adb server  
        fprintf(stdout,"* daemon not running. starting it now on port %d *\n",  
                __adb_server_port);  
    start_server: //启动adb server  
        if(launch_server(__adb_server_port)) { //启动adb server失败  
            fprintf(stderr,"* failed to start daemon *\n");  
            return -1;  
        } else {  
            fprintf(stdout,"* daemon started successfully *\n");  
        }  
        /* give the server some time to start properly and detect devices */  
        adb_sleep_ms(3000);  
        // fall through to _adb_connect  
    } else {//查询到adb server版本信息,说明adb server 已经启动  
        // if server was running, check its version to make sure it is not out of date  
        char buf[100];  
        int n;  
        int version = ADB_SERVER_VERSION - 1;  

        // if we have a file descriptor, then parse version result  
        if(fd >= 0) {  
            if(readx(fd, buf, 4)) goto error; //读取版本信息的长度  

            buf[4] = 0;  
            n = strtoul(buf, 0, 16);  
            if(n > (int)sizeof(buf)) goto error;  
            if(readx(fd, buf, n)) goto error;//读取版本信息  
            adb_close(fd);  

            if (sscanf(buf, "%04x", &version) != 1) goto error;//转换字符串的版本为数值型  
        } else { //fd返回的值表示adb server可能不支持读取版本信息  
            // if fd is -1, then check for "unknown host service",  
            // which would indicate a version of adb that does not support the version command  
            if (strcmp(__adb_error, "unknown host service") != 0)  
                return fd;  //返回错误。  
        }  

        if(version != ADB_SERVER_VERSION) {  
            printf("adb server is out of date.  killing...\n");  
            fd = _adb_connect("host:kill");  
            adb_close(fd);  

            /* XXX can we better detect its death? */  
            adb_sleep_ms(2000);  
            goto start_server; //版本信息过期则关闭adb server并重新启动。  
        }  
    }  

    // if the command is start-server, we are done.  
    if (!strcmp(service, "host:start-server"))  //如果命令是start-server,执行到这就可以了  
        return 0;  

   //下面的代码连接adb server并返回fd。  
    fd = _adb_connect(service); //连接adb server 并返回fd。  
    if(fd == -2) {  
        fprintf(stderr,"** daemon still not running");  
    }  
    D("adb_connect: return fd %d\n", fd);  

    return fd;  
error:  
    adb_close(fd);  
    return -1;  
}  

(5) launch_server()

#if ADB_HOST  
int launch_server(int server_port)  
{  
#ifdef HAVE_WIN32_PROC  
    /* we need to start the server in the background                    */  
    /* we create a PIPE that will be used to wait for the server's "OK" */  
    /* message since the pipe handles must be inheritable, we use a     */  
    /* security attribute                                               */  
    HANDLE                pipe_read, pipe_write;  
    SECURITY_ATTRIBUTES   sa;  
    STARTUPINFO           startup;  
    PROCESS_INFORMATION   pinfo;  
    char                  program_path[ MAX_PATH ];  
    int                   ret;  

    sa.nLength = sizeof(sa);  
    sa.lpSecurityDescriptor = NULL;  
    sa.bInheritHandle = TRUE;  

    /* create pipe, and ensure its read handle isn't inheritable */  
    ret = CreatePipe( &pipe_read, &pipe_write, &sa, 0 );  
    if (!ret) {  
        fprintf(stderr, "CreatePipe() failure, error %ld\n", GetLastError() );  
        return -1;  
    }  

    SetHandleInformation( pipe_read, HANDLE_FLAG_INHERIT, 0 );  

    ZeroMemory( &startup, sizeof(startup) );  
    startup.cb = sizeof(startup);  
    startup.hStdInput  = GetStdHandle( STD_INPUT_HANDLE );  
    startup.hStdOutput = pipe_write;  
    startup.hStdError  = GetStdHandle( STD_ERROR_HANDLE );  
    startup.dwFlags    = STARTF_USESTDHANDLES;  

    ZeroMemory( &pinfo, sizeof(pinfo) );  

    /* get path of current program */  
    GetModuleFileName( NULL, program_path, sizeof(program_path) );  

//创建进程“adb fork-server server”,并把startup信息传给新进程。  
    ret = CreateProcess(  
            program_path,                              /* program path  */  
            "adb fork-server server",  
                                    /* the fork-server argument will set the 
                                       debug = 2 in the child           */  
            NULL,                   /* process handle is not inheritable */  
            NULL,                    /* thread handle is not inheritable */  
            TRUE,                          /* yes, inherit some handles */  
            DETACHED_PROCESS, /* the new process doesn't have a console */  
            NULL,                     /* use parent's environment block */  
            NULL,                    /* use parent's starting directory */  
            &startup,                 /* startup info, i.e. std handles */  
            &pinfo );  

    CloseHandle( pipe_write );  

    if (!ret) {  
        fprintf(stderr, "CreateProcess failure, error %ld\n", GetLastError() );  
        CloseHandle( pipe_read );  
        return -1;  
    }  

    CloseHandle( pinfo.hProcess );  
    CloseHandle( pinfo.hThread );  

    /* wait for the "OK\n" message */  
    {  
        char  temp[3];  
        DWORD  count;  

//等待新进程发送“OK”到pipe_read管道。  
        ret = ReadFile( pipe_read, temp, 3, &count, NULL );  
        CloseHandle( pipe_read );  
        if ( !ret ) {  
            fprintf(stderr, "could not read ok from ADB Server, error = %ld\n", GetLastError() );  
            return -1;  
        }  
        if (count != 3 || temp[0] != 'O' || temp[1] != 'K' || temp[2] != '\n') {  
            fprintf(stderr, "ADB server didn't ACK\n" );  
            return -1;  
        }  
    }  
#elif defined(HAVE_FORKEXEC)  
    char    path[PATH_MAX];  
    int     fd[2];  

    // set up a pipe so the child can tell us when it is ready.  
    // fd[0] will be parent's end, and fd[1] will get mapped to stderr in the child.  
    if (pipe(fd)) {  
        fprintf(stderr, "pipe failed in launch_server, errno: %d\n", errno);  
        return -1;  
    }  
    get_my_path(path, PATH_MAX);  
    pid_t pid = fork();  
    if(pid < 0) return -1;  

    if (pid == 0) {  //下面的代码在子进程中运行  
        // child side of the fork  

        // redirect stderr to the pipe  
        // we use stderr instead of stdout due to stdout's buffering behavior.  
        adb_close(fd[0]);  
        dup2(fd[1], STDERR_FILENO);  //重定向新进程的错误信息给fd[1]  
        adb_close(fd[1]);  

        // child process 运行”adb fok-server server”程序。  
        int result = execl(path, "adb", "fork-server", "server", NULL);  
        // this should not return  
        fprintf(stderr, "OOPS! execl returned %d, errno: %d\n", result, errno);  
    } else  {//下面的代码还是在这个进程中执行  
        // parent side of the fork  

        char  temp[3];  

        temp[0] = 'A'; temp[1] = 'B'; temp[2] = 'C';  
        // wait for the "OK\n" message  
        adb_close(fd[1]);  
        int ret = adb_read(fd[0], temp, 3); //等待新进程发送“OK”字符串。  
        int saved_errno = errno;  
        adb_close(fd[0]);  
        if (ret < 0) {  
            fprintf(stderr, "could not read ok from ADB Server, errno = %d\n", saved_errno);  
            return -1;  
        }  
        if (ret != 3 || temp[0] != 'O' || temp[1] != 'K' || temp[2] != '\n') {//接收字符错误。  
            fprintf(stderr, "ADB server didn't ACK\n" );  
            return -1;  
        }  

        setsid();  
    }  
#else  
#error "cannot implement background server start on this platform"  
#endif  
    return 0;  
}  
#endif  

再来看看”adb fork-server server”的运行。
(1) main()->adb_commandline();

/* modifiers and flags */  
while(argc > 0) {  
    if(!strcmp(argv[0],"server")) {  
        is_server = 1;  
    } else if(!strcmp(argv[0],"nodaemon")) {  
        no_daemon = 1;  
    } else if (!strcmp(argv[0], "fork-server")) {  
        /* this is a special flag used only when the ADB client launches the ADB Server */  
        is_daemon = 1;  
    } else if(!strcmp(argv[0],"persist")) {  
        persist = 1;  
    } else if(!strncmp(argv[0], "-p", 2)) {  
        const char *product = NULL;  
        if (argv[0][2] == '\0') {  
            if (argc < 2) return usage();  
            product = argv[1];  
            argc--;  
            argv++;  
        } else {  
            product = argv[0] + 2;  
        }  
        gProductOutPath = find_product_out_path(product);  
        if (gProductOutPath == NULL) {  
            fprintf(stderr, "adb: could not resolve \"-p %s\"\n",  
                    product);  
            return usage();  
        }  
    } else if (argv[0][0]=='-' && argv[0][1]=='s') {  
        if (isdigit(argv[0][2])) {  
            serial = argv[0] + 2;  
        } else {  
            if(argc < 2 || argv[0][2] != '\0') return usage();  
            serial = argv[1];  
            argc--;  
            argv++;  
        }  
    } else if (!strcmp(argv[0],"-d")) {  
        ttype = kTransportUsb;  
    } else if (!strcmp(argv[0],"-e")) {  
        ttype = kTransportLocal;  
    } else {  
            /* out of recognized modifiers and flags */  
        break;  
    }  
    argc--;  
    argv++;  
}  

adb_set_transport(ttype, serial);  
adb_set_tcp_specifics(server_port);  

if (is_server) {  
    if (no_daemon || is_daemon) {  
        r = adb_main(is_daemon, server_port);  
    } else {  
        r = launch_server(server_port);  
    }  
    if(r) {  
        fprintf(stderr,"* could not start server *\n");  
    }  
    return r;  
}  

这里将is_daemonis_server都置为1,并调用adb_main(1, 5037);

(2) adb_main()

int adb_main(int is_daemon, int server_port)  
{  

#if ADB_HOST  
    HOST = 1;  
    usb_vendors_init();  
    usb_init();  //监听USB端口数据  
    local_init(DEFAULT_ADB_LOCAL_TRANSPORT_PORT); //初始化建立5555网口信道  
    adb_auth_init();  

    char local_name[30];  
    build_local_name(local_name, sizeof(local_name), server_port); //监听5037端口  
    if(install_listener(local_name, "*smartsocket*", NULL)) {  
        exit(1);  
    }  
#else  #endif  

    if (is_daemon)  
    {  
        // inform our parent that we are up and running.  
//发送“OK”给父进程  
#ifdef HAVE_WIN32_PROC  
        DWORD  count;  
        WriteFile( GetStdHandle( STD_OUTPUT_HANDLE ), "OK\n", 3, &count, NULL );  
#elif defined(HAVE_FORKEXEC)  
        fprintf(stderr, "OK\n");  
#endif  
        start_logging();  
    }  
    D("Event loop starting\n");  

    fdevent_loop();  

    usb_cleanup();  

    return 0;  

}  

(3) usb_linux.c中的usb_init()

void usb_init()  
{  
    adb_thread_t tid;  
    struct sigaction    actions;  

    memset(&actions, 0, sizeof(actions));  
    sigemptyset(&actions.sa_mask);  
    actions.sa_flags = 0;  
    actions.sa_handler = sigalrm_handler;  
    sigaction(SIGALRM,& actions, NULL);  

    if(adb_thread_create(&tid, device_poll_thread, NULL)){  
        fatal_errno("cannot create input thread");  
    }  
}  

void* device_poll_thread(void* unused)  
{  
    D("Created device thread\n");  
    for(;;) {  
            /* XXX use inotify */  
        find_usb_device("/dev/bus/usb", register_device);  
        kick_disconnected_devices();  
        sleep(1);  
    }  
    return NULL;  
}  

register_device()函数中最终会调用register_usb_transport()

(4) install_listener(local_name, "*smartsocket*", NULL)

if(!strcmp(l->connect_to, "*smartsocket*")) {  
        fdevent_install(&l->fde, l->fd, ss_listener_event_func, l);  
    } else {  
        fdevent_install(&l->fde, l->fd, listener_event_func, l);  
    }  
    fdevent_set(&l->fde, FDE_READ);  

(5) ss_listener_event_func分析

static void ss_listener_event_func(int _fd, unsigned ev, void *_l)  
{  
    asocket *s;  

    if(ev & FDE_READ) {  
        struct sockaddr addr;  
        socklen_t alen;  
        int fd;  

        alen = sizeof(addr);  
        fd = adb_socket_accept(_fd, &addr, &alen);  //接受客户端的连接  
        if(fd < 0) return;  

        adb_socket_setbufsize(fd, CHUNK_SIZE);  

        s = create_local_socket(fd);  
        if(s) {  
            connect_to_smartsocket(s);  
            return;  
        }  

        adb_close(fd);  
    }  
}  

(6) 执行connect_to_smartsocket(s)

void connect_to_smartsocket(asocket *s)  
{  
    D("Connecting to smart socket \n");  
    asocket *ss = create_smart_socket(smart_socket_action);  
    s->peer = ss;  
    ss->peer = s;  
    s->ready(s);  
}  

(7) 执行create_smart_socket

static int smart_socket_enqueue(asocket *s, apacket *p)  
{  
    unsigned len;  
#if ADB_HOST  
    char *service = NULL;  
    char* serial = NULL;  
    transport_type ttype = kTransportAny;  
#endif  

    D("SS(%d): enqueue %d\n", s->id, p->len);  

    if(s->pkt_first == 0) {  
        s->pkt_first = p;  
        s->pkt_last = p;  
    } else {  
        if((s->pkt_first->len + p->len) > MAX_PAYLOAD) {  
            D("SS(%d): overflow\n", s->id);  
            put_apacket(p);  
            goto fail;  
        }  

        memcpy(s->pkt_first->data + s->pkt_first->len,  
               p->data, p->len);  
        s->pkt_first->len += p->len;  
        put_apacket(p);  

        p = s->pkt_first;  
    }  

        /* don't bother if we can't decode the length */  
    if(p->len < 4) return 0;  

    len = unhex(p->data, 4);  
    if((len < 1) ||  (len > 1024)) {  
        D("SS(%d): bad size (%d)\n", s->id, len);  
        goto fail;  
    }  

    D("SS(%d): len is %d\n", s->id, len );  
        /* can't do anything until we have the full header */  
    if((len + 4) > p->len) {  
        D("SS(%d): waiting for %d more bytes\n", s->id, len+4 - p->len);  
        return 0;  
    }  

    p->data[len + 4] = 0;  

    D("SS(%d): '%s'\n", s->id, (char*) (p->data + 4));  

#if ADB_HOST  
    service = (char *)p->data + 4;  
    if(!strncmp(service, "host-serial:", strlen("host-serial:"))) {  
        char* serial_end;  
        service += strlen("host-serial:");  

        // serial number should follow "host:" and could be a host:port string.  
        serial_end = skip_host_serial(service);  
        if (serial_end) {  
            *serial_end = 0; // terminate string  
            serial = service;  
            service = serial_end + 1;  
        }  
    } else if (!strncmp(service, "host-usb:", strlen("host-usb:"))) {  
        ttype = kTransportUsb;  
        service += strlen("host-usb:");  
    } else if (!strncmp(service, "host-local:", strlen("host-local:"))) {  
        ttype = kTransportLocal;  
        service += strlen("host-local:");  
    } else if (!strncmp(service, "host:", strlen("host:"))) {  
        ttype = kTransportAny;  
        service += strlen("host:");  
    } else {  
        service = NULL;  
    }  

    if (service) {  
        asocket *s2;  

            /* some requests are handled immediately -- in that 
            ** case the handle_host_request() routine has sent 
            ** the OKAY or FAIL message and all we have to do 
            ** is clean up. 
            */  
        if(handle_host_request(service, ttype, serial, s->peer->fd, s) == 0) {  
                /* XXX fail message? */  
            D( "SS(%d): handled host service '%s'\n", s->id, service );  
            goto fail;  
        }  
        if (!strncmp(service, "transport", strlen("transport"))) {  
            D( "SS(%d): okay transport\n", s->id );  
            p->len = 0;  
            return 0;  
        }  

            /* try to find a local service with this name. 
            ** if no such service exists, we'll fail out 
            ** and tear down here. 
            */  
        s2 = create_host_service_socket(service, serial);  
        if(s2 == 0) {  
            D( "SS(%d): couldn't create host service '%s'\n", s->id, service );  
            sendfailmsg(s->peer->fd, "unknown host service");  
            goto fail;  
        }  

            /* we've connected to a local host service, 
            ** so we make our peer back into a regular 
            ** local socket and bind it to the new local 
            ** service socket, acknowledge the successful 
            ** connection, and close this smart socket now 
            ** that its work is done. 
            */  
        adb_write(s->peer->fd, "OKAY", 4);  

        s->peer->ready = local_socket_ready;  
        s->peer->close = local_socket_close;  
        s->peer->peer = s2;  
        s2->peer = s->peer;  
        s->peer = 0;  
        D( "SS(%d): okay\n", s->id );  
        s->close(s);  

            /* initial state is "ready" */  
        s2->ready(s2);  
        return 0;  
    }  
#else /* !ADB_HOST */  
    if (s->transport == NULL) {  
        char* error_string = "unknown failure";  
        s->transport = acquire_one_transport (CS_ANY,  
                kTransportAny, NULL, &error_string);  

        if (s->transport == NULL) {  
            sendfailmsg(s->peer->fd, error_string);  
            goto fail;  
        }  
    }  
#endif  

    if(!(s->transport) || (s->transport->connection_state == CS_OFFLINE)) {  
           /* if there's no remote we fail the connection 
            ** right here and terminate it 
            */  
        sendfailmsg(s->peer->fd, "device offline (x)");  
        goto fail;  
    }  


        /* instrument our peer to pass the success or fail 
        ** message back once it connects or closes, then 
        ** detach from it, request the connection, and 
        ** tear down 
        */  
    s->peer->ready = local_socket_ready_notify;  
    s->peer->close = local_socket_close_notify;  
    s->peer->peer = 0;  
        /* give him our transport and upref it */  
    s->peer->transport = s->transport;  

    connect_to_remote(s->peer, (char*) (p->data + 4));  
    s->peer = 0;  
    s->close(s);  
    return 1;  

fail:  
        /* we're going to close our peer as a side-effect, so 
        ** return -1 to signal that state to the local socket 
        ** who is enqueueing against us 
        */  
    s->close(s);  
    return -1;  
}  

(8) 执行handle_host_request

int handle_host_request(char *service, transport_type ttype, char* serial, int reply_fd, asocket *s)  
{  

    // return a list of all connected devices  
    if (!strncmp(service, "devices", 7)) {   //执行adb devices,返回结果  
        char buffer[4096];  
        int use_long = !strcmp(service+7, "-l");  
        if (use_long || service[7] == 0) {  
            memset(buf, 0, sizeof(buf));  
            memset(buffer, 0, sizeof(buffer));  
            D("Getting device list \n");  
            list_transports(buffer, sizeof(buffer), use_long);  
            snprintf(buf, sizeof(buf), "OKAY%04x%s",(unsigned)strlen(buffer),buffer);  
            D("Wrote device list \n");  
            writex(reply_fd, buf, strlen(buf));  
            return 0;  
        }  
    }  

}  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值