android.app.ActivityManager类提供了removeTask方法来清理任务。
在API21及之前,removeTask中提供一个参数来指定是否要连同任务所运行的进程一起杀掉。
这个方法的第二个参数就是用来指定是否要连同进程一起杀掉,可以为0或者REMOVE_TASK_KILL_PROCESS。
我们先看在4.4上的实现:

    /** * Completely remove the given task. * * @param taskId Identifier of the task to be removed. * @param flags Additional operational flags. May be 0 or * {@link #REMOVE_TASK_KILL_PROCESS}. * @return Returns true if the given task was found and removed. * * @hide */    public boolean removeTask(int taskId, int flags)            throws SecurityException {        try {            return ActivityManagerNative.getDefault().removeTask(taskId, flags);        } catch (RemoteException e) {            // System dead, we will be dead too soon!            return false;        }    }

在ActivityManager中提供的只是一个接口,真正的实现要通过IPC去调用ActivityManagerService的removeTask. 主要的逻辑在cleanUpRemovedTaskLocked中实现。

    @Override    public boolean removeTask(int taskId, int flags) {...            try {                TaskRecord tr = recentTaskForIdLocked(taskId);                if (tr != null) {                    ActivityRecord r = tr.removeTaskActivitiesLocked(-1, false);                    if (r != null) {                        cleanUpRemovedTaskLocked(tr, flags);                        return true;                    }...    }

我们再往下看cleanUpRemovedTaskLocked的逻辑,如果flags&ActivityManager.REMOVE_TASK_KILL_PROCESS就杀进程。

    private void cleanUpRemovedTaskLocked(TaskRecord tr, int flags) {...        final boolean killProcesses = (flags&ActivityManager.REMOVE_TASK_KILL_PROCESS) != 0;...        if (killProcesses) {...                    killUnneededProcessLocked(pr, "remove task");                } else {                    pr.waitingToKill = "remove task";                }            }        }    }

杀进程的逻辑在killUnneededProcessLocked中,接着调用android.os.Process.killProcessQuiet方法来杀进程。然后调用bionic中的函数来做系统调用。

    private void killUnneededProcessLocked(ProcessRecord pr, String reason) {        if (!pr.killedByAm) {            Slog.i(TAG, "Killing " + pr.toShortString() + " (adj " + pr.setAdj + "): " + reason);            EventLog.writeEvent(EventLogTags.AM_KILL, pr.userId, pr.pid,                    pr.processName, pr.setAdj, reason);            pr.killedByAm = true;            Process.killProcessQuiet(pr.pid);        }    }

比如ARM的kill调用是这样的:

ENTRY(kill)    mov     ip, r7    ldr     r7, =__NR_kill    swi     #0    mov     r7, ip    cmn     r0, #(MAX_ERRNO + 1)    bxls    lr    neg     r0, r0    b       __set_errno_internalEND(kill)

在AArch64状态下,swi已经失效了,替换成svc指令。

ENTRY(kill)    mov     x8, __NR_kill    svc     #0    cmn     x0, #(MAX_ERRNO + 1)    cneg    x0, x0, hi    b.hi    __set_errno_internal    retEND(kill)

在Intel x86芯片上,系统调用要用int 0x80软中断。

ENTRY(kill)    pushl   %ebx    pushl   %ecx    mov     12(%esp), %ebx    mov     16(%esp), %ecx    movl    $__NR_kill, %eax    int     $0x80    cmpl    $-MAX_ERRNO, %eax    jb      1f    negl    %eax    pushl   %eax    call    __set_errno    addl    $4, %esp    orl     $-1, %eax1:    popl    %ecx    popl    %ebx    retEND(kill)

但是在x86_64指令集中,系统调用已经变成基本指令了,不再需要int 0x80了。

ENTRY(kill)    movl    $__NR_kill, %eax    syscall    cmpq    $-MAX_ERRNO, %rax    jb      1f    negl    %eax    movl    %eax, %edi    call    __set_errno_internal1:    retEND(kill)

从API 22开始,情况出现了一些变化,带参数的API被取消了,默认就杀进程。
我们看5.1的代码:

    /** * Completely remove the given task. * * @param taskId Identifier of the task to be removed. * @return Returns true if the given task was found and removed. * * @hide */    public boolean removeTask(int taskId) throws SecurityException {        try {            return ActivityManagerNative.getDefault().removeTask(taskId);        } catch (RemoteException e) {            // System dead, we will be dead too soon!            return false;        }    }

经过IPC,走到ActivityManagerService中,默认调用removeTaskByIdLocked时就杀进程。

    @Override    public boolean removeTask(int taskId) {        synchronized (this) {            enforceCallingPermission(android.Manifest.permission.REMOVE_TASKS,                    "removeTask()");            long ident = Binder.clearCallingIdentity();            try {                return removeTaskByIdLocked(taskId, true);            } finally {                Binder.restoreCallingIdentity(ident);            }        }    }

我们继续看removeTaskByIdLocked,还是会调用cleanUpRemovedTaskLocked,这两个方法都是可以控制是否要杀进程的。

    /** * Removes the task with the specified task id. * * @param taskId Identifier of the task to be removed. * @param killProcess Kill any process associated with the task if possible. * @return Returns true if the given task was found and removed. */    private boolean removeTaskByIdLocked(int taskId, boolean killProcess) {        TaskRecord tr = mStackSupervisor.anyTaskForIdLocked(taskId);        if (tr != null) {            tr.removeTaskActivitiesLocked();            cleanUpRemovedTaskLocked(tr, killProcess);            if (tr.isPersistable) {                notifyTaskPersisterLocked(null, true);            }            return true;        }        Slog.w(TAG, "Request to remove task ignored for non-existent task " + taskId);        return false;    }
    private void cleanUpRemovedTaskLocked(TaskRecord tr, boolean killProcess) {        mRecentTasks.remove(tr);        tr.removedFromRecents();......        if (!killProcess) {            return;        }......

更多相关文章

  1. android 6.0 以上 动态申请多个权限
  2. Android短彩信收发流程(应用层)
  3. 使用traceview进行Android性能测试
  4. Android使用Fragment来实现ViewPager的功能(解决切换Fragment状态
  5. SecureRandom漏洞解析
  6. Android(安卓)中application 详解
  7. android Binder Linux IPC 内核 驱动
  8. Android(安卓)3.2 以上转屏,切换屏幕,横竖屏(onConfigurationChange
  9. Android学习笔记50:使用WebView控件浏览网页

随机推荐

  1. android下进行opencv开发的配置
  2. Android再按一次后退键退出
  3. RxJava操作符
  4. 使用Android-PullToRefresh实现下拉刷新
  5. Android(安卓)N(SDK7.0)新特性
  6. android 保持屏幕长亮及解锁的方法
  7. android使用Intent操作拨打电话和发送短
  8. Android(安卓)Studio gradle插件版本和gr
  9. EXOPlayer居中播放,类似ImageView的CENTER
  10. android 获取进程名字