揭开Linux跨平台 adb调试原理神秘面纱
程序功能分析
核心功能
先从Android Debug Bridge (ADB) 的头文件开始了解:
#ifndef __ADB_H
#define __ADB_H
#include <limits.h>
#include "transport.h" /* readx(), writex() */
#define MAX_PAYLOAD 4096 // 定义数据包最大载荷大小
// ADB协议命令定义(通过ASCII码的十六进制表示)
#define A_SYNC 0x434e5953 // 'SYNC' 的十六进制
#define A_CNXN 0x4e584e43 // 'CNXN' 的十六进制 - 连接命令
#define A_OPEN 0x4e45504f // 'OPEN' 的十六进制 - 打开连接
#define A_OKAY 0x59414b4f // 'OKAY' 的十六进制 - 确认响应
#define A_CLSE 0x45534c43 // 'CLSE' 的十六进制 - 关闭连接
#define A_WRTE 0x45545257 // 'WRTE' 的十六进制 - 写入数据
#define A_VERSION 0x01000000 // ADB协议版本
#define ADB_VERSION_MAJOR 1 // 用于帮助/版本信息的主版本号
#define ADB_VERSION_MINOR 0 // 用于帮助/版本信息的次版本号
#define ADB_SERVER_VERSION 29 // 当我们需要强制用户启动新的adb服务器时递增此值
// 前向声明各种结构体类型
typedef struct amessage amessage;
typedef struct apacket apacket;
typedef struct asocket asocket;
typedef struct alistener alistener;
typedef struct aservice aservice;
typedef struct atransport atransport;
typedef struct adisconnect adisconnect;
typedef struct usb_handle usb_handle;
// ADB消息结构体定义
struct amessage {unsigned command; /* 命令标识符常量 */unsigned arg0; /* 第一个参数 */unsigned arg1; /* 第二个参数 */unsigned data_length; /* 载荷长度(允许为0) */unsigned data_check; /* 数据载荷的校验和 */unsigned magic; /* 命令 ^ 0xffffffff */
};
// ADB数据包结构体定义
struct apacket
{apacket *next; // 指向下一个数据包的指针(用于链表)
unsigned len; // 数据长度unsigned char *ptr; // 数据指针
amessage msg; // 消息头unsigned char data[MAX_PAYLOAD]; // 数据载荷缓冲区
};
/* asocket表示本地和远程实体之间连接的一端。
** 本地asocket绑定到文件描述符。
** 远程asocket绑定到协议引擎。
*/
struct asocket {/* 链式指针,用于asocket所在的本地/远程asocket列表*/asocket *next;asocket *prev;
/* 此asocket的唯一标识符*/unsigned id;
/* 标志:当socket的对端已关闭但数据包仍在排队等待传递时设置*/int closing;
/* 标志:当两端都关闭本地服务socket时退出adbd*/int exit_on_close;
/* 我们连接到的asocket*/asocket *peer;
/* 对于本地asocket,fde用于将我们绑定到fd事件系统。** 对于远程asocket,这些字段不被使用。*/fdevent fde; // 文件描述符事件int fd; // 文件描述符
/* 等待写入的apacket队列*/apacket *pkt_first; // 队列头apacket *pkt_last; // 队列尾
/* 当对端有数据给我们时调用enqueue。** 如果我们能接受更多数据应返回0,否则返回1。** 如果我们返回1,当我们再次准备好接收数据时必须调用peer->ready()。*/int (*enqueue)(asocket *s, apacket *pkt);
/* 当对端准备好让我们再次通过enqueue发送数据时,由对端调用ready*/void (*ready)(asocket *s);
/* 当对端消失时由对端调用close。** 一旦我们的close方法被调用,我们不允许再对对端进行任何调用。*/void (*close)(asocket *s);
/* socket类型特定的额外数据 */void *extra;
/* socket绑定到atransport */atransport *transport;
};
/* adisconnect结构体用于记录一个回调函数,
** 该回调函数将在传输断开时被调用(例如由用户断开)
** 这应该用于清理依赖于传输的对象
** (例如远程socket、监听器等)
*/
struct adisconnect
{void (*func)(void* opaque, atransport* t); // 断开回调函数void* opaque; // 不透明数据指针adisconnect* next; // 链表下一个adisconnect* prev; // 链表上一个
};
/* 传输对象模型化到远程设备或模拟器的连接
** 每个连接的设备/模拟器有一个传输。
** "本地传输"通过TCP连接(用于模拟器),
** 而"USB传输"通过USB连接(用于真实设备)
**
** 注意kTransportHost并不真正对应一个真实的传输对象,
** 它是一个特殊值,用于指示客户端想要连接到ADB服务器本身实现的服务。
*/
typedef enum transport_type {kTransportUsb, // USB传输类型kTransportLocal, // 本地传输类型(TCP)kTransportAny, // 任何传输类型kTransportHost, // 主机传输类型
} transport_type;
// 传输结构体定义
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; // 传输socketfdevent transport_fde; // 传输文件描述符事件int ref_count; // 引用计数unsigned sync_token; // 同步令牌int connection_state; // 连接状态transport_type type; // 传输类型
/* 根据需要使用的USB句柄或socket fd */usb_handle *usb; // USB句柄int sfd; // socket文件描述符
/* 用于为客户端标识传输 */char *serial; // 设备序列号char *product; // 产品信息int adb_port; // 用于模拟器(本地传输)
/* 当传输被踢出时调用的adisconnect回调列表 */int kicked; // 踢出标志adisconnect disconnects; // 断开连接回调列表
};
/* 监听器是绑定到本地端口的实体,
** 并在该端口上接收到连接时,创建一个asocket
** 将新的本地连接连接到特定的远程服务。
**
** TODO:一些监听器从新连接读取以确定在远端要连接的确切服务。
*/
struct alistener
{alistener *next; // 链表下一个alistener *prev; // 链表上一个
fdevent fde; // 文件描述符事件int fd; // 文件描述符
const char *local_name; // 本地名称const char *connect_to; // 连接目标atransport *transport; // 关联的传输adisconnect disconnect; // 断开连接回调
};
// 函数声明
void print_packet(const char *label, apacket *p); // 打印数据包信息
asocket *find_local_socket(unsigned id); // 根据ID查找本地socket
void install_local_socket(asocket *s); // 安装本地socket
void remove_socket(asocket *s); // 移除socket
void close_all_sockets(atransport *t); // 关闭所有socket
#define LOCAL_CLIENT_PREFIX "emulator-" // 本地客户端前缀
asocket *create_local_socket(int fd); // 创建本地socket
asocket *create_local_service_socket(const char *destination); // 创建本地服务socket
asocket *create_remote_socket(unsigned id, atransport *t); // 创建远程socket
void connect_to_remote(asocket *s, const char *destination); // 连接到远程
void connect_to_smartsocket(asocket *s); // 连接到智能socket
void fatal(const char *fmt, ...); // 致命错误处理
void fatal_errno(const char *fmt, ...); // 带errno的致命错误处理
void handle_packet(apacket *p, atransport *t); // 处理数据包
void send_packet(apacket *p, atransport *t); // 发送数据包
void get_my_path(char *s, size_t maxLen); // 获取自身路径
int launch_server(int server_port); // 启动服务器
int adb_main(int is_daemon, int server_port); // ADB主函数
/* 传输是引用计数的
** get_device_transport在返回前为您执行获取操作
*/
void init_transport_registration(void); // 初始化传输注册
int list_transports(char *buf, size_t bufsize); // 列出传输
void update_transports(void); // 更新传输
asocket* create_device_tracker(void); // 创建设备跟踪器
/* 从可用传输中获取一个传输。
** 如果state != CS_ANY,只考虑该状态的传输。
** 如果serial非NULL,则只选择具有该序列号的设备。
** 如果没有找到合适的传输,设置错误。
*/
atransport *acquire_one_transport(int state, transport_type ttype, const char* serial, char **error_out);
void add_transport_disconnect( atransport* t, adisconnect* dis ); // 添加传输断开回调
void remove_transport_disconnect( atransport* t, adisconnect* dis ); // 移除传输断开回调
void run_transport_disconnects( atransport* t ); // 运行传输断开回调
void kick_transport( atransport* t ); // 踢出传输
/* 初始化传输对象的函数指针和状态 */
#if ADB_HOST
int get_available_local_transport_index(); // 获取可用本地传输索引
#endif
int init_socket_transport(atransport *t, int s, int port, int local); // 初始化socket传输
void init_usb_transport(atransport *t, usb_handle *usb, int state); // 初始化USB传输
/* 用于MacOS X清理 */
void close_usb_devices(); // 关闭USB设备
/* 导致新传输被初始化并添加到列表 */
void register_socket_transport(int s, const char *serial, int port, int local); // 注册socket传输
/* 这些应仅用于"adb disconnect"命令 */
void unregister_transport(atransport *t); // 注销传输
void unregister_all_tcp_transports(); // 注销所有TCP传输
void register_usb_transport(usb_handle *h, const char *serial, unsigned writeable); // 注册USB传输
/* 这应仅用于connection_state == CS_NOPERM的传输 */
void unregister_usb_transport(usb_handle *usb); // 注销USB传输
atransport *find_transport(const char *serial); // 根据序列号查找传输
#if ADB_HOST
atransport* find_emulator_transport_by_adb_port(int adb_port); // 根据ADB端口查找模拟器传输
#endif
int service_to_fd(const char *name); // 服务名称转换为文件描述符
#if ADB_HOST
asocket *host_service_to_socket(const char* name, const char *serial); // 主机服务转换为socket
#endif
#if !ADB_HOST
int init_jdwp(void); // 初始化JDWP
asocket* create_jdwp_service_socket(); // 创建JDWP服务socket
asocket* create_jdwp_tracker_service_socket(); // 创建JDWP跟踪器服务socket
int create_jdwp_connection_fd(int jdwp_pid); // 创建JDWP连接文件描述符
#endif
#if !ADB_HOST
typedef enum {BACKUP, // 备份操作RESTORE // 恢复操作
} BackupOperation;
int backup_service(BackupOperation operation, char* args); // 备份服务
void framebuffer_service(int fd, void *cookie); // 帧缓冲区服务
void log_service(int fd, void *cookie); // 日志服务
void remount_service(int fd, void *cookie); // 重新挂载服务
char * get_log_file_path(const char * log_name); // 获取日志文件路径
#endif
/* 数据包分配器 */
apacket *get_apacket(void); // 获取数据包
void put_apacket(apacket *p); // 释放数据包
int check_header(apacket *p); // 检查数据包头
int check_data(apacket *p); // 检查数据包数据
/* 定义ADB_TRACE为1启用跟踪支持,或0禁用它 */
#define ADB_TRACE 1
/* 重要:如果您更改以下列表,不要忘记更新adb.c中实现的adb_trace_init()函数中相应的'tags'表 */
typedef enum {TRACE_ADB = 0, /* 0x001 */ // ADB跟踪TRACE_SOCKETS, // Socket跟踪TRACE_PACKETS, // 数据包跟踪TRACE_TRANSPORT, // 传输跟踪TRACE_RWX, /* 0x010 */ // 读写执行跟踪TRACE_USB, // USB跟踪TRACE_SYNC, // 同步跟踪TRACE_SYSDEPS, // 系统依赖跟踪TRACE_JDWP, /* 0x100 */ // JDWP跟踪TRACE_SERVICES, // 服务跟踪
} AdbTrace;
#if ADB_TRACE
#if !ADB_HOST
/** 在模拟器内部运行时,客户机的adbd可以连接到'adb-debug'* qemud服务,该服务可以显示adb跟踪消息(条件是模拟器已使用'-debug adb'选项启动)。*/
/* 通过QEMU管道向模拟器传递跟踪消息。 */
void adb_qemu_trace(const char* fmt, ...);
/* 用于向模拟器发送ADB跟踪消息的宏。 */
#define DQ(...) adb_qemu_trace(__VA_ARGS__)
#else
#define DQ(...) ((void)0)
#endif /* !ADB_HOST */
extern int adb_trace_mask; // 跟踪掩码extern unsigned char adb_trace_output_count; // 跟踪输出计数void adb_trace_init(void); // 初始化跟踪
# define ADB_TRACING ((adb_trace_mask & (1 << TRACE_TAG)) != 0) // 跟踪启用检查
/* 在使用此宏之前必须定义TRACE_TAG */
# define D(...) \do { \if (ADB_TRACING) { \int save_errno = errno; \adb_mutex_lock(&D_lock); \fprintf(stderr, "%s::%s():", \__FILE__, __FUNCTION__); \errno = save_errno; \fprintf(stderr, __VA_ARGS__ ); \fflush(stderr); \adb_mutex_unlock(&D_lock); \errno = save_errno; \} \} while (0)
# define DR(...) \do { \if (ADB_TRACING) { \int save_errno = errno; \adb_mutex_lock(&D_lock); \errno = save_errno; \fprintf(stderr, __VA_ARGS__ ); \fflush(stderr); \adb_mutex_unlock(&D_lock); \errno = save_errno; \} \} while (0)
#else
# define D(...) ((void)0) // 空宏,跟踪禁用时
# define DR(...) ((void)0) // 空宏,跟踪禁用时
# define ADB_TRACING 0 // 跟踪禁用
#endif
#if !TRACE_PACKETS
#define print_packet(tag,p) do {} while (0) // 空宏,数据包跟踪禁用时
#endif
#if ADB_HOST_ON_TARGET
/* adb和adbd在目标上共存,因此对adb使用5038端口以避免与adbd使用5037端口冲突 */
# define DEFAULT_ADB_PORT 5038
#else
# define DEFAULT_ADB_PORT 5037
#endif
#define DEFAULT_ADB_LOCAL_TRANSPORT_PORT 5555 // 默认ADB本地传输端口
#define ADB_CLASS 0xff // ADB设备类
#define ADB_SUBCLASS 0x42 // ADB设备子类
#define ADB_PROTOCOL 0x1 // ADB设备协议
void local_init(int port); // 本地初始化
int local_connect(int port); // 本地连接
int local_connect_arbitrary_ports(int console_port, int adb_port); // 本地任意端口连接
/* USB主机/客户端接口 */
void usb_init(); // USB初始化
void usb_cleanup(); // USB清理
int usb_write(usb_handle *h, const void *data, int len); // USB写入
int usb_read(usb_handle *h, void *data, int len); // USB读取
int usb_close(usb_handle *h); // USB关闭
void usb_kick(usb_handle *h); // USB踢出
/* 用于USB设备检测 */
#if ADB_HOST
int is_adb_interface(int vid, int pid, int usb_class, int usb_subclass, int usb_protocol); // 检查是否为ADB接口
#endif
unsigned host_to_le32(unsigned n); // 主机序转小端序
int adb_commandline(int argc, char **argv); // ADB命令行处理
int connection_state(atransport *t); // 获取连接状态
// 连接状态常量定义
#define CS_ANY -1 // 任何状态
#define CS_OFFLINE 0 // 离线状态
#define CS_BOOTLOADER 1 // 引导加载程序状态
#define CS_DEVICE 2 // 设备状态
#define CS_HOST 3 // 主机状态
#define CS_RECOVERY 4 // 恢复模式状态
#define CS_NOPERM 5 // 权限不足,无法与设备通信
#define CS_SIDELOAD 6 // 侧载状态
extern int HOST; // 主机标志
extern int SHELL_EXIT_NOTIFY_FD; // Shell退出通知文件描述符
#define CHUNK_SIZE (64*1024) // 数据块大小(64KB)
int sendfailmsg(int fd, const char *reason); // 发送失败消息
int handle_host_request(char *service, transport_type ttype, char* serial, int reply_fd, asocket *s); // 处理主机请求
#endif主要数据结构
1. 协议消息结构 (amessage)
定义了ADB协议的6种命令类型
包含命令、参数、数据长度、校验和等字段
使用魔数进行协议验证
2. 数据包结构 (apacket)
链表结构管理数据包
包含消息头和4KB数据载荷
支持数据包的分配和释放
3. Socket抽象 (asocket)
统一的本地和远程socket接口
支持双向数据流控制
包含就绪、关闭等回调函数
4. 传输层抽象 (atransport)
支持USB和TCP两种传输方式
引用计数管理
连接状态跟踪
设计模式应用
1. 抽象工厂模式
create_local_socket(),create_remote_socket()等创建函数统一的socket创建接口
2. 观察者模式
adisconnect回调机制传输断开时的通知系统
3. 策略模式
不同的传输类型(USB、TCP)
可插拔的传输实现
4. 状态模式
连接状态管理(离线、设备、恢复模式等)
状态相关的行为控制
运行效率特性
1. 内存管理
数据包预分配机制
固定大小的数据载荷(4KB)
链表管理避免内存碎片
2. I/O优化
大块数据传输(64KB块大小)
非阻塞I/O支持
批量数据包处理
3. 协议优化
二进制协议减少解析开销
校验和确保数据完整性
魔数验证协议正确性
跨平台支持
条件编译支持不同平台
统一的抽象接口
平台特定的实现封装
再分析这些接口实现
#define TRACE_TAG TRACE_ADB // 定义调试跟踪标签
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <stdarg.h>
#include <errno.h>
#include <string.h>
#include <time.h>
#include <sys/time.h>
#include "sysdeps.h" // 系统依赖头文件
#include "adb.h" // ADB核心头文件
#if !ADB_HOST // 设备端代码
#include <linux/capability.h>
#include <linux/prctl.h>
#else // 主机端代码
#include "usb_vendors.h"
#endif
#if ADB_TRACE
ADB_MUTEX_DEFINE( D_lock ); // 调试跟踪互斥锁
#endif
#define ALLOW_ADBD_ROOT // 允许ADB以root权限运行
int HOST = 0; // 标识当前是主机端还是设备端
static const char *adb_device_banner = "device"; // 设备标识字符串
// 致命错误处理函数
void fatal(const char *fmt, ...)
{va_list ap;va_start(ap, fmt);fprintf(stderr, "error: ");vfprintf(stderr, fmt, ap);fprintf(stderr, "\n");va_end(ap);exit(-1);
}
// 带errno的致命错误处理
void fatal_errno(const char *fmt, ...)
{va_list ap;va_start(ap, fmt);fprintf(stderr, "error: %s: ", strerror(errno));vfprintf(stderr, fmt, ap);fprintf(stderr, "\n");va_end(ap);exit(-1);
}
int adb_trace_mask; // 调试跟踪掩码
/* 从ADB_TRACE环境变量读取逗号/空格分隔的标签列表* 并构建跟踪掩码。注意'1'和'all'是特殊情况,启用所有跟踪*/
void adb_trace_init(void)
{const char* p = getenv("ADB_TRACE");const char* q;
// 跟踪标签定义表static const struct {const char* tag;int flag;} tags[] = {{ "1", 0 }, // 特殊值:启用所有跟踪{ "all", 0 }, // 特殊值:启用所有跟踪{ "adb", TRACE_ADB },{ "sockets", TRACE_SOCKETS },{ "packets", TRACE_PACKETS },{ "rwx", TRACE_RWX },{ "usb", TRACE_USB },{ "sync", TRACE_SYNC },{ "sysdeps", TRACE_SYSDEPS },{ "transport", TRACE_TRANSPORT },{ "jdwp", TRACE_JDWP },{ "services", TRACE_SERVICES },{ NULL, 0 }};
if (p == NULL)return;
// 使用逗号/分号/空格分隔的列表while (*p) {int len, tagn;
q = strpbrk(p, " ,:;"); // 查找分隔符if (q == NULL) {q = p + strlen(p);}len = q - p;
// 在标签表中查找匹配项for (tagn = 0; tags[tagn].tag != NULL; tagn++){int taglen = strlen(tags[tagn].tag);
if (len == taglen && !memcmp(tags[tagn].tag, p, len) ){int flag = tags[tagn].flag;if (flag == 0) { // 特殊标签:启用所有跟踪adb_trace_mask = ~0;return;}adb_trace_mask |= (1 << flag); // 设置对应的跟踪位break;}}p = q;if (*p)p++;}
}
// 数据包管理函数
apacket *get_apacket(void)
{apacket *p = malloc(sizeof(apacket));if(p == 0) fatal("failed to allocate an apacket");memset(p, 0, sizeof(apacket) - MAX_PAYLOAD); // 清零除了数据负载的部分return p;
}
void put_apacket(apacket *p)
{free(p); // 释放数据包内存
}
// 设备上线处理
void handle_online(void)
{D("adb: online\n"); // 调试输出
}
// 设备离线处理
void handle_offline(atransport *t)
{D("adb: offline\n");// 关闭相关的USB连接run_transport_disconnects(t);
}
#if TRACE_PACKETS // 数据包跟踪功能
#define DUMPMAX 32
void print_packet(const char *label, apacket *p)
{char *tag;char *x;unsigned count;
// 根据命令类型设置标签switch(p->msg.command){case A_SYNC: tag = "SYNC"; break;case A_CNXN: tag = "CNXN" ; break;case A_OPEN: tag = "OPEN"; break;case A_OKAY: tag = "OKAY"; break;case A_CLSE: tag = "CLSE"; break;case A_WRTE: tag = "WRTE"; break;default: tag = "????"; break;}
// 打印数据包基本信息fprintf(stderr, "%s: %s %08x %08x %04x \"",label, tag, p->msg.arg0, p->msg.arg1, p->msg.data_length);count = p->msg.data_length;x = (char*) p->data;if(count > DUMPMAX) { // 限制输出长度count = DUMPMAX;tag = "\n";} else {tag = "\"\n";}// 打印数据内容(可打印字符显示原字符,不可打印字符显示点)while(count-- > 0){if((*x >= ' ') && (*x < 127)) {fputc(*x, stderr);} else {fputc('.', stderr);}x++;}fprintf(stderr, tag);
}
#endif
// 发送READY响应
static void send_ready(unsigned local, unsigned remote, atransport *t)
{D("Calling send_ready \n");apacket *p = get_apacket();p->msg.command = A_OKAY;p->msg.arg0 = local;p->msg.arg1 = remote;send_packet(p, t);
}
// 发送CLOSE请求
static void send_close(unsigned local, unsigned remote, atransport *t)
{D("Calling send_close \n");apacket *p = get_apacket();p->msg.command = A_CLSE;p->msg.arg0 = local;p->msg.arg1 = remote;send_packet(p, t);
}
// 发送CONNECT请求建立连接
static void send_connect(atransport *t)
{D("Calling send_connect \n");apacket *cp = get_apacket();cp->msg.command = A_CNXN;cp->msg.arg0 = A_VERSION; // 协议版本cp->msg.arg1 = MAX_PAYLOAD; // 最大负载大小snprintf((char*) cp->data, sizeof cp->data, "%s::",HOST ? "host" : adb_device_banner); // 设备标识cp->msg.data_length = strlen((char*) cp->data) + 1;send_packet(cp, t);
#if ADB_HOST// 给设备时间响应连接消息adb_sleep_ms(1000);
#endif
}
// 获取连接状态名称
static char *connection_state_name(atransport *t)
{if (t == NULL) {return "unknown";}
switch(t->connection_state) {case CS_BOOTLOADER:return "bootloader";case CS_DEVICE:return "device";case CS_OFFLINE:return "offline";default:return "unknown";}
}
// 解析设备标识横幅
void parse_banner(char *banner, atransport *t)
{char *type, *product, *end;
D("parse_banner: %s\n", banner);type = banner;product = strchr(type, ':');if(product) {*product++ = 0;} else {product = "";}
// 移除尾部冒号end = strchr(product, ':');if(end) *end = 0;
// 在设备结构中保存产品名称if (t->product == NULL) {t->product = strdup(product);} else if (strcmp(product, t->product) != 0) {free(t->product);t->product = strdup(product);}
// 根据设备类型设置连接状态if(!strcmp(type, "bootloader")){D("setting connection_state to CS_BOOTLOADER\n");t->connection_state = CS_BOOTLOADER;update_transports();return;}
if(!strcmp(type, "device")) {D("setting connection_state to CS_DEVICE\n");t->connection_state = CS_DEVICE;update_transports();return;}
if(!strcmp(type, "recovery")) {D("setting connection_state to CS_RECOVERY\n");t->connection_state = CS_RECOVERY;update_transports();return;}
if(!strcmp(type, "sideload")) {D("setting connection_state to CS_SIDELOAD\n");t->connection_state = CS_SIDELOAD;update_transports();return;}
t->connection_state = CS_HOST;
}
// 处理接收到的数据包(核心函数)
void handle_packet(apacket *p, atransport *t)
{asocket *s;
D("handle_packet() %c%c%c%c\n", ((char*) (&(p->msg.command)))[0],((char*) (&(p->msg.command)))[1],((char*) (&(p->msg.command)))[2],((char*) (&(p->msg.command)))[3]);print_packet("recv", p);
switch(p->msg.command){case A_SYNC: // 同步命令if(p->msg.arg0){send_packet(p, t);if(HOST) send_connect(t);} else {t->connection_state = CS_OFFLINE;handle_offline(t);send_packet(p, t);}return;
case A_CNXN: // 连接命令if(t->connection_state != CS_OFFLINE) {t->connection_state = CS_OFFLINE;handle_offline(t);}parse_banner((char*) p->data, t); // 解析设备信息handle_online(); // 处理上线if(!HOST) send_connect(t); // 设备端回应连接break;
case A_OPEN: // 打开连接if(t->connection_state != CS_OFFLINE) {char *name = (char*) p->data;name[p->msg.data_length > 0 ? p->msg.data_length - 1 : 0] = 0;s = create_local_service_socket(name); // 创建本地服务socketif(s == 0) {send_close(0, p->msg.arg0, t); // 创建失败则关闭} else {s->peer = create_remote_socket(p->msg.arg0, t); // 创建对端sockets->peer->peer = s;send_ready(s->id, s->peer->id, t); // 发送就绪信号s->ready(s);}}break;
case A_OKAY: // 就绪响应if(t->connection_state != CS_OFFLINE) {if((s = find_local_socket(p->msg.arg1))) {if(s->peer == 0) {s->peer = create_remote_socket(p->msg.arg0, t);s->peer->peer = s;}s->ready(s); // 通知socket就绪}}break;
case A_CLSE: // 关闭连接if(t->connection_state != CS_OFFLINE) {if((s = find_local_socket(p->msg.arg1))) {s->close(s); // 关闭socket}}break;
case A_WRTE: // 写入数据if(t->connection_state != CS_OFFLINE) {if((s = find_local_socket(p->msg.arg1))) {unsigned rid = p->msg.arg0;p->len = p->msg.data_length;
if(s->enqueue(s, p) == 0) { // 数据入队成功D("Enqueue the socket\n");send_ready(s->id, rid, t); // 发送就绪信号}return; // 不释放数据包,数据已传递}}break;
default:printf("handle_packet: what is %08x?!\n", p->msg.command);}
put_apacket(p); // 释放数据包
}
// 监听器链表(双向循环链表)
alistener listener_list = {.next = &listener_list,.prev = &listener_list,
};
// 智能socket监听器事件处理
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); // 连接到智能socketreturn;}
adb_close(fd);}
}
// 普通监听器事件处理
static void listener_event_func(int _fd, unsigned ev, void *_l)
{alistener *l = _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;
s = create_local_socket(fd);if(s) {s->transport = l->transport;connect_to_remote(s, l->connect_to); // 连接到远程return;}
adb_close(fd);}
}
// 释放监听器资源
static void free_listener(alistener* l)
{if (l->next) {l->next->prev = l->prev;l->prev->next = l->next;l->next = l->prev = l;}
// 移除文件描述符事件监听fdevent_remove(&l->fde);
// 释放内存if (l->local_name)free((char*)l->local_name);
if (l->connect_to)free((char*)l->connect_to);
if (l->transport) {remove_transport_disconnect(l->transport, &l->disconnect);}free(l);
}
// 监听器断开连接处理
static void listener_disconnect(void* _l, atransport* t)
{alistener* l = _l;free_listener(l);
}
// 本地名称转换为文件描述符
int local_name_to_fd(const char *name)
{int port;
if(!strncmp("tcp:", name, 4)){ // TCP连接int ret;port = atoi(name + 4);ret = socket_inaddr_any_server(port, SOCK_STREAM); // 创建TCP服务器return ret;}
#ifndef HAVE_WIN32_IPC // Win32没有Unix域socket// 本地抽象socketif(!strncmp(name, "local:", 6)) {return socket_local_server(name + 6,ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);} else if(!strncmp(name, "localabstract:", 14)) {return socket_local_server(name + 14,ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);} else if(!strncmp(name, "localfilesystem:", 16)) {return socket_local_server(name + 16,ANDROID_SOCKET_NAMESPACE_FILESYSTEM, SOCK_STREAM);}
#endifprintf("unknown local portname '%s'\n", name);return -1;
}
// 移除监听器
static int remove_listener(const char *local_name, const char *connect_to, atransport* transport)
{alistener *l;
// 遍历监听器链表查找匹配项for (l = listener_list.next; l != &listener_list; l = l->next) {if (!strcmp(local_name, l->local_name) &&!strcmp(connect_to, l->connect_to) &&l->transport && l->transport == transport) {
listener_disconnect(l, transport);return 0;}}
return -1;
}
// 安装监听器
static int install_listener(const char *local_name, const char *connect_to, atransport* transport)
{alistener *l;
printf("install_listener('%s','%s')\n", local_name, connect_to);
// 检查是否已存在相同本地名称的监听器for(l = listener_list.next; l != &listener_list; l = l->next){if(strcmp(local_name, l->local_name) == 0) {char *cto;
// 不能重新指定智能socketif(l->connect_to[0] == '*') {return -1;}
cto = strdup(connect_to);if(cto == 0) {return -1;}
// 重新绑定到新的连接目标free((void*) l->connect_to);l->connect_to = cto;if (l->transport != transport) {remove_transport_disconnect(l->transport, &l->disconnect);l->transport = transport;add_transport_disconnect(l->transport, &l->disconnect);}return 0;}}
// 创建新的监听器if((l = calloc(1, sizeof(alistener))) == 0) goto nomem;if((l->local_name = strdup(local_name)) == 0) goto nomem;if((l->connect_to = strdup(connect_to)) == 0) goto nomem;
l->fd = local_name_to_fd(local_name);if(l->fd < 0) {free((void*) l->local_name);free((void*) l->connect_to);free(l);printf("cannot bind '%s'\n", local_name);return -2;}
close_on_exec(l->fd); // 设置exec时关闭// 根据连接目标类型安装不同的事件处理器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); // 设置读事件监听
// 添加到监听器链表l->next = &listener_list;l->prev = listener_list.prev;l->next->prev = l;l->prev->next = l;l->transport = transport;
if (transport) {l->disconnect.opaque = l;l->disconnect.func = listener_disconnect;add_transport_disconnect(transport, &l->disconnect);}return 0;
nomem:fatal("cannot allocate listener");return 0;
}
// Windows Ctrl+C处理
#ifdef HAVE_WIN32_PROC
static BOOL WINAPI ctrlc_handler(DWORD type)
{exit(STATUS_CONTROL_C_EXIT);return TRUE;
}
#endif
// ADB清理函数
static void adb_cleanup(void)
{usb_cleanup(); // 清理USB资源
}
// 启动日志记录
void start_logging(void)
{
#ifdef HAVE_WIN32_PROC// Windows平台日志设置char temp[ MAX_PATH ];FILE* fnul;FILE* flog;
GetTempPath( sizeof(temp) - 8, temp );strcat( temp, "adb.log" );
fnul = fopen( "NUL", "rt" );if (fnul != NULL)stdin[0] = fnul[0];
flog = fopen( temp, "at" );if (flog == NULL)flog = fnul;
setvbuf( flog, NULL, _IONBF, 0 );
stdout[0] = flog[0];stderr[0] = flog[0];fprintf(stderr,"--- adb starting (pid %d) ---\n", getpid());
#else// Unix平台日志设置int fd;
fd = unix_open("/dev/null", O_RDONLY);dup2(fd, 0); // 重定向标准输入到/dev/nulladb_close(fd);
fd = unix_open("/tmp/adb.log", O_WRONLY | O_CREAT | O_APPEND, 0640);if(fd < 0) {fd = unix_open("/dev/null", O_WRONLY);}dup2(fd, 1); // 重定向标准输出dup2(fd, 2); // 重定向标准错误adb_close(fd);fprintf(stderr,"--- adb starting (pid %d) ---\n", getpid());
#endif
}
#if !ADB_HOST
// 设备端启动日志
void start_device_log(void)
{int fd;char path[PATH_MAX];struct tm now;time_t t;char value[PROPERTY_VALUE_MAX];
// 从持久属性读取跟踪掩码property_get("persist.adb.trace_mask", value, "");if (sscanf(value, "%x", &adb_trace_mask) != 1)return;
adb_mkdir("/data/adb", 0775);tzset();time(&t);localtime_r(&t, &now);// 生成带时间戳的日志文件名strftime(path, sizeof(path),"/data/adb/adb-%Y-%m-%d-%H-%M-%S.txt",&now);fd = unix_open(path, O_WRONLY | O_CREAT | O_TRUNC, 0640);if (fd < 0)return;
// 重定向标准输出和错误到日志文件dup2(fd, 1);dup2(fd, 2);fprintf(stderr,"--- adb starting (pid %d) ---\n", getpid());adb_close(fd);
fd = unix_open("/dev/null", O_RDONLY);dup2(fd, 0);adb_close(fd);
}
#endif
#if ADB_HOST
// 启动ADB服务器
int launch_server(int server_port)
{
#ifdef HAVE_WIN32_PROC/* Windows平台服务器启动实现 */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;
// 创建管道用于进程间通信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) );
// 获取当前程序路径GetModuleFileName( NULL, program_path, sizeof(program_path) );
// 创建子进程ret = CreateProcess(program_path,"adb fork-server server", // 启动fork-serverNULL,NULL,TRUE,DETACHED_PROCESS,NULL,NULL,&startup,&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 );
// 等待服务器的"OK"消息{char temp[3];DWORD count;
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)/* Unix平台服务器启动实现 */char path[PATH_MAX];int fd[2];
// 创建管道用于父子进程通信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) {// 子进程adb_close(fd[0]);dup2(fd[1], STDERR_FILENO); // 重定向标准错误到管道adb_close(fd[1]);
// 执行adb服务器int result = execl(path, "adb", "fork-server", "server", NULL);fprintf(stderr, "OOPS! execl returned %d, errno: %d\n", result, errno);} else {// 父进程char temp[3];
temp[0] = 'A'; temp[1] = 'B'; temp[2] = 'C';// 等待服务器的"OK"消息adb_close(fd[1]);int ret = adb_read(fd[0], temp, 3);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"
#endifreturn 0;
}
#endif
// 构建本地名称
void build_local_name(char* target_str, size_t target_size, int server_port)
{snprintf(target_str, target_size, "tcp:%d", server_port);
}
#if !ADB_HOST
// 检查是否应该降低权限
static int should_drop_privileges() {
#ifndef ALLOW_ADBD_ROOTreturn 1; // 不允许root权限
#else /* ALLOW_ADBD_ROOT */int secure = 0;char value[PROPERTY_VALUE_MAX];
/* 如果ro.secure设置且不在模拟器中,则以安全模式运行adbd */property_get("ro.kernel.qemu", value, "");if (strcmp(value, "1") != 0) {property_get("ro.secure", value, "1");if (strcmp(value, "1") == 0) {// 如果ro.secure设置,不以root运行...secure = 1;
// ...除非在userdebug版本中且service.adb.root属性被设置property_get("ro.debuggable", value, "");if (strcmp(value, "1") == 0) {property_get("service.adb.root", value, "");if (strcmp(value, "1") == 0) {secure = 0;}}}}return 0; // 实际返回0,允许root权限
#endif /* ALLOW_ADBD_ROOT */
}
#endif /* !ADB_HOST */
// ADB主函数
int adb_main(int is_daemon, int server_port)
{
#if !ADB_HOSTint port;char value[PROPERTY_VALUE_MAX];
umask(000); // 设置文件创建掩码
#endif
atexit(adb_cleanup); // 注册退出清理函数
#ifdef HAVE_WIN32_PROCSetConsoleCtrlHandler( ctrlc_handler, TRUE );
#elif defined(HAVE_FORKEXEC)signal(SIGPIPE, SIG_IGN); // 忽略SIGPIPE信号
#endif
init_transport_registration(); // 初始化传输注册
#if ADB_HOST// 主机端初始化HOST = 1;usb_vendors_init(); // 初始化USB厂商列表usb_init(); // 初始化USBlocal_init(DEFAULT_ADB_LOCAL_TRANSPORT_PORT); // 初始化本地传输
char local_name[30];build_local_name(local_name, sizeof(local_name), server_port);if(install_listener(local_name, "*smartsocket*", NULL)) {exit(1);}
#else// 设备端初始化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);}// 权限降低逻辑(当前被注释)} else {// 保持root权限char local_name[30];build_local_name(local_name, sizeof(local_name), server_port);if(install_listener(local_name, "*smartsocket*", NULL)) {exit(1);}}
// 根据属性设置选择传输方式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) {// 监听TCP端口local_init(port);} else if (access("/dev/android_adb", F_OK) == 0) {// 监听USBusb_init();} else {// 监听默认端口local_init(DEFAULT_ADB_LOCAL_TRANSPORT_PORT);}D("adb_main(): pre init_jdwp()\n");init_jdwp(); // 初始化JDWP调试支持D("adb_main(): post init_jdwp()\n");
#endif
if (is_daemon){// 守护进程模式:通知父进程已启动
#ifdef HAVE_WIN32_PROCDWORD count;WriteFile( GetStdHandle( STD_OUTPUT_HANDLE ), "OK\n", 3, &count, NULL );
#elif defined(HAVE_FORKEXEC)fprintf(stderr, "OK\n");
#endifstart_logging(); // 启动日志记录}D("Event loop starting\n");
fdevent_loop(); // 进入事件循环
usb_cleanup(); // 清理USB资源
return 0;
}
#if ADB_HOST
// 连接设备函数
void connect_device(char* host, char* buffer, int buffer_size)
{int port, fd;char* portstr = strchr(host, ':');char hostbuf[100];char serial[100];
strncpy(hostbuf, host, sizeof(hostbuf) - 1);if (portstr) {// 解析端口号if (portstr - host >= sizeof(hostbuf)) {snprintf(buffer, buffer_size, "bad host name %s", host);return;}hostbuf[portstr - host] = 0;if (sscanf(portstr + 1, "%d", &port) == 0) {snprintf(buffer, buffer_size, "bad port number %s", portstr);return;}} else {port = DEFAULT_ADB_LOCAL_TRANSPORT_PORT; // 默认端口}
snprintf(serial, sizeof(serial), "%s:%d", hostbuf, port);if (find_transport(serial)) {snprintf(buffer, buffer_size, "already connected to %s", serial);return;}
// 创建网络连接fd = socket_network_client(hostbuf, port, SOCK_STREAM);if (fd < 0) {snprintf(buffer, buffer_size, "unable to connect to %s:%d", host, port);return;}
D("client: connected on remote on fd %d\n", fd);close_on_exec(fd);disable_tcp_nagle(fd); // 禁用Nagle算法register_socket_transport(fd, serial, port, 0); // 注册socket传输snprintf(buffer, buffer_size, "connected to %s", serial);
}
// 连接模拟器函数
void connect_emulator(char* port_spec, char* buffer, int buffer_size)
{char* port_separator = strchr(port_spec, ',');if (!port_separator) {snprintf(buffer, buffer_size,"unable to parse '%s' as <console port>,<adb port>",port_spec);return;}
// 解析控制台端口和ADB端口*port_separator++ = 0;int console_port = strtol(port_spec, NULL, 0);int adb_port = strtol(port_separator, NULL, 0);if (!(console_port > 0 && adb_port > 0)) {*(port_separator - 1) = ',';snprintf(buffer, buffer_size,"Invalid port numbers: Expected positive numbers, got '%s'",port_spec);return;}
// 检查模拟器是否已注册atransport* known_emulator = find_emulator_transport_by_adb_port(adb_port);if (known_emulator != NULL) {snprintf(buffer, buffer_size,"Emulator on port %d already registered.", adb_port);return;}
// 检查是否可以注册更多模拟器int candidate_slot = get_available_local_transport_index();if (candidate_slot < 0) {snprintf(buffer, buffer_size, "Cannot accept more emulators.");return;}
// 连接到模拟器if (!local_connect_arbitrary_ports(console_port, adb_port)) {snprintf(buffer, buffer_size,"Connected to emulator on ports %d,%d", console_port, adb_port);} else {snprintf(buffer, buffer_size,"Could not connect to emulator on ports %d,%d",console_port, adb_port);}
}
#endif
// 处理主机请求
int handle_host_request(char *service, transport_type ttype, char* serial, int reply_fd, asocket *s)
{atransport *transport = NULL;char buf[4096];
if(!strcmp(service, "kill")) {// 杀死ADB服务器fprintf(stderr,"adb server killed by remote request\n");fflush(stdout);adb_write(reply_fd, "OKAY", 4);usb_cleanup();exit(0);}
#if ADB_HOST// 传输切换请求if (!strncmp(service, "transport", strlen("transport"))) {char* error_string = "unknown failure";transport_type type = kTransportAny;
// 解析传输类型if (!strncmp(service, "transport-usb", strlen("transport-usb"))) {type = kTransportUsb;} else if (!strncmp(service, "transport-local", strlen("transport-local"))) {type = kTransportLocal;} else if (!strncmp(service, "transport-any", strlen("transport-any"))) {type = kTransportAny;} else if (!strncmp(service, "transport:", strlen("transport:"))) {service += strlen("transport:");serial = service;}
transport = acquire_one_transport(CS_ANY, type, serial, &error_string);
if (transport) {s->transport = transport;adb_write(reply_fd, "OKAY", 4);} else {sendfailmsg(reply_fd, error_string);}return 1;}
// 返回所有已连接设备列表if (!strcmp(service, "devices")) {char buffer[4096];memset(buf, 0, sizeof(buf));memset(buffer, 0, sizeof(buffer));D("Getting device list \n");list_transports(buffer, sizeof(buffer));snprintf(buf, sizeof(buf), "OKAY%04x%s",(unsigned)strlen(buffer),buffer);D("Wrote device list \n");writex(reply_fd, buf, strlen(buf));return 0;}
// 添加新的TCP传输(设备或模拟器)if (!strncmp(service, "connect:", 8)) {char buffer[4096];char* host = service + 8;if (!strncmp(host, "emu:", 4)) {connect_emulator(host + 4, buffer, sizeof(buffer));} else {connect_device(host, buffer, sizeof(buffer));}snprintf(buf, sizeof(buf), "OKAY%04x%s",(unsigned)strlen(buffer), buffer);writex(reply_fd, buf, strlen(buf));return 0;}
// 移除TCP传输if (!strncmp(service, "disconnect:", 11)) {char buffer[4096];memset(buffer, 0, sizeof(buffer));char* serial = service + 11;if (serial[0] == 0) {// 断开所有TCP设备unregister_all_tcp_transports();} else {char hostbuf[100];// 假设端口5555如果未指定if (!strchr(serial, ':')) {snprintf(hostbuf, sizeof(hostbuf) - 1, "%s:5555", serial);serial = hostbuf;}atransport *t = find_transport(serial);
if (t) {unregister_transport(t);} else {snprintf(buffer, sizeof(buffer), "No such device %s", serial);}}
snprintf(buf, sizeof(buf), "OKAY%04x%s",(unsigned)strlen(buffer), buffer);writex(reply_fd, buf, strlen(buf));return 0;}
// 返回ADB服务器版本if (!strcmp(service, "version")) {char version[12];snprintf(version, sizeof version, "%04x", ADB_SERVER_VERSION);snprintf(buf, sizeof buf, "OKAY%04x%s", (unsigned)strlen(version), version);writex(reply_fd, buf, strlen(buf));return 0;}
// 获取序列号if(!strncmp(service,"get-serialno",strlen("get-serialno"))) {char *out = "unknown";transport = acquire_one_transport(CS_ANY, ttype, serial, NULL);if (transport && transport->serial) {out = transport->serial;}snprintf(buf, sizeof buf, "OKAY%04x%s",(unsigned)strlen(out),out);writex(reply_fd, buf, strlen(buf));return 0;}// 新模拟器实例启动if (!strncmp(service,"emulator:",9)) {int port = atoi(service+9);local_connect(port);return 0;}
#endif // ADB_HOST
// 端口转发管理if(!strncmp(service,"forward:",8) || !strncmp(service,"killforward:",12)) {char *local, *remote, *err;int r;atransport *transport;
int createForward = strncmp(service,"kill",4); // 判断是创建还是删除转发
local = service + (createForward ? 8 : 12);remote = strchr(local,';');if(remote == 0) {sendfailmsg(reply_fd, "malformed forward spec");return 0;}
*remote++ = 0;if((local[0] == 0) || (remote[0] == 0) || (remote[0] == '*')){sendfailmsg(reply_fd, "malformed forward spec");return 0;}
transport = acquire_one_transport(CS_ANY, ttype, serial, &err);if (!transport) {sendfailmsg(reply_fd, err);return 0;}
if (createForward) {r = install_listener(local, remote, transport); // 安装监听器} else {r = remove_listener(local, remote, transport); // 移除监听器}if(r == 0) {writex(reply_fd, "OKAYOKAY", 8); // 双重OKAY响应return 0;}
if (createForward) {sendfailmsg(reply_fd, (r == -1) ? "cannot rebind smartsocket" : "cannot bind socket");} else {sendfailmsg(reply_fd, "cannot remove listener");}return 0;}
// 获取设备状态if(!strncmp(service,"get-state",strlen("get-state"))) {transport = acquire_one_transport(CS_ANY, ttype, serial, NULL);char *state = connection_state_name(transport);snprintf(buf, sizeof buf, "OKAY%04x%s",(unsigned)strlen(state),state);writex(reply_fd, buf, strlen(buf));return 0;}return -1; // 未知服务
}
#if !ADB_HOST
int recovery_mode = 0; // 恢复模式标志
#endif
// 程序主入口
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((argc > 1) && (!strcmp(argv[1],"recovery"))) {adb_device_banner = "recovery"; // 恢复模式标识recovery_mode = 1;}
start_device_log(); // 启动设备日志D("Handling main()\n");printf("-v- Handling main() -v-\n");return adb_main(0, DEFAULT_ADB_PORT); // 进入ADB主循环
#endif
}
