adb命令安装流程分析
adb的原理
adb是采用socket的方式实现手机和PC的通信的。
adb调试桥采用的是客户机-服务器的架构模式,包含三个部分:
- adb client:运行在PC上的服务,命令就是通过client转发出去的
- adb server:运行在PC上的后台进程,负责着clent和daemon之间的通讯
- adb daemon:运行在手机上的首台进程
当pc上运行adb服务时,adb服务首先会检查adb server进程是否运行,不运行的话启动server;服务启动后,会监听5037端口。
server与正在运行的emulator/device进行自动连接,连接端口号范围为5555-5585。一个连接会同时使用到2个端口号,一个偶数端口号作为控制台连接端口号和一个奇数端口号作为adb连接端口号。
adb install命令
adb install的安装主要是调用system/core/adb/commandline.c
进行操作的。
安装对应着commandline.c里的install_app()
函数。
int install_app(transport_type transport, char* serial, int argc, char** argv)
{
if (!(err = do_sync_push(filename, to, 1 /* verify APK */))) {
/* file in place; tell the Package Manager to install it */
argv[argc - 1] = to; /* destination name, not source location */
pm_command(transport, serial, argc, argv);
delete_file(transport, serial, to);
}
}
static int pm_command(transport_type transport, char* serial,
int argc, char** argv)
{
char buf[4096];
snprintf(buf, sizeof(buf), "shell:pm");
while(argc-- > 0) {
char *quoted;
quoted = dupAndQuote (*argv++);
strncat(buf, " ", sizeof(buf)-1);
strncat(buf, quoted, sizeof(buf)-1);
free(quoted);
}
send_shellcommand(transport, serial, buf);
return 0;
}
static int send_shellcommand(transport_type transport, char* serial, char* buf)
{
int fd, ret;
for(;;) {
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;
}
可以看出,最终是通过send_shellcommand()
将数据发送到手机端的adbd守护进程中,而手机端守护进程收到这个安装请求后,会执行pm的指令。
Android设备端pm命令位于/system/bin
目录下,其是一个脚本,具体内容如下:
#!/system/bin/sh
base=/system
export CLASSPATH=$base/framework/pm.jar
exec app_process $base/bin com.android.commands.pm.Pm "$@"
pm命令通过app_process执行pm.jar包的main函数。
启动安装
启动安装主要是通过PMS进行安装包的扫描和解析。