为什么80%的码农都做不了架构师?>>>
Android5.1.1源码 - App服务进程被杀后自动重启的原因
@(Android研究)[App服务重启]
[TOC]
前言
当通过长按HOME键的方式
清理一个App时,不仅这个App进程会被杀掉,与这个App相关的服务进程也会被杀掉,但是服务进程被杀后会被系统重启,在下文中分析了重启的原因。
分析
长按HOME键清理App最终会执行到ActivityManagerService.cleanUpRemovedTaskLocked方法中,ActivityManagerService类在文件"frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java"中,下面是ActivityManagerService.cleanUpRemovedTaskLocked方法的源码:
private void cleanUpRemovedTaskLocked(TaskRecord tr, boolean killProcess) {
mRecentTasks.remove(tr);
tr.removedFromRecents();
ComponentName component = tr.getBaseIntent().getComponent();
if (component == null) {
Slog.w(TAG, "No component for base intent of task: " + tr);
return;
}
......
// Find any running services associated with this app and stop if needed.
mServices.cleanUpRemovedTaskLocked(tr, component, new Intent(tr.getBaseIntent()));
// Kill the running processes.
for (int i = 0; i < procsToKill.size(); i++) {
ProcessRecord pr = procsToKill.get(i);
if (pr.setSchedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE) {
pr.kill("remove task", true);
} else {
pr.waitingToKill = "remove task";
}
}
}
mServices是ActiveServices类的对象,mServices.cleanUpRemovedTaskLocked(...)
语句杀掉了与app相关的服务进程,在执行完ActiveServices.cleanUpRemovedTaskLocked方法后,就会调用pr.kill
方法杀掉app进程和app所属进程组中所有的进程。关于杀掉app所属进程组所有进程的分析可以看这篇文章:Android5.1.1源码 - App进程被杀后与App相关的所有服务进程均被杀的原因。本文主要分析ActiveServices.cleanUpRemovedTaskLocked
方法做了什么。
ActiveServices类的源码在文件"frameworks/base/services/core/java/com/android/server/am/ActiveServices.java"中,下面是ActiveServices.cleanUpRemovedTaskLocked方法的源码:
void cleanUpRemovedTaskLocked(TaskRecord tr, ComponentName component, Intent baseIntent) {
ArrayList services = new ArrayList();
ArrayMap alls = getServices(tr.userId);
for (int i=0; i
这个方法先获得了所有的服务,然后将包名与"component.getPackageName()"相等的服务保存到了services中。
遍历services,sr.startRequested为true表明这个服务已经启动,当sr.serviceInfo.flags设置了ServiceInfo.FLAG_STOP_WITH_TASK标识时,会调用stopServiceLocked方法停止服务,如果调用了stopServiceLocked方法那么这个服务就不会再重启了
。
什么情况下会设置ServiceInfo.FLAG_STOP_WITH_TASK标识哪?当App的AndroidManifest.xml中服务标签被设置了android:stopWithTask="true"
,那么sr.serviceInfo.flags会被设置ServiceInfo.FLAG_STOP_WITH_TASK标识,下面是一个例子:
回到ActiveServices.cleanUpRemovedTaskLocked方法中,当sr.serviceInfo.flags没有设置ServiceInfo.FLAG_STOP_WITH_TASK标识时,会执行下面的代码:
sr.pendingStarts.add(new ServiceRecord.StartItem(sr, true,
sr.makeNextStartId(), baseIntent, null));
if (sr.app != null && sr.app.thread != null) {
// We always run in the foreground, since this is called as
// part of the "remove task" UI operation.
sendServiceArgsLocked(sr, true, false);
}
sr.pendingStarts.add(...)语句添加了要重启的服务信息,然后调用sendServiceArgsLocked方法重启服务。