likes
comments
collection
share

AMS之Activity栈管理(上篇)

作者站长头像
站长
· 阅读数 15

Android的知识体系搭建

AMS系列

AMS之AMS的启动流程

AMS之进程的启动流程

AMS之进程管理LRU算法

AMS的内存管理ADJ算法

[AMS之Activity栈管理(上篇)]-本篇

一 概述

之前说到了 Activity 的启动,今天我们就说说 Activity 的启动中,关于栈管理的部分。我们应该经常听说过各种 Activity 栈,比如 Activity 的四种启动模式,其中就有 singleTask 栈内唯一这个模式。那么 Activity 的栈,究竟是一个什么东西,Android 系统对于 Activity 的栈,又是如何进行管理的,今天,我们就来详细说一说。

1.1 相关知识

之前在我们的 Activity 启动流程中,我们已经大概了解到了 Activity 启动过程中,需要哪些类共同参与工作,今天我们再介绍一次,在 Activity 栈管理中,这些重要的类。

1.2 ActivityStackSupervisor

ActivityStackSupervisor 这个类,我们看类名也能猜到,它是 Activity 栈的管理者。

1.3 ActivityRecord

ActivityRecord 是 Activity 在 Android 系统中的记录,它记录了 Activity 里全部的信息,包括这个 Activity 在 Manifest 中的配置信息,还有这个 Activity 运行在哪个栈,哪个应用等等。它确定了 Activity 在系统中的唯一性。我们在【三 ActivityRecord】中它进行了详细介绍。

1 .4 Task

它的前身是 ActivityStack,但是从 Android 12 开始,谷歌删除了 ActivityStack 这个概念,全部使用 Task 进行替代,它代表了 Activity 的栈,

首先还是要从 AMS 的 startActivityAsUser 说起,具体的 Activity 启动流程可以看 Activity启动源码解析

二 Activity 的启动与栈

2.1 startActivityAsUser

private int startActivityAsUser(IApplicationThread caller, String callingPackage,
        @Nullable String callingFeatureId, Intent intent, String resolvedType,
        IBinder resultTo, String resultWho, int requestCode, int startFlags,
        ProfilerInfo profilerInfo, Bundle bOptions, int userId, boolean validateIncomingUser) {
    assertPackageMatchesCallingUid(callingPackage);
    enforceNotIsolatedCaller("startActivityAsUser");

    userId = getActivityStartController().checkTargetUser(userId, validateIncomingUser,
            Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser");

    // 获取 一个 ActivityStartController,然后通过它获取一个 ActivityStarter
    // 然后执行 execute
    return getActivityStartController().obtainStarter(intent, "startActivityAsUser")
            .setCaller(caller)
            .setCallingPackage(callingPackage)
            .setCallingFeatureId(callingFeatureId)
            .setResolvedType(resolvedType)
            .setResultTo(resultTo)
            .setResultWho(resultWho)
            .setRequestCode(requestCode)
            .setStartFlags(startFlags)
            .setProfilerInfo(profilerInfo)
            .setActivityOptions(bOptions)
            .setUserId(userId)
            .execute();
}

在 AMS 启动 Activity 时,出现了这么几个对象 ActivityStartControllerActivityStarter 还有 ActivityRecord。我们先一个个看。

  • 首先是 ActivityStartController,它是 ActivityStarter 的控制者,用于构建一个可以复用的 ActivityStarter。
  • 然后是 ActivityStarter,它是 Activity 的启动器,它是可以复用的。
  • 最后是 ActivityRecord,它是 Android 系统用于记录 Activity 信息的对象。

我们先来看一看 ActivityRecord 的创建代码。

2.2 execute

int execute() {
    try {
        // Refuse possible leaked file descriptors
        if (mRequest.intent != null && mRequest.intent.hasFileDescriptors()) {
                throw new IllegalArgumentException("File descriptors passed in Intent");
        }

        final LaunchingState launchingState;
        synchronized (mService.mGlobalLock) {
                // 在前面的启动流程中,我们已经介绍了,resultTo 就是调用者 Activity。
                // 如果是从非 Activity 的 Context 中调用过来的话,它就是 null
                // forTokenLocked 见 【3.7 forTokenLocked】
                final ActivityRecord caller = ActivityRecord.forTokenLocked(mRequest.resultTo);
                final int callingUid = mRequest.realCallingUid == Request.DEFAULT_REAL_CALLING_UID
                                ?  Binder.getCallingUid() : mRequest.realCallingUid;
                launchingState = mSupervisor.getActivityMetricsLogger().notifyActivityLaunching(
                                mRequest.intent, caller, callingUid);
        }

        if (mRequest.activityInfo == null) {
                mRequest.resolveActivity(mSupervisor);
        }

        ...

        // 执行启动请求
        res = executeRequest(mRequest);

    ...
}

在前面 Activity 启动流程中,我们介绍了 resultTo 这个对象,这里我们再简单说一下,详细的内容可以看上一篇博客。

现在我们假定从 Activity A 中启动 Activity B,那么这个 Activity A 就是这个 resultTo 对象。后续我们将 Activity A 称为源 Activity,将 Activity B 称为目标 Activity

这里创建 ActivityRecord 里记录了要启动的目标 Activity 信息,传入的参数是源 Activity。接下来我们再说一说 ActivityRecord 这个对象。

三 ActivityRecord

首先,我先介绍一下 ActivityRecord 中的一些重要的成员变量,ActivityRecord 因为要记录 Activity 的详细信息,所以里面有非常多的成员变量,这里我们只列举一些比较重要的,

3.1 ActivityRecord

[frameworks/base/services/core/java/com/android/server/wm/ActivityRecord.java]

final class ActivityRecord extends WindowToken implements WindowManagerService.AppFreezeListener {
    final ActivityTaskManagerService mAtmService;

    // AndroidManifest中的信息
    final ActivityInfo info; 
    // TODO: rename to mActivityToken
    final ActivityRecord.Token appToken;
    final int mUserId;
    // 包名
    final String packageName;
    // 组件名
    final ComponentName mActivityComponent;
    // 这个 Activity 属于哪个 Task
    private Task task; 
    // 谁启动了此 Activity,启动此 Activity 的 Activity 信息
    ActivityRecord resultTo;
    // 栈的亲和性
    final String taskAffinity;
}

ActivityRecord 里记录的信息非常多,我们需要重点关注的这里我已经列举出来了,需要注意的是,从 Android 10 开始,ActivityRecord 这个类就开始发生了变化,所以如果你看的是 Android 10 的代码,task 对应的类型是 TaskRecord,而这个类从 Android 11 开始则变成了 Task。它表示的是这个 Activity 所在的栈。

3.2 Task

[frameworks/base/services/core/java/com/android/server/wm/Task.java]
class Task extends WindowContainer<WindowContainer> {
	...
}

Task 继承的是 WindowContainer,这是 WMS 中的一些概念,这里就不过多扩展了,后续讲 WMS 的时候再细说,我们只需要知道,它表示的是 Activity 当前所在的栈即可。

3.3 ActivityRecord 的构造函数

[frameworks/base/services/core/java/com/android/server/wm/ActivityRecord.java]

final class ActivityRecord extends WindowToken implements WindowManagerService.AppFreezeListener {

    private ActivityRecord(ActivityTaskManagerService _service, WindowProcessController _caller,
                    int _launchedFromPid, int _launchedFromUid, String _launchedFromPackage,
                    @Nullable String _launchedFromFeature, Intent _intent, String _resolvedType,
                    ActivityInfo aInfo, Configuration _configuration, ActivityRecord _resultTo,
                    String _resultWho, int _reqCode, boolean _componentSpecified,
                    boolean _rootVoiceInteraction, ActivityTaskSupervisor supervisor,
                    ActivityOptions options, ActivityRecord sourceRecord, PersistableBundle persistentState,
                    TaskDescription _taskDescription, long _createTime) {
            super(_service.mWindowManager, new Token(_intent).asBinder(), TYPE_APPLICATION, true,
                            null /* displayContent */, false /* ownerCanManageAppTokens */);

            mAtmService = _service;
            appToken = (Token) token;

            appToken.attach(this);
            ...
}

在 ActivityRecord 的构造函数中,保存了一个 token 为 appToken,并调用了 appToken 的 attach。Token 也是 WMS 中的概念,但是这里的需要详细说明一下。token 是 ActivityRecord 父类 WindowToken 中的一个成员变量。

3.4 WindowToken

class WindowToken extends WindowContainer<WindowState> {
    private static final String TAG = TAG_WITH_CLASS_NAME ? "WindowToken" : TAG_WM;

    /** The actual token */
    final IBinder token;

    protected WindowToken(WindowManagerService service, IBinder _token, int type,
            boolean persistOnEmpty, DisplayContent dc, boolean ownerCanManageAppTokens) {
        this(service, _token, type, persistOnEmpty, dc, ownerCanManageAppTokens,
                false /* roundedCornerOverlay */, false /* fromClientToken */, null /* options */);
    }

    protected WindowToken(WindowManagerService service, IBinder _token, int type,
            boolean persistOnEmpty, DisplayContent dc, boolean ownerCanManageAppTokens,
            boolean roundedCornerOverlay, boolean fromClientToken, @Nullable Bundle options) {
        super(service);
        token = _token;
        windowType = type;
        mOptions = options;
        mPersistOnEmpty = persistOnEmpty;
        mOwnerCanManageAppTokens = ownerCanManageAppTokens;
        mRoundedCornerOverlay = roundedCornerOverlay;
        mFromClientToken = fromClientToken;
        if (dc != null) {
            dc.addWindowToken(token, this);
        }
    }
}

我们可以看到,token 它定义的是一个 IBinder,联系之前 ActivityRecord 传入的实际上是 Intent,所以 Token 其实是通过 Intent 构造出来的。我们再来看一下 Token 的定义。它其实是 ActivityRecord 中的一个内部类。

3.5 Token

[frameworks/base/services/core/java/com/android/server/wm/ActivityRecord.java]

static class Token extends IApplicationToken.Stub {
	private WeakReference<ActivityRecord> weakActivity;
	private final String name;
	private final String tokenString;

	Token(Intent intent) {
		name = intent.getComponent().flattenToShortString();
		tokenString = "Token{" + Integer.toHexString(System.identityHashCode(this)) + "}";
	}

	private void attach(ActivityRecord activity) {
		if (weakActivity != null) {
			throw new IllegalStateException("Already attached..." + this);
		}
		weakActivity = new WeakReference<>(activity);
	}

	private static @Nullable ActivityRecord tokenToActivityRecordLocked(Token token) {
		if (token == null) {
			return null;
		}
		ActivityRecord r = token.weakActivity.get();
		if (r == null || r.getRootTask() == null) {
			return null;
		}
		return r;
	}

	@Override
	public String toString() {
		StringBuilder sb = new StringBuilder(128);
		sb.append("Token{");
		sb.append(Integer.toHexString(System.identityHashCode(this)));
		sb.append(' ');
		if (weakActivity != null) {
			sb.append(weakActivity.get());
		}
		sb.append('}');
		return sb.toString();
	}

	@Override
	public String getName() {
		return name;
	}
}

Token 是 ActivityRecord 的内部成员类,而它的构造函数,其实就是从 Intent 中取出对应的组件名。

3.6 浅谈 Token

再从 ActivityRecord 的构造函数开始说起,首先,Activity 启动时,会创建一个 Intent 保存需要启动 Activity 的组件信息。然后会创建 ActivityRecord,将要目标 Activity 的信息保存起来。

ActivityRecord 的父类 WindowToken 中,有一个 token 对象,ActivityRecord 会将这个 token 保存为一个 appToken,然后调用 Token 的 attach,传入的参数是 ActivityRecord 自己 this。

在做了上述事情之后,现在 ActivityRecord 中有一个 appToken,它的父类 WindowToken 有一个 token。其实这两个对象是同一个 token。而这个 token 里保存了要启动 Activity 的组件名,还保存了要启动 Activity 对应的 ActivityRecord。

现在想一想,Android 为什么要做这些事?其实反过来问一个问题,Android 系统的不同进程中,Activity 是如何传递的?Android 系统又如何保证不同进程,能找到并且管理同一个 Activity?

想明白了这些,其实就明白了 token 的作用,它其实就和网络请求中的 token 一样,一个 token 对应了一个系统中的 Activity。而为了保证 token 在不同进程中的唯一性,那么它为什么继承自 IBinder 就可以理解了。

也就是说,一个 ActivityRecord 对应一个 token,而一个 ActivityRecord 又对应一个 Activity,所以,通过 token 就保证了 Activity 在系统中的唯一性

3.7 forTokenLocked

说完了关于 ActivityRecord 中 token 和 task 的相关内容,我们接着回到 Activity 启动流程中的 executeRequest ,在其中有这样一行代码 sourceRecord = ActivityRecord.isInAnyTask(resultTo),现在我们看这行代码应该就可以理解了。forTokenLocked 是定义在 Token 中的函数,前面已经全部列出来了 Token 的代码,这里再简单列举一下。

static @Nullable ActivityRecord forTokenLocked(IBinder token) {
    try {
        return Token.tokenToActivityRecordLocked((Token)token);
    } catch (ClassCastException e) {
        Slog.w(TAG, "Bad activity token: " + token, e);
        return null;
    }
}

private static @Nullable ActivityRecord tokenToActivityRecordLocked(Token token) {
    if (token == null) {
            return null;
    }
    ActivityRecord r = token.weakActivity.get();
    if (r == null || r.getRootTask() == null) {
            return null;
    }
    return r;
}

Token 的构造我们全面已经解释了,它在 ActivityRecord 中创建,并调用对应的 attach 函数,而 resultTo 表示的是此次启动的源 Activity。所以通过 ActivityRecord.isInAnyTask(resultTo) 就可以拿到这次启动源 Activity 对应的 ActivityRecord。

而前面我们已经说了 ActivityRecord 中的 task 保存的是这个 Activity 所在的栈,而拿到了源 Activity 的 ActivityRecord,那么也就是拿到了它所在的栈。

那么,拿到了源 Activity 的栈,接下来需要做什么?

显然,相比你已经猜到了,接下来系统需要根据目标 Activity 的启动模式,来判断目标 Activity 所在的栈,是否需要和源 Activity 的栈一致,是需要新建一个栈,还是复用旧的栈。是否需要清除旧栈中的 Activity 等等。

接着说 Activity 启动流程中,非常重要的一个函数 startActivityInner。

四 startActivityInner

前面在 Activity 的启动流程中,介绍了 startActivityInner 这个函数,但是当时并没有详细说明,今天我们再来说一下。

[frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java]

int startActivityInner(final ActivityRecord r, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            int startFlags, boolean doResume, ActivityOptions options, Task inTask,
              boolean restrictedBgActivity, NeededUriGrants intentGrants) {

    // 设置初始状态
    setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
            voiceInteractor, restrictedBgActivity);

    // 首先就是计算 Activity 的启动模式
    // 获得一个的 Flag,这玩意就是我们设置给 Intent 的。
    computeLaunchingTaskFlags();

    // 处理源 Activity 的任务栈
    // 如果源 Activity 正在 finish 则需要开启一个新的栈
    computeSourceRootTask();

    // mLaunchFlags 就是前面计算的,这里设置给 mIntent
    // 其实和我们启动 Activity 时自定义 Flag 很像
    mIntent.setFlags(mLaunchFlags);

    // Reusable 复用,这里是获取可以复用的 Task
    final Task reusedTask = getReusableTask();

    //是否需要冻结 Task 列表
    // ?什么什么时候需要冻结
    if (mOptions != null && mOptions.freezeRecentTasksReordering()
            && mSupervisor.mRecentTasks.isCallerRecents(r.launchedFromUid)
            && !mSupervisor.mRecentTasks.isFreezeTaskListReorderingSet()) {
        mFrozeTaskList = true;
        mSupervisor.mRecentTasks.setFreezeTaskListReordering();
    }

    // 是否存在一个可以现在使用的 Task
    // 是否有复用,如果没有,是否可以计算获取一个
    final Task targetTask = reusedTask != null ? reusedTask : computeTargetTask();
    // 如果没有可以现在使用的 Task,那么就创建一个新 Task
    final boolean newTask = targetTask == null;
    mTargetTask = targetTask;

    // 计算启动参数
    computeLaunchParams(r, sourceRecord, targetTask);

    // 判断是否可以通过 targetTask 或者新建 Task 启动的 Activity
    int startResult = isAllowedToStart(r, newTask, targetTask);
    if (startResult != START_SUCCESS) {
        return startResult;
    }

    // 获取栈顶没有 finish 的 activity
    final ActivityRecord targetTaskTop = newTask
            ? null : targetTask.getTopNonFinishingActivity();
    if (targetTaskTop != null) {
        // 看一下栈顶的 Task targetTaskTop 是否可以回收复用
        startResult = recycleTask(targetTask, targetTaskTop, reusedTask, intentGrants);
        if (startResult != START_SUCCESS) {
            return startResult;
        }
    } else {
        mAddingToTask = true;
    }

    // 如果要启动的 Activity 与当前在顶部的 Activity 相同,那么 我们需要检查它是否应该只被启动一次。
    final Task topRootTask = mPreferredTaskDisplayArea.getFocusedRootTask();
  
    if (topRootTask != null) {
        startResult = deliverToCurrentTopIfNeeded(topRootTask, intentGrants);
        if (startResult != START_SUCCESS) {
            return startResult;
        }
    }

    if (mTargetRootTask == null) {
        // 获得一个栈 Task
        mTargetRootTask = getLaunchRootTask(mStartActivity, mLaunchFlags, targetTask, mOptions);
    }

    if (newTask) {
        // 如果是新建 Task
        final Task taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
                ? mSourceRecord.getTask() : null;
        // 关联 Task 与 ActivityRecord
        // 这个函数也会调用 addOrReparentStartingActivity
        setNewTask(taskToAffiliate);
    } else if (mAddingToTask) {
        // 将要启动的 Activity 添加到 targetTask
        // 并且会将此 Activity 添加到最近启动的 ActivityRecord 中,后续可以通过 findActivity 复用
        addOrReparentStartingActivity(targetTask, "adding to task");
    }

    if (!mAvoidMoveToFront && mDoResume) {
        mTargetRootTask.getRootTask().moveToFront("reuseOrNewTask", targetTask);
        if (mOptions != null) {
            if (mOptions.getTaskAlwaysOnTop()) {
                mTargetRootTask.setAlwaysOnTop(true);
            }
        }
        if (!mTargetRootTask.isTopRootTaskInDisplayArea() && mService.mInternal.isDreaming()) {
            // Launching underneath dream activity (fullscreen, always-on-top). Run the launch-
            // -behind transition so the Activity gets created and starts in visible state.
            mLaunchTaskBehind = true;
            r.mLaunchTaskBehind = true;
        }
    }

    ...

    // 将 Task 移动到 Activity 栈顶
    mTargetRootTask.startActivityLocked(mStartActivity,
            topRootTask != null ? topRootTask.getTopNonFinishingActivity() : null, newTask,
            mKeepCurTransition, mOptions, sourceRecord);
            
    if (mDoResume) {
        final ActivityRecord topTaskActivity =
                mStartActivity.getTask().topRunningActivityLocked();


        // 要启动的 Activity 无法获取焦点
        if (!mTargetRootTask.isTopActivityFocusable()
                || (topTaskActivity != null && topTaskActivity.isTaskOverlay()
                && mStartActivity != topTaskActivity)) {

            // 如果 Activity 不可见就无法恢复
            // 如有要确保可见,就会触发进入动画
            // 并且,被覆盖的 Activity,直到覆盖物被移除前,都是不可见的
            mTargetRootTask.ensureActivitiesVisible(null /* starting */,
                    0 /* configChanges */, !PRESERVE_WINDOWS);
            // 告诉 WMS 继续执行,因为现在 Activity 还无法恢复。
            mTargetRootTask.mDisplayContent.executeAppTransition();
        } else {
           
            if (mTargetRootTask.isTopActivityFocusable()
                    && !mRootWindowContainer.isTopDisplayFocusedRootTask(mTargetRootTask)) {
                mTargetRootTask.moveToFront("startActivityInner");
            }

            // 【重点】恢复栈顶的 Activity
            mRootWindowContainer.resumeFocusedTasksTopActivities(
                    mTargetRootTask, mStartActivity, mOptions, mTransientLaunch);
        }
    }
    // 更新 RootTask
    mRootWindowContainer.updateUserRootTask(mStartActivity.mUserId, mTargetRootTask);

    // Activity 启动时立即更新最近的任务列表
    mSupervisor.mRecentTasks.add(mStartActivity.getTask());
    mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTask(),
            mPreferredWindowingMode, mPreferredTaskDisplayArea, mTargetRootTask);

    return START_SUCCESS;
}

4.1 setInitialState

首先是 setInitialState 这个函数,setInitialState 的字面意思是设置初始化状态。什么是初始化状态呢?其实就是指定启动时的那一堆 m 开头的成员变量,例如 mStartActivity,mIntent 等等。

private void setInitialState(ActivityRecord r, ActivityOptions options, Task inTask,
        boolean doResume, int startFlags, ActivityRecord sourceRecord,
        IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
        boolean restrictedBgActivity) {
    reset(false /* clearRequest */);

    mStartActivity = r;
    mIntent = r.intent;
    mOptions = options;
    mCallingUid = r.launchedFromUid;
    mSourceRecord = sourceRecord;
    mVoiceSession = voiceSession;
    mVoiceInteractor = voiceInteractor;
    mRestrictedBgActivity = restrictedBgActivity;

    ...
}

4.2 computeLaunchingTaskFlags

computeLaunchingTaskFlags 这个函数的作用,就是计算要启动 Activity 所需要的栈参数(Flags)。

private void computeLaunchingTaskFlags() {
    // 注意:我们之前讲过了 Activity 和 Context 启动 Activity 导致的不同的参数,在这里就产生了作用。
    // 如果是从 Activity 启动的新 Activity,那么 mSourceRecord 就不会为空。
    if (mSourceRecord == null && mInTask != null && mInTask.getRootTask() != null) {
	    // 如果 mSourceRecord 为空,就是说明不是 Activity 启动的
        ...


    // 对不同启动模式的处理
    // mInTask 是指定的目标 Activity 的启动栈,
    // 我们正常从 Activity 启动其他 Activity 时这个参数为空
    // mSourceRecord 是源 Activity 的信息。
    if (mInTask == null) {
        if (mSourceRecord == null) {
            // 如果没有源 Activity 栈信息,就添加一个 FLAG_ACTIVITY_NEW_TASK
            if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0 && mInTask == null) {
                mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
            }
        } else if (mSourceRecord.launchMode == LAUNCH_SINGLE_INSTANCE) {
            // 如果源 Activity 是 SingleInstance,那么就需要新开一个栈来启动目标 Activity,
            // 其实就是添加一个 FLAG_ACTIVITY_NEW_TASK 标志
            mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
        } else if (isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK)) {
            // 如果目标 Activity 的启动模式是 SingleInstance 或 SingleTask,也需要新开一个栈
            mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
        }
    }
}

看到这里,我们基本就明白了不同 Activity 的启动模式,对应的 Activity 栈是如何管理的。

  • 从非 Activity 上下文中启动 Activity,需要 FLAG_ACTIVITY_NEW_TASK。
  • 从 SingleInstance 的 Activity 中,启动其他 Activity,不论这个 Activity 是什么模式,都会添加一个 FLAG_ACTIVITY_NEW_TASK
  • 如果目标 Activity 是 SingleInstance 或 SingleTask,也需要新开一个栈

4.3 computeSourceRootTask

private void computeSourceRootTask() {
    // 如果 mSourceRecord 为空,或者 mSourceRecord 已经 finish,mSourceRootTask 都为空
    if (mSourceRecord == null) {
            mSourceRootTask = null;
            return;
    }
    if (!mSourceRecord.finishing) {
            // 如果没有finish,就从 mSourceRecord 中取出 Task
            mSourceRootTask = mSourceRecord.getRootTask();
            return;
    }

    // 清除 mSourceRecord
    if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0) {
            mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
            mNewTaskInfo = mSourceRecord.info;

            final Task sourceTask = mSourceRecord.getTask();
            mNewTaskIntent = sourceTask != null ? sourceTask.intent : null;
    }
    mSourceRecord = null;
    mSourceRootTask = null;
}

computeSourceRootTask 其实是计算源 Activity 的所在栈,当然它的逻辑很简单,就是如果源 Activity 没有 finish,那么直接取它的 RootTask 就行了。

[frameworks/base/services/core/java/com/android/server/wm/ActivityRecord.java]
Task getRootTask() {
	return task != null ? task.getRootTask() : null;
}

4.4 getReusableTask

getReusableTask 是获取可以复用的栈,前面我们已经拿到了源 Activity 的栈。

private Task getReusableTask() {
    // 如果指名了 Task,那么就直接从容器里取
    ...
    
    // 开始判断 Activity 的启动模式
    if (putIntoExistingTask) {
        if (LAUNCH_SINGLE_INSTANCE == mLaunchMode) {
            // 启动模式是 singleInstance 则从历史 Activity 中找
            intentActivity = mRootWindowContainer.findActivity(mIntent, mStartActivity.info,
                   mStartActivity.isActivityTypeHome());
        } else if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
            // 如果是分屏显示也从历史 Activity 中找
            intentActivity = mRootWindowContainer.findActivity(mIntent, mStartActivity.info,
                    !(LAUNCH_SINGLE_TASK == mLaunchMode));
        } else {
            // 其他情况则找可以复用的 Task
            intentActivity =
                    mRootWindowContainer.findTask(mStartActivity, mPreferredTaskDisplayArea);
        }
    }

    ...

    return intentActivity != null ? intentActivity.getTask() : null;
}

获取可以复用的 Task,根据需要启动的目标 Acitivity,判断是复用现有 Task,还是创建新的。这里我们主要看处理 Activity 启动模式的代码。

  • 首先是判断启动模式是否是 singleInstance,如果是,则先查找历史 Activity。显然,系统需要保证 singleInstance 的 Activity 实例是唯一的。
  • 然后是分屏的,也需要先查找历史 Activity
  • 最后则是其他模式,全部调用 findTask

我们接下来看一下这个历史 Activity 的查找逻辑,不过在看 Activity 的查找逻辑之前,我们需要看一下 recycleTask 这个函数。

4.5 recycleTask

int recycleTask(Task targetTask, ActivityRecord targetTaskTop, Task reusedTask,
		NeededUriGrants intentGrants) {
    ...

    complyActivityFlags(targetTask,
                    reusedTask != null ? reusedTask.getTopNonFinishingActivity() : null, intentGrants);

    ...

    return mMovedToFront ? START_TASK_TO_FRONT : START_DELIVERED_TO_TOP;
}

recycleTask 这个函数也很长,我们需要注意的是它其中调用了 complyActivityFlags 这样一个函数。

4.6 complyActivityFlags

complyActivityFlags 这个函数的意思,就是要对 Activity 的各种 Flag 进行运用了。

private void complyActivityFlags(Task targetTask, ActivityRecord reusedActivity,
		NeededUriGrants intentGrants) {
    ActivityRecord targetTaskTop = targetTask.getTopNonFinishingActivity();
    final boolean resetTask = reusedActivity != null && (mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0;
    
    if (resetTask) {
        targetTaskTop = mTargetRootTask.resetTaskIfNeeded(targetTaskTop, mStartActivity);
    }

    if ((mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
                    == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK)) {
        // 首先就判断目标 Activity 的 Flag 是否有 FLAG_ACTIVITY_NEW_TASK 和 
        // FLAG_ACTIVITY_CLEAR_TASK,这两个我们很熟悉,一个是新建栈,一个是清除栈顶
        targetTask.performClearTaskLocked();
        targetTask.setIntent(mStartActivity);
            mAddingToTask = true;
    } else if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
        || isDocumentLaunchesIntoExisting(mLaunchFlags)
        || isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK,
            LAUNCH_SINGLE_INSTANCE_PER_TASK)) {
            
        // LAUNCH_SINGLE_INSTANCE 和 LAUNCH_SINGLE_TASK
        // 如果有 FLAG_ACTIVITY_CLEAR_TOP,就需要清除栈顶
        final ActivityRecord top = targetTask.performClearTaskForReuseLocked(mStartActivity,
                            mLaunchFlags);

        // 【重点】这里的 if 就是Activity栈顶复用的逻辑
        // 如果清除栈顶之后能拿到目标 Activity
        if (top != null) {
            if (top.isRootOfTask()) {
                // Activity aliases may mean we use different intents for the top activity,
                // so make sure the task now has the identity of the new intent.
                top.getTask().setIntent(mStartActivity);
            }
            // 设置 NewIntent 参数,这就是 Activity 栈顶复用时会调用 NewIntent 的原因了
            deliverNewIntent(top, intentGrants);
        } else {
            // 清除栈顶后,当前栈还是没有目标 Activity
            mAddingToTask = true;
            if (targetTask.getRootTask() == null) {
                // 获取启动栈,走启动流程
                mTargetRootTask = getLaunchRootTask(mStartActivity, mLaunchFlags,
                        null /* task */, mOptions);
                mTargetRootTask.addChild(targetTask, !mLaunchTaskBehind /* toTop */,
                                (mStartActivity.info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0);
            }
        }
    } else if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) == 0 && !mAddingToTask
                    && (mLaunchFlags & FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
        // 如果 Activity 不需要清除栈顶,并且 Flag 是移动到前台
        final ActivityRecord act = targetTask.findActivityInHistory(mStartActivity.mActivityComponent);
        // 如果栈内有 Activity 就把它移动到前台
        if (act != null) {
            final Task task = act.getTask();
            task.moveActivityToFrontLocked(act);
            act.updateOptionsLocked(mOptions);
            deliverNewIntent(act, intentGrants);
            mTargetRootTask.mLastPausedActivity = null;
        } else {
            mAddingToTask = true;
        }
    } else if (mStartActivity.mActivityComponent.equals(targetTask.realActivity)) {
        if (targetTask == mInTask) {

        } else if (((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
            || LAUNCH_SINGLE_TOP == mLaunchMode)
            && targetTaskTop.mActivityComponent.equals(mStartActivity.mActivityComponent)
            && mStartActivity.resultTo == null) {
            
            // 如果是 FLAG_ACTIVITY_SINGLE_TOP 启动模式,就直接判断栈顶即可
            if (targetTaskTop.isRootOfTask()) {
                targetTaskTop.getTask().setIntent(mStartActivity);
            }
            // 有就设置 NewIntent 参数
            deliverNewIntent(targetTaskTop, intentGrants);
        } else if (!targetTask.isSameIntentFilter(mStartActivity)) {
                mAddingToTask = true;
        } else if (reusedActivity == null) {
                mAddingToTask = true;
        }
    } else if (!resetTask) {
            mAddingToTask = true;
    } else if (!targetTask.rootWasReset) {
            targetTask.setIntent(mStartActivity);
    }
}

complyActivityFlags 中分别对 Activity 的三种特殊启动模式分别做了处理 singleTop,singleTask 还有 singleInstance,并且还判断了是否有清除栈顶的参数 Flag,然后调用 deliverNewIntent 设置 NewIntent 参数。

4.7 deliverNewIntent

private void deliverNewIntent(ActivityRecord activity, NeededUriGrants intentGrants) {
    if (mIntentDelivered) {
            return;
    }

    activity.logStartActivity(EventLogTags.WM_NEW_INTENT, activity.getTask());
    activity.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, intentGrants,
                    mStartActivity.launchedFromPackage);
    mIntentDelivered = true;
}

4.8 deliverNewIntentLocked

[frameworks/base/services/core/java/com/android/server/wm/ActivityRecord.java]
final void deliverNewIntentLocked(int callingUid, Intent intent, NeededUriGrants intentGrants,
		String referrer) {

    mAtmService.mUgmInternal.grantUriPermissionUncheckedFromIntent(intentGrants,
                    getUriPermissionsLocked());
    final ReferrerIntent rintent = new ReferrerIntent(intent, referrer);
    boolean unsent = true;
    final boolean isTopActivityWhileSleeping = isTopRunningActivity() && isSleeping();

    if ((mState == RESUMED || mState == PAUSED || isTopActivityWhileSleeping)
            && attachedToProcess()) {
        try {
                // 如果 Activity 当前处于 RESUMED,PAUSED 或者正在顶部休眠
                ArrayList<ReferrerIntent> ar = new ArrayList<>(1);
                ar.add(rintent);
                // 确保事务完成后状态为 RESUMED,并且立刻调用 NewIntent
                mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
                                NewIntentItem.obtain(ar, mState == RESUMED));
                unsent = false;
        } catch (RemoteException e) {
                Slog.w(TAG, "Exception thrown sending new intent to " + this, e);
        } catch (NullPointerException e) {
                Slog.w(TAG, "Exception thrown sending new intent to " + this, e);
        }
    }

    // 如果不为上述状态,则将 rintent 保存
    if (unsent) {
        addNewIntentLocked(rintent);
    }
}

4.9 addNewIntentLocked

// newIntents 是 ActivityRecord 中的成员变量
ArrayList<ReferrerIntent> newIntents; // any pending new intents for single-top mode
private void addNewIntentLocked(ReferrerIntent intent) {
    if (newIntents == null) {
        newIntents = new ArrayList<>();
    }
    newIntents.add(intent);
}

到此,NewIntent 我们就处理完了,记住这个 newIntents 变量,后面它还会出现。

五 RootWindowContainer

5.1 findActivity

ActivityRecord findActivity(Intent intent, ActivityInfo info, boolean compareIntentFilters) {

    // ComponentName = 包名 + Activity 类名
    ComponentName cls = intent.getComponent();
    if (info.targetActivity != null) {
        cls = new ComponentName(info.packageName, info.targetActivity);
    }
    final int userId = UserHandle.getUserId(info.applicationInfo.uid);

    // 注意,这里传入的参数 RootWindowContainer::matchesActivity。
    // 在【5.2】中需要使用
    final PooledPredicate p = PooledLambda.obtainPredicate(
            RootWindowContainer::matchesActivity, PooledLambda.__(ActivityRecord.class),
            userId, compareIntentFilters, intent, cls);

    // 查找可以复用的 Activity
    final ActivityRecord r = getActivity(p);
    p.recycle();
    return r;
}

5.2 getActivity

ActivityRecord getActivity(Predicate<ActivityRecord> callback, boolean traverseTopToBottom,
        ActivityRecord boundary) {
    return callback.test(this) ? this : null;
}

这里只是调用了传入的 callback.test,这个 callback 是哪里来的呢?在之前的 RootWindowContainer.findActivity 中,我们创建了一个 PooledPredicate,它的第一个参数就是 RootWindowContainer::matchesActivity。 这个参数是一个函数,这里的 test 会调用到这个函数,这个函数的名字 matchesActivity 我们就可以看出来,它是用来匹配 Activity 的。

5.3 matchesActivity

[frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java]
private static boolean matchesActivity(ActivityRecord r, int userId,
        boolean compareIntentFilters, Intent intent, ComponentName cls) {
    if (!r.canBeTopRunning() || r.mUserId != userId) return false;

    if (compareIntentFilters) {
        if (r.intent.filterEquals(intent)) {
            return true;
        }
    } else {
        // Compare the target component instead of intent component so we don't miss if the
        // activity uses alias.
        if (r.mActivityComponent.equals(cls)) {
            return true;
        }
    }
    return false;
}

Activity 匹配有两种情况,第一种就是 IntentFilters 匹配,第二种就是包名 + Activity 类名匹配。所以在 RootWindowContainer.findActivity 中会找到一个符合匹配的 ActivityRecord。

六 computeTargetTask

private Task computeTargetTask() {
    if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
            && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
        // 1. 源Activity为空,目标Activity的启动Flag有FLAG_ACTIVITY_NEW_TASK标志
        return null;
    } else if (mSourceRecord != null) {
        // 2. 源 Activity 不为空
        return mSourceRecord.getTask();
    } else if (mInTask != null) {
        // 3. 有指定的启动栈
        return mInTask;
    } else {
        // 一些其他情况
        final Task rootTask = getLaunchRootTask(mStartActivity, mLaunchFlags, null /* task */,
                mOptions);
        final ActivityRecord top = rootTask.getTopNonFinishingActivity();
        if (top != null) {
            return top.getTask();
        } else {
            // Remove the root task if no activity in the root task.
            rootTask.removeIfPossible("computeTargetTask");
        }
    }
    return null;
}

computeTargetTask 是计算目标 Activity 的栈,如果计算的结果不为 null,就使用计算的结果,如果计算的结果为 null,则会创建一个新的栈。

七 RootWindowContainer

7.1 resumeFocusedTasksTopActivities

[frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java]
boolean resumeFocusedTasksTopActivities(
            Task targetRootTask, ActivityRecord target, ActivityOptions targetOptions,
            boolean deferPause) {
    if (!mTaskSupervisor.readyToResume()) {
            return false;
    }

    boolean result = false;
    if (targetRootTask != null && (targetRootTask.isTopRootTaskInDisplayArea()
                    || getTopDisplayFocusedRootTask() == targetRootTask)) {
        // 恢复栈顶的 Activity
        result = targetRootTask.resumeTopActivityUncheckedLocked(target, targetOptions,
                        deferPause);
    }

    for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
        final DisplayContent display = getChildAt(displayNdx);

        // 将结果保存到 curResult 中
        final boolean curResult = result;
        boolean[] resumedOnDisplay = new boolean[1];
        display.forAllRootTasks(rootTask -> {
            final ActivityRecord topRunningActivity = rootTask.topRunningActivity();
            if (!rootTask.isFocusableAndVisible() || topRunningActivity == null) {
                    return;
            }
            if (rootTask == targetRootTask) {
                // 更新 curResult 结果
                resumedOnDisplay[0] |= curResult;
                return;
            }
            if (rootTask.getDisplayArea().isTopRootTask(rootTask)
                            && topRunningActivity.isState(RESUMED)) {
                    rootTask.executeAppTransition(targetOptions);
            } else {
                    resumedOnDisplay[0] |= topRunningActivity.makeActiveIfNeeded(target);
            }
        });
        
        result |= resumedOnDisplay[0];
        
        if (!resumedOnDisplay[0]) {
            // 前面更新了 resumedOnDisplay[0]
            // 但是假如 resumedOnDisplay[0] 没有内容,那么就需要回到 focusedRoot,
            // 如果 focusedRoot 也没有,就回到 Home Activity
            final Task focusedRoot = display.getFocusedRootTask();
            if (focusedRoot != null) {
                    result |= focusedRoot.resumeTopActivityUncheckedLocked(target, targetOptions);
            } else if (targetRootTask == null) {
                    result |= resumeHomeActivity(null /* prev */, "no-focusable-task",
                                    display.getDefaultTaskDisplayArea());
            }
        }
    }

    return result;
}

resumeFocusedTasksTopActivities 主要的目的就是处理栈顶的 Activity,由于设计到显示的内容,所以会有一些 WMS 相关的知识,这里我们先关注恢复栈顶的操作 resumeTopActivityUncheckedLocked,它是 Task 中的函数,WMS 相关的知识后面再看。

八 Task

8.1 resumeTopActivityUncheckedLocked

[frameworks/base/services/core/java/com/android/server/wm/Task.java]
@GuardedBy("mService")
boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options,
		boolean deferPause) {
		
    if (mInResumeTopActivity) {
        // 不要开始递归
        return false;
    }

    boolean someActivityResumed = false;
    try {
        // 防止递归
        mInResumeTopActivity = true;

        if (isLeafTask()) {
            // 可见,并且还有焦点
            if (isFocusableAndVisible()) {
                    // 调用恢复栈顶的函数 resumeTopActivityInnerLocked
                    someActivityResumed = resumeTopActivityInnerLocked(prev, options, deferPause);
            }
        } else {
            int idx = mChildren.size() - 1;
            while (idx >= 0) {
                final Task child = (Task) getChildAt(idx--);
                if (!child.isTopActivityFocusable()) {
                        continue;
                }
                if (child.getVisibility(null /* starting */) != TASK_VISIBILITY_VISIBLE) {
                        break;
                }

                // 调用 child 的 resumeTopActivityUncheckedLocked
                someActivityResumed |= child.resumeTopActivityUncheckedLocked(prev, options,
                                deferPause);

                if (idx >= mChildren.size()) {
                        idx = mChildren.size() - 1;
                }
            }
        }

        // 当恢复顶部活动时,可能需要暂停顶部活动(例如,返回到锁定屏幕。 
        // 我们在{@link #resumeTopActivityUncheckedLocked }中抑制了正常的暂停逻辑,
        // 因为顶部的 Activity 会在结束时恢复。 我们在这里再次调用{@link ActivityTaskSupervisor #checkReadyForSleepLocked },
        // 以确保发生任何必要的暂停逻辑。 如果无论锁定屏幕如何都将显示“活动”,
        // 则将跳过对{@link ActivityTaskSupervisor #checkReadyForSleepLocked }的调用。
        final ActivityRecord next = topRunningActivity(true /* focusableOnly */);
        if (next == null || !next.canTurnScreenOn()) {
                checkReadyForSleep();
        }
    } finally {
        // 最终将 mInResumeTopActivity 设置为 false
        mInResumeTopActivity = false;
    }

    return someActivityResumed;
}

8.2 resumeTopActivityInnerLocked

@GuardedBy("mService")
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options,
		boolean deferPause) {
    // 判断 ATMS 服务是否准备好
    if (!mAtmService.isBooting() && !mAtmService.isBooted()) {
        return false;
    }

    // 在此根任务中查找下一个要继续的、未完成且可获得焦点的最顶层 Activity。
    // 如果它不是可获取焦点的的,我们将在下一个可获取焦点的栈中继续。
    ActivityRecord next = topRunningActivity(true /* focusableOnly */);

    final boolean hasRunningActivity = next != null;

    if (hasRunningActivity && !isAttached()) {
        return false;
    }

    mRootWindowContainer.cancelInitializingActivities();

    if (!hasRunningActivity) {
        // There are no activities left in the root task, let's look somewhere else.
        return resumeNextFocusableActivityWhenRootTaskIsEmpty(prev, options);
    }

    next.delayedResume = false;
    final TaskDisplayArea taskDisplayArea = getDisplayArea();

    // 如果栈顶的 Activity 已经 Resume,直接返回即可
    // 正常启动此时 Activity 还没 Resume
    if (mResumedActivity == next && next.isState(RESUMED)
                    && taskDisplayArea.allResumedActivitiesComplete()) {
        ...
        return false;
    }

    if (!next.canResumeByCompat()) {
        return false;
    }

    // 如果我们正在调用 Activity 的 pause,那么在它 pause 之前不要做任何事情。
    final boolean allPausedComplete = mRootWindowContainer.allPausedActivitiesComplete();
    if (!allPausedComplete) {
            return false;
    }

    // 如果当前 Activity 是 pause 并且休眠中,直接返回
    if (mLastPausedActivity == next && shouldSleepOrShutDownActivities()) {
            ...
            return false;
    }

    ...

    // 【重要】Pausing 掉现在正 Resume 的 Activity
    boolean pausing = !deferPause && taskDisplayArea.pauseBackTasks(next);
    ...

    if (pausing) {
        ProtoLog.v(WM_DEBUG_STATES, "resumeTopActivityLocked: Skip resume: need to"
                        + " start pausing");

        if (next.attachedToProcess()) {
            // 更新进程到 LRU 队列,这个函数在 ProcessRecord.java 中
            next.app.updateProcessInfo(false /* updateServiceConnectionActivities */,
                            true /* activityChange */, false /* updateOomAdj */,
                            false /* addPendingTopUid */);
        } else if (!next.isProcessRunning()) {
            // 如果进程还没启动,先启动进程
            final boolean isTop = this == taskDisplayArea.getFocusedRootTask();
            mAtmService.startProcessAsync(next, false /* knownToBeDead */, isTop,
                                isTop ? "pre-top-activity" : "pre-activity");
        }
        if (lastResumed != null) {
            lastResumed.setWillCloseOrEnterPip(true);
        }
        return true;
    } else if (mResumedActivity == next && next.isState(RESUMED)
            && taskDisplayArea.allResumedActivitiesComplete()) {

        executeAppTransition(options);
        return true;
    }

    ...


    if (next.attachedToProcess()) {
        // 如果  Activity 已经与 Process 绑定,则执行下面的函数
        // 走生命周期 A.onPause -> B.onResume

        try {
            // 通过 app 的 IBinder 对象和 appToken 获取到它对应的 ClientTransaction
            // app.getThread 在之前的 Activity 启动流程和 AMS 里已经详细讲解过了
            // appToken 在【3.6】中也详细讲解了
            final ClientTransaction transaction =
                            ClientTransaction.obtain(next.app.getThread(), next.appToken);
            // Deliver all pending results.
            ArrayList<ResultInfo> a = next.results;
            if (a != null) {
                    final int N = a.size();
                    if (!next.finishing && N > 0) {
                            // 分发所有的 ActivityResult
                            transaction.addCallback(ActivityResultItem.obtain(a));
                    }
            }

            // 如果有 newIntents,就调用 NewIntent
            if (next.newIntents != null) {
                    transaction.addCallback(
                                    NewIntentItem.obtain(next.newIntents, true /* resume */));
            }

            // 清除应用的 stopped 状态
            next.notifyAppResumed(next.stopped);

            EventLogTags.writeWmResumeActivity(next.mUserId, System.identityHashCode(next),
                            next.getTask().mTaskId, next.shortComponentName);


            mAtmService.getAppWarningsLocked().onResumeActivity(next);
            next.app.setPendingUiCleanAndForceProcessStateUpTo(mAtmService.mTopProcessState);
            next.abortAndClearOptionsAnimation();

            // 调用 Activity 的 onResume
            transaction.setLifecycleStateRequest(
                            ResumeActivityItem.obtain(next.app.getReportedProcState(),
                                            dc.isNextTransitionForward()));
            // 事件开始
            mAtmService.getLifecycleManager().scheduleTransaction(transaction);

            ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivityLocked: Resumed %s", next);
        } catch (Exception e) {
            ...
            return true;
        }

        // 从这一点开始,如果出现问题,就没有办法恢复 Activity。
        try {
                next.completeResumeLocked();
        } catch (Exception e) {
                ...
                return true;
        }
    } else {
        // 如果没有绑定,走 Activity 的启动,启动流程可以看另一篇博客,专门讲 Activity 启动的
        ...
        mTaskSupervisor.startSpecificActivity(next, true, true);
    }

    return true;
}

resumeTopActivityInnerLocked 这段代码很重要,它回答了 A Activity 启动 B Activity 时,Activity 的生命周期执行顺序,并且,它还回调了 Activity 启动时的生命周期,如果 Activity 需要栈内复用,NewIntent 也是在这里回调的。newIntents 这个对象之前我们在【4.9 addNewIntentLocked】中已经介绍过了。

到此,我们已经见到源 Activity 启动目标 Activity 的流程了,而在 resumeTopActivityInnerLocked 函数中,做了我们最熟悉,也经常被问题的一个问题。A Activity 启动 B Activity 的生命周期是如何走的?

从代码中,我们可以看到,系统会首先调用源 Activity 的 Pausing,然后再判断目标 Activity,决定是走启动流程,还是直接走 onResume。

8.3 pauseBackTasks

[frameworks/base/services/core/java/com/android/server/wm/TaskDisplayArea.java]
boolean pauseBackTasks(ActivityRecord resuming) {
    final int[] someActivityPaused = {0};
    forAllLeafTasks((task) -> {
        final ActivityRecord resumedActivity = task.getResumedActivity();
        if (resumedActivity != null
                && (task.getVisibility(resuming) != TASK_VISIBILITY_VISIBLE
                || !task.isTopActivityFocusable())) {

            // 调用 Pausing
            if (task.startPausingLocked(false /* uiSleeping*/,
                    resuming, "pauseBackTasks")) {
                someActivityPaused[0]++;
            }
        }
    }, true /* traverseTopToBottom */);
    return someActivityPaused[0] > 0;
}

最后再来看一下 Pausing 的调用,它其实就是从栈 Task 中取出 Resume 状态的 Activity,并调用它的 startPausingLocked。

九 总结

到此,我们介绍了 AMS 中,关于 Activity 启动时,栈管理的部分的内容。当然,栈管理是 Activity 启动中的重要内容,并且还涉及 AMS,而 Activity 栈显示的内容,还有容器相关的内容又涉及到 WMS,这里就先略过 WMS 相关的内容,后面再详细说。

关于 Activity 的栈管理,分为启动和销毁两个部分,这篇博客我们介绍了启动部分的内容,销毁部分的内容因为篇幅原因,我们放下一个部分介绍。我们先就目前的内容做一个简单的总结。

  1. 首先,Activity 启动,分为两个类型,从 Activity 中的启动,和非 Activity 中的启动,这两种启动,决定了启动流程中的 resultTo 是否存在,即源 Activity 的 ActivityRecord。
  2. 目标 Activity 的启动栈计算,取决于它的启动模式,即最后的 mFlag,还有源 Activity 的栈。
  3. 目标 Activity 的启动模式,决定了它启动栈 Task 的计算还有 mFlag,而 Task 中是否有历史 Activity,又决定了目标 Activity 的这次启动的需要执行那些生命周期函数。
  4. 最后就是 Activity 的生命周期函数的回调,这块内容谷歌官方一直在做修改,在 Android 12 中,它的回调分改为了 Callback 加上事件处理的方式,这块内容之前在 Activity 的启动流程中有说明。

最后再简单说明一下,Activity 的启动,销毁,AMS 的栈管理,进程管理等等属于 Android 中的重要内容,并且整个流程极为复杂,只看一遍源码都不一定能弄懂,所以需要反复翻看,之后我们聊 WMS 还有 Activity 窗口显示的部分内容时,这部分内容还会不断提及。