本章节主要讲讲Task移除的流程
文件:SystemServicesProxy.java
public void removeTask(final int taskId) {
if (mAm == null) return;
if (RecentsDebugFlags.Static.EnableMockTasks) return;
// Remove the task.
BackgroundThread.getHandler().post(new Runnable() {
@Override
public void run() {
// 见4.2
mAm.removeTask(taskId);
}
});
}
调用AM的removeTask方法来移除Task
文件:ActivityManagerService.java
@Override
public boolean removeTask(int taskId) {
// 检查是否有移除栈的权限
enforceCallingPermission(android.Manifest.permission.REMOVE_TASKS, "removeTask()");
synchronized (this) {
final long ident = Binder.clearCallingIdentity();
try {
// 见4.3
return removeTaskByIdLocked(taskId, true, REMOVE_FROM_RECENTS);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
}
根据任务的taskId来移除
文件:ActivityManagerService.java
private boolean removeTaskByIdLocked(int taskId, boolean killProcess,
boolean removeFromRecents) {
// 根据taskId找到对应的栈
final TaskRecord tr = mStackSupervisor.anyTaskForIdLocked(
taskId, !RESTORE_FROM_RECENTS, INVALID_STACK_ID);
if (tr != null) {
// 见4.3.1 调用TaskRecord的removeTaskActivitiesLocked
tr.removeTaskActivitiesLocked();
// 见4.3.2
cleanUpRemovedTaskLocked(tr, killProcess, removeFromRecents);
if (tr.isPersistable) {
notifyTaskPersisterLocked(null, true);
}
return true;
}
Slog.w(TAG, "Request to remove task ignored for non-existent task " + taskId);
return false;
}
这三个参数的意思分别是:
taskId:需要被移除的task的Id
killProcess:如果可能,杀掉所有和该task相关的进程
removeFromRecents:是否将该任务从Recents中移除
这个方法调用了两个比较关键的方法,分别是removeTaskActivitiesLocked和cleanUpRemovedTaskLocked
文件:TaskRecord.java
public void removeTaskActivitiesLocked() {
// 见4.3.1.1仅仅移除整个任务
performClearTaskAtIndexLocked(0);
}
文件:TaskRecord.java
final void performClearTaskAtIndexLocked(int activityNdx) {
int numActivities = mActivities.size();
for ( ; activityNdx < numActivities; ++activityNdx) {
final ActivityRecord r = mActivities.get(activityNdx);
if (r.finishing) {
continue;
}
if (stack == null) {
// Task was restored from persistent storage.
r.takeFromHistory();
mActivities.remove(activityNdx);
--activityNdx;
--numActivities;
} else if (stack.finishActivityLocked( // 移除该TaskRecord中的ActivityRecord对象
r, Activity.RESULT_CANCELED, null, "clear-task-index", false)) {
--activityNdx;
--numActivities;
}
}
}
这个方法是真正执行移除栈,移除所有和该栈相关连的activity。参数activityNdx为0,代表要把TaskRecord内的所有Activity移除。
方法中mActivities是该TaskRecord中保存的所有的ActivityRecord对象;stack是该TaskRecord所在的ActivityStack,这里不为空(ActivityStack是一个管理者的角色,负责管理ActivityRecord和TaskRecord)
文件:ActivityManagerService.java
private void cleanUpRemovedTaskLocked(TaskRecord tr, boolean killProcess,
boolean removeFromRecents) {
// 把该TaskRecord从mRecentTasks中移除
if (removeFromRecents) {
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;
}
// 如果需要,找到和这个app相关并正在运行的services,将它们停止
mServices.cleanUpRemovedTaskLocked(tr, component, new Intent(tr.getBaseIntent()));
// 如果不需要杀进程,则返回
if (!killProcess) {
return;
}
// Determine if the process(es) for this task should be killed.
final String pkg = component.getPackageName();
ArrayList procsToKill = new ArrayList<>();
ArrayMap> pmap = mProcessNames.getMap();
for (int i = 0; i < pmap.size(); i++) {
SparseArray uids = pmap.valueAt(i);
for (int j = 0; j < uids.size(); j++) {
ProcessRecord proc = uids.valueAt(j);
if (proc.userId != tr.userId) {
// 不杀不同用户的进程
continue;
}
if (proc == mHomeProcess) {
// Don't kill the home process along with tasks from the same package.
continue;
}
if (!proc.pkgList.containsKey(pkg)) {
// 不杀与该task无关的进程
continue;
}
for (int k = 0; k < proc.activities.size(); k++) {
TaskRecord otherTask = proc.activities.get(k).task;
if (tr.taskId != otherTask.taskId && otherTask.inRecents) {
// 如果进程中有activity属于recents中另一个不同的task,那么该进程也不杀
return;
}
}
if (proc.foregroundServices) {
// 有前台service的不杀
return;
}
// 添加进程到kill list
// 如下情况都不杀:进程的userid和TaskRecord不同;进程是HomeProcess;和该TaskRecord无关的进程;
// 进程有Activity处于其他的任务栈,并且也在recents里面的;除了上述的,其他的都加入procsToKill列表
procsToKill.add(proc);
}
}
// 杀掉运行的进程
for (int i = 0; i < procsToKill.size(); i++) {
ProcessRecord pr = procsToKill.get(i);
if (pr.setSchedGroup == ProcessList.SCHED_GROUP_BACKGROUND
&& pr.curReceiver == null) {
// 立刻杀
pr.kill("remove task", true);
} else {
// 如果没有运行在后台,或者运行了一个receiver,就延迟杀
pr.waitingToKill = "remove task";
}
}
}
这个方法主要的作用就是清除进程。这里removeFromRecents为true,会先TaskRecord从mRecntTasks中移除,然后将不能杀的进程过滤掉,剩下的加入到kill list里面。最后杀进程也分为两种:
- 一种是SHED_GROUP_BACKGROUND类型并且没有正执行reciver,那就会调用kill立即去杀掉
- 另一种是简单将procsToKill中ProcessRecord的waitingToKill字段设置为remove task