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

```java
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.