adb和adbd分析 在adb中有三个模块,分别是adbd,adb server,adb client,如下表所示: module name process name run as
adbd adbd device/emulator
adb server windows: adb.exe linux: adb client
adb client such as eclipse, screencast,ddm app…and so on client adb server需要连接到adbd,这个连接叫adbconnect,这时候就可以通过客户端与设备端进行沟通,如下图: 
具体的沟通交流层次如下图所示:
 adbd是运行在设备端的一个守护进程,具体代码在adb.c中: 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); //adbd的入口#endif}- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
其中adb_main 函数是adbd进程的入口,执行“sevice adbd”时从这里开始调用。 在adbd中将会创建一对socket,一个用来控制连接,一个用来连接到adb client,adbd将会接收和发送信息与应用层的程序进行交流,如图所示:
 数据结构 struct fdevent { fdevent *next; fdevent *prev; int fd; int force_eof; unsigned short state; unsigned short events; fd_func func; void *arg;};adb server将会扫描设备的5555到5585的奇数端口号,install_listener将会实施交互监听,如图所示:
 adb server和adb client将会通过socket与设备端进行交流,端口号为5037,如下图:
 adb使用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 interfaceUSB_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_BUG6558362endififeq ($(HOST_OS),darwin) USB_SRCS := usb_osx.c EXTRA_SRCS := get_my_path_darwin.c LOCAL_LDLIBS += -lpthread -framework CoreFoundation -framework IOKit -framework Carbonendififeq ($(HOST_OS),freebsd) USB_SRCS := usb_libusb.c EXTRA_SRCS := get_my_path_freebsd.c LOCAL_LDLIBS += -lpthread -lusbendififeq ($(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/endifLOCAL_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) \ utils.c \ usb_vendors.cLOCAL_C_INCLUDES += external/openssl/includeifneq ($(USE_SYSDEPS_WIN32),) LOCAL_SRC_FILES += sysdeps_win32.celse LOCAL_SRC_FILES += fdevent.cendifLOCAL_CFLAGS += -O2 -g -DADB_HOST=1 -Wall -Wno-unused-parameterLOCAL_CFLAGS += -D_XOPEN_SOURCE -D_GNU_SOURCELOCAL_MODULE := adbLOCAL_MODULE_TAGS := debugLOCAL_STATIC_LIBRARIES := libzipfile libunz libcrypto_static $(EXTRA_STATIC_LIBS)ifeq ($(USE_SYSDEPS_WIN32),) LOCAL_STATIC_LIBRARIES += libcutilsendifinclude $(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.dllendif# 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 \ utils.cLOCAL_CFLAGS := -O2 -g -DADB_HOST=0 -Wall -Wno-unused-parameterLOCAL_CFLAGS += -D_XOPEN_SOURCE -D_GNU_SOURCEifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT)))LOCAL_CFLAGS += -DALLOW_ADBD_ROOT=1endifLOCAL_MODULE := adbdLOCAL_FORCE_STATIC_EXECUTABLE := trueLOCAL_MODULE_PATH := $(TARGET_ROOT_OUT_SBIN)LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_SBIN_UNSTRIPPED)LOCAL_STATIC_LIBRARIES := libcutils libc libmincryptinclude $(BUILD_EXECUTABLE)# adb host tool for device-as-host# =========================================================ifneq ($(SDK_ONLY),true)include $(CLEAR_VARS)LOCAL_LDLIBS := -lrt -ldl -lpthreadLOCAL_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 \ utils.c \ usb_vendors.c \ fdevent.cLOCAL_CFLAGS := \ -O2 \ -g \ -DADB_HOST=1 \ -DADB_HOST_ON_TARGET=1 \ -Wall \ -Wno-unused-parameter \ -D_XOPEN_SOURCE \ -D_GNU_SOURCELOCAL_C_INCLUDES += external/openssl/includeLOCAL_MODULE := adbLOCAL_STATIC_LIBRARIES := libzipfile libunz libcutilsLOCAL_SHARED_LIBRARIES := libcryptoinclude $(BUILD_EXECUTABLE)endif- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
- 169
- 170
- 171
- 172
- 173
- 174
- 175
- 176
- 177
- 178
- 179
- 180
- 181
- 182
- 183
- 184
通过编译,最终会有3个执行文件被生成,adbd和两个adb程序。
adbd是设备终端的守护进程;
adb一个是windows、linux、darwin或freebsd运行的程序,另一个是目标机上运行的程序。
其中宏ADB_HOST用于区分是PC端程序还是目标机端的程序。宏ADB_HOST_ON_TARGET用于区分adb程序是否是在目标机上运行。 这3个程序使用的是同一份源码,在内部,使用这些宏来区别不同的程序。 先来看adbd程序,此时宏的设置是ADB_HOST=0。在main函数代码中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();//初始化fevent transport_registration_fde#if ADB_HOST HOST = 1;#ifdef WORKAROUND_BUG6558362 if(is_daemon) adb_set_affinity();#endif 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, 0)) { exit(1); }#else property_get("ro.adb.secure", value, "0");//判断系统属性ro.adb.secure,目标板没有设置这个宏 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) { //没有定义环境变量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 */ /*根据android编译环境should_drop_privileges返回不同的值,如果它的值是userdebug或eng,宏ALLOW_ADBD_ROOT的值被定义为1,执行install_listener(),否则不会定义,这种情况下,由于adbd运行在root下,为保证它的安全性,它需要降级运行*/ if (should_drop_privileges()) { struct __user_cap_header_struct header; struct __user_cap_data_struct cap[2]; if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) != 0) { exit(1); } drop_capabilities_bounding_set_if_needed(); memset(&header, 0, sizeof(header)); memset(cap, 0, sizeof(cap)); /* set CAP_SYS_BOOT capability, so "adb reboot" will succeed */ header.version = _LINUX_CAPABILITY_VERSION_3; header.pid = 0; cap[CAP_TO_INDEX(CAP_SYS_BOOT)].effective |= CAP_TO_MASK(CAP_SYS_BOOT); cap[CAP_TO_INDEX(CAP_SYS_BOOT)].permitted |= CAP_TO_MASK(CAP_SYS_BOOT); 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, 0)) { exit(1); } } //判断是否存在设备文件USB_ADB_PATH或USB_FFS_ADB_EP0,存在则执行usb_init() 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. //读取属性service.adb.tcp.port或persist.adb.tcp.port,执行local_init(),它内部会创建adb thread 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 { // listen on default port local_init(DEFAULT_ADB_LOCAL_TRANSPORT_PORT); } D("adb_main(): pre init_jdwp()\n"); init_jdwp();//执行init_jdwp(),jdwp是Java调试体系中的一种 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();//调用fdevent_loop()监听fdevent并处理 usb_cleanup(); return 0;}- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
再来看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 || server_port > 65535) { fprintf(stderr, "adb: Env var ANDROID_ADB_SERVER_PORT must be a positive number less than 65535. 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 if (!strcmp(argv[0],"-a")) { gListenAll = 1; } else if(!strncmp(argv[0], "-H", 2)) { const char *hostname = NULL; if (argv[0][2] == '\0') { if (argc < 2) return usage(); hostname = argv[1]; argc--; argv++; } else { hostname = argv[0] + 2; } adb_set_tcp_name(hostname); } else if(!strncmp(argv[0], "-P", 2)) { if (argv[0][2] == '\0') { if (argc < 2) return usage(); server_port_str = argv[1]; argc--; argv++; } else { server_port_str = argv[0] + 2; } if (strlen(server_port_str) > 0) { server_port = (int) strtol(server_port_str, NULL, 0); if (server_port <= 0 || server_port > 65535) { fprintf(stderr, "adb: port number must be a positive number less than 65536. Got \"%s\"\n", server_port_str); return usage(); } } else { fprintf(stderr, "adb: port number must be a positive number less than 65536. Got empty string.\n"); return usage(); } } 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")) { char host_prefix[64]; char remove = 0; char remove_all = 0; char list = 0; char no_rebind = 0; // Parse options here. while (argc > 1 && argv[1][0] == '-') { if (!strcmp(argv[1], "--list")) list = 1; else if (!strcmp(argv[1], "--remove")) remove = 1; else if (!strcmp(argv[1], "--remove-all")) remove_all = 1; else if (!strcmp(argv[1], "--no-rebind")) no_rebind = 1; else { return usage(); } argc--; argv++; } // Ensure we can only use one option at a time. if (list + remove + remove_all + no_rebind > 1) { return usage(); } // Determine the <host-prefix> for this command. if (serial) { snprintf(host_prefix, sizeof host_prefix, "host-serial:%s", serial); } else if (ttype == kTransportUsb) { snprintf(host_prefix, sizeof host_prefix, "host-usb"); } else if (ttype == kTransportLocal) { snprintf(host_prefix, sizeof host_prefix, "host-local"); } else { snprintf(host_prefix, sizeof host_prefix, "host"); } // Implement forward --list if (list) { if (argc != 1) return usage(); snprintf(buf, sizeof buf, "%s:list-forward", host_prefix); char* forwards = adb_query(buf); if (forwards == NULL) { fprintf(stderr, "error: %s\n", adb_error()); return 1; } printf("%s", forwards); free(forwards); return 0; } // Implement forward --remove-all else if (remove_all) { if (argc != 1) return usage(); snprintf(buf, sizeof buf, "%s:killforward-all", host_prefix); } // Implement forward --remove <local> else if (remove) { if (argc != 2) return usage(); snprintf(buf, sizeof buf, "%s:killforward:%s", host_prefix, argv[1]); } // Or implement one of: // forward <local> <remote> // forward --no-rebind <local> <remote> else { if (argc != 3) return usage(); const char* command = no_rebind ? "forward:norebind:" : "forward"; snprintf(buf, sizeof buf, "%s:%s:%s;%s", host_prefix, command, 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;}- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
- 169
- 170
- 171
- 172
- 173
- 174
- 175
- 176
- 177
- 178
- 179
- 180
- 181
- 182
- 183
- 184
- 185
- 186
- 187
- 188
- 189
- 190
- 191
- 192
- 193
- 194
- 195
- 196
- 197
- 198
- 199
- 200
- 201
- 202
- 203
- 204
- 205
- 206
- 207
- 208
- 209
- 210
- 211
- 212
- 213
- 214
- 215
- 216
- 217
- 218
- 219
- 220
- 221
- 222
- 223
- 224
- 225
- 226
- 227
- 228
- 229
- 230
- 231
- 232
- 233
- 234
- 235
- 236
- 237
- 238
- 239
- 240
- 241
- 242
- 243
- 244
- 245
- 246
- 247
- 248
- 249
- 250
- 251
- 252
- 253
- 254
- 255
- 256
- 257
- 258
- 259
- 260
- 261
- 262
- 263
- 264
- 265
- 266
- 267
- 268
- 269
- 270
- 271
- 272
- 273
- 274
- 275
- 276
- 277
- 278
- 279
- 280
- 281
- 282
- 283
- 284
- 285
- 286
- 287
- 288
- 289
- 290
- 291
- 292
- 293
- 294
- 295
- 296
- 297
- 298
- 299
- 300
- 301
- 302
- 303
- 304
- 305
- 306
- 307
- 308
- 309
- 310
- 311
- 312
- 313
- 314
- 315
- 316
- 317
- 318
- 319
- 320
- 321
- 322
- 323
- 324
- 325
- 326
- 327
- 328
- 329
- 330
- 331
- 332
- 333
- 334
- 335
- 336
- 337
- 338
- 339
- 340
- 341
- 342
- 343
- 344
- 345
- 346
- 347
- 348
- 349
- 350
- 351
- 352
- 353
- 354
- 355
- 356
- 357
- 358
- 359
- 360
- 361
- 362
- 363
- 364
- 365
- 366
- 367
- 368
- 369
- 370
- 371
- 372
- 373
- 374
- 375
- 376
- 377
- 378
- 379
- 380
- 381
- 382
- 383
- 384
- 385
- 386
- 387
- 388
- 389
- 390
- 391
- 392
- 393
- 394
- 395
- 396
- 397
- 398
- 399
- 400
- 401
- 402
- 403
- 404
- 405
- 406
- 407
- 408
- 409
- 410
- 411
- 412
- 413
- 414
- 415
- 416
- 417
- 418
- 419
- 420
- 421
- 422
- 423
- 424
- 425
- 426
- 427
- 428
- 429
- 430
- 431
- 432
- 433
- 434
- 435
- 436
- 437
- 438
- 439
- 440
- 441
- 442
- 443
- 444
- 445
- 446
- 447
- 448
- 449
- 450
- 451
- 452
- 453
- 454
- 455
- 456
- 457
- 458
- 459
- 460
- 461
- 462
- 463
- 464
- 465
- 466
- 467
- 468
- 469
- 470
- 471
- 472
- 473
- 474
- 475
- 476
- 477
- 478
- 479
- 480
- 481
- 482
- 483
- 484
- 485
- 486
- 487
- 488
- 489
- 490
- 491
- 492
- 493
- 494
- 495
- 496
- 497
- 498
- 499
- 500
- 501
- 502
- 503
- 504
- 505
- 506
- 507
- 508
- 509
- 510
- 511
- 512
- 513
- 514
- 515
- 516
- 517
- 518
- 519
- 520
- 521
- 522
- 523
- 524
- 525
- 526
- 527
- 528
- 529
- 530
- 531
- 532
- 533
- 534
- 535
- 536
- 537
- 538
- 539
- 540
- 541
- 542
- 543
- 544
- 545
- 546
- 547
- 548
- 549
- 550
- 551
- 552
- 553
- 554
- 555
- 556
- 557
- 558
- 559
- 560
- 561
- 562
- 563
- 564
- 565
- 566
- 567
- 568
- 569
- 570
- 571
- 572
- 573
- 574
- 575
- 576
- 577
- 578
adb_commandline 函数根据命令的参数执行不同的功能。adb程序可能以服务的方式或命令行客户端的方式运行。 使用usb进行调试,则执行usb_init(),它的代码在usb_linux_client.c 中,如下: 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"); }}- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
它初始化了usb_handle,并把它作为参数创建usb_adb_open_thread()线程。这里不能打开/dev/android_adb_enable。h->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;}- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
这个线程的作用是一进入立即打开/dev/android_adb或/dev/Android,如果成功,则调用register_usb_transport()后再次循环,并阻塞在以下代码处 while(usb->fd != -1) adb_cond_wait(&usb->notify, &usb->lock);当usb->kick()调用后fd的值被赋为-1,并发送cond唤醒上面的代码。 adb源码fdevent.c文件中定义了工作时创建、监听和处理读写事件。 static fdevent **fd_table = 0; //fd_table保存的是以fdevent->fd为索引保存的fdevent指针static int fd_table_max = 0;the_fdevent的值等于fd_table[the_fdevent->fd] static void fdevent_register(fdevent *fde){ 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); }}- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
其中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; //参数 };其中事件可以是: /* events that may be observed */#define FDE_READ 0x0001#define FDE_WRITE 0x0002#define FDE_ERROR 0x0004#define FDE_TIMEOUT 0x0008/* features that may be set (via the events set/add/del interface) */#define FDE_DONT_CLOSE 0x0080状态可以是: #define FDE_ACTIVE 0x0100#define FDE_PENDING 0x0200#define FDE_CREATED 0x0400 时间和状态的掩码分别为: #define FDE_EVENTMASK 0x00ff#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); } }}- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
其中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;}- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
事件的处理是阻塞方式的,可以有两种代码实现方法。定义宏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 != 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; if(fde == 0) continue; if(fcntl(i, F_GETFL, NULL) < 0) { FD_SET(i, fds); n++; // fde->state |= FDE_DONT_CLOSE; } } return n; } - 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
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;};- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
它是一个双向链表,所有的实体都保存在全局数据transport_list中: static atransport transport_list = { .next = &transport_list, .prev = &transport_list,};atransport的数据传输的两个函数是: static intread_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 intwrite_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;}- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
这是它的内部传输接口,注意传输的是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"); }}- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
物理接口到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;}- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
这里做了一个物理到抽象的转换。最上层还有一层是tmsg的传输 , tmsg的作用是用于atransport的管理 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"); }}- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
未完待续。。。
|