深入理解 Android:PackageManagerService
SystemServer 创建 PackageManagerService:
调用
PackageManagerService的main()方法,得到IPackageManager对象;调用
IPackageManager.isFirstBoot()判断是否开机后第一次启动(Zygote或SystemServer退出后,init会再次启动它们);调用
IPackageManager.performBootDexOpt()执行 dex 优化;调用
IPackageManager.systemReady()通知系统已进入就绪状态;
PackageManagerService 构造方法:
创建
Settings对象,并调用其addSharedUserLPw()方法,保存SharedUserSetting信息;创建
Installer对象,用于和 Native 进程installd交互;创建
ThreadHandler线程,并以其Looper为参数创建PackageHandler对象,用于程序的安装和卸载;根据
Installer对象和 /data/user 文件对象创建UserManager对象,用于多用户管理;调用
readPermissions()方法,从 /system/etc/permissions 目录下的 XML 文件读取权限信息;调用
Settings对象的readLPw()方法解析 /data/system 目录下的文件;扫描 /system/frameworks 目录以及
BOOTCLASSPATH和 platform.xml 定义的系统库目录下的 jar 和 APK 文件是否需要 dex 优化,如果需要则调用Installer.dexopt()方法发消息给installd让它优化;如果任意一个文件执行了 dex 优化操作,删除 /data/dalvik-cache 目录下的缓存文件;创建
AppDirObserver对象监听 /system/frameworks、/system/app、/vendor/app (厂商定制)、/data/app、/data/app-private 5 个目录,并调用scanDirLI()方法扫描其中的 APK 文件;汇总上面扫描 XML 和 APK 得到的信息,并写入文件;
Settings:
Settings类定义了一个HashMap类型的mSharedUsers成员,以字符串(如 “android.uid.system” )为 Key,以SharedUserSetting对象为 Value;SharedUserSetting类从GrantedPermissions类派生,内部包含一个HashSet类型的packages成员,用于保存声明了相同sharedUserId的Package的权限设置信息(PackageSetting);每个
Package有自己的PackageSetting,该类继承自GrantedPermissions的子类PackageSettingBase;Settings还有一个ArrayList类型的mUserIds成员和一个SparseArray类型的mOtherUserIds成员,它们的目的是以 UID 为索引,得到对应的SharedUserSetting对象;
解析权限相关 XML 文件 readPermissions():
/system/etc/permission 目录下的文件是硬件厂商根据设备配置信息拷贝、编译为 system 镜像,最后烧录到设备上的;
先调用
readPermissionsFromXml()读取除 platform.xml 以外的所有文件;最后调用readPermissionsFromXml()读取该文件;platform.xml 主要使用了四个标签:
permission和group用于建立 Linux 层 gid 和 Android 层 Permission 的映射关系;assign-permission用于向指定的 uid 赋予相应的权限;library用于指定系统库;
其他 XML 文件主要包含
feature标签,用于描述屏幕、相机、蓝牙、传感器等硬件特性;readPermissionFromXml()实际上就是从 XML 文件将各种标签及映射关系转换为相应的数据结构;
解析 PMS 启动后生成的 XML 文件 readLPw():
主要有三个文件:
packages.xml:
PackageManagerService启动完成后会生成该文件,当安装/卸载/更新等操作均会修改该文件;packages.list: 描述所有非系统自带 APK 信息,当这些程序有变动时会更新该文件;
packages-stopped.xml: 保存被用户强制停止的应用信息;
与
readPermissionFromXml()方法类似,也是将 XML 数据转换为相应的数据结构;
扫描包路径 APK 文件 scanDirLI():
内部调用
scanPackageLI(),返回PackageParser.Package对象,它是和 APK 文件对应的数据结构;创建
PackageParser对象,调用其parsePackage()方法解析 AndroidManifest.xml 中的各种标签,参数传入了扫描标志和Metrics屏幕信息;调用
collectCertificatesLI()方法收集APK签名信息;将上面扫描得到的
PackageParser.Package信息加入系统,其中单独处理packcage为android的包,即 framework-res.apk,它包含系统资源和ChooserActivity、ShutdownActivity、RingtonePickerActivity等常用页面;检查 Library、settings 和签名信息;
调用
Installer.install()和UserManager.installPackageForAllUsers()安装 APK;如果 APK 包含 Native 库,则解压并复制到相应目录;从 Android 2.3 开始,系统包的 Native 库统一放在 /system/lib 目录,所以它们不用复制;
如果该 APK 已存在,杀掉该进程;
adb install 命令 commandline.c::install_app():
调用
do_sync_push()将 host 中的 APK 拷贝到手机指定目录(内部存储为 /data/local/tmp,外部储存为 /sdcard/tmp);Android 4.0 新增了 APK 验证,其实就是将相关信息发送给 Verification 程序(另一个 APK);
调用
pm_command()将pm install命令和参数发送给 adbd,执行 pm 脚本安装 APK:在编译 system.image 时,Android.mk 会将 pm 脚本复制到 /system/bin 目录;
pm 脚本通过 Native 的
app_process进程 (Zygote创建者) 创建虚拟机并执行 pm.jar 中的main()函数;
删除 tmp 目录下的 APK 文件,因为安装后 APK 会被复制到 /data/app 目录;
pm.java:
获取
PackageManagerService的 Binder 客户端;处理命令(以
install命令为例):创建
PackageInstallObserver用于接收PackageManagerService安装结果;调用
PackageManagerService.installPackageWithVerification()完成安装;同步机制等待安装结果;
PackageManagerService.installPackageWithVerification():
检查客户端进程是否具有安装 Package 的权限,如果是通过 shell 安装,则增加
INSTALL_FROM_ADB标记;调用
bindService()启动 DefaultContainerService.apk 提供的DefaultContainerService;调用
HandlerParams.startCopy();
HandlerParams:
HandlerParams有三个子类:InstallParams(处理 APK 安装)、MoveParams(处理已安装的 APK 位置移动)、MeasureParams(查询已安装 APK 存储和缓存等);根据
adb install参数得到待安装 APK 位置;获取
DeviceStorageMonitorService的 Binder 客户端,查询内部存储空间最小余量(默认是总存储 10%);调用
DefaultContainerService.getMinimalPackageInfo()得到一个PackageInfoLite对象;内部调用PackageParser.parsePackageLite()解析 APK,返回PackageParser.PackageLite对象;调用
DefaultContainerService.recommendApInstallLocation()得到推荐安装位置:设置
prefer值为PREFER_INTERNAL,即倾向于内部存储空间;查询
Settings数据库中的secure表,获取用户设置的安装路径;判断外部存储空间是否是模拟的;
检查内部和外部存储空间是否足够;
如果内部空间满足条件,直接返回;如果外部空间也不满足,返回错误;
调用
installLocationPolicy()检查推荐安装位置(比如系统 Package 不允许安装在 SD 卡);调用
createInstallArgs()创建不同的InstallArgs:内部存储返回FileInstallArgs,外部存储返回SdInstallArgs;对 APK 进行检查(Verification):
创建
Intent对象,调用queryIntentReceivers()查找满足条件的广播接收者,筛选后发送广播;调用
PackageManagerService.verifyPendingInstall()通知校验结果;
调用
InstallArgs.copyApk()进行安装:将 /data/local/tmp 中的 APK 复制到 /data/app 目录,生成 “vmdl-随机数.tmp” 的临时文件,因为
PackageManagerService通过 Linux 的 inotify 机制监控了 /data/app 目录,如果新文件后缀为 APK 会触发扫描;创建
PackageInstalledInfo对象;调用
InstallArgs.doPreInstall();调用
installPackageLI()执行安装,内部对文件重命名(包名-数字.apk),并扫描 APK,将信息注册到系统;调用
InstallArgs.doPostInstall();发送
PACKAGE_ADDED广播,如果是 APK 更新,发送PACKAGE_REPLACE和MY_PACKAGE_REPLACED广播;调用 GC,并调用
InstallArgs.doPostDeleteLI()进行资源清理;通知 pm 安装的结果;
installd.c:
Java 层的
Installer通过 Socket 和 Native 层的installd进程进行交互;installd的main()函数调用android_get_control_socket()创建 socket,处理各种Installer的命令;处理
dexopt命令:委派给dexopt进程(/dalvik/dexopt/OptMain.cpp)实现,生成的 dex 文件一般位于 /data/dalvik-cache 目录;
参考: