摘要:PackageManagerService是Android系统核心服务之一,在Android中的非常重要,主要负责APK、jar包等的管理。
阅读本文大约需要花费50分钟。
文章的内容主要还是从源码进行分析,虽然又臭又长,但是如果想要学习Android系统源码,这是必要走的路,没有捷径。
相对于碎片学习,我更倾向于静下心来花费1个小时认真的学习一段内容。
文章首发微信公众号:IngresGe
专注于Android系统级源码分析,Android的平台设计,欢迎关注我,谢谢!
欢迎关注我的公众号!
[Android取经之路] 的源码都基于Android-Q(10.0) 进行分析
[Android取经之路] 系列文章:
《系统启动篇》
- Android系统架构
- Android是怎么启动的
- Android 10.0系统启动之init进程
- Android10.0系统启动之Zygote进程
- Android 10.0 系统启动之SystemServer进程
- Android 10.0 系统服务之ActivityMnagerService
- Android10.0系统启动之Launcher(桌面)启动流程
- Android10.0应用进程创建过程以及Zygote的fork流程
- Android 10.0 PackageManagerService(一)工作原理及启动流程
- Android 10.0 PackageManagerService(二)权限扫描
- Android 10.0 PackageManagerService(三)APK扫描
- Android 10.0 PackageManagerService(四)APK安装流程
《日志系统篇》
- Android10.0 日志系统分析(一)-logd、logcat 指令说明、分类和属性
- Android10.0 日志系统分析(二)-logd、logcat架构分析及日志系统初始化
- Android10.0 日志系统分析(三)-logd、logcat读写日志源码分析
- Android10.0 日志系统分析(四)-selinux、kernel日志在logd中的实现
《PackageManagerService系列文章》
- Android 10.0 PackageManagerService(一)工作原理及启动流程
- Android 10.0 PackageManagerService(二)权限扫描
- Android 10.0 PackageManagerService(三)APK扫描
- Android 10.0 PackageManagerService(四)APK安装流程
《Binder通信原理》
- Android10.0 Binder通信原理(一)Binder、HwBinder、VndBinder概要
- Android10.0 Binder通信原理(二)-Binder入门篇
- Android10.0 Binder通信原理(三)-ServiceManager篇
- Android10.0 Binder通信原理(四)-Native-C\C++实例分析
- Android10.0 Binder通信原理(五)-Binder驱动分析
- Android10.0 Binder通信原理(六)-Binder数据如何完成定向打击
- Android10.0 Binder通信原理(七)-Framework binder示例
- Android10.0 Binder通信原理(八)-Framework层分析
- Android10.0 Binder通信原理(九)-AIDL Binder示例
- Android10.0 Binder通信原理(十)-AIDL原理分析-Proxy-Stub设计模式
- Android10.0 Binder通信原理(十一)-Binder总结
《HwBinder通信原理》
- HwBinder入门篇-Android10.0 HwBinder通信原理(一)
- HIDL详解-Android10.0 HwBinder通信原理(二)
- HIDL示例-C++服务创建Client验证-Android10.0 HwBinder通信原理(三)
- HIDL示例-JAVA服务创建-Client验证-Android10.0 HwBinder通信原理(四)
- HwServiceManager篇-Android10.0 HwBinder通信原理(五)
- Native层HIDL服务的注册原理-Android10.0 HwBinder通信原理(六)
- Native层HIDL服务的获取原理-Android10.0 HwBinder通信原理(七)
- JAVA层HIDL服务的注册原理-Android10.0 HwBinder通信原理(八)
- JAVA层HIDL服务的获取原理-Android10.0 HwBinder通信原理(九)
- HwBinder驱动篇-Android10.0 HwBinder通信原理(十)
- HwBinder原理总结-Android10.0 HwBinder通信原理(十一)
《编译原理》
- 编译系统入门篇-Android10.0编译系统(一)
- 编译环境初始化-Android10.0编译系统(二)
- make编译过程-Android10.0编译系统(三)
- Image打包流程-Android10.0编译系统(四)
- Kati详解-Android10.0编译系统(五)
1.概述
PackageManagerService是Android系统核心服务之一,在Android中的非常重要,主要负责的功能如下:
-
解析 AndroidManifest.xml,主要包括AndroidManifest中节点信息的解析和target-name的分析和提炼
-
扫描本地文件,主要针对apk,主要是系统应用、本地安装应用等等。这部分会在下面仔细讲解。
-
管理本地apk,主要包括安装、删除等等。
下面称PackageManagerService为PKMS。
2.核心源码
/frameworks/base/core/java/android/app/ApplicationPackageManager.java
/frameworks/base/services/java/com/android/server/SystemServer.java
/frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
/frameworks/base/services/core/java/com/android/server/pm/PackageDexOptimizer.java
/frameworks/base/services/core/java/com/android/server/pm/Installer.java
/frameworks/base/services/core/java/com/android/server/pm/Settings.java
/frameworks/base/services/core/java/com/android/server/pm/permission/BasePermission.java
/frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
/frameworks/base/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
/frameworks/base/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
/frameworks/base/core/java/android/content/pm/IPackageManager.aidl
/frameworks/base/core/java/android/content/pm/PackageManager.java
/frameworks/base/core/java/com/android/server/SystemConfig.java
3.架构
3.1 PKMS 启动过程
3.2 PKMS 继承关系
3.3 权限管理
3.4 APK扫描
扫描APK的AndroidManifest.xml中的各个标签信息,
例如"application"、"overlay"、"permission"、"uses-permission"等信息。
再针对各个标签的子标签进程扫描,
例如application会扫描"activity"、"receiver"、"service"、"provider"等信息
后面会详细讲解扫描过程
4.启动过程
4.1 启动过程
PKMS服务由SystemServer进行启动,在SystemServer中startBootstrapServices()启动PKMS服务,再调用startOtherServices()进行dex优化,磁盘管理等功能,并让PKMS进入systemready状态。
启动调用栈如下图所示:
4.1.1 [SystemServer.java] startBootstrapServices()
说明:startBootstrapServices()首先启动Installer服务,也就是安装器,随后判断当前的设备是否处于加密状态,如果是则只是解析核心应用,接着调用PackageManagerService的静态方法main来创建pms对象
(1)启动Installer服务
(2)获取设备是否加密(手机设置密码),如果设备加密了,则只解析"core"应用
(3)调用PKMS main方法初始化PackageManagerService,其中调用PackageManagerService()构造函数创建了PKMS对象
(4)如果设备没有加密,操作它。管理A/B OTA dexopting。
源码:
private void startBootstrapServices() {...//(1)启动Installer//阻塞等待installd完成启动,以便有机会创建具有适当权限的关键目录,如/data/user。//我们需要在初始化其他服务之前完成此任务。Installer installer = mSystemServiceManager.startService(Installer.class);mActivityManagerService.setInstaller(installer);...//(2)获取设别是否加密(手机设置密码),如果设备加密了,则只解析"core"应用,mOnlyCore = true,后面会频繁使用该变量进行条件判断String cryptState = VoldProperties.decrypt().orElse("");if (ENCRYPTING_STATE.equals(cryptState)) {Slog.w(TAG, "Detected encryption in progress - only parsing core apps");mOnlyCore = true;} else if (ENCRYPTED_STATE.equals(cryptState)) {Slog.w(TAG, "Device encrypted - only parsing core apps");mOnlyCore = true;}//(3)调用main方法初始化PackageManagerService,参考[4.1.3]mPackageManagerService = PackageManagerService.main(mSystemContext, installer,mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);//PKMS是否是第一次启动mFirstBoot = mPackageManagerService.isFirstBoot();//(4)如果设备没有加密,操作它。管理A/B OTA dexopting。if (!mOnlyCore) {boolean disableOtaDexopt = SystemProperties.getBoolean("config.disable_otadexopt",false);OtaDexoptService.main(mSystemContext, mPackageManagerService);}...
}
4.1.2 [SystemServer.java]
startOtherServices()
说明:
(5)执行 updatePackagesIfNeeded ,完成dex优化;
(6)执行 performFstrimIfNeeded ,完成磁盘维护;
(7)调用systemReady,准备就绪。
源码:
private void startOtherServices() {...if (!mOnlyCore) {...//(5)如果设备没有加密,执行performDexOptUpgrade,完成dex优化;[参考4.3]mPackageManagerService.updatePackagesIfNeeded();}...//(6) 最终执行performFstrim,完成磁盘维护,[参考4.4]mPackageManagerService.performFstrimIfNeeded();...//(7)PKMS准备就绪,[参考4.5]mPackageManagerService.systemReady();...
}
4.1.3 [PackageManagerService.java] main()
说明:
main函数主要工作:
(1)检查Package编译相关系统属性
(2)调用PackageManagerService构造方法
(3)启用部分应用服务于多用户场景
(4)往ServiceManager中注册”package”和”package_native”。
源码:
public static PackageManagerService main(Context context, Installer installer,boolean factoryTest, boolean onlyCore) {// (1)检查Package编译相关系统属性PackageManagerServiceCompilerMapping.checkProperties();//(2)调用PackageManagerService构造方法,参考[4.2]PackageManagerService m = new PackageManagerService(context, installer,factoryTest, onlyCore);//(3)启用部分应用服务于多用户场景m.enableSystemUserPackages();//(4)往ServiceManager中注册”package”和”package_native”。ServiceManager.addService("package", m);final PackageManagerNative pmn = m.new PackageManagerNative();ServiceManager.addService("package_native", pmn);return m;
}
PKMS初始化时的核心部分为PackageManagerService()构造函数的内容,我们下面就来分析该流程
4.2 PKMS构造函数分析
PKMS的构造函数中由两个重要的锁(mInstallLock、mPackages) 和5个阶段构成,下面会详细的来分析这些内容。
mInstallLock :用来保护所有安装apk的访问权限,此操作通常涉及繁重的磁盘数据读写等操作,并且是单线程操作,故有时候会处理很慢。
此锁不会在已经持有mPackages锁的情况下火的,反之,在已经持有mInstallLock锁的情况下,立即获取mPackages是安全的
mPackages:用来解析内存中所有apk的package信息及相关状态。
5个阶段:
阶段1:BOOT_PROGRESS_PMS_START
阶段2:BOOT_PROGRESS_PMS_SYSTEM_SCAN_START
阶段3:BOOT_PROGRESS_PMS_DATA_SCAN_START
阶段4:BOOT_PROGRESS_PMS_SCAN_END
阶段5:BOOT_PROGRESS_PMS_READY
PKMS服务也是通过binder进行通信,IPackageManager.aidl由工具转换后自动生成binder的服务端IPackageManager.Stub和客户端IPackageManager.Stub.Proxy,具体关系如图:
Binder服务端:PackageManagerService继承于IPackageManager.Stub;
Binder客户端:ApplicationPackageManager(简称APM)的成员变量mPM继承于IPackageManager.Stub.Proxy; 本身APM是继承于PackageManager对象。
4.2.1 [PackageManagerService.java]
说明:IPackageManager.Stub是IPackageManager.aidl自动生成的,正好也说明了PKMS是service端的,通过binder交互
源码:
public class PackageManagerService extends IPackageManager.Stubimplements PackageSender {
}
4.2.2 [PackageManagerService.java] PackageManagerService()
说明:PackageManagerService构造函数
源码:
public PackageManagerService(Context context, Installer installer,boolean factoryTest, boolean onlyCore) {...//阶段1:BOOT_PROGRESS_PMS_START, 参考[4.2.3]EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START,SystemClock.uptimeMillis());//阶段2:BOOT_PROGRESS_PMS_SYSTEM_SCAN_START ,参考[4.2.4]EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,startTime);...//阶段3:BOOT_PROGRESS_PMS_DATA_SCAN_START ,参考[4.2.5]if (!mOnlyCore) {EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,SystemClock.uptimeMillis());}...//阶段4:BOOT_PROGRESS_PMS_SCAN_END ,参考[4.2.6]EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END,SystemClock.uptimeMillis());...//阶段5:BOOT_PROGRESS_PMS_READY,参考[4.2.7]EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY,SystemClock.uptimeMillis());
}
4.2.3 阶段1:BOOT_PROGRESS_PMS_START
主要工作:
(1)构造 DisplayMetrics ,保存分辨率等相关信息;
(2)创建Installer对象,与installd交互;
(3)创建mPermissionManager对象,进行权限管理;
(4)构造Settings类,保存安装包信息,清除路径不存在的孤立应用,主要涉及/data/system/目录的packages.xml,packages-backup.xml,packages.list,packages-stopped.xml,packages-stopped-backup.xml等文件。
(5)构造PackageDexOptimizer及DexManager类,处理dex优化;
(6)创建SystemConfig实例,获取系统配置信息,配置共享lib库;
(7)创建PackageManager的handler线程,循环处理外部安装相关消息。
源码:
public PackageManagerService(...) {LockGuard.installLock(mPackages, LockGuard.INDEX_PACKAGES);EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START,SystemClock.uptimeMillis());mContext = context;mFactoryTest = factoryTest; // 一般为false,即非工厂生产模式mOnlyCore = onlyCore; //标记是否只加载核心服务mMetrics = new DisplayMetrics(); // 分辨率配置mInstaller = installer; //保存installer对象//创建提供服务/数据的子组件。这里的顺序很重要,使用到了两个重要的同步锁:mInstallLock、mPackagessynchronized (mInstallLock) {synchronized (mPackages) {// 公开系统组件使用的私有服务// 本地服务LocalServices.addService(PackageManagerInternal.class, new PackageManagerInternalImpl());// 多用户管理服务sUserManager = new UserManagerService(context, this,new UserDataPreparer(mInstaller, mInstallLock, mContext, mOnlyCore), mPackages);mComponentResolver = new ComponentResolver(sUserManager,LocalServices.getService(PackageManagerInternal.class),mPackages);// 权限管理服务mPermissionManager = PermissionManagerService.create(context,mPackages /*externalLock*/);mDefaultPermissionPolicy = mPermissionManager.getDefaultPermissionGrantPolicy();//创建Settings对象mSettings = new Settings(Environment.getDataDirectory(),mPermissionManager.getPermissionSettings(), mPackages);}}// 添加system, phone, log, nfc, bluetooth, shell,se,networkstack 这8种shareUserId到mSettings;mSettings.addSharedUserLPw("android.uid.system", Process.SYSTEM_UID,ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);mSettings.addSharedUserLPw("android.uid.phone", RADIO_UID,ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);mSettings.addSharedUserLPw("android.uid.log", LOG_UID,ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);mSettings.addSharedUserLPw("android.uid.nfc", NFC_UID,ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);mSettings.addSharedUserLPw("android.uid.bluetooth", BLUETOOTH_UID,ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);mSettings.addSharedUserLPw("android.uid.shell", SHELL_UID,ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);mSettings.addSharedUserLPw("android.uid.se", SE_UID,ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);mSettings.addSharedUserLPw("android.uid.networkstack", NETWORKSTACK_UID,ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);...// DexOpt优化mPackageDexOptimizer = new PackageDexOptimizer(installer, mInstallLock, context,"*dexopt*");mDexManager = new DexManager(mContext, this, mPackageDexOptimizer, installer, mInstallLock);// ART虚拟机管理服务mArtManagerService = new ArtManagerService(mContext, this, installer, mInstallLock);mMoveCallbacks = new MoveCallbacks(FgThread.get().getLooper());mViewCompiler = new ViewCompiler(mInstallLock, mInstaller);// 权限变化监听器mOnPermissionChangeListeners = new OnPermissionChangeListeners(FgThread.get().getLooper());mProtectedPackages = new ProtectedPackages(mContext);mApexManager = new ApexManager(context);// 获取默认分辨率getDefaultDisplayMetrics(context, mMetrics);//拿到SystemConfig()的对象,其中会调用SystemConfig的readPermissions()完成权限的读取,参考[5 权限管理]SystemConfig systemConfig = SystemConfig.getInstance();synchronized (mInstallLock) {// writersynchronized (mPackages) {// 启动"PackageManager"线程,负责apk的安装、卸载mHandlerThread = new ServiceThread(TAG,Process.THREAD_PRIORITY_BACKGROUND, true /*allowIo*/);mHandlerThread.start();// 应用handlermHandler = new PackageHandler(mHandlerThread.getLooper());// 进程记录handlermProcessLoggingHandler = new ProcessLoggingHandler();// Watchdog监听ServiceThread是否超时:10分钟Watchdog.getInstance().addThread(mHandler, WATCHDOG_TIMEOUT);// Instant应用注册mInstantAppRegistry = new InstantAppRegistry(this);// 共享lib库配置ArrayMap<String, SystemConfig.SharedLibraryEntry> libConfig= systemConfig.getSharedLibraries();final int builtInLibCount = libConfig.size();for (int i = 0; i < builtInLibCount; i++) {String name = libConfig.keyAt(i);SystemConfig.SharedLibraryEntry entry = libConfig.valueAt(i);addBuiltInSharedLibraryLocked(entry.filename, name);}...// 读取安装相关SELinux策略SELinuxMMAC.readInstallPolicy();// 返回栈加载FallbackCategoryProvider.loadFallbacks();//读取并解析/data/system下的XML文件mFirstBoot = !mSettings.readLPw(sUserManager.getUsers(false));// 清理代码路径不存在的孤立软件包final int packageSettingCount = mSettings.mPackages.size();for (int i = packageSettingCount - 1; i >= 0; i--) {PackageSetting ps = mSettings.mPackages.valueAt(i);if (!isExternal(ps) && (ps.codePath == null || !ps.codePath.exists())&& mSettings.getDisabledSystemPkgLPr(ps.name) != null) {mSettings.mPackages.removeAt(i);mSettings.enableSystemPackageLPw(ps.name);}}// 如果不是首次启动,也不是CORE应用,则拷贝预编译的DEX文件if (!mOnlyCore && mFirstBoot) {requestCopyPreoptedFiles();}...} // synchronized (mPackages)}
}
readLPw()会扫描下面5个文件
1) "/data/system/packages.xml"
2) "/data/system/packages-backup.xml"
3) "/data/system/packages.list"
4) "/data/system/packages-stopped.xml"
5) "/data/system/packages-stopped-backup.xml"
个文件共分为三组,简单的作用描述如下:
-
packages.xml:PKMS 扫描完目标文件夹后会创建该文件。当系统进行程序安装、卸载和更新等操作时,均会更新该文件。该文件保存了系统中与 package 相关的一些信息。
-
packages.list:描述系统中存在的所有非系统自带的 APK 的信息。当这些程序有变动时,PKMS 就会更新该文件。
-
packages-stopped.xml:从系统自带的设置程序中进入应用程序页面,然后在选择强制停止(ForceStop)某个应用时,系统会将该应用的相关信息记录到此文件中。也就是该文件保存系统中被用户强制停止的 Package 的信息。
这些目录的指向,都在Settings中的构造函数完成, 如下所示,得到目录后调用readLPw()进行扫描
Settings(File dataDir, PermissionSettings permission,Object lock) {mLock = lock;mPermissions = permission;mRuntimePermissionsPersistence = new RuntimePermissionPersistence(mLock);mSystemDir = new File(dataDir, "system"); //mSystemDir指向目录"/data/system"mSystemDir.mkdirs(); //创建 "/data/system"//设置权限FileUtils.setPermissions(mSystemDir.toString(),FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IROTH|FileUtils.S_IXOTH,-1, -1);//(1)指向目录"/data/system/packages.xml"mSettingsFilename = new File(mSystemDir, "packages.xml");//(2)指向目录"/data/system/packages-backup.xml"mBackupSettingsFilename = new File(mSystemDir, "packages-backup.xml");//(3)指向目录"/data/system/packages.list"mPackageListFilename = new File(mSystemDir, "packages.list");FileUtils.setPermissions(mPackageListFilename, 0640, SYSTEM_UID, PACKAGE_INFO_GID);//(4)指向目录"/data/system/packages-stopped.xml"mStoppedPackagesFilename = new File(mSystemDir, "packages-stopped.xml");//(5)指向目录"/data/system/packages-stopped-backup.xml"mBackupStoppedPackagesFilename = new File(mSystemDir, "packages-stopped-backup.xml");
}
解析上面这个几个xml的内容,建立对应的数据结构
[Settings.java]
boolean readLPw(@NonNull List<UserInfo> users) {FileInputStream str = null;...if (str == null) {str = new FileInputStream(mSettingsFilename);}//解析"/data/system/packages.xml"XmlPullParser parser = Xml.newPullParser();parser.setInput(str, StandardCharsets.UTF_8.name());int type;while ((type = parser.next()) != XmlPullParser.START_TAG&& type != XmlPullParser.END_DOCUMENT) {;}int outerDepth = parser.getDepth();while ((type = parser.next()) != XmlPullParser.END_DOCUMENT&& (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {continue;}//根据XML的各个节点进行各种操作,例如读取权限、shared-user等String tagName = parser.getName();if (tagName.equals("package")) {readPackageLPw(parser);} else if (tagName.equals("permissions")) {mPermissions.readPermissions(parser);} else if (tagName.equals("permission-trees")) {mPermissions.readPermissionTrees(parser);} else if (tagName.equals("shared-user")) {readSharedUserLPw(parser);}...}str.close();...return true;
}
说明:创建 SharedUserSetting 对象并添加到 Settings 的成员变量 mSharedUsers 中,在 Android 系统中,多个 package 通过设置 sharedUserId 属性可以运行在同一个进程,共享同一个 UID
源码:
mSettings.addSharedUserLPw("android.uid.system", //字符串Process.SYSTEM_UID, //系统进程使用的用户id,值为1000ApplicationInfo.FLAG_SYSTEM, //标志系统 PackageApplicationInfo.PRIVATE_FLAG_PRIVILEGED); //特权系统应用SharedUserSetting addSharedUserLPw(String name, int uid, int pkgFlags, int pkgPrivateFlags) {//mSharedUsers 是一个 HashMap,key 为字符串,值为 SharedUserSetting 对象SharedUserSetting s = mSharedUsers.get(name);if (s != null) {if (s.userId == uid) {return s;}PackageManagerService.reportSettingsProblem(Log.ERROR,"Adding duplicate shared user, keeping first: " + name);return null;}//创建一个新的 SharedUserSetting 对象,并设置的 userId 为 uids = new SharedUserSetting(name, pkgFlags, pkgPrivateFlags);s.userId = uid;if (registerExistingAppIdLPw(uid, s, name)) {mSharedUsers.put(name, s);//将name与s键值对添加到mSharedUsers中保存return s;}return null;
}
4.2.4 阶段2:BOOT_PROGRESS_PMS_SYSTEM_SCAN_START
主要工作:
(1)从init.rc中获取环境变量BOOTCLASSPATH和SYSTEMSERVERCLASSPATH;
(2)对于旧版本升级的情况,将安装时获取权限变更为运行时申请权限;
(3)扫描system/vendor/product/odm/oem等目录的priv-app、app、overlay包;
(4)清除安装时临时文件以及其他不必要的信息。
源码:
public PackageManagerService(Context context, Installer installer,boolean factoryTest, boolean onlyCore) {synchronized (mInstallLock) {synchronized (mPackages) {// 记录扫描开始时间long startTime = SystemClock.uptimeMillis();EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,startTime);//获取环境变量,init.rcfinal String bootClassPath = System.getenv("BOOTCLASSPATH");final String systemServerClassPath = System.getenv("SYSTEMSERVERCLASSPATH");...// 获取system/framework目录File frameworkDir = new File(Environment.getRootDirectory(), "framework");// 获取内部版本final VersionInfo ver = mSettings.getInternalVersion();// 判断fingerprint是否有更新mIsUpgrade = !Build.FINGERPRINT.equals(ver.fingerprint);...// 对于Android M之前版本升级上来的情况,需将系统应用程序权限从安装升级到运行时mPromoteSystemApps =mIsUpgrade && ver.sdkVersion <= Build.VERSION_CODES.LOLLIPOP_MR1;// 对于Android N之前版本升级上来的情况,需像首次启动一样处理packagemIsPreNUpgrade = mIsUpgrade && ver.sdkVersion < Build.VERSION_CODES.N;mIsPreNMR1Upgrade = mIsUpgrade && ver.sdkVersion < Build.VERSION_CODES.N_MR1;mIsPreQUpgrade = mIsUpgrade && ver.sdkVersion < Build.VERSION_CODES.Q;// 在扫描之前保存预先存在的系统package的名称,不希望自动为新系统应用授予运行时权限if (mPromoteSystemApps) {Iterator<PackageSetting> pkgSettingIter = mSettings.mPackages.values().iterator();while (pkgSettingIter.hasNext()) {PackageSetting ps = pkgSettingIter.next();if (isSystemApp(ps)) {mExistingSystemPackages.add(ps.name);}}}// 准备解析package的缓存mCacheDir = preparePackageParserCache();// 设置flag,而不在扫描安装时更改文件路径int scanFlags = SCAN_BOOTING | SCAN_INITIAL;...//扫描以下路径:/vendor/overlay、/product/overlay、/product_services/overlay、/odm/overlay、/oem/overlay、/system/framework/system/priv-app、/system/app、/vendor/priv-app、/vendor/app、/odm/priv-app、/odm/app、/oem/app、/oem/priv-app、/product/priv-app、/product/app、/product_services/priv-app、/product_services/app、/product_services/priv-app//参考[6 PMS jar包、apk的安装]scanDirTracedLI(new File(VENDOR_OVERLAY_DIR),...);scanDirTracedLI(new File(PRODUCT_OVERLAY_DIR),...);scanDirTracedLI(new File(PRODUCT_SERVICES_OVERLAY_DIR),...);scanDirTracedLI(new File(ODM_OVERLAY_DIR),...);scanDirTracedLI(new File(OEM_OVERLAY_DIR),...);...final List<String> possiblyDeletedUpdatedSystemApps = new ArrayList<>();final List<String> stubSystemApps = new ArrayList<>();// 删掉不存在的packageif (!mOnlyCore) {final Iterator<PackageParser.Package> pkgIterator = mPackages.values().iterator();while (pkgIterator.hasNext()) {final PackageParser.Package pkg = pkgIterator.next();if (pkg.isStub) {stubSystemApps.add(pkg.packageName);}}final Iterator<PackageSetting> psit = mSettings.mPackages.values().iterator();while (psit.hasNext()) {PackageSetting ps = psit.next();// 如果不是系统应用,则不被允许disableif ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0) {continue;}// 如果应用被扫描,则不允许被擦除final PackageParser.Package scannedPkg = mPackages.get(ps.name);if (scannedPkg != null) {// 如果系统应用被扫描且存在disable应用列表中,则只能通过OTA升级添加if (mSettings.isDisabledSystemPackageLPr(ps.name)) {...removePackageLI(scannedPkg, true);mExpectingBetter.put(ps.name, ps.codePath);}continue;}...}}// 删除临时文件deleteTempPackageFiles();// 删除没有关联应用的共享UID标识mSettings.pruneSharedUsersLPw();...}...}...
}
4.2.5 阶段3:BOOT_PROGRESS_PMS_DATA_SCAN_START
主要工作有:对于不仅仅解析核心应用的情况下,还处理data目录的应用信息,及时更新,祛除不必要的数据。
源码:
public PackageManagerService(Context context, Installer installer,boolean factoryTest, boolean onlyCore) {synchronized (mInstallLock) {synchronized (mPackages) {...if (!mOnlyCore) {EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,SystemClock.uptimeMillis());scanDirTracedLI(sAppInstallDir, 0, scanFlags | SCAN_REQUIRE_KNOWN, 0);...// 移除通过OTA删除的更新系统应用程序的禁用package设置// 如果更新不再存在,则完全删除该应用。否则,撤消其系统权限for (int i = possiblyDeletedUpdatedSystemApps.size() - 1; i >= 0; --i) {final String packageName = possiblyDeletedUpdatedSystemApps.get(i);final PackageParser.Package pkg = mPackages.get(packageName);final String msg;mSettings.removeDisabledSystemPackageLPw(packageName);...}// 确保期望在userdata分区上显示的所有系统应用程序实际显示// 如果从未出现过,需要回滚以恢复系统版本for (int i = 0; i < mExpectingBetter.size(); i++) {final String packageName = mExpectingBetter.keyAt(i);if (!mPackages.containsKey(packageName)) {final File scanFile = mExpectingBetter.valueAt(i);...mSettings.enableSystemPackageLPw(packageName);try {//扫描APKscanPackageTracedLI(scanFile, reparseFlags, rescanFlags, 0, null);} catch (PackageManagerException e) {Slog.e(TAG, "Failed to parse original system package: "+ e.getMessage());}}}// 解压缩并安装任何存根系统应用程序。必须最后执行此操作以确保替换或禁用所有存根installSystemStubPackages(stubSystemApps, scanFlags);...// 获取storage manager包名mStorageManagerPackage = getStorageManagerPackageName();// 解决受保护的action过滤器。只允许setup wizard(开机向导)为这些action设置高优先级过滤器mSetupWizardPackage = getSetupWizardPackageName();...// 更新客户端以确保持有正确的共享库路径updateAllSharedLibrariesLocked(null, Collections.unmodifiableMap(mPackages));...// 读取并更新要保留的package的上次使用时间mPackageUsage.read(mPackages);mCompilerStats.read();}}}
}
4.2.6 阶段4:BOOT_PROGRESS_PMS_SCAN_END
主要工作:
(1)sdk版本变更,更新权限;
(2)OTA升级后首次启动,清除不必要的缓存数据;
(3)权限等默认项更新完后,清理相关数据;
(4)更新package.xml
源码:
public PackageManagerService(Context context, Installer installer,boolean factoryTest, boolean onlyCore) {synchronized (mInstallLock) {synchronized (mPackages) {...EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END,SystemClock.uptimeMillis());// 如果自上次启动以来,平台SDK已改变,则需要重新授予应用程序权限以捕获出现的任何新权限final boolean sdkUpdated = (ver.sdkVersion != mSdkVersion);mPermissionManager.updateAllPermissions(StorageManager.UUID_PRIVATE_INTERNAL, sdkUpdated, mPackages.values(),mPermissionCallback);...// 如果这是第一次启动或来自Android M之前的版本的升级,并且它是正常启动,那需要在所有已定义的用户中初始化默认的首选应用程序if (!onlyCore && (mPromoteSystemApps || mFirstBoot)) {for (UserInfo user : sUserManager.getUsers(true)) {mSettings.applyDefaultPreferredAppsLPw(user.id);primeDomainVerificationsLPw(user.id);}}// 在启动期间确实为系统用户准备存储,因为像SettingsProvider和SystemUI这样的核心系统应用程序无法等待用户启动final int storageFlags;if (StorageManager.isFileEncryptedNativeOrEmulated()) {storageFlags = StorageManager.FLAG_STORAGE_DE;} else {storageFlags = StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE;}...// 如果是在OTA之后首次启动,并且正常启动,那需要清除代码缓存目录,但不清除应用程序配置文件if (mIsUpgrade && !onlyCore) {Slog.i(TAG, "Build fingerprint changed; clearing code caches");for (int i = 0; i < mSettings.mPackages.size(); i++) {final PackageSetting ps = mSettings.mPackages.valueAt(i);if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, ps.volumeUuid)) {// No apps are running this early, so no need to freezeclearAppDataLIF(ps.pkg, UserHandle.USER_ALL,FLAG_STORAGE_DE | FLAG_STORAGE_CE | FLAG_STORAGE_EXTERNAL| Installer.FLAG_CLEAR_CODE_CACHE_ONLY);}}ver.fingerprint = Build.FINGERPRINT;}//安装Android-Q前的非系统应用程序在Launcher中隐藏他们的图标if (!onlyCore && mIsPreQUpgrade) {Slog.i(TAG, "Whitelisting all existing apps to hide their icons");int size = mSettings.mPackages.size();for (int i = 0; i < size; i++) {final PackageSetting ps = mSettings.mPackages.valueAt(i);if ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0) {continue;}ps.disableComponentLPw(PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME,UserHandle.USER_SYSTEM);}}// 仅在权限或其它默认配置更新后清除mExistingSystemPackages.clear();mPromoteSystemApps = false;...// 所有变更均在扫描过程中完成ver.databaseVersion = Settings.CURRENT_DATABASE_VERSION;//降级去读取mSettings.writeLPr();}}
}
4.2.7 阶段5:BOOT_PROGRESS_PMS_READY
主要工作有:
(1)创建PackageInstallerService对象
(2)GC回收内存
源码:
public PackageManagerService(Context context, Installer installer,boolean factoryTest, boolean onlyCore) {synchronized (mInstallLock) {synchronized (mPackages) {...EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY,SystemClock.uptimeMillis());...//PermissionController 主持 缺陷许可证的授予和角色管理,所以这是核心系统的一个关键部分。mRequiredPermissionControllerPackage = getRequiredPermissionControllerLPr();...updateInstantAppInstallerLocked(null);// 阅读并更新dex文件的用法// 在PM init结束时执行此操作,以便所有程序包都已协调其数据目录// 此时知道了包的代码路径,因此可以验证磁盘文件并构建内部缓存// 使用文件预计很小,因此与其他活动(例如包扫描)相比,加载和验证它应该花费相当小的时间final Map<Integer, List<PackageInfo>> userPackages = new HashMap<>();for (int userId : userIds) {userPackages.put(userId, getInstalledPackages(/*flags*/ 0, userId).getList());}mDexManager.load(userPackages);if (mIsUpgrade) {MetricsLogger.histogram(null, "ota_package_manager_init_time",(int) (SystemClock.uptimeMillis() - startTime));}}}...// 打开应用之后,及时回收处理Runtime.getRuntime().gc();// 上面的初始扫描在持有mPackage锁的同时对installd进行了多次调用mInstaller.setWarnIfHeld(mPackages);...
}
4.3 dex 优化
检查是否需要去更新Packages并进行dex优化,如果没有OTA升级、没有大版本升级、没有清楚过dalvik虚拟机的缓存,可以去更新packages,
最终调用的是Installer的dexopt()进行优化
调用栈如下:
4.3.1 [PackageManagerService.java] updatePackagesIfNeeded()
说明:
检查是否需要去更新Packages并进行dex优化,如果没有OTA升级、没有大版本升级、没有清楚过dalvik虚拟机的缓存,可以去更新packages
更新packages的优先级:core app >system app > other app,调用 performDexOptUpgrade()进行更新
源码:
public void updatePackagesIfNeeded() {//只有system或是root用户才有权限请求 package updateenforceSystemOrRoot("Only the system can request package update");//(1)判断有没有进行OTA升级,我们需要在OTA后重新提取。boolean causeUpgrade = isDeviceUpgrading();//(2)是否是第一次启动或是系统大版本升级boolean causeFirstBoot = isFirstBoot() || mIsPreNUpgrade;// We need to re-extract after a pruned cache, as AoT-ed files will be out of date.//(3)判断是否有清除过dalvik虚拟机的缓存boolean causePrunedCache = VMRuntime.didPruneDalvikCache();//(4)如果上面的三个都没有,那么就不进行任何操作if (!causeUpgrade && !causeFirstBoot && !causePrunedCache) {return;}List<PackageParser.Package> pkgs;synchronized (mPackages) {//(5)按照package的优先级进行排序,core app >system app > other apppkgs = PackageManagerServiceUtils.getPackagesForDexopt(mPackages.values(), this);}final long startTime = System.nanoTime(); //记录开始时间//进行dex优化,参考[4.3.2]final int[] stats = performDexOptUpgrade(pkgs, mIsPreNUpgrade /* showDialog */,causeFirstBoot ? REASON_FIRST_BOOT : REASON_BOOT,false /* bootComplete */);...
}
4.3.2 [PackageManagerService.java] performDexOptUpgrade()
说明:判断是否需要对package进行更新,如果需要更新那么按照优先级完成dex优化,最终调用Install的dexopt()进行dex优化,参考上面的调用栈
源码:
private int[] performDexOptUpgrade(List<PackageParser.Package> pkgs, boolean showDialog,final int compilationReason, boolean bootComplete) {...//循环取出packages,进行优化for (PackageParser.Package pkg : pkgs) {numberOfPackagesVisited++;boolean useProfileForDexopt = false;//第一次启动或是ota升级之后并且是系统应用才会进行odexif ((isFirstBoot() || isDeviceUpgrading()) && isSystemApp(pkg)) {...}...//最终是调用 mInstaller.dexopt 完成优化的,installd守护进程,installer安装器和Installd通信int primaryDexOptStaus = performDexOptTraced(new DexoptOptions(pkg.packageName,pkgCompilationReason,dexoptFlags));switch (primaryDexOptStaus) {case PackageDexOptimizer.DEX_OPT_PERFORMED:numberOfPackagesOptimized++; //odex优化完成的应用break;case PackageDexOptimizer.DEX_OPT_SKIPPED:numberOfPackagesSkipped++; //跳过的应用break;case PackageDexOptimizer.DEX_OPT_FAILED:numberOfPackagesFailed++; //失败的应用break;default:Log.e(TAG, "Unexpected dexopt return code " + primaryDexOptStaus);break;}}return new int[] { numberOfPackagesOptimized, numberOfPackagesSkipped,numberOfPackagesFailed };
}
4.4 磁盘维护
磁盘维护最终调用的是vold进程的 fstrim()进行清理操作
调用栈:
[PackageManagerService.java] performFstrimIfNeeded()
说明:主要是执行磁盘清理工作,释放磁盘空间
源码:
public void performFstrimIfNeeded() {//只有system或是root用户才有权限请求fstrimenforceSystemOrRoot("Only the system can request fstrim");//在其他事情之前,看看我们是否需要fstrimtry {//获取StorageManager对象IStorageManager sm = PackageHelper.getStorageManager();if (sm != null) {boolean doTrim = false;//获取执行FTRIM间隔,默认是3天,可以通过setting provider更改这个时间long interval = android.provider.Settings.Global.getLong(mContext.getContentResolver(),android.provider.Settings.Global.FSTRIM_MANDATORY_INTERVAL,DEFAULT_MANDATORY_FSTRIM_INTERVAL);if (interval > 0) {final long timeSinceLast = System.currentTimeMillis() - sm.lastMaintenance();if (timeSinceLast > interval) {doTrim = true; //如果超过了三天就进行磁盘清理Slog.w(TAG, "No disk maintenance in " + timeSinceLast+ "; running immediately");}}if (doTrim) {final boolean dexOptDialogShown;synchronized (mPackages) {dexOptDialogShown = mDexOptDialogShown;}//如果不是第一次启动,显示一个提示框if (!isFirstBoot() && dexOptDialogShown) {try {ActivityManager.getService().showBootMessage(mContext.getResources().getString(R.string.android_upgrading_fstrim), true);} catch (RemoteException e) {}}// 这里的sm是 StorageManagerService,发送消息H_FSTRIM给handler,然后再向vold发送fstrim命sm.runMaintenance();}} else {Slog.e(TAG, "storageManager service unavailable!");}} catch (RemoteException e) {// Can't happen; StorageManagerService is local}
}
4.5 PKMS 准备就绪
[PackageManagerService.java] systemReady()
说明:systemReady主要完成的是默认授权和更新package的信息,通知在等待pms的一些组件
源码:
public void systemReady() {//只有system或是root用户才有权限 声称system已经readyenforceSystemOrRoot("Only the system can claim the system is ready");ContentObserver co = new ContentObserver(mHandler) {...};co.onChange(true); //注册一个监听...synchronized (mPackages) {ArrayList<PreferredActivity> removed = new ArrayList<>();for (int i=0; i<mSettings.mPreferredActivities.size(); i++) {PreferredIntentResolver pir = mSettings.mPreferredActivities.valueAt(i);removed.clear();for (PreferredActivity pa : pir.filterSet()) {if (!mComponentResolver.isActivityDefined(pa.mPref.mComponent)) {removed.add(pa);}}//移除不存在的先前用户设置保存的优先选择的activity组件if (removed.size() > 0) {for (int r=0; r<removed.size(); r++) {PreferredActivity pa = removed.get(r);Slog.w(TAG, "Removing dangling preferred activity: "+ pa.mPref.mComponent);pir.removeFilter(pa);}mSettings.writePackageRestrictionsLPr(mSettings.mPreferredActivities.keyAt(i)); //写入到文件中}}for (int userId : UserManagerService.getInstance().getUserIds()) {if (!mSettings.areDefaultRuntimePermissionsGrantedLPr(userId)) {grantPermissionsUserIds = ArrayUtils.appendInt(grantPermissionsUserIds, userId);}}}sUserManager.systemReady(); //多用户服务 systemReady//升级所有已获取的默认权限for (int userId : grantPermissionsUserIds) {mDefaultPermissionPolicy.grantDefaultPermissions(userId); //默认授权操作,参考[]}...// Now that we've scanned all packages, and granted any default// permissions, ensure permissions are updated. Beware of dragons if you// try optimizing this.synchronized (mPackages) {mPermissionManager.updateAllPermissions(StorageManager.UUID_PRIVATE_INTERNAL, false, mPackages.values(),mPermissionCallback); //更新权限信息...});}//注意随时间变化的外部存储设备final StorageManager storage = mContext.getSystemService(StorageManager.class);storage.registerListener(mStorageListener);mInstallerService.systemReady();mApexManager.systemReady();mPackageDexOptimizer.systemReady();...//清除过期的userid和appsUserManager.reconcileUsers(StorageManager.UUID_PRIVATE_INTERNAL);reconcileApps(StorageManager.UUID_PRIVATE_INTERNAL);mPermissionManager.systemReady();if (mInstantAppResolverConnection != null) {mContext.registerReceiver(new BroadcastReceiver() {@Overridepublic void onReceive(Context context, Intent intent) {mInstantAppResolverConnection.optimisticBind();mContext.unregisterReceiver(this);}}, new IntentFilter(Intent.ACTION_BOOT_COMPLETED));}if (!isFirstBoot()) {Slog.i(TAG, "enablePackageStoppedPolicy");}mModuleInfoProvider.systemReady();// Installer service might attempt to install some packages that have been staged for// installation on reboot. Make sure this is the last component to be call since the// installation might require other components to be ready.mInstallerService.restoreAndApplyStagedSessionIfNeeded();//update partner appnew Thread(() -> {updatePartnerAppInFota();}).start();
}
下一节将会讲解PKMS 的权限扫描、APK扫描、安装等内容,欢迎关注我
微信公众号:IngresGe