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
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)
{
…
//确定修飾與标志
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 );
if (err) {
goto cleanup_apk;
}else {
argv[last_apk] = apk_dest;
}
//通過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);
}