https://blog.youkuaiyun.com/u013553529/article/details/61962439
PackageManagerService中的方法名中的LI、LIF、LPw、LPr的含义
注1:本文参考Android 7.1.1r13源码中的PackageManagerService的说明。
这个说明在Android6.0.1中是没有的。
注2:本文中PackageManagerService简称为PMS。
1. 方法名后缀为LI、LIF、LPw、LPr的方法
这里只列举一部分。
| 后缀 | 方法名 |
|---|---|
| LI | collectCertificatesLI() installPackageLI() scanPackageLI() scanDirLI() |
| LIF | deletePackageLIF() deleteSystemPackageLIF() clearApplicationUserDataLIF() clearAppDataLIF() |
| LP | verifySignaturesLP() checkPermissionTreeLP() findPermissionTreeLP() findPersistentPreferredActivityLP() |
| LPw | grantPermissionsLPw() updatePermissionsLPw() enableSystemPackageLPw() setInstallerPackageNameLPw() |
| LPr | getRequiredInstallerLPr() verifyPackageUpdateLPr() normalizePackageNameLPr() needsNetworkVerificationLPr() |
2. PMS中的两个锁
要想弄明白方法名中的LI、LIF、LPw、LPr的含义,需要先了解PackageManagerService内部使用的两个锁。因为LI、LIF、LPw、LPr中的L,指的是Lock,而后面跟的I和P指的是两个锁,I表示mInstallLock同步锁。P表示mPackages同步锁。LPw、LPr中的w表示writing,r表示reading。LIF中的F表示Freeze。
mPackages同步锁,是指操作mPackages时,用synchronized (mPackages) {}保护起来。mPackages同步锁用来保护内存中已经解析的包信息和其他相关状态。mPackages同步锁是细粒度的锁,只能短时间持有这个锁,因为争抢mPackages锁的请求很多,短时间持有mPackages锁,可以让其他请求等待的时间短些。
mInstallLock同步锁,是指安装App的时候,对安装的处理要用synchronized (mInstaller) {}保护起来。mInstallLock同步锁,用来保护所有对installd的访问。installd通常包含对应用数据的繁重操作。
由于installd是单线程的,并且installd的操作通常很慢,所以在已经持有mPackages同步锁的时候,千万不要再请求mInstallLock同步锁。反之,在已经持有mInstallLock同步锁的时候,可以去请求mPackages同步锁。
用代码表示出来,是这样的:
注意:不允许的情况:
synchronized (mPackages) {
synchronized (mInstaller) {
// 这种情况是不允许的。因为Install的处理时间会很长,导致对mPackages锁住的时间加长,会使得其他对mPackages操作的请求处于长时间等待。
}
}
- 1
- 2
- 3
- 4
- 5
允许的情况:
synchronized (mInstaller) {
synchronized (mPackages) {
// 这种情况是允许的。因为mPackages处理完之后,其他对mPackages操作的请求可以对mPackages处理,不需要等待太久。
// 由于处理Install的时间本身很长,synchronized (mPackages)又较快,所以不会对原本长时间持有mInstaller锁的情况有大的影响。
}
}
- 1
- 2
- 3
- 4
- 5
- 6
注:关于Java同步的官方说明:https://docs.oracle.com/javase/tutorial/essential/concurrency/sync.html
3. 方法名中的LI、LIF、LPw、LPr的含义
| 方法名 | 使用方式 |
|---|---|
| fooLI() | 调用fooLI(),必须先持有mInstallLock锁。 |
| fooLIF() | 调用fooLIF(),必须先持有mInstallLock锁,并且正在被修改的包(package)必须被冻结(be frozen)。 |
| fooLPr() | 调用fooLPr(),必须先持有mPackages锁,并且只用于读操作。 |
| fooLPw() | 调用fooLPw(),必须先持有mPackages锁,并且只用于写操作。 |
举一些例子:
例1:方法名中带有LP的方法:verifySignaturesLP()
使用verifySignaturesLP()的时候,要加上synchronized (mPackages)或者在其他带LP的方法中使用。
synchronized (mPackages) {
//省略其他代码
verifySignaturesLP(pkgSetting, pkg);
}
- 1
- 2
- 3
- 4
例2: 方法名中带有LI的方法:installPackageLI()和installPackageTracedLI()
使用installPackageTracedLI()的时候,加上synchronized (mInstallLock):
synchronized (mInstallLock) {
installPackageTracedLI(args, res);
}
- 1
- 2
- 3
调用installPackageLI()的时候,没有加上synchronized (mInstallLock),但是在带有LI的方法中使用,例如installPackageTracedLI()中调用installPackageLI():
private void installPackageTracedLI(InstallArgs args, PackageInstalledInfo res) {
try {
installPackageLI(args, res);
}
...
}
- 1
- 2
- 3
- 4
- 5
- 6
4. @GuardedBy 注解
在代码中还有一种@GuardedBy注解(com.android.internal.annotations.GuardedBy),用于标记哪些变量要用同步锁保护起来。
例1:@GuardedBy(“mPackages”)
@GuardedBy("mPackages")
private boolean mDexOptDialogShown;
- 1
- 2
上面的@GuardedBy注解表示所有使用mDexOptDialogShown的地方,都要用synchronized (mPackages)保护起来,以保证并发时不会有错误。
例如,
synchronized (mPackages) {
mDexOptDialogShown = true;
}
synchronized (mPackages) {
dexOptDialogShown = mDexOptDialogShown;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
例2:@GuardedBy(“mInstallLock”)
带@GuardedBy("mInstallLock")注解的变量:mInstaller。如下:
@GuardedBy("mInstallLock")
final Installer mInstaller;
- 1
- 2
所以,使用mInstaller的地方都要用synchronized (mInstallLock)保护起来。
例如,
synchronized (mInstallLock) {
mSettings.createNewUserLI(this, mInstaller, userId);
}
synchronized (mInstallLock) {
mInstaller.createUserData(volumeUuid, userId, userSerial, flags);
}
synchronized (mInstallLock) {
// 注意这里的info.args是InstallArgs。PMS中对InstallArgs的处理,也是用mInstallLock锁保护起来的。
info.args.doPostDeleteLI(true);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
PMS中还有synchronized (mInstaller)这种同步锁。不知道是笔误,还是就是这样子的。
synchronized (mInstaller) {
try {
mInstaller.moveCompleteApp(move.fromUuid, move.toUuid, move.packageName,
move.dataAppName, move.appId, move.seinfo, move.targetSdkVersion);
}
...
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
synchronized (mInstaller) {
for (int userId : installedUserIds) {
if (!getPackageSizeInfoLI(packageName, userId, stats)) {
freezer.close();
...
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
需要注意的是:在有的编译环境中可能并不检查@GuardedBy注解,即标有@GuardedBy注解的变量也可能会出现错误用法(即,没有被同步锁保护起来)。某些静态分析工具(例如FindBug)可能会检查@GuardedBy注解,以保证相关变量被正确的使用(即,被同步锁保护起来)。
注:FindBug中检查的GuardedBy注解,是net.jcip.annotations.GuardedBy,不是Android中的com.android.internal.annotations.GuardedBy。
5. 附:PMS中的原始内容
/**
* Keep track of all those APKs everywhere.
* <p>
* Internally there are two important locks:
* <ul>
* <li>{@link #mPackages} is used to guard all in-memory parsed package details
* and other related state. It is a fine-grained lock that should only be held
* momentarily, as it's one of the most contended locks in the system.
* <li>{@link #mInstallLock} is used to guard all {@code installd} access, whose
* operations typically involve heavy lifting of application data on disk. Since
* {@code installd} is single-threaded, and it's operations can often be slow,
* this lock should never be acquired while already holding {@link #mPackages}.
* Conversely, it's safe to acquire {@link #mPackages} momentarily while already
* holding {@link #mInstallLock}.
* </ul>
* Many internal methods rely on the caller to hold the appropriate locks, and
* this contract is expressed through method name suffixes:
* <ul>
* <li>fooLI(): the caller must hold {@link #mInstallLock}
* <li>fooLIF(): the caller must hold {@link #mInstallLock} and the package
* being modified must be frozen
* <li>fooLPr(): the caller must hold {@link #mPackages} for reading
* <li>fooLPw(): the caller must hold {@link #mPackages} for writing
* </ul>
* <p>
* Because this class is very central to the platform's security; please run all
* CTS and unit tests whenever making modifications:
*
* <pre>
* $ runtest -c android.content.pm.PackageManagerTests frameworks-core
* $ cts-tradefed run commandAndExit cts -m AppSecurityTests
* </pre>
*/
- 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
8353

被折叠的 条评论
为什么被折叠?



