Android 进阶——系统启动之SystemServer创建并启动PackageManagerService服务
Posted CrazyMo_
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 进阶——系统启动之SystemServer创建并启动PackageManagerService服务相关的知识,希望对你有一定的参考价值。
文章大纲
- 引言
- 一、PackageManagerService概述
- 二、PackageManagerService 体系结构概述
- 三、SystemServer进程启动PKMS服务
- 三、PKMS 遍历安装系统目录下的App
引言
SystemServer首先启动,创建一个ServerThread线程来启动所有android核心服务,在创建和启动Installer
、ActivityManagerService
、PowerManagerService
、RecoverySystemService、LightsService、DisplayManagerService
系统服务启动之后,PackageManagerService
就会接着被创建和启动。
基于Android 28,为了阅读,本文约定方法表示Java的,而函数表示Native层概念,仅供参考
一、PackageManagerService概述
PackageManagerService(PKMS)
作为管理APK包的系统服务,负责APK包的安装、卸载、优化和查询,
Android 系统在启动过程中会通过PKMS(PackageManagerService)服务自动去扫描系统中指定的目录寻找APK文件、JAR包和SO库,并逐一解析封装为对应的对象再保存到内存中,系统运行时就迅速找到对应的信息并自动安装。
PKMS在扫描时遇到需要优化的文件还会额外执行转换工作,将APK的dex格式优化为oat格式(Linux 的ELF格式的一种私有形式)。
在PKMS 在准备安装APK时主要做了两大工作:
- 解析APK的清单文件(AndroidManifest.xml)获取其对应的包信息供后面封装为对应的JavaBean 对象(即APK的内存描述对象)
- 为App 分配Linux的用户Id 和Linux 用户组Id ,要不然可能在系统里运行时因为安全机制无法得到对应的权限。所以Android 中么一个App 都有一个对应的Linux 用户ID,在PMS 安装该App 时检测发现它没有和其他应用共享同一个用户ID时,就会自动给其分配一个用户ID,除了用户ID之外,当PMS安装时还发现该App 申请了一个特殊的资源访问权限,还会给其分配对应的Linux 用户组ID
当所有App都安装完毕之后,Android Framework 还会启动Home Launcher 应用程序在Launcher 启动。
二、PackageManagerService 体系结构概述
\\frameworks\\base\\core\\java\\android\\content\\pm\\IPackageManager.aidl
\\out\\target\\common\\obj\\JAVA_LIBRARIES\\framework_intermediates\\src\\core\\java\\android\\content\\pm\\IPackageManager.java
作为Android 系统的核心服务,PackageManagerService自然也是采用Binder 服务的架构,当某个进程需要访问某个系统服务时首先得通过ServiceManager 获取其对应的Binder对象,从而调用对应的方法,至于中间的通信细节全部由Binder 通信去完成,PackageManagerService 只是负责包管理的相关工作,解析完成之后再传到Installer服务里。
在应用进程里通过调用Context#getPackageManager() 得到ApplicationPackageManager 对象后,通过Binder 机制与PackageManagerService 服务通信,再由PackageManagerService 调用Installer服务,最终Installer服务通过socket 与installd 守护进程通信。
三、SystemServer进程启动PKMS服务
在前面文章中介绍System进程(SystemServer.java)启动过程中,在AMS、PowerManagerService、DisplayManagerService核心服务启动后,会通过调用PackageManagerService#main方法将PMS 启动
- 启动Installer服务
- 启动AMS、PowerManagerService、DisplayManagerService系统服务
- 调用PackageManagerService#main方法将PKMS 启动
- 启动MountService
- dex 优化
- 调用PackageManagerService#systemReady 回调方法
当然启动PMS 只是System进程启动后干的很小一部分工作,还有其他很多系统服务也会被启动,而且很多启动流程都大同小异。
1、com.android.server.SystemServer#startBootstrapServices 触发PKMS 服务启动
private void startBootstrapServices()
//启动Installer服务
Installer installer = mSystemServiceManager.startService(Installer.class);
...
// Activity manager runs the show.
mActivityManagerService = mSystemServiceManager.startService(
ActivityManagerService.Lifecycle.class).getService();
mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
mActivityManagerService.setInstaller(installer);
//创建 PKMS 对象
mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
//PKMS是否首次启动
mFirstBoot = mPackageManagerService.isFirstBoot();
mPackageManager = mSystemContext.getPackageManager();
//...
2、com.android.server.pm.PackageManagerService#main触发PMKS对象创建并注册到ServiceManager
public static PackageManagerService main(Context context, Installer installer,
boolean factoryTest, boolean onlyCore)
// Self-check for initial settings.
PackageManagerServiceCompilerMapping.checkProperties();
PackageManagerService m = new PackageManagerService(context, installer,
factoryTest, onlyCore);
m.enableSystemUserPackages();
ServiceManager.addService("package", m);
final PackageManagerNative pmn = m.new PackageManagerNative();
ServiceManager.addService("package_native", pmn);
return m;
3、PackageManagerService构造对象时完成Apk和Jar包的格式转化和扫描解析已安装的系统应用并提取信息
PackageManagerService 在自己构造方法里主要完成两件事:
- 把系统中指定目录的Apk文件和Jar包从dex格式转为oat格式
- 扫描系统已安装的应用,并提取对应的信息
public PackageManagerService(Context context, Installer installer,
boolean factoryTest, boolean onlyCore)
//true 表示PMKS此次只处理系统应用, SystemProperties.get("vold.decrypt")得到值为trigger_restart_min_framework或者1时SystemServer传过来的参数为true
mOnlyCore = onlyCore;
//创建屏幕显示对象
mMetrics = new DisplayMetrics();
//mInstallLock 用来保护所有安装apk的访问权限,此操作通常涉及繁重的磁盘数据读写等操作,并且是单线程操作,故有时候会处理很慢
synchronized (mInstallLock)
//mpackages 用来解析内存中所有apk的package信息及相关状态
synchronized (mPackages)
...
//多用户管理机制,这是google想模拟windows多用户管理系统,为未来的设计
sUserManager = new UserManagerService(context, this,
new UserDataPreparer(mInstaller, mInstallLock, mContext, mOnlyCore), mPackages);
mPermissionManager = PermissionManagerService.create(context,
new DefaultPermissionGrantedCallback()
@Override
public void onDefaultRuntimePermissionsGranted(int userId)
synchronized(mPackages)
mSettings.onDefaultRuntimePermissionsGrantedLPr(userId);
, mPackages /*externalLock*/);
mDefaultPermissionPolicy = mPermissionManager.getDefaultPermissionGrantPolicy();
///创建Settings对象
mSettings = new Settings(mPermissionManager.getPermissionSettings(), mPackages);
//创建 SharedUserSetting 对象并把system, phone, log, nfc, bluetooth, shell,se,networkstack 这8种shareUserId到mSettings,把这些系统应用的uid 保存起来,添加共享用户组的信息
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);
...
//dex优化工具类
mPackageDexOptimizer = new PackageDexOptimizer(installer, mInstallLock, context,
"*dexopt*");
//Dex 管理类
mDexManager = new DexManager(mContext, this, mPackageDexOptimizer, installer, mInstallLock,
dexManagerListener);
// ART虚拟机管理服务
mArtManagerService = new ArtManagerService(mContext, this, installer, mInstallLock);
mMoveCallbacks = new MoveCallbacks(FgThread.get().getLooper());
getDefaultDisplayMetrics(context, mMetrics);//用系统属性设置DisplayMetrics
//获取SystemConfig()的对象,在其构造方法中会调用readPermissions()完成权限的读取
SystemConfig systemConfig = SystemConfig.getInstance();
...
synchronized (mInstallLock)
// writer
synchronized (mPackages)
//创建消息处理线程处理APK的安装和卸载请求
mHandlerThread = new ServiceThread(TAG,
Process.THREAD_PRIORITY_BACKGROUND, true /*allowIo*/);
mHandlerThread.start();
//用于处理安装、卸载应用请求的Handler
mHandler = new PackageHandler(mHandlerThread.getLooper());
mProcessLoggingHandler = new ProcessLoggingHandler();//创建进程运行信息记录Handler
Watchdog.getInstance().addThread(mHandler, WATCHDOG_TIMEOUT);//绑定到SystemServer 的Watchdog服务
...
//com.android.server.pm.Settings mSettings 读取并解析/data/system下的XML文件
mFirstBoot = !mSettingsreadLPw(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);
if (mFirstBoot)
//拷贝预编译的DEX文件
requestCopyPreoptedFiles();
...
///获取环境变量 在init.rc里配置的
final String bootClassPath = System.getenv("BOOTCLASSPATH");
final String systemServerClassPath = System.getenv("SYSTEMSERVERCLASSPATH");
File frameworkDir = new File(Environment.getRootDirectory(), "framework"); ...
mCacheDir = preparePackageParserCache(mIsUpgrade);
// 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;
// Collect vendor/product overlay packages. (Do this before scanning any apps.)
// For security and version matching reason, only consider
// overlay packages if they reside in the right directory.
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);
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);
// 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);
// 裁剪不在存在的系统应用的包package
final List<String> possiblyDeletedUpdatedSystemApps = new ArrayList<>();
final List<String> stubSystemApps = new ArrayList<>();
if (!mOnlyCore)
final Iterator<PackageSetting> psit = mSettings.mPackages.values().iterator();
while (psit.hasNext())
PackageSetting ps = psit.next();
/**
*如果得到的ps代表的package信息不是系统应用的则不能禁用
*/
if ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0)
continue;
final PackageParser.Package scannedPkg = mPackages.get(ps.name);
if (scannedPkg != null)
if (mSettings.isDisabledSystemPackageLPr(ps.name))
removePackageLI(scannedPkg, true);
mExpectingBetter.put(ps.name, ps.codePath);
continue;
...
//删除临时文件
deleteTempPackageFiles();
final int cachedSystemApps = PackageParser.sCachedPackageReadCount.get();
//裁剪多余没有关联应用的uid
mSettings.pruneSharedUsersLPw();
if (!mOnlyCore)
scanDirTracedLI(sAppInstallDir, 0, scanFlags | SCAN_REQUIRE_KNOWN, 0);
scanDirTracedLI(sDrmAppPrivateInstallDir, mDefParseFlags
| PackageParser.PARSE_FORWARD_LOCK,
以上是关于Android 进阶——系统启动之SystemServer创建并启动PackageManagerService服务的主要内容,如果未能解决你的问题,请参考以下文章
Android 进阶——系统启动之SystemServer创建并启动Installer服务
Android 进阶——系统启动之SystemServer创建并启动Installer服务
Android 进阶——系统启动之Framework 核心ActivitityManagerService服务启动
Android 进阶——系统启动之Framework 核心ActivitityManagerService服务启动