adb install 流程解析
相关文件及函数调用流程
adb install 流程
system/core/adb/adb.c àmain()
system/core/adb/commandline.c àadb_commandline()
system/core/adb/commandline.c àinstall_app()
system/core/adb/commandline.c àpm_command()
system/core/adb/commandline.c à send_shellcommand()
system/core/adb/Adb_client.c àadb_connect()
system/core/adb/Transport.c à writex()
system/core/adb/Sysdeps_win32.c à adb_write()
system/core/adb/Sysdeps_win32.c->fh_write()
system/core/adb/commandline.c àdo_cmd() à va_start()
1、 进入adb
代码位置:system/core/adb/adb.c àmain()
运行adb install命令之后,第一步是进入adb的main函数当中,此处我们的adb命令是从windows上发出的,所以是进入到ADB_HOST当中,所以将命令adb install *.apk去掉adb变成install *.apk传递到adb_commandline(int, char**)。
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();
while(1) {
int c;
int option_index = 0;
static struct option opts[] = {
{"root_seclabel", required_argument, 0, 's' },
{"device_banner", required_argument, 0, 'b' }
};
c = getopt_long(argc, argv, "", opts, &option_index);
if (c == -1)
break;
switch (c) {
case 's':
root_seclabel = optarg;
break;
case 'b':
adb_device_banner = optarg;
break;
default:
break;
}
}
start_device_log();
D("Handling main()\n");
return adb_main(0, DEFAULT_ADB_PORT);
#endif
}
2、 判断命令
函数位置system/core/adb/commandline.c àadb_commandline()
int adb_commandline(int argc, char **argv)
{
…
/* modifiers and flags */
//确定修饰与标志
while(argc > 0) {
…
}
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();
}
...
//跳转安装应用,ttype为传输模式、serial为序列号,argc与argv继续传递install*.apk
if (!strcmp(argv[0], "install")) {
if (argc < 2) return usage();
return install_app(ttype, serial, argc, argv);
}
...
usage();
return 1;
}
3、 得到安装应用的命令,将应用文件从电脑移动到手机的data文件夹或者sd卡当中
函数位置system/core/adb/commandline.c à install_app()
int install_app(transport_type transport,char* serial, int argc, char** argv)
{
//目标数据位置
static const char *const DATA_DEST = "/data/local/tmp/%s";
static const char *const SD_DEST = "/sdcard/tmp/%s";
const char* where = DATA_DEST;
int i;
struct stat sb;
//-s可以安装到sd卡当中
for (i = 1; i < argc; i++) {
if (!strcmp(argv[i], "-s")) {
where = SD_DEST;
}
}
// Find last APK argument.
// All other arguments passed through verbatim.
//从最后一个argv开始查找,直到找到一个apk为止
int last_apk = -1;
for (i = argc - 1; i >= 0; i--) {
char* file = argv[i];
char* dot = strrchr(file, '.');
if (dot && !strcasecmp(dot, ".apk")) {
if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
fprintf(stderr, "InvalidAPK file: %s\n", file);
return -1;
}
last_apk = i;
break;
}
}
if (last_apk == -1) {
fprintf(stderr, "Missing APK file\n");
return -1;
}
char* apk_file = argv[last_apk];
char apk_dest[PATH_MAX];
snprintf(apk_dest, sizeof apk_dest, where, get_basename(apk_file));
//首先把应用从原来的位置放到apk_dest上,apk_dest目录在/data/local/tmp/
int err = do_sync_push(apk_file, apk_dest, 0 /* no show progress */);
if (err) {
goto cleanup_apk;
}else {
argv[last_apk] = apk_dest; /* destination name, not source location */
}
//通过pm执行安装应用的命令
pm_command(transport, serial, argc, argv);
cleanup_apk:
delete_file(transport, serial, apk_dest);
return err;
}
4、通过pm命令安装应用
static int pm_command(transport_typetransport, char* serial,
int argc, char** argv)
{
char buf[4096];
snprintf(buf, sizeof(buf), "shell:pm");
while(argc--> 0) {
//将一些分割符号替换为\\符号
char *quoted = escape_arg(*argv++);
strncat(buf, " ", sizeof(buf) - 1);
strncat(buf, quoted, sizeof(buf) - 1);
free(quoted);
}
//此处传入的buff经过处理后的值是shell:pm install *.apk
send_shellcommand(transport, serial, buf);
return 0;
}
5、 调用shell执行pm命令
system/core/adb/commandline.c àsend_shellcommand()
static int send_shellcommand(transport_typetransport, char* serial, char* buf)
{
int fd, ret;
for(;;) {
//每秒通过adb_connect传递命令
fd = adb_connect(buf);
if(fd >= 0)
break;
fprintf(stderr,"- waiting for device -\n");
adb_sleep_ms(1000);
do_cmd(transport, serial, "wait-for-device", 0);
}
read_and_dump(fd);
ret = adb_close(fd);
if (ret)
perror("close");
return ret;
}
6、校验Adb服务端的情况并保证通过adb客户端传递信息时服务端正常运行
system/core/adb/Adb_client.c àadb_connect()
int adb_connect(const char *service)
{
// first query the adb server's version
//首先查询adb服务的版本
int fd = _adb_connect("host:version");
//然后检验adb服务的状态是否异常
...
// if the command is start-server, we are done.
if (!strcmp(service, "host:start-server"))
return 0;
//验证完成之后通过_adb_connect()继续传递参数
fd = _adb_connect(service);
if(fd == -1) {
D("_adb_connect error: %s\n", __adb_error);
} else if(fd == -2) {
fprintf(stderr,"** daemon still not running\n");
}
D("adb_connect: return fd %d\n", fd);
return fd;
error:
adb_close(fd);
return -1;
}
7、连接到服务端并通过writex写入长度以及具体的客户端命令
int _adb_connect(const char *service)
{
char tmp[5];
int len;
int fd;
D("_adb_connect: %s\n", service);
len = strlen(service);
if((len < 1) || (len > 1024)) {
strcpy(__adb_error, "service name too long");
return -1;
}
snprintf(tmp, sizeof tmp, "%04x", len);
if (__adb_server_name)
fd = socket_network_client(__adb_server_name, __adb_server_port,SOCK_STREAM);
else
fd = socket_loopback_client(__adb_server_port, SOCK_STREAM);
if(fd < 0) {
strcpy(__adb_error, "cannot connect to daemon");
return -2;
}
if (memcmp(service,"host",4) != 0 &&switch_socket_transport(fd)) {
return -1;
}
//此处写入长度以及命令
if(writex(fd, tmp, 4) || writex(fd, service, len)) {
strcpy(__adb_error, "write failure during connection");
adb_close(fd);
return -1;
}
if(adb_status(fd)) {
adb_close(fd);
return -1;
}
D("_adb_connect: return fd %d\n", fd);
return fd;
}
8、通过adb_write()写入
int writex(int fd, const void *ptr, size_tlen)
{
char *p = (char*) ptr;
int r;
#if ADB_TRACE
D("writex: fd=%d len=%d: ", fd, (int)len);
dump_hex( ptr, len );
#endif
while(len > 0) {
r = adb_write(fd, p, len);
if(r > 0) {
len -= r;
p += r;
} else {
if (r < 0) {
D("writex: fd=%d error %d:%s\n", fd, errno, strerror(errno));
if (errno == EINTR)
continue;
if (errno == EAGAIN) {
adb_sleep_ms(1); // justyield some cpu time
continue;
}
} else {
D("writex: fd=%ddisconnected\n", fd);
}
return -1;
}
}
return 0;
}
9、写入adb驱动,通过fh_write将shell命令
System/core/adb/System_win32.c
int adb_write(int fd, constvoid* buf, int len)
{
FH f = _fh_from_int(fd);
if (f == NULL) {
return -1;
}
return f->clazz->_fh_write(f, buf, len);
}