Framework学习系列第一篇|基于Android 13分析几个特殊场景下的Activity启动流程

450 阅读3分钟

背景

在唤端过程中有个有趣的现象。 同一个 activity Task

Activity A打开B接着打开C

  1. 打开B间隔一段时间打开C,按顺序正常走B和C的onCreate 和onResume
  2. 打开B和C的时间很接近 只会走C的 onCreate 和onResume, 按返回键走到B的onCreate和onResume
  3. 1的状态下在后台去打开B和C B和C均不走生命周期方法 ,回到前台走到C的onCreate 和onResume,按返回键走到B的onCreate和onResume
  4. 2的状态下 代码内finish A,然后在后台5s内去打开B和C ,C会被直接调起走C的 onCreate 和onResume。

分析

基于Android 13.0.0-r11源码调试分析

场景1

走正常的acitivity 启动流程 按顺序启动B和 启动C

未命名文件 (3).jpg

场景2

相对于场景1 两个activity启动时间接近。 启动第二个activity C时 C加入了Task 但是没通过allPausedActivitiesComplete 所以没有走后续相关流程,resumeTopActivity时获取到Top的activity是C 所以走了C的生命周期 B就没有走了 等点击返回键时resumeTopActivity获取到了B又走了一遍B的生命周期。

image.png

final boolean allPausedComplete = mRootWindowContainer.allPausedActivitiesComplete();

if (!allPausedComplete) {

ProtoLog.v(WM_DEBUG_STATES,

"resumeTopActivity: Skip resume: some activity pausing.");

return false;

}

场景3

应用在后台调用startActivity时 并不会去创建对应Activity, 在system_server进程会有是否允许后台进程启动activity的判断 shouldAbortBackgroundActivityStart ****如果不允许,把Activity加入相应task后 就不去走相应Acitivity的流程了,在这个例子中按顺序把B和C加入Task, 点击app icon后,home进程调用startActivity A resumeTopActivity后发现C在最上层就会先去走C的创建和生命周期流程,点击返回键后发现B在最上层就去走B的创建和生命周期流程

未命名文件 (3).png

场景4

有几个关键字段

lastActivityLaunchTime:A Activity的Launch时间

lastActivityFinishTime: A Activity的finish时间

lastStopAppSwitchesTime:这个字段是全局的 任意 app 按home键都会更新这个时间

条件1:当前时间不超过lastActivityLaunchTime或者不超过lastActivityFinishTime时间的10s

条件2: lastActivityLaunchTime或lastActivityFinishTime之后没有更改lastStopAppSwitchesTime

满足上面两个条件 activity能够正常起来。

if (appSwitchState == APP_SWITCH_ALLOW) {
    // Allow if any activity in the caller has either started or finished very recently, and
    // it must be started or finished after last stop app switches time.
    final long now = SystemClock.uptimeMillis();
    if (now - lastActivityLaunchTime < ACTIVITY_BG_START_GRACE_PERIOD_MS
            || now - lastActivityFinishTime < ACTIVITY_BG_START_GRACE_PERIOD_MS) {
        // If activity is started and finished before stop app switch time, we should not
        // let app to be able to start background activity even it's in grace period.
        if (lastActivityLaunchTime > lastStopAppSwitchesTime
                || lastActivityFinishTime > lastStopAppSwitchesTime) {
            if (DEBUG_ACTIVITY_STARTS) {
                Slog.d(TAG, "[Process(" + pid
                        + ")] Activity start allowed: within "
                        + ACTIVITY_BG_START_GRACE_PERIOD_MS + "ms grace period");
            }
            return true;
        }
        if (DEBUG_ACTIVITY_STARTS) {
            Slog.d(TAG, "[Process(" + pid + ")] Activity start within "
                    + ACTIVITY_BG_START_GRACE_PERIOD_MS
                    + "ms grace period but also within stop app switch window");
        }

    }
}

堆栈记录

System_server进程 startActivity调用堆栈

        at com.android.server.wm.TaskFragment.schedulePauseActivity(TaskFragment.java:1665)
        at com.android.server.wm.TaskFragment.startPausing(TaskFragment.java:1608)
        at com.android.server.wm.TaskFragment.resumeTopActivity(TaskFragment.java:1198)
        at com.android.server.wm.Task.resumeTopActivityInnerLocked(Task.java:5003)
        at com.android.server.wm.Task.resumeTopActivityUncheckedLocked(Task.java:4938)
        at com.android.server.wm.RootWindowContainer.resumeFocusedTasksTopActivities(RootWindowContainer.java:2260)
        at com.android.server.wm.ActivityStarter.startActivityInner(ActivityStarter.java:1935)
        at com.android.server.wm.ActivityStarter.startActivityUnchecked(ActivityStarter.java:1661)
        at com.android.server.wm.ActivityStarter.executeRequest(ActivityStarter.java:1216)
        at com.android.server.wm.ActivityStarter.execute(ActivityStarter.java:702)
        at com.android.server.wm.ActivityTaskManagerService.startActivityAsUser(ActivityTaskManagerService.java:1260)
        at com.android.server.wm.ActivityTaskManagerService.startActivityAsUser(ActivityTaskManagerService.java:1223)
        at com.android.server.wm.ActivityTaskManagerService.startActivity(ActivityTaskManagerService.java:1198)
        at android.app.IActivityTaskManager$Stub.onTransact(IActivityTaskManager.java:893)
        at com.android.server.wm.ActivityTaskManagerService.onTransact(ActivityTaskManagerService.java:5222)
        at android.os.Binder.execTransactInternal(Binder.java:1280)
        at android.os.Binder.execTransact(Binder.java:1244)

System_server进程 com.android.server.wm.Task addChild调用堆栈

        at com.android.server.wm.WindowContainer.addChild(WindowContainer.java:742)
        at com.android.server.wm.TaskFragment.addChild(TaskFragment.java:1835)
        at com.android.server.wm.Task.addChild(Task.java:1429)
        at com.android.server.wm.ActivityStarter.addOrReparentStartingActivity(ActivityStarter.java:2927)
        at com.android.server.wm.ActivityStarter.startActivityInner(ActivityStarter.java:1866)
        at com.android.server.wm.ActivityStarter.startActivityUnchecked(ActivityStarter.java:1661)
        at com.android.server.wm.ActivityStarter.executeRequest(ActivityStarter.java:1216)
        at com.android.server.wm.ActivityStarter.execute(ActivityStarter.java:702)
        at com.android.server.wm.ActivityTaskManagerService.startActivityAsUser(ActivityTaskManagerService.java:1260)
        at com.android.server.wm.ActivityTaskManagerService.startActivityAsUser(ActivityTaskManagerService.java:1223)
        at com.android.server.wm.ActivityTaskManagerService.startActivity(ActivityTaskManagerService.java:1198)
        at android.app.IActivityTaskManager$Stub.onTransact(IActivityTaskManager.java:893)
        at com.android.server.wm.ActivityTaskManagerService.onTransact(ActivityTaskManagerService.java:5222)
        at android.os.Binder.execTransactInternal(Binder.java:1280)
        at android.os.Binder.execTransact(Binder.java:1244)

System_server进程 activityPaused调用堆栈

        at com.android.server.wm.ActivityTaskSupervisor.realStartActivityLocked(ActivityTaskSupervisor.java:924)
        at com.android.server.wm.ActivityTaskSupervisor.startSpecificActivity(ActivityTaskSupervisor.java:1042)
        at com.android.server.wm.TaskFragment.resumeTopActivity(TaskFragment.java:1483)
        at com.android.server.wm.Task.resumeTopActivityInnerLocked(Task.java:5003)
        at com.android.server.wm.Task.resumeTopActivityUncheckedLocked(Task.java:4938)
        at com.android.server.wm.RootWindowContainer.resumeFocusedTasksTopActivities(RootWindowContainer.java:2260)
        at com.android.server.wm.RootWindowContainer.resumeFocusedTasksTopActivities(RootWindowContainer.java:2246)
        at com.android.server.wm.TaskFragment.completePause(TaskFragment.java:1735)
        at com.android.server.wm.ActivityRecord.activityPaused(ActivityRecord.java:5992)
        at com.android.server.wm.ActivityClientController.activityPaused(ActivityClientController.java:178)
        at android.app.IActivityClientController$Stub.onTransact(IActivityClientController.java:574)
        at com.android.server.wm.ActivityClientController.onTransact(ActivityClientController.java:124)
        at android.os.Binder.execTransactInternal(Binder.java:1280)
        at android.os.Binder.execTransact(Binder.java:1244)

总结

事实上调用startActivity后,还是需要很多个步骤才能去完成activity的创建以及生命周期流程的走完,平常开发时也需要注意一些细节,比如连续调用两个activity 可能是后面的activity更早创建,如果有些逻辑依赖了前一个activity就可能出现问题。