一、标识persistent=”true”的app启动过程

        在源码/frameworks/base/core/res/res/values/attrs_manifest.xml中这样描述:

1
2
3
4
<!-- Flag to control special persistent mode of an application. This should
not normally be used by applications; it requires that the system keep
your application running at all times. -->
<attr name="persistent" format="boolean" />

        配置该属性的app有如下特点:
* 在android系统启动的时候会自动启动;
* app被强制杀掉后,系统会重新启动app,app必须安装在/system/app路径下。

        app在安装或者系统启动的时候解析androidmanifest.xml文件中的persistent属性,解析源码在/frameworks/base/core/java/com/android/content/pm/PackageParser.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
private boolean parseBaseApplication(Package owner, Resources res,
XmlPullParser parser,
AttributeSet attrs,
int flags,
String[] outError)
throws XmlPullParserException, IOException {
// ............
if ((flags&PARSE_IS_SYSTEM) != 0) {
if (sa.getBoolean(
com.android.internal
.R.styleable.AndroidManifestApplication_persistent,
false)) {
ai.flags |= ApplicationInfo.FLAG_PERSISTENT;
}
}
// ............
}

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;系统启动,在systemReady()加载所有persistent=true的应用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public void systemReady(final Runnable goingCallback) {
// ............
try {
List apps = AppGlobals.getPackageManager()
.getPersistentApplications(STOCK_PM_FLAGS);
if (apps != null) {
int N = apps.size();
int i;
for (i=0; i<N; i++) {
ApplicationInfo info = (ApplicationInfo)apps.get(i);
if (info != null &&
!info.packageName.equals("android"))
{
addAppLocked(info, false);
}
}
}
} catch (RemoteException ex) {
// pm is in same process, this will never happen.
}
}

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;其中 getPersistentApplications()函数的定义如下:

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
public List<ApplicationInfo> getPersistentApplications(int flags) {
final ArrayList<ApplicationInfo> finalList
= new ArrayList<ApplicationInfo>();
// reader
synchronized (mPackages)
{
final Iterator<PackageParser.Package> i
= mPackages.values().iterator();
final int userId = UserId.getCallingUserId();
while (i.hasNext())
{
final PackageParser.Package p = i.next();
if (p.applicationInfo != null
&& (p.applicationInfo.flags
& ApplicationInfo.FLAG_PERSISTENT) != 0
&& (!mSafeMode || isSystemApp(p)))
{
PackageSetting ps = mSettings
.mPackages.get(p.packageName);
finalList.add(PackageParser.generateApplicationInfo(p, flags,
ps != null ? ps.getStopped(userId) : false,
ps != null ? ps.getEnabled(userId) : COMPONENT_ENABLED_STATE_DEFAULT,
userId));
}
}
}
return finalList;
}

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;在PKMS中,有一个记录所有的程序包信息的哈希表(mPackages),每个表项中含有ApplicationInfo信息,该信息的flags(int型)数据中有一个专门的bit用于表示persistent。getPersistentApplications()函数会遍历这张表,找出所有persistent包,如果选中的persistent包是系统应用,或者当前系统处于非安全模式,则将persistent包添加到ArrayList

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;随后systemReady()开始遍历选中的ApplicationInfo,并对包名不为“android”的结点执行addAppLocked()。

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
final ProcessRecord addAppLocked(ApplicationInfo info, boolean isolated) {
ProcessRecord app;
if (!isolated) {
app = getProcessRecordLocked(info.processName, info.uid);
} else {
app = null;
}

if (app == null) {
app = newProcessRecordLocked(null, info, null, isolated);
mProcessNames.put(info.processName, app.uid, app);
if (isolated) {
mIsolatedProcesses.put(app.uid, app);
}
updateLruProcessLocked(app, true, true);
}

// This package really, really can not be stopped.
try {
AppGlobals
.getPackageManager()
.setPackageStoppedState( info.packageName, false, UserId.getUserId(app.uid));
} catch (RemoteException e) {
} catch (IllegalArgumentException e) {
Slog.w(TAG, "Failed trying to unstop package " + info.packageName + ": " + e);
}

if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
== (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
app.persistent = true;
app.maxAdj = ProcessList.PERSISTENT_PROC_ADJ;
}

if (app.thread == null
&& mPersistentStartingProcesses.indexOf(app) < 0) {
mPersistentStartingProcesses.add(app);
startProcessLocked(app, "added application", app.processName);
}
return app;
}

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;在AMS中,所谓的“add App”主要是指“添加一个与App进程对应的ProcessRecord节点”。在添加节点的动作完成以后,addAppLocked()还会检查App进程是否已经启动好了,如果尚未开始启动,此时就会调用startProcessLocked()启动这个进程。既然addAppLocked()试图确认App“正在正常运作”或者“将被正常启动”,那么其对应的package就不可能处于stopped状态。

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;自此,我们已知设置了persistent=”true”的应用是随着系统启动就即时启动了。

二、如何保持应用的持久性(persistent)

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;本身persistent一词翻译过来即持久、固执的意思。在android系统内,persistent应用会随着系统启动而启动,一直持续到系统关机。


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;为了保证这种持久性,persistent应用必须能够在异常出现时,自动重新启动。在Android里是这样实现的。每个ActivityThread中会有一个专门和AMS通信的binder实体——final ApplicationThread mAppThread。这个实体在AMS中对应的代理接口为IApplicationThread。


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;当AMS执行到attachApplicationLocked()时,会针对目标用户进程的IApplicationThread接口,注册一个binder讣告监听器,一旦日后用户进程意外挂掉,AMS就能在第一时间感知到,并采取相应的措施。如果AMS发现意外挂掉的应用是persistent的,它会尝试重新启动这个应用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
private final class AppDeathRecipient implements IBinder.DeathRecipient {
final ProcessRecord mApp;
final int mPid;
final IApplicationThread mAppThread;
AppDeathRecipient(ProcessRecord app, int pid, IApplicationThread thread) {
if (localLOGV)
Slog.v(TAG, "New death recipient " + this + " for thread " + thread.asBinder());
mApp = app;
mPid = pid;
mAppThread = thread;
}

public void binderDied() {
if (localLOGV)
Slog.v(TAG, "Death received in " + this + " for thread " + mAppThread.asBinder());
synchronized(ActivityManagerService.this) {
appDiedLocked(mApp, mPid, mAppThread);
}
}
}

        当其监听的binder实体死亡时,系统会回调AppDeathRecipient的binderDied()。
image
image

        一般情况下,当一个应用进程挂掉后,AMS当然会清理掉其对应的ProcessRecord,这就是cleanUpApplicationRecordLocked()的主要工作。然而,对于persistent应用,cleanUpApplicationRecordLocked()会尝试再次启动对应的应用进程。