type
status
date
slug
summary
tags
category
icon
password
Android系统的代码总是在不断迭代的,具体的类和方法本身并不重要,关键是了解流程与主要的路径本文基于AOSP master分支 2020年8月,Android 11 已经处于beta版
三种安装方式
- 系统级app安装
- 普通app安装
- adb安装
这里看一下普通APP的安装.
在分析之前,想一下如果是我们来安装apk,需要怎么做:
- apk实际上是一个zip包,先解压,要不然只能测量下大小了,当然也可以不解压直接查看zip包的内容
- 系统重启之后我们依然要快速显示和启动app,那么肯定得存一份APP信息到手机上,那么存什么信息呢?
- 可执行文件的位置,在Android里跑的是dex,或者dex处理过后的机器码,因此这里应该是dex或者oat文件的位置
- 应用有一些特殊的功能,比如可以用来打开文档,网页等,因此需要把这些信息注册到一个系统表里,可以快速查询,Android中应也有这么一个表
而且最好是把apk的资源,可执行文件等内部数据放到一个文件夹下,这样卸载的时候可以直接删除目录.
- zip包解压了,信息也存了,为了安全,应该把对应的可执行文件和资源文件复制到指定的路径,如果有so库,还要让程序知道去哪里找so文件
- 检查手机上之前是否已经安装了这个app,如果安装了,比较一下版本,签名,再确定怎么处理
- 删除apk包以节省空间
APK解压缩
APK的解析在Java中的入口在
PackageParser
中,但是实际解压的操作在Native层,也就是ApkAssets
中,ApkAssets
中会调用libziparchive库去解压缩APK.解压的具体的过程就不分析了,使用解压库就行,来看下Manifest.xml信息的提取.
ApkAssets.java
中有:frameworks/base/core/jni/android_content_res_ApkAssets.cpp
中有:在
AppAssets.cpp
中有:Android中的资源主要是Deflate和Stored两种压缩方式,其中Stored实际并不压缩数据,只是转换成字节数据存储而已.
Manifest.xml使用了Deflate压缩算法进行压缩,因此这里需要对应的解压出来.
其他的几个步骤,在零零碎碎的源码中找吧.
普通APP安装
先看一个简单的下载并安装apk的例子:
这里使用
ACTION_VIEW
,最终会调用到PacakgeInstaller APP中.Android 10的PacakgeInstaller源码在framworks/base/packages/PackageInstaller下,看一下它的Manifest.xml来确定下谁是入口:
可以看到PackageInstaller支持的action以及协议,即content协议和package协议.
进入了
InstallStart
之后,根据状态的不同可能会经过InstallStaging
等页面后进入到PacakgeInstallerActivity
,然后就是不同的安装进度了,InstallInstalling
InstallFailed
InstallSuccess
:来看一下关键的对象:
然后就是开始安装APP了:
来看下InstallInstalling中的处理逻辑:
将信息保存到SessionParams中,并返回一个sessionId,后面会用到这个sessionid,在onResume的时候会启动一个后台任务去读取APK文件:
这里主要是读取APK文件到Session中,并更新安装进度.读取完毕之后发送一个广播.
此处的关键是就是
session.commit()
方法.这里会调用PackageManagerService中.首先进入的是Copy阶段:
复制APK
这个copy阶段会进行一些判断,比如存储空间是否足够,如果不够会试图清理一下缓存,如果之前已经存在了APK,则直接覆盖,但是如果存在APK验证器,则必须在copy之前进行验证,只有验证通过之后才可以开始复制APK.
APK会被复制到/data/app下:
实际的copy过程如下,使用了FileDescriptor:
复制之前,会使用
PacakgeParser
解析APK中的mannifest文件,得到一些应用信息,并且还会获取签名信息.然后就是复制apk文件,并且复制APK中的so文件到指定的路径.
复制完成之后,进入下一阶段
processPendingInstall(mArgs, mRet);
安装APK
对于包含split APP的安装过程暂时不分析,这里指分析单个完整APK的安装流程.
实际安装步骤在
installPackagesLI(requests)
:这里分为4个步骤:
- prepare
使用PackageParser解析APK,获取各种信息,检查是否有静态共享库,有的话放在内部存储中.决定安装方式(更新,还是新安装)之类的逻辑.
- scan
扫描APK,更新共享库和Settings信息
- reconcile
新旧包以及签名相关的逻辑
- commit
更新设置
其实都是对APK文件进行一系列的检查验证,以确保最后可以安装成功.然后就是真实的安装了:
这里主要分为两部:
- 调用Installer创建APP数据
- 如果so库是32为,创建symlink,64位的so库不需要
Installer
中的操作基本上都是委托给守护进程installd
去完成的.Installer中通过Binder机制获取到intalld服务,真实的执行逻辑在native层:
总结
- 应用发出Intent,要求应用内安装APK;
- PackageInstaller APP 中的
InstallStart
Activity接收到Intent,解析数据;
- 转到PackageInstallerActivity展示界面,用户确认之后开始进入安装过程;
- 请求PackageManagerService去完成安装,这里会复制APK到指定目录中,并进行签名验证
- 通过binder机制请求
installd
守护进程去完成安装过程.
- 作者:姜康
- 链接:https://jiangkang.tech/article/2c0e6ac7-fe1e-4dba-8000-fc88e9042629
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。