引入 在Android系统App中(注意是系统App),都会添加一个persistent 属性,表明此应用是一个永久性应用,就是从系统一开机就一直运行,直到系统关机。他的另外一个特写是,服务被杀死后会自动重启,本篇就来一探究竟。
AndroidManifest.xml
android:persistent="true"
启动
Android系统在启动时,ActivityManagerService 会调用systemReady 方法,在这里会调起所谓的 永久性应用:
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, null );
}
}
}
} catch (RemoteException ex) {
}
...
}
先来看看 getPersistentApplications(),它的定义在PKMS中:
public List<ApplicationInfo> getPersistentApplications(int flags) {
final ArrayList<ApplicationInfo> finalList = new ArrayList<ApplicationInfo>();
synchronized (mPackages) {
final Iterator<PackageParser.Package> i = mPackages.values().iterator();
final int userId = UserHandle.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);
if (ps != null) {
ApplicationInfo ai = PackageParser.generateApplicationInfo(p, flags,
ps.readUserState(userId), userId);
if (ai != null) {
finalList.add(ai);
}
}
}
}
}
return finalList;
}
注意这里有过滤非系统App:isSystemApp§,只有系统App 才会添加到列表里面。 再回到传给AMS的addAppLocked()方法:
final ProcessRecord addAppLocked(ApplicationInfo info, boolean isolated,
String abiOverride) {
ProcessRecord app;
...
if (app == null) {
app = newProcessRecordLocked(info, null, isolated, 0);
mProcessNames.put(info.processName, app.uid, app);
if (isolated) {
mIsolatedProcesses.put(app.uid, app);
}
updateLruProcessLocked(app, false, null);
updateOomAdjLocked();
}
try {
AppGlobals.getPackageManager().setPackageStoppedState(
info.packageName, false, UserHandle.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, abiOverride,
null , null );
}
return app;
}
这里再次通过ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT 过滤非系统APP. 并设置 app.persistent = true;最后调用startProcessLocked()启动进程。 当进程启动成功之后,便会从mPersistentStartingProcesses里删除这个进程。
private final boolean attachApplicationLocked() {
...
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);
startProcessLocked(app, "link fail", processName);
return false;
}
mPersistentStartingProcesses.remove(app);
mProcessesOnHold.remove(app);
if (!didSomething) {
updateOomAdjLocked();
}
...
}
补充:第三方应用及时带有persist属性,在进程创建时,也会被拦截
private static final int PERSISTENT_MASK =
ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT;
final ProcessRecord newProcessRecordLocked(ApplicationInfo info, String customProcess,
boolean isolated, int isolatedUid) {
...
final ProcessRecord r = new ProcessRecord(this, stats, info, proc, uid);
if (!mBooted && !mBooting
&& userId == UserHandle.USER_SYSTEM
&& (info.flags & PERSISTENT_MASK) == PERSISTENT_MASK) {
r.curSchedGroup = ProcessList.SCHED_GROUP_DEFAULT;
r.setSchedGroup = ProcessList.SCHED_GROUP_DEFAULT;
r.persistent = true;
r.maxAdj = ProcessList.PERSISTENT_PROC_ADJ;
}
...
addProcessNameLocked(r);
return r;
}
服务重启
我们知道每一个应用进程里都会有一个ApplicationThread mAppThread对象,AMS通过它在AMS里的代理接口IApplicationThread与应用进程进行通信。(attachApplicationLocked 函数里面的第一个参数thread,就是一个应用进程在AMS里的代理对象) 在应用进程启动时,会调用ActivityThread的attach()方法将自己依附于AMS当中,也就是由AMS启动它并对它进行管理,attach()最终通过binder机制调用到AMS的attachApplicationLocked()方法。 再次贴出上面的关键代码:
private final boolean attachApplicationLocked(IApplicationThread thread...) {
...
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);
startProcessLocked(app, "link fail", processName);
return false;
}
...
}
上面AppDeathRecipient 在AMS中声明如下:
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
private final class AppDeathRecipient implements IBinder.DeathRecipient {
final ProcessRecord mApp;
final int mPid;
final IApplicationThread mAppThread;
AppDeathRecipient(ProcessRecord app, int pid,
IApplicationThread thread) {
if (DEBUG_ALL) Slog.v(
TAG, "New death recipient " + this
+ " for thread " + thread.asBinder());
mApp = app;
mPid = pid;
mAppThread = thread;
}
@Override
public void binderDied() {
if (DEBUG_ALL) Slog.v(
TAG, "Death received in " + this
+ " for thread " + mAppThread.asBinder());
synchronized(ActivityManagerService.this) {
appDiedLocked(mApp, mPid, mAppThread, true);
}
}
}
当应用进程死掉时,系统会回调由linkToDeath()注册的AppDeathRecipient对象的binderDied()方法。 有如下调用关系
binderDied();
appDiedLocked();
handleAppDiedLocked();
cleanUpApplicationRecordLocked();
在cleanUpApplicationRecordLocked() 函数里面,我们看到了关键处理:
private final boolean cleanUpApplicationRecordLocked(ProcessRecord app,
boolean restarting, boolean allowRestart, int index, boolean replacingPid) {
...
if (!app.persistent || app.isolated) {
if (DEBUG_PROCESSES || DEBUG_CLEANUP) Slog.v(TAG_CLEANUP,
"Removing non-persistent process during cleanup: " + app);
if (!replacingPid) {
removeProcessNameLocked(app.processName, app.uid, app);
}
if (mHeavyWeightProcess == app) {
mHandler.sendMessage(mHandler.obtainMessage(CANCEL_HEAVY_NOTIFICATION_MSG,
mHeavyWeightProcess.userId, 0));
mHeavyWeightProcess = null;
}
} else if (!app.removed) {
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) {
...
}
可以看到,如果是非persist的进程死亡,则直接回收所有的进程资源。 persist的进程,就会再加入mPersistentStartingProcesses队列,然后等待重启。
彩蛋:利用persist 属性可以自启动的原理,我们也可以利用增加白名单方式,将进程加入persist属性, 实现常驻和自启动:
final ProcessRecord startProcessLocked(String processName, ApplicationInfo info,
...
if (app == null) {
checkTime(startTime, "startProcess: creating new process record");
app = newProcessRecordLocked(info, processName, isolated, isolatedUid);
if (app == null) {
Slog.w(TAG, "Failed making new process record for "
+ processName + "/" + info.uid + " isolated=" + isolated);
return null;
}
List<String> persistentAdList = ThirdPartyPermissions.getPersistentAdApps(mContext);
if (app != null && null != persistentAdList && persistentAdList.contains(processName)) {
app.persistent = true;
app.maxAdj = ProcessList.PERSISTENT_PROC_ADJ;
if (mPersistentStartingProcesses.indexOf(app) < 0) {
mPersistentStartingProcesses.add(app);
}
}
app.crashHandler = crashHandler;
mProcessNames.put(processName, app.uid, app);
if (isolated) {
mIsolatedProcesses.put(app.uid, app);
}
checkTime(startTime, "startProcess: done creating new process record");
}
...
|