Android PKMS核心分析

PackageManagerService是android系统核心服务之一,它主要负责的工作如下:
一. 解析AndroidManifest.xml文件,解析清单文件中的所有节点信息。
二. 扫描.apk文件,安装系统应用,本地应用等。
三. 管理本地应用,主要有:安装、卸载、应用信息查询等。

概述

Android系统启动时,会启动(应用程序管理服务器PKMS),此服务负责扫描系统中特定的目录,寻找里面的APK格式的文件,并对这些文件进行解析,然后得到应用程序相关信息,最后完成应用程序的安装

PKMS在安装应用过程中, 会全面解析应用程序的AndroidManifest.xml文件, 来得到Activity, Service, BroadcastReceiver, ContextProvider 等信息, 在结合PKMS服务就可以在OS中正常的使用应用程序了

在Android系统中, 系统启动时由SystemServer启动PKMS服务, 启动该服务后会执行应用程序的安装过程

PKMS架构设计

类图关系

image

继承关系

image

注意:
客户端可通过Context.getPackageManager()获得ApplicationPackageManager对象,
而mPM指向的是Proxy代理,当调用到mPM.方法后,将会调用到IPackageManager的Proxy代理方法,
然后通过Binder机制中的mRemote与服务端PackageManagerService通信
并调用到PackageManagerService的方法;
自我总结:PKMS是属于Binder机制的服务端角色

PKMS启动过程

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

image

SystemServer的启动

SystemServer七部曲

image

调用startBootstrapServices()服务

SystemServer启动Boot服务

1
(1) 启动Installer服务:mSystemServiceManager.startService(Installer.class);
1
2
(2) 获取设备是否加密(手机设置密码),如果设备加密了,则只解析"core"应用
String cryptState = VoldProperties.decrypt().orElse("");
1
2
3
4
5
6
(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服务
1
2
(4) 如果设备没有加密,操作它。管理A/B OTA dexopting
if (!mOnlyCore) // 判断是否只是核心应用

startBootstrapServices源码

SystemServer.java startBootstrapServices()
说明:startBootstrapServices()首先启动Installer服务,也就是安装器,随后判断当前的设备是否是出于加密状态。如果是出于加密状态则只是解析核心应用,接着调用PackageManagerService的静态方法main来创建PKMS对象。
(1) 启动Installer对象
(2) 获取设备是否加密(手机设置密码),如果设备加密了,则只解析”core”应用。
(3) 调用PKMS main方法初始化PackageManagerService,其中调用PackageManagerService()构造方法创建了PKMS对象。
(4) 如果设备没有加密,操作它。管理A/B OTA dexopting。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
private void startBootstrapServices(@NonNull TimingsTraceAndSlog t) {

// (1)启动Installer服务
// 阻塞等待installed完成启动,以便有机会创建具有适当权限的关键目录,
// 如/data/user。我们需要在初始化其他服务之前完成此任务。
Installer installer = mSystemServiceManager.startService(Installer.class);

// 初始化AMS
mActivityManagerService = 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方法,初始化PKMS
mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);

// PKMS 是否是第一次启动
mFirstBoot = mPackageManagerService.isFirstBoot();
// 通过context.getPackageManager()来获得PackageManager对象
mPackageManager = mSystemContext.getPackageManager();

// (4) 如果设备没有加密,操作它。管理A/B OTA dexopting
if (!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();
}
}
}
}

调用startOtherServices()方法

SystemServer启动其他服务,并使一些核心服务处于ready状态

1
2
3
4
5
6
7
8
(5) // 如果设备没有加密,执行performDexoptUpgrade,完成dexopt优化
mPackageManagerService.updatePackagesIfNeeded();
该方法,作用:检查是否需要去更新Packages并进行dex优化。

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

1
2
(6) mPackageManagerService.performFstrimIfNeeded(); // 执行performFstrimIfNeeded(),完成磁盘维护

1
2
3
(7) mPackageManagerService.systemReady(mActivityManagerService.getAppOpsService());// PackageManagerNative 准备就绪
DefaultPermissionPolicy.grantDefaultPermissions(userId); // 启动之前授予默认所有权限

startOtherServices源码

[SystemServer.java] startOtherServices()
(5) 执行updatePackageIfNeeded,完成dex优化
(6) 执行performFstrimIfNeeded,完成磁盘维护
(7) 调用systemReady,准备就绪

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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构造初始化

PKMS.main

main函数主要工作:
(1) 检查Package编译相关系统属性
(2) 调用PackageManagerService构造方法
(3) 启用部分应用服务于多用户场景
(4) 往ServiceManager中注册 “package” 和 “package_native’。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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;
}

【总结回顾】

1
2
3
创建PackageManagerService并向ServiceManager注册
创建PackageManagerNative并向ServiceManager注册

PKMS构造

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

此函数由两个重要的锁(mInstallLock和mLock)和五个阶段构成。在Android 11.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对象。

五个阶段

image

1
2
3
4
5
6
7
5个阶段构成,下面会详细的来分析这些内容。
阶段1:BOOT_PROGRESS_PMS_START 开始阶段
阶段2:BOOT_PROGRESS_PMS_SYSTEM_SCAN_START 系统扫描阶段
阶段3:BOOT_PROGRESS_PMS_DATA_SCAN_START Data扫描阶段
阶段4:BOOT_PROGRESS_PMS_SCAN_END 扫描结束
阶段5:BOOT_PROGRESS_PMS_READY 就绪阶段

阶段1,阶段2,阶段3,阶段4,阶段5 的 EventLog

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public PackageManagerService(Context context, Installer installer,
boolean factoryTest, boolean onlyCore) {
...
// 阶段1:BOOT_PROGRESS_PMS_START
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START,
SystemClock.uptimeMillis());

// 阶段2:BOOT_PROGRESS_PMS_SYSTEM_SCAN_START
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,
startTime);
...

// 阶段3:BOOT_PROGRESS_PMS_DATA_SCAN_STAR
if (!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_READY
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY,
SystemClock.uptimeMillis());
}

阶段一

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线程,循环处理外部安装相关消息。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
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 IndentationCheck
synchronized (mInstallLock) {
// writer
synchronized (mLock) {
//(7)创建PackageManager的handler线程,循环处理外部安装相关消息
//启动PackageManager线程,负责apk的安装、卸载
mHandlerThread = new ServiceThread(TAG,
Process.THREAD_PRIORITY_BACKGROUND, true /*allowIo*/);
mHandlerThread.start();
// 应用Handler
mHandler = new PackageHandler(mHandlerThread.getLooper());
// 进程记录handler
mProcessLoggingHandler = 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();

// 这句很重要,解析系统配置文件package.xml
// 读取并解析/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)
}
}

【总结回顾】

1
2
3
这里主要是对一些属性和子服务进行了创建或赋值,其中比较重要的有mInstaller、mSettings、mPackageDexOptimizer等。
在之前的有些版本,mSettings等有些属性是在这里直接new的,而现在采用传入Injector的方式来获取。另外、这里还开启了工作线程。

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)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
// Settins类的几个重要属性
private final File mSettingsFilename;
private final File mBackupSettingsFilename;
private final File mPackageListFilename;
private final File mStoppedPackagesFilename;
private final File mBackupStoppedPackagesFilename;
/** The top level directory in configfs for sdcardfs to push the package->uid,userId mappings */
private final File mKernelMappingFilename;

/** 已经安装的App的信息 */
final ArrayMap<String, PackageSetting> mPackages = new ArrayMap<>();

// 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;

// 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的内容,建立对应的数据结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
Setting.java
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) {
;
}

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();
// 解析xml
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属性可以运行在同一个进程,共享同一个UID
final SharedUserSetting sharedUser = (SharedUserSetting) idObj;
p.sharedUser = sharedUser;
p.appId = sharedUser.userId;
addPackageSettingLPw(p, sharedUser);
}
return true;
}

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
mSettings.addSharedUserLPw("android.uid.system", // 字符串
Process.SYSTEM_UID, //系统进程使用的用户id,值为1000
ApplicationInfo.FLAG_SYSTEM, //标志系统 Package
ApplicationInfo.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为UID
s = new SharedUserSetting(name, pkgFlags, pkgPrivateFlags);
s.userId = uid;
if (registerExistingAppIdLPw(uid, s, name)) {
mSharedUsers.put(name, s);// 将name与键值对添加到mSharedUsers中保存
return s;
}
return null;
}

【总结回顾】

1
2
3
4
初始化PMS的各个子组件/子服务以及相关属性
解析package.xml,获取已经安装的App信息,存储到Settings的mPackages中
创建了后台工作线程及其Handler

阶段二

BOOT_PROGRESS_PMS_SYSTEM_SCAN_START 系统扫描阶段

主要工作:
(1) 从init.rc中获取环境变量BOOTCLASSPATH和SYSTEMSERVERCLASSPATH;
(2) 对于旧版本升级的情况,将安装时获取权限变更为运行时申请权限;
(3) 扫描system/vendor/product/odm/oem等目录的priv-app、app、overlay包;
(4) 清除安装时临时文件以及其他不必要的信息。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
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.rc
final 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之前版本升级上来的情况,需要像首次启动一样处理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;

// 在扫描之前保存预先存在的系统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 11.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-app
for (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);
}

// 删掉不存在的package
if (!mOnlyCore) {
// do this first before mucking with mPackages for the "expecting better" case
final Iterator<AndroidPackage> pkgIterator = mPackages.values().iterator();
// 这里把mSettings.mPackages(也就是packages.xml文件中读取的记录)和mPackages(实时扫描得到的记录)做比较,看看有哪些变化
// 有变化的情况往往是OTA升级
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();
// 非系统App跳过
// 如果不是系统应用,则不被允许禁用其他应用
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();

......
}

分析上面调用的 scanDirTracedLI

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
private void scanDirTracedLI(File scanDir, final int parseFlags, int scanFlags,
long currentTime, PackageParser2 packageParser, ExecutorService executorService) {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "scanDir [" + scanDir.getAbsolutePath() + "]");
try {
// 这个方法几乎没有做其他的事情,除了日志,就是直接调用scanDirLI
scanDirLI(scanDir, parseFlags, scanFlags, currentTime, packageParser, executorService);
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
}

private void scanDirLI(File scanDir, int parseFlags, int scanFlags, long currentTime,
PackageParser2 packageParser, ExecutorService executorService) {
final File[] files = scanDir.listFiles();
// 空文件夹直接返回
if (ArrayUtils.isEmpty(files)) {
Log.d(TAG, "No files in app dir " + scanDir);
return;
}

if (DEBUG_PACKAGE_SCANNING) {
Log.d(TAG, "Scanning app dir " + scanDir + " scanFlags=" + scanFlags
+ " flags=0x" + Integer.toHexString(parseFlags));
}

// 把传进来的PackageParser2对象和线程池封装成ParallelPackageParser对象
ParallelPackageParser parallelPackageParser =
new ParallelPackageParser(packageParser, executorService);

int fileCount = 0;
for (File file : files) {
final boolean isPackage = (isApkFile(file) || file.isDirectory())
&& !PackageInstallerService.isStageName(file.getName());
if (!isPackage) {
// Ignore entries which are not packages
continue;
}

// 解析包的关键代码
parallelPackageParser.submit(file, parseFlags);
fileCount++;
}

// 解析完成之后,取出结果挨个处理
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 {
// addForInitLI --> commitReconciledScanResultLocked --> commitPackageSettings -->
// 更新mSettings中相关包的数据
// 把包的信息存储到mPackages里面
addForInitLI(parseResult.parsedPackage, parseFlags, scanFlags,
currentTime, null);
} catch (PackageManagerException e) {
...
}
} else ...

// 删除无效的用户App
if ((scanFlags & SCAN_AS_SYSTEM) == 0
&& errorCode != PackageManager.INSTALL_SUCCEEDED) {
logCriticalInfo(Log.WARN,
"Deleting invalid package at " + parseResult.scanFile);
removeCodePathLI(parseResult.scanFile);
}
}
}

以上函数的【总结回顾】

1
2
3
4
通过ParallelPackageParser解析扫描目录下的包
取出解析结果,执行addForInitLI
删除无效的用户App

【总结回顾】

1
2
3
4
扫描各个系统分区的的App
解析系统App信息
把解析结果存储起来,存储在PMS的相关属性和mSettings里

阶段三

BOOT_PROGRESS_PMS_DATA_SCAN_START Data扫描阶段
扫描/data/app下的App,也就是用户安装的App

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
PackageManagerService.packageManagerService()

if (!mOnlyCore) {
// 第三阶段
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,
SystemClock.uptimeMillis());

// 扫描用户安装的App,/data/app目录
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;

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 {
// 扫描APK
scanPackageTracedLI(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();
}

【总结回顾】

1
2
这里就是对/data/app进行了扫描,主要工作与扫描系统App目录是一样的,只是细节处理上有些不同。初次之外还做了一些扫尾工作

阶段四

BOOT_PROGRESS_PMS_SCAN_END 扫描结束

主要工作:
(1) sdk版本变更,更新权限;
(2) OTA升级后首次启动,清除不必要的缓存数据;
(3) 权限等默认项更新完后,清理相关数据;
(4) 更新package.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
PackageManagerService.packageManager()

// 第四阶段
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END,SystemClock.uptimeMillis());

// 如果SDK版本发生了变化(升级系统),重新对App进行授权
// 如果自上次启动以来,平台SDK已改变,则需要重新授予应用程序权限以捕获出现的任何新权限
final boolean sdkUpdated = (ver.sdkVersion != mSdkVersion);
if (sdkUpdated) {

mPermissionManager.updateAllPermissions(StorageManager.UUID_PRIVATE_INTERNAL, sdkUpdated);
ver.sdkVersion = mSdkVersion;

// 如果是首次启动或者从6.0以前的系统升级,初始化用户首选App
// 如果这是第一次启动或这是来自Android M之前的版本升级,并且它是正常启动,
// 那需要在所有已定义的用户初始化默认的首选应用程序
if (!mOnlyCore && (mPromoteSystemApps || mFirstBoot)) {
for (UserInfo user : mInjector.getUserManagerInternal().getUsers(true)) {
mSettings.applyDefaultPreferredAppsLPw(user.id);
primeDomainVerificationsLPw(user.id);
}
}
// 为系统用户准备存储空间,因为SettingsProvider和SystemUI等核心系统App不可能等用户去启动
// 在启动期间尽早为系统用户准备存储,因为像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 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前的非系统应用程序在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;

// 把更新后的mSettings中更新后的相关信息写入packages.xml等对应文件中
mSettings.writeLPr();

【总结回顾】

1
2
3
4
5
如果SDK版本发生了变化(升级系统),重新对App进行授权
为系统核心服务准备存储空间
如果是升级后第一次正常启动,需要清除代码缓存,但不是会清除应用的配置文件
把更新后的信息写回对应的xml文件中

阶段五

BOOT_PROGRESS_PMS_READY 就绪阶段

主要工作:
(1)创建PackageInstallerService对象
(2)GC回收内存

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// 第五阶段
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();

【总结回顾】

1
2
对一些属性进行了赋值,最重要的是初始化PackageInstallerService。

五阶段总结

阶段一:开始阶段:BOOT_PROGRESS_PMS_START。这个阶段的主要工作:

1
2
3
4
第一件事:初始化PMS的各个子组件/子服务以及相关属性
第二件事:解析package.xml,获取已经安装的App信息,存储到Settings的mPackages中
第三件事:创建了后台工作线程及其Handler


阶段二:系统扫描阶段:BOOT_PROGRESS_PMS_SYSTEM_SCAN_START。这个阶段的主要工作:

1
2
3
4
第一件事:扫描各个系统分区的的App
第二件事:解析系统App信息
第三件事:把解析结果存储起来,存储在PMS的相关属性和mSettings里


阶段三:Data扫描阶段:BOOT_PROGRESS_PMS_DATA_SCAN_START。

1
2
3
这个阶段对/data/app进行了扫描,主要工作与扫描系统App目录是一样的,
只是细节处理上有些不同。初次之外还做了一些扫尾工作。


阶段四:扫描结束:BOOT_PROGRESS_PMS_SCAN_END。这个阶段主要工作:

1
2
3
4
5
第一件事:如果SDK版本发生了变化(升级系统),重新对App进行授权
第二件事:为系统核心服务准备存储空间
第三件事:如果是升级后第一次正常启动,需要清除代码缓存,但不是会清除应用的配置文件
第四讲事:把更新后的信息写回对应的xml文件中


阶段五:就绪阶段:BOOT_PROGRESS_PMS_READY。

1
2
这个阶段又对一些属性进行了赋值,最重要的是初始化PackageInstallerService

PKMS构建成功之后

在SystemServer中,PMS构建完成之后,仍然后一些额外的操作(通过查找mPackageManagerService看它在哪些地方用到了)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
t.traceBegin("startOtherServices");

...

if (!mOnlyCore) {
...
// 优化Dex
mPackageManagerService.updatePackagesIfNeeded();
...
}

t.traceBegin("PerformFstrimIfNeeded");
try {
// 磁盘清理
mPackageManagerService.performFstrimIfNeeded();
} catch (Throwable e) {
reportWtf("performing fstrim", e);
}
t.traceEnd();

...

t.traceBegin("MakePackageManagerServiceReady");
// 通知mPackageManagerService及其子组件系统已就绪
mPackageManagerService.systemReady();
t.traceEnd();

...

// We now tell the activity manager it is okay to run third party
// code. It will call back into us once it has gotten to the state
// where third party code can really run (but before it has actually
// started launching the initial applications), for us to complete our
// initialization.
mActivityManagerService.systemReady(() -> {
...

// 等待PMS中为App的启动做好准备工作
mPackageManagerService.waitForAppDataPrepared();

...
}, t);

t.traceEnd(); // startOtherServices
}

【总结回顾】

1
2
3
4
5
6
在startOtherServices中,PKMS做了几件事情:
在需要的情况下进行dex优化
在需要的情况下进行磁盘清理
通知PMS及其子组件系统已就绪
ActivityManagerService启动Launcher之前等待PMS中为App的启动做好准备工作

简述总结

总的来说,PMS在SystemServer里面创建,并向ServiceManager注册。
其创建过程分为五个阶段,在此过程中会从packages.xml等相关文件中读取上次保存的包列表和实时扫描的列表进行比较和更新,
处理升级事宜,最后把更新后的包列表重新持久化。
另外,创建完成之后还进行了一些dex优化、磁盘清理等等一些列额外操作。

APK的扫描

PKMS的构造函数中调用了 scanDirTracedLI方法 来扫描某个目录的apk文件。

APK的扫描,整体描述图:

image

PKMS.scanDirTracedLi:首先加入了一些systtrace的日志追踪,然后调用scanDirLI()进行分析

1
2
3
4
5
6
7
8
9
private void scanDirTracedLI(File scanDir, final int parseFlags, int scanFlags, long currentTime) {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "scanDir [" + scanDir.getAbsolutePath() + "]");
try {
// 【注意】会调用此 scanDirLI函数
scanDirLI(scanDir, parseFlags, scanFlags, currentTime);
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
}

PKMS.scanDirLI: 使用了ParallelPackageParser的对象,ParallelPackageParser是一个队列,我们这里手机所有系统的apk,然后从这些队列里面取出apk,再调用PackageParser 解析进行解析:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
private void scanDirLI(File scanDir, int parseFlags, int scanFlags, long currentTime) {
final File[] files = scanDir.listFiles();
if (ArrayUtils.isEmpty(files)) {
Log.d(TAG, "No files in app dir " + scanDir);
return;
}

if (DEBUG_PACKAGE_SCANNING) {
Log.d(TAG, "Scanning app dir " + scanDir + " scanFlags=" + scanFlags
+ " flags=0x" + Integer.toHexString(parseFlags));
}
// parallelPackageParser是一个队列,收集系统 apk 文件,
// 然后从这个队列里面一个个取出 apk ,调用 PackageParser 解析
try (ParallelPackageParser parallelPackageParser = new ParallelPackageParser(
mSeparateProcesses, mOnlyCore, mMetrics, mCacheDir,
mParallelPackageParserCallback)) {
// 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());
过滤掉非 apk 文件,如果不是则跳过继续扫描
if (!isPackage) {
// Ignore entries which are not packages
continue;
}
// 把APK信息存入parallelPackageParser中的对象mQueue,PackageParser()函数赋给了队列中的pkg成员
// 【们注意】 这里的 submit 函数 很重要,下面就会分析此函数
parallelPackageParser.submit(file, parseFlags);
fileCount++;
}

// Process results one by one
for (; fileCount > 0; fileCount--) {
// 从parallelPackageParser中取出队列apk的信息
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.pkg.applicationInfo.isStaticSharedLibrary()) {
renameStaticSharedLibraryPackage(parseResult.pkg);
}
try {
//调用 scanPackageChildLI 方法扫描一个特定的 apk 文件
// 该类的实例代表一个 APK 文件,所以它就是和 apk 文件对应的数据结构。
scanPackageChildLI(parseResult.pkg, parseFlags, scanFlags,
currentTime, null);
} catch (PackageManagerException e) {
errorCode = e.error;
Slog.w(TAG, "Failed to scan " + parseResult.scanFile + ": " + e.getMessage());
}
} else if (throwable instanceof PackageParser.PackageParserException) {
PackageParser.PackageParserException e = (PackageParser.PackageParserException)
throwable;
errorCode = e.error;
Slog.w(TAG, "Failed to parse " + parseResult.scanFile + ": " + e.getMessage());
} else {
throw new IllegalStateException("Unexpected exception occurred while parsing "
+ parseResult.scanFile, throwable);
}

// Delete invalid userdata apps
//如果是非系统 apk 并且解析失败
if ((scanFlags & SCAN_AS_SYSTEM) == 0 &&
errorCode != PackageManager.INSTALL_SUCCEEDED) {
logCriticalInfo(Log.WARN,
"Deleting invalid package at " + parseResult.scanFile);
// 非系统 Package 扫描失败,删除文件
removeCodePathLI(parseResult.scanFile);
}
}
}
}

ParallelPackageParser.submit :

把扫描路径中的APK等内容,放入队列mQueue,

并把parsePackage() pp 赋给ParseResult,用于后面的调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public void submit(File scanFile, int parseFlags) {
mService.submit(() -> {
ParseResult pr = new ParseResult();
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parallel parsePackage [" + scanFile + "]"); // 日志打印
try {
PackageParser pp = new PackageParser();
pp.setSeparateProcesses(mSeparateProcesses);
pp.setOnlyCoreApps(mOnlyCore);
pp.setDisplayMetrics(mMetrics);
pp.setCacheDir(mCacheDir);
pp.setCallback(mPackageParserCallback);
pr.scanFile = scanFile;
// 并把parsePackage()与pp 赋值ParseResult,用于后面的调用
pr.pkg = parsePackage(pp, scanFile, parseFlags); // 【注意】parsePackage下面会分析
} catch (Throwable e) {
pr.throwable = e;
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
try {
// 把扫描路径中的APK等内容,放入队列mQueue
mQueue.put(pr);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
// Propagate result to callers of take().
// This is helpful to prevent main thread from getting stuck waiting on
// ParallelPackageParser to finish in case of interruption
mInterruptedInThread = Thread.currentThread().getName();
}
});
}

通过 PackageParser.parsePackage 进行apk解析:

​ 如果传入的packageFile是目录, 调用parseClusterPackage()解析

​ 如果传入的packageFile是APK文件, 调用parseMonolithicPackage()解析

1
2
3
4
5
6
7
8
9
10
11
12
13
public Package parsePackage(File packageFile, int flags, boolean useCaches)
throws PackageParserException {
...
if (packageFile.isDirectory()) {
//如果传入的packageFile是目录,调用parseClusterPackage()解析
parsed = parseClusterPackage(packageFile, flags);
} else {
//如果是APK文件,就调用parseMonolithicPackage()解析
parsed = parseMonolithicPackage(packageFile, flags); // 【注意】下面我们分析此函数
}
...
return parsed;
}

PackageParser.parseMonolithicPackage(),它的作用是解析给定的APK文件,将其作为单个单块包处理,最终调用parseBaseApk()进行解析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public Package parseMonolithicPackage(File apkFile, int flags) throws PackageParserException {
final PackageLite lite = parseMonolithicPackageLite(apkFile, flags);
if (mOnlyCoreApps) {
if (!lite.coreApp) {
throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
"Not a coreApp: " + apkFile);
}
}

final SplitAssetLoader assetLoader = new DefaultSplitAssetLoader(lite, flags);
try {
// 对核心应用解析 【注意】 最终调用parseBaseApk()进行解析,我们下面来分析
final Package pkg = parseBaseApk(apkFile, assetLoader.getBaseAssetManager(), flags);
pkg.setCodePath(apkFile.getCanonicalPath());
pkg.setUse32bitAbi(lite.use32bitAbi);
return pkg;
} catch (IOException e) {
throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
"Failed to get path: " + apkFile, e);
} finally {
IoUtils.closeQuietly(assetLoader);
}
}

PackageParser.parseBaseApk()主要是对AndroidManifest.xml进行解析,解析后所有的信息放在Package对象中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
 private Package parseBaseApk(File apkFile, AssetManager assets, int flags)
throws PackageParserException {
final String apkPath = apkFile.getAbsolutePath();
...
XmlResourceParser parser = null;
...
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对象
// 【注意】解析后所有的信息放在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;
...
}

parseBaseApk —–> parseBaseApkCommon , parseBaseApk省略了

PackageParser.parseBaseApkCommon 从AndroidManifest.xml中获取标签名,解析标签中的各个item的内容,存入Package对象中

例如:获取标签 “application”、”permission”、”package”、”manifest” ,太多了,省略了哈

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
 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);

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;
}
...
//如果标签是"permission"
else if (tagName.equals(TAG_PERMISSION)) {
//进行"permission"的解析
if (!parsePermission(pkg, res, parser, outError)) {
return null;
}
....
}
}
}

上面解析AndroidManifest.xml,会得到 “application“、”overlay”、”permission”、”uses-permission” 等信息

我们下面就针对”application“进行展开分析一下,进入 PackageParser.parseBaseApplication()函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
private boolean parseBaseApplication(Package owner, Resources res,
XmlResourceParser parser, int flags, String[] outError)
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
&& (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
// 获取"application"子标签的标签内容
String tagName = parser.getName();
// 如果标签是"activity"
if (tagName.equals("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);
}
...
}
}

在 PackageParser 扫描完一个 APK 后,此时系统已经根据该 APK 中 AndroidManifest.xml,创建了一个完整的 Package 对象

APK的扫描,自我总结:

第一步:扫描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操作, 进行安装

安装的三步走, 整体描述图:

image

用户点击 xxx.apk 文件进行安装, 从 开始安装 到 完成安装 流程如下:

image

APK的安装, 整体描述图:

image

点击一个apk后,会弹出安装界面,点击确定按钮后,会进入PackageInstallerActivitybindUi() 中的mAlert点击事件, 弹出的安装界面底部显示的是一个diaglog,主要由bindUi构成,上面有 ”取消“ 和 ”安装“ 两个按钮,点击安装后 调用startInstall()进行安装:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
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 {
startInstall(); // 进行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);
}

startInstall方法组装了一个Intent,并跳转到 InstallInstalling 这个Activity,并关闭掉当前的PackageInstallerActivity。InstallInstalling主要用于向包管理器发送包的信息并处理包管理的回调:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
private void startInstall() {
// Start subactivity to actually install the application
Intent newIntent = new Intent();
newIntent.putExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO,
mPkgInfo.applicationInfo);
newIntent.setData(mPackageURI);
// 设置Intent中的class为 InstallInstalling,用来进行Activity跳转
// class InstallInstalling extends AlertActivity [注意] 下面会分析 InstallInstalling Activity
newIntent.setClass(this, InstallInstalling.class);
String installerPackageName = getIntent().getStringExtra(
Intent.EXTRA_INSTALLER_PACKAGE_NAME);
if (mOriginatingURI != null) {
newIntent.putExtra(Intent.EXTRA_ORIGINATING_URI, mOriginatingURI);
}
if (mReferrerURI != null) {
newIntent.putExtra(Intent.EXTRA_REFERRER, mReferrerURI);
}
if (mOriginatingUid != PackageInstaller.SessionParams.UID_UNKNOWN) {
newIntent.putExtra(Intent.EXTRA_ORIGINATING_UID, mOriginatingUid);
}
if (installerPackageName != null) {
newIntent.putExtra(Intent.EXTRA_INSTALLER_PACKAGE_NAME,
installerPackageName);
}
if (getIntent().getBooleanExtra(Intent.EXTRA_RETURN_RESULT, false)) {
newIntent.putExtra(Intent.EXTRA_RETURN_RESULT, true);
}
newIntent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
if(localLOGV) Log.i(TAG, "downloaded app uri="+mPackageURI);
startActivity(newIntent);
finish();
}

启动 InstallInstalling,进入onCreate, 重点是看onCreate函数中的六步:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
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())) {
try {
getPackageManager().installExistingPackage(appInfo.packageName);
launchSuccess();
} catch (PackageManager.NameNotFoundException e) {
launchFailure(PackageManager.INSTALL_FAILED_INTERNAL_ERROR, null);
}
} else {
//根据mPackageURI创建一个对应的File
final File sourceFile = new File(mPackageURI.getPath());
PackageUtil.AppSnippet as = PackageUtil.getAppSnippet(this, appInfo, sourceFile);

mAlert.setIcon(as.icon);
mAlert.setTitle(as.label);
mAlert.setView(R.layout.install_content_view);
mAlert.setButton(DialogInterface.BUTTON_NEGATIVE, getString(R.string.cancel),
(ignored, ignored2) -> {
if (mInstallingTask != null) {
mInstallingTask.cancel(true);
}

if (mSessionId > 0) {
getPackageManager().getPackageInstaller().abandonSession(mSessionId);
mSessionId = 0;
}

setResult(RESULT_CANCELED);
finish();
}, null);
setupAlert();
requireViewById(R.id.installing).setVisibility(View.VISIBLE);

// 第一步.如果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);
} catch (EventResultPersister.OutOfIdsException e) {
// Does not happen
}
} else {
// 第三步.创建SessionParams,它用来代表安装会话的参数,组装params
PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(
PackageInstaller.SessionParams.MODE_FULL_INSTALL);
params.setInstallAsInstantApp(false);
params.setReferrerUri(getIntent().getParcelableExtra(Intent.EXTRA_REFERRER));
params.setOriginatingUri(getIntent()
.getParcelableExtra(Intent.EXTRA_ORIGINATING_URI));
params.setOriginatingUid(getIntent().getIntExtra(Intent.EXTRA_ORIGINATING_UID,
UID_UNKNOWN));
params.setInstallerPackageName(getIntent().getStringExtra(
Intent.EXTRA_INSTALLER_PACKAGE_NAME));
params.setInstallReason(PackageManager.INSTALL_REASON_USER);

// 第四步.根据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));
} catch (PackageParser.PackageParserException e) {
Log.e(LOG_TAG, "Cannot parse package " + file + ". Assuming defaults.");
Log.e(LOG_TAG,
"Cannot calculate installed size " + file + ". Try only apk size.");
params.setSize(file.length());
} catch (IOException e) {
Log.e(LOG_TAG,
"Cannot calculate installed size " + file + ". Try only apk size.");
params.setSize(file.length());
}

try {
// 第五步.向InstallEventReceiver注册一个观察者返回一个新的mInstallId,
//其中InstallEventReceiver继承自BroadcastReceiver,用于接收安装事件并回调给EventResultPersister。
mInstallId = InstallEventReceiver
.addObserver(this, EventResultPersister.GENERATE_NEW_ID,
this::launchFinishBasedOnResult);
} catch (EventResultPersister.OutOfIdsException e) {
launchFailure(PackageManager.INSTALL_FAILED_INTERNAL_ERROR, null);
}

try {
// 第六步.PackageInstaller的createSession方法内部会通过IPackageInstaller与PackageInstallerService进行进程间通信,
//最终调用的是PackageInstallerService的createSession方法来创建并返回mSessionId
mSessionId = getPackageManager().getPackageInstaller().createSession(params);
} catch (IOException e) {
launchFailure(PackageManager.INSTALL_FAILED_INTERNAL_ERROR, null);
}
}

mCancelButton = mAlert.getButton(DialogInterface.BUTTON_NEGATIVE);

mSessionCallback = new InstallSessionCallback();
}
}

注意: 以上第六步是重点 PackageInstaller 的 createSession()内部会通过IPackageInstaller与PackageInstallerService进行进程间通信,最终调用的是PackageInstallerService的createSession方法来创建并返回mSessionId

InstallInstalling.onResume方法中,调用onPostExecute()方法,将APK的信息通过IO流的形式写入到PackageInstaller.Session中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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()) {
// 【注意】 最终执行onPostExecute() 下面来分析
// 创建内部类InstallingAsyncTask的对象,调用execute(),最终进入onPostExecute()
mInstallingTask = new InstallingAsyncTask();
mInstallingTask.execute();
} else {
// we will receive a broadcast when the install is finished
mCancelButton.setEnabled(false);
setFinishOnTouchOutside(false);
}
}
}

Installinstalling.InstallingAsyncTask: 关注 第一步 和 第二步

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
 private final class InstallingAsyncTask extends AsyncTask<Void, Void, PackageInstaller.Session> {
volatile boolean isDone;

// 第一步: doInBackground()会根据包(APK)的Uri,将APK的信息通过IO流的形式写入到PackageInstaller.Session中
@Override
protected PackageInstaller.Session doInBackground(Void... params) {
PackageInstaller.Session session;
try {
session = getPackageManager().getPackageInstaller().openSession(mSessionId);
} catch (IOException e) {
return null;
}

session.setStagingProgress(0);

try {
File file = new File(mPackageURI.getPath());

try (InputStream in = new FileInputStream(file)) {
long sizeBytes = file.length();
try (OutputStream out = session
.openWrite("PackageInstaller", 0, sizeBytes)) {
byte[] buffer = new byte[1024 * 1024];
while (true) {
int numRead = in.read(buffer);

if (numRead == -1) {
session.fsync(out);
break;
}

if (isCancelled()) {
session.close();
break;
}
//将APK的信息通过IO流的形式写入到PackageInstaller.Session中
out.write(buffer, 0, numRead);
if (sizeBytes > 0) {
float fraction = ((float) numRead / (float) sizeBytes);
session.addProgress(fraction);
}
}
}
}

return session;
} catch (IOException | SecurityException e) {
Log.e(LOG_TAG, "Could not write package", e);

session.close();

return null;
} finally {
synchronized (this) {
isDone = true;
notifyAll();
}
}
}

// 第二步:最后在onPostExecute()中 调用PackageInstaller.Session的commit方法,进行安装
@Override
protected void onPostExecute(PackageInstaller.Session session) {
if (session != null) {
Intent broadcastIntent = new Intent(BROADCAST_ACTION);
broadcastIntent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
broadcastIntent.setPackage(getPackageName());
broadcastIntent.putExtra(EventResultPersister.EXTRA_ID, mInstallId);

PendingIntent pendingIntent = PendingIntent.getBroadcast(
InstallInstalling.this,
mInstallId,
broadcastIntent,
PendingIntent.FLAG_UPDATE_CURRENT);

// 【注意】commit 下面会分析
// 调用PackageInstaller.Session的commit方法,进行安装
session.commit(pendingIntent.getIntentSender());
mCancelButton.setEnabled(false);
setFinishOnTouchOutside(false);
} else {
getPackageManager().getPackageInstaller().abandonSession(mSessionId);

if (!isCancelled()) {
launchFailure(PackageManager.INSTALL_FAILED_INVALID_APK, null);
}
}
}
}

PackageInstaller的commit()

1
2
3
4
5
6
7
8
9
10
[PackageInstaller.java] commit
public void commit(@NonNull IntentSender statusReceiver) {
try {
// mSession的类型为IPackageInstallerSession,这说明要通过IPackageInstallerSession来进行进程间的通信,最终会调用PackageInstallerSession的commit方法,这样代码逻辑就到了Java框架层的。
// 调用IPackageInstallerSession的commit方法, 跨进程调用到 PackageInstallerSession.commit()
mSession.commit(statusReceiver, false);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}

PackageInstallerSession.**commit()**中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[PackageInstallerSession.java] commit()
public void commit(@NonNull IntentSender statusReceiver, boolean forTransfer) {
if (mIsPerfLockAcquired && mPerfBoostInstall != null) {
mPerfBoostInstall.perfLockRelease();
mIsPerfLockAcquired = false;
}
...
// 调用markAsCommitted()
if (!markAsCommitted(statusReceiver, forTransfer)) {
return;
}
...
// 【注意】向Handler发送一个类型为MSG_COMMIT的消息 ,下面会分析
mHandler.obtainMessage(MSG_COMMIT).sendToTarget();
}

MSG_COMMIT在handler中进行处理,进入handleCommit()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public boolean handleMessage(Message msg) {
switch (msg.what) {
case MSG_COMMIT:
handleCommit();
break;
}
}

private void handleCommit() {
...
List<PackageInstallerSession> childSessions = getChildSessions();

try {
synchronized (mLock) {
//最终调用installStage(),进入PKMS
commitNonStagedLocked(childSessions);
}
} catch (PackageManagerException e) {
final String completeMsg = ExceptionUtils.getCompleteMessage(e);
Slog.e(TAG, "Commit of session " + sessionId + " failed: " + completeMsg);
destroyInternal();
dispatchSessionFinished(e.error, completeMsg, null);
}
}

最终调用 **mPm.installStage()**,进入PKMS 【经过千辛万苦,终于要进入PKMS了】

1
2
3
4
5
6
7
8
private void commitNonStagedLocked(...)throws PackageManagerException {
if (isMultiPackage()) {
...
mPm.installStage(activeChildSessions); // 【注意】跨越进程 进入 PKMS.installStage了
} else {
mPm.installStage(committingSession);
}
}

PKMS.installStage

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
[PackageManagerService.java] 
void installStage(ActiveInstallSession activeInstallSession) {
if (DEBUG_INSTANT) {
if ((activeInstallSession.getSessionParams().installFlags
& PackageManager.INSTALL_INSTANT_APP) != 0) {
Slog.d(TAG, "Ephemeral install of " + activeInstallSession.getPackageName());
}
}
// 第一步.创建了类型为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);
}

对INIT_COPY的消息的处理
[PackageManagerService.java]
void doHandleMessage(Message msg) {
switch (msg.what) {
case INIT_COPY: {
HandlerParams params = (HandlerParams) msg.obj;
if (params != null) {
if (DEBUG_INSTALL) Slog.i(TAG, "init_copy: " + params);
Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "queueInstall",
System.identityHashCode(params));
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "startCopy");
// 【注意】执行APK拷贝动作,这里会执行到 final void startCopy()
params.startCopy();
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
break;
}
}
}

[PKMS.HandlerParams]
final void startCopy() {
if (DEBUG_INSTALL) Slog.i(TAG, "startCopy " + mUser + ": " + this);
handleStartCopy();
handleReturnCode(); // 调用到下面 handleReturnCode
}

[PKMS.MultiPackageInstallParams]
void handleReturnCode() {
if (mVerificationCompleted && mEnableRollbackCompleted) {
.....
if (mRet == PackageManager.INSTALL_SUCCEEDED) {
mRet = mArgs.copyApk(); // 【注意】 下面会说到 copyApk
}
.....
}
}

APK 拷贝 方法调用步骤如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
PKMS 
copyApk()
doCopyApk()

PackageManagerServiceUtils
copyPacakge()
copyFile()

// TODO 通过文件流的操作,把APK拷贝到/data/app等目录
private static void copyFile(String sourcePath, File targetDir, String targetName)
throws ErrnoException, IOException {
if (!FileUtils.isValidExtFilename(targetName)) {
throw new IllegalArgumentException("Invalid filename: " + targetName);
}
Slog.d(TAG, "Copying " + sourcePath + " to " + targetName);

final File targetFile = new File(targetDir, targetName);
final FileDescriptor targetFd = Os.open(targetFile.getAbsolutePath(),
O_RDWR | O_CREAT, 0644);
Os.chmod(targetFile.getAbsolutePath(), 0644);
FileInputStream source = null;
try {
source = new FileInputStream(sourcePath);
FileUtils.copy(source.getFD(), targetFd);
} finally {
IoUtils.closeQuietly(source);
}
}

进入 Android 11.0 核心安装环节:

image

processPendingInstall:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
private void processPendingInstall(final InstallArgs args, final int currentStatus) {
if (args.mMultiPackageInstallParams != null) {
args.mMultiPackageInstallParams.tryProcessInstallRequest(args, currentStatus);
} else {
//1.设置安装参数
PackageInstalledInfo res = createPackageInstalledInfo(currentStatus);
//2.创建一个新线程,处理安装参数,进行安装
processInstallRequestsAsync(
res.returnCode == PackageManager.INSTALL_SUCCEEDED,
Collections.singletonList(new InstallRequest(args, res)));
}
}

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
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));
}
});
}

installPackagesTracedLI

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
 
private void installPackagesLI(List<InstallRequest> requests) {
...
// 环节一.Prepare 准备:分析任何当前安装状态,分析包并对其进行初始验证。
prepareResult = preparePackageLI(request.args, request.installResult);
...
// 环节二.Scan 扫描:考虑到prepare中收集的上下文,询问已分析的包。
final List<ScanResult> scanResults = scanPackageTracedLI(
prepareResult.packageToScan, prepareResult.parseFlags,
prepareResult.scanFlags, System.currentTimeMillis(),
request.args.user);
...
// 环节三.Reconcile 调和:在彼此的上下文和当前系统状态中验证扫描的包,以确保安装成功。
ReconcileRequest reconcileRequest = new ReconcileRequest(preparedScans, installArgs,
installResults,
prepareResults,
mSharedLibraries,
Collections.unmodifiableMap(mPackages), versionInfos,
lastStaticSharedLibSettings);
...
// 环节四.Commit 提交:提交所有扫描的包并更新系统状态。这是安装流中唯一可以修改系统状态的地方,必须在此阶段之前确定所有可预测的错误。
commitPackagesLocked(commitRequest);
...
// 环节五.完成APK的安装【注意:下面会分析这个操作】
executePostCommitSteps(commitRequest);
}

executePostCommitSteps 安装APK,并为新的代码路径准备应用程序配置文件,并再次检查是否需要dex优化

如果是直接安装新包,会为新的代码路径准备应用程序配置文件

如果是替换安装:其主要过程为更新设置,清除原有的某些APP数据,重新生成相关的app数据目录等步骤,同时要区分系统应用替换和非系统应用替换。而安装新包:则直接更新设置,生成APP数据即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
[PackageManagerService.java] executePostCommitSteps()
private void executePostCommitSteps(CommitRequest commitRequest) {
for (ReconciledPackage reconciledPkg : commitRequest.reconciledPackages.values()) {
...
//1)进行安装
prepareAppDataAfterInstallLIF(pkg);
//2)如果需要替换安装,则需要清楚原有的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);
}


//3)为新的代码路径准备应用程序配置文件。这需要在调用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.applicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) == 0);

if (performDexopt) {
...
//4)执行dex优化
mPackageDexOptimizer.performDexOpt(pkg,
null /* instructionSets */,
getOrCreateCompilerPackageStats(pkg),
mDexManager.getPackageUseInfoOrDefault(packageName),
dexoptOptions);
}

BackgroundDexOptService.notifyPackageChanged(packageName);
}
}

prepareAppDataAfterInstallLIF:

1
2
3
4
5
6
7
8
9
10
11
通过一系列的调用,最终会调用到[Installer.java] createAppData()进行安装,交给installed进程进行APK的安装
调用栈如下:

prepareAppDataAfterInstallLIF()
|
prepareAppDataLIF()
|
prepareAppDataLeafLIF()
|
[Installer.java]
createAppData()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
private void prepareAppDataAfterInstallLIF(PackageParser.Package pkg) {
...
for (UserInfo user : um.getUsers()) {
...
if (ps.getInstalled(user.id)) {
// TODO: when user data is locked, mark that we're still dirty
prepareAppDataLIF(pkg, user.id, flags);
}
}
}

private void prepareAppDataLIF(PackageParser.Package pkg, int userId, int flags) {
if (pkg == null) {
Slog.wtf(TAG, "Package was null!", new Throwable());
return;
}
prepareAppDataLeafLIF(pkg, userId, flags);
final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;
for (int i = 0; i < childCount; i++) {
prepareAppDataLeafLIF(pkg.childPackages.get(i), userId, flags);
}
}

private void prepareAppDataLeafLIF(PackageParser.Package pkg, int userId, int flags) {
...
try {
// 调用Installd守护进程的入口
ceDataInode = mInstaller.createAppData(volumeUuid, packageName, userId, flags,
appId, seInfo, app.targetSdkVersion);
} catch (InstallerException e) {
if (app.isSystemApp()) {
destroyAppDataLeafLIF(pkg, userId, flags);
try {
ceDataInode = mInstaller.createAppData(volumeUuid, packageName, userId, flags,
appId, seInfo, app.targetSdkVersion);
} catch (InstallerException e2) {
...
}
}
}
}

Installer.createAppData 收尾工作,安装完成后,更新设置,更新安装锁等:

1
2
3
4
5
6
7
8
9
10
11
12
13
[Installer.java]
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()
// 【注意】 mInstalld是一个aidl文件,通过此aidl文件调用到 Binder机制的服务端,服务端哪里要操控底层....
return mInstalld.createAppData(uuid, packageName, userId, flags, appId, seInfo,
targetSdkVersion);
} catch (Exception e) {
throw InstallerException.from(e);
}
}

总结:安装的原理:

image

权限扫描

PackageManagerService中执行systemReady()后,需求对 /system/etc/permissions中的各种xml进行扫描,进行相应的权限存储,让以后可以使用.

PackageManagerService执行systemReady()时,通过SystemConfig的readPermissionsFromXml()来扫描读取/system/etc/permissions中的xml文件,包括platform.xml和系统支持的各种硬件模块的feature主要工作:

整体图:

image

SystemConfig 的 readPermissions函数:

此函数目的:(扫描/system/etc/permissions中文件,调用readPermissionsFromXml()进行解析,存入SsytemConfig相应的成员数组变量中)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 void readPermissions(File libraryDir, int permissionFlag) {
...
// Iterate over the files in the directory and scan .xml files
File platformFile = null;
for (File f : libraryDir.listFiles()) {
if (!f.isFile()) {
continue;
}

// 最后读取platform.xml
if (f.getPath().endsWith("etc/permissions/platform.xml")) {
platformFile = f;
continue;
}
...
readPermissionsFromXml(f, permissionFlag);
}

// Read platform permissions last so it will take precedence
if (platformFile != null) {
readPermissionsFromXml(platformFile, permissionFlag);
}
}

解析xml的标签节点,存入mGlobalGids、mPermissions、mSystemPermissions等成员变量中,供其他进行调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
 
private void readPermissionsFromXml(File permFile, int permissionFlag) {
FileReader permReader = null;
permReader = new FileReader(permFile);
...
XmlPullParser parser = Xml.newPullParser();
parser.setInput(permReader);

while (true) {
...
String name = parser.getName();
switch (name) {
//解析 group 标签,前面介绍的 XML 文件中没有单独使用该标签的地方
case "group": {
String gidStr = parser.getAttributeValue(null, "gid");
if (gidStr != null) {
int gid = android.os.Process.getGidForName(gidStr);
//转换 XML 中的 gid字符串为整型,并保存到 mGlobalGids 中
mGlobalGids = appendInt(mGlobalGids, gid);
} else {
Slog.w(TAG, "<" + name + "> without gid in " + permFile + " at " + parser.getPositionDescription());
}
...
}
break;
case "permission": { //解析 permission 标签
if (allowPermissions) {
String perm = parser.getAttributeValue(null, "name");
if (perm == null) {
Slog.w(TAG, "<" + name + "> without name in " + permFile + " at " + parser.getPositionDescription());
XmlUtils.skipCurrentTag(parser);
break;
}
perm = perm.intern();
readPermission(parser, perm); //调用 readPermission 处理,存入mPermissions
} else {
logNotAllowedInPartition(name, permFile, parser);
XmlUtils.skipCurrentTag(parser);
}
} break;
}
}
}

查看 XML文件:

adb devices

adb shell

image

然后在导出去:

1
adb pull /system/etc/permissions

/system/etc/permissions中会存在很多的xml文件,例如我们看下 android.software.webview.xml的文件,内容如下:

里面只只有一个feature “android.software.webview”,大部分的xml都是类似的定义方式

1
2
3
4
<?xml version="1.0" encoding="utf-8"?>
<permissions>
<feature name="android.software.webview" />
</permissions>

让我们来简单的看下/system/etc/permissions/platform.xml的内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<?xml version="1.0" encoding="utf-8"?>
<permissions>
<permission name="android.permission.BLUETOOTH_ADMIN" >
<group gid="net_bt_admin" />
</permission>
<permission name="android.permission.INTERNET" >
<group gid="inet" />
</permission>
<permission name="android.permission.READ_LOGS" >
<group gid="log" />
</permission>
...
<assign-permission name="android.permission.MODIFY_AUDIO_SETTINGS" uid="media" />
<assign-permission name="android.permission.ACCESS_SURFACE_FLINGER" uid="media" />
<assign-permission name="android.permission.WAKE_LOCK" uid="media" />
...
<split-permission name="android.permission.ACCESS_FINE_LOCATION">
<new-permission name="android.permission.ACCESS_COARSE_LOCATION" />
</split-permission>
<split-permission name="android.permission.WRITE_EXTERNAL_STORAGE">
<new-permission name="android.permission.READ_EXTERNAL_STORAGE" />
</split-permission>
<split-permission name="android.permission.READ_CONTACTS"
targetSdk="16">
<new-permission name="android.permission.READ_CALL_LOG" />
</split-permission>
...
<library name="android.test.base"
file="/system/framework/android.test.base.jar" />
<library name="android.test.mock"
file="/system/framework/android.test.mock.jar"
dependency="android.test.base" />
<library name="android.test.runner"
file="/system/framework/android.test.runner.jar"
dependency="android.test.base:android.test.mock" />

<!-- In BOOT_JARS historically, and now added to legacy applications. -->
<library name="android.hidl.base-V1.0-java"
file="/system/framework/android.hidl.base-V1.0-java.jar" />
<library name="android.hidl.manager-V1.0-java"
file="/system/framework/android.hidl.manager-V1.0-java.jar"
dependency="android.hidl.base-V1.0-java" />
...
</permissions>

以上platform.xml中出现的标签种类则较为多样,它们的含义分别是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
platform.xml中出现的标签种类则较为多样,它们的含义分别是:

<group>:根据name获取gid

<permission >标签:把属性name所描述的权限赋予给<group>标签中属性gid所表示的用户组,一个权限可以有一个或多个group对象,当一个APK授权于这个这个权限时,它同时属于这几个组

<assign-permission>标签:把属性name所描述的权限赋予给uid属性所表示的用户

<split-permission>标签:一个权限可以扩展出一个新的权限

<library>标签:除framework中动态库以外的,所有系统会自动加载的动态库

<feature>标签:硬件支持的一些feature

<oem-permission>标签:oem厂商自己定义的一些权限

<privapp-permission>标签:来自system、vendor、product、system_ext的privapp权限分别存储,这是防止供应商分区中的xml授权于系统分区中的私有应用权限



最后将上面xml解析出来的数据做如下存储:

<group>标签gid属性的值会存放在mGlobalGids数组中;

<permission>标签,解析得到的值会存放在mPermissions集合中;

<assign-permission>标签解析得到的值会存放在mSystemPermissions中;

<split-permission>存储在mSplitPermissions

<library>标签解析得到的值会存放在mSharedLibraries中;

<feature>存储在mAvaliableFeatures

<oem-permission>存储在mOemPermissions

<privapp-permission>会根据不同的存储路径,分别存储在mVendorPrivAppPermissions、mProductPrivAppPermissions、mSystemExtPrivAppPermissions、mPrivAppPermissions

总结:权限扫描,扫描/system/etc/permissions中的xml,存入相应的结构体中,供之后权限管理使用