本文源码都是android29,10.0 代码
一 概述
PackageManagerService 也是一个比较核心的系统服务,他管理着apk安装,卸载,以及信息查询和权限管理等等。管理着跟 package 相关的,主要功能有:
- 解析AndroidNanifest.xml清单文件
- 扫描.apk文件,安装系统应用,安装本地应用等
- 管理本地应用,主要有, 安装,卸载,应用信息查询(比如权限) 等
二 启动
在系统启动,也就是开机的时候。在SystemServer启动,也就是SystemServer的main方法中调用startBootstrapServices中,启动了PackageManagerService的main方法,
private void startBootstrapServices() {
//省略代码
mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
}
private void startOtherServices() {
//省略代码
//dex 优化
mPackageManagerService.updatePackagesIfNeeded();
//磁盘维护
mPackageManagerService.performFstrimIfNeeded();
// 当准备好之后,需要处理的东西,比如处理所有等待系统准备就绪的消息
mPackageManagerService.systemReady();
}
三 启动总结
- 通过Zygote分裂出来的SystemServer进程,初始化的时候创建了PMS
- 扫描pacages.xml,就想window的注册表似的,里面有包名,权限等等信息,随着apk的卸载和安装,都会更新里面的东西
- 扫描所有的apk,system/app (系统),data/app(用户),用户装的程序越多,扫描时间越长,开机一般耗费这里了(还有就是在SystemServer中启动各种各样的服务)。PackageParser解析APK文件中的AndroidManifest.xml 保存下来,手机桌面就是从这里拿到数据
安装apk
- 当我们点击一个apk的时候其实打开了packages/app/PackageInstaller.PackageInstallerActivity
- 然后当我们点击确定的时候,打开 InstallAppProgress 这个Activity,也就是转菊花的页面, , 注册了PackageInstallObserver监听安装完成的回调,之后调用到PackageInstallerService,
- 拷贝apk到data/app下面,之后才开始正式安装
- 解析apk信息,将apk的权限、应用包名,创建data/data/包名下的路径,so库的lib,file,cache,数据库等文件夹,更新Settings信息,里面有packages.xml,类似于注册表的东西
- 当app安装完成 给laucher发送一个广播Intent.ACTION_PACKAGE_ADDED,完成
PackageManagerService的main
main()方法的作用:
- 检查系统属性
- 初始化 PackageManagerService
- 初始化部分应用服务,主要用于多用户场景
- 将 package 服务注册到 ServiceManager
- 将 package_native 服务注册到 ServiceManager, 主要是给native代码调用的
public static PackageManagerService main(Context context, Installer installer,
boolean factoryTest, boolean onlyCore) {
// 检查系统属性
PackageManagerServiceCompilerMapping.checkProperties();
//初始化 PackageManagerService
PackageManagerService m = new PackageManagerService(context, installer,
factoryTest, onlyCore);
//启用部分应用服务于多用户场景
m.enableSystemUserPackages();
//将 package 服务注册到 ServiceManager
ServiceManager.addService("package", m);
final PackageManagerNative pmn = m.new PackageManagerNative();
//将 package_native 服务注册到 ServiceManager, 主要是给native代码调用的
ServiceManager.addService("package_native", pmn);
return m;
}
PackageManagerService构造函数
中间我会省略不必要的代码
public PackageManagerService(Context context, Installer installer,
boolean factoryTest, boolean onlyCore) {
//屏幕的宽高,分辨率等信息
mMetrics = new DisplayMetrics();
//installer对象,在SystemServer里面初始化的,apk的安装和卸载最终都是调用installd来实现的
mInstaller = installer;
synchronized (mInstallLock) {
synchronized (mPackages) {
// Expose private service for system components to use.
LocalServices.addService(
PackageManagerInternal.class, new PackageManagerInternalImpl());
//UserManager是Andorid 4.0新增的一个功能,也就是一个手机可以有多个用户,有多个配置,
//至今好像也没发现他的应用落地
sUserManager = new UserManagerService(context, this,
new UserDataPreparer(mInstaller, mInstallLock, mContext, mOnlyCore), mPackages);
// 解析 activities, services, providers and receivers
mComponentResolver = new ComponentResolver(sUserManager,
LocalServices.getService(PackageManagerInternal.class),
mPackages);
//权限管理
mPermissionManager = PermissionManagerService.create(context,
mPackages /*externalLock*/);
mDefaultPermissionPolicy = mPermissionManager.getDefaultPermissionGrantPolicy();
//创建Settings 对象,里面有很多重要的文件管理 比如packages.xml 和 packages.list
mSettings = new Settings(Environment.getDataDirectory(),
mPermissionManager.getPermissionSettings(), mPackages);
// dex 的优化
mPackageDexOptimizer = new PackageDexOptimizer(installer, mInstallLock, context,
"*dexopt*");
// dex 管理
mDexManager = new DexManager(mContext, this, mPackageDexOptimizer, installer, mInstallLock);
//ART虚拟机管理
mArtManagerService = new ArtManagerService(mContext, this, installer, mInstallLock);
// Permission 监听器
mOnPermissionChangeListeners = new OnPermissionChangeListeners(
FgThread.get().getLooper());
// 得到默认的DisplayMetrics
getDefaultDisplayMetrics(context, mMetrics);
//
SystemConfig systemConfig = SystemConfig.getInstance();
synchronized (mPackages) {
// PMS中的线程,轮训,app的安装与卸载
mHandlerThread = new ServiceThread(TAG,
Process.THREAD_PRIORITY_BACKGROUND, true /*allowIo*/);
mHandlerThread.start();
mHandler = new PackageHandler(mHandlerThread.getLooper());
mProcessLoggingHandler = new ProcessLoggingHandler();
Watchdog.getInstance().addThread(mHandler, WATCHDOG_TIMEOUT);
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);
}
long undefinedVersion = SharedLibraryInfo.VERSION_UNDEFINED;
for (int i = 0; i < builtInLibCount; i++) {
String name = libConfig.keyAt(i);
SystemConfig.SharedLibraryEntry entry = libConfig.valueAt(i);
final int dependencyCount = entry.dependencies.length;
for (int j = 0; j < dependencyCount; j++) {
final SharedLibraryInfo dependency =
getSharedLibraryInfoLPr(entry.dependencies[j], undefinedVersion);
if (dependency != null) {
getSharedLibraryInfoLPr(name, undefinedVersion).addDependency(dependency);
}
}
}
SELinuxMMAC.readInstallPolicy();
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "loadFallbacks");
FallbackCategoryProvider.loadFallbacks();
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "read user settings");
//读取并解析文件/data/system下的XML文件
// packages.xml 和 packages-backup.xml 包信息,以及权限当系统进行程序安装、
// 卸载和更新等操作时,均会更新该文件。该文件保存了系统中与 package 相关的一些信息
// 相当于注册表似的
// packages.list
// packages-stopped.xml 和 packages-stopped-backup.xml
mFirstBoot = !mSettings.readLPw(sUserManager.getUsers(false));
//.....
//准备解析 Package
mCacheDir = preparePackageParserCache();
// Set flag to monitor and not change apk file paths when
// scanning install directories.
int scanFlags = SCAN_BOOTING | SCAN_INITIAL;
if (mIsUpgrade || mFirstBoot) {
scanFlags = scanFlags | SCAN_FIRST_BOOT_OR_UPGRADE;
}
// 下面都是扫描对应目录下的包 ,解析成PackageParser实例类
//扫描/vendor/overlay下的apk
scanDirTracedLI(new File(VENDOR_OVERLAY_DIR),
mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM_DIR,
scanFlags
| SCAN_AS_SYSTEM
| SCAN_AS_VENDOR,
0);
scanDirTracedLI(new File(PRODUCT_OVERLAY_DIR),
mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM_DIR,
scanFlags
| SCAN_AS_SYSTEM
| SCAN_AS_PRODUCT,
0);
scanDirTracedLI(new File(PRODUCT_SERVICES_OVERLAY_DIR),
mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM_DIR,
scanFlags
| SCAN_AS_SYSTEM
| SCAN_AS_PRODUCT_SERVICES,
0);
scanDirTracedLI(new File(ODM_OVERLAY_DIR),
mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM_DIR,
scanFlags
| SCAN_AS_SYSTEM
| SCAN_AS_ODM,
0);
scanDirTracedLI(new File(OEM_OVERLAY_DIR),
mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM_DIR,
scanFlags
| SCAN_AS_SYSTEM
| SCAN_AS_OEM,
0);
mParallelPackageParserCallback.findStaticOverlayPackages();
// Find base frameworks (resource packages without code).
scanDirTracedLI(frameworkDir,
mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM_DIR,
scanFlags
| SCAN_NO_DEX
| SCAN_AS_SYSTEM
| SCAN_AS_PRIVILEGED,
0);
if (!mPackages.containsKey("android")) {
throw new IllegalStateException(
"Failed to load frameworks package; check log for warnings");
}
// Collect privileged system packages.
final File privilegedAppDir = new File(Environment.getRootDirectory(), "priv-app");
scanDirTracedLI(privilegedAppDir,
mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM_DIR,
scanFlags
| SCAN_AS_SYSTEM
| SCAN_AS_PRIVILEGED,
0);
// Collect ordinary system packages.
final File systemAppDir = new File(Environment.getRootDirectory(), "app");
scanDirTracedLI(systemAppDir,
mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM_DIR,
scanFlags
| SCAN_AS_SYSTEM,
0);
// Collect privileged vendor packages.
File privilegedVendorAppDir = new File(Environment.getVendorDirectory(), "priv-app");
try {
privilegedVendorAppDir = privilegedVendorAppDir.getCanonicalFile();
} catch (IOException e) {
// failed to look up canonical path, continue with original one
}
scanDirTracedLI(privilegedVendorAppDir,
mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM_DIR,
scanFlags
| SCAN_AS_SYSTEM
| SCAN_AS_VENDOR
| SCAN_AS_PRIVILEGED,
0);
// Collect ordinary vendor packages.
File vendorAppDir = new File(Environment.getVendorDirectory(), "app");
try {
vendorAppDir = vendorAppDir.getCanonicalFile();
} catch (IOException e) {
// failed to look up canonical path, continue with original one
}
scanDirTracedLI(vendorAppDir,
mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM_DIR,
scanFlags
| SCAN_AS_SYSTEM
| SCAN_AS_VENDOR,
0);
// Collect privileged odm packages. /odm is another vendor partition
// other than /vendor.
File privilegedOdmAppDir = new File(Environment.getOdmDirectory(),
"priv-app");
try {
privilegedOdmAppDir = privilegedOdmAppDir.getCanonicalFile();
} catch (IOException e) {
// failed to look up canonical path, continue with original one
}
scanDirTracedLI(privilegedOdmAppDir,
mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM_DIR,
scanFlags
| SCAN_AS_SYSTEM
| SCAN_AS_VENDOR
| SCAN_AS_PRIVILEGED,
0);
// Collect ordinary odm packages. /odm is another vendor partition
// other than /vendor.
File odmAppDir = new File(Environment.getOdmDirectory(), "app");
try {
odmAppDir = odmAppDir.getCanonicalFile();
} catch (IOException e) {
// failed to look up canonical path, continue with original one
}
scanDirTracedLI(odmAppDir,
mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM_DIR,
scanFlags
| SCAN_AS_SYSTEM
| SCAN_AS_VENDOR,
0);
// Collect all OEM packages.
final File oemAppDir = new File(Environment.getOemDirectory(), "app");
scanDirTracedLI(oemAppDir,
mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM_DIR,
scanFlags
| SCAN_AS_SYSTEM
| SCAN_AS_OEM,
0);
// Collected privileged /product packages.
File privilegedProductAppDir = new File(Environment.getProductDirectory(), "priv-app");
try {
privilegedProductAppDir = privilegedProductAppDir.getCanonicalFile();
} catch (IOException e) {
// failed to look up canonical path, continue with original one
}
scanDirTracedLI(privilegedProductAppDir,
mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM_DIR,
scanFlags
| SCAN_AS_SYSTEM
| SCAN_AS_PRODUCT
| SCAN_AS_PRIVILEGED,
0);
// Collect ordinary /product packages.
File productAppDir = new File(Environment.getProductDirectory(), "app");
try {
productAppDir = productAppDir.getCanonicalFile();
} catch (IOException e) {
// failed to look up canonical path, continue with original one
}
scanDirTracedLI(productAppDir,
mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM_DIR,
scanFlags
| SCAN_AS_SYSTEM
| SCAN_AS_PRODUCT,
0);
// 后面整不动了
}
参考
深入理解android卷2
Android 10.0 PackageManagerService(一)工作原理及启动流程-[Android取经之路]