前语
写 Activity 系列的文章,是一件十分具有挑战性的事情,因为 Activity 与窗口、动画,紧密关联。
本文从最根底的方面开端剖析,也便是生命周期,可是读者也不必担心自己不懂窗口、动画,等等。因为我会在剖析的时分,帮你避开这些,让你能快速了解生命周期是怎么运转的。然后,当你把握了窗口、动画,等等常识,不妨再回头研究本文,或许你会有更深的了解。
那么挑选什么 Android 版本来剖析代码呢?现在市面上最新款的手机,使用的是 Android 14 ,例如 Xiaomi14。那么,我也挑选 Android 14,也便是 Android U,来剖析 Activity 的生命周期,窗口显现,窗口动画,等等。后边的文章就不再赘述剖析的是哪个 Android 版本了。
挑选剖析事例
为了完整的剖析 Activity 生命周期流程,我挑选以桌面冷发动 App 为例,来剖析 Activity 的发动,因为这个进程中会为 App 创立进程。别的,也触及桌面的远程动画,也是为今后剖析动画做准备。
桌面冷发动 App
我粗略地看过 Launcher 发动 App 的源码,其实便是调用 Context#startActivity() 来发动 Activity,终究完结的函数如下
// ContextImpl.java
public void startActivity(Intent intent, Bundle options) {
mMainThread.getInstrumentation().execStartActivity(
getOuterContext(), mMainThread.getApplicationThread(), null,
(Activity) null, intent, -1, options);
}
// Instrumentation.java
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
IApplicationThread whoThread = (IApplicationThread) contextThread;
// ...
try {
// ...
// 经过 ATMS 告诉服务端发动
int result = ActivityTaskManager.getService().startActivity(whoThread,
who.getOpPackageName(), who.getAttributionTag(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()), token,
target != null ? target.mEmbeddedID : null, requestCode, 0, null, options);
// ...
} catch (RemoteException e) {
throw new RuntimeException("Failure from system", e);
}
return null;
}
很简单,终究是经过 ActivityTaskManagerService(简称 ATMS) 来让服务端发动 Activity。至于 Launcher 传入了什么参数,在后边的剖析中,假如有需求,我会指出来,因而这儿就不详细描述传入了哪些数据。
因为在服务端,发动 Activity 并不是一次性完结,我分为了三个发动阶段来剖析,旨在让读者更清晰地把握 Activity 的发动进程。
第一阶段发动
第一阶段发动,由 App 端建议,而且由服务端 ATMS 处理。
ATMS
// ActivityTaskManagerService.java
public final int startActivity(IApplicationThread caller, String callingPackage,
String callingFeatureId, Intent intent, String resolvedType, IBinder resultTo,
String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo,
Bundle bOptions) {
// 增加了终究一个参数 userId
return startActivityAsUser(caller, callingPackage, callingFeatureId, intent, resolvedType,
resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions,
UserHandle.getCallingUserId());
}
public int startActivityAsUser(IApplicationThread caller, String callingPackage,
String callingFeatureId, Intent intent, String resolvedType, IBinder resultTo,
String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo,
Bundle bOptions, int userId) {
// 增加了终究一个参数 validateIncomingUser,值为 true
return startActivityAsUser(caller, callingPackage, callingFeatureId, intent, resolvedType,
resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions, userId,
true /*validateIncomingUser*/);
}
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) {
// app 端传过来的参数是 Bundle 类型,而且是序列化的,因而无法打印
// 在服务端,需求把它转换为 ActivityOptions 才干打印 app 端传入的数据
// 这儿更进一步,把 ActivityOptions 包装成 SafeActivityOptions,为的是检测调用方的权限
final SafeActivityOptions opts = SafeActivityOptions.fromBundle(bOptions);
// ...
// 把发动参数包装成 ActivityStart#mRequest ,并经过 ActivityStarter 来发动 activity
return getActivityStartController().obtainStarter(intent, "startActivityAsUser")
.setCaller(caller) // 指向 launcher
.setCallingPackage(callingPackage) // com.android.launcher
.setCallingFeatureId(callingFeatureId) // null
.setResolvedType(resolvedType) // 这是 mime type,现在是 null
.setResultTo(resultTo) // 指向 launcher
.setResultWho(resultWho) // null
// 留意,这个恳求码是 -1,也便是说 launcher 不需求知道发动成果
.setRequestCode(requestCode)
.setStartFlags(startFlags) // 0
.setProfilerInfo(profilerInfo) // null
.setActivityOptions(opts) // 这个是发动 Activity 传入的数据,不为 null
.setUserId(userId)
.execute();
}
ATMS 把参数保存到 ActivityStart#mRequest 中,并经过 ActivityStarter 来履行发动流程。
ActivityStarter
// ActivityStarter.java
/**
* Resolve necessary information according the request parameters provided earlier, and execute
* the request which begin the journey of starting an activity.
* @return The starter result.
*/
int execute() {
try {
// ...
// 1.解析 Activity 信息,并保存到 mRequest.activityInfo
if (mRequest.activityInfo == null) {
mRequest.resolveActivity(mSupervisor);
}
// ...
int res;
synchronized (mService.mGlobalLock) {
// ...
try {
// 2.履行activity发动恳求
res = executeRequest(mRequest);
} finally {
mRequest.logMessage.append(" result code=").append(res);
// 3. log 中输出发动的数据,以及发动成果
// 这个log 便是著名的 START u0 XXX
Slog.i(TAG, mRequest.logMessage.toString());
mRequest.logMessage.setLength(0);
}
// ...
return getExternalResult(res);
}
} finally {
onExecutionComplete();
}
}
看注释,这一步首要便是解析一些必要信息,例如 activity 信息,然后履行恳求,终究输出一条 START u0 的log。
executeRequest()
// ActivityStarter.java
/**
* Executing activity start request and starts the journey of starting an activity. Here
* begins with performing several preliminary checks. The normally activity launch flow will
* go through {@link #startActivityUnchecked} to {@link #startActivityInner}.
*/
private int executeRequest(Request request) {
// 1. 做一些发动前检查,以及解析一些参数
// ...
// 2.结构 START u0 的log
if (err == ActivityManager.START_SUCCESS) {
request.logMessage.append("START u").append(userId).append(" {")
.append(intent.toShortString(true, true, true, false))
.append("} with ").append(launchModeToString(launchMode))
.append(" from uid ").append(callingUid);
if (callingUid != realCallingUid
&& realCallingUid != Request.DEFAULT_REAL_CALLING_UID) {
request.logMessage.append(" (realCallingUid=").append(realCallingUid).append(")");
}
}
ActivityRecord resultRecord = null;
if (resultTo != null) {
sourceRecord = ActivityRecord.isInAnyTask(resultTo);
if (sourceRecord != null) {
// requestCode 此刻值为 -1,因而 resultRecord 终究值为 null
// 从这儿能够看出,actvity 要想接纳发动别的一个的成果,requestCode 有必要大于0,而且自己没有正在 finish
if (requestCode >= 0 && !sourceRecord.finishing) {
resultRecord = sourceRecord;
}
}
}
// ...
// 3. 创立 ActivityRecord
final ActivityRecord r = new ActivityRecord.Builder(mService)
.setCaller(callerApp) // 指向 launcher 进程
.setLaunchedFromPid(callingPid)
.setLaunchedFromUid(callingUid)
.setLaunchedFromPackage(callingPackage) // com.android.launcher
.setLaunchedFromFeature(callingFeatureId) // null
.setIntent(intent)
.setResolvedType(resolvedType) // null
.setActivityInfo(aInfo)
.setConfiguration(mService.getGlobalConfiguration()) // 当时装备
.setResultTo(resultRecord) // null
.setResultWho(resultWho) // null
.setRequestCode(requestCode) // -1
.setComponentSpecified(request.componentSpecified) // false
.setRootVoiceInteraction(voiceSession != null) // false
.setActivityOptions(checkedOptions) // 不为空
.setSourceRecord(sourceRecord) // launcher
.build();
// mLastStartActivityRecord 保存最近一次发动的activity
mLastStartActivityRecord = r;
// ...
// 4. 以 ActivityRecord 为参数,持续履行发动
mLastStartActivityResult = startActivityUnchecked(r, sourceRecord, voiceSession,
request.voiceInteractor, startFlags, checkedOptions,
inTask, inTaskFragment, balCode, intentGrants, realCallingUid);
// ...
return mLastStartActivityResult;
}
正如注释所说,这一步做了发动前的检查,我省掉了这段代码,因为关于本文来说,并不重要。一旦检查经过,就创立 ActivityRecord,然后利用 ActivityRecord 来履行下一步的发动。
在这一步中,我还展现了 START u0 的 log 是怎么结构的,这儿展现下从桌面冷发动 App 的 log
ActivityTaskManager: START u0
{act=com.android.intent.MAIN,
cat=[com.android.category.LAUNCHER],
flg=0x10200000, cmp=com.example.helloworld/.MainActivity ....} ...
result code = 0
大括号内是 Intent 的信息,flg 的值中包括 FLAG_ACTIVITY_NEW_TASK,所以从桌面冷发动 App,是需求新建一个 Task 的。
startActivityUnchecked()
// ActivityStarter.java
/**
* Start an activity while most of preliminary checks has been done and caller has been
* confirmed that holds necessary permissions to do so.
* Here also ensures that the starting activity is removed if the start wasn't successful.
*/
private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
int startFlags, ActivityOptions options, Task inTask,
TaskFragment inTaskFragment, @BalCode int balCode,
NeededUriGrants intentGrants, int realCallingUid) {
int result = START_CANCELED;
final Task startedActivityRootTask;
final TransitionController transitionController = r.mTransitionController;
// 1.创立 OPEN transition,并使 transition 进入搜集状况
Transition newTransition = transitionController.isShellTransitionsEnabled()
? transitionController.createAndStartCollecting(TRANSIT_OPEN) : null;
// 从 launcher 发动 app 是,会携带一个 RemoteTranstion 数据,与动画相关
RemoteTransition remoteTransition = r.takeRemoteTransition();
try {
mService.deferWindowLayout();
// 1.1 transition 搜集正在发动的 ActivityRecord
transitionController.collect(r);
try {
Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "startActivityInner");
// 2. 持续发动 activity
result = startActivityInner(r, sourceRecord, voiceSession, voiceInteractor,
startFlags, options, inTask, inTaskFragment, balCode,
intentGrants, realCallingUid);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
// 3.处理发动成果
// 首要做两件事,一是失败后的整理作业,二是成功后的恳求发动transition
startedActivityRootTask = handleStartResult(r, options, result, newTransition,
remoteTransition);
}
} finally {
mService.continueWindowLayout();
}
// 留意这段代码中关于 START_TASK_TO_FRONT 和 START_DELIVERED_TO_TOP 成果的处理,与PIP等功用有关
postStartActivityProcessing(r, result, startedActivityRootTask);
return result;
}
- 创立一个 OPEN Transition ,然后搜集 target ActivityRecord。
- 履行下一步发动。
- 处理发动的成果。假如发动失败,会做一些整理作业。假如发动成功时,会恳求发动 transition 。
第1步和第3步的重点在于动画,本文能够不必关怀,我这儿罗列出来,是为了便利今后剖析动画。
约定: target Activity 或许 target ActivityRecord 都代表要发动的 Activity。
startActivityInner()
// ActivityStarter.java
/**
* Start an activity and determine if the activity should be adding to the top of an existing
* task or delivered new intent to an existing activity. Also manipulating the activity task
* onto requested or valid root-task/display.
*
* Note: This method should only be called from {@link #startActivityUnchecked}.
*/
int startActivityInner(final ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
int startFlags, ActivityOptions options, Task inTask,
TaskFragment inTaskFragment, @BalCode int balCode,
NeededUriGrants intentGrants, int realCallingUid) {
// 保存一些初始状况,然后解析一些参数,例如 mDoResume 解析为 true
setInitialState(r, options, inTask, inTaskFragment, startFlags, sourceRecord,
voiceSession, voiceInteractor, balCode, realCallingUid);
// 调整 mLaunchFlags ,它来自于 Intent#mFlags
computeLaunchingTaskFlags();
// mIntent 保存调整后的 mLaunchFlags
mIntent.setFlags(mLaunchFlags);
// ...
// Get top task at beginning because the order may be changed when reusing existing task.
final Task prevTopRootTask = mPreferredTaskDisplayArea.getFocusedRootTask();
final Task prevTopTask = prevTopRootTask != null ? prevTopRootTask.getTopLeafTask() : null;
// 找到一个可重用的Task,现在回来的是 null
final Task reusedTask = getReusableTask();
// ...
// Compute if there is an existing task that should be used for.
// 获取 activity 应该参加的 task,现在获取为 null
final Task targetTask = reusedTask != null ? reusedTask : computeTargetTask();
// 获取不到 activity 应该参加的 task,因而 newTask 为 true
final boolean newTask = targetTask == null;
// mTargetTask 保存 activity 应该参加的 task
// 因为现在没有获取到,因而 mTargetTask 为 null
mTargetTask = targetTask;
// 调整 mLaunchParams,然后从 mLauchParams 中更新 mPreferredTaskDisplayArea,mPreferredWindowingMode
// mPreferredTaskDisplayArea 值为 DefaultTaskDisplayArea
// mPreferredWindowingMode 的值为 WINDOWING_MODE_UNDEFINED
computeLaunchParams(r, sourceRecord, targetTask);
// ...
// null
final ActivityRecord targetTaskTop = newTask
? null : targetTask.getTopNonFinishingActivity();
if (targetTaskTop != null) {
// ...
} else {
// 表明正在把 activity 参加 task
mAddingToTask = true;
}
// 假如当时焦点 root task 的栈顶的 activity 便是要发动的 activity,那么检测是否调用 onNewIntent
final Task topRootTask = mPreferredTaskDisplayArea.getFocusedRootTask();
if (topRootTask != null) {
startResult = deliverToCurrentTopIfNeeded(topRootTask, intentGrants);
if (startResult != START_SUCCESS) {
return startResult;
}
}
if (mTargetRootTask == null) {
// 1. 创立 root task ,而且作为 top child 保存到 TDA 下
mTargetRootTask = getOrCreateRootTask(mStartActivity, mLaunchFlags, targetTask,
mOptions);
}
if (newTask) {
// taskToAffiliate 为 null
final Task taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
? mSourceRecord.getTask() : null;
// 2. root task 作为 leaf task 保存 ActivityRecord,而且是以 top child 的方式保存
setNewTask(taskToAffiliate);
} else if (mAddingToTask) {
// ...
}
if (!mAvoidMoveToFront && mDoResume) {
// 在创立 root task 进程中,现已把 root task 作为 top child 保存到 TDA 下
mTargetRootTask.getRootTask().moveToFront("reuseOrNewTask", targetTask);
if (!mTargetRootTask.isTopRootTaskInDisplayArea() && mService.isDreaming()
&& !dreamStopping) {
// ...
}
}
// ...
final Task startedTask = mStartActivity.getTask();
if (newTask) {
EventLogTags.writeWmCreateTask(mStartActivity.mUserId, startedTask.mTaskId,
startedTask.getRootTaskId(), startedTask.getDisplayId());
}
// event log 会输出 wm_create_activity [XXX],括号里展现了发动 activity 的 Intent 的各种信息,
// 例如 ComponentName , action, flags 等等。
mStartActivity.logStartActivity(EventLogTags.WM_CREATE_ACTIVITY, startedTask);
mStartActivity.getTaskFragment().clearLastPausedActivity();
mRootWindowContainer.startPowerModeLaunchIfNeeded(
false /* forceSend */, mStartActivity);
// isTaskSwitch 为 true
final boolean isTaskSwitch = startedTask != prevTopTask;
// 3. 创立发动窗口
mTargetRootTask.startActivityLocked(mStartActivity, topRootTask, newTask, isTaskSwitch,
mOptions, sourceRecord);
if (mDoResume) {
final ActivityRecord topTaskActivity = startedTask.topRunningActivityLocked();
if (!mTargetRootTask.isTopActivityFocusable()
|| (topTaskActivity != null && topTaskActivity.isTaskOverlay()
&& mStartActivity != topTaskActivity)) {
// ...
} else {
// mTargetRootTask 现在现已是 top focused task
if (!mAvoidMoveToFront && mTargetRootTask.isTopActivityFocusable()
&& !mRootWindowContainer.isTopDisplayFocusedRootTask(mTargetRootTask)) {
// ...
}
// 4. ActivityRecord 的窗口层级现已构建成功,现在由 RWC 来履行下一步发动
// mTransientLaunch 来自于 mOptions 的解析某一个数据,这儿值为 false
mRootWindowContainer.resumeFocusedTasksTopActivities(
mTargetRootTask, mStartActivity, mOptions, mTransientLaunch);
}
}
mRootWindowContainer.updateUserRootTask(mStartActivity.mUserId, mTargetRootTask);
// Update the recent tasks list immediately when the activity starts
// 保存到 RecentTasks#mTasks 中
mSupervisor.mRecentTasks.add(startedTask);
// ...
return START_SUCCESS;
}
这一步,触及到窗口层级树的常识,这儿需求先简单介绍下
窗口层级树大致如下
graph TD
RootWindowContainer --> DisplayContent
DisplayContent --> DislayArea1
DisplayContent --> DislayArea
DisplayContent --> DislayArea2
DislayArea --> TaskDisplayArea
TaskDisplayArea --> Task
Task --> ActivityRecor
ActivityRecord --> WindowState
其中,RootWindowContainer 是层级树的根,DisplayContent 代表一个屏幕,DisplayArea 办理着屏幕上某一部分窗口,TaskDisplayArea 是用来办理 Task,Task 用来保存代表 Activity 的 ActivityRecord,ActivityRecord 保存显现的窗口 WindowState。
有了这个窗口层级树的概念后,再来看这一步的代码。这一步中,有许多琐碎的逻辑,我不好一一剖析,这儿简单阐明下大致的进程
- 创立 root Task,并以 top child 保存到 TaskDisplayArea 下。什么是 root Task ? 保存在 TaskDisplayArea 下的第一个 Task 便是 root Task。
- root Task 作为 leaf Task(叶子结点 Task),把 target ActivityRecord 作为 top child 进行保存。什么是 leaf Task ? 其实 Task 下面也能够保存子 Task,子 Task 下面假如没有 Task,那么子 Task 便是 leaf Task。
- 创立发动窗口。便是 App 开发经常说的 splash screen。
- 窗口层级构建完结后,经过层级树的根 RootWindowContainer 来履行下一步的 Activity 发动。
经过这一步之后,窗口层级树如下
graph TD
RootWindowContainer --> DisplayContent
DisplayContent --> DislayArea1
DisplayContent --> DislayArea
DisplayContent --> DislayArea2
DislayArea --> TaskDisplayArea
TaskDisplayArea --> Task
Task --> ActivityRecord
ActivityRecord --> WindowState
TaskDisplayArea --> targetTask
targetTask --> taretActivityRecord
其中,targetTask 和 targetActvityRecord 的意思,就不言而喻了吧。这儿读者必定很猎奇,targetActvityRecord 为何没有 WindowState 呢?因为现在还没有给 ActivityRecord 增加实践显现的窗口。ActivityRecord 其实不是代表 Activity 的窗口,它是办理 Activity 的一切窗口的容器。
1.我这儿仅仅简单介绍窗口层级树,对窗口有兴趣的读者,能够自行 Google 相关的文章进行学习。
2.能够经过 adb shell dumpsys activity a 检查窗口层级树,你会有一个比较全面的认识。
小结
到此,ActivityStarter 的作业现已完结,回顾下它的效果是什么呢?其实便是构建窗口层级,然后交给 RootWindowContainer 去发动 Activity。
RootWindowContainer
// RootWindowContainer.java
boolean resumeFocusedTasksTopActivities(
Task targetRootTask, ActivityRecord target, ActivityOptions targetOptions,
boolean deferPause) {
if (!mTaskSupervisor.readyToResume()) {
return false;
}
boolean result = false;
// targetRootTask 是要 target activity 的 root task
// targetRootTask 现在现已是 top root task
if (targetRootTask != null && (targetRootTask.isTopRootTaskInDisplayArea()
|| getTopDisplayFocusedRootTask() == targetRootTask)) {
// 有 toot task 发动它的 top activity
// 参数 deferPause 为 false
result = targetRootTask.resumeTopActivityUncheckedLocked(target, targetOptions,
deferPause);
}
// 处理 activity 发动失败的状况
// 例如,从桌面发动 activity 失败,至少体系得再把桌面拉起来
for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
// ...
}
return result;
}
RootWindowContainer 交给 target activity 的 root task 来发动它的 top activity,这个 top activity 便是 target activity.
root Task#resumeTopActivityUncheckedLocked()
// Task.java
// prev 便是 target actvity
// options 不为 null
// deferPause 为 false
boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options,
boolean deferPause) {
if (mInResumeTopActivity) {
// Don't even start recursing.
return false;
}
boolean someActivityResumed = false;
try {
// Protect against recursion.
mInResumeTopActivity = true;
if (isLeafTask()) { // leaf Task
if (isFocusableAndVisible()) { // top activity 能够获焦,而且 task 可见
// 由 leaf Task 来发动它的 top activity
// 参数 prev 此刻是 target activity, 参数deferPause为false
someActivityResumed = resumeTopActivityInnerLocked(prev, options, deferPause);
}
} else {
// ... 这儿处理不是 leaf task 的状况,不外乎便是遍历 children,然后递归调用当时办法
}
final ActivityRecord next = topRunningActivity(true /* focusableOnly */);
if (next == null || !next.canTurnScreenOn()) {
checkReadyForSleep();
}
} finally {
mInResumeTopActivity = false;
}
return someActivityResumed;
}
root Task 把发动使命交给 leaf Task,依据前面的剖析可知,target activity 的 root Task 便是 leaf Task。
leaf Task#resumeTopActivityInnerLocked()
// Task.java
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options,
boolean deferPause) {
if (!mAtmService.isBooting() && !mAtmService.isBooted()) {
// Not ready yet!
return false;
}
//获取 Task 的 top-focusable-non-finishing-activty
final ActivityRecord topActivity = topRunningActivity(true /* focusableOnly */);
if (topActivity == null) {
// ...
}
final boolean[] resumed = new boolean[1];
final TaskFragment topFragment = topActivity.getTaskFragment();
// 由 top activity 的 TaskFragment 来发动 top activity
resumed[0] = topFragment.resumeTopActivity(prev, options, deferPause);
forAllLeafTaskFragments(f -> {
// ...
}, true);
return resumed[0];
}
这儿又有一个 TaskFragment 概念,其实 Task 是承继自 TaskFragment,Task 下面能够保存 TaskFragment,当然也能够保存 Task(因为 Task 是 TaskFragment 子类)。
关于现在剖析的状况,Task 下面是不存在 TaskFragment 的。因而,这儿 leaf Task 把发动使命交给 top activity 的 TaskFragment,这个 TaskFragment 其实便是 leaf Task,而且也是 root Task。
TaskFragment#resumeTopActivity()
// TaskFragment.java
// prev 此刻便是 target activity
// deferPause 为 false
final boolean resumeTopActivity(ActivityRecord prev, ActivityOptions options,
boolean deferPause) {
// 获取 top-focusable-activity,其实便是 target activity
ActivityRecord next = topRunningActivity(true /* focusableOnly */);
if (next == null || !next.canResumeByCompat()) {
return false;
}
next.delayedResume = false;
// 假如当时有 Actvity 正在暂停,那么什么也不做
// If we are currently pausing an activity, then don't do anything until that is done.
final boolean allPausedComplete = mRootWindowContainer.allPausedActivitiesComplete();
if (!allPausedComplete) {
ProtoLog.v(WM_DEBUG_STATES,
"resumeTopActivity: Skip resume: some activity pausing.");
return false;
}
final TaskDisplayArea taskDisplayArea = getDisplayArea();
// Task 才刚刚创立,mResumedActivity 和 mLastPausedActivity 都为 null
if (mResumedActivity == next && next.isState(RESUMED)
&& taskDisplayArea.allResumedActivitiesComplete()) {
// ....
return false;
}
if (mLastPausedActivity == next && shouldSleepOrShutDownActivities()) {
// ...
return false;
}
// ...
// 1.暂停后台 Task
// 假如有后台 Task 的 resumed activity 正在暂停,那么回来 false
// 此刻 deferPause 为 false
boolean pausing = !deferPause && taskDisplayArea.pauseBackTasks(next);
if (mResumedActivity != null) {
// ...
}
if (pausing) {
ProtoLog.v(WM_DEBUG_STATES, "resumeTopActivity: Skip resume: need to"
+ " start pausing");
if (next.attachedToProcess()) {
// ...
} else if (!next.isProcessRunning()) {
// Since the start-process is asynchronous, if we already know the process of next
// activity isn't running, we can start the process earlier to save the time to wait
// for the current activity to be paused.
final boolean isTop = this == taskDisplayArea.getFocusedRootTask();
// 2. 假如要发动的 acivity 的进程还没有发动,那么先创立进程
mAtmService.startProcessAsync(next, false /* knownToBeDead */, isTop,
isTop ? HostingRecord.HOSTING_TYPE_NEXT_TOP_ACTIVITY
: HostingRecord.HOSTING_TYPE_NEXT_ACTIVITY);
}
// 留意,这儿直接回来了
// 此刻的状况是 activity 的进程现已发动
return true;
} else if (mResumedActivity == next && next.isState(RESUMED)
&& taskDisplayArea.allResumedActivitiesComplete()) {
// ...
}
// ...
return true;
}
target activity 的 TaskFragment ,先暂停后台 Task ,然后因为 target activity 的进程还没有发动,因而需求先创立进程。
暂停后台Task
依据前面所了解的窗口层级树可知,TaskDisplayArea 办理一切的 Task,因而暂停后台 Task 的使命必定是交给它。
// TaskDisplayArea.java
// 参数 resuming 此刻便是 target activity
boolean pauseBackTasks(ActivityRecord resuming) {
final int[] someActivityPaused = {0};
// 从上到下,遍历 TaskDisplayArea 下的一切 leaf Task
forAllLeafTasks(leafTask -> {
// 现在咱们剖析的状况,leaf Task 是不包括 TaskFragment
if (!leafTask.isLeafTaskFragment()) {
// ...
}
// 从上到下,遍历 leaf Task 下的 leaf TaskFragment
// 留意,假如 Task 下没有 TaskFragment,那么 Task 会作为 leaf TaskFragment 来回调
leafTask.forAllLeafTaskFragments((taskFrag) -> {
final ActivityRecord resumedActivity = taskFrag.getResumedActivity();
// 后台 Task 有必要要有 resumed activity,而且不能发动 target activity
if (resumedActivity != null && !taskFrag.canBeResumed(resuming)) {
if (taskFrag.startPausing(false /* uiSleeping*/, resuming, "pauseBackTasks")) {
someActivityPaused[0]++;
}
}
}, true /* traverseTopToBottom */);
}, true /* traverseTopToBottom */);
return someActivityPaused[0] > 0;
}
TaskDisplayArea 遍历一切 leaf Task,然后 leaf Task 遍历一切 leaf TaskFragment,终究又 leaf TaskFragment 来暂停 resumed activity。
依据前面的剖析可知,leaf Task 下是不存在 TaskFragment 的,因而这儿其实便是有 leaf Task 暂停 resumed activity。此刻的需求暂停的后台 Task 便是桌面的 Task,因为只要它有 resumed activity。
// TaskFragment.java
final boolean startPausing(boolean uiSleeping, ActivityRecord resuming, String reason) {
return startPausing(mTaskSupervisor.mUserLeaving, uiSleeping, resuming, reason);
}
// 参数 resuming 此刻是 target activity
boolean startPausing(boolean userLeaving, boolean uiSleeping, ActivityRecord resuming,
String reason) {
if (!hasDirectChildActivities()) {
return false;
}
ProtoLog.d(WM_DEBUG_STATES, "startPausing: taskFrag =%s " + "mResumedActivity=%s", this,
mResumedActivity);
if (mPausingActivity != null) {
// ..
}
// mResumedActivity 便是桌面正在显现的 Activity
ActivityRecord prev = mResumedActivity;
if (prev == null) {
// ...
return false;
}
if (prev == resuming) {
Slog.wtf(TAG, "Trying to pause activity that is in process of being resumed");
return false;
}
ProtoLog.v(WM_DEBUG_STATES, "Moving to PAUSING: %s", prev);
// 保存正在暂停的 Activity
mPausingActivity = prev;
mLastPausedActivity = prev;
// TODO: 这个 no history 有什么用
if (!prev.finishing && prev.isNoHistory()
&& !mTaskSupervisor.mNoHistoryActivities.contains(prev)) {
mTaskSupervisor.mNoHistoryActivities.add(prev);
}
// 1. 正在暂停的 Activity,状况切换到 PAUSING
// 而且还会告诉 TaskFragment 状况改变,TaskFragment 会把它的 mResumedActivity 更新为 null
prev.setState(PAUSING, "startPausingLocked");
prev.getTask().touchActiveTime();
mAtmService.updateCpuStats();
// pauseImmediately 表明在告诉 app 端去暂停 activity 后,服务端是否立即完结暂停使命
// 假如 pauseImmediately 为 true,那么要发动的 Activity 不会等候后台 activity 暂停完结
// 就能够直接发动,这个关于热发动或许温发动十分有用,因为能够加快 Activity 发动速度
// 可是,很显然是有坏处的,后台 Activity 还没有调用 onPaused() 就发动新 Activity,
// 可能会导致数据丢掉等等的异常状况
boolean pauseImmediately = false;
boolean shouldAutoPip = false;
if (resuming != null) {
final boolean resumingOccludesParent = resuming.occludesParent();
// false
final boolean lastResumedCanPip = prev.checkEnterPictureInPictureState(
"shouldAutoPipWhilePausing", userLeaving);
if (userLeaving && resumingOccludesParent && lastResumedCanPip
&& prev.pictureInPictureArgs.isAutoEnterEnabled()) {
// ...
} else if (!lastResumedCanPip) {
// 这是 AndroidManifest 中 Activity 的属性 resumeWhilePausing
pauseImmediately = (resuming.info.flags & FLAG_RESUME_WHILE_PAUSING) != 0;
} else {
// ...
}
}
if (prev.attachedToProcess()) {
if (shouldAutoPip) {
// ...
} else {
// 2.告诉app端去暂停activity
// 参数 pauseImmediately 一般为 false
schedulePauseActivity(prev, userLeaving, pauseImmediately,
false /* autoEnteringPip */, reason);
}
} else {
// ...
}
// ...
if (mPausingActivity != null) {
if (!uiSleeping) {
prev.pauseKeyDispatchingLocked();
} else {
ProtoLog.v(WM_DEBUG_STATES, "Key dispatch not paused for screen off");
}
// pauseImmediately 一般为 false
if (pauseImmediately) {
// ...
} else {
// 发送一个暂停超时消息
prev.schedulePauseTimeout();
// All activities will be stopped when sleeping, don't need to wait for pause.
if (!uiSleeping) {
// 3. 更新 Transition 的 ready 状况为 false,因为要等候后台 activity 暂停完结。
// Unset readiness since we now need to wait until this pause is complete.
mTransitionController.setReady(this, false /* ready */);
}
return true;
}
} else {
// ...
}
}
来看下 leaf TaskFragment 是怎么完结暂停后台 Task 的使命
- 用 mPausingActivity 保存正在暂停的 Activity,而且把状况切换到 PAUSING,这儿还会整理掉 mResumingActivity。
- 告诉 app 端去暂停 Activity。
- 更新 Transition 的 ready 状况为 false,这归于动画部分,可不必关怀。
下一篇文章,我会详细剖析服务端怎么告诉 app 端去操作 Activity 生命周期,以及 app 端怎么告诉服务端生命周期处理完结。
小结
现在总结下 RootWindowContainer 在发动进程的效果
- 暂停后台 Task,也便是告诉后台 Task 的 app 端去暂停 Activity,而且 app 端也会告诉服务端 activity 暂停完结。而服务端处理 activity 暂停完结时,也会尝试去发动 target activity,我称之为第二阶段发动。
- 创立 target activity 的进程。当进程创立完结后,会运行 app,然后告诉服务端去 attach app,服务端处理 attach app 时,也会去发动 target activity,我称之为第三个发动阶段。
要留意,以上所说的两个发动阶段,都是异步履行的。那么谁先履行,导致代码的履行流程也不同。可是,通常创立进程是十分缓慢的,慢到什么程度呢?慢到第二阶段完毕时,第三阶段还没有开端。
第二阶段发动
如前面所说,第二阶段发动,开端于 app 端告诉服务端 activity 暂停完结,服务端会调用如下函数
// ActivityClientController.java
public void activityPaused(IBinder token) {
final long origId = Binder.clearCallingIdentity();
synchronized (mGlobalLock) {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "activityPaused");
// 获取服务端对应的 ActivityRecord
final ActivityRecord r = ActivityRecord.forTokenLocked(token);
if (r != null) {
// 告诉 ActvityRecord 暂停完结
r.activityPaused(false);
}
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
Binder.restoreCallingIdentity(origId);
}
// ActivityRecord.java
void activityPaused(boolean timeout) {
ProtoLog.v(WM_DEBUG_STATES, "Activity paused: token=%s, timeout=%b", token,
timeout);
final TaskFragment taskFragment = getTaskFragment();
if (taskFragment != null) {
removePauseTimeout();
final ActivityRecord pausingActivity = taskFragment.getPausingActivity();
if (pausingActivity == this) {
ProtoLog.v(WM_DEBUG_STATES, "Moving to PAUSED: %s %s", this,
(timeout ? "(due to timeout)" : " (pause complete)"));
mAtmService.deferWindowLayout();
try {
// 1. activity 的 TaskFragment 完结 activity 暂停
// 第一个参数 resumeNext 为 true,表明需求 resume 下一个 activity
taskFragment.completePause(true /* resumeNext */, null /* resumingActivity */);
} finally {
mAtmService.continueWindowLayout();
}
// 暂停完结,直接退出
return;
} else {
// ...
}
}
// ...
}
能够看到,服务端是由已暂停 ActivityRecord 的 TaskFragment 来处理暂停完结的作业
// TaskFragment.java
void completePause(boolean resumeNext, ActivityRecord resuming) {
ActivityRecord prev = mPausingActivity;
ProtoLog.v(WM_DEBUG_STATES, "Complete pause: %s", prev);
if (prev != null) {
prev.setWillCloseOrEnterPip(false);
// 当时状况是 PAUSING,所以这儿为 false
final boolean wasStopping = prev.isState(STOPPING);
// 1. 更新 AcivityRecrod#mState 为 PAUSED
prev.setState(PAUSED, "completePausedLocked");
if (prev.finishing) {
// ...
} else if (prev.attachedToProcess()) {
ProtoLog.v(WM_DEBUG_STATES, "Enqueue pending stop if needed: %s "
+ "wasStopping=%b visibleRequested=%b", prev, wasStopping,
prev.isVisibleRequested());
if (prev.deferRelaunchUntilPaused) {
// ...
} else if (wasStopping) {
// ...
} else if (!prev.isVisibleRequested() || shouldSleepOrShutDownActivities()) {
// ... 现在 prev.mVisibleRequested 仍是 true
}
} else {
// ...
}
if (prev != null) {
prev.stopFreezingScreenLocked(true /*force*/);
}
// 现在现已进入 PAUSED 状况,因而整理 mPausingActivity
mPausingActivity = null;
}
// 此刻 resumeNext 为 true
if (resumeNext) {
final Task topRootTask = mRootWindowContainer.getTopDisplayFocusedRootTask();
if (topRootTask != null && !topRootTask.shouldSleepOrShutDownActivities()) {
// 2. resume top activity of top focused root task
mRootWindowContainer.resumeFocusedTasksTopActivities(topRootTask, prev,
null /* targetOptions */);
} else {
// ...
}
}
if (prev != null) {
prev.resumeKeyDispatchingLocked();
}
// 3.更新 activity 可见性
mRootWindowContainer.ensureActivitiesVisible(resuming, 0, !PRESERVE_WINDOWS);
if (mTaskSupervisor.mAppVisibilitiesChangedSinceLastPause
|| (getDisplayArea() != null && getDisplayArea().hasPinnedTask())) {
mAtmService.getTaskChangeNotificationController().notifyTaskStackChanged();
mTaskSupervisor.mAppVisibilitiesChangedSinceLastPause = false;
}
}
TaskFragment 处理 activity 暂停完结
- 把正在暂停的 ActivityRecord 的 mState 更新为 PAUSED,而且整理 mPausingActivity。
- 告诉 RootWindowContainer 再次去发动 top root task 的 top activity,其实便是发动 target activity。
- 更新 ActivityRecord 的可见性,这一步其实触及到已暂停 Activity 的生命周期流程,已暂停 Activity 会在这儿进入 stopping 流程。
RootWindowContainer 发动 target actiity
RootWindowContainer#resumeTopActivity() 这个函数,在前面现已剖析过,终究是由 TaskFragment 来发动 target activity
// TaskFragment.java
// 参数 prev 此刻代表现已完结暂停的 Activity
// options 为 null
// deferPause 为 false
final boolean resumeTopActivity(ActivityRecord prev, ActivityOptions options,
boolean deferPause) {
// 获取 TaskFragment 的 top-focusable-activity
ActivityRecord next = topRunningActivity(true /* focusableOnly */);
if (next == null || !next.canResumeByCompat()) {
return false;
}
next.delayedResume = false;
// 假如有 activity 正在暂停,那么什么也不做
final boolean allPausedComplete = mRootWindowContainer.allPausedActivitiesComplete();
if (!allPausedComplete) {
ProtoLog.v(WM_DEBUG_STATES,
"resumeTopActivity: Skip resume: some activity pausing.");
return false;
}
final TaskDisplayArea taskDisplayArea = getDisplayArea();
// 此刻 mResumedActivity 为 null
if (mResumedActivity == next && next.isState(RESUMED)
&& taskDisplayArea.allResumedActivitiesComplete()) {
// ....
return false;
}
// 此刻 mLastPausedActivity 为 null
if (mLastPausedActivity == next && shouldSleepOrShutDownActivities()) {
// ...
return false;
}
// ...
// 暂停后台 Task
// 此刻现已没有需求暂停的后台 Task 了,因而这儿回来 false
boolean pausing = !deferPause && taskDisplayArea.pauseBackTasks(next);
// mResumedActivity 为 null
if (mResumedActivity != null) {
// ...
}
if (pausing) {
// ...
}
// mResumedActivity 为 null
else if (mResumedActivity == next && next.isState(RESUMED)
&& taskDisplayArea.allResumedActivitiesComplete()) {
// ....
return true;
}
// ...
// next 代表 target activity
// next.nowVisible 代表是 Acivity 的窗口是否可见,现在是不行见的
if (prev != null && prev != next && next.nowVisible) {
// ...
}
// ...
boolean anim = true;
final DisplayContent dc = taskDisplayArea.mDisplayContent;
if (prev != null) {
if (prev.finishing) {
// ...
} else {
if (DEBUG_TRANSITION) {
Slog.v(TAG_TRANSITION, "Prepare open transition: prev=" + prev);
}
// shell transition 翻开的状况下,下面的 AppTransition 功用无效
if (mTaskSupervisor.mNoAnimActivities.contains(next)) {
anim = false;
dc.prepareAppTransition(TRANSIT_NONE);
} else {
dc.prepareAppTransition(TRANSIT_OPEN,
next.mLaunchTaskBehind ? TRANSIT_FLAG_OPEN_BEHIND : 0);
}
}
} else {
// ...
}
if (anim) {
// 这儿虽然是针对 app transition 动画,可是有设置状况栏动画推迟
next.applyOptionsAnimation();
} else {
next.abortAndClearOptionsAnimation();
}
mTaskSupervisor.mNoAnimActivities.clear();
// 检测行将发动的 ActivityRecord 是否绑定到进程
// 进程还在创立中呢!
if (next.attachedToProcess()) {
// ...
} else {
// Whoops, need to restart this activity!
if (!next.hasBeenLaunched) {
next.hasBeenLaunched = true;
} else {
if (SHOW_APP_STARTING_PREVIEW) {
next.showStartingWindow(false /* taskSwich */);
}
if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Restarting: " + next);
}
ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivity: Restarting %s", next);
// 依据进程状况发动 activity
mTaskSupervisor.startSpecificActivity(next, true, true);
}
return true;
}
现在,后台 Task 现已暂停完结了,因而,一般来说,target ActivityRecord 此刻还没有绑定进程,那么只能经过 AcivityTaskSupervisor 依据进程状况来发动 target activity
// ActivityTaskSupervisor.java
void startSpecificActivity(ActivityRecord r, boolean andResume, boolean checkConfig) {
// Is this activity's application already running?
final WindowProcessController wpc =
mService.getProcessController(r.processName, r.info.applicationInfo.uid);
boolean knownToBeDead = false;
if (wpc != null && wpc.hasThread()) {
try {
// 假如现已完结了 attach app ,那么直接告诉 app 端发动 target activity
realStartActivityLocked(r, wpc, andResume, checkConfig);
return;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when starting activity "
+ r.intent.getComponent().flattenToShortString(), e);
}
// ...
} else if (r.intent.isSandboxActivity(mService.mContext)) {
// ...
}
r.notifyUnknownVisibilityLaunchedForKeyguardTransition();
final boolean isTop = andResume && r.isTopRunningActivity();
// 走到这儿,表明连 attach app 进程都没有完结
// 那么直接走发动进程的流程
mService.startProcessAsync(r, knownToBeDead, isTop,
isTop ? HostingRecord.HOSTING_TYPE_TOP_ACTIVITY
: HostingRecord.HOSTING_TYPE_ACTIVITY);
}
其实,到现在为止,target activity 的进程还在创立中,更不行能完结 attach app ,因而,这儿终究仍是直接走了创立进程的流程。 因为 target activity 的进程,此刻现已在创立中,那么这儿其实什么也没做。
更新 ActivityRecord 可见性
// RootWindowContainer.java
// starting 为 null
// configChanges 为 0
// preserveWindows 为 false
void ensureActivitiesVisible(ActivityRecord starting, int configChanges,
boolean preserveWindows) {
ensureActivitiesVisible(starting, configChanges, preserveWindows, true /* notifyClients */);
}
这儿会从 RootWindowContainer 开端,从上到下遍历,找到 leaf Task ,然后由 EnsureActivitiesVisibleHelper 来处理 leaf Task 下的 ActivityRecord 可见性,如下
// EnsureActivitiesVisibleHelper.java
// starting 为 null, configChanges 为0,preserveWindows为false,notifyClients为true
void process(@Nullable ActivityRecord starting, int configChanges, boolean preserveWindows,
boolean notifyClients) {
// ...
ArrayList<TaskFragment> adjacentTaskFragments = null;
for (int i = mTaskFragment.mChildren.size() - 1; i >= 0; --i) {
final WindowContainer child = mTaskFragment.mChildren.get(i);
final TaskFragment childTaskFragment = child.asTaskFragment();
if (childTaskFragment != null
&& childTaskFragment.getTopNonFinishingActivity() != null) {
// ...
} else if (child.asActivityRecord() != null) {
// 设置 ActivityRecord 可见性
setActivityVisibilityState(child.asActivityRecord(), starting, resumeTopActivity);
}
}
}
EnsureActivitiesVisibleHelper 也是从上到下遍历 leaf Task 的 children,因为咱们剖析的状况是 Task 下只存在 ActivityRecord,因而终究调用 setActivityVisibilityState() 来更新可见性
// EnsureActivitiesVisibleHelper.java
private void setActivityVisibilityState(ActivityRecord r, ActivityRecord starting,
final boolean resumeTopActivity) {
// ...
if (reallyVisible) {
// ...
if (!r.attachedToProcess()) {
// 1.更新可见
makeVisibleAndRestartIfNeeded(mStarting, mConfigChanges,
resumeTopActivity && isTop, r);
} else if (r.isVisibleRequested()) {
// ...
} else {
// ...
}
mConfigChanges |= r.configChangeFlags;
} else {
if (DEBUG_VISIBILITY) {
Slog.v(TAG_VISIBILITY, "Make invisible? " + r
+ " finishing=" + r.finishing + " state=" + r.getState()
+ " containerShouldBeVisible=" + mContainerShouldBeVisible
+ " behindFullyOccludedContainer=" + mBehindFullyOccludedContainer
+ " mLaunchTaskBehind=" + r.mLaunchTaskBehind);
}
// 2.更新不行见
r.makeInvisible();
}
// ...
}
这儿触及到一些琐碎的窗口可见性核算,本文就不展现了。关于现在的状况来说,top Task 便是 target activity 的 Task,它的 top activity ,也便是 target activity,因为进程还在创立中,因而它会更新可见。而关于桌面的 Task,因为它现在是后台 Task,因而它的 top activity 要更新不行见。
咱们这儿只关怀不行见性更新,只为它直接与生命周期相关
// ActivityRecord.java
void makeInvisible() {
// 从这儿能够看出,更新可见性其实便是更新 mVisibleRequested
if (!mVisibleRequested) {
if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Already invisible: " + this);
return;
}
if (DEBUG_VISIBILITY) {
Slog.v(TAG_VISIBILITY, "Making invisible: " + this + ", state=" + getState());
}
try {
// ...
// 1.更新可见性为 false,其实便是更新 mVisibleRequested
setVisibility(false);
switch (getState()) {
// ...
case PAUSED:
// 2.已暂停的 activity 进入 stopping 流程
addToStopping(true /* scheduleIdle */,
canEnterPictureInPicture /* idleDelayed */, "makeInvisible");
break;
}
}
}
第一步是更新可见性,也便是更新 ActivityRecord#mVisibleRequested,这儿就不剖析。来看下第二步,已暂停的 Activity 进入 stopping 流程
// ActivityRecord.java
void addToStopping(boolean scheduleIdle, boolean idleDelayed, String reason) {
// 1. 参加到 mTaskSupervisor.mStoppingActivities 中
if (!mTaskSupervisor.mStoppingActivities.contains(this)) {
EventLogTags.writeWmAddToStopping(mUserId, System.identityHashCode(this),
shortComponentName, reason);
mTaskSupervisor.mStoppingActivities.add(this);
}
final Task rootTask = getRootTask();
boolean forceIdle = mTaskSupervisor.mStoppingActivities.size() > MAX_STOPPING_TO_FORCE
|| (isRootOfTask() && rootTask.getChildCount() <= 1);
// scheduleIdle 此刻为 true
if (scheduleIdle || forceIdle) {
ProtoLog.v(WM_DEBUG_STATES,
"Scheduling idle now: forceIdle=%b immediate=%b", forceIdle, !idleDelayed);
// idleDelayed 此刻为 false
if (!idleDelayed) {
// 2.强制调用 idle 处理流程
mTaskSupervisor.scheduleIdle();
} else {
// ...
}
} else {
// ...
}
}
已暂停的 Activity 在真实进入到 stopping 流程前,首要需求参加到 stopping list 中,也便是 mTaskSupervisor.mStoppingActivities,然后强制调度一次 idle 流程。
idle 流程才决定了是否真实进入到 stopping 流程,可是有条件限制的,来看下完结,终究会调用到如下函数
// ActivityRecord.java
void processStoppingAndFinishingActivities(ActivityRecord launchedActivity,
boolean processPausingActivities, String reason) {
boolean displaySwapping = false;
ArrayList<ActivityRecord> readyToStopActivities = null;
for (int i = 0; i < mStoppingActivities.size(); i++) {
final ActivityRecord s = mStoppingActivities.get(i);
// 判别 ActivityRecord 是否处于动画中
// 现在,确实处于动画中
final boolean animating = s.isInTransition()
&& s.getTask() != null && !s.getTask().isForceHidden();
displaySwapping |= s.isDisplaySleepingAndSwapping();
ProtoLog.v(WM_DEBUG_STATES, "Stopping %s: nowVisible=%b animating=%b "
+ "finishing=%s", s, s.nowVisible, animating, s.finishing);
// 假如 ActivityRecord 处于动画中,那就保存到 readyToStopActivities
if ((!animating && !displaySwapping) || mService.mShuttingDown) {
if (!processPausingActivities && s.isState(PAUSING)) {
// Defer processing pausing activities in this iteration and reschedule
// a delayed idle to reprocess it again
removeIdleTimeoutForActivity(launchedActivity);
scheduleIdleTimeout(launchedActivity);
continue;
}
ProtoLog.v(WM_DEBUG_STATES, "Ready to stop: %s", s);
if (readyToStopActivities == null) {
readyToStopActivities = new ArrayList<>();
}
readyToStopActivities.add(s);
mStoppingActivities.remove(i);
i--;
}
}
// ...
final int numReadyStops = readyToStopActivities == null ? 0 : readyToStopActivities.size();
for (int i = 0; i < numReadyStops; i++) {
final ActivityRecord r = readyToStopActivities.get(i);
if (r.isInHistory()) {
if (r.finishing) {
// ...
} else {
// 告诉 app 端去 stop
r.stopIfPossible();
}
}
}
// ...
}
看到了吧,只要已暂停的 ActivityRecord 不处于动画中,才干真实的进入 stopping 流程。可是,很可惜,在 ActivityRecord 更新可见性时,就被搜集到 Transition 中,也便是处于动画中了。所以,已暂停的 Activity 此刻不能进入 stopping 流程,也就无法告诉 app 端去 stop activity。
小结
第二阶段发动,是由服务端收到 actvity paused 开端,首要便是把已暂停的 ActivityRecord 状况更新到 PAUSED,然后参加到 stopping list 中。
第三阶段发动
第三阶段的发动,是由创立 target activity 进程开端,可是进程创立的进程,本文就不剖析了。当进程创立完毕后,会履行 App 的进口函数,也便是 ActivityThread#main()
// ActivityThread.java
public static void main(String[] args) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
// ...
Looper.prepareMainLooper();
// ...
// 创立 ActivityThread,并调用它的 attach()
ActivityThread thread = new ActivityThread();
thread.attach(false, startSeq);
// ...
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
private void attach(boolean system, long startSeq) {
// ..
if (!system) {
final IActivityManager mgr = ActivityManager.getService();
try {
// 1. attach app
// mAppThread 是一个 binder 回调,在服务端代表 app 进程
mgr.attachApplication(mAppThread, startSeq);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
// ...
} else {
// ...
}
// ...
}
ActivityThreaad#main() 终究便是向服务端注册一个 Binder 回调,这便是所谓的 attach app。
attach app
现在来看下服务端的 attach app 流程
// ActivityManagerService.java
public final void attachApplication(IApplicationThread thread, long startSeq) {
if (thread == null) {
throw new SecurityException("Invalid application interface");
}
synchronized (this) {
int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
final long origId = Binder.clearCallingIdentity();
attachApplicationLocked(thread, callingPid, callingUid, startSeq);
Binder.restoreCallingIdentity(origId);
}
}
private void attachApplicationLocked(@NonNull IApplicationThread thread,
int pid, int callingUid, long startSeq) {
// ...
if (pid != MY_PID && pid >= 0) {
synchronized (mPidsSelfLocked) {
// 进程创立的时分,会保存到 mPidsSelfLocked
app = mPidsSelfLocked.get(pid);
}
if (app != null && (app.getStartUid() != callingUid || app.getStartSeq() != startSeq)) {
// ...
}
} else {
// ...
}
// ...
EventLogTags.writeAmProcBound(app.userId, pid, app.processName);
// ...
try {
// ...
if (app.getIsolatedEntryPoint() != null) {
// ....
} else if (instr2 != null) {
// ...
} else {
// 1. 告诉 app 进行 bind application
thread.bindApplication(processName, appInfo,
app.sdkSandboxClientAppVolumeUuid, app.sdkSandboxClientAppPackage,
providerList, null, profilerInfo, null, null, null, testMode,
mBinderTransactionTrackingEnabled, enableTrackAllocation,
isRestrictedBackupMode || !normalMode, app.isPersistent(),
new Configuration(app.getWindowProcessController().getConfiguration()),
app.getCompat(), getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked(),
buildSerial, autofillOptions, contentCaptureOptions,
app.getDisabledCompatChanges(), serializedSystemFontMap,
app.getStartElapsedTime(), app.getStartUptime());
}
// ...
synchronized (mProcLock) {
// 2. 完结 attach app
// 其实便是进程实例 ProcessRecord 保存 app 端传入的回调 IApplicationThread 对象
app.makeActive(thread, mProcessStats);
checkTime(startTime, "attachApplicationLocked: immediately after bindApplication");
}
// ...
// mConstants.mEnableWaitForFinishAttachApplication 默以为 false
// 假如为 true,表明需求等候 app 完结 bind application 之后,才履行 finish attach application 操作
if (!mConstants.mEnableWaitForFinishAttachApplication) {
// 3. 收尾 attach app
// 四大组件中假如有等候进程发动的,此刻就能够发动组件
finishAttachApplicationInner(startSeq, callingUid, pid);
} else {
// ...
}
} catch (Exception e) {
// ...
}
}
服务端处理 attach app
- 告诉 app 端 bind application。其实首要便是创立 Application 。
- 进程实例保存 app 端收支的回调,这便是真实的 attach app,也能够叫做 attach app to process。
- attach app 收尾。首要是针对四大组件的发动,例如,假如发动 activity 时,activity 连进程都没有创立,那么等进程创立完毕,在 attach app 时,再发动 activity。
finish attach app
// ActivityManagerService.java
private void finishAttachApplicationInner(long startSeq, int uid, int pid) {
final ProcessRecord app;
synchronized (mPidsSelfLocked) {
// 获取进程实例 ProcessRecord
app = mPidsSelfLocked.get(pid);
}
// ...
synchronized (this) {
// ...
// See if the top visible activity is waiting to run in this process...
if (normalMode) {
try {
didSomething = mAtmInternal.attachApplication(app.getWindowProcessController());
} catch (Exception e) {
// ...
}
}
// ...
}
}
从注释能够看出,检测是否 top visible acitivity 等候进程发动,假如有,这个时分就能够发动这个 top visible activity
// ActivityTaskManagerService.java
public boolean attachApplication(WindowProcessController wpc) throws RemoteException {
synchronized (mGlobalLockWithoutBoost) {
if (Trace.isTagEnabled(TRACE_TAG_WINDOW_MANAGER)) {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "attachApplication:" + wpc.mName);
}
try {
return mRootWindowContainer.attachApplication(wpc);
} finally {
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
}
}
// RootWindowContainer.java
boolean attachApplication(WindowProcessController app) throws RemoteException {
try {
return mAttachApplicationHelper.process(app);
} finally {
mAttachApplicationHelper.reset();
}
}
boolean process(WindowProcessController app) throws RemoteException {
mApp = app;
// RootWindowContainer 从上到下,遍历一切的 children,也便是 DisplayContent
for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
// DisplayContent 遍历一切的 root task
getChildAt(displayNdx).forAllRootTasks(this);
if (mRemoteException != null) {
throw mRemoteException;
}
}
// 此刻有 aciivty 发动,mHasActivityStar为 true
if (!mHasActivityStarted) {
// ...
}
return mHasActivityStarted;
}
public void accept(Task rootTask) {
if (mRemoteException != null) {
return;
}
// root task 不行见,不能发动 activity
// top root task 一般都是可见的
if (rootTask.getVisibility(null /* starting */)
== TASK_FRAGMENT_VISIBILITY_INVISIBLE) {
return;
}
// 保存 root task 的 top activity
mTop = rootTask.topRunningActivity();
// root task 从上到下遍历 activity
rootTask.forAllActivities(this);
}
public boolean test(ActivityRecord r) {
// 留意这儿 r.app != null 条件,假如 r.app 不为 null,那么表明 activity 现已发动
if (r.finishing || !r.showToCurrentUser() || !r.visibleIgnoringKeyguard
|| r.app != null || mApp.mUid != r.info.applicationInfo.uid
|| !mApp.mName.equals(r.processName)) {
return false;
}
try {
// 真实发动 acivity 地方
if (mTaskSupervisor.realStartActivityLocked(r, mApp,
mTop == r && r.getTask().canBeResumed(r) /* andResume */,
true /* checkConfig */)) {
// 表明有activity发动了
mHasActivityStarted = true;
}
} catch (RemoteException e) {
// ...
}
return false;
}
有了窗口层级树的常识,这儿是不是十分简单,便是从根 RootWindowContainer 开端,从上到下遍历,然后发动那些还没有发动的 activity,也便是发动咱们的 target actvity
OK,现在由 ActivityTaskSupervisor 真实的来发动 target activity
// ActivityTaskSupervisor.java
boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc,
boolean andResume, boolean checkConfig) throws RemoteException {
// 有 Activity 正在暂停,不能发动 activity
if (!mRootWindowContainer.allPausedActivitiesComplete()) {
ProtoLog.v(WM_DEBUG_STATES,
"realStartActivityLocked: Skipping start of r=%s some activities pausing...",
r);
return false;
}
// ...
try {
// ...
// 1.ActivityRecord 绑定进程,这便是 attach ActivityRecord to process
// 下面立刻就要告诉 app 端发动 activity
r.setProcess(proc);
// ...
// checkConfig 此刻为 true
if (checkConfig) {
// 更新可见性,然后检测体系方向是否要更新,假如要更新,那么还会更新体系装备
mRootWindowContainer.ensureVisibilityAndConfig(r, r.getDisplayId(),
false /* markFrozenIfConfigChanged */, true /* deferResume */);
}
// ...
// 这是一个 binder ,它会被发送给客户端,客户端使用它来回调 activity 状况
final IActivityClientController activityClientController =
proc.hasEverLaunchedActivity() ? null : mService.mActivityClientController;
// ...
try {
if (!proc.hasThread()) {
throw new RemoteException();
}
// ...
// event log : wm_restart_activity [userId, hashCode, taskId, componentName]
EventLogTags.writeWmRestartActivity(r.mUserId, System.identityHashCode(r),
task.mTaskId, r.shortComponentName);
// ...
// 核算发送客户端的装备
final Configuration procConfig = proc.prepareConfigurationForLaunchingActivity();
final MergedConfiguration mergedConfiguration = new MergedConfiguration(
procConfig, r.getMergedOverrideConfiguration());
// 保存上一次发送的装备
r.setLastReportedConfiguration(mergedConfiguration);
// ...
// 创立一个事务,这个事务会发送给客户端
final ClientTransaction clientTransaction = ClientTransaction.obtain(
proc.getThread(), r.token);
final boolean isTransitionForward = r.isTransitionForward();
final IBinder fragmentToken = r.getTaskFragment().getFragmentToken();
final int deviceId = getDeviceIdForDisplayId(r.getDisplayId());
// 给这个事务,增加一个回调,这个用于创立 Activity,而且调用 Activity#onCreate()
clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),
System.identityHashCode(r), r.info,
// TODO: Have this take the merged configuration instead of separate global
// and override configs.
mergedConfiguration.getGlobalConfiguration(),
mergedConfiguration.getOverrideConfiguration(), deviceId,
r.getFilteredReferrer(r.launchedFromPackage), task.voiceInteractor,
proc.getReportedProcState(), r.getSavedState(), r.getPersistentSavedState(),
results, newIntents, r.takeOptions(), isTransitionForward,
proc.createProfilerInfoIfNeeded(), r.assistToken, activityClientController,
r.shareableActivityToken, r.getLaunchedFromBubble(), fragmentToken));
// Set desired final state.
final ActivityLifecycleItem lifecycleItem;
if (andResume) {
// 创立一个 Resume 的生命周期恳求
// 代表 Activity 声明周期的终究状况
lifecycleItem = ResumeActivityItem.obtain(isTransitionForward,
r.shouldSendCompatFakeFocus());
} else {
// ...
}
// 设置终究的生命周期状况
clientTransaction.setLifecycleStateRequest(lifecycleItem);
// 2. 告诉 app 端创立 Activity,并将生命周期履行到 onResumed()
mService.getLifecycleManager().scheduleTransaction(clientTransaction);
// ...
} catch (RemoteException e) {
// ...
}
} finally {
endDeferResume();
proc.resumeConfigurationDispatch();
}
r.launchFailed = false;
if (andResume && readyToResume()) {
// 3.完结最小部分 activity resumed 的作业
// 例如将 activity 状况设置为 RESUMED
// Activity履行完 onResumed() 后,会告诉服务端的,服务端然后完结剩余的 resumed activity 作业
rootTask.minimalResumeActivityLocked(r);
} else {
// ...
}
// ...
return true;
}
ActivityTaskSupervisor#realStartActivityLocked() 正如函数名一样,真实用来发动 Activity
- 因为行将要告诉 app 端发动 target activity,所以,这个时分 ActivityRecord 就要与进程绑定起来,这便是所谓的 attach ActivityRecord to process。
- 告诉 app 端创立 Activity,并将生命周期履行到 onResumed(),至此,activity 的发动,终于完结。
- 完结最小部分 activity resumed 的作业,首要便是把 ActivityRecord 的状况切换为 RESUMED。剩余的一部分作业将由 app 端告诉服务端 activity resumed 后完结,服务端收到 activity resumed 后,处理了一些杂事,本文不剖析。
stop activity
前面 target activity 现已履行了 onResumed(),那么已暂停的 Activity 什么时分履行 onStoped() 呢?
前面剖析过,一定得等到动画完毕,才干被答应进入 stopping 流程,动画完毕后会调用如下函数
// ActivityTaskSupervisor.java
void scheduleProcessStoppingAndFinishingActivitiesIfNeeded() {
// 能够看到,这儿不仅处理 stopping 流程,还处理 finishing 流程
if (mStoppingActivities.isEmpty() && mFinishingActivities.isEmpty()) {
return;
}
// 1.一切 resumed activity 进入 idle 状况,调度一次 idle 流程,处理 stopping 流程
if (mRootWindowContainer.allResumedActivitiesIdle()) {
scheduleIdle();
return;
}
// 2.activity 真窗制作完结,也能够履行 stopping 流程
if (!mHandler.hasMessages(PROCESS_STOPPING_AND_FINISHING_MSG)
&& mRootWindowContainer.allResumedActivitiesVisible()) {
mHandler.sendEmptyMessage(PROCESS_STOPPING_AND_FINISHING_MSG);
}
}
能够看到,有两种方式进入 stopping 流程
- 一切 resumed activity 上报了 idle 状况,能够处理 stopping 流程。
- Activity 真窗制作完结,也能够进入 stopping 流程。
什么是 idle 状况,大家查询下 IdleHandler 就知道了。
进入 stopping 流程,终究调用人下函数
// ActivityTaskSupervisor.java
void processStoppingAndFinishingActivities(ActivityRecord launchedActivity,
boolean processPausingActivities, String reason) {
boolean displaySwapping = false;
ArrayList<ActivityRecord> readyToStopActivities = null;
for (int i = 0; i < mStoppingActivities.size(); i++) {
final ActivityRecord s = mStoppingActivities.get(i);
// 判别 ActivityRecord 是否处于动画中
// 现在,确实处于动画中
final boolean animating = s.isInTransition()
&& s.getTask() != null && !s.getTask().isForceHidden();
displaySwapping |= s.isDisplaySleepingAndSwapping();
ProtoLog.v(WM_DEBUG_STATES, "Stopping %s: nowVisible=%b animating=%b "
+ "finishing=%s", s, s.nowVisible, animating, s.finishing);
// 假如 ActivityRecord 处于动画中,那就保存到 readyToStopActivities
if ((!animating && !displaySwapping) || mService.mShuttingDown) {
if (!processPausingActivities && s.isState(PAUSING)) {
// Defer processing pausing activities in this iteration and reschedule
// a delayed idle to reprocess it again
removeIdleTimeoutForActivity(launchedActivity);
scheduleIdleTimeout(launchedActivity);
continue;
}
ProtoLog.v(WM_DEBUG_STATES, "Ready to stop: %s", s);
if (readyToStopActivities == null) {
readyToStopActivities = new ArrayList<>();
}
readyToStopActivities.add(s);
mStoppingActivities.remove(i);
i--;
}
}
// ...
final int numReadyStops = readyToStopActivities == null ? 0 : readyToStopActivities.size();
for (int i = 0; i < numReadyStops; i++) {
final ActivityRecord r = readyToStopActivities.get(i);
if (r.isInHistory()) {
if (r.finishing) {
// ...
} else {
// 告诉 app 端去 stop
r.stopIfPossible();
}
}
}
// ...
}
现在,动画现已完毕了,已暂停的 ActivityRecord 正式进入 stop 流程,如下
// ActivityRecord.java
void stopIfPossible() {
if (DEBUG_SWITCH) Slog.d(TAG_SWITCH, "Stopping: " + this);
final Task rootTask = getRootTask();
if (isNoHistory()) {
if (!finishing) {
if (!rootTask.shouldSleepActivities()) {
ProtoLog.d(WM_DEBUG_STATES, "no-history finish of %s", this);
// 留意,nohistory 的 Activity,直接进入 finish 流程
if (finishIfPossible("stop-no-history", false /* oomAdj */)
!= FINISH_RESULT_CANCELLED) {
resumeKeyDispatchingLocked();
return;
}
} else {
ProtoLog.d(WM_DEBUG_STATES, "Not finishing noHistory %s on stop "
+ "because we're just sleeping", this);
}
}
}
if (!attachedToProcess()) {
return;
}
resumeKeyDispatchingLocked();
try {
ProtoLog.v(WM_DEBUG_STATES, "Moving to STOPPING: %s (stop requested)", this);
// 1.状况切换到 STOPPING
setState(STOPPING, "stopIfPossible");
if (DEBUG_VISIBILITY) {
Slog.v(TAG_VISIBILITY, "Stopping:" + this);
}
EventLogTags.writeWmStopActivity(
mUserId, System.identityHashCode(this), shortComponentName);
//2. 告诉 app 端去 stop activity
mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), token,
StopActivityItem.obtain(configChangeFlags));
mAtmService.mH.postDelayed(mStopTimeoutRunnable, STOP_TIMEOUT);
} catch (Exception e) {
// ...
}
}
能够看到,stop 流程中,服务端告诉 app 端去 stop activity,终究生命周期走到 onStopped()。
完毕
限于篇幅的原因,本身省掉了许多细节,想深入研究的读者,能够在本文的根底上持续研究。
虽然省掉了许多细节,可是 Activity 发动的生命周期流程,仍然是是非杂乱的。犹如练天地大移动一般,每练深一层,需求更高的内功。
可能,你现在的根底不行牢固,可是没有关系,Activity 生命周期方面,我现已带你入门了。你能够点赞收藏加关注之后,渐渐打好根底,再基于本文,进行融会贯通。