0%

PackageManagerService启动篇整理1

1. PackageManagerService的启动过程

本篇主要介绍pkms的构造函数所做的工作.

1.1. BOOT_PROGRESS_PMS_START 阶段

1.1.1. 初始化Settings类

初始化Settings类对象并添加6个ShareUserId

1
2
3
4
5
6
7
8
9
10
11
12
13
mSettings = new Settings(mPackages);
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);

SharedUserSettings将“android:sharedUserId”属性的名称和对应的uid关联起来,同时持有所有声明相同sharedUserId的APK的PackageSettings,因此PKMS可以为同一类APK设置相同的权限。

1.1.1.1. Settings类的作用

首先可以看下Settings的构造函数

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
Settings(File dataDir, Object lock) {
//该 lock 为mPackages 的ArrayMap
mLock = lock;

mRuntimePermissionsPersistence = new RuntimePermissionPersistence(mLock);

mSystemDir = new File(dataDir, "system");
mSystemDir.mkdirs();
FileUtils.setPermissions(mSystemDir.toString(),
FileUtils.S_IRWXU|FileUtils.S_IRWXG
|FileUtils.S_IROTH|FileUtils.S_IXOTH,
-1, -1);
// Settings 工具类, 初始化/data/system下的几个目录
mSettingsFilename = new File(mSystemDir, "packages.xml");
mBackupSettingsFilename = new File(mSystemDir, "packages-backup.xml");
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
mStoppedPackagesFilename = new File(mSystemDir, "packages-stopped.xml");
mBackupStoppedPackagesFilename = new File(mSystemDir, "packages-stopped-backup.xml");
}

Settings为工具类,与权限分配和Package的信息持久化有关.

创建/data/system下几个与Package包信息相关的几个文件:

  • /data/system/packages.xml - 记录系统中已安装的APK的运行信息;
  • /data/system/packages-backup.xml - 是packages.xml的备份文件,当packages.xml更新完毕时删除;
  • /data/system/packages.list - 初始化为/data/system/packages.list,记录所有已安装APK的简略信息;
  • /data/system/packages-stopped.xml - 记录强制stop的应用程序信息(非系统级应用默认为stopped状态)
  • /data/system/packages-stopped-backup.xml - 初始化为/data/system/packages-stopped-backup.xml,是packages-stopped.xml的备份文件,二者在Jelly Bean中已标记为废弃。

Setting工具类图

/data/system/packages.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
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
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<packages>
<version volumeUuid="f3127468-e382-4328-9d82-40d6ba08c31d" sdkVersion="26" databaseVersion="3" fingerprint="SPRD/sp9850ka_1h10_native:8.0.0/OPR1.170623.013/W17.31:userdebug/test-keys" />
<version sdkVersion="26" databaseVersion="3" fingerprint="SPRD/sp9850ka_1h10_native:8.0.0/OPR1.170623.013/W17.31:userdebug/test-keys" />
<version volumeUuid="primary_physical" sdkVersion="26" databaseVersion="26" fingerprint="SPRD/sp9850ka_1h10_native:8.0.0/OPR1.170623.013/W17.31:userdebug/test-keys" />
<permission-trees />
<permissions>
<item name="android.permission.REAL_GET_TASKS" package="android" protection="18" />
<item name="android.permission.ACCESS_CACHE_FILESYSTEM" package="android" protection="18" />
<item name="android.permission.REMOTE_AUDIO_PLAYBACK" package="android" protection="2" />
<item name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" package="com.android.providers.downloads" />
<item name="android.permission.REGISTER_WINDOW_MANAGER_LISTENERS" package="android" protection="2" />
<item name="android.permission.INTENT_FILTER_VERIFICATION_AGENT" package="android" protection="18" />
...此处省略n个权限信息...
</permissions>
<package name="com.android.fmradio" codePath="/system/priv-app/DreamFMRadio" nativeLibraryPath="/system/priv-app/DreamFMRadio/lib" primaryCpuAbi="armeabi-v7a" publicFlags="944291397" privateFlags="8" ft="15d9d796930" it="15d9d796930" ut="15d9d796930" version="2" userId="10006" isOrphaned="true">
<sigs count="1">
<cert index="0" key="308204a830820390a003020102020900b3998086d056cffa300d06092a864886f70d0101040500308194310b3009060355040613025553311330110603550408130a43616c69666f726e6961311630140603550407130d4d6f756e7461696e20566965773110300e060355040a1307416e64726f69643110300e060355040b1307416e64726f69643110300e06035504031307416e64726f69643122302006092a864886f70d0109011613616e64726f696440616e64726f69642e636f6d301e170d3038303431353232343035305a170d3335303930313232343035305a308194310b3009060355040613025553311330110603550408130a43616c69666f726e6961311630140603550407130d4d6f756e7461696e20566965773110300e060355040a1307416e64726f69643110300e060355040b1307416e64726f69643110300e06035504031307416e64726f69643122302006092a864886f70d0109011613616e64726f696440616e64726f69642e636f6d30820120300d06092a864886f70d01010105000382010d003082010802820101009c780592ac0d5d381cdeaa65ecc8a6006e36480c6d7207b12011be50863aabe2b55d009adf7146d6f2202280c7cd4d7bdb26243b8a806c26b34b137523a49268224904dc01493e7c0acf1a05c874f69b037b60309d9074d24280e16bad2a8734361951eaf72a482d09b204b1875e12ac98c1aa773d6800b9eafde56d58bed8e8da16f9a360099c37a834a6dfedb7b6b44a049e07a269fccf2c5496f2cf36d64df90a3b8d8f34a3baab4cf53371ab27719b3ba58754ad0c53fc14e1db45d51e234fbbe93c9ba4edf9ce54261350ec535607bf69a2ff4aa07db5f7ea200d09a6c1b49e21402f89ed1190893aab5a9180f152e82f85a45753cf5fc19071c5eec827020103a381fc3081f9301d0603551d0e041604144fe4a0b3dd9cba29f71d7287c4e7c38f2086c2993081c90603551d230481c13081be80144fe4a0b3dd9cba29f71d7287c4e7c38f2086c299a1819aa48197308194310b3009060355040613025553311330110603550408130a43616c69666f726e6961311630140603550407130d4d6f756e7461696e20566965773110300e060355040a1307416e64726f69643110300e060355040b1307416e64726f69643110300e06035504031307416e64726f69643122302006092a864886f70d0109011613616e64726f696440616e64726f69642e636f6d820900b3998086d056cffa300c0603551d13040530030101ff300d06092a864886f70d01010405000382010100572551b8d93a1f73de0f6d469f86dad6701400293c88a0cd7cd778b73dafcc197fab76e6212e56c1c761cfc42fd733de52c50ae08814cefc0a3b5a1a4346054d829f1d82b42b2048bf88b5d14929ef85f60edd12d72d55657e22e3e85d04c831d613d19938bb8982247fa321256ba12d1d6a8f92ea1db1c373317ba0c037f0d1aff645aef224979fba6e7a14bc025c71b98138cef3ddfc059617cf24845cf7b40d6382f7275ed738495ab6e5931b9421765c491b72fb68e080dbdb58c2029d347c8b328ce43ef6a8b15533edfbe989bd6a48dd4b202eda94c6ab8dd5b8399203daae2ed446232e4fe9bd961394c6300e5138e3cfd285e6e4e483538cb8b1b357" />
</sigs>
<perms>
<item name="android.permission.MODIFY_AUDIO_SETTINGS" granted="true" flags="0" />
<item name="android.permission.MODIFY_AUDIO_ROUTING" granted="true" flags="0" />
<item name="android.permission.ACCESS_MOCK_LOCATION" granted="true" flags="0" />
<item name="android.permission.ACCESS_FM_RADIO" granted="true" flags="0" />
<item name="android.permission.BLUETOOTH" granted="true" flags="0" />
<item name="android.permission.WRITE_MEDIA_STORAGE" granted="true" flags="0" />
<item name="android.permission.INTERNET" granted="true" flags="0" />
<item name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" granted="true" flags="0" />
<item name="android.permission.WRITE_SECURE_SETTINGS" granted="true" flags="0" />
<item name="android.permission.WAKE_LOCK" granted="true" flags="0" />
</perms>
<proper-signing-keyset identifier="1" />
</package>
....此处省略n个package信息..
<package name="com.android.providers.telephony" codePath="/system/priv-app/TelephonyProvider" nativeLibraryPath="/system/priv-app/TelephonyProvider/lib" publicFlags="1007402501" privateFlags="8" ft="15d9d7707d0" it="15d9d7707d0" ut="15d9d7707d0" version="26" sharedUserId="1001" isOrphaned="true">
<sigs count="1">
<cert index="0" />
</sigs>
<perms>
<item name="android.permission.WRITE_SETTINGS" granted="true" flags="0" />
<item name="android.permission.MODIFY_AUDIO_SETTINGS" granted="true" flags="0" />
<item name="android.permission.MANAGE_ACCOUNTS" granted="true" flags="0" />
<item name="android.permission.SYSTEM_ALERT_WINDOW" granted="true" flags="0" />
<item name="android.permission.BIND_CARRIER_SERVICES" granted="true" flags="0" />
<item name="android.permission.SEND_RESPOND_VIA_MESSAGE" granted="true" flags="0" />
<item name="android.permission.SHUTDOWN" granted="true" flags="0" />
<item name="android.permission.CHANGE_COMPONENT_ENABLED_STATE" granted="true" flags="0" />
<item name="android.permission.INTERNAL_SYSTEM_WINDOW" granted="true" flags="0" />
<item name="android.permission.PROCESS_PHONE_ACCOUNT_REGISTRATION" granted="true" flags="0" />
<item name="android.permission.BROADCAST_SMS" granted="true" flags="0" />
<item name="android.permission.CALL_PRIVILEGED" granted="true" flags="0" />
<item name="android.permission.CHANGE_NETWORK_STATE" granted="true" flags="0" />
<item name="android.permission.WRITE_SYNC_SETTINGS" granted="true" flags="0" />
<item name="android.permission.RECEIVE_BOOT_COMPLETED" granted="true" flags="0" />
...
</perms>
<proper-signing-keyset identifier="1" />
</package>
....此处省略n个package信息..
<shared-user name="android.uid.phone" userId="1001">
<sigs count="1">
<cert index="0" />
</sigs>
<perms>
<item name="android.permission.WRITE_SETTINGS" granted="true" flags="0" />
<item name="android.permission.MODIFY_AUDIO_SETTINGS" granted="true" flags="0" />
<item name="android.permission.MANAGE_ACCOUNTS" granted="true" flags="0" />
<item name="android.permission.SYSTEM_ALERT_WINDOW" granted="true" flags="0" />
<item name="android.permission.BIND_CARRIER_SERVICES" granted="true" flags="0" />
<item name="android.permission.SEND_RESPOND_VIA_MESSAGE" granted="true" flags="0" />
<item name="android.permission.SHUTDOWN" granted="true" flags="0" />
<item name="android.permission.CHANGE_COMPONENT_ENABLED_STATE" granted="true" flags="0" />
<item name="android.permission.INTERNAL_SYSTEM_WINDOW" granted="true" flags="0" />
<item name="android.permission.PROCESS_PHONE_ACCOUNT_REGISTRATION" granted="true" flags="0" />
<item name="android.permission.BROADCAST_SMS" granted="true" flags="0" />
<item name="android.permission.CALL_PRIVILEGED" granted="true" flags="0" />
<item name="android.permission.CHANGE_NETWORK_STATE" granted="true" flags="0" />
<item name="android.permission.WRITE_SYNC_SETTINGS" granted="true" flags="0" />
<item name="android.permission.RECEIVE_BOOT_COMPLETED" granted="true" flags="0" />
<item name="android.permission.DEVICE_POWER" granted="true" flags="0" />
<item name="android.permission.SET_TIME_ZONE" granted="true" flags="0" />
...
</perms>
</shared-user>
<keyset-settings version="1">
<keys>
<public-key identifier="1" value="MIIBIDANBgkqhkiG9w0BAQEFAAOCAQ0AMIIBCAKCAQEAnHgFkqwNXTgc3qpl7MimAG42SAxtcgexIBG+UIY6q+K1XQCa33FG1vIgIoDHzU172yYkO4qAbCazSxN1I6SSaCJJBNwBST58Cs8aBch09psDe2AwnZB00kKA4WutKoc0NhlR6vcqSC0JsgSxh14SrJjBqnc9aAC56v3lbVi+2OjaFvmjYAmcN6g0pt/tt7a0SgSeB6Jp/M8sVJbyzzbWTfkKO42PNKO6q0z1M3GrJ3GbO6WHVK0MU/wU4dtF1R4jT7vpPJuk7fnOVCYTUOxTVge/aaL/SqB9tffqIA0JpsG0niFAL4ntEZCJOqtakYDxUugvhaRXU89fwZBxxe7IJwIBAw==" />
<public-key identifier="2" value="MIIBIDANBgkqhkiG9w0BAQEFAAOCAQ0AMIIBCAKCAQEAyMLb/QlKLfRcP/GjLtIYBexy/FjQF5cb0Pa1LCYtcIGdGRln4Vjf06LH8bPg6AzlRdedKEgiAhHrhvD9gxLTe0IMETdQzJRhiuhy9IhkY73EYnyqDASDyGST41FVcRcDOL/cxM1q3dHAovNfXPJO0+QEOj5Y4rBeZkzN4SvLZ3Nf1t8SScNp5iVCvApHKeU5F/XDj/pS0Xtzycc3mN2xjtSBWQh1VH5mv8XaykwlpuuWDtlpI3CdowK6ZGy0lrMl6Gxciy56M3eyu+THzzMlQpEWP2iRUqwIhVDIPFCPS/Wt8K7VotygWD+asK0XZQ237qSyP9tFiFVH0P6rchg4iQIBAw==" />
<public-key identifier="3" value="MIIBIDANBgkqhkiG9w0BAQEFAAOCAQ0AMIIBCAKCAQEA1pMZBN7GCySx7cdi4NnYJT4+zWzrHeL/Boyo6LyozWvTeG6nCqds5g67D5k1Wf/ZPnepQ+foPUtkuOT+otPmVvHiZ6gbv7IwtXjCBEO+THIYuEb1IRWG8DihTonCvjh/jr7Pj8rD2h7jMMnqk9Cnw9xK81AiDVAIBzLggJcX7moFM1nmppTsLLPyhKCkZsh6lNg7MQk6ZzcuL2QSwG5tQvFYGN/+A4HMDNRE2mzdw7gkWBlIAbMlZBNPv96YySh3SNv1Z2pUDYFUyLvKB7niR1UzEcRrmvdv3uzMjmnnyKLQjngmIJQ/mXJ9PAT+cpkdmd+brjigshd/ox1bav7pHwIBAw==" />
<public-key identifier="4" value="MIIBIDANBgkqhkiG9w0BAQEFAAOCAQ0AMIIBCAKCAQEAriUMWhbvl/woaaxlGzIXzDa6DoaWQWjVigSfQM6FhnEjo/+09tlJwzzy2joFwj6sqlfYA4ibF1m89Z58byGJCuJQhbftVqpibAmJ75zNNjYsoOjRuWA/1Ngyh2eSbMwJDGi3da5/8wk0zDae8oVaJmffDGZ/0MfPXY66ZVgGc3MDu2JHJuq67fty8H7Xp2qzy5o4HEt9zYCbFA2JHwAhO+QB9Y1qBqYercOpwvHGVnKFsJrgk0Kmb6Qh6vk633VzoCjDMdcGAas698yEAz7OfHcqOluGsNvp13fDpIqpgB7c7ieBWJ9E2eQROXlgBXaplBC6gQkSWdrZjGxo/3hLjwIBAw==" />
</keys>
<keysets>
<keyset identifier="1">
<key-id identifier="1" />
</keyset>
<keyset identifier="2">
<key-id identifier="2" />
</keyset>
<keyset identifier="3">
<key-id identifier="3" />
</keyset>
<keyset identifier="4">
<key-id identifier="4" />
</keyset>
</keysets>
<lastIssuedKeyId value="4" />
<lastIssuedKeySetId value="4" />
</keyset-settings>
</packages>

该文件记录的信息包括:

  • 所有包公布的权限信息:
权限名称 公布该权限的包名 权限的保护级别(ProtectLevel)
android.permission.DOWNLOAD_WITHOUT_NOTIFICATION com.android.providers.downloads none
android.permission.REAL_GET_TASKS android 18
sprd.permission.SPRD_MODIFY_PHONE_STATE android 2
android.permission.WRITE_EXTERNAL_STORAGE android 1

具体的权限保护级别请查看PermissionInfo.java文件

  • 安装包的信息: <package标签>
item 作用 例子
name 包名 com.android.fmradio
codePath apk位置 /system/priv-app/DreamFMRadio
nativeLibraryPath native依赖库 /system/priv-app/DreamFMRadio/lib
primaryCpuAbi 首要的abi指令集 armeabi-v7a
publicFlags pkg的flag, 解析相关.将十进制转换为二进制后,通过比对ApplicationInfo.java中的标志位查看带有哪些flag 944291397
privateFlags 安装\解析 相关的flag, 比如 PRIVATE_FLAG_DIRECT_BOOT_AWARE, android:directBootAware=”true”, 同上,需要将十进制转换为二进制后,通过比对ApplicationInfo.java中的标志位查看带有哪些flag 8
ft apk文件的最后一次修改时间(时间采用UNIX时间戳格式,需要先将16进制转换为10进制,再将数字转换unix时间戳)十六进制转换十进制 UNIX时间戳转换,注意切换为ms 15d9d796930
it 第一次安装时间 15d9d796930
ut 最后一次应用升级的时间 15d9d796930
version 软件版本, 来自于android:versionCode/AndroidManifest 2
userId appid 10006
isOrphaned 与PackageInstaller相关. FLAG_SYSTEM的 app都为true,这个值来自与解析时的PARSE_IS_SYSTEM,目前看到的所有非data目录外的app都携带该标志; 另外用户自己安装的app,如果安装该apk的installer安装器销毁,该apk的此标志位也会变为true. 该标志为默认为false. 与应用卸载的逻辑有关. true
sigs 签名信息, count为签名的数目,签名可以有多个.注意修改apk签名后,或者更改shareUserId后,最好删除packages.xml文件,否则可能是读取的文件中的签名的信息 count=”1”
perms 申请的所有权限信息 MODIFY_AUDIO_SETTINGS
granted 是否授予 true
flags 授予的标志位 0
proper-signing-keyset 可能的密钥集?/与内置的签名集合有关.比如platform的签名其值都是1.而media的签名都是4.与最后的keyset-settings项是关联的. 1
  • version标签信息:
item 作用 例子
sdkVersion 标明sdk的版本 24
databaseVersion package database 的版本 24, 对应与绑定volumeUuid的项与sdkVersion相同
fingerprint 版本信息 SPRD/sp9853i_1h10_vmm_tos/sp9853i_1h10:7.0/NRD90M/W17.31.1N00:userdebug/test-keys
volumeUuid 通过volumeUuid创建VersionInfo信息. 对应内部存储还是外部存储 da2a94f3-d7f6-489f-b293-5bdb44b8dcc5

/data/system/packages.list

1
2
3
4
5
6
7
8
com.android.fmradio 10023 0 /data/user/0/com.android.fmradio platform:privapp 1013,3002,1023,1015,3003
plugin.sprd.sosForEmergency 10052 0 /data/user/0/plugin.sprd.sosForEmergency default none
com.android.cts.priv.ctsshim 10005 0 /data/user/0/com.android.cts.priv.ctsshim default:privapp none
com.android.providers.telephony 1001 0 /data/user_de/0/com.android.providers.telephony platform:privapp 3002,3003,3001
com.sprd.engineermode 1000 0 /data/user/0/com.sprd.engineermode platform 1013,3002,1023,1015,3003,3001
com.android.providers.calendar 10011 0 /data/user/0/com.android.providers.calendar default:privapp 3003
com.android.providers.media 10017 0 /data/user/0/com.android.providers.media default:privapp 2001,1023,1015,3003,1024,3007
com.android.wallpapercropper 10025 0 /data/user/0/com.android.wallpapercropper platform:privapp none

该文件记录了所有已安装apk的简略信息

包名 appid 用户 数据目录 包所属的性质(签名+app性质) gids
com.android.fmradio 10023 0 /data/user/0/com.android.fmradio platform:privapp 1013,3002,1023,1015,3003

1.1.2. 解析属性

获取系统默认配置主要包括两方面:属性系统配置和默认显示参数。

debug.separate_processes

用于标记是否在独立进程中运行某个程序。根据其值设置两个全局变量的值,后续ScanDirLI扫描安装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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
        String separateProcesses = SystemProperties.get("debug.separate_processes");
if (separateProcesses != null && separateProcesses.length() > 0) {
if ("*".equals(separateProcesses)) {
// debug.separate_processes 为*时,解析AndroidManifest时忽略process, 即所有进程都运行在它自己的进程中
mDefParseFlags = PackageParser.PARSE_IGNORE_PROCESSES;
mSeparateProcesses = null;
Slog.w(TAG, "Running with debug.separate_processes: * (ALL)");
} else {
mDefParseFlags = 0;
// 不为*时,指定的组件运行在自己进程中
mSeparateProcesses = separateProcesses.split(",");
Slog.w(TAG, "Running with debug.separate_processes: "
+ separateProcesses);
}
} else {
mDefParseFlags = 0;
mSeparateProcesses = null;
}

...
// separateProcesses = mSeparateProcesses
// flags = mDefParseFlags
private static String buildProcessName(String pkg, String defProc,
CharSequence procSeq, int flags, String[] separateProcesses,
String[] outError) {
// procSeq 为从AndroidManifest中解析出来的 android:process的名称
if ((flags&PARSE_IGNORE_PROCESSES) != 0 && !"system".equals(procSeq)) {
return defProc != null ? defProc : pkg;
}
if (separateProcesses != null) {
for (int i=separateProcesses.length-1; i>=0; i--) {
String sp = separateProcesses[i];
if (sp.equals(pkg) || sp.equals(defProc) || sp.equals(procSeq)) {
return pkg;
}
}
}
if (procSeq == null || procSeq.length() <= 0) {
return defProc;
}
return buildCompoundName(pkg, procSeq, "process", outError);
}

获取系统默认显示参数

通过WindowManager获取屏幕默认显示参数,存入一个DiaplayMetrics类型的全局变量PackageManagerService.mMetric中,后续扫描安装时使用该值匹配APK的asset和resource。

1
2
// mMetrics是一个描述界面显示,尺寸,分辨率,密度的类。
getDefaultDisplayMetrics(context, mMetrics);

1.1.3. dex优化相关

创建dex优化类的实例, mPackageDexOptimizer

1
2
3
mInstaller = installer;
mPackageDexOptimizer = new PackageDexOptimizer(installer, mInstallLock, context,
"*dexopt*");

1.1.4. SysConfig类构造并初始化

1
2
3
4
5
6
// 执行systemConfig初始化, 权限、feature sharedLibarys相关,解析一些配置文件,解析后的结果放在  SystemConfig
// 的 mGlobalGids mSystemPermissions mAvailableFeatures 列表中
SystemConfig systemConfig = SystemConfig.getInstance();
mGlobalGids = systemConfig.getGlobalGids();
mSystemPermissions = systemConfig.getSystemPermissions();
mAvailableFeatures = systemConfig.getAvailableFeatures();

初始化SysConfig对象, 主要调用了SysConfig的构造函数

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
SystemConfig() {
/*
解析
/system/etc/
/odm/etc/
/oem/etc/
sysconfig permissions 下的xml文件
权限 features 相关
*/
// 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);
// Allow ODM to customize system configs around libs, features and apps
int odmPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_APP_CONFIGS;
readPermissions(Environment.buildPath(
Environment.getOdmDirectory(), "etc", "sysconfig"), odmPermissionFlag);
readPermissions(Environment.buildPath(
Environment.getOdmDirectory(), "etc", "permissions"), odmPermissionFlag);
// Only allow OEM to customize features
readPermissions(Environment.buildPath(
Environment.getOemDirectory(), "etc", "sysconfig"), ALLOW_FEATURES);
readPermissions(Environment.buildPath(
Environment.getOemDirectory(), "etc", "permissions"), ALLOW_FEATURES);
}

但往往只存在一个目录 /system/etc/permissions

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
sp9832a_2h11:/system/etc/permissions # ls -l
total 224
-rw-r--r-- 1 root root 820 2017-07-12 00:16 android.hardware.bluetooth.xml
-rw-r--r-- 1 root root 830 2017-07-12 00:16 android.hardware.bluetooth_le.xml
-rw-r--r-- 1 root root 931 2017-07-12 00:16 android.hardware.camera.autofocus.xml
-rw-r--r-- 1 root root 1052 2017-07-12 00:16 android.hardware.camera.flash-autofocus.xml
-rw-r--r-- 1 root root 877 2017-07-12 00:16 android.hardware.camera.front.xml
-rw-r--r-- 1 root root 942 2017-07-12 00:16 android.hardware.location.gps.xml
-rw-r--r-- 1 root root 824 2017-07-12 00:16 android.hardware.sensor.accelerometer.xml
-rw-r--r-- 1 root root 816 2017-07-12 00:16 android.hardware.sensor.light.xml
-rw-r--r-- 1 root root 815 2017-07-12 00:16 android.hardware.sensor.proximity.xml
-rw-r--r-- 1 root root 881 2017-07-12 00:16 android.hardware.telephony.gsm.xml
-rw-r--r-- 1 root root 1035 2017-07-12 00:16 android.hardware.touchscreen.multitouch.xml
-rw-r--r-- 1 root root 909 2017-07-12 00:16 android.hardware.touchscreen.xml
-rw-r--r-- 1 root root 975 2017-07-12 00:16 android.hardware.usb.accessory.xml
-rw-r--r-- 1 root root 868 2017-07-12 00:16 android.hardware.usb.host.xml
-rw-r--r-- 1 root root 843 2017-07-12 00:16 android.hardware.wifi.direct.xml
-rw-r--r-- 1 root root 829 2017-07-12 00:16 android.hardware.wifi.xml
-rw-r--r-- 1 root root 1050 2017-07-12 00:11 android.software.live_wallpaper.xml
-rw-r--r-- 1 root root 860 2017-07-12 00:16 android.software.managed_users.xml
-rw-r--r-- 1 root root 745 2017-07-12 00:16 android.software.midi.xml
-rw-r--r-- 1 root root 748 2017-07-12 00:16 android.software.webview.xml
-rw-r--r-- 1 root root 828 2017-07-12 00:14 com.android.location.provider.xml
-rw-r--r-- 1 root root 828 2017-07-12 00:14 com.android.media.remotedisplay.xml
-rw-r--r-- 1 root root 820 2017-07-12 00:14 com.android.mediadrm.signer.xml
-rw-r--r-- 1 root root 4188 2017-07-12 00:16 handheld_core_hardware.xml
-rw-r--r-- 1 root root 8467 2017-07-12 00:14 platform.xml

其中比较重要的文件是 **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
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
129
130
131
132
133
134
135
136
137
138
139
140
141
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2008 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
...
-->
<permissions>
<!-- The following tags are associating low-level group IDs with
permission names. By specifying such a mapping, you are saying
that any application process granted the given permission will
also be running with the given group ID attached to its process,
so it can perform any filesystem (read, write, execute) operations
allowed for that group. -->

<permission name="android.permission.BLUETOOTH_ADMIN" >
<group gid="net_bt_admin" />
</permission>

<permission name="android.permission.BLUETOOTH" >
<group gid="net_bt" />
</permission>
...
<permission name="android.permission.WRITE_MEDIA_STORAGE" >
<group gid="media_rw" />
<group gid="sdcard_rw" />
</permission>

<permission name="android.permission.ACCESS_MTP" >
<group gid="mtp" />
</permission>

<permission name="android.permission.NET_ADMIN" >
<group gid="net_admin" />
</permission>

<!-- The group that /cache belongs to, linked to the permission
set on the applications that can access /cache -->
<permission name="android.permission.ACCESS_CACHE_FILESYSTEM" >
<group gid="cache" />
</permission>

<!-- RW permissions to any system resources owned by group 'diag'.
This is for carrier and manufacture diagnostics tools that must be
installable from the framework. Be careful. -->
<permission name="android.permission.DIAGNOSTIC" >
<group gid="input" />
<group gid="diag" />
</permission>

<!-- Group that can read detailed network usage statistics -->
<permission name="android.permission.READ_NETWORK_USAGE_HISTORY">
<group gid="net_bw_stats" />
</permission>

<!-- Group that can modify how network statistics are accounted -->
<permission name="android.permission.MODIFY_NETWORK_ACCOUNTING">
<group gid="net_bw_acct" />
</permission>

<permission name="android.permission.LOOP_RADIO" >
<group gid="loop_radio" />
</permission>

<!-- Hotword training apps sometimes need a GID to talk with low-level
hardware; give them audio for now until full HAL support is added. -->
<permission name="android.permission.MANAGE_VOICE_KEYPHRASES">
<group gid="audio" />
</permission>

<permission name="android.permission.ACCESS_FM_RADIO" >
<!-- /dev/fm is gid media, not audio -->
<group gid="media" />
</permission>

<!-- These are permissions that were mapped to gids but we need
to keep them here until an upgrade from L to the current
version is to be supported. These permissions are built-in
and in L were not stored in packages.xml as a result if they
are not defined here while parsing packages.xml we would
ignore these permissions being granted to apps and not
propagate the granted state. From N we are storing the
built-in permissions in packages.xml as the saved storage
is negligible (one tag with the permission) compared to
the fragility as one can remove a built-in permission which
no longer needs to be mapped to gids and break grant propagation. -->
<permission name="android.permission.READ_EXTERNAL_STORAGE" />
<permission name="android.permission.WRITE_EXTERNAL_STORAGE" />

<!-- ================================================================== -->
<!-- ================================================================== -->
<!-- ================================================================== -->

<!-- The following tags are assigning high-level permissions to specific
user IDs. These are used to allow specific core system users to
perform the given operations with the higher-level framework. For
example, we give a wide variety of permissions to the shell user
since that is the user the adb shell runs under and developers and
others should have a fairly open environment in which to
interact with the system. -->

<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" />
<assign-permission name="android.permission.UPDATE_DEVICE_STATS" uid="media" />
<assign-permission name="android.permission.UPDATE_APP_OPS_STATS" uid="media" />
<assign-permission name="android.permission.GET_PROCESS_STATE_AND_OOM_SCORE" uid="media" />

<assign-permission name="android.permission.MODIFY_AUDIO_SETTINGS" uid="cameraserver" />
<assign-permission name="android.permission.ACCESS_SURFACE_FLINGER" uid="cameraserver" />
<assign-permission name="android.permission.WAKE_LOCK" uid="cameraserver" />
<assign-permission name="android.permission.UPDATE_DEVICE_STATS" uid="cameraserver" />
<assign-permission name="android.permission.UPDATE_APP_OPS_STATS" uid="cameraserver" />

<assign-permission name="android.permission.ACCESS_SURFACE_FLINGER" uid="graphics" />

<!-- This is a list of all the libraries available for application
code to link against. -->

<library name="android.test.runner"
file="/system/framework/android.test.runner.jar" />
<library name="javax.obex"
file="/system/framework/javax.obex.jar" />
<library name="org.apache.http.legacy"
file="/system/framework/org.apache.http.legacy.jar" />

<!-- These are the standard packages that are white-listed to always have internet
access while in power save mode, even if they aren't in the foreground. -->
<!-- 白名单中的应用始终可以访问网络,即使是在省电模式下,且并不在前台也可以 -->
<allow-in-power-save package="com.android.providers.downloads" />

<!-- These are the standard packages that are white-listed to always have internet
access while in data mode, even if they aren't in the foreground. -->

<!-- 白名单中的应用始终可以访问网络,即使是节省流量模式下,仍可访问网络,且并不在前台也可以 -->
<allow-in-data-usage-save package="com.android.providers.downloads" />

<!-- These are the packages that are white-listed to be able to run as system user -->
<system-user-whitelisted-app package="com.android.settings" />

<!-- These are the packages that shouldn't run as system user -->
<system-user-blacklisted-app package="com.android.wallpaper.livepicker" />
</permissions>

每一个XML文件必须要有一个顶级标签<permissions>,至于子标签,可以支持这么几种:

标签 作用 关联的数据结构
permission标签 指定permission所属的gid,通过gid实现native层的权限控制;可以指定一个权限与几个组id对应,当一个apk被授予这个权限时,它也同时属于这几个组,拥有这几个组id了 perm.gids
group标签 安装到系统中的apk都具有的组id mGlobalGids
assign-permission 把一个权限赋予一个UID,当进程使用这个UID运行时,就具备了这个权限 mSystemPermissions
library 为系统添加一些扩展库用的。对应的.jar文件放在/system/framework/目录下。 mSharedLibraries
feature 每添加一个硬件,都要增加对应的feature mAvailableFeatures
unavailable-feature 保存不支持的feature mUnavailableFeatures
allow-in-power-save 白名单中的应用始终可以访问网络,即使是在省电模式下,且并不在前台也可以 mAllowInPowerSave
allow-in-power-save-except-idle 保存省电模式下(非Idle),可上网的应用 mAllowInPowerSaveExceptIdle
allow-in-data-usage-save 白名单中的应用始终可以访问网络,即使是节省流量模式下,仍可访问网络,且并不在前台也可以 mAllowInDataUsageSave
system-user-whitelisted-app 指定以system user权限运行的app mSystemUserWhitelistedApps
system-user-blacklisted-app 指定在system user权限下,不应该运行的app mSystemUserBlacklistedApp
default-enabled-vr-app 指定默认运行在VR模式下的components mDefaultVrComponents
backup-transport-whitelisted-service 保存能够传输备份数据的服务 mBackupTransportWhitelist

对这些XML文件的解析是由/framework/base/services/java/com/android/server/PackageManagerService.java中的**readPermissions()**负责的。解析时会先解析其它XML文件,最后解析platform.xml。

解析结果放入mSystemPermissions,mSharedLibraries,mPermissions,mAvailableFeatures等几个集合中供系统查询和权限配置使用。

像重力加速、多点触摸、WIFI等,只要系统支持,就要往**/system/etc/permissions/下面添加对应的XML配置文件。因为APK使用这些功能之前很有可能先调用PackageManager.hasSystemFeature**查询是否支持这个某个硬件模块。

/framework/base/data/etc/handheld_core_hardware.xml里面包含了一些系统的核心硬件模块配置文件。/framework/base/data/etc/Android.mk中会把这一块儿在编译时复制到/system/etc/permissions/目录下。这部分代码默认是关闭的,需要打开。

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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
private void readPermissionsFromXml(File permFile, int permissionFlag) {
FileReader permReader = null;
try {
//利用file构造fileReader
permReader = new FileReader(permFile);
} catch (FileNotFoundException e) {
.......
}
//读取系统属性"ro.config.low_ram",如果该属性为true,不会加载指定notLowRam的feature属性
final boolean lowRam = ActivityManager.isLowRamDeviceStatic();

try {
XmlPullParser parser = Xml.newPullParser();
//Xml解析器的输入为fileReader读取的内容
parser.setInput(permReader);

//找到解析的起点
.........

//根据传入的flag,决定当前目录下,从xml文件中解析内容的范围
//对于system目录,allowAll
boolean allowAll = permissionFlag == ALLOW_ALL;
boolean allowLibs = (permissionFlag & ALLOW_LIBS) != 0;
boolean allowFeatures = (permissionFlag & ALLOW_FEATURES) != 0;
boolean allowPermissions = (permissionFlag & ALLOW_PERMISSIONS) != 0;
boolean allowAppConfigs = (permissionFlag & ALLOW_APP_CONFIGS) != 0;
while (true) {
XmlUtils.nextElement(parser);
if (parser.getEventType() == XmlPullParser.END_DOCUMENT) {
break;
}

String name = parser.getName();
//解析group标签,前面介绍的xml文件中没有单独使用该标签的地方
if ("group".equals(name) && allowAll) {
String gidStr = parser.getAttributeValue(null, "gid");
if (gidStr != null) {
//将Gid字符串转化成整形,保存到mGlobalGids中
int gid = android.os.Process.getGidForName(gidStr);
mGlobalGids = appendInt(mGlobalGids, gid);
} else {
.........
}
XmlUtils.skipCurrentTag(parser);
continue;
} else if ("permission".equals(name) && allowPermissions) {
String perm = parser.getAttributeValue(null, "name");
.......
perm = perm.intern();
//调用readPermission解析permission标签
readPermission(parser, perm);
} else if ("assign-permission".equals(name) && allowPermissions) {
//得到权限名
String perm = parser.getAttributeValue(null, "name");
........
//得到uid字符串
String uidStr = parser.getAttributeValue(null, "uid");
......
//将uid字符串转变为整形
int uid = Process.getUidForName(uidStr);
.......
perm = perm.intern();
//得到保存uid当前已有的所有权限的ArraySet
ArraySet<string> perms = mSystemPermissions.get(uid);
if (perms == null) {
perms = new ArraySet<string>();
mSystemPermissions.put(uid, perms);
}
//将uid新增的权限,加入到它的ArraySet
perms.add(perm);
XmlUtils.skipCurrentTag(parser);
} else if ("library".equals(name) && allowLibs) {
String lname = parser.getAttributeValue(null, "name");
String lfile = parser.getAttributeValue(null, "file");

if (lname == null) {
......
} else if (lfile == null) {
.....
} else {
//保存library标签对应的内容
mSharedLibraries.put(lname, lfile);
}
} else if ("feature".equals(name) && allowFeatures) {
String fname = parser.getAttributeValue(null, "name");
int fversion = XmlUtils.readIntAttribute(parser, "version", 0);

if (!lowRam) {
allowed = true;
} else {
//内存不足时,指定notLowRam的feature不再加载
String notLowRam = parser.getAttributeValue(null, "notLowRam");
allowed = !"true".equals(notLowRam);
}

if (fname == null) {
.....
} else if (allowed) {
//将feature构造成featureInfo,加入到mAvailableFeatures对象中
addFeature(fname, fversion);
}
.......
} else if ("unavailable-feature".equals(name) && allowFeatures) {
//mUnavailableFeatures保存不支持的feature
.........
} else if ("allow-in-power-save-except-idle".equals(name) && allowAll) {
// These are the packages that are white-listed to be able to run in the
// background while in power save mode (but not whitelisted from device idle modes),
// as read from the configuration files.
//mAllowInPowerSaveExceptIdle中保存省电模式下(非Idle),可上网的应用
.........
} else if ("allow-in-power-save".equals(name) && allowAll) {
// These are the packages that are white-listed to be able to run in the
// background while in power save mode, as read from the configuration files.
//mAllowInPowerSave与mAllowInPowerSaveExceptIdle类似,权限更高
//这与Android M新特性Doze and App Standby模式有关
//DeviceIdleController用于判断设备是否进入Idle状态,进入Idle状态时,mAllowInPowerSaveExceptIdle中的应用要被禁掉
//但mAllowInPowerSave中的应用仍可运行
............
} else if ("allow-in-data-usage-save".equals(name) && allowAll) {
// These are the packages that are white-listed to be able to run in the
// background while in data-usage save mode, as read from the configuration files.
//mAllowInDataUsageSave保存此标签对应的packageName
//貌似android 7新增了一个节省数据流量的能力,有此标签的应用在节省数据流量时,仍可访问网络
............
} else if ("app-link".equals(name) && allowAppConfigs) {
// These are the package names of apps which should be in the 'always'
// URL-handling state upon factory reset.
//mLinkedApps保存此标签对应的packageName
//这个不太明白,好像是指定可以一直处于URL-handling state的app
.......
} else if ("system-user-whitelisted-app".equals(name) && allowAppConfigs) {
// These are the packages that are whitelisted to be able to run as system user
//mSystemUserWhitelistedApps保存此标签对应的packageName
//指定以system user权限运行的app
.......
} else if ("system-user-blacklisted-app".equals(name) && allowAppConfigs) {
// These are the packages that should not run under system user
//mSystemUserBlacklistedApp保存此标签对应的packageName
//指定在system user权限下,不应该运行的app
.........
}else if ("default-enabled-vr-app".equals(name) && allowAppConfigs) {
// These are the components that are enabled by default as VR mode listener services.
//mDefaultVrComponents保存此标签对应的packageName
//指定默认运行在VR模式下的components
.......
} else if ("backup-transport-whitelisted-service".equals(name) && allowFeatures) {
// These are the permitted backup transport service components
//mBackupTransportWhitelist保存此标签对应的packageName
//保存能够传输备份数据的服务
........
} else {
.......
}
}
} catch (XmlPullParserException e) {PullParserException e) {
.......
} catch (IOException e) {
.......
} finally {
IoUtils.closeQuietly(permReader);
}

// Some devices can be field-converted to FBE, so offer to splice in
// those features if not already defined by the static config
//加密相关的feature
if (StorageManager.isFileEncryptedNativeOnly()) {
addFeature(PackageManager.FEATURE_FILE_BASED_ENCRYPTION, 0);
addFeature(PackageManager.FEATURE_SECURELY_REMOVES_USERS, 0);
}

for (String featureName : mUnavailableFeatures) {
//从mAvailableFeatures移除不支持的feature
removeFeature(featureName);
}
}

从上面的代码可以看出readPermissions函数就是将xml文件中的标签转换成对应的数据结构,此处重要的是理解各种标签的作用。
对于”permission”标签,还调用了readPermission函数:

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
void readPermission(XmlPullParser parser, String name)
throws IOException, XmlPullParserException {
if (mPermissions.containsKey(name)) {
throw new IllegalStateException("Duplicate permission definition for " + name);
}

final boolean perUser = XmlUtils.readBooleanAttribute(parser, "perUser", false);
final PermissionEntry perm = new PermissionEntry(name, perUser);
//将permission name和permissionEntry结合起来
mPermissions.put(name, perm);
........
while(.....) {
.......
String tagName = parser.getName();
if ("group".equals(tagName)) {
String gidStr = parser.getAttributeValue(null, "gid");
if (gidStr != null) {
int gid = Process.getGidForName(gidStr);
//对应gid存入permissionEntry结构体中,于是permission name与gid对应起来
perm.gids = appendInt(perm.gids, gid);
} else {
......
}
}
.......
}
}

20160929092228476

1.1.5. 初始化PackageHandler

PackageHandler是PackageManagerService的内部类,它是Handler的子类。PackageManagerService启动时开启了Looper线程HandlerThread,使用HandlerThread的Looper对象与PackageHandler建立联系,负责轮询和分发处理消息。

1
2
3
4
5
// 新建一个Thread,用来和PackageHandler绑定
mHandlerThread = new ServiceThread(TAG,
Process.THREAD_PRIORITY_BACKGROUND, true /*allowIo*/);
mHandlerThread.start();
mHandler = new PackageHandler(mHandlerThread.getLooper());

通过PackageHandler处理的消息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
INIT_COPY
MCS_BOUND
MCS_RECONNECT
MCS_UNBIND
MCS_GIVE_UP
SEND_PENDING_BROADCAST
START_CLEANING_PACKAGE
POST_INSTALL
UPDATED_MEDIA_STATUS
WRITE_SETTINGS
WRITE_PACKAGE_RESTRICTIONS
WRITE_PACKAGE_LIST
CHECK_PENDING_VERIFICATION
PACKAGE_VERIFIED
START_INTENT_FILTER_VERIFICATIONS
INTENT_FILTER_VERIFIED

PackageHandler主要负责处理APK的复制和更名等相关的消息,但具体的处理则通过connectToService方法连接到DefaulyContainerService.apk,由它提供的MCS服务完成。

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
final private DefaultContainerConnection mDefContainerConn =
new DefaultContainerConnection();
class DefaultContainerConnection implements ServiceConnection {
public void onServiceConnected(ComponentName name, IBinder service) {
if (DEBUG_SD_INSTALL) Log.i(TAG, "onServiceConnected");
IMediaContainerService imcs =
IMediaContainerService.Stub.asInterface(service);
mHandler.sendMessage(mHandler.obtainMessage(MCS_BOUND, imcs));
}

public void onServiceDisconnected(ComponentName name) {
if (DEBUG_SD_INSTALL) Log.i(TAG, "onServiceDisconnected");
}
}

private boolean connectToService() {
if (DEBUG_SD_INSTALL) Log.i(TAG, "Trying to bind to" +
" DefaultContainerService");
Intent service = new Intent().setComponent(DEFAULT_CONTAINER_COMPONENT);
Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
// bind DefaultContainerService
if (mContext.bindServiceAsUser(service, mDefContainerConn,
Context.BIND_AUTO_CREATE, UserHandle.SYSTEM)) {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
mBound = true;
return true;
}
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
return false;
}

DefContainerSercice

1.1.6. 初始化UserManagerService, 并创建用户目录

1
2
3
4
5
6
7
File dataDir = Environment.getDataDirectory();
mAppInstallDir = new File(dataDir, "app");
mAppLib32InstallDir = new File(dataDir, "app-lib");
mEphemeralInstallDir = new File(dataDir, "app-ephemeral");
mAsecInternalPath = new File(dataDir, "app-asec").getPath();
mDrmAppPrivateInstallDir = new File(dataDir, "app-private");
sUserManager = new UserManagerServiceEx(context, this, mPackages);

Ø mAppDataDir:初始化为/data/data

Ø mAppInstallDir:初始化为/data/app

Ø mAppLibInstallDir:初始化为/data/app-lib

Ø mAsecInternalPath:初始化为/data/app-asec的路径信息

Ø mDrmAppPrivateInstallDir:初始化为/data/app-private

Ø mUserAppDataDir:初始化为/data/user

Ø mDeletedRecord:初始化为/data/app/.delrecord

1.1.6.1. UserManagerService初始化

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
private UserManagerService(Context context, PackageManagerService pm,
Object packagesLock, File dataDir) {
mContext = context;
mPm = pm;
mPackagesLock = packagesLock;
mHandler = new MainHandler();
synchronized (mPackagesLock) {
// 创建/data/system/users
mUsersDir = new File(dataDir, USER_INFO_DIR);
mUsersDir.mkdirs();
// Make zeroth user directory, for services to migrate their files to that location
// 创建/data/system/users/0
File userZeroDir = new File(mUsersDir, String.valueOf(UserHandle.USER_SYSTEM));
userZeroDir.mkdirs();
FileUtils.setPermissions(mUsersDir.toString(),
FileUtils.S_IRWXU | FileUtils.S_IRWXG | FileUtils.S_IROTH | FileUtils.S_IXOTH,
-1, -1);
// /data/system/users/userlist.xml
mUserListFile = new File(mUsersDir, USER_LIST_FILENAME);
initDefaultGuestRestrictions();
// 该函数比较重要,解析userlist.xml和<id>.xml文件;并清理不完整用户
readUserListLP();
sInstance = this;
}
mLocalService = new LocalService();
LocalServices.addService(UserManagerInternal.class, mLocalService);
// 锁屏相关服务初始化
mLockPatternUtils = new LockPatternUtils(mContext);
// 机主用户初始状态为STATE_BOOTING
mUserStates.put(UserHandle.USER_SYSTEM, UserState.STATE_BOOTING);
}

通过readUserListLP函数创建或解析 /data/system/users/0.xml 和 userlist.xml

1
sp9832a_2h11:/data/system/users # cat userlist.xml                    
1
2
3
4
5
6
7
8
9
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<users nextSerialNumber="10" version="6">
<guestRestrictions>
<!--访客限制-->
<restrictions no_sms="true" no_install_unknown_sources="true" no_config_wifi="true" no_outgoing_calls="true" />
</guestRestrictions>
<globalRestrictionOwnerUserId id="-10000" />
<user id="0" />
</users>
1
sp9832a_2h11:/data/system/users # cat 0.xml
1
2
3
4
5
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<user id="0" serialNumber="0" flags="19" created="0" lastLoggedIn="1325377476475" lastLoggedInFingerprint="SPRD/sp9832a_2h11_4mvoltesea_tee/sp9832a_2h11:7.0/NRD90M/W17.28.3N00:userdebug/test-keys">
<restrictions />
<device_policy_restrictions />
</user>
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
private void readUserListLP() {
// 如果/data/system/users/userlist.xml 文件不存在, 调用fallbackToSingleUserLP函数创建单用户
if (!mUserListFile.exists()) {
fallbackToSingleUserLP();
return;
}
...
AtomicFile userListFile = new AtomicFile(mUserListFile);
try {
fis = userListFile.openRead();
...
// xml 文件损坏, 也回滚调用fallbackToSingleUserLP函数创建单用户
if (type != XmlPullParser.START_TAG) {
Slog.e(LOG_TAG, "Unable to read user list");
fallbackToSingleUserLP();
return;
}

mNextSerialNumber = -1;
// users标签
if (parser.getName().equals(TAG_USERS)) {
String lastSerialNumber = parser.getAttributeValue(null, ATTR_NEXT_SERIAL_NO);
if (lastSerialNumber != null) {
mNextSerialNumber = Integer.parseInt(lastSerialNumber);
}
String versionNumber = parser.getAttributeValue(null, ATTR_USER_VERSION);
if (versionNumber != null) {
mUserVersion = Integer.parseInt(versionNumber);
}
}

final Bundle newDevicePolicyGlobalUserRestrictions = new Bundle();

while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
if (type == XmlPullParser.START_TAG) {
final String name = parser.getName();
// user标签
if (name.equals(TAG_USER)) {
String id = parser.getAttributeValue(null, ATTR_ID);
// 根据其user id值,嵌套读取对应的/data/system/users/<id>.xml文件,返回UserData对象
UserData userData = readUserLP(Integer.parseInt(id));

if (userData != null) {
synchronized (mUsersLock) {
// 将UserData对象放入mUsers SparseArray中
mUsers.put(userData.info.id, userData);
if (mNextSerialNumber < 0
|| mNextSerialNumber <= userData.info.id) {
mNextSerialNumber = userData.info.id + 1;
}
}
}
} else if (name.equals(TAG_GUEST_RESTRICTIONS)) {
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
&& type != XmlPullParser.END_TAG) {
if (type == XmlPullParser.START_TAG) {
if (parser.getName().equals(TAG_RESTRICTIONS)) {
synchronized (mGuestRestrictions) {
// 访客限制
UserRestrictionsUtils
.readRestrictions(parser, mGuestRestrictions);
}
} else if (parser.getName().equals(TAG_DEVICE_POLICY_RESTRICTIONS)
) {
UserRestrictionsUtils.readRestrictions(parser,
newDevicePolicyGlobalUserRestrictions);
}
break;
}
}
} else if (name.equals(TAG_GLOBAL_RESTRICTION_OWNER_ID)) {
String ownerUserId = parser.getAttributeValue(null, ATTR_ID);
if (ownerUserId != null) {
mGlobalRestrictionOwnerUserId = Integer.parseInt(ownerUserId);
}
}
}
}
synchronized (mRestrictionsLock) {
mDevicePolicyGlobalUserRestrictions = newDevicePolicyGlobalUserRestrictions;
}
// 根据UserData.info.partial信息确定用户信息是否完整, 只有完整的才放入mUserIds的数组中
updateUserIds();
upgradeIfNecessaryLP();
//SPRD: add protection mechanism for power-test @{
// 机主用户找不到, 回滚创建单用户
if(mUsers.get(UserHandle.USER_SYSTEM) == null){
fallbackToSingleUserLP();
}
// @}
} catch (IOException | XmlPullParserException e) {
fallbackToSingleUserLP();
} finally {
IoUtils.closeQuietly(fis);
}
}

在解析过程中用到了UserData UserInfo info类,它用于保存用户信息,包含用户id、用户名name以及用户类型标记三部分,其中用户类型分为私有用户、管理员用户和guest用户。

通过readUserLP函数从id.xml文件中创建出UserData数据

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
129
private UserData readUserLP(int id) {
int flags = 0;
int serialNumber = id;
String name = null;
String account = null;
String iconPath = null;
long creationTime = 0L;
long lastLoggedInTime = 0L;
String lastLoggedInFingerprint = null;
int profileGroupId = UserInfo.NO_PROFILE_GROUP_ID;
int restrictedProfileParentId = UserInfo.NO_PROFILE_GROUP_ID;
boolean partial = false;
boolean guestToRemove = false;
boolean persistSeedData = false;
String seedAccountName = null;
String seedAccountType = null;
PersistableBundle seedAccountOptions = null;
Bundle baseRestrictions = new Bundle();
Bundle localRestrictions = new Bundle();

FileInputStream fis = null;
try {
// /data/system/users/<id>.xml文件
AtomicFile userFile =
new AtomicFile(new File(mUsersDir, Integer.toString(id) + XML_SUFFIX));
fis = userFile.openRead();
XmlPullParser parser = Xml.newPullParser();
parser.setInput(fis, StandardCharsets.UTF_8.name());
int type;
...
// user id标签
if (type == XmlPullParser.START_TAG && parser.getName().equals(TAG_USER)) {
int storedId = readIntAttribute(parser, ATTR_ID, -1);
// id 与传入的id不对应,直接返回
if (storedId != id) {
Slog.e(LOG_TAG, "User id does not match the file name");
return null;
}
serialNumber = readIntAttribute(parser, ATTR_SERIAL_NO, id);
flags = readIntAttribute(parser, ATTR_FLAGS, 0);
iconPath = parser.getAttributeValue(null, ATTR_ICON_PATH);
creationTime = readLongAttribute(parser, ATTR_CREATION_TIME, 0);
lastLoggedInTime = readLongAttribute(parser, ATTR_LAST_LOGGED_IN_TIME, 0);
lastLoggedInFingerprint = parser.getAttributeValue(null,
ATTR_LAST_LOGGED_IN_FINGERPRINT);
profileGroupId = readIntAttribute(parser, ATTR_PROFILE_GROUP_ID,
UserInfo.NO_PROFILE_GROUP_ID);
restrictedProfileParentId = readIntAttribute(parser,
ATTR_RESTRICTED_PROFILE_PARENT_ID, UserInfo.NO_PROFILE_GROUP_ID);
String valueString = parser.getAttributeValue(null, ATTR_PARTIAL);
if ("true".equals(valueString)) {
partial = true;
}
valueString = parser.getAttributeValue(null, ATTR_GUEST_TO_REMOVE);
if ("true".equals(valueString)) {
guestToRemove = true;
}

seedAccountName = parser.getAttributeValue(null, ATTR_SEED_ACCOUNT_NAME);
seedAccountType = parser.getAttributeValue(null, ATTR_SEED_ACCOUNT_TYPE);
if (seedAccountName != null || seedAccountType != null) {
persistSeedData = true;
}

int outerDepth = parser.getDepth();
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
&& (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
continue;
}
String tag = parser.getName();
if (TAG_NAME.equals(tag)) {
type = parser.next();
if (type == XmlPullParser.TEXT) {
name = parser.getText();
}
} else if (TAG_RESTRICTIONS.equals(tag)) {
UserRestrictionsUtils.readRestrictions(parser, baseRestrictions);
} else if (TAG_DEVICE_POLICY_RESTRICTIONS.equals(tag)) {
UserRestrictionsUtils.readRestrictions(parser, localRestrictions);
} else if (TAG_ACCOUNT.equals(tag)) {
type = parser.next();
if (type == XmlPullParser.TEXT) {
account = parser.getText();
}
} else if (TAG_SEED_ACCOUNT_OPTIONS.equals(tag)) {
seedAccountOptions = PersistableBundle.restoreFromXml(parser);
persistSeedData = true;
}
}
}

// Create the UserInfo object that gets passed around
UserInfo userInfo = new UserInfo(id, name, iconPath, flags);
userInfo.serialNumber = serialNumber;
userInfo.creationTime = creationTime;
userInfo.lastLoggedInTime = lastLoggedInTime;
userInfo.lastLoggedInFingerprint = lastLoggedInFingerprint;
userInfo.partial = partial;
userInfo.guestToRemove = guestToRemove;
userInfo.profileGroupId = profileGroupId;
userInfo.restrictedProfileParentId = restrictedProfileParentId;

// Create the UserData object that's internal to this class
UserData userData = new UserData();
userData.info = userInfo;
userData.account = account;
userData.seedAccountName = seedAccountName;
userData.seedAccountType = seedAccountType;
userData.persistSeedData = persistSeedData;
userData.seedAccountOptions = seedAccountOptions;

synchronized (mRestrictionsLock) {
mBaseUserRestrictions.put(id, baseRestrictions);
mDevicePolicyLocalUserRestrictions.put(id, localRestrictions);
}
return userData;
} catch (IOException ioe) {
} catch (XmlPullParserException pe) {
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
}
}
}
return null;
}

fallbackToSingleUserLP 函数初始化用户信息,并创建id.xml文件和userlist.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
private void fallbackToSingleUserLP() {
int flags = UserInfo.FLAG_INITIALIZED;
// In split system user mode, the admin and primary flags are assigned to the first human
// user.
if (!UserManager.isSplitSystemUser()) {
flags |= UserInfo.FLAG_ADMIN | UserInfo.FLAG_PRIMARY;
}
// Create the system user
UserInfo system = new UserInfo(UserHandle.USER_SYSTEM, null, null, flags);
UserData userData = new UserData();
userData.info = system;
// 将创建的机主用户加入到mUsers中
synchronized (mUsersLock) {
mUsers.put(system.id, userData);
}
mNextSerialNumber = MIN_USER_ID;
mUserVersion = USER_VERSION;

Bundle restrictions = new Bundle();
synchronized (mRestrictionsLock) {
mBaseUserRestrictions.append(UserHandle.USER_SYSTEM, restrictions);
}

updateUserIds();
initDefaultGuestRestrictions();
// 创建 /data/system/users/0.xml
writeUserLP(userData);
// 创建 /data/system/users/userlist.xml文件
writeUserListLP();
}

1.1.6.2. 清理部分创建/删除的用户

根据UserInfo.partial属性的值,将不完整的用户信息放入UserManagerService.partials成员变量中,然后调用cleanupPartialUsers方法执行清理动作。

onBootPhase阶段清理不完整的用户信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
void cleanupPartialUsers() {
// Prune out any partially created, partially removed and ephemeral users.
ArrayList<UserInfo> partials = new ArrayList<>();
synchronized (mUsersLock) {
final int userSize = mUsers.size();
for (int i = 0; i < userSize; i++) {
UserInfo ui = mUsers.valueAt(i).info;
if ((ui.partial || ui.guestToRemove || ui.isEphemeral()) && i != 0) {
partials.add(ui);
}
}
}
final int partialsSize = partials.size();
for (int i = 0; i < partialsSize; i++) {
UserInfo ui = partials.get(i);
Slog.w(LOG_TAG, "Removing partially created user " + ui.id
+ " (name=" + ui.name + ")");
// 调用removeUserState清除不完整的用户信息
removeUserState(ui.id);
}
}

直接看removeUserState函数

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
private void removeUserState(final int userHandle) {
try {
// 加密相关. 清除用户的锁屏密码
mContext.getSystemService(StorageManager.class).destroyUserKey(userHandle);
} catch (IllegalStateException e) {
// This may be simply because the user was partially created.
Slog.i(LOG_TAG,
"Destroying key for user " + userHandle + " failed, continuing anyway", e);
}

// Cleanup gatekeeper secure user id
try {
final IGateKeeperService gk = GateKeeper.getService();
if (gk != null) {
// gatekeeper中清除该用户的信息
gk.clearSecureUserId(userHandle);
}
} catch (Exception ex) {
Slog.w(LOG_TAG, "unable to clear GK secure user id");
}

// Cleanup package manager settings
// 清除用户相关的信息.包括该用户下安装的apk信息, 申请的权限信息, 更新packages.xml文件, 与用户相关的packages的文件如
// /data/system/users/<id>/package-restrictions.xml mPendingBroadcasts中去除等等
mPm.cleanUpUser(this, userHandle);

// Clean up all data before removing metadata
// 清除用户的数据目录 /data/user_de/<id> /data/user/<id>
mPm.destroyUserData(userHandle,
StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE);

// Remove this user from the list
synchronized (mUsersLock) {
mUsers.remove(userHandle);
mIsUserManaged.delete(userHandle);
}
synchronized (mUserStates) {
mUserStates.delete(userHandle);
}
synchronized (mRestrictionsLock) {
mBaseUserRestrictions.remove(userHandle);
mAppliedUserRestrictions.remove(userHandle);
mCachedEffectiveUserRestrictions.remove(userHandle);
mDevicePolicyLocalUserRestrictions.remove(userHandle);
}
// Update the user list
synchronized (mPackagesLock) {
// 更新 /data/system/users/userlist.xml文件
writeUserListLP();
}
// Remove user file
AtomicFile userFile = new AtomicFile(new File(mUsersDir, userHandle + XML_SUFFIX));
// 最后删除 /data/system/users/<id>.xml
userFile.delete();
// 更新mUserIds 数组
updateUserIds();
Slog.i(LOG_TAG, "removeUserState finished! " + userHandle);
}

1.1.7. 同步SysConfig中的 Permission到Setting.mPermissions中

Permission转化SystemConfig.PermissionEntry->BasePermission

注意转化到BasePermission的包名为andriod,且对应的权限type 为 PROTECTION_SIGNATURE

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// Propagate permission configuration in to package manager.
// SystemConfig 解析的 Permission 放进 mSettings.mPermissions 中。
// 注意包名为andriod,且对应的权限type 为 PROTECTION_SIGNATURE
ArrayMap<String, SystemConfig.PermissionEntry> permConfig
= systemConfig.getPermissions();
for (int i=0; i<permConfig.size(); i++) {
SystemConfig.PermissionEntry perm = permConfig.valueAt(i);
BasePermission bp = mSettings.mPermissions.get(perm.name);
if (bp == null) {
bp = new BasePermission(perm.name, "android", BasePermission.TYPE_BUILTIN);
mSettings.mPermissions.put(perm.name, bp);
}
if (perm.gids != null) {
// 填充global gid
bp.setGids(perm.gids, perm.perUser);
}
}

1.1.8. 获取共享库,将其加入到mSharedLibraries并加入到优化集合中

将sysConfig.getSharedLibraries 放入 mSharedLibraries中.

1
2
3
4
5
6
// 获取共享库,将其加入到mSharedLibraries 加入到优化集合中。
ArrayMap<String, String> libConfig = systemConfig.getSharedLibraries();
for (int i=0; i<libConfig.size(); i++) {
mSharedLibraries.put(libConfig.keyAt(i),
new SharedLibraryEntry(libConfig.valueAt(i), null));
}

1.2. BOOT_PROGRESS_PMS_SYSTEM_SCAN_START 阶段

1.2.1. dex优化判定

zygote启动时,已经将 SYSTEMSERVERCLASSPATH 里的资源做过dex优化,此处不需要再次执行

首先通过InstructionSets.getAllInstructionSets 获取 abi集,需要读取Build.SUPPORTED_ABIS属性.

Returns the runtime instruction set corresponding to a given ABI. Multiple
compatible ABIs might map to the same instruction set. For example
armeabi-v7a and armeabi might map to the instruction set arm.
它描述了应用程序与OS之间的底层接口。ABI涉及了程序的各个方面,比如:目标文件格式、数据类型、数据对齐、函数调用约定以及函数如何传递参数、如何返回值、系统调用号、如何实现系统调用等。

遍历支持的abi集合后, 对mSharedLibraries 进行dex优化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// Shared libraries do not have profiles so we perform a full
// AOT compilation (if needed).

// 没有做过dex优化,或者该文件变更了,需要重新做dex优化
int dexoptNeeded = DexFile.getDexOptNeeded(
lib, dexCodeInstructionSet,
getCompilerFilterForReason(REASON_SHARED_APK),
false /* newProfile */);
if (dexoptNeeded != DexFile.NO_DEXOPT_NEEDED) {
mInstaller.dexopt(lib, Process.SYSTEM_UID, dexCodeInstructionSet,
dexoptNeeded, DEXOPT_PUBLIC /*dexFlags*/,
getCompilerFilterForReason(REASON_SHARED_APK),
StorageManager.UUID_PRIVATE_INTERNAL,
SKIP_SHARED_LIBRARY_CHECK);
}

1.2.2. pre-M版本apk升级权限install->runtime判断

sdkVersion

其中VersionInfo中存放了

  • sdkVersion
  • databaseVersion
  • fingerprint
1
2
3
4
private static final String ATTR_SDK_VERSION = "sdkVersion";
readLPw(){
ver.sdkVersion = XmlUtils.readIntAttribute(parser, ATTR_SDK_VERSION);
}
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
// 升级前的版本信息是从Settings中读取的,读取VersionInfo
final VersionInfo ver = mSettings.getInternalVersion();
mIsUpgrade = !Build.FINGERPRINT.equals(ver.fingerprint);

// when upgrading from pre-M, promote system app permissions from install to runtime

// 从Android5.1 及之前的版本 升级上来时,将 system app 的权限从install 变更为 runtime权限,
// 默认赋予runtime权限。
mPromoteSystemApps =
mIsUpgrade && ver.sdkVersion <= Build.VERSION_CODES.LOLLIPOP_MR1;

// When upgrading from pre-N, we need to handle package extraction like first boot,
// as there is no profiling data available.

mIsPreNUpgrade = mIsUpgrade && ver.sdkVersion < Build.VERSION_CODES.N;

// save off the names of pre-existing system packages prior to scanning; we don't
// want to automatically grant runtime permissions for new system apps


// 保存到 mExistingSystemPackages 中,用于install-> runtime
if (mPromoteSystemApps) {
Iterator<PackageSetting> pkgSettingIter = mSettings.mPackages.values().iterator();
while (pkgSettingIter.hasNext()) {
PackageSetting ps = pkgSettingIter.next();
// 此处为非用户安装的应用
if (isSystemApp(ps)) {
mExistingSystemPackages.add(ps.name);
}
}
}

此处涉及到权限授予的流程,先摘一小段:

当同时满足三个条件,会进行install->runtime权限的转换:

  • 从5.1及5.1之前升级上来的版本
  • 非用户安装的应用
  • 应用还在,没有被删除
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
private void grantPermissionsLPw(PackageParser.Package pkg, boolean replace,
String packageOfInterest) {
...
final int level = bp.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE;
switch (level) {
...
// DANGEROUS权限
case PermissionInfo.PROTECTION_DANGEROUS: {
//
else if (mPromoteSystemApps
&& isSystemApp(ps)
&& mExistingSystemPackages.contains(ps.name)) {
// For legacy system apps, install becomes runtime.
// We cannot check hasInstallPermission() for system apps since those
// permissions were granted implicitly and not persisted pre-M.
grant = GRANT_UPGRADE;
}
}
}
...
}

1.2.3. 开始扫描apk

1.2.3.1. 先扫描这两个目录

1
2
/vendor/overlay
/system/framework

1.2.3.2. 再扫描这几个目录下面(system app):

1
2
3
4
/system/priv-app
/system/app
/vendor/app
/oem/app

具体的扫描流程可参考扫描apk的流程

1.2.3.2.1. 扫描system app 后的处理

这几个目录下面的都是system app, 扫描完成后 , 在扫描到data app之前,需要对扫描后的结果做一下处理:

首先删除禁用的system 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
// 现在mPackages中查找是否有该包
final PackageParser.Package scannedPkg = mPackages.get(ps.name);
if (scannedPkg != null) {
// 遍历所有扫描到的apk(packages.xml文件中以及现在扫描到的都有),
// 如果该apk FLAG_SYSTEM 生效,是 system app 且 在 disabled packages list 中时,去除该apk,不再进行解析。
if (mSettings.isDisabledSystemPackageLPr(ps.name)) {
logCriticalInfo(Log.WARN, "Expecting better updated system app for "
+ ps.name + "; removing system app. Last known codePath="
+ ps.codePathString + ", installStatus=" + ps.installStatus
+ ", versionCode=" + ps.versionCode + "; scanned versionCode="
+ scannedPkg.mVersionCode);
removePackageLI(scannedPkg, true);
mExpectingBetter.put(ps.name, ps.codePath);
}
continue;
}
// 如果未在mPackages中查找到,但在mSettings.mPackages中有, 但未在禁用列表中,需要将该项从mSettings.mPackages中删除
if (!mSettings.isDisabledSystemPackageLPr(ps.name)) {
psit.remove();
logCriticalInfo(Log.WARN, "System package " + ps.name
+ " no longer exists; it's data will be wiped");
// Actual deletion of code and data will be handled by later
// reconciliation step
} else {
// 如果未在mPackages中查找到,但在mSettings.mPackages中有,且在禁用列表中,且数据目录为空时,加到 possiblyDeletedUpdatedSystemApps中
final PackageSetting disabledPs = mSettings.getDisabledSystemPkgLPr(ps.name);
if (disabledPs.codePath == null || !disabledPs.codePath.exists()) {
possiblyDeletedUpdatedSystemApps.add(ps.name);
}
}
- 查找该Package是否在PackageManagerService.mPackages和mSettings.mPackages中.如果都在,且在禁用列表中,则直接删除该apk,不再进行解析.同时将该package加到`mExpectingBetter`中
  • 如果未在mPackages中查找到,但在mSettings.mPackages中有, 但未在禁用列表中,需要将该项从mSettings.mPackages中删除

  • 如果未在mPackages中查找到,但在mSettings.mPackages中有,且在禁用列表中,且数据目录为空时,加到 possiblyDeletedUpdatedSystemApps

1.2.3.3. 处理未安装完成的app

遍历mPackages的packageSetting,如果其installStatus为PKG_INSTALL_INCOMPLETE,则调用mSettings.removePackageLPw对该包进行处理

  • 从mSettings.mPackages中删除
  • 从mSettings.mInstallerPackages中删除
  • 从其shareUser中删除该包
  • 从mUserIds或mOtherUserIds中删除
1
2
3
4
5
6
7
8
9
10
ArrayList<PackageSetting> deletePkgsList = mSettings.getListOfIncompleteInstallPackagesLPr();
for (int i = 0; i < deletePkgsList.size(); i++) {
// Actual deletion of code and data will be handled by later
// reconciliation step
final String packageName = deletePkgsList.get(i).name;
logCriticalInfo(Log.WARN, "Cleaning up incompletely installed app: " + packageName);
synchronized (mPackages) {
mSettings.removePackageLPw(packageName);
}
}

1.2.3.4. 删除临时文件以及删除没有关联的package包的shareUser

在对shareUser进行处理时,即遍历Settingss.mShareUsers, 查找其中的项有没有关联shareUserSetting,没有的话,需要将该单项从mShareUser中删除.

另外需要查看该shareuserSetting中关联的packageSetting有没有安装,并进行处理

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
// 删除安装过程中产生的临时文件, vmdl***.tmp文件
deleteTempPackageFiles();
// Remove any shared userIDs that have no associated packages
mSettings.pruneSharedUsersLPw();

void pruneSharedUsersLPw() {
ArrayList<String> removeStage = new ArrayList<String>();
for (Map.Entry<String,SharedUserSetting> entry : mSharedUsers.entrySet()) {
final SharedUserSetting sus = entry.getValue();
// mSharedUsers 绑定的 SharedUserSetting 为 null, 直接把该shareUser项从mSharedUsers中删除
if (sus == null) {
removeStage.add(entry.getKey());
continue;
}
// remove packages that are no longer installed
// 如果当前安装的包中没有 ShareUser关联的包,则删除该关联项.
// shareUser可以关联多个包, 单包没有安装,则从shareUser中删除这个关联的单包
for (Iterator<PackageSetting> iter = sus.packages.iterator(); iter.hasNext();) {
PackageSetting ps = iter.next();
if (mPackages.get(ps.name) == null) {
iter.remove();
}
}
// 如果某个shareUser关联的包列表中的所有项都没有安装,则直接将该shareuser 从mSharedUsers中去除.
if (sus.packages.size() == 0) {
removeStage.add(entry.getKey());
}
}
for (int i = 0; i < removeStage.size(); i++) {
mSharedUsers.remove(removeStage.get(i));
}
}

1.3. BOOT_PROGRESS_PMS_DATA_SCAN_START阶段

1.3.1.1. 最后扫描这几个目录下面(data app):

1
2
3
4
/data/app
/data/app-private
/system/preloadapp
/system/app-ephemeral

1.3.1.2. possiblyDeletedUpdatedSystemApps包的处理

Remove disable package settings for any updated system
apps that were removed via an OTA. If they’re not a
previously-updated app, remove them completely.
Otherwise, just revoke their system-level permissions.

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
for (String deletedAppName : possiblyDeletedUpdatedSystemApps) {
// 需要在 mPackages中查找
PackageParser.Package deletedPkg = mPackages.get(deletedAppName);
// 从禁用列表中删除
mSettings.removeDisabledSystemPackageLPw(deletedAppName);

String msg;
if (deletedPkg == null) {
msg = "Updated system package " + deletedAppName
+ " no longer exists; it's data will be wiped";
// Actual deletion of code and data will be handled by later
// reconciliation step
} else {
// 在mPakcages中查到了
msg = "Updated system app + " + deletedAppName
+ " no longer present; removing system privileges for "
+ deletedAppName;

deletedPkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_SYSTEM;

PackageSetting deletedPs = mSettings.mPackages.get(deletedAppName);
//removing system privileges
// 删除系统权限
deletedPs.pkgFlags &= ~ApplicationInfo.FLAG_SYSTEM;
}
logCriticalInfo(Log.WARN, msg);
}

对应possiblyDeletedUpdatedSystemApps, 在这个地方该包是没在mPackages,如果此处能在mPackages查到,说明中间经过了其他的扫描. 而这中间是通过扫描dataapp的,这说明该包是data app的升级包,所以此处仅撤销掉FLAG_SYSTEM的flag,标明其为data app.

1.3.1.3. mExpectingBetter的处理

对于之前监测到的禁用的apk,在删除该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
29
30
31
32
33
34
35
36
37
38
39
40
    for (int i = 0; i < mExpectingBetter.size(); i++) {
final String packageName = mExpectingBetter.keyAt(i);
if (!mPackages.containsKey(packageName)) {
final File scanFile = mExpectingBetter.valueAt(i);

logCriticalInfo(Log.WARN, "Expected better " + packageName
+ " but never showed up; reverting to system");

int reparseFlags = mDefParseFlags;
if (FileUtils.contains(privilegedAppDir, scanFile)) {
reparseFlags = PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR
| PackageParser.PARSE_IS_PRIVILEGED;
} else if (FileUtils.contains(systemAppDir, scanFile)) {
reparseFlags = PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR;
} else if (FileUtils.contains(vendorAppDir, scanFile)) {
reparseFlags = PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR;
} else if (FileUtils.contains(oemAppDir, scanFile)) {
reparseFlags = PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR;
} else {
Slog.e(TAG, "Ignoring unexpected fallback path " + scanFile);
continue;
}
// 重新启用这些package
mSettings.enableSystemPackageLPw(packageName);

try {
// 重新使用新的解析参数进行解析
scanPackageTracedLI(scanFile, reparseFlags, scanFlags, 0, null);
} catch (PackageManagerException e) {
Slog.e(TAG, "Failed to parse original system package: "
+ e.getMessage());
}
}
}
}
mExpectingBetter.clear();

1.3.1.4. 解析受保护的action filter(setupWizard相关)

Only the setup wizard is allowed to have a high priority filter for these actions.

首先看下受保护的action filter

1
2
3
4
5
6
7
private static final Set<String> PROTECTED_ACTIONS = new ArraySet<>();
static {
PROTECTED_ACTIONS.add(Intent.ACTION_SEND);
PROTECTED_ACTIONS.add(Intent.ACTION_SENDTO);
PROTECTED_ACTIONS.add(Intent.ACTION_SEND_MULTIPLE);
PROTECTED_ACTIONS.add(Intent.ACTION_VIEW);
}

mProtectedFilters是在parseActivity和解析BroadcastReceiver时根据intentfilter匹配添加的.

将开机向导处理这些mProtectedFilters的优先级设置为最高

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
// 从之前解析的所有包中查找setupwizard应用
mSetupWizardPackage = getSetupWizardPackageName();
if (mProtectedFilters.size() > 0) {
if (DEBUG_FILTERS && mSetupWizardPackage == null) {
Slog.i(TAG, "No setup wizard;"
+ " All protected intents capped to priority 0");
}
for (ActivityIntentInfo filter : mProtectedFilters) {
if (filter.activity.info.packageName.equals(mSetupWizardPackage)) {
if (DEBUG_FILTERS) {
Slog.i(TAG, "Found setup wizard;"
+ " allow priority " + filter.getPriority() + ";"
+ " package: " + filter.activity.info.packageName
+ " activity: " + filter.activity.className
+ " priority: " + filter.getPriority());
}
// skip setup wizard; allow it to keep the high priority filter
continue;
}
//拥有mProtectedFilters的其他的包的优先级降为0,降为最低,只有开机向导的优先级比较高
Slog.w(TAG, "Protected action; cap priority to 0;"
+ " package: " + filter.activity.info.packageName
+ " activity: " + filter.activity.className
+ " origPrio: " + filter.getPriority());
filter.setPriority(0);
}
}

1.3.1.5. 扫描结束后,更新所有的共享库,以及为所有的shareUser更新Abi架构集

这个地方与添加共享库后,为应用更新共享库信息呼应, 而更新指令集的部分与为shareUser统一调整指令集呼应

1
2
3
4
5
6
7
8
9
//检测pkg的 usesLibraries 和 usesOptionalLibraries 项, 如果其中有lib项,则从mSharedLibraries查找该项,如果没有找到报异常.如果能找到,则将该项的path找到,聚合应用的话,则添加包括 basecodepath splitcodepath ,将这些path更新到 pkg.usesLibraryFiles字段中
updateAllSharedLibrariesLPw();
for (SharedUserSetting setting : mSettings.getAllSharedUsersLPw()) {
// NOTE: We ignore potential failures here during a system scan (like
// the rest of the commands above) because there's precious little we
// can do about it. A settings error is reported, though.
adjustCpuAbisForSharedUserLPw(setting.packages, null /* scanned package */,
false /* boot complete */);
}

1.3.1.6. 读取PackageUsage文件更新pkg的mLastPackageUsageTimeInMills字段

Now that we know all the packages we are keeping,read and update their last usage time

1
2
// 读取data/system/package-usage.list
mPackageUsage.readLP();

data/system/package-usage.list

1
2
3
4
PACKAGE_USAGE_VERSION1
com.android.providers.telephony 0 0 0 0 1420072084352 0 1420072084443 0
com.sprd.engineermode 1420072113355 1420072113459 0 1420072405475 1420072101365 0 0 0
com.android.providers.calendar 0 0 0 1420072105482 1420072100291 0 0 0

mLastPackageUsageTimeInMills保存了下面这几项(8项 UNIX时间,转换见这里)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//Used when starting a process for an Activity.
public static final int NOTIFY_PACKAGE_USE_ACTIVITY = 0;
//Used when starting a process for a Service.
public static final int NOTIFY_PACKAGE_USE_SERVICE = 1;
//Used when moving a Service to the foreground.
public static final int NOTIFY_PACKAGE_USE_FOREGROUND_SERVICE = 2;
//Used when starting a process for a BroadcastReceiver.
public static final int NOTIFY_PACKAGE_USE_BROADCAST_RECEIVER = 3;
//Used when starting a process for a ContentProvider.
public static final int NOTIFY_PACKAGE_USE_CONTENT_PROVIDER = 4;
//Used when starting a process for a BroadcastReceiver.
public static final int NOTIFY_PACKAGE_USE_BACKUP = 5;
//Used with Context.getClassLoader() across Android packages.
public static final int NOTIFY_PACKAGE_USE_CROSS_PACKAGE = 6;
//Used when starting a package within a process for Instrumentation.
public static final int NOTIFY_PACKAGE_USE_INSTRUMENTATION = 7;

1.4. BOOT_PROGRESS_PMS_SCAN_END

上面的system扫描和data扫描结束

1.4.1.1. 更新赋予权限 updatePermissionsLPw

1
ver.sdkVersion != mSdkVersion

mSdkVersion取的是ro.build.version.sdk,这个值是编版本时指定的,指的是framework的sdk

而ver.sdkVersion是记录在packages.xml中

对于OTA升级的场景,这个值一上来就是有的.

而对于首次开机的场景,即上来packages.xml文件不存在,这个值会在mSettings.readLPw方法中创建,并将ver.sdkVersion的值设置为mSdkVersion

1
2
3
4
5
6
7
8
9
10
11
12
// 升级的场景
if (ver.sdkVersion != mSdkVersion) {
Slog.i(TAG, "Platform changed from " + ver.sdkVersion + " to "
+ mSdkVersion + "; regranting permissions for internal storage");
// 指定重新赋予 regrant权限
updateFlags |= UPDATE_PERMISSIONS_REPLACE_PKG | UPDATE_PERMISSIONS_REPLACE_ALL;
}
synchronized (mPackages) {
// Make sure there are no dangling permission trees.
updatePermissionsLPw(null, null, StorageManager.UUID_PRIVATE_INTERNAL, updateFlags);
}
ver.sdkVersion = mSdkVersion;
1.4.1.1.1. 更新权限流程图
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
@startuml
PackageManagerServcice -> PackageManagerServcice:updatePermissionsLPw
opt UPDATE_PERMISSIONS_ALL
PackageManagerServcice -> PackageManagerServcice: getVolumeUuidForPackage(pkg)
PackageManagerServcice -> PackageManagerServcice: grantPermissionsLPw(pkg, replace, changingPkg);
PackageManagerServcice ->PackageSetting: getPermissionsState
PackageSetting ->> SettingBase: getPermissionsState
PackageSetting -->> PackageManagerServcice: return PermissionsState
PackageManagerServcice -> PermissionsState: setGlobalGids
PackageManagerServcice -> PackageParser.Package:pkg.requestedPermissions.get
PackageParser.Package -> PackageManagerServcice: return requestedPermission name
PackageManagerServcice -> PackageManagerServcice: BasePermission bp = mSettings.mPermissions.get(name)
PackageManagerServcice -> BasePermission: bp.protectionLevel
opt GRANT_INSTALL
PackageManagerServcice -> PermissionsState:grantInstallPermission(bp)
else
end
opt GRANT_RUNTIME
PackageManagerServcice ->> PermissionsState:grantRuntimePermission(bp, userId)
PackageManagerServcice ->> PermissionsState:updatePermissionFlags(bp, userId,flags, flags)
else
end
opt GRANT_UPGRADE
PackageManagerServcice ->> PermissionsState:revokeInstallPermission(bp)
PackageManagerServcice ->> PermissionsState:updatePermissionFlags(bp, ...)
PackageManagerServcice ->> PermissionsState:grantRuntimePermission(bp, userId)
PackageManagerServcice ->> PermissionsState:updatePermissionFlags(bp, userId,flags, flags)
else
opt
alt GRANT_DENIED
PackageManagerServcice ->> PermissionsState:revokeInstallPermission(bp)
PackageManagerServcice ->> PermissionsState:updatePermissionFlags(bp, userId,flags, flags)
else
opt
PackageManagerServcice ->> Settings:writeRuntimePermissionsForUserLPr(userId, sync)
else
end

opt pkginfo is not null
PackageManagerServcice ->> PackageManagerServcice: getVolumeUuidForPackage(pkg)
PackageManagerServcice ->> PackageManagerServcice: grantPermissionsLPw
else
end
@enduml
1.4.1.1.2. 具体流程
1.4.1.1.2.1. updatePermissionsLPw函数更新数据在内部存储上的包
1
2
3
4
5
6
7
if (ver.sdkVersion != mSdkVersion) {
Slog.i(TAG, "Platform changed from " + ver.sdkVersion + " to "
+ mSdkVersion + "; regranting permissions for internal storage");
// 为升级场景时,携带UPDATE_PERMISSIONS_REPLACE_ALL标记
updateFlags |= UPDATE_PERMISSIONS_REPLACE_PKG | UPDATE_PERMISSIONS_REPLACE_ALL;
}
updatePermissionsLPw(null, null, StorageManager.UUID_PRIVATE_INTERNAL, updateFlags);

首先读取mSettings.mPermissionTrees上的item,如果其item对应的packageSetting为空,则从该tree上删除该item

其次读取mSettings.mPermissions上的项目, 如果权限为TYPE_DYNAMIC, bp.packageSetting 为空,则从其对应的tree 继承构造.

如果 bp.packageSetting还为空的话,需要从 mSettings.mPermissions 中删除该权限,进行下一步

最后监测是否携带了UPDATE_PERMISSIONS_ALL标记,携带此标记,说明是为所有包更新权限, 如果携带UPDATE_PERMISSIONS_REPLACE_ALL标记,将replace设置为true

调用grantPermissionsLPw(pkg, replace, changingPkg) 更新授予权限

同样检测pkgInfo是否为空,此参数表明为单个指定的包更新授予权限.如果携带UPDATE_PERMISSIONS_REPLACE_ALL标记,则将replace设置为true,调用调用grantPermissionsLPw(pkg, replace, changingPkg) 更新授予权限.

1.4.1.1.2.2. grantPermissionsLPw函数进行权限更新授予

权限类型为PROTECTION_SIGNATURE和PROTECTION_NORMAL时,为安装时权限.

但在PROTECTION_SIGNATURE的情况下,需要对签名进行校验(并不只是签名的比对),校验未通过,则grant类型为GRANT_DENIED

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
final boolean appSupportsRuntimePermissions = pkg.applicationInfo.targetSdkVersion
>= Build.VERSION_CODES.M;
switch (level) {
case PermissionInfo.PROTECTION_NORMAL: {
// For all apps normal permissions are install time ones.
grant = GRANT_INSTALL;
} break;

case PermissionInfo.PROTECTION_DANGEROUS: {
// If a permission review is required for legacy apps we represent
// their permissions as always granted runtime ones since we need
// to keep the review required permission flag per user while an
// install permission's state is shared across all users.
// 如果Build.PERMISSIONS_REVIEW_REQUIRED为true,则肯定不为GRANT_INSTALL类型
// 一般情况下,PERMISSIONS_REVIEW_REQUIRED 不进行设置, 即为false
// legacy app ,即 sdk小于M的apk, 在这种情况下,对应dangerous的权限, 授予为安装时权限
if (!appSupportsRuntimePermissions && !Build.PERMISSIONS_REVIEW_REQUIRED) {
// For legacy apps dangerous permissions are install time ones.
grant = GRANT_INSTALL;
} else if (origPermissions.hasInstallPermission(bp.name)) {
// 如果权限已经被赋予了,对应于legacy app 升级为sdk>=M的情况, 类型变为GRANT_UPGRADE
// For legacy apps that became modern, install becomes runtime.
grant = GRANT_UPGRADE;
// 对于从pre-M升级上来的 system app,即使权限没有被赋予, install->runtime
} else if (mPromoteSystemApps
&& isSystemApp(ps)
&& mExistingSystemPackages.contains(ps.name)) {
// For legacy system apps, install becomes runtime.
// We cannot check hasInstallPermission() for system apps since those
// permissions were granted implicitly and not persisted pre-M.
grant = GRANT_UPGRADE;
} else {
// For modern apps keep runtime permissions unchanged.
grant = GRANT_RUNTIME;
}
} break;

case PermissionInfo.PROTECTION_SIGNATURE: {
// For all apps signature permissions are install time ones.
// 进行签名校验,并不只是签名的比对
allowedSig = grantSignaturePermission(perm, pkg, bp, origPermissions);
if (allowedSig) {
grant = GRANT_INSTALL;
}
} break;
}

授予权限时,对应安装时权限

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
switch (grant) {
case GRANT_INSTALL: {
// Revoke this as runtime permission to handle the case of
// a runtime permission being downgraded to an install one.
// Also in permission review mode we keep dangerous permissions
// for legacy apps
// runtime权限降级为install权限,需要将runtime权限撤销
for (int userId : UserManagerService.getInstance().getUserIds()) {
if (origPermissions.getRuntimePermissionState(
bp.name, userId) != null) {
// Revoke the runtime permission and clear the flags.
origPermissions.revokeRuntimePermission(bp, userId);
origPermissions.updatePermissionFlags(bp, userId,
PackageManager.MASK_PERMISSION_FLAGS, 0);
// If we revoked a permission permission, we have to write.
changedRuntimePermissionUserIds = ArrayUtils.appendInt(
changedRuntimePermissionUserIds, userId);
}
}
// Grant an install permission.
if (permissionsState.grantInstallPermission(bp) !=
PermissionsState.PERMISSION_OPERATION_FAILURE) {
changedInstallPermission = true;
}
} break;

对应runtime权限的授予

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
case GRANT_RUNTIME: {
// Grant previously granted runtime permissions.
for (int userId : UserManagerService.getInstance().getUserIds()) {
PermissionState permissionState = origPermissions
.getRuntimePermissionState(bp.name, userId);
int flags = permissionState != null
? permissionState.getFlags() : 0;
// 原来的包中已经由该权限项,不论该权限项是否被授予
if (origPermissions.hasRuntimePermission(bp.name, userId)) {
//进行授予权限
if (permissionsState.grantRuntimePermission(bp, userId) ==
PermissionsState.PERMISSION_OPERATION_FAILURE) {
// If we cannot put the permission as it was, we have to write.
// 权限未授予成功,才对权限对应xml文件进行更新
changedRuntimePermissionUserIds = ArrayUtils.appendInt(
changedRuntimePermissionUserIds, userId);
}
// If the app supports runtime permissions no need for a review.
// permission Review时,需要更新权限对应xml文件
if (Build.PERMISSIONS_REVIEW_REQUIRED
&& appSupportsRuntimePermissions
&& (flags & PackageManager
.FLAG_PERMISSION_REVIEW_REQUIRED) != 0) {
flags &= ~PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
// Since we changed the flags, we have to write.
changedRuntimePermissionUserIds = ArrayUtils.appendInt(
changedRuntimePermissionUserIds, userId);
}
// REVIEW permission Review 且 app版本小于M版本时, 授予运行时权限
// 一般情况下,不在permission review模式下,即该字段不存在
} else if (Build.PERMISSIONS_REVIEW_REQUIRED
&& !appSupportsRuntimePermissions) {
// For legacy apps that need a permission review, every new
// runtime permission is granted but it is pending a review.
// We also need to review only platform defined runtime
// permissions as these are the only ones the platform knows
// how to disable the API to simulate revocation as legacy
// apps don't expect to run with revoked permissions.
if (PLATFORM_PACKAGE_NAME.equals(bp.sourcePackage)) {
if ((flags & FLAG_PERMISSION_REVIEW_REQUIRED) == 0) {
flags |= FLAG_PERMISSION_REVIEW_REQUIRED;
// We changed the flags, hence have to write.
changedRuntimePermissionUserIds = ArrayUtils.appendInt(
changedRuntimePermissionUserIds, userId);
}
}
if (permissionsState.grantRuntimePermission(bp, userId)
!= PermissionsState.PERMISSION_OPERATION_FAILURE) {
// We changed the permission, hence have to write.
changedRuntimePermissionUserIds = ArrayUtils.appendInt(
changedRuntimePermissionUserIds, userId);
}
}
// Propagate the permission flags.
permissionsState.updatePermissionFlags(bp, userId, flags, flags);
}
} break;

对应GRANT_UPGRADE的权限进行授予:

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
case GRANT_UPGRADE: {
// Grant runtime permissions for a previously held install permission.
PermissionState permissionState = origPermissions
.getInstallPermissionState(bp.name);
final int flags = permissionState != null ? permissionState.getFlags() : 0;
// 撤销安装时权限
if (origPermissions.revokeInstallPermission(bp)
!= PermissionsState.PERMISSION_OPERATION_FAILURE) {
// We will be transferring the permission flags, so clear them.
origPermissions.updatePermissionFlags(bp, UserHandle.USER_ALL,
PackageManager.MASK_PERMISSION_FLAGS, 0);
changedInstallPermission = true;
}

// If the permission is not to be promoted to runtime we ignore it and
// also its other flags as they are not applicable to install permissions.
// install->runtime 的权限在被撤销后会携带FLAG_PERMISSION_REVOKE_ON_UPGRADE的标志, 应用下次升级时,就不会赋予该权限了
if ((flags & PackageManager.FLAG_PERMISSION_REVOKE_ON_UPGRADE) == 0) {
for (int userId : currentUserIds) {
// 授予运行时权限
if (permissionsState.grantRuntimePermission(bp, userId) !=
PermissionsState.PERMISSION_OPERATION_FAILURE) {
// Transfer the permission flags.
permissionsState.updatePermissionFlags(bp, userId,
flags, flags);
// If we granted the permission, we have to write.
changedRuntimePermissionUserIds = ArrayUtils.appendInt(
changedRuntimePermissionUserIds, userId);
}
}
}
} break;

GRANT_DENIED类型,需要撤销安装时权限

1
2
3
4
5
6
7
8
9
10
11
12
if (permissionsState.revokeInstallPermission(bp) !=
PermissionsState.PERMISSION_OPERATION_FAILURE) {
// Also drop the permission flags.
permissionsState.updatePermissionFlags(bp, UserHandle.USER_ALL,
PackageManager.MASK_PERMISSION_FLAGS, 0);
changedInstallPermission = true;
Slog.i(TAG, "Un-granting permission " + perm
+ " from package " + pkg.packageName
+ " (protectionLevel=" + bp.protectionLevel
+ " flags=0x" + Integer.toHexString(pkg.applicationInfo.flags)
+ ")");
}

最后根据变更权限的user更新权限对应的xml文件

/data/system/users//runtime-permissions.xml

1.4.1.2. 第一次开机或者从pre-M版本升级上来,重设偏好应用

1
2
3
4
5
6
7
8
9
10
11
12
// If this is the first boot or an update from pre-M, and it is a normal
// boot, then we need to initialize the default preferred apps across
// all defined users.
// mPromoteSystemApps 标志pre-M版本升级上来
// mRestoredSettings为false 表明首次开机
if (!onlyCore && (mPromoteSystemApps || !mRestoredSettings)) {
for (UserInfo user : sUserManager.getUsers(true)) {
mSettings.applyDefaultPreferredAppsLPw(this, user.id);
applyFactoryDefaultBrowserLPw(user.id);
primeDomainVerificationsLPw(user.id);
}
}

1.4.1.3. 调整应用的数据目录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
final int storageFlags;
if (StorageManager.isFileEncryptedNativeOrEmulated()) {
// 文件加密模式,只设置DE区
storageFlags = StorageManager.FLAG_STORAGE_DE;
} else {
// 非文件加密模式, 同时设置DE区和CE区
storageFlags = StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE;
}
// Destroys app data that isn't expected, either due to uninstallation or reinstallation on another volume.
// 然后,为已安装该应用的用户准备数据目录,包括设置权限及设置selinux标签
// /data/user_de/<userid>/**
// /data/user/<userid>/**
reconcileAppsDataLI(StorageManager.UUID_PRIVATE_INTERNAL, UserHandle.USER_SYSTEM,
storageFlags);

1.4.1.4. 当监测到为升级场景时,需要删除原来包的code_cache

携带了Installer.FLAG_CLEAR_CODE_CACHE_ONLY的flag

1
2
3
4
5
6
7
8
9
10
11
12
13
14
if (mIsUpgrade && !onlyCore) {
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,
StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE
// 只清除codecache目录
| Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
}
}
ver.fingerprint = Build.FINGERPRINT;
}

1.4.1.5. 更新完应用权限,且偏好应用更新完时,重置某些字段并写入packages.xml

在这个地方会对packages.xml文件进行写入更新

1
2
3
4
5
6
7
8
9
10
11
// clear only after permissions and other defaults have been updated
// 该字段用于保存install->runtime的权限
mExistingSystemPackages.clear();
mPromoteSystemApps = false;

// All the changes are done during package scanning.
ver.databaseVersion = Settings.CURRENT_DATABASE_VERSION;

// can downgrade to reader
将上述扫描的结果写入packages.xml
mSettings.writeLPr();

1.4.1.6. 对core app执行dex优化

首次开机或者升级场景或者DalvikCache被删除时,需要对core app 执行dex优化

core app来自 pkg.coreApp, 从AndroidManifest中解析的.

1
2
3
4
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
package="com.android.proxyhandler"
coreApp="true">

1.5. BOOT_PROGRESS_PMS_READY阶段

1.5.1. 初始化PackageInstallerService

该服务主要处理来自应用安装器的安装请求

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
mInstallerService = new PackageInstallerService(context, this);
public PackageInstallerService(Context context, PackageManagerService pm) {
mContext = context;
mPm = pm;
mInstallThread = new HandlerThread(TAG);
mInstallThread.start();
mInstallHandler = new Handler(mInstallThread.getLooper());
mCallbacks = new Callbacks(mInstallThread.getLooper());

mSessionsFile = new AtomicFile(
new File(Environment.getDataSystemDirectory(), "install_sessions.xml"));
mSessionsDir = new File(Environment.getDataSystemDirectory(), "install_sessions");
mSessionsDir.mkdirs();

synchronized (mSessions) {
readSessionsLocked();

reconcileStagesLocked(StorageManager.UUID_PRIVATE_INTERNAL, false /*isEphemeral*/);
reconcileStagesLocked(StorageManager.UUID_PRIVATE_INTERNAL, true /*isEphemeral*/);

final ArraySet<File> unclaimedIcons = newArraySet(
mSessionsDir.listFiles());

// Ignore stages and icons claimed by active sessions
for (int i = 0; i < mSessions.size(); i++) {
final PackageInstallerSession session = mSessions.valueAt(i);
unclaimedIcons.remove(buildAppIconFile(session.sessionId));
}

// Clean up orphaned icons
for (File icon : unclaimedIcons) {
Slog.w(TAG, "Deleting orphan icon " + icon);
icon.delete();
}
}
}

1.5.2. 为几个变量赋值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
if (!mOnlyCore) {
// 默认校验器,来自android.intent.action.PACKAGE_NEEDS_VERIFICATION
mRequiredVerifierPackage = getRequiredButNotReallyRequiredVerifierLPr();
// 默认的安装器,来自android.intent.action.INSTALL_PACKAGE
mRequiredInstallerPackage = getRequiredInstallerLPr();
// 默认的校验器对应的component
mIntentFilterVerifierComponent = getIntentFilterVerifierComponentNameLPr();
// 校验代理
mIntentFilterVerifier = new IntentVerifierProxy(mContext,
mIntentFilterVerifierComponent);
// 使用"android.ext.services" 共享库的 client apk 的名字
mServicesSystemSharedLibraryPackageName = getRequiredSharedLibraryLPr(
PackageManager.SYSTEM_SHARED_LIBRARY_SERVICES);
// 使用"android.ext.shared" 共享库的 client apk的名字
mSharedSystemSharedLibraryPackageName = getRequiredSharedLibraryLPr(
PackageManager.SYSTEM_SHARED_LIBRARY_SHARED);
}

1.5.3. ephemeral app 安装准备

  • 获取解析ephemeral app 的组件
  • 获取安装ephemeral app 的组件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
final ComponentName ephemeralResolverComponent = getEphemeralResolverLPr();
final ComponentName ephemeralInstallerComponent = getEphemeralInstallerLPr();
// both the installer and resolver must be present to enable ephemeral
if (ephemeralInstallerComponent != null && ephemeralResolverComponent != null) {
if (DEBUG_EPHEMERAL) {
Slog.i(TAG, "Ephemeral activated; resolver: " + ephemeralResolverComponent
+ " installer:" + ephemeralInstallerComponent);
}
mEphemeralResolverComponent = ephemeralResolverComponent;
mEphemeralInstallerComponent = ephemeralInstallerComponent;
// 初始化mEphemeralInstallerActivity 对应 ActivityInfo数据的基础信息
setUpEphemeralInstallerActivityLP(mEphemeralInstallerComponent);
mEphemeralResolverConnection =
new EphemeralResolverConnection(mContext, mEphemeralResolverComponent);
}

1.5.4. 注册PackageManagerInternal 私有LOCAL service服务

通过该local service, server进程内的所有服务可以通过其公布的接口拿到或设置一些组件的信息

具体可以查看 PackageManagerInternalImpl类

如使用getHomeActivitiesAsUser 查询 home activity的component name

至此, pkms的构造函数执行完毕.