Andorid N 最近任务管理器流程详解(四)

来源:互联网 发布:销售提成计算软件 编辑:程序博客网 时间:2024/06/07 00:23

4. Task的移除

本章节主要讲讲Task移除的流程

4.1 removeTask

文件: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

4.2 removeTask

文件: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来移除

4.3 removeTaskByIdLocked

文件: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

4.3.1 removeTaskActivitiesLocked

文件:TaskRecord.java

    public void removeTaskActivitiesLocked() {        // 见4.3.1.1仅仅移除整个任务        performClearTaskAtIndexLocked(0);    }

4.3.1.1 performClearTaskAtIndexLocked

文件: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)

4.3.2 cleanUpRemovedTaskLocked

文件: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<ProcessRecord> procsToKill = new ArrayList<>();        ArrayMap<String, SparseArray<ProcessRecord>> pmap = mProcessNames.getMap();        for (int i = 0; i < pmap.size(); i++) {            SparseArray<ProcessRecord> 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