简述
PackageManagerService(简称 PKMS),是 Android 系统中核心服务之一,负责应用程序的安装,卸载,信息查询,等工作。
PKMS服务也是通过binder进行通信,IPackageManager.aidl由工具转换后自动生成binder的服务端IPackageManager.Stub和客户端IPackageManager.Stub.Proxy,具体关系如图:
- Binder服务端:PackageManagerService继承于IPackageManager.Stub;
- Binder客户端:ApplicationPackageManager(简称APM)的成员变量
mPM
继承于IPackageManager.Stub.Proxy; 本身APM是继承于PackageManager对象。
PKMS 启动过程
我们知道PKMS 是Android 的核心服务之一,他在我们SystemServer进程中启动。
SystemServer启动PKMS: 先是在SystemServer.startBootstrapServices()函数中启动PKMS服务, 再调用startOtherServices()函数中对dex优化,磁盘管理功能,让PKMS进入systemReady状态。
核心步骤
SystemServer.startBootstrapServices()
private void startBootstrapServices(@NonNull TimingsTraceAndSlog t) {
//1.启动Installer服务
Installer installer = mSystemServiceManager.startService(Installer.class);
//2.获取设备是否加密(手机设置密码),如果设备加密了,则只解析"core"应用
String cryptState = VoldProperties.decrypt().orElse("");
if (ENCRYPTING_STATE.equals(cryptState)) {
mOnlyCore = true;
} else if (ENCRYPTED_STATE.equals(cryptState)) {
mOnlyCore = true;
}
//3.调用PKMS main方法初始化PackageManagerService,其中调用PackageManagerService() 构造函数创建了PKMS对象
mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
//PKMS是否是第一次启动
mFirstBoot = mPackageManagerService.isFirstBoot();
//4.如果设备没有加密,操作它。管理A/B OTA dexopting。
if (!mOnlyCore) {
boolean disableOtaDexopt = SystemProperties.getBoolean("config.disable_otadexopt",
false);
if (!disableOtaDexopt) {
OtaDexoptService.main(mSystemContext, mPackageManagerService);
}
}
}
复制代码
startBootstrapServices()首先启动Installer服务,也就是安装器,随后判断当前的设备是否处于加密 状态,如果是则只是解析核心应用,接着调用PackageManagerService的静态方法main来创建pms对象
SystemServer.startOtherServices()
private void startOtherServices() {
if (!mOnlyCore) {
//5.如果设备没有加密,执行performDexOptUpgrade,完成dex优化;
mPackageManagerService.updatePackagesIfNeeded();
}
//6.最终执行performFstrim,完成磁盘维护
mPackageManagerService.performFstrimIfNeeded();
//7.PKMS准备就绪
mPackageManagerService.systemReady();
}
复制代码
- 启动Installer服务
- 获取设备是否加密(手机设置密码),如果设备加密了,则只解析"core"应用
- 调用PKMS main方法初始化PackageManagerService,其中调用PackageManagerService() 构造函数创建了PKMS对象
- 如果设备没有加密,操作它。管理A/B OTA dexopting。
- 如果设备没有加密,执行performDexOptUpgrade,完成dex优化
- 最终执行performFstrim,完成磁盘维护
- PKMS准备就绪
PKMS.main()
public static PackageManagerService main(Context context, Installer installer,
boolean factoryTest, boolean onlyCore) {
//1.检查Package编译相关系统属性
PackageManagerServiceCompilerMapping.checkProperties();
//2.调用PackageManagerService构造方法
PackageManagerService m = new PackageManagerService(injector, onlyCore, factoryTest);
//3.启用部分应用服务于多用户场景
m.installWhitelistedSystemPackages();
//4.往ServiceManager中注册”package”和”package_native”。
ServiceManager.addService("package", m);
final PackageManagerNative pmn = m.new PackageManagerNative();
ServiceManager.addService("package_native", pmn);
return m;
}
复制代码
main函数主要工作:
- 检查Package编译相关系统属性
- 调用PackageManagerService构造方法
- 启用部分应用服务于多用户场景
- 往ServiceManager中注册”package”和”package_native”。
PKMS初始化 (构造方法) 细节可忽略
PKMS构造方法,整体描述图:
PKMS的构造函数中由两个重要的锁(mInstallLock、mPackages)和5个阶段构成
public PackageManagerService(Injector injector, boolean onlyCore, boolean factoryTest) {
PackageManager.disableApplicationInfoCache();
PackageManager.disablePackageInfoCache();
// Avoid invalidation-thrashing by preventing cache invalidations from causing property
// writes if the cache isn't enabled yet. We re-enable writes later when we're
// done initializing.
PackageManager.corkPackageInfoCache();
final TimingsTraceAndSlog t = new TimingsTraceAndSlog(TAG + "Timing",
Trace.TRACE_TAG_PACKAGE_MANAGER);
mPendingBroadcasts = new PendingPackageBroadcasts();
mInjector = injector;
mInjector.bootstrap(this);
mLock = injector.getLock();
mInstallLock = injector.getInstallLock();
LockGuard.installLock(mLock, LockGuard.INDEX_PACKAGES);
//阶段一
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START,
SystemClock.uptimeMillis());
//....
// CHECKSTYLE:OFF IndentationCheck
synchronized (mInstallLock) {
// writer
synchronized (mLock) {
//...
//阶段二
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,
startTime);
//...
//阶段三
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,
SystemClock.uptimeMillis());
//...
//阶段四
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END,
SystemClock.uptimeMillis());
//...
//阶段五
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY,
SystemClock.uptimeMillis());
} // synchronized (mLock)
} // synchronized (mInstallLock)
// CHECKSTYLE:ON IndentationCheck
//...
//gc
Runtime.getRuntime().gc();
}
复制代码
两个重要的锁(mInstallLock、mLock)、mPackages
mInstallLock、mLock:用来保护所有安装apk的访问权限,此操作通常涉及繁重的磁盘数据读写等操作,并且是单线程操作,故有时候会处理很慢, 此锁不会在已经持有mLock锁的情况下加锁,反之,在已经持有mInstallLock锁的情况下,立即获取mLock是安全的
mLock = injector.getLock();
mInstallLock = injector.getInstallLock();
复制代码
mPackages:用来解析内存中所有apk的package信息及相关状态。
final ArrayMap<String, AndroidPackage> mPackages = new ArrayMap<>();
复制代码
阶段一(BOOT_PROGRESS_PMS_START)
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START,
SystemClock.uptimeMillis());
mContext = injector.getContext();
mFactoryTest = factoryTest;// 一般为false,即非工厂生产模式
mOnlyCore = onlyCore;//标记是否只加载核心服务
//1.构造 DisplayMetrics ,保存分辨率等相关信息
mMetrics = new DisplayMetrics();
//2.创建Installer对象,与installd交互
mInstaller = injector.getInstaller();
// 将本地服务PackageManagerInternalImpl公开到LocalServices容器中
mPmInternal = new PackageManagerInternalImpl();
LocalServices.addService(PackageManagerInternal.class, mPmInternal);
//多用户管理服务
mUserManager = injector.getUserManagerService();
mComponentResolver = injector.getComponentResolver();
//3.获取权限管理服务mPermissionManager 和 mPermissionManagerService
mPermissionManager = injector.getPermissionManagerServiceInternal();//内部服务
mPermissionManagerService = (IPermissionManager) ServiceManager.getService("permissionmgr");//binder 注册的服务
//4.创建Settings对象
mSettings = injector.getSettings();
//添加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);
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);
//ART虚拟机管理服务
mArtManagerService = new ArtManagerService(mContext, this, mInstaller, mInstallLock);
mMoveCallbacks = new MoveCallbacks(FgThread.get().getLooper());
mViewCompiler = new ViewCompiler(mInstallLock, mInstaller);
//获取默认分辨率
getDefaultDisplayMetrics(mInjector.getDisplayManager(), mMetrics);
//6.创建SystemConfig实例,获取系统配置信息,配置共享lib库
SystemConfig systemConfig = SystemConfig.getInstance();
//创建提供服务/数据的子组件。这里的顺序很重要,使用到了两个重要的同步锁:mInstallLock、 mPackages
// CHECKSTYLE:OFF IndentationCheck
synchronized (mInstallLock) {
// writer
synchronized (mLock) {
//7.创建PackageManager的handler线程,循环处理外部安装相关消息。
mHandlerThread = new ServiceThread(TAG,
Process.THREAD_PRIORITY_BACKGROUND, true /*allowIo*/);
mHandlerThread.start();
//应用handler
mHandler = new PackageHandler(mHandlerThread.getLooper());
//进程记录handler
mProcessLoggingHandler = new ProcessLoggingHandler();
//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);
}
//添加依赖的依赖lib库
long undefinedVersion = SharedLibraryInfo.VERSION_UNDEFINED;
for (int i = 0; i < builtInLibCount; i++) {
String name = libConfig.keyAt(i);
SystemConfig.SharedLibraryEntry entry = libConfig.valueAt(i);
final int dependencyCount = entry.dependencies.length;
for (int j = 0; j < dependencyCount; j++) {
final SharedLibraryInfo dependency =
getSharedLibraryInfoLPr(entry.dependencies[j], undefinedVersion);
if (dependency != null) {
getSharedLibraryInfoLPr(name, undefinedVersion).addDependency(dependency);
}
}
}
//读取安装相关SELinux策略
SELinuxMMAC.readInstallPolicy();
// 返回栈加载
FallbackCategoryProvider.loadFallbacks();
//读取并解析/data/system下的XML文件,下面详解
mFirstBoot = !mSettings.readLPw(mInjector.getUserManagerInternal().getUsers(false));
// 清理代码路径不存在的孤立软件包
final int packageSettingCount = mSettings.mPackages.size();
for (int i = packageSettingCount - 1; i >= 0; i--) {
PackageSetting ps = mSettings.mPackages.valueAt(i);
if (!isExternal(ps) && (ps.codePath == null || !ps.codePath.exists())
&& mSettings.getDisabledSystemPkgLPr(ps.name) != null) {
mSettings.mPackages.removeAt(i);
mSettings.enableSystemPackageLPw(ps.name);
}
}
// 如果不是首次启动,也不是CORE应用,则拷贝预编译的DEX文件
if (!mOnlyCore && mFirstBoot) {
requestCopyPreoptedFiles();
}
...
复制代码
先看Settings 构造函数
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;
//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");
}
复制代码
readLPw()会扫描下面5个文件
- "/data/system/packages.xml" 所有安装app信息
- "/data/system/packages-backup.xml" 所有安装app信息之备份的信息记录
- "/data/system/packages.list" 记录应用的数据信息
- "/data/system/packages-stopped.xml" 所有强制停止app信息
- "/data/system/packages-stopped-backup.xml" 所有强制停止app信息之备份的信息记录
个文件共分为三组,简单的作用描述如下:
-
packages.xml:PKMS 扫描完目标文件夹后会创建该文件。当系统进行程序安装、卸载和更新等操作时,均 会更新该文件。该文件保存了系统中与 package 相关的一些信息。
-
packages.list:描述系统中存在的所有非系统自带的 APK 的信息。当这些程序有变动时,PKMS 就会更 新该文件。
-
packages-stopped.xml:从系统自带的设置程序中进入应用程序页面,然后在选择强制停止 (ForceStop)某个应用时,系统会将该应用的相关信息记录到此文件中。也就是该文件保存系统中被用户强 制停止的 Package 的信息。
这些目录的指向,都在Settings中的构造函数完成, 如下所示,得到目录后调用readLPw()进行扫描
Settings.readLPw()
扫码文件
boolean readLPw(@NonNull List<UserInfo> users) {
FileInputStream str = null;
if (str == null) {
str = new FileInputStream(mSettingsFilename);
}
//解析"/data/system/packages.xml"
XmlPullParser parser = Xml.newPullParser();
parser.setInput(str, StandardCharsets.UTF_8.name());
int type;
while ((type = parser.next()) != XmlPullParser.START_TAG
&& type != XmlPullParser.END_DOCUMENT) {
;
}
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);
} else if (tagName.equals("preferred-packages")) {
// no longer used.
} else if (tagName.equals("preferred-activities")) {
// Upgrading from old single-user implementation;
// these are the preferred activities for user 0.
readPreferredActivitiesLPw(parser, 0);
} else if (tagName.equals(TAG_PERSISTENT_PREFERRED_ACTIVITIES)) {
// TODO: check whether this is okay! as it is very
// similar to how preferred-activities are treated
readPersistentPreferredActivitiesLPw(parser, 0);
} else if (tagName.equals(TAG_CROSS_PROFILE_INTENT_FILTERS)) {
// TODO: check whether this is okay! as it is very
// similar to how preferred-activities are treated
readCrossProfileIntentFiltersLPw(parser, 0);
} //...
}
str.close();
//...
return true;
}
复制代码
阶段二(BOOT_PROGRESS_PMS_SYSTEM_SCAN_START)
- 从init.rc中获取环境变量BOOTCLASSPATH和SYSTEMSERVERCLASSPATH;
- 对于旧版本升级的情况,将安装时获取权限变更为运行时申请权限;
- 扫描system/vendor/product/odm/oem等目录的priv-app、app、overlay包;
- 清除安装时临时文件以及其他不必要的信息。
synchronized (mInstallLock) {
// writer
synchronized (mLock) {
long startTime = SystemClock.uptimeMillis();
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,
startTime);
//从init.rc中获取环境变量BOOTCLASSPATH和 SYSTEMSERVERCLASSPATH;
final String bootClassPath = System.getenv("BOOTCLASSPATH");
final String systemServerClassPath = System.getenv("SYSTEMSERVERCLASSPATH");
// 获取system/framework目录
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之前版本升级上来的情况,需像首次启动一样处理package
mIsPreNUpgrade = mIsUpgrade && ver.sdkVersion < Build.VERSION_CODES.N;
mIsPreNMR1Upgrade = mIsUpgrade && ver.sdkVersion < Build.VERSION_CODES.N_MR1;
mIsPreQUpgrade = mIsUpgrade && ver.sdkVersion < Build.VERSION_CODES.Q;
// Save the names of pre-existing packages prior to scanning, so we can determine
// which system packages are completely new due to an upgrade.
// 在扫描之前保存预先存在的系统package的名称,这样我们可以决定哪些系统packages有更新的预期
if (isDeviceUpgrading()) {
mExistingPackages = new ArraySet<>(mSettings.mPackages.size());
for (PackageSetting ps : mSettings.mPackages.values()) {
mExistingPackages.add(ps.name);
}
}
// 准备解析package的缓存
mCacheDir = preparePackageParserCache();
// 设置flag,而不在扫描安装时更改文件路径
int scanFlags = SCAN_BOOTING | SCAN_INITIAL;
final int systemParseFlags = mDefParseFlags | PackageParser.PARSE_IS_SYSTEM_DIR;
final int systemScanFlags = scanFlags | SCAN_AS_SYSTEM;
//扫描以下路径:/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-app
//......scanDirTracedLI方法扫描
final List<String> possiblyDeletedUpdatedSystemApps = new ArrayList<>();
final List<String> stubSystemApps = new ArrayList<>();
// 删掉不存在的package
if (!mOnlyCore) {
final 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();
// 如果不是系统应用,则不被允许disable
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)) {
removePackageLI(scannedPkg, true);
mExpectingBetter.put(ps.name, ps.codePath);
}
continue;
}
//...
}
}
}
}
复制代码
阶段三(BOOT_PROGRESS_PMS_DATA_SCAN_START)
对于不仅仅解析核心应用的情况下,还处理data目录的应用信息,及时更新,祛除不必要的数据。
if (!mOnlyCore) {
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,SystemClock.uptimeMillis());
scanDirTracedLI(sAppInstallDir, 0, scanFlags | SCAN_REQUIRE_KNOWN, 0,packageParser, executorService);
// 移除通过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;
// remove from the disabled system list; do this first so any future
// scans of this package are performed without this state
mSettings.removeDisabledSystemPackageLPw(packageName);
//...
}
// 确保期望在userdata分区上显示的所有系统应用程序实际显示
// 如果从未出现过,需要回滚以恢复系统版本
for (int i = 0; i < mExpectingBetter.size(); i++) {
final String packageName = mExpectingBetter.keyAt(i);
if (!mPackages.containsKey(packageName)) {
final File scanFile = mExpectingBetter.valueAt(i);
//...
mSettings.enableSystemPackageLPw(packageName);
try {
//扫描APK
scanPackageTracedLI(scanFile, reparseFlags, rescanFlags, 0, null);
} catch (PackageManagerException e) {
}
}
}
// 解压缩并安装任何存根系统应用程序。必须最后执行此操作以确保替换或禁用所有存根
installSystemStubPackages(stubSystemApps, scanFlags);
//...
}
// 获取storage manager包名
mStorageManagerPackage = getStorageManagerPackageName();
// 解决受保护的action过滤器。只允许setup wizard(开机向导)为这些action设置高优先级过滤器
mSetupWizardPackage = getSetupWizardPackageNameImpl();
// 更新客户端以确保持有正确的共享库路径
updateAllSharedLibrariesLocked(null, null, Collections.unmodifiableMap(mPackages));
// 读取并更新要保留的package的上次使用时间
mPackageUsage.read(mSettings.mPackages);
mCompilerStats.read();
复制代码
阶段四(BOOT_PROGRESS_PMS_SCAN_END)
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END, SystemClock.uptimeMillis());
//sdk版本变更,更新权限;
// 如果自上次启动以来,平台SDK已改变,则需要重新授予应用程序权限以捕获出现的任何新权限
final boolean sdkUpdated = (ver.sdkVersion != mSdkVersion);
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升级后首次启动,清除不必要的缓存数据;
//如果是在OTA之后首次启动,并且正常启动,那需要清除代码缓存目录,但不清除应用程序配置文件
if (mIsUpgrade && !mOnlyCore) {
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 freeze
clearAppDataLIF(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前的非系统应用程序在Launcher中隐藏他们的图标
if (!mOnlyCore && mIsPreQUpgrade) {
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);
}
}
// 仅在权限或其它默认配置更新后清除
mExistingSystemPackages.clear();
mPromoteSystemApps = false;
// 所有变更均在扫描过程中完成
ver.databaseVersion = Settings.CURRENT_DATABASE_VERSION;
//降级去读取
//更新package.xml
mSettings.writeLPr();
复制代码
- sdk版本变更,更新权限;
- OTA升级后首次启动,清除不必要的缓存数据;
- 权限等默认项更新完后,清理相关数据;
- 更新package.xml
阶段五(BOOT_PROGRESS_PMS_READY)
GC回收内存 和一些细节而已
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY, SystemClock.uptimeMillis());
//...
//PermissionController 主持 缺陷许可证的授予和角色管理,所以这是核心系统的一个关键部分。
mRequiredPermissionControllerPackage = getRequiredPermissionControllerLPr();
mSettings.setPermissionControllerVersion(
getPackageInfo(mRequiredPermissionControllerPackage, 0,
UserHandle.USER_SYSTEM).getLongVersionCode());
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)
// CHECKSTYLE:ON IndentationCheck
// 打开应用之后,及时回收处理
Runtime.getRuntime().gc();
// 上面的初始扫描在持有mPackage锁的同时对installd进行了多次调用
mInstaller.setWarnIfHeld(mLock);
复制代码
APK扫描
在PKMS初始化的阶段二会调用PKMS.scanDirTracedLI()
扫描某个目录的apk文件
- PKMS.scanDirTracedLI 首先加入了一些systtrace的日志追踪,然后调用scanDirLI()进行分析
- PKMS.scanDirLI
PKMS.scanDirLI
使用了ParallelPackageParser的对象,ParallelPackageParser是一个队列,我们这 里手机所有系统的apk,然后从这些队列里面取出apk,再调用PackageParser 解析进行解析:
private void scanDirLI(File scanDir, int parseFlags, int scanFlags, long currentTime,
PackageParser2 packageParser, ExecutorService executorService) {
final File[] files = scanDir.listFiles();
if (ArrayUtils.isEmpty(files)) {
return;
}
// parallelPackageParser是一个队列,收集系统 apk 文件,
// 然后从这个队列里面一个个取出 apk ,调用 PackageParser 解析
ParallelPackageParser parallelPackageParser =
new ParallelPackageParser(packageParser, executorService);
// Submit files for parsing in parallel
int fileCount = 0;
for (File file : files) {
// 是Apk文件,或者是目录
final boolean isPackage = (isApkFile(file) || file.isDirectory())
&& !PackageInstallerService.isStageName(file.getName());
if (!isPackage) {
// Ignore entries which are not packages
continue;
}
// 把APK信息存入parallelPackageParser中的对象mQueue,PackageParser()函数 赋给了队列中的pkg成员
parallelPackageParser.submit(file, parseFlags);
fileCount++;
}
// 从parallelPackageParser中取出队列apk的信息
for (; fileCount > 0; fileCount--) {
ParallelPackageParser.ParseResult parseResult = parallelPackageParser.take();
Throwable throwable = parseResult.throwable;
int errorCode = PackageManager.INSTALL_SUCCEEDED;
if (throwable == null) {
// TODO(toddke): move lower in the scan chain
// Static shared libraries have synthetic package names
if (parseResult.parsedPackage.isStaticSharedLibrary()) {
renameStaticSharedLibraryPackage(parseResult.parsedPackage);
}
try {
//调用 scanPackageChildLI 方法扫描一个特定的 apk 文件
//该类的实例代表一个 APK 文件,所以它就是和 apk 文件对应的数据结构。
addForInitLI(parseResult.parsedPackage, parseFlags, scanFlags,
currentTime, null);
} //...
} //...
//如果是非系统 apk 并且解析失败
if ((scanFlags & SCAN_AS_SYSTEM) == 0
&& errorCode != PackageManager.INSTALL_SUCCEEDED) {
// 非系统 Package 扫描失败,删除文件
removeCodePathLI(parseResult.scanFile);
}
}
}
复制代码
ParallelPackageParser.submit
把扫描路径中的APK等内容,放入队列mQueue, 并把parsePackage() 赋给ParseResult,用于PKMS.scanDirLI()
里parallelPackageParser.take()
的调用.
public void submit(File scanFile, int parseFlags) {
mExecutorService.submit(() -> {
ParseResult pr = new ParseResult();
try {
pr.scanFile = scanFile;
//把parsePackage()赋值ParseResult,用于后面的调用
pr.parsedPackage = parsePackage(scanFile, parseFlags);
} //...
try {
//把扫描路径中的APK等内容,放入队列mQueue
mQueue.put(pr);
} //...
});
}
复制代码
PackageParser.parsePackage
通过 PackageParser.parsePackage 进行apk解析:
如果传入的packageFile是目录, 调用parseClusterPackage()解析
如果传入的packageFile是APK文件, 调用parseMonolithicPackage()解析
public Package parsePackage(File packageFile, int flags, boolean useCaches)
throws PackageParserException {
if (packageFile.isDirectory()) {
return parseClusterPackage(packageFile, flags);
} else {
return parseMonolithicPackage(packageFile, flags);
}
}
复制代码
- PackageParser.parseClusterPackage
- PackageParser.parseBaseApk
- PackageParser.parseMonolithicPackage
- PackageParser.parseBaseApk
两个方法都会进入PackageParser.parseBaseApk 来解析APK
PackageParser.parseBaseApk
private Package parseBaseApk(File apkFile, AssetManager assets, int flags)
throws PackageParserException {
final String apkPath = apkFile.getAbsolutePath();
//...
XmlResourceParser parser = null;
try {
final int cookie = assets.findCookieForPath(apkPath);
if (cookie == 0) {
throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
"Failed adding asset path: " + apkPath);
}
// 获得一个 XML 资源解析对象,该对象解析的是 APK 中的 AndroidManifest.xml 文件。
parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
final Resources res = new Resources(assets, mMetrics, null);
final String[] outError = new String[1];
//再调用重载函数parseBaseApk()最终到parseBaseApkCommon(),解析 AndroidManifest.xml 后得到一个Package对象
final Package pkg = parseBaseApk(apkPath, res, parser, flags, outError);
pkg.setVolumeUuid(volumeUuid);
pkg.setApplicationVolumeUuid(volumeUuid);
pkg.setBaseCodePath(apkPath);
pkg.setSigningDetails(SigningDetails.UNKNOWN);
return pkg;
} //...
}
复制代码
PackageParser.parseBaseApkCommon
parseBaseApk -----> parseBaseApkCommon , parseBaseApk省略了
PackageParser.parseBaseApkCommon 从AndroidManifest.xml中获取标签名,解析标签中的各个item的内容,存入Package对象中 例如:获取标签 "application"、"permission"、"package"、"manifest"
private Package parseBaseApkCommon(Package pkg, Set<String> acceptedTags, Resources res,
XmlResourceParser parser, int flags, String[] outError) throws XmlPullParserException,
IOException {
TypedArray sa = res.obtainAttributes(parser,
com.android.internal.R.styleable.AndroidManifest);
//拿到AndroidManifest.xml 中的sharedUserId, 一般情况下有“android.uid.system”等信息
String str = sa.getNonConfigurationString(
com.android.internal.R.styleable.AndroidManifest_sharedUserId, 0);
if (str != null && str.length() > 0) {
//...
//赋值SharedUserId
pkg.mSharedUserId = str.intern();
pkg.mSharedUserLabel = sa.getResourceId(
com.android.internal.R.styleable.AndroidManifest_sharedUserLabel, 0);
}
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
&& (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
//从AndroidManifest.xml中获取标签名
String tagName = parser.getName();
//如果读到AndroidManifest.xml中的tag是"application",执行parseBaseApplication()进行解析
if (tagName.equals(TAG_APPLICATION)) {
if (foundApp) {
//...
}
foundApp = true;
// 解析"application"的信息,赋值给pkg, 这里解析到的是"application" <application 包含了 四大组件
if (!parseBaseApplication(pkg, res, parser, flags, outError)) {
return null;
}
} else if (tagName.equals(TAG_PERMISSION_GROUP)) {
//进行"permission group"的解析
if (!parsePermissionGroup(pkg, flags, res, parser, outError)) {
return null;
}
} else if (tagName.equals(TAG_PERMISSION)) {
//进行"permission"的解析
if (!parsePermission(pkg, res, parser, outError)) {
return null;
}
} //...
}
//...
return pkg;
}
复制代码
上面解析AndroidManifest.xml,会得到 "application"、"overlay"、"permission"、"uses- permission" 等信息
我们下面就针对"application"进行展开分析一下,进入 PackageParser.parseBaseApplication()函数
PackageParser.parseBaseApplication
private boolean parseBaseApplication(Package owner, Resources res,
XmlResourceParser parser, int flags, String[] outError)
throws XmlPullParserException, IOException {
//...
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
&& (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
//...
// 获取"application"子标签的标签内容
String tagName = parser.getName();
if (tagName.equals("activity")) {//如果标签是"activity", 解析Activity的信息,把activity加入 Package对象
Activity a = parseActivity(owner, res, parser, flags, outError, cachedArgs, false,
owner.baseHardwareAccelerated);
if (a == null) {
mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
return false;
}
hasActivityOrder |= (a.order != 0);
owner.activities.add(a);
} else if (tagName.equals("receiver")) {// 如果标签是"receiver",获取 receiver信息,加入Package对象
Activity a = parseActivity(owner, res, parser, flags, outError, cachedArgs,
true, false);
if (a == null) {
mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
return false;
}
hasReceiverOrder |= (a.order != 0);
owner.receivers.add(a);
} else if (tagName.equals("service")) {// 如果标签是"service",获取service信 息,加入Package对象
Service s = parseService(owner, res, parser, flags, outError, cachedArgs);
if (s == null) {
mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
return false;
}
hasServiceOrder |= (s.order != 0);
owner.services.add(s);
} else if (tagName.equals("provider")) {// 如果标签是"provider",获取 provider信息,加入Package对象
Provider p = parseProvider(owner, res, parser, flags, outError, cachedArgs);
if (p == null) {
mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
return false;
}
owner.providers.add(p);
} //...
}
//...
return true;
}
复制代码
在 PackageParser 扫描完一个 APK 后,此时系统已经根据该 APK 中 AndroidManifest.xml,创建了一 个完整的 Package 对象
总结
第一步:扫描APK,解析AndroidManifest.xml文件,得到清单文件各个标签内容
第二步:解析清单文件到的信息由 Package 保存。从该类的成员变量可看出,和 Android 四大组件相关 的信息分别由 activites、receivers、providers、services 保存,由于一个 APK 可声明多个组件,因此 activites 和 receivers等均声明为 ArrayList
APK的安装
安装步骤一: 把Apk的信息通过IO流的形式写入到PackageInstaller.Session中
安装步骤二: 调用PackageInstaller.Session的commit方法, 把Apk的信息交给PKMS处理
安装步骤三: 进行Apk的Copy操作, 进行安装
安装的三步走,整体描述图:
PackageInstallerActivity.bindUi
点击一个apk后,会弹出安装界面,点击确定按钮后,会进入PackageInstallerActivity 的 bindUi() 中 的mAlert点击事件, 弹出的安装界面底部显示的是一个diaglog,主要由bindUi构成,上面有 ”取消“ 和 ” 安装“ 两个按钮,点击安装后 调用startInstall()进行安装:
private void bindUi() {
mAlert.setIcon(mAppSnippet.icon);
mAlert.setTitle(mAppSnippet.label);
mAlert.setView(R.layout.install_content_view);
mAlert.setButton(DialogInterface.BUTTON_POSITIVE, getString(R.string.install),
(ignored, ignored2) -> {
if (mOk.isEnabled()) {
if (mSessionId != -1) {
mInstaller.setPermissionsResult(mSessionId, true);
finish();
} else {
//进行APK安装
startInstall();
}
}
}, null);
mAlert.setButton(DialogInterface.BUTTON_NEGATIVE, getString(R.string.cancel),
(ignored, ignored2) -> {
// Cancel and finish
setResult(RESULT_CANCELED);
if (mSessionId != -1) {
//如果mSessionId存在,执行setPermissionsResult()完成取消安装
mInstaller.setPermissionsResult(mSessionId, false);
}
finish();
}, null);
setupAlert();
mOk = mAlert.getButton(DialogInterface.BUTTON_POSITIVE);
mOk.setEnabled(false);
}
复制代码
PackageInstallerActivity.startInstall
startInstall方法组装了一个Intent,并跳转到 InstallInstalling 这个Activity,并关闭掉当前的 PackageInstallerActivity。InstallInstalling主要用于向包管理器发送包的信息并处理包管理的回调:
private void startInstall() {
Intent newIntent = new Intent();
//设置Intent中的class为 InstallInstalling,用来进行Activity跳转
newIntent.setClass(this, InstallInstalling.class);
//...
startActivity(newIntent);
finish();
}
复制代码
InstallInstalling.onCreate
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ApplicationInfo appInfo = getIntent()
.getParcelableExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO);
mPackageURI = getIntent().getData();
if ("package".equals(mPackageURI.getScheme())) {
//...
} else {
//根据mPackageURI创建一个对应的File
final File sourceFile = new File(mPackageURI.getPath());
//...
//第一步.如果savedInstanceState不为null,获取此前保存的mSessionId和 mInstallId,其中mSessionId是安装包的会话id,mInstallId是等待的安装事件id
if (savedInstanceState != null) {
mSessionId = savedInstanceState.getInt(SESSION_ID);
mInstallId = savedInstanceState.getInt(INSTALL_ID);
// Reregister for result; might instantly call back if result was delivered while
// activity was destroyed
try {
// 第二步.根据mInstallId向InstallEventReceiver注册一个观察者,launchFinishBasedOnResult会接收到安装事件的回调,
//无论安装成功或者失败都会关闭当前的Activity(InstallInstalling)。如果savedInstanceState为null,代码的逻辑也是类似的
InstallEventReceiver.addObserver(this, mInstallId,
this::launchFinishBasedOnResult);
} //...
} else {
// 第三步.创建SessionParams,它用来代表安装会话的参数,组装params
PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(
PackageInstaller.SessionParams.MODE_FULL_INSTALL);
//...
// 第四步.根据mPackageUri对包(APK)进行轻量级的解析,并将解析的参数赋值给 SessionParams
File file = new File(mPackageURI.getPath());
try {
PackageParser.PackageLite pkg = PackageParser.parsePackageLite(file, 0);
params.setAppPackageName(pkg.packageName);
params.setInstallLocation(pkg.installLocation);
params.setSize(
PackageHelper.calculateInstalledSize(pkg, false, params.abiOverride));
} //...
try {
// 第五步.向InstallEventReceiver注册一个观察者返回一个新的mInstallId,
//其中InstallEventReceiver继承自BroadcastReceiver,用于接收安装事件并回调给EventResultPersister。
mInstallId = InstallEventReceiver
.addObserver(this, EventResultPersister.GENERATE_NEW_ID,
this::launchFinishBasedOnResult);
} //...
try {
// 第六步.PackageInstaller的createSession方法内部会通过IPackageInstaller与PackageInstallerService进行进程间通信,
//最终调用的是PackageInstallerService的createSession方法来创建并返回mSessionId
mSessionId = getPackageManager().getPackageInstaller().createSession(params);
} //...
}
mCancelButton = mAlert.getButton(DialogInterface.BUTTON_NEGATIVE);
mSessionCallback = new InstallSessionCallback();
}
}
复制代码
以上第六步是重点 PackageInstaller 的 createSession()内部会通过IPackageInstaller与 PackageInstallerService进行进程间通信,最终调用的是PackageInstallerService的createSession方法 来创建并返回mSessionId
InstallInstalling.onResume
protected void onResume() {
super.onResume();
// This is the first onResume in a single life of the activity
if (mInstallingTask == null) {
PackageInstaller installer = getPackageManager().getPackageInstaller();
// 获取sessionInfo
PackageInstaller.SessionInfo sessionInfo = installer.getSessionInfo(mSessionId);
if (sessionInfo != null && !sessionInfo.isActive()) {
// 创建内部类InstallingAsyncTask的对象,调用execute(),最终进入
onPostExecute()
mInstallingTask = new InstallingAsyncTask();
mInstallingTask.execute();
} //...
}
}
复制代码
InstallInstalling.onResume方法中,调用onPostExecute()方法,将APK的信息通过IO流的形式写入 到PackageInstaller.Session中
InstallInstalling.InstallingAsyncTask 会在onPostExecute
中 调用PackageInstaller.Session的commit方法,进行安装
PackageInstaller.Session.commit()
最总会执行PackageInstallerSession.commit()
PackageInstallerSession.commit
public void commit(@NonNull IntentSender statusReceiver, boolean forTransfer) {
//...
//调用markAsSealed
if (!markAsSealed(statusReceiver, forTransfer)) {
return;
}
//...
//向Handler发送一个类型为MSG_STREAM_VALIDATE_AND_COMMIT的消息
dispatchStreamValidateAndCommit();
}
复制代码
dispatchStreamValidateAndCommit()
=> mHandler.obtainMessage(MSG_STREAM_VALIDATE_AND_COMMIT).sendToTarget()
=> mHandlerCallback.handleMessage()
=> handleStreamValidateAndCommit()
PackageInstallerSession.handleStreamValidateAndCommit
private void handleStreamValidateAndCommit() {
PackageManagerException unrecoverableFailure = null;
// This will track whether the session and any children were validated and are ready to
// progress to the next phase of install
//判断当前seesion和子seesion都已经准备就绪,准备进入下一步install 步骤
boolean allSessionsReady = false;
try {
allSessionsReady = streamValidateAndCommit();
} catch (PackageManagerException e) {
unrecoverableFailure = e;
}
if (isMultiPackage()) {
int childCount = mChildSessionIds.size();
ArrayList<PackageInstallerSession> nonFailingSessions = new ArrayList<>(childCount);
for (int i = childCount - 1; i >= 0; --i) {
final int childSessionId = mChildSessionIds.keyAt(i);
try {
PackageInstallerSession session = mSessionProvider.getSession(childSessionId);
//遍历所有子session
allSessionsReady &= session.streamValidateAndCommit();
nonFailingSessions.add(session);
} catch (PackageManagerException e) {
allSessionsReady = false;
if (unrecoverableFailure == null) {
unrecoverableFailure = e;
}
}
}
//...
}
if (!allSessionsReady) {
return;
}
//进入下一步Install
mHandler.obtainMessage(MSG_INSTALL).sendToTarget();
}
复制代码
mHandlerCallback.handleMessage()
=> handleInstall()
=> installNonStagedLocked()
=> PackageManagerService.installStage()
PackageManagerService.installStage
发送 INIT_COPY 的Handler 消息
void installStage(ActiveInstallSession activeInstallSession) {
//创建了类型为INIT_COPY的消息
final Message msg = mHandler.obtainMessage(INIT_COPY);
//创建InstallParams,它对应于包的安装数据
final InstallParams params = new InstallParams(activeInstallSession);
params.setTraceMethod("installStage").setTraceCookie(System.identityHashCode(params));
msg.obj = params;
Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "installStage",
System.identityHashCode(msg.obj));
Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "queueInstall",
System.identityHashCode(msg.obj));
//将InstallParams通过消息发送出去。
mHandler.sendMessage(msg);
}
void installStage(List<ActiveInstallSession> children)
throws PackageManagerException {
final Message msg = mHandler.obtainMessage(INIT_COPY);
final MultiPackageInstallParams params =
new MultiPackageInstallParams(UserHandle.ALL, children);
params.setTraceMethod("installStageMultiPackage")
.setTraceCookie(System.identityHashCode(params));
msg.obj = params;
Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "installStageMultiPackage",
System.identityHashCode(msg.obj));
Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "queueInstall",
System.identityHashCode(msg.obj));
mHandler.sendMessage(msg);
}
复制代码
mHandler在PKMS初始化阶段一里面创建的,所以后续流程进入PKMS.PackageHandler.handleMessage
=> PKMS.PackageHandler.doHandleMessage
PKMS.PackageHandler.doHandleMessage
void doHandleMessage(Message msg) {
switch (msg.what) {
case INIT_COPY: {
HandlerParams params = (HandlerParams) msg.obj;
if (params != null) {
//执行APK拷贝动作,这里会执行到 final void startCopy()
params.startCopy();
}
break;
} //...
}
}
复制代码
PKMS.HandlerParams.startCopy
final void startCopy() {
handleStartCopy();
handleReturnCode();
}
abstract void handleStartCopy();
abstract void handleReturnCode();
复制代码
进入startCopy
后调用两个抽象方法,PKMS.HandlerParams 的派生类分别是 PKMS.MultiPackageInstallParams (多个包安装)和 InstallParams (单个包安装)不过最终进入到 PKMS.InstallParams.handleStartCopy()
和 PKMS.InstallParams.handleReturnCode()
PKMS.InstallParams.handleReturnCode
void handleReturnCode() {
if (mVerificationCompleted
&& mIntegrityVerificationCompleted && mEnableRollbackCompleted) {
//....
//拷贝APK
if (mRet == PackageManager.INSTALL_SUCCEEDED) {
mRet = mArgs.copyApk();
}
//...
//进入加载流程
processPendingInstall(mArgs, mRet);
}
}
复制代码
PKMS.InstallParams.copyApk()
=> PKMS.InstallParams.doCopyApk()
=> PackageManagerServiceUtils.copyPackage()
=> PackageManagerServiceUtils.copyFile()
通过文件流的操作,把APK拷贝到/data/app等目录
PKMS.processPendingInstall
文件拷贝到指定目录之后,接着就是安装解析APK
private void processPendingInstall(final InstallArgs args, final int currentStatus) {
if (args.mMultiPackageInstallParams != null) {
//多个安装包需要打包,最后还是执行processInstallRequestsAsync()
args.mMultiPackageInstallParams.tryProcessInstallRequest(args, currentStatus);
} else {
//设置安装参数
PackageInstalledInfo res = createPackageInstalledInfo(currentStatus);
//创建一个新线程,处理安装参数,进行安装
processInstallRequestsAsync(
res.returnCode == PackageManager.INSTALL_SUCCEEDED,
Collections.singletonList(new InstallRequest(args, res)));
}
}
复制代码
PKMS.processInstallRequestsAsync
mHandler.post 进行安装
private void processInstallRequestsAsync(boolean success,
List<InstallRequest> installRequests) {
mHandler.post(() -> {
if (success) {
for (InstallRequest request : installRequests) {
//1.如果之前安装失败,清除无用信息
request.args.doPreInstall(request.installResult.returnCode);
}
synchronized (mInstallLock) {
//2. installPackagesTracedLI 是安装过程的核心方法,然后调用 installPackagesLI 进行安装。
installPackagesTracedLI(installRequests);
}
for (InstallRequest request : installRequests) {
//3.如果之前安装失败,清除无用信息
request.args.doPostInstall(
request.installResult.returnCode, request.installResult.uid);
}
}
for (InstallRequest request : installRequests) {
restoreAndPostInstall(request.args.user.getIdentifier(), request.installResult,
new PostInstallData(request.args, request.installResult, null));
}
});
}
复制代码
PKMS.installPackagesLI
private void installPackagesLI(List<InstallRequest> requests) {
//...
try {
for (InstallRequest request : requests) {
final PrepareResult prepareResult;
try {
// 环节一.Prepare 准备:分析任何当前安装状态,分析包并对其进行初始验证。
prepareResult =
preparePackageLI(request.args, request.installResult);
} //....
//...
try {
// 环节二.Scan 扫描:考虑到prepare中收集的上下文,询问已分析的包。
final ScanResult result = scanPackageTracedLI(
prepareResult.packageToScan, prepareResult.parseFlags,
prepareResult.scanFlags, System.currentTimeMillis(),
request.args.user, request.args.abiOverride);
//...
} //...
}
// 环节三.Reconcile 调和:在彼此的上下文和当前系统状态中验证扫描的包,以确保安装成功。
ReconcileRequest reconcileRequest = new ReconcileRequest(preparedScans, installArgs,
installResults,
prepareResults,
mSharedLibraries,
Collections.unmodifiableMap(mPackages), versionInfos,
lastStaticSharedLibSettings);
synchronized (mLock) {
Map<String, ReconciledPackage> reconciledPackages;
try {
reconciledPackages = reconcilePackagesLocked(
reconcileRequest, mSettings.mKeySetManagerService);
} //...
try {
commitRequest = new CommitRequest(reconciledPackages,
mUserManager.getUserIds());
//环节四.Commit 提交:提交所有扫描的包并更新系统状态。这是安装流中唯一可以修改系统状态的 地方,必须在此阶段之前确定所有可预测的错误。
commitPackagesLocked(commitRequest);
success = true;
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
}
// 环节五.完成APK的安装
executePostCommitSteps(commitRequest);
} //...
}
复制代码
PKMS.executePostCommitSteps
安装APK,并为新的代码路径准备应用程序配置文件,并再次检查是否需要 dex优化
如果是直接安装新包,会为新的代码路径准备应用程序配置文件
如果是替换安装:其主要过程为更新设置,清除原有的某些APP数据,重新生成相关的app数据目录等 步骤,同时要区分系统应用替换和非系统应用替换。而安装新包:则直接更新设置,生成APP数据即 可。
private void executePostCommitSteps(CommitRequest commitRequest) {
final ArraySet<IncrementalStorage> incrementalStorages = new ArraySet<>();
for (ReconciledPackage reconciledPkg : commitRequest.reconciledPackages.values()) {
//...
//准备AppData 进行安装
prepareAppDataAfterInstallLIF(pkg);
//如果需要替换安装,则需要清楚原有的APP数据
if (reconciledPkg.prepareResult.clearCodeCache) {
clearAppDataLIF(pkg, UserHandle.USER_ALL, FLAG_STORAGE_DE | FLAG_STORAGE_CE
| FLAG_STORAGE_EXTERNAL | Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
}
//...
//为新的代码路径准备应用程序配置文件。这需要在调用dexopt之前完成,以便任何安装时配 置文件都可以用于优化。
mArtManagerService.prepareAppProfiles(
pkg,
resolveUserIds(reconciledPkg.installArgs.user.getIdentifier()),
/* updateReferenceProfileContent= */ true);
final boolean performDexopt =
(!instantApp || Global.getInt(mContext.getContentResolver(),
Global.INSTANT_APP_DEXOPT_ENABLED, 0) != 0)
&& !pkg.isDebuggable()
&& (!onIncremental);
if (performDexopt) {
//...
//4)执行dex优化
mPackageDexOptimizer.performDexOpt(pkg, realPkgSetting,
null /* instructionSets */,
getOrCreateCompilerPackageStats(pkg),
mDexManager.getPackageUseInfoOrDefault(packageName),
dexoptOptions);
}
BackgroundDexOptService.notifyPackageChanged(packageName);
notifyPackageChangeObserversOnUpdate(reconciledPkg);
}
NativeLibraryHelper.waitForNativeBinariesExtraction(incrementalStorages);
}
复制代码
我们的安装流程会经过下面的跳转PKMS.prepareAppDataAfterInstallLIF()
=> PKMS.prepareAppDataLIF()
=> PKMS.prepareAppDataLeafLIF()
PKMS.prepareAppDataLeafLIF
private void prepareAppDataLeafLIF(AndroidPackage pkg, int userId, int flags) {
//...
try {
//调用Installd守护进程的入口
ceDataInode = mInstaller.createAppData(volumeUuid, packageName, userId, flags,
appId, seInfo, pkg.getTargetSdkVersion());
} //...
//...
prepareAppDataContentsLeafLIF(pkg, ps, userId, flags);
}
复制代码
Installer.createAppData
收尾工作,安装完成后,更新设置,更新安装锁等:
public long createAppData(String uuid, String packageName, int userId, int flags, int appId,
String seInfo, int targetSdkVersion) throws InstallerException {
if (!checkBeforeRemote()) return -1;
try {
// mInstalld 为IInstalld的对象,即通过Binder调用到 进程installd,最终调用 installd的createAppData()
// Installd 是由init 进程孵化出来的进程
return mInstalld.createAppData(uuid, packageName, userId, flags, appId, seInfo,
targetSdkVersion);
} catch (Exception e) {
throw InstallerException.from(e);
}
}
复制代码
总结
整个安装的原理就是将apk文件安装到对应的目录下。
PKMS权限扫描
PackageManagerService 需求对 /system/etc/permissions中的各种xml进行扫描,进行相应的权限存储,以便后面权限申请使用。
那么权限扫描又是在什么时候执行的呢?
我们知道在PackageManagerService的构造函数中,会获取SystemConfig的单例对象,SystemConfig 在实例化的时候就会进行权限扫描。
SystemConfig
public static SystemConfig getInstance() {
synchronized (SystemConfig.class) {
if (sInstance == null) {
sInstance = new SystemConfig();
}
return sInstance;
}
}
SystemConfig() {
try {
readAllPermissions();
} //...
}
private void readAllPermissions() {
// Read configuration from system
readPermissions(Environment.buildPath(
Environment.getRootDirectory(), "etc", "sysconfig"), ALLOW_ALL);
// Read configuration from the old permissions dir
readPermissions(Environment.buildPath(
Environment.getRootDirectory(), "etc", "permissions"), ALLOW_ALL);
// Vendors are only allowed to customize these
int vendorPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_PRIVAPP_PERMISSIONS
| ALLOW_ASSOCIATIONS;
if (Build.VERSION.FIRST_SDK_INT <= Build.VERSION_CODES.O_MR1) {
// For backward compatibility
vendorPermissionFlag |= (ALLOW_PERMISSIONS | ALLOW_APP_CONFIGS);
}
readPermissions(Environment.buildPath(
Environment.getVendorDirectory(), "etc", "sysconfig"), vendorPermissionFlag);
readPermissions(Environment.buildPath(
Environment.getVendorDirectory(), "etc", "permissions"), vendorPermissionFlag);
String vendorSkuProperty = SystemProperties.get(VENDOR_SKU_PROPERTY, "");
if (!vendorSkuProperty.isEmpty()) {
String vendorSkuDir = "sku_" + vendorSkuProperty;
readPermissions(Environment.buildPath(
Environment.getVendorDirectory(), "etc", "sysconfig", vendorSkuDir),
vendorPermissionFlag);
readPermissions(Environment.buildPath(
Environment.getVendorDirectory(), "etc", "permissions", vendorSkuDir),
vendorPermissionFlag);
}
// Allow ODM to customize system configs as much as Vendor, because /odm is another
// vendor partition other than /vendor.
int odmPermissionFlag = vendorPermissionFlag;
readPermissions(Environment.buildPath(
Environment.getOdmDirectory(), "etc", "sysconfig"), odmPermissionFlag);
readPermissions(Environment.buildPath(
Environment.getOdmDirectory(), "etc", "permissions"), odmPermissionFlag);
String skuProperty = SystemProperties.get(SKU_PROPERTY, "");
if (!skuProperty.isEmpty()) {
String skuDir = "sku_" + skuProperty;
readPermissions(Environment.buildPath(
Environment.getOdmDirectory(), "etc", "sysconfig", skuDir), odmPermissionFlag);
readPermissions(Environment.buildPath(
Environment.getOdmDirectory(), "etc", "permissions", skuDir),
odmPermissionFlag);
}
//...
}
复制代码
SystemConfig 是一个单例的设计模式,在创建SystemConfig的时候自动会通过调用SystemConfig.readAllPermissions()
读取所有权限,SystemConfig.readPermissions()
扫描指定文件。
SystemConfig.readPermissionsFromXml
SystemConfig.readPermissions()
=>SystemConfig.readPermissionsFromXml()
解析xml的标签节点,存入mGlobalGids、mPermissions、mSystemPermissions等成员变量中.
private void readPermissionsFromXml(File permFile, int permissionFlag) {
FileReader permReader = null;
try {
permReader = new FileReader(permFile);
} //...
final boolean lowRam = ActivityManager.isLowRamDeviceStatic();
try {
XmlPullParser parser = Xml.newPullParser();
parser.setInput(permReader);
//...
while (true) {
//...
String name = parser.getName();
switch (name) {
case "group": { //解析 group 标签,前面介绍的 XML 文件中没有单独使用该标签的地方
if (allowAll) {
String gidStr = parser.getAttributeValue(null, "gid");
if (gidStr != null) {
int gid = android.os.Process.getGidForName(gidStr);
mGlobalGids = appendInt(mGlobalGids, gid);
}
} else {
logNotAllowedInPartition(name, permFile, parser);
}
XmlUtils.skipCurrentTag(parser);
} break;
case "permission": {//解析 permission 标签
if (allowPermissions) {
String perm = parser.getAttributeValue(null, "name");
if (perm == null) {
XmlUtils.skipCurrentTag(parser);
break;
}
perm = perm.intern();
readPermission(parser, perm);//调用 readPermission 处理,存入mPermissions
} else {
logNotAllowedInPartition(name, permFile, parser);
XmlUtils.skipCurrentTag(parser);
}
} break;
}
}
} //...
}
复制代码
签名
静默安装,签名,须知内容:
// 如果想实现,静默安装,就需要设置好UID,只有设置这个UID后,才有安装的权限
// 但是这个UID必须要求有系统的[签名], 而这个系统的[签名]是属于各大手机厂商的机密,也 意味着非常的坑爹
// 如果是系统厂商要做这种静默安装, 那就是非常容易的事情, 因为系统厂商可以轻而易举的拿 到 系统的[签名]
mSettings.addSharedUserLPw("android.uid.system", Process.SYSTEM_UID,
ApplicationInfo.FLAG_SYSTEM,ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
mSettings.addSharedUserLPw("android.uid.phone", RADIO_UID,
ApplicationInfo.FLAG_SYSTEM,ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
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);
复制代码
总结
Android系统启动时,会启动(应用程序管理服务器PKMS),此服务负责扫描系统中特定的目录,寻找里面的APK格式的文件,并对这些文件进行解析,然后得到应用程序相关信息,最后完成应用程序的安装
PKMS在安装应用过程中,会全面解析应用程序的AndroidManifest.xml文件,来得到Activity, Service, BroadcastReceiver, ContextProvider 等信息,在结合PKMS服务就可以在OS中正常的使用 应用程序了
在Android系统中,系统启动时由SystemServer启动PKMS服务,启动该服务后会执行应用程序的安装过程