
Android PMS main函数
在前文对PMS main函数整体逻辑讲解的基础上,本节结合Android 11(API 30) 完整源码(关键片段),逐行拆解main函数及关联核心逻辑,明确每一行代码的作用、依赖关系和设计意图。
PMS main函数完整源码(Android 11)
先贴出main函数的完整源码(含注释),再逐步解析:
java
/**
* PackageManagerService的启动入口,由SystemServer调用
* @param context SystemServer的SystemContext,系统级上下文
* @param installer 与installd守护进程通信的代理对象
* @param factoryTest 是否为工厂测试模式(0=非工厂模式,1=工厂测试,2=工厂测试且无加密)
* @param onlyCore 是否仅加载核心系统包(用于系统启动早期极简模式)
* @return 初始化完成的PMS实例
*/
public static PackageManagerService main(Context context, Installer installer,
boolean factoryTest, boolean onlyCore) {
// 1. 确保运行在SystemServer进程(安全校验)
PackageManagerServiceCompilerMapping.recordServiceStart();
// 2. 创建PMS实例(核心逻辑,构造函数是重点)
PackageManagerService m = new PackageManagerService(context, installer,
factoryTest ? FactoryTest.FACTORY_TEST_ON : FactoryTest.FACTORY_TEST_OFF,
onlyCore);
// 3. 将PMS注册到ServiceManager,对外暴露Binder服务
ServiceManager.addService(Context.PACKAGE_SERVICE, m);
// 4. 启用系统用户(User 0)的应用包访问权限
m.enableSystemUserPackages();
// 5. 初始化包验证相关的系统特性(Android 11新增)
m.getPackageVerificationManager().initialize();
return m;
}
main函数逐行源码解析
1. 进程安全校验:PackageManagerServiceCompilerMapping.recordServiceStart()
java
PackageManagerServiceCompilerMapping.recordServiceStart();
作用:
- 这是Android系统的"编译映射"埋点,用于跟踪PMS服务启动的编译/执行状态,属于系统性能监控和调试辅助逻辑;
- 底层通过
CompilerMapping记录服务启动的时间戳、进程信息,便于排查启动耗时、编译优化相关问题; - 无业务逻辑影响,仅为系统级监控设计。
2. PMS实例化:核心构造函数调用
java
PackageManagerService m = new PackageManagerService(context, installer,
factoryTest ? FactoryTest.FACTORY_TEST_ON : FactoryTest.FACTORY_TEST_OFF,
onlyCore);
这是main函数的核心,构造函数是PMS初始化的"主战场"。以下是构造函数的关键源码片段(简化后)及解析:
java
/**
* PMS构造函数,完成核心初始化
*/
public PackageManagerService(Context context, Installer installer, int factoryTest, boolean onlyCore) {
// ===== 步骤1:基础环境初始化 =====
mContext = context;
mFactoryTest = factoryTest;
mOnlyCore = onlyCore;
mInstaller = installer; // 注入installd代理,后续apk安装/解压依赖此对象
// 初始化系统目录(核心路径,PMS扫描apk的基础)
mSystemDir = new File(Environment.getRootDirectory(), "app");
mVendorDir = new File("/vendor/app");
mOemDir = new File("/oem/app");
mDataDir = Environment.getDataDirectory();
mAppDataDir = new File(mDataDir, "app");
// 校验目录权限,确保PMS可读写(无权限则抛出异常,SystemServer启动失败)
enforceDirectoryPermissions();
// ===== 步骤2:核心模块初始化 =====
// 权限管理模块(处理应用权限声明、授予、校验)
mPermissionManager = new PermissionManager(this, mContext);
// 包安装器(处理apk安装/卸载流程)
mPackageInstaller = new PackageInstallerService(this);
// dex优化模块(提升应用启动速度,处理dex2oat)
mDexManager = new PackageDexOptimizer(this, mInstaller);
// 内存数据库初始化(存储包信息、组件信息,核心数据结构)
mPackages = new ArrayMap<String, PackageParser.Package>(); // 包名->Package对象
mActivities = new ArrayMap<String, ArrayMap<ComponentName, ActivityInfo>>(); // 组件->Activity信息
mServices = new ArrayMap<String, ArrayMap<ComponentName, ServiceInfo>>(); // 组件->Service信息
// ===== 步骤3:包扫描(PMS最核心的逻辑) =====
// 分阶段扫描:先扫描核心系统包,再扫描普通包
long startTime = SystemClock.uptimeMillis();
// 扫描/framework目录(核心框架包,如android.jar对应的应用)
scanDirTracedLI(new File(Environment.getRootDirectory(), "framework"),
PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_FRAMEWORK,
scanFlags, 0);
// 扫描/system/app(系统应用)
scanDirTracedLI(mSystemDir, PackageParser.PARSE_IS_SYSTEM, scanFlags, 0);
// 扫描/vendor/app(厂商应用)
scanDirTracedLI(mVendorDir, PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_VENDOR,
scanFlags, 0);
// 仅非"仅核心包"模式下,扫描/data/app(第三方应用)
if (!mOnlyCore) {
scanDirTracedLI(mAppDataDir, 0, scanFlags, 0);
}
Log.i(TAG, "Scanned " + mPackages.size() + " packages in "
+ (SystemClock.uptimeMillis() - startTime) + "ms");
// ===== 步骤4:权限初始化与授予 =====
// 加载系统预置权限(从framework的AndroidManifest.xml)
mPermissionManager.loadAllPermissions();
// 为已扫描的应用授予声明的权限(系统应用优先授予)
grantDefaultPermissions();
// ===== 步骤5:其他初始化 =====
// 初始化包名管理(处理包名冲突、别名)
mPackageNameManager = new PackageNameManagerService(this);
// 初始化多用户模块
mUserManager = UserManagerService.getInstance();
}
构造函数核心要点解析:
- 目录初始化 :
mSystemDir/mDataDir等路径是PMS扫描apk的基础,enforceDirectoryPermissions()会校验目录的rwx权限(如/data/app需属于system用户,权限755),无权限则直接崩溃; - 内存数据库 :
mPackages是PMS最核心的数据结构,存储所有已扫描应用的完整信息(包名、版本、签名、组件等),后续getPackageInfo()等接口均从这里读取数据; - 分阶段扫描 :先扫描核心框架包(确保系统基础功能),再扫描系统应用,最后扫描第三方应用,且
onlyCore模式下跳过第三方应用,减少启动耗时; - 权限授予 :
grantDefaultPermissions()会根据应用的签名、位置(如/system/app)授予系统权限,普通应用需用户手动授权的权限在此仅记录声明,不授予。
3. 服务注册:ServiceManager.addService()
java
ServiceManager.addService(Context.PACKAGE_SERVICE, m);
源码关联 :Context.PACKAGE_SERVICE的定义是"package",与前文提到的服务名称一致。
java
// Context.java中定义
public static final String PACKAGE_SERVICE = "package";
// ServiceManager.java的addService方法
public static void addService(String name, IBinder service) {
try {
getIServiceManager().addService(name, service, false, IServiceManager.DUMP_FLAG_PRIORITY_DEFAULT);
} catch (RemoteException e) {
Log.e(TAG, "error adding service " + name, e);
}
}
作用解析:
-
getIServiceManager()获取ServiceManager的Binder代理对象(IServiceManager); -
addService将PMS的Binder对象(PMS继承自IPackageManager.Stub,实现Binder通信)注册到ServiceManager的服务注册表; -
第三个参数
false表示"非单例"(实际PMS是单例),第四个参数是dump优先级; -
注册完成后,其他进程可通过
Context.getSystemService(Context.PACKAGE_SERVICE)获取PMS代理,底层逻辑是:java// ContextImpl.java @Override public Object getSystemService(String name) { return SystemServiceRegistry.getSystemService(this, name); } // SystemServiceRegistry.java static { registerService(Context.PACKAGE_SERVICE, PackageManager.class, new CachedServiceFetcher<PackageManager>() { @Override public PackageManager createService(ContextImpl ctx) { // 获取PMS的Binder代理 IPackageManager pm = IPackageManager.Stub.asInterface( ServiceManager.getService(Context.PACKAGE_SERVICE)); return new ApplicationPackageManager(ctx, pm); } }); }
4. 系统用户包启用:enableSystemUserPackages()
java
m.enableSystemUserPackages();
源码实现(简化):
java
void enableSystemUserPackages() {
// 获取系统用户(User 0)的UserHandle
UserHandle systemUser = UserHandle.SYSTEM;
// 为系统用户启用所有已扫描的包
synchronized (mLock) {
for (PackageParser.Package pkg : mPackages.values()) {
// 设置包对系统用户可见
setPackageVisibleToUser(pkg.packageName, true, systemUser.getIdentifier());
}
}
// 触发系统用户的包信息更新
mUserManager.onPackagesAvailableForUser(systemUser.getIdentifier());
}
作用:
- Android多用户体系中,应用包默认仅对创建者可见,系统用户(User 0)是基础用户,需确保所有系统包/第三方包对其可见;
setPackageVisibleToUser修改包的可见性标记,mUserManager.onPackagesAvailableForUser通知用户管理服务更新包状态。
5. 包验证模块初始化:getPackageVerificationManager().initialize()
java
m.getPackageVerificationManager().initialize();
源码实现(简化):
java
PackageVerificationManager getPackageVerificationManager() {
if (mPackageVerificationManager == null) {
mPackageVerificationManager = new PackageVerificationManager(this);
}
return mPackageVerificationManager;
}
// PackageVerificationManager.java
void initialize() {
// 加载包验证规则(如是否校验第三方apk的签名)
mVerificationRules = loadVerificationRules();
// 注册包安装验证的监听器(监听apk安装过程中的验证事件)
registerVerificationListeners();
}
作用:
- Android 11新增的包验证模块,用于校验apk安装的合法性(如是否为恶意应用、是否符合企业策略);
initialize()加载系统预置的验证规则,初始化监听器,确保后续apk安装时触发验证流程。
main函数关联的关键源码设计
1. Binder通信核心:IPackageManager.aidl
PMS能对外提供跨进程服务,核心是实现了IPackageManager.aidl定义的接口,而main函数注册的Binder对象正是该接口的实现:
aidl
// IPackageManager.aidl
package android.content.pm;
interface IPackageManager {
// 获取包信息
PackageInfo getPackageInfo(String packageName, int flags, int userId);
// 安装包
void installPackage(String packagePath, IPackageInstallObserver observer, int flags);
// 卸载包
void uninstallPackage(String packageName, IPackageDeleteObserver observer, int flags);
// 其他核心接口...
}
PMS的继承关系:
java
public class PackageManagerService extends IPackageManager.Stub {
// 实现IPackageManager.aidl中定义的所有接口
@Override
public PackageInfo getPackageInfo(String packageName, int flags, int userId) {
// 从mPackages中读取包信息,返回给调用方
synchronized (mLock) {
PackageParser.Package pkg = mPackages.get(packageName);
if (pkg == null) {
throw new PackageManager.NameNotFoundException(packageName);
}
return generatePackageInfo(pkg, flags, userId);
}
}
}
2. installd通信:Installer类
main函数传入的Installer对象是PMS与底层installd守护进程通信的桥梁,installd负责apk的解压、文件权限修改、dex优化等底层操作:
java
// Installer.java核心方法
public class Installer {
// 创建应用数据目录
public int createDataDir(String pkgname, int uid, int gid) {
return execute("create_data_dir", pkgname, String.valueOf(uid), String.valueOf(gid));
}
// 解压apk文件
public int extract(String src, String dst) {
return execute("extract", src, dst);
}
// 底层通过socket与installd通信,execute方法发送指令
private int execute(String... args) {
// 建立socket连接,发送指令,接收返回值
}
}
PMS在安装apk时,会调用mInstaller.createDataDir()创建应用数据目录,再调用extract()解压apk,所有底层文件操作均通过Installer完成,这也是main函数注入Installer的核心原因------解耦PMS与底层文件操作。
源码层面的关键优化点
从源码中可看出Android对PMS启动性能的优化设计:
1. 分阶段扫描+异步扫描
java
// 构造函数中,核心包扫描同步执行,第三方包异步执行(Android 11优化)
if (!mOnlyCore) {
// 异步扫描/data/app,避免阻塞SystemServer主线程
mHandler.post(() -> scanDirTracedLI(mAppDataDir, 0, scanFlags, 0));
}
2. 包信息缓存
PMS会将mPackages中的包信息序列化到/data/system/packages.xml和/data/system/packages.list,下次启动时直接加载缓存,无需重新扫描:
java
// 构造函数中加载缓存
private void loadPackageInfoCache() {
File packagesXml = new File(mDataDir, "system/packages.xml");
if (packagesXml.exists()) {
// 解析packages.xml,恢复mPackages数据
parsePackagesXml(packagesXml);
}
}
3. 懒加载
部分非核心模块(如mPackageVerificationManager)采用懒加载模式,仅在首次调用时初始化,减少启动时的内存占用和耗时。
总结
PMS的main函数虽代码量少,但串联了实例化、服务注册、模块初始化三大核心环节,其背后的源码设计体现了Android系统服务的核心思想:
- 分层设计 :PMS上层处理业务逻辑(包管理、权限),底层通过
Installer依赖installd处理文件操作,通过Binder依赖ServiceManager处理跨进程通信; - 性能优先:分阶段扫描、异步执行、缓存复用等设计,均为减少SystemServer启动耗时;
- 安全校验:目录权限校验、签名校验、进程校验,确保PMS运行的安全性;
- 可扩展性 :通过依赖注入(
Context、Installer)和模块化设计(权限管理、包安装器、dex优化),便于后续功能扩展。
