Android 11.0 PackageManagerService(一)工作原理和启动流程
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(一)工作原理和启动流程相关推荐
- Android 10.0 PackageManagerService(一)工作原理及启动流程-[Android取经之路]
摘要:PackageManagerService是Android系统核心服务之一,在Android中的非常重要,主要负责APK.jar包等的管理. 阅读本文大约需要花费50分钟. 文章的内容主要还是从 ...
- Android 10.0 PackageManagerService(三)APK扫描-[Android取经之路]
摘要:上一节讲解了PKMS的 权限扫描,扫描/system/etc/permissions中的xml,存入相应的结构体中,供之后权限管理使用. 这一节主要来讲讲APK的扫描. 阅读本文大约需要花费15 ...
- Android 10.0 PackageManagerService(二)权限扫描-[Android取经之路]
摘要:PackageManagerService在systemReady()后,进行了/system/etc/permissions中的各种xml进行扫描,进行相应的权限存储,供以后使用 阅读本文大约 ...
- android camera(二):摄像头工作原理、s5PV310 摄像头接口(CAMIF)
关键词: android camera CMM 模组 camera参数 CAMIF 平台信息: 内核: linux 系统: android 平台:S5PV310(samsung exynos 42 ...
- Android 11.0 Settings源码分析 - 主界面加载
Android 11.0 Settings源码分析 - 主界面加载 本篇主要记录AndroidR Settings源码主界面加载流程,方便后续工作调试其流程. Settings代码路径: packag ...
- Android 11.0 无源码apk授予QUERY_ALL_PACKAGES权限
目录 1.概述 2.Android 11.0 无源码apk授予QUERY_ALL_PACKAGES权限的核心类 3.Android 11.0 无源码apk授予QUERY_ALL_
- Android 11.0 支持exfat格式
点滴积累,记录自己的成长. 最近系统要支持exfat格式,参考了大佬们的帖子之后,终于搞定了. 由于之前都是Android.mk,自己系统中使用的Android.bp,而且要求以模块的形式调用对应的k ...
- Android 11.0 锁屏页面时钟显示样式
一.需求分析 Android 11.0系统默认的锁屏时钟 年月日 显示的样式不符合需求,现在需要定制化.下图是系统默认的时间样式. 目标是改成这样: 二.核心代码路径 frameworks/base/ ...
- MTK Android 11.0:充电低电指示灯会被未读消息信号灯灭掉,无优先级控制。
MTK Android 11.0:充电低电指示灯会被未读消息信号灯灭掉,无优先级控制: 1.电池充电.低电状态提示(红绿双色).(LIGHT_ID_BATTERY) 小于15%时: A 正在充电 亮红 ...
最新文章
- Linux 虚拟内存和物理内存的理解【转】
- 戴上脑机接口头盔,他用大脑跟别人「说话」
- 【Envi风暴】Envi5.4经典安装图文教程
- 【渝粤题库】国家开放大学2021春1443卫生信息与文献检索题目
- Android开发:5-1、Adopter
- Linux常用的分区方案及目录结构
- 爱心的数学函数方程_高中数学中的函数与方程思想
- openjudge7624:山区建小学
- xml转java代码_java 中xml转换为Bean实例解析(纯代码)
- 太拼了!张朝阳的一张作息表刷爆朋友圈
- 辅助驾驶功能开发-功能规范篇(05)-智能限速辅助SLA
- python实现数据库的增删改查
- C# wpf 实现简单的颜色板
- Python交叉排序 计蒜客例题
- windows开源会有linux吗,微软真的要开源Windows?小伙伴惊呆了!
- 高桥盾react和boost_热门对比丨React pk Boost,你更偏向哪一双?
- 量化初级 -- akshare获得股票代码,最简策略
- Sporadic IOException: Failed to persist config
- Ymir初级使用教程
- 智能卡操作(非接触CPU卡又称智能卡) 总结
热门文章
- linux windows10双系统安装教程,【笔记】windows10安装linux双系统教程(可能是现今最简单方法)...
- 如何用Sonic云真机打王者
- 三相PFC程序30KW充电桩 采用目前最常用的TI DSP数字信号处理芯片
- 大数据分析助迈凯轮车队角逐F1
- LeetCode/LintCode 题解丨一周爆刷双指针:最小范围
- 【26天高效学完Java编程】Day03:Java中的运算符与流程控制语句的基本概念与实操
- vue-3d-model:一个展示三维模型的 Vue 组件
- 计算机连接不上蓝牙鼠标,图文教您win7系统蓝牙鼠标连接不上的处理方法
- You Can’t Future-Proof Solutions
- (iOS)仿App第一步:获取App素材