引自https://source.android.com/devices/tech/ota/apex
因本人忘性越来越大,故记录一下本文加深下记忆,描述有些问题的地方见谅。
建议有英文阅读能力的同学自行访问官方网址。
Android Pony EXpress (APEX) 是Android 10引入的一种容器格式,用于底层系统模块的安装flow。因为不用符合Android标准应用程序格式, 因此该格式的引用可以促进更新系统模块。底层模块包括像Native的services和库、HALs、ART等。
尽管Android支持底层系统模块以安装Android应用程序的方式更新,但仍然有以下缺点
1、基于APK的模块无法在启动流程中更早的启动。PackageManager 是apk的重要存储中心,且只能被activity manager启动。因此,APK的模块只能在启动序列较晚的阶段中准备好。
2、APK的格式(尤其是manifest)对系统模块来说并不是非常适合
本节介绍APEX文件格式和APEX Manager。APEX Manager是管理APEX文件的Service。
APEX文件格式如下
Note: 上图应该是Android Q的,R应该又有些变化
从顶层看,APEX文件是一个Zip文件,其中的文件均是未压缩的。
其中的四个文件有
apex_manifest.json文件包括package name和版本,用来标识该APEX文件
AndroidManifest.xml可以允许APEX文件使用一些apk的工具,像adb、package manager、 app install app等。举个例子APEX文件可以使用aapt检查文件的metadata。该文件还包括packcage name和版本号,这些内容通常也会再apex_manifest.json文件中。
apex_payload.img是依赖dm-verity的EXT4文件系统镜像。该镜像在运行时通过一个回环设备加载。具体地说,metadata和hash tree是通过libavb创建的。apex_payload.img还没有被解析,因为要求该文件是可挂载的。一些常规文件包含在该镜像中。
apex_pubkey是用来给文件系统签名的公钥。该公钥确保下载的apex文件是以编译阶段相同的方式签名。
APEX Manger是个独立的Native进程,用来验证、卸载、安装APEX文件。该进程会在启动序列的早期启动并准备好。预安装的APEX文件通常在设备的/system/apex目录下。当没有其他更新可用时,APEX Manger默认使用这些package。
APEX使用Package Manager更新的过程如下:
当所有的APEX文件均被加载后,APEX Manger会创建一个binder service以便让其他的系统组件查询已安装的APEX文件列表。举个例子,系统组件可以查询到所有已安装的APEX文件列表以及其挂载位置。
APEX文件是一个有效的APK文件,因为它有使用APK签名机制签名。这就允许了apex文件使用一些apk的基本功能,像包安装app、签名组件和package manager。
AnroidManifest.xml包括信息有package name、versionCode,还有可选项的targetSdkVersion、minSdkVersion和maxSdkVersion。这些信息就允许APEX文件可以使用apk的现有传输途径,像ADB等。
APEX格式支持以下类型:
Native层的共享库
Naive层的可执行bin档
JAR文件
数据文件
配置文件
这不意味着APEX可以完全替换这些文件类型,还要看平台支持和接口的稳定程度。
APEX文件签名需要两个过程。首先,apex_payload.img文件单独被签名。接着,整个APEX文件通过APK签名方案V3签名。两个过程使用的是不同的Key。
在设备端,安装了公钥(对应vbmeta签名的私钥)。APEX Manger通过公钥验证APEX文件可以被安装。
APEX文件可以位于内置分区中,如/system。分区已经在dm verity上,因此APEX文件直接挂载在环回设备上。
如果APEX存在于内置分区中,则可以通过提供具有相同包名和更高版本代码的APEX包来更新APEX。新的APEX存储在/data中,与apk类似,新版本会隐藏内置分区中已经存在的版本。但与apk不同的是,APEX的新版本只在重启后才被激活。
本节描述如何编译一个APEX文件。下面展示名为apex.test的APEX文件。
Android.bp文件如下:
apex_manifest.json如下:
file_contexts如下:
文件类型和路径如下(相应文件放到子目录中)
File type | Location in APEX |
---|---|
Shared libraries | /lib and /lib64 (/lib/arm for translated arm in x86) |
Executables | /bin |
Java libraries | /javalib |
Prebuilts | /etc |
APEX将自动include可执行bin档或者Native共享库的依赖。举个例子,比如LibFoo依赖LibBar,当LibFoo在APEX的native_shared_libs属性中时,LibBar也会被include进来。
需要给每个APEX使用不同的Key进行加密。当需要一个新的Key时,会创建一对公私密钥对和生成一个apex_key模块。使用Key属性去给APEX加密。公钥文件(avb_pubkey)就会自动放到APEX里。
上面的例子就是生成了id为foo的公钥。公钥签名了APEX后,将该id记录在了APEX中。在运行期间,apexd会通过id 找到在设备上的公钥,并来验证APEX文件。
使用APKs签名方式签名APEXs文件。APEXs需要签名两次,一次是签名给小文件系统中apex_payload.img,一次是整个文件。
这个文件的签名,可以选择以下三个方式的一种进行设置certificate属性:
不设置:如果未设置该属性,APEX将会使用PRODUCT_DEFAULT_DEV_CERTIFICATE flag指示的证书位置,如该flag没有设置,将默认build/target/product/security/testkey。
:
例子如下
安装一个apex文件,使用adb工具
在reboot后,APEX被挂载在/apex/
Client端可以使用绑定的挂载目录从APEX读取和执行文件。
通常如下方式访问APEX:
使用APEX更新service
1、service定义的地方增加updatable标签
2、为更新service创建新的rc文件,使用override标签重定义service
service的定义只能再APEX的rc文件中,APEX不支持动作触发
如果service被标记updatable,那么只能再APEX激活后,才会启动service。
配置如下的 system property为true,才能支持APEX更新
或者