相关文章链接:

1. Android Framework - 学习启动篇
2. Android 系统服务 - PMS 的启动过程

相关源码文件:

frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
frameworks/base/services/core/java/com/android/server/pm/PackageInstallerService.java
frameworks/base/services/core/java/com/android/server/pm/Settings.java
frameworks/base/services/core/java/com/android/server/SystemConfig
frameworks/base/core/java/android/content/pm/PackageManager.javaframeworks/base/core/android/java/content/pm/IPackageManager.aidl
frameworks/base/core/java/android/content/pm/PackageParser.java
frameworks/base/cmds/pm/src/com/android/commands/pm/Pm.javaframeworks/base/services/core/java/com/android/server/pm/Installer.java
frameworks/base/core/java/com/android/internal/os/InstallerConnection.java

PackageManagerService 也是 Android 应用开发者需要重点熟悉的一个服务,也是由 SystemService 进程创建的,管理着所有跟 package 相关的工作,常见的比如安装、卸载应用。我们先找到其启动创建的源代码:

private void startBootstrapServices() {// 启动 installer 服务Installer installer = mSystemServiceManager.startService(Installer.class);...// 处于加密状态则仅仅解析核心应用String cryptState = SystemProperties.get("vold.decrypt");if (ENCRYPTING_STATE.equals(cryptState)) {mOnlyCore = true; // ENCRYPTING_STATE = "trigger_restart_min_framework"} else if (ENCRYPTED_STATE.equals(cryptState)) {mOnlyCore = true; // ENCRYPTED_STATE = "1"}// 创建 PKMS 对象 mPackageManagerService = PackageManagerService.main(mSystemContext, installer,mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);mPackageManager = mSystemContext.getPackageManager();
}

SystemService 进程启动过程中跟 PKMS 相关的有 installer 服务和 PackageManager 对象,我们主要分析他的创建过程也就是 PackageManagerService.main() 方法

    public static PackageManagerService main(Context context, Installer installer,boolean factoryTest, boolean onlyCore) {// 创建 PackageManagerService 对象PackageManagerService m = new PackageManagerService(context, installer,factoryTest, onlyCore);// 将 PKMS 添加到 ServiceManager 进程去管理ServiceManager.addService("package", m);return m;}
    public PackageManagerService(Context context, Installer installer,boolean factoryTest, boolean onlyCore) {// 保存一些基本变量mContext = context;mFactoryTest = factoryTest;mOnlyCore = onlyCore;// 创建 Settings 对象mSettings = new Settings(mPackages);// 添加 system, phone, log, nfc, bluetooth, shell 这六种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);mInstaller = installer;// 用来优化 dexmPackageDexOptimizer = new PackageDexOptimizer(this);synchronized (mInstallLock) {synchronized (mPackages) {// 创建名为 “PackageManager” 的 handler 线程mHandlerThread = new ServiceThread(TAG,Process.THREAD_PRIORITY_BACKGROUND, true /*allowIo*/);mHandlerThread.start();mHandler = new PackageHandler(mHandlerThread.getLooper());Watchdog.getInstance().addThread(mHandler, WATCHDOG_TIMEOUT);// 创建各种目录File dataDir = Environment.getDataDirectory();mAppDataDir = new File(dataDir, "data");mAppInstallDir = new File(dataDir, "app");mAppLib32InstallDir = new File(dataDir, "app-lib");mAsecInternalPath = new File(dataDir, "app-asec").getPath();mUserAppDataDir = new File(dataDir, "user");mDrmAppPrivateInstallDir = new File(dataDir, "app-private");// 创建用户管理服务sUserManager = new UserManagerService(context, this,mInstallLock, mPackages);// 这个目录为 /system/frameworkFile frameworkDir = new File(Environment.getRootDirectory(), "framework");// 获取到 frameworkDir 下面的所有文件String[] frameworkFiles = frameworkDir.list();if (frameworkFiles != null) {for (String dexCodeInstructionSet : dexCodeInstructionSets) {for (int i=0; i<frameworkFiles.length; i++) {File libPath = new File(frameworkDir, frameworkFiles[i]);String path = libPath.getPath();// alreadyDexOpted 列表是否包含该文件if (alreadyDexOpted.contains(path)) {continue;}// 过滤掉不是 apk 和 jar 的文件if (!path.endsWith(".apk") && !path.endsWith(".jar")) {continue;}try {int dexoptNeeded = DexFile.getDexOptNeeded(path, null, dexCodeInstructionSet, false);if (dexoptNeeded != DexFile.NO_DEXOPT_NEEDED) {// 执行 dexopt 优化操作 mInstaller.dexopt(path, Process.SYSTEM_UID, true, dexCodeInstructionSet, dexoptNeeded);}} catch (FileNotFoundException e) {Slog.w(TAG, "Jar not found: " + path);} catch (IOException e) {Slog.w(TAG, "Exception reading jar: " + path, e);}}}}// 搜集解析系统各种 app 包信息...// 移除文件mInstaller.moveFiles();// 清理所有安装不完整的包ArrayList<PackageSetting> deletePkgsList = mSettings.getListOfIncompleteInstallPackagesLPr();for(int i = 0; i < deletePkgsList.size(); i++) {cleanupInstallFailedPackage(deletePkgsList.get(i));}// 删除临时文件deleteTempPackageFiles();// 处理解析非系统的 app if (!mOnlyCore) {// 扫描解析 /data/app 目录scanDirLI(mAppInstallDir, 0, scanFlags | SCAN_REQUIRE_KNOWN, 0);// 扫描解析 /data/app-private 目录scanDirLI(mDrmAppPrivateInstallDir, PackageParser.PARSE_FORWARD_LOCK,scanFlags | SCAN_REQUIRE_KNOWN, 0);...}// 将所有解析的包信息写到 packages.xml 文件mSettings.writeLPr();} // synchronized (mPackages)} // synchronized (mInstallLock)// 调用 gc Runtime.getRuntime().gc();}

PKMS 的创建和启动过程比 AMS 复杂太多,我删减了很多不是核心的代码,总得来说 PKMS 在创建的过程中会去解析所有 apk 的安装信息,其中包括系统应用和非系统的安装应用,对于应用开发者来说,我们只需要关注非系统应用就足够了。我们平时安装的手机应用主要放在 mAppInstallDir(data/app) 目录下。总的来说 PKMS 在启动的时候会去解析我们手机所有的应用的 apk 包信息,并会将其所解析的内容全部保存在 mPackages 变量中,最后我们来看下 PKMS 到底是扫描解析保存了 apk 的哪些信息。

    private void scanDirLI(File dir, int parseFlags, int scanFlags, long currentTime) {...for (File file : files) {// 是不是 apk 文件final boolean isPackage = (isApkFile(file) || file.isDirectory())&& !PackageInstallerService.isStageName(file.getName());if (!isPackage) {// Ignore entries which are not packagescontinue;}try {// 扫描解析 apk 文件scanPackageLI(file, parseFlags | PackageParser.PARSE_MUST_BE_APK,scanFlags, currentTime, null);} catch (PackageManagerException e) {// 如果有异常,把这个文件或者文件夹删除if ((parseFlags & PackageParser.PARSE_IS_SYSTEM) == 0 &&e.error == PackageManager.INSTALL_FAILED_INVALID_APK) {logCriticalInfo(Log.WARN, "Deleting invalid package at " + file);if (file.isDirectory()) {mInstaller.rmPackageDir(file.getAbsolutePath());} else {file.delete();}}}}}private PackageParser.Package scanPackageLI(File scanFile, int parseFlags, int scanFlags,long currentTime, UserHandle user) throws PackageManagerException {// 创建一个解析对象PackageParser pp = new PackageParser();pp.setSeparateProcesses(mSeparateProcesses);pp.setOnlyCoreApps(mOnlyCore);pp.setDisplayMetrics(mMetrics);final PackageParser.Package pkg;try {// 解析 apk 参数,返回 PackageParser.Packagepkg = pp.parsePackage(scanFile, parseFlags);} catch (PackageParserException e) {throw PackageManagerException.from(e);}// 搜集证书信息collectCertificatesLI(pp, ps, pkg, scanFile, parseFlags);...return scannedPkg;}public Package parsePackage(File packageFile, int flags) throws PackageParserException {if (packageFile.isDirectory()) {...} else {return parseMonolithicPackage(packageFile, flags);}}public Package parseMonolithicPackage(File apkFile, int flags) throws PackageParserException {final AssetManager assets = new AssetManager();try {final Package pkg = parseBaseApk(apkFile, assets, flags);pkg.codePath = apkFile.getAbsolutePath();return pkg;} finally {IoUtils.closeQuietly(assets);}}private Package parseBaseApk(File apkFile, AssetManager assets, int flags)throws PackageParserException {final String apkPath = apkFile.getAbsolutePath();final int cookie = loadApkIntoAssetManager(assets, apkPath, flags);Resources res = null;XmlResourceParser parser = null;try {res = new Resources(assets, mMetrics, null);assets.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,Build.VERSION.RESOURCES_SDK_INT);// 打开解析 AndroidManifest.xml 文件parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);final String[] outError = new String[1];final Package pkg = parseBaseApk(res, parser, flags, outError);if (pkg == null) {throw new PackageParserException(mParseError,apkPath + " (at " + parser.getPositionDescription() + "): " + outError[0]);}return pkg;} catch (PackageParserException e) {throw e;} catch (Exception e) {throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,"Failed to read manifest from " + apkPath, e);} finally {IoUtils.closeQuietly(parser);}}private Package parseBaseApk(Resources res, XmlResourceParser parser, int flags,String[] outError) throws XmlPullParserException, IOException {AttributeSet attrs = parser;// 解析包名try {Pair<String, String> packageSplit = parsePackageSplitNames(parser, attrs, flags);pkgName = packageSplit.first;splitName = packageSplit.second;} catch (PackageParserException e) {mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;return null;}// 构建一个 Package 对象final Package pkg = new Package(pkgName);boolean foundApp = false;// 获取 VersionCode 和 VersionNameTypedArray sa = res.obtainAttributes(attrs,com.android.internal.R.styleable.AndroidManifest);pkg.mVersionCode = pkg.applicationInfo.versionCode = sa.getInteger(com.android.internal.R.styleable.AndroidManifest_versionCode, 0);pkg.mVersionName = sa.getNonConfigurationString(com.android.internal.R.styleable.AndroidManifest_versionName, 0);if (pkg.mVersionName != null) {pkg.mVersionName = pkg.mVersionName.intern();}// 解析所有可能出现的属性,application ,uses-permission,permission,等等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;}String tagName = parser.getName();if (tagName.equals("application")) {if (foundApp) {if (RIGID_PARSER) {outError[0] = "<manifest> has more than one <application>";mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;return null;} else {Slog.w(TAG, "<manifest> has more than one <application>");XmlUtils.skipCurrentTag(parser);continue;}}foundApp = true;if (!parseBaseApplication(pkg, res, parser, attrs, flags, outError)) {return null;}} else if (tagName.equals("permission")) {if (parsePermission(pkg, res, parser, attrs, outError) == null) {return null;}} else if (tagName.equals("uses-permission")) {if (!parseUsesPermission(pkg, res, parser, attrs)) {return null;}} else if (RIGID_PARSER) {outError[0] = "Bad element under <manifest>: "+ parser.getName();mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;return null;} else {Slog.w(TAG, "Unknown element under <manifest>: " + parser.getName()+ " at " + mArchiveSourcePath + " "+ parser.getPositionDescription());XmlUtils.skipCurrentTag(parser);continue;}}...return pkg;}private boolean parseBaseApplication(Package owner, Resources res,XmlPullParser parser, AttributeSet attrs, int flags, String[] outError)throws XmlPullParserException, IOException {final ApplicationInfo ai = owner.applicationInfo;final String pkgName = owner.applicationInfo.packageName;TypedArray sa = res.obtainAttributes(attrs,com.android.internal.R.styleable.AndroidManifestApplication);// 解析 applicationString name = sa.getNonConfigurationString(com.android.internal.R.styleable.AndroidManifestApplication_name, 0);if (name != null) {ai.className = buildClassName(pkgName, name, outError);if (ai.className == null) {sa.recycle();mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;return false;}}// 解析 allowBackupboolean allowBackup = sa.getBoolean(com.android.internal.R.styleable.AndroidManifestApplication_allowBackup, true);if (allowBackup) {...}// 解析 label 也就是 app 的名字TypedValue v = sa.peekValue(com.android.internal.R.styleable.AndroidManifestApplication_label);if (v != null && (ai.labelRes=v.resourceId) == 0) {ai.nonLocalizedLabel = v.coerceToString();}// 解析 icon ,logo,theme 等等ai.icon = sa.getResourceId(com.android.internal.R.styleable.AndroidManifestApplication_icon, 0);ai.logo = sa.getResourceId(com.android.internal.R.styleable.AndroidManifestApplication_logo, 0);ai.banner = sa.getResourceId(com.android.internal.R.styleable.AndroidManifestApplication_banner, 0);ai.theme = sa.getResourceId(com.android.internal.R.styleable.AndroidManifestApplication_theme, 0); // 开始解析四大组件final int innerDepth = parser.getDepth();int type;while ((type = parser.next()) != XmlPullParser.END_DOCUMENT&& (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {continue;}String tagName = parser.getName();if (tagName.equals("activity")) {Activity a = parseActivity(owner, res, parser, attrs, flags, outError, false,owner.baseHardwareAccelerated);if (a == null) {mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;return false;}owner.activities.add(a);} else if (tagName.equals("receiver")) {Activity a = parseActivity(owner, res, parser, attrs, flags, outError, true, false);if (a == null) {mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;return false;}owner.receivers.add(a);} else if (tagName.equals("service")) {Service s = parseService(owner, res, parser, attrs, flags, outError);if (s == null) {mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;return false;}owner.services.add(s);} else if (tagName.equals("provider")) {Provider p = parseProvider(owner, res, parser, attrs, flags, outError);if (p == null) {mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;return false;}owner.providers.add(p);} else if (tagName.equals("activity-alias")) {Activity a = parseActivityAlias(owner, res, parser, attrs, flags, outError);if (a == null) {mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;return false;}owner.activities.add(a);} else if (parser.getName().equals("meta-data")) {// note: application meta-data is stored off to the side, so it can// remain null in the primary copy (we like to avoid extra copies because// it can be large)if ((owner.mAppMetaData = parseMetaData(res, parser, attrs, owner.mAppMetaData,outError)) == null) {mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;return false;}} else if (tagName.equals("library")) {sa = res.obtainAttributes(attrs,com.android.internal.R.styleable.AndroidManifestLibrary);// Note: don't allow this value to be a reference to a resource// that may change.String lname = sa.getNonResourceString(com.android.internal.R.styleable.AndroidManifestLibrary_name);sa.recycle();if (lname != null) {lname = lname.intern();if (!ArrayUtils.contains(owner.libraryNames, lname)) {owner.libraryNames = ArrayUtils.add(owner.libraryNames, lname);}}XmlUtils.skipCurrentTag(parser);} else if (tagName.equals("uses-library")) {sa = res.obtainAttributes(attrs,com.android.internal.R.styleable.AndroidManifestUsesLibrary);// Note: don't allow this value to be a reference to a resource// that may change.String lname = sa.getNonResourceString(com.android.internal.R.styleable.AndroidManifestUsesLibrary_name);boolean req = sa.getBoolean(com.android.internal.R.styleable.AndroidManifestUsesLibrary_required,true);sa.recycle();if (lname != null) {lname = lname.intern();if (req) {owner.usesLibraries = ArrayUtils.add(owner.usesLibraries, lname);} else {owner.usesOptionalLibraries = ArrayUtils.add(owner.usesOptionalLibraries, lname);}}XmlUtils.skipCurrentTag(parser);} else if (tagName.equals("uses-package")) {// Dependencies for app installers; we don't currently try to// enforce this.XmlUtils.skipCurrentTag(parser);} else {if (!RIGID_PARSER) {Slog.w(TAG, "Unknown element under <application>: " + tagName+ " at " + mArchiveSourcePath + " "+ parser.getPositionDescription());XmlUtils.skipCurrentTag(parser);continue;} else {outError[0] = "Bad element under <application>: " + tagName;mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;return false;}}}return true;}

视频地址:https://pan.baidu.com/s/1dM3K9bPRuepFUJIASIDeQg
视频密码:af97

Android 系统服务 - PMS 的启动过程相关推荐

  1. Android 系统服务管家servicemanager启动过程详解

    Android考虑到移动设备耗电以及跨进程通信效率等因素,基于OpenBinder专门为进程通信开发了一套框架:binder.例如,客户端程序需要获取WindowManager,TelephonyMa ...

  2. 从源码角度看Android系统SystemServer进程启动过程

    SystemServer进程是由Zygote进程fork生成,进程名为system_server,主要用于创建系统服务. 备注:本文将结合Android8.0的源码看SystemServer进程的启动 ...

  3. 从源码角度看Android系统Zygote进程启动过程

    在Android系统中,DVM.ART.应用程序进程和SystemServer进程都是由Zygote进程创建的,因此Zygote又称为"孵化器".它是通过fork的形式来创建应用程 ...

  4. 从源码角度看Android系统init进程启动过程

    init进程是Linux系统中用户空间的第一个进程,进程号为1.Kernel启动后,在用户空间启动init进程,并调用/system/core/init.cpp中的main方法执行一些重要的工作. 备 ...

  5. Android应用程序进程启动过程的源代码分析(1)

    Android应用程序框架层创建的应用程序进程具有两个特点,一是进程的入口函数是ActivityThread.main,二是进程天然支持Binder进程间通信机制:这两个特点都是在进程的初始化过程中实 ...

  6. Android应用程序进程启动过程

    相关文章 Android系统架构与系统源码目录 Android系统启动流程(一)解析init进程启动过程 Android系统启动流程(二)解析Zygote进程启动过程 Android系统启动流程(三) ...

  7. android actviity模糊,Framework启动过程浅析

    浅显的总结一下Framework启动大概过程 总体 Android底层是linux系统,因而在开机时仍然是运行天字第一号进程inti,读取init.rc来创建第一个Dalvik进程zygote,下面是 ...

  8. Android应用程序进程启动过程的源代码分析(2)

      Step 5. ZygoteInit.runSelectLoopMode         这个函数定义在frameworks/base/core/java/com/android/internal ...

  9. 新手大战Android源码之启动过程

    新手上路,当学习笔记整理记忆. 先来个基本启动流程框架图: 1 招兵买马 古语云:机会总是留给有准备的人.为了这场战役,我准备了如下几个利器. 深入理解Android卷I书籍一本 有关博客数篇,大小不 ...

最新文章

  1. 博科VP:闪存推动了与之相匹配的第六代FC的发展
  2. 简单记事本及目录树形图的Java实现
  3. setTimeout使用问题
  4. 前端学习(1851)vue之电商管理系统电商系统vue创建项目
  5. netty心跳过程中 发送消息失败_Netty 4.0 实现心跳检测和断线重连
  6. java获取界面输入数字_通过JAVA设计 GUI 界面的计算器程序,用户可以通过鼠标依次输入参加计算的数值,进行加、减、乘、...
  7. 邮件代理发送功能更新和Exchange 6月份补丁更新提示
  8. 看云计算时代的web1800远程服务支持系统
  9. 如何升级mysql-libs_MySQL升级教程(CentOS)
  10. centos7 安装 dos2unix
  11. mysql按笔划排序_Sql Server数据库汉字按字母、笔划、拼音首字母、排序
  12. swfobject简单封装
  13. 吃豆豆--Java小游戏
  14. 软件测试知识点和面试题--app测试篇
  15. php 图片获得大小,PHP获取一张图片的宽度和高度大小 并裁切图片
  16. D3.js v5.0 旭日图
  17. win10在哪找计算机配置,电脑教程:windows10的设置在哪
  18. Link/Cut Tree学习笔记
  19. Zemax操作6--激光扩束镜
  20. 一文读懂 TCP/IP 网络模型

热门文章

  1. Nginx 使用之一(server参数配置)
  2. SQL注入【二】——MYSQL注入的基本流程
  3. 操作系统 | PV操作练习题汇总(一)
  4. 手把手教你如何玩转Solr(包含项目实战)
  5. [转载]Alsa驱动分析
  6. 医疗大数据知识库的主要功能和作用
  7. 给定三条边,请你判断一下能不能组成一个三角形。
  8. 苏菲的世界——史宾诺莎
  9. [STM32F4]STM32F407 ADC采集+DMA传输
  10. matlab结果以向量形式输出,MATLAB:为什么我自己写的这个函数,即使输入值为一个向量,输出也只有一个值?...