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

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

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值