【android x86 5.1.1】 adb install 流程分析

VMware虚拟机安装Android-x86:打造纯净可控的安卓开发测试环境 虚拟化技术通过在单一物理硬件上创建多个隔离的虚拟环境,实现了资源的高效利用与环境的灵活部署。其核心原理在于通过Hypervisor层抽象硬件资源,为每个虚拟机提供独立的操作系统实例。这项技术的价值在于为软件开发、测试和安全研究提供了高度可控、可复现且与宿主机隔离的沙箱环境。在移动应用生态中,安卓应用开发、自动化测试以及安全分析等场景,尤其需要一个稳定、纯净且配置灵活的安卓系统环境。传统的商业模拟器往往存在系统定制、捆绑软件或控制权有限的问题。通过将Android-x86项目移植到VMware这类专业虚拟化平 阅读详情

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

}

【ADB】在adb shell中安装apk文件 (如某些系统分区受限的设备),可以尝试将 APK 内容通过管道传递给。中安装 APK 文件,可以通过以下步骤完成。内安装(例如需要脚本自动化或调试),可以使用。如果 APK 文件已经通过。 阅读详情

相关推荐

安卓模拟器安装APK全攻略:ADB命令、架构兼容与常见错误排查

安卓模拟器是一种通过软件虚拟出完整Android运行环境的工具,但它并非简单的一台虚拟手机。由于宿主机CPU架构与APK目标架构可能不同,安装应用时经常遇到INSTALL_FAILED_NO_MATCHING_ABIS等错误,这也是许多用户在模拟器上安装软件失败的主要原因。理解虚拟化原理、ABI兼容性以及ADB调试通道的工作机制,是解决这类问题的关键。ADB不仅提供可靠的命令行安装方式,还能输出标准化错误码,帮助定位问题。通过adb install、adb shell pm list packages、lo

weixin_34258838的博客 304

Android Adb 源码分析(一)

扭起屁股得意洋洋最近,我负责的项目因为临近量产,把之前的userdebug版本关闭,转成了user版本,增加selinux的权限,大家都洋溢在项目准备量产的兴奋和喜悦之中不能自拔谁知,好景不长,user版本发布之后,各种bug接踵而来,但是因为user版本权限的原因,我们之前保留在/data/logs/下面的日志不能pull出来,定位问题非常困难不得不想到的解决方案第一个办法:我们想到的第一个办法就是更改data目录的权限,改成system用户,但是因为data下面的logs目录的文件是root权限,获取日

kunkliu的博客 3788

凤凰系统安装与ADB调试指南:在PC上打造安卓桌面环境

Android-x86项目将移动操作系统移植到x86架构PC,实现了安卓生态在传统计算机上的运行。其核心原理是通过修改Linux内核与硬件抽象层,使安卓系统能识别并驱动PC硬件。这项技术的价值在于为开发者提供了原生、高效的安卓测试平台,同时让老旧PC变身为轻量级娱乐或办公终端。在实际应用场景中,用户可通过制作启动U盘安装凤凰系统这类定制发行版,并利用ADB调试工具进行深度控制与文件传输。本文聚焦于凤凰系统的安装部署与网络ADB连接配置,其中涉及SSHDroid架设SFTP服务器、ADB环境变量配置等关键热词

diandingyin9417的博客 408

Android ADB 你想要的都在这

1、模拟按键事件 模拟返回(back)事件 adb shell input keyevent 4 键值表在:frameworks/base/core/java/android/view/KeyEvent.java 2、发送broadcast(广播) 广播模型: private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { @Override public void onR

qq_27494201的博客 9179

Mac上如何用Android Studio轻松运行APK?5分钟搞定安卓虚拟机配置

本文详细指导Mac用户如何利用Android Studio快速配置安卓虚拟机并运行APK。核心在于正确选择与Mac芯片匹配的系统镜像ABI,避免常见的INSTALL_FAILED_NO_MATCHING_ABIS错误,并通过ADB命令或拖拽等方式高效安装APK,助力开发者快速搭建流畅的安卓应用测试环境。

alpha的博客 538

逍遥模拟器安卓7.1安装Xposed框架v87完整指南与排错

Xposed框架作为Android系统级的模块化扩展框架,其核心原理是通过替换系统关键文件(如app_process)实现运行时代码注入,从而允许在不修改APK的情况下改变应用行为。这一技术为应用逆向分析、自动化测试和功能增强提供了底层支持,尤其在需要动态修改应用逻辑的场景中价值显著。在x86架构的Android虚拟环境(如逍遥模拟器)中部署Xposed,需严格匹配框架版本与系统API级别(如SDK 25对应Android 7.1),并正确处理系统分区挂载与文件权限。本文以逍遥模拟器安卓7.1为例,详细解析

weixin_33797791的博客 323

android 5.1.1,最新的安卓5.1.1 ROOT教程(不需要刷第三方内核)

该楼层疑似违规已被系统折叠隐藏此楼查看此楼大家感谢Chainfire无私的奉献!等谷歌市场登陆中国,如果有supersu大家付费支持吧!我是这样想的,前段时间苦于5.1.1无法直接卡刷supersu。必须先刷第三方内核(第三方内核大家懂得,多少有些问题)但是三星并还并没有上传OK系列的原码。还好我们的大神不负众望,解决了需要第三方内核的问题,马隆大神也给Chainfire发去了开机第一屏红字问题...

weixin_39987211的博客 1667

Android模拟器安装APK全攻略:ADB命令与故障排查实战

虚拟化技术让我们可以在电脑上运行完整的Android系统,为应用调试、自动化测试和软件试用提供了隔离环境。而ADB(Android Debug Bridge)作为连接电脑与模拟器的官方调试工具,是执行安装、日志分析和设备管理的关键桥梁。在实际工程中,APK的安装方式多种多样,从图形界面的拖拽安装到命令行操作,各有适用场景。理解ADB install的常用参数、系统权限模型以及CPU架构(如x86与ARM)的匹配关系,能有效解决解析失败、版本降级、ABI不兼容等高频问题。本文从模拟器基础概念出发,结合开发者日

weixin_30595035的博客 471

adb 深入分析一1、adb模块的源码路径,源码编译生成的结果。 2、adb模块分为adb client、adb server、services、adbd daemon几个模块。 3、adb通讯模

1、adb模块的源码路径,源码编译生成的结果。 2、adb模块分为adb client、adb server、services、adbd daemon几个模块。 3、adb通讯模型。 4、adb与 adbd daemon的入口函数

冯海林的专栏 4037

adb install --abi:Android强制指定32/64位安装的ABI匹配指南

在Android应用安装和运行过程中,ABI(应用二进制接口)是连接CPU指令集与so库的关键桥梁。当APK中的Native库与设备CPU架构不匹配时,就会出现解析包错误、安装失败或启动闪退等问题。随着64位设备普及,系统默认优先选择arm64-v8a,但某些场景仍需强制指定32位运行。通过adb install --abi参数,开发者可以绕过系统默认ABI选择,精确控制App以32位或64位模式安装,从而复现线上崩溃、对比性能差异、兼容旧版SDK。本文从ABI原理出发,详解adb与pm命令的实操方法,并总

weixin_33875839的博客 281

X86系统android adb调试工具

万能android开发调试工具,免去安装,放到硬盘里就能直接用。 在cmd命令提示符中,进到adb.exe目录,直接就可以用adb命令操作。

多apk发布的Android程序的adb安装——adb install-multiple

多apk发布之所以然:多架构、多语言、多Layout;Google Play应用程序与手机匹配策略;adb install-multiple

田海立@优快云 1万+

android 5.1的ADB 工具ADB最新工具

adb 最新工具,从android SDK 24中拷贝出来

使用拷贝的方式(adb push) 绕过Android系统和adb install 直接安装APK

某些情况下定制的Android系统为了限制用户安装应用,例如电视盒子,车载中控等,通过修改代码屏蔽了正常安装应用的方式 本文探讨如何在 adb shell 具有读写data分区目录的权限前提下,通过adb push 拷贝方式绕过Android系统和adb install直接安装apk到Android系统,适用于对Android系统和adb指令操作有一定基础的读者 测试环境:夜神模拟器(...

a462533587的博客 1万+

OPC与AI智能体集成实战:一人公司的技术栈构建与避坑指南

1. 先搞清楚“一人公司”和“AI工具”到底在解决什么问题 最近看到不少关于“裸辞搞OPC一人公司”和“AI时代骗局”的讨论,结合搜索热词里高频出现的 openclaw 、 AI编程 、 OPC ,我觉得有必要把这里面的水搅一搅,说点实在的。 首先得拆开看。标题里混了三个东西: 一人公司 、 OPC/OpenClaw 、 AI培训 。它们被放在一起讨论“骗局”,但本质上解决的是不同层面的问题。 一人公司 ,或者说个人工作室、独立开发者模式,核心是 用最小化团队(甚至一个人)去承接项目、开发产品或提供服务 。

weixin_29038345的博客 320

手把手教你安装 Vivado2019.2(附安装包)

Vivado 2019.2 作为 Xilinx 公司发布的一款设计套件版本,具有多个显著的优点,以下是对其优点的详细归纳

dpwkj的博客 1万+

告别卡顿广告盒:用ADB命令玩转原生Android TV x86的完整配置与优化指南

本文提供了一份完整的Android TV x86配置与优化指南,重点介绍如何使用ADB命令打造无广告、高性能的原生电视系统。从镜像选择、系统安装到ADB深度配置,涵盖ARM兼容性解决方案、性能调优技巧和必备应用推荐,帮助用户彻底告别卡顿广告盒,享受纯净流畅的电视体验。

weixin_30572613的博客 368

人工智能情感分析实战:文本情绪识别

人工智能情感分析,特别是文本情绪识别,已成为理解和处理人类情感信息的重要工具。通过数据预处理、特征提取、模型训练与评估等步骤,我们可以有效地从文本数据中提取情感信息,为各种应用场景提供有价值的洞察。随着技术的不断进步和创新,情感分析的应用前景将更加广阔,为我们的生活和工作带来更多便利和机遇。

shejizuopin的博客 1095

安卓模拟器安装APK全攻略:从拖拽到adb,彻底解决安装失败

安卓模拟器本质上是运行在PC上的虚拟Android系统,安装APK看似简单,实则涉及系统版本、CPU架构、签名校验和ADB连接等多重因素。不同模拟器如雷电、MuMu、夜神及Android Studio自带的AVD,在底层实现与安装路径上存在差异,导致同一APK在不同环境下的表现截然不同。理解其虚拟化原理与APK兼容性机制,是高效安装与问题排查的基础。掌握adb install命令及参数,配合环境检查和失败日志分析,能够大幅提升开发调试与自动化测试的效率。无论是拖拽安装、命令行安装还是通过应用商店,最终都要验

weixin_30945039的博客 405

SAP-ML章<<<<第二节:物料账报错处理ABAP编程错误:RAISE_EXCEPTION>>>>

#SAP-ML章<<<<第一节:物料账报错处理ABAP编程错误:RAISE_EXCEPTION>>>> 1.物料账报错提示: ABAP编程错误:RAISE_EXCEPTION ABAP程序:SAPLFCML4H_RUN_PRICES应用组件CO-PC-ACT 2. 物料账报错背景: CKMLCP运行结算时 3. 解决方案: 通过DEBUG查看错误的地方 OKTZ:分析原因为:可能打包或者配置传输时弄错 ...

SAP.David.Gao的博客 1858

STM32Cube高效开发教程<高级篇><FreeRTOS>(十八)-----软件定时器

一、 软件定时器概述声明:本人水平有限,博客可能存在部分错误的地方,请广大读者谅解并向本人反馈错误。本专栏博客参考《STM32Cube高效开发教程(高级篇)》,有意向的读者可以购买正版书籍辅助学习,本书籍由王维波老师、鄢志丹老师、王钊老师倾力打造,书籍内容干货满满。在FreeRTOS中,自动创建的任务有空闲任务和定时器服务任务。FreeRTOS可以通过定时器服务任务提供软件定时器功能。在某些对定时精度要求不太高,无须使用硬件定时器的情况下,我们可以使用FreeRTOS的软件定时器。

我的博客 157

adb打开packages_使用拷贝的方式(adb push) 绕过Android系统和adb install直接安装APK

某些情况下定制的Android系统为了限制用户安装应用,例如电视盒子,车载中控等,通过修改代码屏蔽了正常安装应用的方式本文探讨如何在 adb shell 具有读写data分区目录的权限前提下,通过adb push 拷贝方式绕过Android系统和adb install直接安装apk到Android系统,适用于对Android系统和adb指令操作有一定基础的读者测试环境: 夜神模拟器(Android...

weixin_29169505的博客 991

Python爬虫:爬取健身平台运动数据(跑步、骑行轨迹)

通过分析这些运动数据,用户能够了解自己的运动趋势、运动成绩,并作出相应的调整。通过使用Strava的API,我们成功地获取了用户的运动活动信息和运动轨迹数据,并进行了存储与可视化。Strava的API提供了丰富的数据接口,能够通过OAuth2认证获取用户的运动数据,包括历史数据、运动轨迹等信息。Strava的API还提供了获取活动轨迹数据的接口,返回的数据格式通常是GeoJSON格式,适用于地图可视化。随着大数据技术的发展,运动数据的分析和可视化为个人健康管理、运动训练计划的优化等提供了强大的支持。

2201_76125261的博客 1075
上一篇: 面向接口编程------编程思想
下一篇: 项目成本评估及预算的制定
class_brick
博客等级 码龄12年 223粉丝 76原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值