一、概念
frameworks/base/services/core/java/com.android.server.pm.PackageManagerService.java
PackageManageService, 简称PMS,用来管理所有包信息(安装、卸载、更新、解析AndroidManifest)。AndroidManefest中注册了 APP 所有的四大组件和权限等信息,PMS提前将 AMS 要用的信息解析保存在内存中提供快速调用。
二、启动PMS过程
Zygote 启动 SystemServer.main() 调用 run() 调用 startBootstrapServices() 启动 PMS,并添加到 ServiceManager 中用于进程间 Binder 通信。
public final class SystemServer {
public static void main(String[] args) {
new SystemServer().run();
}
private void run() {
startBootstrapServices();
}
private void startBootstrapServices() {
mPackageManagerService = PackageManagerService.main(mSystemContext, installer, mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
mFirstBoot = mPackageManagerService.isFirstBoot();
mPackageManager = mSystemContext.getPackageManager();
}
}
public class PackageManagerService extends IPackageManager.Stub implements PackageSender {
public static PackageManagerService main(Context context, Installer installer, boolean factoryTest, boolean onlyCore) {
PackageManagerServiceCompilerMapping.checkProperties();
//创建自己的实例
PackageManagerService m = new PackageManagerService(context, installer, factoryTest, onlyCore);
m.enableSystemUserPackages();
//将PMS注册到ServiceManager(AMS找PMS拿数据时就通过ServiceManager找到PMS)
ServiceManager.addService("package", m);
final PackageManagerNative pmn = m.new PackageManagerNative();
ServiceManager.addService("package_native", pmn);
return m;
}
}
三、获取PMS过程
例如在 Activity 中调用 getPackageManager() 时:
//ContextWrapper.java
public PackageManager getPackageManager() {
return mBase.getPackageManager(); //mBase 是 ContextImpl
}
//ContextImpl.java
public PackageManager getPackageManager() {
if (mPackageManager != null) {
return mPackageManager;
}
IPackageManager pm = ActivityThread.getPackageManager();
if (pm != null) {
// Doesn't matter if we make more than one instance.
return (mPackageManager = new ApplicationPackageManager(this, pm));
}
return null;
}
//ActivityThread.java
public static IPackageManager getPackageManager() {
if (sPackageManager != null) {
return sPackageManager;
}
IBinder b = ServiceManager.getService("package"); //通过 ServiceManager 拿到 PMS
sPackageManager = IPackageManager.Stub.asInterface(b); //Binder 通信
return sPackageManager;
}
四、解析AndroidManifest过程
至少消耗70%的开机时间。
- 扫描系统(/data/app/)和用户(/system/app/)已安装应用目录下的所有 apk 文件并解压。
- 获取 AndroidManifest.xml 文件并进行 dom 解析,将权限、四大组件、Application等信息转换为 Java Bean 保存在内存中供 AMS 查询。
4.1 扫描
scanDirLI() 使用 for 循环遍历已安装软件目录(系统system/app、第三方data/app),如果是 apk 文件就调用 parallelPackageParser.submit() 提交任务给子线程的包解析器处理(Android 10.0起使用子线程加快开机速度,之前版本是直接解析)。
public PackageManagerService(Context context, Installer installer, boolean factoryTest, boolean onlyCore) {
// 扫描 /system/app 目录下的 apk 文件
scanDirTracedLI(systemAppDir, mDefParseFlags | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags | SCAN_AS_SYSTEM, 0);
// 扫描用户目录下的apk文件
scanDirTracedLI(sAppInstallDir, 0, scanFlags | SCAN_REQUIRE_KNOWN, 0);
}
private void scanDirLI(File scanDir, int parseFlags, int scanFlags, long currentTime) {
for (File file : files) {
// 判断是否是 .apk 后缀的文件
final boolean isPackage = (isApkFile(file) || file.isDirectory()) && !PackageInstallerService.isStageName(file.getName());
if (!isPackage) {
continue; // Ignore entries which are not packages
}
// 提交给子线程包解析器处理apk文件
parallelPackageParser.submit(file, parseFlags);
}
}
4.2 解析
根据传过来的 apk 路径判断是文件还是目录,文件走 parseMonolithicPackage() 调用 parseBaseApk() 解析 apk 文件,通过 dom 解析 AndroidManefest 将节点信息存放到对应的 JavaBean 中然后再存放到 Package 对象的集合中,最后放在 PMS 成员变量 ArrayMap<String, PackageParser.Package> mPackage 中(即缓存在内存中,key是包名)方便后续 AMS 查询。(Android 9.0起解析结果会开启缓存,没有缓存就解析每个 app 的 AndroidManefest)。
ParallelPackageParser.java
public void submit(File scanFile, int parseFlags) {
pr.scanFile = scanFile; //传入待解析的apk文件
pr.pkg = parsePackage(pp, scanFile, parseFlags); //交给packageParser解析
}
PackageParser.java
public Package parsePackage(File packageFile, int flags, boolean useCaches) throws PackageParserException {
//如果有缓存直接返回
Package parsed = useCaches ? getCachedResult(packageFile, flags) : null;
if (parsed != null) {
return parsed;
}
//apk文件不是目录,所以会走的parseMonolithicPackage()
if (packageFile.isDirectory()) {
parsed = parseClusterPackage(packageFile, flags);
} else {
parsed = parseMonolithicPackage(packageFile, flags);
}
}
public Package parseMonolithicPackage(File apkFile, int flags) throws PackageParserException {
//解析apk文件
final Package pkg = parseBaseApk(apkFile, assetLoader.getBaseAssetManager(), flags);
}
private Package parseBaseApk(File apkFile, AssetManager assets, int flags) throws PackageParserException {
//解压apk文件
final int cookie = assets.findCookieForPath(apkPath);
//dom解析AndroidManifest.xml
parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
final Package pkg = parseBaseApk(apkPath, res, parser, flags, outError);
}
private Package parseBaseApk(String apkPath, Resources res, XmlResourceParser parser, int flags, String[] outError) throws XmlPullParserException, IOException {
//后续的流程就是将xml解析的权限、四大组件等信息存到同名的JavaBean字段中再存到Package对象集合中
//所有解析出来的Package对象最后会放在PMS成员变量 mPackage 中,是一个ArrayMap,key是包名。
final Package pkg = new Package(pkgName);
return parseBaseApkCommon(pkg, null, res, parser, flags, outError);
}
public final static class Package implements Parcelable {
//包名
public String packageName;
//一个APP中所有的权限
public final ArrayList<Permission> permissions = new ArrayList<Permission>(0);
public final ArrayList<PermissionGroup> permissionGroups = new ArrayList<PermissionGroup>(0);
//一个APP中所有的四大组件
public final ArrayList<Activity> activities = new ArrayList<Activity>(0);
public final ArrayList<Activity> receivers = new ArrayList<Activity>(0);
public final ArrayList<Provider> providers = new ArrayList<Provider>(0);
public final ArrayList<Service> services = new ArrayList<Service>(0);
}