天天看點

【android x86 5.1.1】 adb install 流程分析

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);

}