Android 进程绝杀技--forceStop

基于Android 6.0源码剖析,force-stop的全过程

一.概述

1.1 引言

话说Android开源系统拥有着App不计其数,百家争鸣,都想在这“大争之世”寻得系统存活的一席之地。然则系统资源有限,如若都割据为王,再强劲的CPU也会忙不过来,再庞大的内存终会消耗殆尽,再大容量的电池续航终会昙花一现。

面对芸芸众生,无尽变数,系统以不变应万变,一招绝杀神技forceStop腾空出世,此处以adb指令的方式为例来说说其内部机理:

    am force-stop pkgName
    am force-stop --user 2 pkgName //只杀用户userId=2的相关信息

force-stop命令杀掉所有用户空间下的包名pkgName相关的信息,也可以通过--user来指定用户Id。 当执行上述am指令时,则会触发调用Am.java的main()方法,接下来从main方法开始说起。

1.2 Am.main

[-> Am.java]

    public static void main(String[] args) {
         (new Am()).run(args); //【见小节1.3】
    }

1.3 Am.run

[-> Am.java]

    public void run(String[] args) {
        ...
        mArgs = args;
        mNextArg = 0;
        mCurArgData = null;
        onRun(); //【见小节1.4】
        ...
    }

1.4 Am.onRun

[-> Am.java]

    public void onRun() throws Exception {
        //获取的是Binder proxy对象AMP
        mAm = ActivityManagerNative.getDefault();
        String op = nextArgRequired();

        if (op.equals("start")) {
            ...
        } else if (op.equals("force-stop")) {
            runForceStop(); //【见小节1.5】
        }
        ...
    }

1.5 Am.runForceStop

[-> Am.java]

    private void runForceStop() throws Exception {
        int userId = UserHandle.USER_ALL;

        String opt;
        // 当指定用户时,则解析相应userId
        while ((opt=nextOption()) != null) {
            if (opt.equals("--user")) {
                userId = parseUserArg(nextArgRequired());
            }
        }
        //【见小节1.6】
        mAm.forceStopPackage(nextArgRequired(), userId);
    }

当不指定userId时,则默认为UserHandle.USER_ALL。

1.6 AMP.forceStopPackage

[-> ActivityManagerNative.java ::AMP]

    public void forceStopPackage(String packageName, int userId) throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         data.writeInterfaceToken(IActivityManager.descriptor);
         data.writeString(packageName);
         data.writeInt(userId);
         //【见小节1.7】
         mRemote.transact(FORCE_STOP_PACKAGE_TRANSACTION, data, reply, 0);
         reply.readException();
         data.recycle();
         reply.recycle();
     }

1.7 AMN.onTransact

[-> ActivityManagerNative.java]

    public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
            throws RemoteException {
        switch (code) {
          case FORCE_STOP_PACKAGE_TRANSACTION: {
               data.enforceInterface(IActivityManager.descriptor);
               String packageName = data.readString();
               int userId = data.readInt();
               //【见小节2.1】
               forceStopPackage(packageName, userId);
               reply.writeNoException();
               return true;
          }
          ...
        }
    }

AMP.forceStopPackage来运行在执行adb时所创建的进程,经过Binder Driver后,进入system_server进程的一个binder线程来执行AMN.forceStopPackage,从这开始的操作(包括当前操作)便都运行在system_server系统进程。

1.8 小节

进程绝杀技force-stop,并非任意app可直接调用, 否则App间可以相互停止对方,则岂非天下大乱。该方法的存在便是供系统差遣。一般地,点击home弹出的清理用户最近使用app采取的策略便是force-stop.

至于force-stop的触发方式,除了adb的方式,还可通过获取ActivityManager再调用其方法forceStopPackage(),不过这是@hide隐藏方法,同样是需要具有FORCE_STOP_PACKAGES权限。虽然第三方普通app不能直接调用,但对于深入理解Android,还是很有必要知道系统是如何彻底清理进程的过程。接下来,进入AMS来深入探查force-stop的内部机理。

二. force-stop内部机理

2.1 AMS.forceStopPackage

[-> ActivityManagerService.java]

    public void forceStopPackage(final String packageName, int userId) {
        if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
                        != PackageManager.PERMISSION_GRANTED) {
            //需要权限permission.FORCE_STOP_PACKAGES
            throw new SecurityException();
        }
        final int callingPid = Binder.getCallingPid();
        userId = handleIncomingUser(callingPid, Binder.getCallingUid(),
                        userId, true, ALLOW_FULL_ONLY, "forceStopPackage", null);
        long callingId = Binder.clearCallingIdentity();
        try {
            IPackageManager pm = AppGlobals.getPackageManager();
            synchronized(this) {
                int[] users = userId == UserHandle.USER_ALL
                                ? getUsersLocked() : new int[] { userId };
                for (int user : users) {
                        int pkgUid = -1;
                        //根据包名和userId来查询相应的uid
                        pkgUid = pm.getPackageUid(packageName, user);
                        //设置包的状态为stopped
                        pm.setPackageStoppedState(packageName, true, user);

                        if (isUserRunningLocked(user, false)) {
                                //【见流程2.2】
                                forceStopPackageLocked(packageName, pkgUid, "from pid " + callingPid);
                        }
                }
            }
        } finally {
                Binder.restoreCallingIdentity(callingId);
        }
    }

这里有一个过程非常重要,那就是setPackageStoppedState()将包的状态设置为stopped,那么所有广播都无法接收,除非带有标记FLAG_INCLUDE_STOPPED_PACKAGES的广播,系统默认的广播几乎都是不带有该标志,也就意味着被force-stop的应用是无法通过建立手机网络状态或者亮灭的广播来拉起进程。

当使用force stop方式来结束进程时, reason一般都是"from pid " + callingPid. 当然也有另外,那就是AMS.clearApplicationUserData方法调用forceStopPackageLocked的reason为"clear data".

2.2 AMS.forceStopPackageLocked

    private void forceStopPackageLocked(final String packageName, int uid, String reason) {
        //[见流程2.3]
        forceStopPackageLocked(packageName, UserHandle.getAppId(uid), false,
                    false, true, false, false, UserHandle.getUserId(uid), reason);

        Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
                    Uri.fromParts("package", packageName, null));
        //系统启动完毕后,则mProcessesReady=true
        if (!mProcessesReady) {
                intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
                            | Intent.FLAG_RECEIVER_FOREGROUND);
        }
        intent.putExtra(Intent.EXTRA_UID, uid);
        intent.putExtra(Intent.EXTRA_USER_HANDLE, UserHandle.getUserId(uid));
        //发送广播用于停止alarm以及通知 【见小节8.1】
        broadcastIntentLocked(null, null, intent,
                        null, null, 0, null, null, null, AppOpsManager.OP_NONE,
                        null, false, false, MY_PID, Process.SYSTEM_UID, UserHandle.getUserId(uid));
    }

清理跟该包名相关的进程和四大组件之外,还会发送广播ACTION_PACKAGE_RESTARTED,用于清理已注册的alarm,notification信息。

2.3 AMS.forceStopPackageLocked

    //callerWillRestart = false, doit = true;
    private final boolean forceStopPackageLocked(String packageName, int appId,
             boolean callerWillRestart, boolean purgeCache, boolean doit,
             boolean evenPersistent, boolean uninstalling, int userId, String reason) {
         int i;

         if (appId < 0 && packageName != null) {
             // 重新获取正确的appId
             appId = UserHandle.getAppId(
                     AppGlobals.getPackageManager().getPackageUid(packageName, 0));
         }

         // doit =true能进入该分支
         if (doit) {
             final ArrayMap<String, SparseArray<Long>> pmap = mProcessCrashTimes.getMap();
             for (int ip = pmap.size() - 1; ip >= 0; ip--) {
                 SparseArray<Long> ba = pmap.valueAt(ip);
                 for (i = ba.size() - 1; i >= 0; i--) {
                     boolean remove = false;
                     final int entUid = ba.keyAt(i);
                     if (packageName != null) {
                         if (userId == UserHandle.USER_ALL) {
                             if (UserHandle.getAppId(entUid) == appId) {
                                 remove = true;
                             }
                         } else {
                             if (entUid == UserHandle.getUid(userId, appId)) {
                                 remove = true;
                             }
                         }
                     } else if (UserHandle.getUserId(entUid) == userId) {
                         remove = true;
                     }
                     if (remove) {
                         ba.removeAt(i);
                     }
                 }
                 if (ba.size() == 0) {
                     pmap.removeAt(ip);
                 }
             }
         }

         //清理Process [见流程3.1]
         boolean didSomething = killPackageProcessesLocked(packageName, appId, userId,
                 -100, callerWillRestart, true, doit, evenPersistent,
                 packageName == null ? ("stop user " + userId) : ("stop " + packageName));

         //清理Activity [见流程4.1]
         if (mStackSupervisor.finishDisabledPackageActivitiesLocked(
                 packageName, null, doit, evenPersistent, userId)) {
             ...
             didSomething = true;
         }

         // 结束该包中的Service [见流程5.1]
         if (mServices.bringDownDisabledPackageServicesLocked(
                 packageName, null, userId, evenPersistent, true, doit)) {
             ...
             didSomething = true;
         }

         if (packageName == null) {
             //当包名为空, 则移除当前用户的所有sticky broadcasts
             mStickyBroadcasts.remove(userId);
         }

         //收集providers [见流程6.1]
         ArrayList<ContentProviderRecord> providers = new ArrayList<>();
         if (mProviderMap.collectPackageProvidersLocked(packageName, null, doit, evenPersistent,
                 userId, providers)) {
              ...
             didSomething = true;
         }
         for (i = providers.size() - 1; i >= 0; i--) {
              //清理providers [见流程6.3]
             removeDyingProviderLocked(null, providers.get(i), true);
         }

         //移除已获取的跟该package/user相关的临时权限
         removeUriPermissionsForPackageLocked(packageName, userId, false);

         if (doit) {
             // 清理Broadcast [见流程7.1]
             for (i = mBroadcastQueues.length - 1; i >= 0; i--) {
                 didSomething |= mBroadcastQueues[i].cleanupDisabledPackageReceiversLocked(
                         packageName, null, userId, doit);
             }
         }

         if (packageName == null || uninstalling) {
             ... //包名为空的情况
         }

         if (doit) {
             if (purgeCache && packageName != null) {
                ... //不进入该分支
             }
             if (mBooted) {
                 //恢复栈顶的activity
                 mStackSupervisor.resumeTopActivitiesLocked();
                 mStackSupervisor.scheduleIdleLocked();
             }
         }

         return didSomething;
     }

对于didSomething只指当方法中所有行为,则返回true.比如killPackageProcessesLocked(),只要杀过一个进程则代表didSomething为true.

该方法的主要功能:

  1. Process: 调用AMS.killPackageProcessesLocked()清理该package所涉及的进程;
  2. Activity: 调用ASS.finishDisabledPackageActivitiesLocked()清理该package所涉及的Activity;
  3. Service: 调用AS.bringDownDisabledPackageServicesLocked()清理该package所涉及的Service;
  4. Provider: 调用AMS.removeDyingProviderLocked()清理该package所涉及的Provider;
  5. BroadcastRecevier: 调用BQ.cleanupDisabledPackageReceiversLocked()清理该package所涉及的广播

接下来,从这5个角度来分别说说force-stop的执行过程.

三. Process

3.1 AMS.killPackageProcessesLocked

    //callerWillRestart = false, allowRestart = true, doit = true;
    private final boolean killPackageProcessesLocked(String packageName, int appId,
            int userId, int minOomAdj, boolean callerWillRestart, boolean allowRestart,
            boolean doit, boolean evenPersistent, String reason) {
        ArrayList<ProcessRecord> procs = new ArrayList<>();

        //遍历当前所有运行中的进程
        final int NP = mProcessNames.getMap().size();
        for (int ip=0; ip<NP; ip++) {
            SparseArray<ProcessRecord> apps = mProcessNames.getMap().valueAt(ip);
            final int NA = apps.size();
            for (int ia=0; ia<NA; ia++) {
                ProcessRecord app = apps.valueAt(ia);
                if (app.persistent && !evenPersistent) {
                    continue; //不杀persistent进程
                }
                if (app.removed) {
                    //已标记removed的进程,便是需要被杀的进程,加入procs队列
                    if (doit) {
                        procs.add(app);
                    }
                    continue;
                }

                if (app.setAdj < minOomAdj) {
                    continue; //不杀adj低于预期的进程
                }

                if (packageName == null) {
                    ...
                //已指定包名的情况
                } else {
                    //pkgDeps: 该进程所依赖的包名
                    final boolean isDep = app.pkgDeps != null
                            && app.pkgDeps.contains(packageName);
                    if (!isDep && UserHandle.getAppId(app.uid) != appId) {
                        continue;
                    }
                    if (userId != UserHandle.USER_ALL && app.userId != userId) {
                        continue;
                    }
                    //pkgList: 运行在该进程的所有包名;
                    if (!app.pkgList.containsKey(packageName) && !isDep) {
                        continue;
                    }
                }

                //通过前面所有条件,则意味着该进程需要被杀, 添加到procs队列
                app.removed = true;
                procs.add(app);
            }
        }

        int N = procs.size();
        for (int i=0; i<N; i++) {
            // [见流程3.2]
            removeProcessLocked(procs.get(i), callerWillRestart, allowRestart, reason);
        }
        updateOomAdjLocked();
        return N > 0;
    }

一般地force-stop会指定包名,该方法会遍历当前所有运行中的进程mProcessNames,以下条件同时都不满足的进程,则会成为被杀的目标进程:(也就是说满足以下任一条件都可以免死)

  1. persistent进程:
  2. 进程setAdj < minOomAdj(默认为-100):
  3. 非UserHandle.USER_ALL同时, 且进程的userId不相等:多用户模型下,不同用户下不能相互杀;
  4. 进程没有依赖该packageName, 且进程的AppId不相等;
  5. 进程没有依赖该packageName, 且该packageName没有运行在该进程.

通俗地来说就是:

  • forceStop不杀系统persistent进程;
  • 当指定用户userId时,不杀其他用户空间的进程;

除此之外,以下情况则必然会成为被杀进程:

  • 进程已标记remove=true的进程,则会被杀;
  • 进程的pkgDeps中包含该packageName,则会被杀;
  • 进程的pkgList中包含该packageName,且该进程与包名所指定的AppId相等则会被杀;

进程的pkgList是在启动组件或者创建进程的过程向该队列添加的,代表的是该应用下有组件运行在该进程。那么pkgDeps是指该进程所依赖的包名,调用ClassLoader的过程添加。

3.2 AMS.removeProcessLocked

    //callerWillRestart = false, allowRestart = true
    private final boolean removeProcessLocked(ProcessRecord app,
             boolean callerWillRestart, boolean allowRestart, String reason) {
         final String name = app.processName;
         final int uid = app.uid;
         //从mProcessNames移除该进程
         removeProcessNameLocked(name, uid);
         if (mHeavyWeightProcess == app) {
            ...
         }
         boolean needRestart = false;
         if (app.pid > 0 && app.pid != MY_PID) {
             int pid = app.pid;
             synchronized (mPidsSelfLocked) {
                 mPidsSelfLocked.remove(pid);
                 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
             }

             if (app.isolated) {
                 mBatteryStatsService.removeIsolatedUid(app.uid, app.info.uid);
             }
             boolean willRestart = false;
             if (app.persistent && !app.isolated) {
                 if (!callerWillRestart) {
                     willRestart = true; //用于标记persistent进程则需重启进程
                 } else {
                     needRestart = true; //用于返回值,作用不大
                 }
             }
             //杀掉该进程
             app.kill(reason, true);
             //清理该进程相关的信息
             handleAppDiedLocked(app, willRestart, allowRestart);

             //对于persistent进程,则需要重新启动该进程
             if (willRestart) {
                 removeLruProcessLocked(app);
                 addAppLocked(app.info, false, null /* ABI override */);
             }
         } else {
             mRemovedProcesses.add(app);
         }

         return needRestart;
     }

该方法的主要功能:

  • 从mProcessNames, mPidsSelfLocked队列移除该进程;
  • 移除进程启动超时的消息PROC_START_TIMEOUT_MSG;
  • 调用app.kill()来杀进程会同时调用Process.kill和Process.killProcessGroup, 该过程详见理解杀进程的实现原理
  • 调用handleAppDiedLocked()来清理进程相关的信息, 该过程详见binderDied()过程分析

四. Activity

4.1 ASS.finishDisabledPackageActivitiesLocked

[-> ActivityStackSupervisor.java]

    boolean finishDisabledPackageActivitiesLocked(String packageName, Set<String> filterByClasses,
            boolean doit, boolean evenPersistent, int userId) {
        boolean didSomething = false;
        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
            final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
            final int numStacks = stacks.size();
            for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
                final ActivityStack stack = stacks.get(stackNdx);
                // [见流程4.2]
                if (stack.finishDisabledPackageActivitiesLocked(
                        packageName, filterByClasses, doit, evenPersistent, userId)) {
                    didSomething = true;
                }
            }
        }
        return didSomething;
    }

4.2 AS.finishDisabledPackageActivitiesLocked

[-> ActivityStack.java]

    // doit = true;
    boolean finishDisabledPackageActivitiesLocked(String packageName, Set<String> filterByClasses,
            boolean doit, boolean evenPersistent, int userId) {
        boolean didSomething = false;
        TaskRecord lastTask = null;
        ComponentName homeActivity = null;

        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
            final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
            int numActivities = activities.size();
            for (int activityNdx = 0; activityNdx < numActivities; ++activityNdx) {
                ActivityRecord r = activities.get(activityNdx);
                final boolean sameComponent =
                        (r.packageName.equals(packageName) && (filterByClasses == null
                                || filterByClasses.contains(r.realActivity.getClassName())))
                        || (packageName == null && r.userId == userId);
                if ((userId == UserHandle.USER_ALL || r.userId == userId)
                        && (sameComponent || r.task == lastTask)
                        && (r.app == null || evenPersistent || !r.app.persistent)) {
                    ...
                    if (r.isHomeActivity()) {
                        if (homeActivity != null && homeActivity.equals(r.realActivity)) {
                            continue; //不结束home activity
                        } else {
                            homeActivity = r.realActivity;
                        }
                    }
                    didSomething = true;

                    if (sameComponent) {
                        if (r.app != null) {
                            r.app.removed = true;
                        }
                        r.app = null;
                    }
                    lastTask = r.task;
                    //强制结束该Activity [见流程4.3]
                    if (finishActivityLocked(r, Activity.RESULT_CANCELED, null, "force-stop",
                            true)) {
                        // r已从mActivities中移除
                        --numActivities;
                        --activityNdx;
                    }
                }
            }
        }
        return didSomething;
    }

4.3 AS.finishActivityLocked

[-> ActivityStack.java]

    final boolean finishActivityLocked(ActivityRecord r, int resultCode, Intent resultData,
            String reason, boolean oomAdj) {
        if (r.finishing) {
            return false;
        }

        //[见流程4.3.1]
        r.makeFinishingLocked();
        final TaskRecord task = r.task;

        final ArrayList<ActivityRecord> activities = task.mActivities;
        final int index = activities.indexOf(r);
        if (index < (activities.size() - 1)) {
            //[见流程4.3.3]
            task.setFrontOfTask();
            if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
                //当该activity会被移除,则将该activity信息传播给下一个activity
                ActivityRecord next = activities.get(index+1);
                next.intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
            }
        }

        //暂停按键事件的分发
        r.pauseKeyDispatchingLocked();

        //调整聚焦的activity [见流程4.3.4]
        adjustFocusedActivityLocked(r, "finishActivity");
        //重置activity的回调结果信息
        finishActivityResultsLocked(r, resultCode, resultData);

        //当r为前台可见的activity时
        if (mResumedActivity == r) {
            boolean endTask = index <= 0;
            //准备关闭该transition
            mWindowManager.prepareAppTransition(endTask
                    ? AppTransition.TRANSIT_TASK_CLOSE
                    : AppTransition.TRANSIT_ACTIVITY_CLOSE, false);

            //告知wms来准备从窗口移除该activity
            mWindowManager.setAppVisibility(r.appToken, false);

            if (mPausingActivity == null) {
                //暂停该activity
                startPausingLocked(false, false, false, false);
            }

            if (endTask) {
                mStackSupervisor.removeLockedTaskLocked(task);
            }
        } else if (r.state != ActivityState.PAUSING) {
            //当r不可见的情况 [见流程4.3.5]
            return finishCurrentActivityLocked(r, FINISH_AFTER_PAUSE, oomAdj) == null;
        }

        return false;
    }

4.3.1 AR.makeFinishingLocked

[-> ActivityRecord.java]

    void makeFinishingLocked() {
        if (!finishing) {
            if (task != null && task.stack != null
                    && this == task.stack.getVisibleBehindActivity()) {
                //处于finishing的activity不应该在后台保留可见性 [见流程4.3.2]
                mStackSupervisor.requestVisibleBehindLocked(this, false);
            }
            finishing = true;
            if (stopped) {
                clearOptionsLocked();
            }
        }
    }

4.3.2 ASS.requestVisibleBehindLocked

    boolean requestVisibleBehindLocked(ActivityRecord r, boolean visible) {
        final ActivityStack stack = r.task.stack;
        if (stack == null) {
            return false; //r所在栈为空,则直接返回
        }
        final boolean isVisible = stack.hasVisibleBehindActivity();

        final ActivityRecord top = topRunningActivityLocked();
        if (top == null || top == r || (visible == isVisible)) {
            stack.setVisibleBehindActivity(visible ? r : null);
            return true;
        }

        if (visible && top.fullscreen) {
            ...
        } else if (!visible && stack.getVisibleBehindActivity() != r) {
            //设置不可见,且当前top activity跟该activity相同时返回
            return false;
        }

        stack.setVisibleBehindActivity(visible ? r : null);
        if (!visible) {
            //将activity置于不透明的r之上
            final ActivityRecord next = stack.findNextTranslucentActivity(r);
            if (next != null) {
                mService.convertFromTranslucent(next.appToken);
            }
        }
        if (top.app != null && top.app.thread != null) {
            //将改变通知给top应用
            top.app.thread.scheduleBackgroundVisibleBehindChanged(top.appToken, visible);
        }
        return true;
    }

4.3.3 TaskRecord.setFrontOfTask

[-> TaskRecord.java]

    final void setFrontOfTask() {
        boolean foundFront = false;
        final int numActivities = mActivities.size();
        for (int activityNdx = 0; activityNdx < numActivities; ++activityNdx) {
            final ActivityRecord r = mActivities.get(activityNdx);
            if (foundFront || r.finishing) {
                r.frontOfTask = false;
            } else {
                r.frontOfTask = true;
                foundFront = true;
            }
        }
        //所有activity都处于finishing状态.
        if (!foundFront && numActivities > 0) {
            mActivities.get(0).frontOfTask = true;
        }
    }
  • 将该Task中从底部往上查询, 第一个处于非finishing状态的ActivityRecord,则设置为根Activity(即r.frontOfTask = true),其他都为false;
  • 当所有的activity都处于finishing状态,则把最底部的activity设置成跟Activity.

4.3.4 AS.adjustFocusedActivityLocked

[-> ActivityStack.java]

    private void adjustFocusedActivityLocked(ActivityRecord r, String reason) {
        if (mStackSupervisor.isFrontStack(this) && mService.mFocusedActivity == r) {
            ActivityRecord next = topRunningActivityLocked(null);
            final String myReason = reason + " adjustFocus";
            if (next != r) {
                final TaskRecord task = r.task;
                boolean adjust = false;
                //当下一个activity为空, 或者下一个与当前的task不同, 或者要结束的r为根activity.
                if ((next == null || next.task != task) && r.frontOfTask) {
                    if (task.isOverHomeStack() && task == topTask()) {
                        adjust = true;
                    } else {
                        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
                            final TaskRecord tr = mTaskHistory.get(taskNdx);
                            if (tr.getTopActivity() != null) {
                                break;
                            } else if (tr.isOverHomeStack()) {
                                adjust = true;
                                break;
                            }
                        }
                    }
                }
                // 需要调整Activity的聚焦情况
                if (adjust) {
                    // 对于非全屏的stack, 则移动角度到下一个可见的栈,而不是直接移动到home栈而屏蔽其他可见的栈.
                    if (!mFullscreen
                            && adjustFocusToNextVisibleStackLocked(null, myReason)) {
                        return;
                    }
                    //当该栈为全屏,或者没有其他可见栈时, 则把home栈移至顶部
                    if (mStackSupervisor.moveHomeStackTaskToTop(
                            task.getTaskToReturnTo(), myReason)) {
                        //聚焦已调整完整,则直接返回
                        return;
                    }
                }
            }

            final ActivityRecord top = mStackSupervisor.topRunningActivityLocked();
            if (top != null) {
                mService.setFocusedActivityLocked(top, myReason);
            }
        }
    }

4.3.5 AS.finishCurrentActivityLocked

    final ActivityRecord finishCurrentActivityLocked(ActivityRecord r, int mode, boolean oomAdj) {
        if (mode == FINISH_AFTER_VISIBLE && r.nowVisible) {
            if (!mStackSupervisor.mStoppingActivities.contains(r)) {
                mStackSupervisor.mStoppingActivities.add(r);
                if (mStackSupervisor.mStoppingActivities.size() > 3
                        || r.frontOfTask && mTaskHistory.size() <= 1) {
                    mStackSupervisor.scheduleIdleLocked();
                } else {
                    mStackSupervisor.checkReadyForSleepLocked();
                }
            }
top Created with Sketch.