APK安装流程详解(二)
一.Installer、InstallerConnection和Installd守护进程
1.1Installer
Installer继承自SystemService,在Android中有两个SystemServer,一个是os/SystemService.java,另一个是server/SystemService.java,这里Installer继承的是server/SystemService.java,所以我们可以说Installer其实是一个系统服务。
1.2InstallerConnection
InstallerConeection就是一个连接类,负责连接installd
1.3Installd守护进程
1.3.1概述
上一篇文章我们知道PMS负责应用的安装、卸载等工作,但是里面主要是“Manager”,Installd才是真正干活的,PMS是通过访问installd服务来执行程序包的安装与卸载的。
1.3.2为什么要用installd
有的同学可能要问,PMS已经有一万多行了,为什么还要再加一个installd服务呢?这样不是画蛇添足了吗?
其实不是的,因为PMS只有system权限,而installid具有root权限。如下图:

1.3.3installd支持的命令
struct cmdinfo cmds[] = {
{ "ping", 0, do_ping }, // 用于测试的空操作
{ "install", 5, do_install }, // 安装应用
{ "dexopt", 9, do_dexopt }, //将dex转换为oat或者patchoat oat文件
{ "markbootcomplete", 1, do_mark_boot_complete },
{ "movedex", 3, do_move_dex }, //把apk文件从一个目录移动到另一个目录
{ "rmdex", 2, do_rm_dex }, // 删除apk文件
{ "remove", 3, do_remove }, // 卸载应用
{ "rename", 2, do_rename }, // 更改应用数据目录的名称
{ "fixuid", 4, do_fixuid }, // 更改应用数据目录的uid
{ "freecache", 2, do_free_cache }, // 清除/cache目录下的文件
{ "rmcache", 3, do_rm_cache }, // 删除/cache下某个应用的目录
{ "rmcodecache", 3, do_rm_code_cache }, // 删除数据目录中code_cache文件夹
{ "getsize", 8, do_get_size }, // 计算一个应用占用的空间大小,包括apk大小,数据目录,cache目录等
{ "rmuserdata", 3, do_rm_user_data },// 删除一个用户中某个app的应用数据
{ "cpcompleteapp", 6, do_cp_complete_app },
{ "movefiles", 0, do_movefiles },//执行/system/etc/updatecmds/中的脚本
{ "linklib", 4, do_linklib }, // 建立 jib连接
{ "mkuserdata", 5, do_mk_user_data },// 为某个用户创建应用数据目录
{ "mkuserconfig", 1, do_mk_user_config },// 创建/data/misc/user/userid/
{ "rmuser", 2, do_rm_user },// 删除一个user的所有文件
{ "idmap", 3, do_idmap },
{ "restorecondata", 4, do_restorecon_data },// 恢复目录的SEAndroid安全上下文
{ "createoatdir", 2, do_create_oat_dir }, // 创建 /data/app/包名/oat/<inst>文件夹
{ "rmpackagedir", 1, do_rm_package_dir },// 删除/data/app/包名
{ "linkfile", 3, do_link_file } // 创建软连接
};
上表我们可以看到,几乎所有跟包相关的文件操作都是installid的指令集完成的。
1.3.4小结

PMS启动过程中使用了Installer的之个方法。APK的安装和卸载主要是由Installer和Installd完成的。Installer是Java层提供的Java API接口,Installd则是init进程启动的Daemon Service。Installer与Installd通过Socket通信,Installer是Socket的Client端,Installd则是Socket的Server端。通过Socket通信,将Installer的API调用转化为Installd中具体命令
二.APK安装流程
Android应用最终是打成APK文件然后安装至手机运行的。其中APK是Android Package的缩写。
2.1应用安装涉及到的目录
- /system/app :系统自带应用程序,获得root权限才可删除
- /data/app: 用户程序安装的目录,安装时把APK文件复制到此目录
- /data/data:存放应用程序的数据
- /data/dalvik-cache:将apk中的dex文件copy到该目录下,ART可执行文件为.oat,启动ART时,系统会执行dex文件转换至oat
- /data/system:该目录下的packages.xml文件,类似于Windows的注册表,记录了系统的permissions,每个apk的name,codePath,,version,userid等信息,这些信息主要通过AndroidManifest.xml文件解析获取,解析完apk后将更新信息写入这个文件并保存到flash,下次开机的时候直接从里面读取相关信息并添加到内存相关列表中。当有APK安装、升级或者删除时会更新这个文件。
- /data/system/packages.xml /data/system/packages.list:packages.list指定了应用的默认存储位置/data/data/com.xxx.xxx;package.xml中包含了该应用权限、应用包名、APK的安装位置、版本、userID等信息,并且两者都有同一个userld。之所以每个应用都要一个userId,是因为Android在系统设计上把每个应用当做Linux系统上的一个用户对待,这样就可以利用已有的Linux用户管理机制来设计Android应用,比如应用目录,应用权限,应用进程管理等。
2.2安装流程概述
apk的大体流程如下:
- 第一步,拷贝文件到指定目录:在Android中,APK文件是会被保存起来的,默认情况下,用户安装的app首先会被拷贝到/data/app目录下,/data/app目录是用户有权限访问的目录,在安装apk的时候会自动选择该目录存放用户安装的文件,而系统出厂apk被放到/system分区下,这就是没有ROOT手机前,我们无法删除系统app的原因。
- 第二步,解压缩apk,copy文件,创建应用的数据目录:为了加快app的启动速度,apk在安装的时候,会首先将app的可执行文件dex拷贝到/data/dalvik-cache目录,缓存起来。然后,在/data/data/目录下创建应用程序的数据目录(以应用的包名命名),存放在应用的相关数据,如数据库、xml文件、cache、二进制的so动态库等。
- 解析apk中的AndroidManifest.xml文件:系统在安装apk的过程中,会提取AndroidManifest.xml中的信息,用来更新/data/system/packages.xml文件
- 显示快捷方式:安装完毕之后,我们需要有一个Home应用,负责从PMS中把安装好的应用程序取出来,并以友好的方式在桌面上展现出来,在Android系统中,发挥这个作用的应用就是Launcher
2.3APK安装的界面
我们在安装应用时,出现的界面是系统的安装APP-PackageInstall.apk,篇幅和时间关系我们就不展开分析了,大致上,这个app就是封装了对PMS的调用,感兴趣的同学可以查阅相关资料。
网友评论