1. 概述

PackageManagerService是Android系统核心服务之一,也是Android中最常用的服务之一。它主要负责的工作如下:

1.  解析AndroidManifest.xml文件,解析清单文件中的所有节点信息。

2.  扫描.apk文件,安装系统应用,本地应用等。

3.  管理本地应用,主要有:安装、卸载、应用信息查询等。

2. 核心源码

/frameworks/base/core/java/android/app/ApplicationPackageManager.java
/frameworks/base/services/java/com/android/server/SystemServer.java
/frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
/frameworks/base/services/core/java/com/android/server/pm/PackageDexOptimizer.java
/frameworks/base/services/core/java/com/android/server/pm/Installer.java
/frameworks/base/services/core/java/com/android/server/pm/Settings.java
/frameworks/base/services/core/java/com/android/server/pm/permission/BasePermission.java
/frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
/frameworks/base/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
/frameworks/base/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
/frameworks/base/core/java/android/content/pm/IPackageManager.aidl
/frameworks/base/core/java/android/content/pm/PackageManager.java
/frameworks/base/core/java/com/android/server/SystemConfig.java

3. PKMS架构

3.1 继承关系

客户端可通过context.getPackageManager()获得ApplicationPackageManager对象,而mPm指向的是Proxy代理,当调用到mPm的方法时,将会调用到IPackageManager的Proxy代理方法,然后通过Binder机制中的mRemote与服务端PackageManagerService通信,并调用到PackageManagerService的方法。因此,PKMS是属于Binder机制中的服务端角色。

3.2 启动过程

启动过程描述:

SystemServer启动PKMS:先是在SystemServer.startBootstrapServices()函数中启动PKMS服务,再调用startOtherServices()函数中对dex优化,磁盘管理功能,让PKMS进入SystemReady状态。

4. 启动过程

上文提到,PKMS服务由SystemServer进行启动。其启动过程具体由以下七步来完成。具体如下:

1. SystemServer启动Boot服务

调用startBootstrapServices()服务
(1) 启动Installer服务:mSystemServiceManager.startService(Installer.class);
(2) 获取设备是否加密(手机设置密码),如果设备加密了,则只解析"core"应用

String cryptState = VoldProperties.decrypt().orElse("");

(3) 调用PKMS.main()方法初始化PackageManagerService

PackageManagerService.main(mSystemContext,installer,mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);       
PackageManagerService m = new PackageManagerService(context, installer,
                factoryTest, onlyCore); // 构造PackageManagerService对象
ServiceManager.addService("package",m); // 把实例化出来的PKMS丢给ServiceManager进行注册
final PackageManagerNative pmn = m.new PackageManagerNative(); // 构造PackageManagerNative对象
ServiceManager.addService("package_native", pmn); // 启动package_native服务

(4) 如果设备没有加密,操作它。管理A/B OTA dexopting

if (!mOnlyCore)  // 判断是否只是核心应用

2. SystemServer启动其他服务,并使一些核心服务处于ready状态
   调用startOtherServices()方法

(5) // 如果设备没有加密,执行performDexoptUpgrade,完成dexopt优化

mPackageManagerService.updatePackagesIfNeeded();   
该方法,作用:检查是否需要去更新Packages并进行dex优化。

条件:没有OTA升级,没有大版本升级,
          没有清除过dalvik虚拟机的缓存,可以去更新Packages。
更新Packages的优先级:core app > system app > other app,调用performDexOptUpgrade()方法进行更新

(6) mPackageManagerService.performFstrimIfNeeded(); // 执行performFstrimIfNeeded(),完成磁盘维护
(7) mPowerManagerService.systemReady(mActivityManagerService.getAppOpsService());// PackageManagerNative 准备就绪
     DefaultPermissionPolicy.grantDefaultPermissions(userId); // 启动之前授予默认所有权限

4.1.1 SystemServer.java startBootstrapServices()

说明:startBootstrapServices()首先启动Installer服务,也就是安装器,随后判断当前的设备是否是出于加密状态。如果是出于加密状态则只是解析核心应用,接着调用PackageManagerService的静态方法main来创建PKMS对象。

(1) 启动Installer对象

(2) 获取设备是否加密(手机设置密码),如果设备加密了,则只解析"core"应用。

(3) 调用PKMS main方法初始化PackageManagerService,其中调用PackageManagerService()构造方法创建了PKMS对象。

(4) 如果设备没有加密,操作它。管理A/B OTA dexopting。

源码:

private void startBootstrapServices(@NonNull TimingsTraceAndSlog t) {// (1)启动Installer服务// 阻塞等待installed完成启动,以便有机会创建具有适当权限的关键目录,// 如/data/user。我们需要在初始化其他服务之前完成此任务。Installer installer = mSystemServiceManager.startService(Installer.class);// 初始化AMSmActivityManagerService = ActivityManagerService.Lifecycle.startService(mSystemServiceManager, atm);mActivityManagerService.setSystemServiceManager(mSystemServiceManager);// 我们需要在初始化其他服务之前完成此任务mActivityManagerService.setInstaller(installer);// Only run "core" apps if we're encrypting the device.// (2).获取设备是否加密// 如果设备加密了,则只解析 "core" 应用// mOnlyCore = true,后面会频繁使用该变量进行条件判断String cryptState = VoldProperties.decrypt().orElse("");if (ENCRYPTING_STATE.equals(cryptState)) {Slog.w(TAG, "Detected encryption in progress - only parsing core apps");mOnlyCore = true;} else if (ENCRYPTED_STATE.equals(cryptState)) {Slog.w(TAG, "Device encrypted - only parsing core apps");mOnlyCore = true;}// (3) 调用PKMS的main方法,初始化PKMSmPackageManagerService = PackageManagerService.main(mSystemContext, installer,mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);// PKMS 是否是第一次启动mFirstBoot = mPackageManagerService.isFirstBoot();// 通过context.getPackageManager()来获得PackageManager对象mPackageManager = mSystemContext.getPackageManager();// (4) 如果设备没有加密,操作它。管理A/B OTA dexoptingif (!mOnlyCore) {boolean disableOtaDexopt = SystemProperties.getBoolean("config.disable_otadexopt",false);if (!disableOtaDexopt) {t.traceBegin("StartOtaDexOptService");try {Watchdog.getInstance().pauseWatchingCurrentThread("moveab");OtaDexoptService.main(mSystemContext, mPackageManagerService);} catch (Throwable e) {reportWtf("starting OtaDexOptService", e);} finally {Watchdog.getInstance().resumeWatchingCurrentThread("moveab");t.traceEnd();}}}}

4.1.2 [SystemServer.java] startOtherServices()

说明:

(5) 执行updatePackageIfNeeded,完成dex优化

(6) 执行performFstrimIfNeeded,完成磁盘维护

(7) 调用systemReady,准备就绪

源码:

private void startOtherServices(@NonNull TimingsTraceAndSlog t) {if (!mOnlyCore) {try {Watchdog.getInstance().pauseWatchingCurrentThread("dexopt");// (5) 如果设备没有加密,执行performDexoptUpgrade,完成dexopt优化mPackageManagerService.updatePackagesIfNeeded();} catch (Throwable e) {reportWtf("update packages", e);} finally {Watchdog.getInstance().resumeWatchingCurrentThread("dexopt");}}try {// (6) 执行performFstrim,完成磁盘维护mPackageManagerService.performFstrimIfNeeded();} catch (Throwable e) {reportWtf("performing fstrim", e);}// (7) PackageManagerService准备就绪mPackageManagerService.systemReady();}

我们重点分析一下第三步。也就是PKMS的main方法

4.1.3 [PackageManagerService.java] main()

main函数主要工作:

(1) 检查Package编译相关系统属性

(2) 调用PackageManagerService构造方法

(3) 启用部分应用服务于多用户场景

(4) 往ServiceManager中注册 "package" 和 "package_native'。

源码:

public static PackageManagerService main(Context context, Installer installer,boolean factoryTest, boolean onlyCore) {// Self-check for initial settings.// (1) 检查Package编译相关系统属性PackageManagerServiceCompilerMapping.checkProperties();// (2) 构造PackageManagerService对象PackageManagerService m = new PackageManagerService(injector, onlyCore, factoryTest);// 基于用户类型,为所有用户安装/卸载系统应用m.installWhitelistedSystemPackages();// 向ServiceManager注册PKMS(启动package服务)ServiceManager.addService("package", m);// 构造PackageManagerNative对象final PackageManagerNative pmn = m.new PackageManagerNative();// 启动package_native服务ServiceManager.addService("package_native", pmn);return m;}

PKMS 初始化时的核心部分为PackageManagerService的构造函数的内容,现在我们来看一下该函数。

4.2 PKMS构造函数分析

此函数由两个重要的锁(mInstallLock和mLock)和五个阶段构成。在Android 10.0源码中是由(mInstallLock和mPackages)两个锁

mInstallLock、mLock:用来保护所有安装apk的访问权限,此操作通常涉及繁重的磁盘数据读写等操作。并且是单线程操作,所以有时候会处理很慢。此锁不会在已经持有了mLock锁的情况下加锁,反之,在已经持有mInstallLock锁的情况下,立即获得mLock是安全的。

mPackages(mLock):用来解析内存中所有apk的package信息及相关状态。

PKMS服务也是通过Binder进行通信,IPackageManager.aidl由工具转换后自动生成Binder的服务端IPackageManager.Stub和客户端IPackageManager.Stub.Proxy。

Binder服务端:PackageManagerService继承自IPackageManager.Stub

Binder客户端:ApplicationPackageManager(简称APM)的成员变量mPm继承于IPackageManager.Stub.Proxy。本身APM继承与PackageManager对象。

如 3.1 中的继承关系图所示

5个阶段:

阶段一:BOOT_PROGRESS_PMS_START
阶段二:BOOT_PROGRESS_PMS_SYSTEM_SCAN_START
阶段三:BOOT_PROGRESS_PMS_DATA_SCAN_START
阶段四:BOOT_PROGRESS_PMS_SCAN_END
阶段五:BOOT_PROGRESS_PMS_READY

4.2.1 [PackageManagerService.java]

说明:IPackageManager.Stub是IPackageManager.aidl自动生成的,正好也说明了PKMS是service端的,通过binder交互

源码:


public class PackageManagerService extends IPackageManager.Stubimplements PackageSender {
}

4.2.2 [PackageManagerService.java]   PackageManagerService()

说明:PackageManagerService构造函数

源码:

public PackageManagerService(Context context, Installer installer,boolean factoryTest, boolean onlyCore) {...//阶段1:BOOT_PROGRESS_PMS_STARTEventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START,SystemClock.uptimeMillis());//阶段2:BOOT_PROGRESS_PMS_SYSTEM_SCAN_STARTEventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,startTime);...//阶段3:BOOT_PROGRESS_PMS_DATA_SCAN_STARTif (!mOnlyCore) {EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,SystemClock.uptimeMillis());}...//阶段4:BOOT_PROGRESS_PMS_SCAN_END EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END,SystemClock.uptimeMillis());...//阶段5:BOOT_PROGRESS_PMS_READYEventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY,SystemClock.uptimeMillis());
}

4.2.3 阶段1:BOOT_PROGRESS_PMS_START

主要工作:

(1) 构造 DisplayMetrics,保存分辨率相关信息。

(2) 创建Installer对象,与installd交互

(3) 创建mPermissionManager对象,进行权限管理

(4) 构造Settings类,保存安装包信息,清除路径不存在的孤立应用,主要涉及/data/system/目录的packages.xml,
     packages-backup.xml,packages.list,packages-stopped.xml,packages-stopped-backup.xml等文件。
(5) 构造PackageDexOptimizer及DexManager类,处理dex优化;
(6) 创建SystemConfig实例,获取系统配置信息,配置共享lib库;
(7) 创建PackageManager的Handler线程,循环处理外部安装相关消息。

源码:

public PackageManagerService(Injector injector, boolean onlyCore, boolean factoryTest) {// 第一阶段EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START,SystemClock.uptimeMillis());// mSdkVersion是编译的SDK版本if (mSdkVersion <= 0) {Slog.w(TAG, "**** ro.build.version.sdk not set!");}mFactoryTest = factoryTest;  // 假设为false,即运行在非工厂模式下mOnlyCore = onlyCore;// 假设为false,即运行在普通模式下。标记是否只加载核心服务// (1) mMetrics用于存储与显示屏相关的一些属性,例如屏幕的宽高尺寸、分辨率等信息mMetrics = new DisplayMetrics();// (2) 构建Installer对象,与installed交互mInstaller = injector.getInstaller();// 本地服务LocalServices.addService(PackageManagerInternal.class, mPmInternal);// 构建多用户管理服务mUserManager = injector.getUserManagerService();mComponentResolver = injector.getComponentResolver();// (3) 构建权限管理服务mPermissionManager = injector.getPermissionManagerServiceInternal();// 创建Settings对象,Settings是一个非常重要的类,用于存储系统运行过程中的一些设置mSettings = injector.getSettings();// (4)构造Settings类,保存安装包信息,清除路径不存在的孤立应用,主要涉// 及/data/system/目录的packages.xml,packages-backup.xml, packages.list,// packages-stopped.xml,packages-stopped-backup.xml等文件。// 添加system,phone,log,nfc,bluetooth,shell,se,networkstack这八种shareUserId到settings对象中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);mSettings.addSharedUserLPw("android.uid.se", SE_UID,ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);mSettings.addSharedUserLPw("android.uid.networkstack", NETWORKSTACK_UID,ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);// (5)构造PackageDexOptimizer及DexManager类,处理dex优化mPackageDexOptimizer = new PackageDexOptimizer(mInstaller, mInstallLock, mContext,"*dexopt*");mDexManager =new DexManager(mContext, this, mPackageDexOptimizer, mInstaller, mInstallLock);// 创建ATR虚拟机管理服务mArtManagerService = new ArtManagerService(mContext, this, mInstaller, mInstallLock);// 获取默认分辨率getDefaultDisplayMetrics(mInjector.getDisplayManager(), mMetrics);// (6)创建SystemConfig实例,获取系统配置信息,配置共享lib库;//拿到SystemConfig()的对象,其中会调用SystemConfig的readPermissions()完成权限的读取SystemConfig systemConfig = SystemConfig.getInstance();        // CHECKSTYLE:OFF IndentationChecksynchronized (mInstallLock) {// writersynchronized (mLock) {//(7)创建PackageManager的handler线程,循环处理外部安装相关消息//启动PackageManager线程,负责apk的安装、卸载mHandlerThread = new ServiceThread(TAG,Process.THREAD_PRIORITY_BACKGROUND, true /*allowIo*/);mHandlerThread.start();// 应用HandlermHandler = new PackageHandler(mHandlerThread.getLooper());// 进程记录handlermProcessLoggingHandler = new ProcessLoggingHandler();// WatchDog监听ServiceThread是否超时:10分钟Watchdog.getInstance().addThread(mHandler, WATCHDOG_TIMEOUT);// Instant应用注册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);}         // 读取安装SELinux相关策略SELinuxMMAC.readInstallPolicy();// 返回栈加载FallbackCategoryProvider.loadFallbacks();// 读取并解析/data/system下的XML文件mFirstBoot = !mSettings.readLPw(mInjector.getUserManagerInternal().getUsers(false));// Clean up orphaned packages for which the code path doesn't exist// and they are an update to a system app - caused by bug/32321269// 清理代码路径不存在的孤立软件包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);}}// 如果不是首次启动,也不是CORE应用,则拷贝预编译的DEX文件if (!mOnlyCore && mFirstBoot) {requestCopyPreoptedFiles();}......}    // synchronized (mPackages)}}

readLPw()会扫描下面5个文件

1) "/data/system/packages.xml"                                       // 所有安装app信息

2) "/data/system/packages-backup.xml"                          // 所有安装app信息的备份的信息记录

3) "/data/system/packages.list"                                        // 所有安装app信息

4) "/data/system/packages-stopped.xml"                        // 所有强制停止app信息

5) "/data/system/packages-stopped-backup.xml"           // 所以强制停止app信息的备份的信息记录

5个文件共分为三组,简单的作用描述如下:

1. packages.xml: PKMS扫描完成目标文件夹之后会创建该文件。当系统进行程序安装、卸载和更新等操作时,均会更新该文件。该文件保存了系统中与 package相关的一些信息。

2. packages.list: 描述系统中存在的所有非系统自带的apk的信息。当这些程序有变动时 PKMS 就会更新该文件。

3. packages-stopped.xml : 从系统自带的设置程序中进入应用程序页面,然后再选择强制停止(ForceStop) 某个应用时,系统会将该应用的相关信息记录到此文件中。也就是该文件保存系统中被用户强制停止的 package 的信息。

这些目录的指向,都在settings中的构造函数中完成,如下所示,得到目录后调用readLpw()进行扫描。

看一下settings的构造函数(package com.android.server.pm)

源码:

Settings(File dataDir, PermissionSettings permission,Object lock) {mLock = lock;mPermissions = permission;mRuntimePermissionsPersistence = new RuntimePermissionPersistence(mLock);mSystemDir = new File(dataDir, "system");               //mSystemDir指向目录"/data/system"mSystemDir.mkdirs();        //创建 "/data/system"// 设置权限FileUtils.setPermissions(mSystemDir.toString(),FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IROTH|FileUtils.S_IXOTH,-1, -1);//(1)指向目录"/data/system/packages.xml"mSettingsFilename = new File(mSystemDir, "packages.xml");//(2)指向目录"/data/system/packages-backup.xml"mBackupSettingsFilename = new File(mSystemDir, "packages-backup.xml");//(3)指向目录"/data/system/packages.list"mPackageListFilename = new File(mSystemDir, "packages.list");FileUtils.setPermissions(mPackageListFilename, 0640, SYSTEM_UID, PACKAGE_INFO_GID);final File kernelDir = new File("/config/sdcardfs");mKernelMappingFilename = kernelDir.exists() ? kernelDir : null;// Deprecated: Needed for migration//(4)指向目录"/data/system/packages-stopped.xml"mStoppedPackagesFilename = new File(mSystemDir, "packages-stopped.xml");//(5)指向目录"/data/system/packages-stopped-backup.xml"mBackupStoppedPackagesFilename = new File(mSystemDir, "packages-stopped-backup.xml");}

解析上面这几个xml的内容,建立对应的数据结构

Setting.javaboolean readLPw(@NonNull List<UserInfo> users) {FileInputStream str = null;   if (str == null) {str = new FileInputStream(mSettingsFilename);}// 解析 "/data/system/packages.xmlXmlPullParser parser = Xml.newPullParser();parser.setInput(str, StandardCharsets.UTF_8.name());int type;while ((type = parser.next()) != XmlPullParser.START_TAG&& type != XmlPullParser.END_DOCUMENT) {;}if (type != XmlPullParser.START_TAG) {mReadMessages.append("No start tag found in settings file\n");PackageManagerService.reportSettingsProblem(Log.WARN,"No start tag found in package manager settings");Slog.wtf(PackageManagerService.TAG,"No start tag found in package manager settings");return false;}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;}// 根据xml的各个节点进行各种操作,例如读取权限、shared-user等String tagName = parser.getName();if (tagName.equals("package")) {readPackageLPw(parser);} else if (tagName.equals("permissions")) {mPermissions.readPermissions(parser);} else if (tagName.equals("permission-trees")) {mPermissions.readPermissionTrees(parser);} else if (tagName.equals("shared-user")) {readSharedUserLPw(parser);} .....str.close();       for (int i = 0; i < N; i++) {final PackageSetting p = mPendingPackages.get(i);final int sharedUserId = p.getSharedUserId();final Object idObj = getSettingLPr(sharedUserId);if (idObj instanceof SharedUserSetting) {// 创建SharedUserSetting对象并添加到Settings的成员变量mSharedUsers中,// 在Android系统中,多个Package通过设置SharedUserId属性可以运行在同一个进程,共享同一个UIDfinal SharedUserSetting sharedUser = (SharedUserSetting) idObj;p.sharedUser = sharedUser;p.appId = sharedUser.userId;addPackageSettingLPw(p, sharedUser);}return true;}

说明:创建 SharedUserSetting 对象并添加到 Settings 的成员变量 mSharedUsers 中,在 Android 系统中,多个 package 通过设置 sharedUserId 属性可以运行在同一个进程,共享同一个 UID。

源码:

mSettings.addSharedUserLPw("android.uid.system", // 字符串Process.SYSTEM_UID, //系统进程使用的用户id,值为1000ApplicationInfo.FLAG_SYSTEM, //标志系统 PackageApplicationInfo.PRIVATE_FLAG_PRIVILEGED); //特权系统应用  SharedUserSetting addSharedUserLPw(String name, int uid, int pkgFlags, int pkgPrivateFlags) {// mSharedUsers是一个HashMap,key是字符串,值为 SharedUserSetting对象SharedUserSetting s = mSharedUsers.get(name);if (s != null) {if (s.userId == uid) {return s;}PackageManagerService.reportSettingsProblem(Log.ERROR,"Adding duplicate shared user, keeping first: " + name);return null;}// 创建一个 SharedUserSetting对象,并设置userId为UIDs = new SharedUserSetting(name, pkgFlags, pkgPrivateFlags);s.userId = uid;if (registerExistingAppIdLPw(uid, s, name)) {mSharedUsers.put(name, s);// 将name与键值对添加到mSharedUsers中保存return s;}return null;}

4.2.4 阶段2:BOOT_PROGRESS_PMS_SYSTEM_SCAN_START

主要工作:

(1) 从init.rc中获取环境变量BOOTCLASSPATH和SYSTEMSERVERCLASSPATH;

(2) 对于旧版本升级的情况,将安装时获取权限变更为运行时申请权限;

(3) 扫描system/vendor/product/odm/oem等目录的priv-app、app、overlay包;

(4) 清除安装时临时文件以及其他不必要的信息。

源码:

public PackageManagerService(Context context, Installer installer,boolean factoryTest, boolean onlyCore) {// 记录扫描开始时间long startTime = SystemClock.uptimeMillis();// 第二阶段EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,startTime);// 获取环境变量,init.rcfinal String bootClassPath = System.getenv("BOOTCLASSPATH");final String systemServerClassPath = System.getenv("SYSTEMSERVERCLASSPATH");// 获取system/frameworks目录File frameworkDir = new File(Environment.getRootDirectory(), "framework");// 获取内部版本final VersionInfo ver = mSettings.getInternalVersion();// 判断fingerprint是否更新mIsUpgrade = !Build.FINGERPRINT.equals(ver.fingerprint);           // 对于Android M之前版本升级上来的情况,需要将系统应用程序权限从安装升级到运行时mPromoteSystemApps =mIsUpgrade && ver.sdkVersion <= Build.VERSION_CODES.LOLLIPOP_MR1;// 对于Android N之前版本升级上来的情况,需要像首次启动一样处理packagemIsPreNUpgrade = mIsUpgrade && ver.sdkVersion < Build.VERSION_CODES.N;mIsPreNMR1Upgrade = mIsUpgrade && ver.sdkVersion < Build.VERSION_CODES.N_MR1;mIsPreQUpgrade = mIsUpgrade && ver.sdkVersion < Build.VERSION_CODES.Q;// 在扫描之前保存预先存在的系统Package的名称,这样我们可以确定哪些系统包在升级后是全新的。if (isDeviceUpgrading()) {mExistingPackages = new ArraySet<>(mSettings.mPackages.size());for (PackageSetting ps : mSettings.mPackages.values()) {mExistingPackages.add(ps.name);}}// 准备解析Package的缓存mCacheDir = preparePackageParserCache();// Set flag to monitor and not change apk file paths when// scanning install directories.// 设置Flag,而不在扫描安装时更改文件路径int scanFlags = SCAN_BOOTING | SCAN_INITIAL;// 在Android 10.0 中,此处会扫描以下路径//扫描以下路径:/vendor/overlay、/product/overlay、/product_services/overlay、                  // /odm/overlay、/oem/overlay、/system/framework、/system/priv-app、// /system/app、/vendor/priv-app、/vendor/app、/odm/priv-app、/odm/app、// /oem/app、/oem/priv-app、/product/priv-app、/product/app、// /product_services/priv-app、/product_services/app、// /product_services/priv-appfor (int i = mDirsToScanAsSystem.size() - 1; i >= 0; i--) {final ScanPartition partition = mDirsToScanAsSystem.get(i);if (partition.getOverlayFolder() == null) {continue;}// 扫描overlay包scanDirTracedLI(partition.getOverlayFolder(), systemParseFlags,systemScanFlags | partition.scanFlag, 0,packageParser, executorService);}scanDirTracedLI(frameworkDir, systemParseFlags,systemScanFlags | SCAN_NO_DEX | SCAN_AS_PRIVILEGED, 0,packageParser, executorService);if (!mPackages.containsKey("android")) {throw new IllegalStateException("Failed to load frameworks package; check log for warnings");}for (int i = 0, size = mDirsToScanAsSystem.size(); i < size; i++) {final ScanPartition partition = mDirsToScanAsSystem.get(i);if (partition.getPrivAppFolder() != null) {// 扫描priv-app路径scanDirTracedLI(partition.getPrivAppFolder(), systemParseFlags,systemScanFlags | SCAN_AS_PRIVILEGED | partition.scanFlag, 0,packageParser, executorService);}// 扫描app路径scanDirTracedLI(partition.getAppFolder(), systemParseFlags,systemScanFlags | partition.scanFlag, 0,packageParser, executorService);}// 删掉不存在的packageif (!mOnlyCore) {// do this first before mucking with mPackages for the "expecting better" casefinal Iterator<AndroidPackage> pkgIterator = mPackages.values().iterator();while (pkgIterator.hasNext()) {final AndroidPackage pkg = pkgIterator.next();if (pkg.isStub()) {stubSystemApps.add(pkg.getPackageName());}}final Iterator<PackageSetting> psit = mSettings.mPackages.values().iterator();while (psit.hasNext()) {PackageSetting ps = psit.next();// 如果不是系统应用,则不被允许禁用其他应用if ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0) {continue;}// 如果应用被扫描,则不允许被擦除final AndroidPackage scannedPkg = mPackages.get(ps.name);if (scannedPkg != null) {// 如果系统应用被扫描,且存在于disable应用列表中,那它一定是通过OTA添加的if (mSettings.isDisabledSystemPackageLPr(ps.name)) {logCriticalInfo(Log.WARN,"Expecting better updated system app for " + ps.name+ "; removing system app.  Last known"+ " codePath=" + ps.codePathString+ ", versionCode=" + ps.versionCode+ "; scanned versionCode=" + scannedPkg.getLongVersionCode());removePackageLI(scannedPkg, true);mExpectingBetter.put(ps.name, ps.codePath);}continue;}// 删除没有关联应用的共享UID标识mSettings.pruneSharedUsersLPw();......}

4.2.5 阶段3:BOOT_PROGRESS_PMS_DATA_SCAN_START

主要工作有:对于不仅仅解析核心应用的情况下,还处理data目录的应用信息,及时更新,去除不必要的数据。

源码:

PackageManagerService.packageManagerService()if (!mOnlyCore) {// 第三阶段EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,SystemClock.uptimeMillis());              // 移除通过OTA删除的更新系统应用程序的禁用package设置// 如果更新不存在,则完全删除该应用。否则,撤销其系统权限for (int i = possiblyDeletedUpdatedSystemApps.size() - 1; i >= 0; --i) {final String packageName = possiblyDeletedUpdatedSystemApps.get(i);final AndroidPackage pkg = mPackages.get(packageName);final String msg;mSettings.removeDisabledSystemPackageLPw(packageName);.....}// 确保期望在userdata分区上显示的所有系统应用程序实际显示了。// 如果从未出现过,需要回滚以恢复系统版本for (int i = 0; i < mExpectingBetter.size(); i++) {final String packageName = mExpectingBetter.keyAt(i);if (!mPackages.containsKey(packageName)) {mSettings.enableSystemPackageLPw(packageName);try {// 扫描APKscanPackageTracedLI(scanFile, reparseFlags, rescanFlags, 0, null);} catch (PackageManagerException e) {Slog.e(TAG, "Failed to parse original system package: "+ e.getMessage());}}}// 解压缩并安装任何存根系统应用程序。必须最后执行此操作以确保禁用或替换所有存根installSystemStubPackages(stubSystemApps, scanFlags);......// Resolve the storage manager.// 获取Storage manager包名mStorageManagerPackage = getStorageManagerPackageName();// 解决受保护的action过滤器。只允许setup wizard(开机向导)为这些action设置高优先级过滤器mSetupWizardPackage = getSetupWizardPackageNameImpl();// 更新客户端,以确保持有正确的共享库路径updateAllSharedLibrariesLocked(null, null, Collections.unmodifiableMap(mPackages));......// 读取并更新要保留的package的上次使用时间mPackageUsage.read(mSettings.mPackages);mCompilerStats.read();
}

4.2.6 阶段4:BOOT_PROGRESS_PMS_SCAN_END

主要工作:

(1) sdk版本变更,更新权限;

(2) OTA升级后首次启动,清除不必要的缓存数据;

(3) 权限等默认项更新完后,清理相关数据;

(4) 更新package.xml

源码:

PackageManagerService.packageManager()// 第四阶段
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END,SystemClock.uptimeMillis());// 如果自上次启动以来,平台SDK已改变,则需要重新授予应用程序权限以捕获出现的任何新权限
final boolean sdkUpdated = (ver.sdkVersion != mSdkVersion);
if (sdkUpdated) {mPermissionManager.updateAllPermissions(StorageManager.UUID_PRIVATE_INTERNAL, sdkUpdated);ver.sdkVersion = mSdkVersion;// 如果这是第一次启动或这是来自Android M之前的版本升级,并且它是正常启动,// 那需要在所有已定义的用户初始化默认的首选应用程序if (!mOnlyCore && (mPromoteSystemApps || mFirstBoot)) {for (UserInfo user : mInjector.getUserManagerInternal().getUsers(true)) {mSettings.applyDefaultPreferredAppsLPw(user.id);primeDomainVerificationsLPw(user.id);}}// 在启动期间尽早为系统用户准备存储,因为像SettingsProvider和systemUI这样的核心系统应用程序无法等待用户启动final int storageFlags;if (StorageManager.isFileEncryptedNativeOrEmulated()) {storageFlags = StorageManager.FLAG_STORAGE_DE;} else {storageFlags = StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE;}// 如果是在OTA之后首次启动,并且正常启动,那需要清除代码缓存目录,但不清除应用程序配置文件if (mIsUpgrade && !mOnlyCore) {Slog.i(TAG, "Build fingerprint changed; clearing code caches");for (int i = 0; i < mSettings.mPackages.size(); i++) {final PackageSetting ps = mSettings.mPackages.valueAt(i);if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, ps.volumeUuid)) {// No apps are running this early, so no need to freezeclearAppDataLIF(ps.pkg, UserHandle.USER_ALL, FLAG_STORAGE_DE | FLAG_STORAGE_CE | FLAG_STORAGE_EXTERNAL | Installer.FLAG_CLEAR_CODE_CACHE_ONLY
| Installer.FLAG_CLEAR_APP_DATA_KEEP_ART_PROFILES);}}ver.fingerprint = Build.FINGERPRINT;}// 安装Android-Q前的非系统应用程序在Luncher中隐藏他们的图标if (!mOnlyCore && mIsPreQUpgrade) {Slog.i(TAG, "Whitelisting all existing apps to hide their icons");int size = mSettings.mPackages.size();for (int i = 0; i < size; i++) {final PackageSetting ps = mSettings.mPackages.valueAt(i);if ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0) {continue;}ps.disableComponentLPw(PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME,UserHandle.USER_SYSTEM);}}// 仅在权限或其他默认配置更新后清除mPromoteSystemApps = false;// All the changes are done during package scanning.// 所有变化都在扫描过程中完成ver.databaseVersion = Settings.CURRENT_DATABASE_VERSION;// can downgrade to reader// 降级读取

4.2.7 阶段5:BOOT_PROGRESS_PMS_READY

主要工作有:

(1)创建PackageInstallerService对象

(2)GC回收内存

源码:

// 第五阶段
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY,SystemClock.uptimeMillis());// PermissionController 包含磨人的授予和角色管理,所以它是一个核心系统的关键部分
mRequiredPermissionControllerPackage = getRequiredPermissionControllerLPr();.......updateInstantAppInstallerLocked(null);// 阅读并更新dex文件的用法
// 在 PM init结束时执行此操作,以便所有程序包都已协调其数据目录
// 此时知道了包的代码路径,因此可以验证磁盘文件并构建内部缓存
// 使用文件预计很小,因为与其他活动(例如包扫描)相比,加载和验证它应该花费相当小的时间
final Map<Integer, List<PackageInfo>> userPackages = new HashMap<>();
for (int userId : userIds) {userPackages.put(userId, getInstalledPackages(/*flags*/ 0, userId).getList());
}
mDexManager.load(userPackages);
if (mIsUpgrade) {FrameworkStatsLog.write(FrameworkStatsLog.BOOT_TIME_EVENT_DURATION_REPORTED,BOOT_TIME_EVENT_DURATION__EVENT__OTA_PACKAGE_MANAGER_INIT_TIME,SystemClock.uptimeMillis() - startTime);}
} // synchronized (mLock)
} // synchronized (mInstallLock)......        // 打开应用之后,及时的回收处理
Runtime.getRuntime().gc();

4.3 dex 优化

检查是否需要去更新Packages并进行dex优化,如果没有OTA升级、没有大版本升级、没有清楚过dalvik虚拟机的缓存,可以去更新packages。

上面我们在分析PKMS启动过程的时候说到了七个步骤,其中第五步就是dex文件优化。

这一过程的调用流程如下:

4.3.1 [PackageManagerService.java] updatePackagesIfNeeded()

说明:

检查是否需要更新Packages并进行dex优化,如果没有OTA升级,没有大版本升级、没有清除过dalvik虚拟机的缓存可以去更新Packages。

更新Packages的优先级:core app > system app > other app,调用 performDexOptUpgrade()进行更新。

源码:

    @Overridepublic void updatePackagesIfNeeded() {// 只有system或是root用户才有权限请求 package updateenforceSystemOrRoot("Only the system can request package update");// (1) 判断有没有进行OTA升级,我们需要在OTA后重新获取boolean causeUpgrade = isDeviceUpgrading();// (2) 是否是第一次启动或是系统大版本升级boolean causeFirstBoot = isFirstBoot() || mIsPreNUpgrade;// (3) 判断是否清除过Dalvik虚拟机的缓存。我们需要在删除缓存后重新提取,因为AoT-ed文件将过期boolean causePrunedCache = VMRuntime.didPruneDalvikCache();// (4) 如果上面三个判断都没有,那么就不做任何操作if (!causeUpgrade && !causeFirstBoot && !causePrunedCache) {return;}List<PackageSetting> pkgSettings;synchronized (mLock) {// 按照Package的优先级进行排序,core app > system app > other apppkgSettings = PackageManagerServiceUtils.getPackagesForDexopt(mSettings.mPackages.values(), this);}// 记录开始的时间final long startTime = System.nanoTime();// 执行performDexOptUpgrade方法,完成dex优化final int[] stats = performDexOptUpgrade(pkgs, mIsPreNUpgrade /* showDialog */,causeFirstBoot ? REASON_FIRST_BOOT : REASON_BOOT,false /* bootComplete */);......}

4.3.2  [PackageManagerService.java] performDexOptUpgrade()

说明:判断是否需要对Package进行更新,如果需要更新那么按照优先级完成dex优化,最终调用Installer的dexopt()进行dex优化。

源码:

private int[] performDexOptUpgrade(List<AndroidPackage> pkgs, boolean showDialog,final int compilationReason, boolean bootComplete) {// 循环取出Packages,进行优化for (AndroidPackage pkg : pkgs) {numberOfPackagesVisited++;boolean useProfileForDexopt = false;// 第一次启动或是OTA升级之后并且是系统应用才会进行odexif ((isFirstBoot() || isDeviceUpgrading()) && pkg.isSystem()) {.......}......            // 最终是调用mInstaller.dexopt 完成优化的,instal的守护进程Installer安装器和Installed通信int primaryDexOptStaus = performDexOptTraced(new DexoptOptions(pkg.getPackageName(),pkgCompilationReason,dexoptFlags));switch (primaryDexOptStaus) {case PackageDexOptimizer.DEX_OPT_PERFORMED:numberOfPackagesOptimized++;                // odex优化完成的应用break;case PackageDexOptimizer.DEX_OPT_SKIPPED:numberOfPackagesSkipped++;                   // 跳过的应用break;case PackageDexOptimizer.DEX_OPT_FAILED:numberOfPackagesFailed++;                   // 失败的应用break;default:Log.e(TAG, "Unexpected dexopt return code " + primaryDexOptStaus);break;}}return new int[] { numberOfPackagesOptimized, numberOfPackagesSkipped,numberOfPackagesFailed };}

4.3.3 [PackageManagerService.java] performDexOptInternal()

源码:

    // 在给定的包上执行dex优化。如果dexopt没有失败则返回true,// 也就是说,对于给定的过滤器,现在就可以认定位包是最新的private int performDexOptInternal(DexoptOptions options) {.....try {synchronized (mInstallLock) {// 执行performDexOptInternalWithDependenciesLIreturn performDexOptInternalWithDependenciesLI(p, pkgSetting, options);}} finally {Binder.restoreCallingIdentity(callingId);}}

在perormDexOptInternalWithDependenciesLI方法中,最终调用了PackageDexOptimizer.performDexOpt方法。

4.3.4 [PackageDexOptimizer.java] performDexOpt()

源码:

    // 在指定包的所有代码路径和库上执行dexoptint performDexOpt(AndroidPackage pkg, @NonNull PackageSetting pkgSetting,String[] instructionSets, CompilerStats.PackageStats packageStats,PackageDexUsage.PackageUseInfo packageUseInfo, DexoptOptions options) {......       synchronized (mInstallLock) {final long acquireTime = acquireWakeLockLI(pkg.getUid());try {// 执行performDexoptLIreturn performDexOptLI(pkg, pkgSetting, instructionSets,packageStats, packageUseInfo, options);} finally {releaseWakeLockLI(acquireTime);}}}

该方法作用就是在指定包的所有代码路径和库上执行dexopt。最终会继续调用performDexOptLI方法。

4.3.5 [PackageDexOptimizer.java] performDexOptLI()

源码:

    // 对给定包的所有路径执行dexopt// 假装mInstallLock已经被持有@GuardedBy("mInstallLock")private int performDexOptLI(AndroidPackage pkg, @NonNull PackageSetting pkgSetting,String[] targetInstructionSets, CompilerStats.PackageStats packageStats,PackageDexUsage.PackageUseInfo packageUseInfo, DexoptOptions options) {......for (String dexCodeIsa : dexCodeInstructionSets) {// 执行dexoptPath方法int newResult = dexOptPath(pkg, pkgSetting, path, dexCodeIsa, compilerFilter,profileUpdated, classLoaderContexts[i], dexoptFlags, sharedGid,packageStats, options.isDowngrade(), profileName, dexMetadataPath,options.getCompilationReason());// The end result is://  - FAILED if any path failed,//  - PERFORMED if at least one path needed compilation,//  - SKIPPED when all paths are up to dateif ((result != DEX_OPT_FAILED) && (newResult != DEX_OPT_SKIPPED)) {result = newResult;}}}return result;}

对于dexOptPath方法,就是在属于当前包的路径上执行dexopt操作。并最终调到了Installer.dexopt()。

4.4 磁盘维护

磁盘维护是在SystemServer.startOtherServices()方法中,通过调用PKMS的performFstrimIfNeeded()方法开始的。

调用过程如下:

4.4.1 [PackageManagerService.java] performFstrimIfNeeded()

说明:主要是执行磁盘清理工作,释放磁盘空间

源码:

// 磁盘守护。主要是执行磁盘清理工作,释放磁盘空间@Overridepublic void performFstrimIfNeeded() {// 只有system或是root用户才有权限请求fstrimenforceSystemOrRoot("Only the system can request fstrim");// 在其他事情之前,看看我们是否需要fstrimtry {// 获取StorageManager对象IStorageManager sm = PackageHelper.getStorageManager();if (sm != null) {boolean doTrim = false;// 获取执行FSTRIM时间间隔,默认是3天,可以通过setting provider更改这个时间final long interval = android.provider.Settings.Global.getLong(mContext.getContentResolver(),android.provider.Settings.Global.FSTRIM_MANDATORY_INTERVAL,DEFAULT_MANDATORY_FSTRIM_INTERVAL);if (interval > 0) {final long timeSinceLast = System.currentTimeMillis() - sm.lastMaintenance();if (timeSinceLast > interval) {doTrim = true;     // 如果时间超过了三天就进行磁盘清理Slog.w(TAG, "No disk maintenance in " + timeSinceLast+ "; running immediately");}}if (doTrim) {final boolean dexOptDialogShown;synchronized (mLock) {dexOptDialogShown = mDexOptDialogShown;}// 如果不是第一次启动,显示一个提示框if (!isFirstBoot() && dexOptDialogShown) {try {ActivityManager.getService().showBootMessage(mContext.getResources().getString(R.string.android_upgrading_fstrim), true);} catch (RemoteException e) {}}// 这里的sm是 StorageManagerService,发送消息H_FSTRIM给Handler,然后向vold发送fstrim命令sm.runMaintenance();}} else {Slog.e(TAG, "storageManager service unavailable!");}} catch (RemoteException e) {// Can't happen; StorageManagerService is local}}

4.4.2 [StorageManagerService] runMaintenance()

源码:

@Override
public void runMaintenance() {enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);runIdleMaintenance(null);
}void runIdleMaintenance(Runnable callback) {mHandler.sendMessage(mHandler.obtainMessage(H_FSTRIM, callback));
}class StorageManagerServiceHandler extends Handler {public StorageManagerServiceHandler(Looper looper) {super(looper);}@Overridepublic void handleMessage(Message msg) {switch (msg.what) {......case H_FSTRIM: {......    // 调用fstrim方法fstrim(0, null);break;}}

4.4.3 [StorageManagerService] fstrim()

源码:

    @Overridepublic void fstrim(int flags, IVoldTaskListener listener) {// 基于块的检查点进行进行fstrim。因此,如果检查点正在进行(OTA后的第一次启动),// 我们跳过空闲维护,并确保最后的fstrim时间仍然更新。如果基于文件的检查点,// 我们将运行空闲维护(GC fstrim),而不考虑检查点的状态。if (!needsCheckpoint() || !supportsBlockCheckpoint()) {// 最终会执行到vold进程的fstrimmVold.fstrim(flags, new IVoldTaskListener.Stub() {.......}

4.5 PKMS 准备就绪

[PackageManagerService.java] systemReady()

说明:systemReady主要完成的是默认授权和更新package的信息,通知在等待pms的一些组件

源码:

@Overridepublic void systemReady() {//只有system或是root用户才有权限 声称system已经readyenforceSystemOrRoot("Only the system can claim the system is ready");ContentObserver co = new ContentObserver(mHandler) {。。。。。。};// 注册一个监听co.onChange(true);......synchronized (mLock) {ArrayList<PreferredActivity> removed = new ArrayList<>();for (int i=0; i<mSettings.mPreferredActivities.size(); i++) {PreferredIntentResolver pir = mSettings.mPreferredActivities.valueAt(i);removed.clear();for (PreferredActivity pa : pir.filterSet()) {if (!mComponentResolver.isActivityDefined(pa.mPref.mComponent)) {removed.add(pa);}}// 移除不存在的先前用户设置保存的优先选择的activity组件if (removed.size() > 0) {for (int r=0; r<removed.size(); r++) {PreferredActivity pa = removed.get(r);Slog.w(TAG, "Removing dangling preferred activity: "+ pa.mPref.mComponent);pir.removeFilter(pa);}mSettings.writePackageRestrictionsLPr(mSettings.mPreferredActivities.keyAt(i));     // 写入到文件中}}}mUserManager.systemReady();         // 多用户服务 systemReady// Now that we've scanned all packages, and granted any default// permissions, ensure permissions are updated. Beware of dragons if you// try optimizing this.synchronized (mLock) {// 更新权限信息mPermissionManager.updateAllPermissions(StorageManager.UUID_PRIVATE_INTERNAL, false);final PermissionPolicyInternal permissionPolicyInternal =mInjector.getPermissionPolicyInternal();permissionPolicyInternal.setOnInitializedCallback(userId -> {// The SDK updated case is already handled when we run during the ctor.synchronized (mLock) {mPermissionManager.updateAllPermissions(StorageManager.UUID_PRIVATE_INTERNAL, false);}});}// Watch for external volumes that come and go over time//注意随时间变化的外部存储设备final StorageManager storage = mInjector.getStorageManager();storage.registerListener(mStorageListener);mInstallerService.systemReady();mPackageDexOptimizer.systemReady();mInjector.getStorageManagerInternal().addExternalStoragePolicy(new StorageManagerInternal.ExternalStorageMountPolicy() {@Overridepublic int getMountMode(int uid, String packageName) {if (Process.isIsolated(uid)) {return Zygote.MOUNT_EXTERNAL_NONE;}if (checkUidPermission(READ_EXTERNAL_STORAGE, uid) == PERMISSION_DENIED) {return Zygote.MOUNT_EXTERNAL_DEFAULT;}if (checkUidPermission(WRITE_EXTERNAL_STORAGE, uid) == PERMISSION_DENIED) {return Zygote.MOUNT_EXTERNAL_READ;}return Zygote.MOUNT_EXTERNAL_WRITE;}@Overridepublic boolean hasExternalStorage(int uid, String packageName) {return true;}});// Now that we're mostly running, clean up stale users and apps// 清除过期的userId和appmUserManager.reconcileUsers(StorageManager.UUID_PRIVATE_INTERNAL);reconcileApps(StorageManager.UUID_PRIVATE_INTERNAL);mPermissionManager.systemReady();if (mInstantAppResolverConnection != null) {mContext.registerReceiver(new BroadcastReceiver() {@Overridepublic void onReceive(Context context, Intent intent) {mInstantAppResolverConnection.optimisticBind();mContext.unregisterReceiver(this);}}, new IntentFilter(Intent.ACTION_BOOT_COMPLETED));}IntentFilter overlayFilter = new IntentFilter(Intent.ACTION_OVERLAY_CHANGED);overlayFilter.addDataScheme("package");mContext.registerReceiver(new BroadcastReceiver() {@Overridepublic void onReceive(Context context, Intent intent) {if (intent == null) {return;}Uri data = intent.getData();if (data == null) {return;}String packageName = data.getSchemeSpecificPart();if (packageName == null) {return;}AndroidPackage pkg = mPackages.get(packageName);if (pkg == null) {return;}sendPackageChangedBroadcast(pkg.getPackageName(),true /* dontKillApp */,new ArrayList<>(Collections.singletonList(pkg.getPackageName())),pkg.getUid(),Intent.ACTION_OVERLAY_CHANGED);}}, overlayFilter);mModuleInfoProvider.systemReady();// Installer service might attempt to install some packages that have been staged for// installation on reboot. Make sure this is the last component to be call since the// installation might require other components to be ready.mInstallerService.restoreAndApplyStagedSessionIfNeeded();mExistingPackages = null;}

至此,PKMS的启动过程就分析完了。

Android 11.0 PackageManagerService(一)工作原理和启动流程相关推荐

  1. Android 10.0 PackageManagerService(一)工作原理及启动流程-[Android取经之路]

    摘要:PackageManagerService是Android系统核心服务之一,在Android中的非常重要,主要负责APK.jar包等的管理. 阅读本文大约需要花费50分钟. 文章的内容主要还是从 ...

  2. Android 10.0 PackageManagerService(三)APK扫描-[Android取经之路]

    摘要:上一节讲解了PKMS的 权限扫描,扫描/system/etc/permissions中的xml,存入相应的结构体中,供之后权限管理使用. 这一节主要来讲讲APK的扫描. 阅读本文大约需要花费15 ...

  3. Android 10.0 PackageManagerService(二)权限扫描-[Android取经之路]

    摘要:PackageManagerService在systemReady()后,进行了/system/etc/permissions中的各种xml进行扫描,进行相应的权限存储,供以后使用 阅读本文大约 ...

  4. android camera(二):摄像头工作原理、s5PV310 摄像头接口(CAMIF)

    关键词: android  camera CMM 模组 camera参数  CAMIF 平台信息: 内核: linux 系统: android 平台:S5PV310(samsung exynos 42 ...

  5. Android 11.0 Settings源码分析 - 主界面加载

    Android 11.0 Settings源码分析 - 主界面加载 本篇主要记录AndroidR Settings源码主界面加载流程,方便后续工作调试其流程. Settings代码路径: packag ...

  6. Android 11.0 无源码apk授予QUERY_ALL_PACKAGES权限

    目录 1.概述 2.Android 11.0 无源码apk授予QUERY_ALL_PACKAGES权限的核心类 3.Android 11.0 无源码apk授予QUERY_ALL_

  7. Android 11.0 支持exfat格式

    点滴积累,记录自己的成长. 最近系统要支持exfat格式,参考了大佬们的帖子之后,终于搞定了. 由于之前都是Android.mk,自己系统中使用的Android.bp,而且要求以模块的形式调用对应的k ...

  8. Android 11.0 锁屏页面时钟显示样式

    一.需求分析 Android 11.0系统默认的锁屏时钟 年月日 显示的样式不符合需求,现在需要定制化.下图是系统默认的时间样式. 目标是改成这样: 二.核心代码路径 frameworks/base/ ...

  9. MTK Android 11.0:充电低电指示灯会被未读消息信号灯灭掉,无优先级控制。

    MTK Android 11.0:充电低电指示灯会被未读消息信号灯灭掉,无优先级控制: 1.电池充电.低电状态提示(红绿双色).(LIGHT_ID_BATTERY) 小于15%时: A 正在充电 亮红 ...

最新文章

  1. Linux 虚拟内存和物理内存的理解【转】
  2. 戴上脑机接口头盔,他用大脑跟别人「说话」
  3. 【Envi风暴】Envi5.4经典安装图文教程
  4. 【渝粤题库】国家开放大学2021春1443卫生信息与文献检索题目
  5. Android开发:5-1、Adopter
  6. Linux常用的分区方案及目录结构
  7. 爱心的数学函数方程_高中数学中的函数与方程思想
  8. openjudge7624:山区建小学
  9. xml转java代码_java 中xml转换为Bean实例解析(纯代码)
  10. 太拼了!张朝阳的一张作息表刷爆朋友圈
  11. 辅助驾驶功能开发-功能规范篇(05)-智能限速辅助SLA
  12. python实现数据库的增删改查
  13. C# wpf 实现简单的颜色板
  14. Python交叉排序 计蒜客例题
  15. windows开源会有linux吗,微软真的要开源Windows?小伙伴惊呆了!
  16. 高桥盾react和boost_热门对比丨React pk Boost,你更偏向哪一双?
  17. 量化初级 -- akshare获得股票代码,最简策略
  18. Sporadic IOException: Failed to persist config
  19. Ymir初级使用教程
  20. 智能卡操作(非接触CPU卡又称智能卡) 总结

热门文章

  1. linux windows10双系统安装教程,【笔记】windows10安装linux双系统教程(可能是现今最简单方法)...
  2. 如何用Sonic云真机打王者
  3. 三相PFC程序30KW充电桩 采用目前最常用的TI DSP数字信号处理芯片
  4. 大数据分析助迈凯轮车队角逐F1
  5. LeetCode/LintCode 题解丨一周爆刷双指针:最小范围
  6. 【26天高效学完Java编程】Day03:Java中的运算符与流程控制语句的基本概念与实操
  7. vue-3d-model:一个展示三维模型的 Vue 组件
  8. 计算机连接不上蓝牙鼠标,图文教您win7系统蓝牙鼠标连接不上的处理方法
  9. You Can’t Future-Proof Solutions
  10. (iOS)仿App第一步:获取App素材