Android persistent属性原理分析
[TOC] 以下代码基于Android9.0
persistent属性的定义
开发系统应用时,有时我们需要应用常驻,被杀死后能够自动重启,此时就需要使用到persistent属性, 下面是关于该属性在framework层的定义,属性的定义位于 persistent属性定义在platform/frameworks/base/core/res/res/values/attrs_manifest.xml文件内:
1
2
<!-- 控制应用程序是否处于特殊持久模式的标志,通常情况下不应该被使用,该标志位能够保证应用程序一直运行 -->
<attr name="persistent" format="boolean" />
persistent属性的使用
开发系统应用时,有时我们需要应用常驻,被杀死后能够自动重启,此时我们就要在应用的AndroidManifest.xml中设置
1
android:persistent="true"
设置后应用就具备了以下两个特性:
- 系统启动时该应用也会启动
- 应用被杀死后,系统会重启该应用
persistent属性的原理
persistent属性的解析
当我们应用安装或启动的过程中,会对AndroidManifest.xml进行解析,解析相关的代码位于 platform/frameworks/base/core/java/android/content/pm/PackageParser.java:
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
public class PackageParser {
....
private boolean parseBaseApplication(Package owner, Resources res,
XmlResourceParser parser, int flags, String[] outError)
throws XmlPullParserException, IOException {
final ApplicationInfo ai = owner.applicationInfo;
final String pkgName = owner.applicationInfo.packageName;
// 获取 AndroidManifest 的属性
TypedArray sa = res.obtainAttributes(parser,
com.android.internal.R.styleable.AndroidManifestApplication);
....
// 获取所设置的 persistent 值,默认为 false
if (sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestApplication_persistent,
false)) {
// 检查应用是否支持这个权限
final String requiredFeature = sa.getNonResourceString(com.android.internal.R.styleable
.AndroidManifestApplication_persistentWhenFeatureAvailable);
if (requiredFeature == null || mCallback.hasFeature(requiredFeature)) {
// 将 persistent 的 flag 设置到应用信息中
ai.flags |= ApplicationInfo.FLAG_PERSISTENT;
}
}
....
}
....
}
解析后就会将应用的各种信息保存在PKMS中的一个存储所有应用信息的一个Map中,其中设置了persistent的应用就包含了ApplicationInfo.FLAG_PERSISTENT标志位,之后在系统的启动过程中就会根据这个标志位控制应用的启动。
persistent应用的启动
persistent应用的启动发生在AMS的systemReady方法内,这一部分通过PKMS获取到所有persistent为true的应用列表,之后对列表进行遍历,通过addAppLocked方法将应用一个个启动起来。 对应代码的位于 /platform/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
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
public class ActivityManagerService extends IActivityManager.Stub
implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
....
// 该静态常量用于判断应用是否persistent应用
private static final int PERSISTENT_MASK =
ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT;
// 当系统服务启动时,AMS执行systemReady方法
public void systemReady(final Runnable goingCallback, TimingsTraceLog traceLog) {
....
synchronized (this) {
// 1.启动所有persistent属性为true的应用
startPersistentApps(PackageManager.MATCH_DIRECT_BOOT_AWARE);
....
}
}
....
void startPersistentApps(int matchFlags) {
if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL) return;
synchronized (this) {
try {
// 从PKMS的应用MAP中拿到所有具有FLAG_PERSISTENT标志位的应用
final List<ApplicationInfo> apps = AppGlobals.getPackageManager()
.getPersistentApplications(STOCK_PM_FLAGS | matchFlags).getList();
for (ApplicationInfo app : apps) {
// 过滤掉包名为android的应用
if (!"android".equals(app.packageName)) {
//2. 添加并启动该APP进程
addAppLocked(app, null, false, null /* ABI override */);
}
}
} catch (RemoteException ex) {
}
}
}
}
获得所有具有FLAG_PERSISTENT标志位的应用
platform/frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
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
public class PackageManagerService extends IPackageManager.Stub
implements PackageSender {
....
// 存放所有应用的信息的Map
final ArrayMap<String, PackageParser.Package> mPackages =
new ArrayMap<String, PackageParser.Package>();
....
@Override
public @NonNull ParceledListSlice<ApplicationInfo> getPersistentApplications(int flags) {
if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
return ParceledListSlice.emptyList();
}
return new ParceledListSlice<>(getPersistentApplicationsInternal(flags));
}
private @NonNull List<ApplicationInfo> getPersistentApplicationsInternal(int flags) {
final ArrayList<ApplicationInfo> finalList = new ArrayList<ApplicationInfo>();
synchronized (mPackages) {
final Iterator<PackageParser.Package> i = mPackages.values().iterator();
final int userId = UserHandle.getCallingUserId();\
// 遍历mPackages
while (i.hasNext()) {
final PackageParser.Package p = i.next();
if (p.applicationInfo == null) continue;
....
// 判断应用信息是否有FLAG_PERSISTENT标志位
if ((p.applicationInfo.flags & ApplicationInfo.FLAG_PERSISTENT) != 0
&& (!mSafeMode || isSystemApp(p))
&& (matchesUnaware || matchesAware)) {
PackageSetting ps = mSettings.mPackages.get(p.packageName);
if (ps != null) {
ApplicationInfo ai = PackageParser.generateApplicationInfo(p, flags,
ps.readUserState(userId), userId);
if (ai != null) {
// 将应用的ApplicationInfo添加进列表
finalList.add(ai);
}
}
}
}
}
return finalList;
}
}
添加并启动应用进程
AMS内有一个存放所有正在启动的persistent应用的List:mPersistentStartingProcesses,后续在启动应用和重启应用时都会使用到该List。
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
public class ActivityManagerService extends IActivityManager.Stub
implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
/**
* 正在启动的persistent应用程序列表。
*/
final ArrayList<ProcessRecord> mPersistentStartingProcesses = new ArrayList<ProcessRecord>();
....
final ProcessRecord addAppLocked(ApplicationInfo info, String customProcess, boolean isolated,
String abiOverride) {
return addAppLocked(info, customProcess, isolated, false /* disableHiddenApiChecks */,
abiOverride);
}
final ProcessRecord addAppLocked(ApplicationInfo info, String customProcess, boolean isolated,
boolean disableHiddenApiChecks, String abiOverride) {
// ProcessRecord是用于描述进程的数据结构
ProcessRecord app;
// 传入的isolated为false
if (!isolated) {
// 第一次启动,这里查找应用所在的进程返回都为null
app = getProcessRecordLocked(customProcess != null ? customProcess : info.processName,
info.uid, true);
} else {
app = null;
}
if (app == null) {
// 为应用创建ProcessRecord
app = newProcessRecordLocked(info, customProcess, isolated, 0);
updateLruProcessLocked(app, false, null);
updateOomAdjLocked();
}
....
if ((info.flags & PERSISTENT_MASK) == PERSISTENT_MASK) {
app.persistent = true;
app.maxAdj = ProcessList.PERSISTENT_PROC_ADJ;
}
// 整个启动过程是异步的,所以这里仍需要判断应用线程是否为null,同时判断应用是否正在启动中(在mPersistentStartingProcesses列表内)
if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
// 应用没有在启动,则将应用添加到mPersistentStartingProcesses列表
mPersistentStartingProcesses.add(app);
// 启动应用
startProcessLocked(app, "added application",
customProcess != null ? customProcess : app.processName, disableHiddenApiChecks,
abiOverride);
}
return app;
}
....
}
系统启动时应用的ProcessRecord都未创建,所以在addAppLocked内首先通过newProcessRecordLocked为应用程序创建ProcessRecord,之后调用startProcessLocked来启动应用程序,启动的过程不是这部分的重点,就不再详细说明。
persistent应用启动完成
当应用启动完毕后就会调用到ActivityThread.java内的attach方法,方法内调用了AMS的attachApplication方法,之后再到attachApplicationLocked,该方法内部就会将应用移除mPersistentStartingProcesses列表,表明应用启动完毕,同时为应用并注册一个死亡监听器AppDeathRecipient,用于应用被异常杀死后的重启。
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
public class ActivityManagerService extends IActivityManager.Stub
implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
....
private boolean attachApplicationLocked(@NonNull IApplicationThread thread,
int pid, int callingUid, long startSeq) {
....
final String processName = app.processName;
try {
AppDeathRecipient adr = new AppDeathRecipient(
app, pid, thread);
thread.asBinder().linkToDeath(adr, 0);
app.deathRecipient = adr;
} catch (RemoteException e) {
app.resetPackageList(mProcessStats);
//如果注册死亡接收器失败,也会重新启动App进程
startProcessLocked(app, "link fail", processName);
return false;
}
....
// 将应用移除正在启动的持久性应用列表
mPersistentStartingProcesses.remove(app);
....
}
}
persistent应用死亡后重启
当应用被杀死后,就会调用死亡接收器AppDeathRecipient的binderDied方法,方法内根据应用是否是persistent应用来控制是否重启,整个流程如下:
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
public class ActivityManagerService extends IActivityManager.Stub
implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
....
private final class AppDeathRecipient implements IBinder.DeathRecipient {
final ProcessRecord mApp;
final int mPid;
final IApplicationThread mAppThread;
AppDeathRecipient(ProcessRecord app, int pid,
IApplicationThread thread) {
mApp = app;
mPid = pid;
mAppThread = thread;
}
@Override
public void binderDied() {
synchronized(ActivityManagerService.this) {
// 1. 调用appDiedLocked
appDiedLocked(mApp, mPid, mAppThread, true);
}
}
}
final void appDiedLocked(ProcessRecord app, int pid, IApplicationThread thread,
boolean fromBinderDied) {
....
if (app.pid == pid && app.thread != null &&
app.thread.asBinder() == thread.asBinder()) {
....
// 2. 调用appDiedLocked
handleAppDiedLocked(app, false, true);
....
}
....
}
private final void handleAppDiedLocked(ProcessRecord app,
boolean restarting, boolean allowRestart) {
int pid = app.pid;
// 3. 调用appDiedLocked
boolean kept = cleanUpApplicationRecordLocked(app, restarting, allowRestart, -1,
false /*replacingPid*/);
....
}
private final boolean cleanUpApplicationRecordLocked(ProcessRecord app,
boolean restarting, boolean allowRestart, int index, boolean replacingPid) {
....
// 判断应用是否是persistent应用
if (!app.persistent || app.isolated) {
// 如果不是persistent应用,则直接被清理掉
....
} else if (!app.removed) {
// 如果是persistent应用,则保留相应的信息
// 判断其是否在待启动应用程序mPersistentStartingProcesses列表
// 不在的话则添加,并设置restart为true
if (mPersistentStartingProcesses.indexOf(app) < 0) {
mPersistentStartingProcesses.add(app);
restart = true;
}
}
if (restart && !app.isolated) {
// 重新启动我们的应用进程
if (index < 0) {
ProcessList.remove(app.pid);
}
addProcessNameLocked(app);
app.pendingStart = false;
// 启动应用程序进程
startProcessLocked(app, "restart", app.processName);
return true;
} else if (app.pid > 0 && app.pid != MY_PID) {
// 不需要重启的应用
boolean removed;
synchronized (mPidsSelfLocked) {
mPidsSelfLocked.remove(app.pid);
mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
}
mBatteryStatsService.noteProcessFinish(app.processName, app.info.uid);
if (app.isolated) {
mBatteryStatsService.removeIsolatedUid(app.uid, app.info.uid);
}
app.setPid(0);
}
}
}
经过这个过程之后,persistent属性为true的应用程序进程就会被重启。