启动阶段分析

我们把Activity启动分为4个阶段,

阶段1:用户点击应用图标,由Launcher传入参数,ATMS构建ActivityRecord和Task

阶段2:Pause掉Launcher的Activty

阶段3:Zygote进程创建目标进程,触发ActivityThread的运行

阶段4:ActivityThread主线程绑定AMS,目标Activity的初始化和显示到前台

上面四个阶段还可以细分到不同的进程:Launcher,system_server,zygote,目标进程

总流程图

flowchart TD A[Launcher进程: startActivity] --> B[AMS进程: 处理启动请求] B --> C[创建ActivityRecord和Task] C --> D[挂载到窗口层级树] D --> E{启动流程分两路并行} E --> F[阶段二: 暂停Launcher] E --> G[阶段三: 创建应用进程] subgraph F [阶段二: Launcher暂停流程] F1[AMS通知Launcher暂停] --> F2[Launcher执行onPause] F2 --> F3[completePause完成] F3 --> F4[调用startSpecificActivity] end subgraph G [阶段三: 应用进程创建] G1[通过Zygote创建进程] --> G2[应用进程初始化] G2 --> G3[attachApplication绑定AMS] G3 --> G4[调用startSpecificActivity] end F4 --> H[进入startSpecificActivity] G4 --> H H --> I{进程是否存在?} I -->|否| J[触发进程创建<br>可能重复触发] I -->|是| K[调用realStartActivityLocked] J --> L[等待进程创建] L --> H K --> M{检查是否已暂停?} M -->|是| N[阶段四: 真正启动Activity] M -->|否| O[return等待暂停完成] O --> P[等待completePause] P --> H subgraph N [阶段四: realStartActivityLocked执行] N0[ActivityThread] --> N1 N1[创建TargetActivity实例] --> N2[执行onCreate] N2 --> N3[执行onStart] N3 --> N4[执行onResume] N4 --> N5[Activity完全显示] end %% 样式定义 classDef launcher fill:#e1f5fe,stroke:#01579b classDef ams fill:#fce4ec,stroke:#c2185b classDef target fill:#e8f5e8,stroke:#2e7d32 classDef decision fill:#fff3e0,stroke:#ef6c00 classDef parallel fill:#fff8e1,stroke:#ffa000 classDef keyFunction fill:#ffebee,stroke:#d32f2f,stroke-width:3px class A,F1,F2,F3 launcher class B,C,D,G1,G3 ams class N0,N1,N2,N3,N4,N5 target class I,M decision class E,F,G parallel class F4,G4,H,K keyFunction

Luancher启动app入口

Launcher点击app图标后触发点击事件,设置启动目标Activity参数,最后调用Activity的startActivityForResult函数进入Instrumentation

Intrumentation

Intrumentation 对象用来监控应用程序和系统之间的交互操作。由于启动 Activity 是应用程序与系统之间的交互操作,因此调用 Intrumentation 的成员函数 execStartActivity 来代替执行启动 Activity 的操作,以便可以监控这个交互过程

Instrumentation获取系统服务ATMS的startActivity进入system_server进程调用

 public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
        IApplicationThread whoThread = (IApplicationThread) contextThread;
        ...
        try {
            intent.migrateExtraStreamToClipData(who);
            intent.prepareToLeaveProcess(who);
            // ATMS启动Activity
            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);
            checkStartActivityResult(result, intent);
        } catch (RemoteException e) {
            throw new RuntimeException("Failure from system", e);
        }
        return null;
    }

时序图

sequenceDiagram participant ItemClickHandler participant QuickstepLauncher participant BaseQuickstepLauncher participant Activity participant Instrumentation participant AMS as ActivityTaskManagerService Note over ItemClickHandler,AMS: 应用启动流程 - 点击处理阶段 ItemClickHandler->>ItemClickHandler: onClick() ItemClickHandler->>ItemClickHandler: onClickAppShortcut() ItemClickHandler->>QuickstepLauncher: startAppShortcutOrInfoActivity() Note over QuickstepLauncher,AMS: Launcher内部处理阶段 QuickstepLauncher->>QuickstepLauncher: startActivitySafely() QuickstepLauncher->>BaseQuickstepLauncher: getActivityLaunchOptions() BaseQuickstepLauncher-->>QuickstepLauncher: 返回Options参数 Note over Activity,AMS: Activity标准启动流程 QuickstepLauncher->>Activity: startActivity() Activity->>Activity: startActivityForResult() Activity->>Instrumentation: execStartActivity() Instrumentation->>AMS: startActivity() Note over AMS: 进入系统服务处理流程

Launcher的作用

总结一下,Launcher 阶段就干了一件事:准备下一阶段 Activity 启动的参数

SystemServer处理

SystemServer 端主要要完成以下一些工作:

  1. 解析与处理请求参数,要启动那个 Activity,怎么启动(flags 等参数),是谁启动等等一些信息

  2. 修改窗口容器树,创建新的 ActivityRecord 与 Task 并挂载到窗口容器树中

  3. pause 源 Activity

  4. 启动新进程,触发 Application Activity 的初始化和启动生命周期回调

ATMS创建ActivityStarter

ATMS收到请求后,通过ActivityController创建ActivityStarter对象,创建ActivityStarter类时调用了很多set函数,这些参数都会保存到Request类里边,Request 中保存了启动 Activity 需要的所有数据,这些数据主要来自 startActivity 的传入参数

base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java

 
    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) {
        ...
        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();

    }

内部的request对象调用

base/services/core/java/com/android/server/wm/ActivityStarter.java

    ActivityStarter setRequestCode(int requestCode) {
        mRequest.requestCode = requestCode;
        return this;
    }

ActivityStarter-Factory-Request类图

ActivityStarter主要是由Factory创建,相关的类图如下:

classDiagram class ActivityTaskManagerService { -ActivityStartController mActivityStartController +initialize(IntentFirewall, PendingIntentController, Looper) +getActivityStartController() ActivityStartController +startActivityAsUser(...) int } class ActivityStartController { -ActivityTaskManagerService mService -ActivityStackSupervisor mSupervisor -Factory mFactory -StartHandler mHandler -PendingRemoteAnimationRegistry mPendingRemoteAnimationRegistry +ActivityStartController(ActivityTaskManagerService) +ActivityStartController(ActivityTaskManagerService, ActivityStackSupervisor, Factory) +obtainStarter(Intent, String) ActivityStarter } class ActivityStarter { -Request mRequest +setCaller(IApplicationThread) ActivityStarter +setCallingPackage(String) ActivityStarter +setResolvedType(String) ActivityStarter +setResultTo(IBinder) ActivityStarter +setResultWho(String) ActivityStarter +setRequestCode(int) ActivityStarter +setStartFlags(int) ActivityStarter +setProfilerInfo(ProfilerInfo) ActivityStarter +setActivityOptions(Bundle) ActivityStarter +setUserId(int) ActivityStarter +execute() int +executeRequest() int +startActivityUnchecked() int } class Request { -IApplicationThread caller -Intent intent -String resolvedType -IBinder resultTo -String resultWho -int requestCode -int startFlags -String callingPackage -ProfilerInfo profilerInfo -Bundle activityOptions -int userId -String reason # ...其他字段 +resolveActivity() void } class Factory { <<interface>> +obtain() ActivityStarter +recycle(ActivityStarter) void +setController(ActivityStartController) void } class DefaultFactory { -ActivityStartController mController -ActivityTaskManagerService mService -ActivityStackSupervisor mSupervisor -ActivityStartInterceptor mInterceptor -Pool&lt;ActivityStarter&gt; mStarterPool +obtain() ActivityStarter +recycle(ActivityStarter) void +setController(ActivityStartController) void } %% 关联关系 ActivityTaskManagerService "1" --> "1" ActivityStartController : contains ActivityStartController "1" --> "1" Factory : uses ActivityStartController "1" --> "n" ActivityStarter : creates via factory ActivityStarter "1" --> "1" Request : contains DefaultFactory ..|> Factory : implements ActivityStartController --> DefaultFactory : initializes with %% 依赖关系 ActivityStarter --> ActivityStartController : depends on DefaultFactory --> ActivityStarter : creates instances

ActivityRecord创建

ActivityRecord是Activity在服务端AMS中的描述,保存了所有的activity信息,包括启动模式flag,包名,进程

Activity信息的提取

在execute()函数中关注两点resolveActivity和接下来的executeRequest

    int execute() {
            ...
            if (mRequest.activityInfo == null) {
                mRequest.resolveActivity(mSupervisor);
            }
            int res;
            synchronized (mService.mGlobalLock) {
                ...
                res = executeRequest(mRequest);
    }

resolveActivity通过PMS获取目标Activity信息,这些信息是在应用安装时由PMS解析而来,从AndroidManifest.xml提取Activity信息

void resolveActivity(ActivityTaskSupervisor supervisor) {
            ...
            resolveInfo = supervisor.resolveIntent(intent, resolvedType, userId,
                    0 /* matchFlags */,
                    computeResolveFilterUid(callingUid, realCallingUid, filterCallingUid));
            ...
            // Collect information about the target of the Intent.
            activityInfo = supervisor.resolveActivity(intent, resolveInfo, startFlags,
                    profilerInfo);
}

其中supervisor的resolveActivity总的来说就是

  • 从 ResolveInfo 中获取到 ActivityInfo,这些信息包括 launchMode,configChanges,screenOrientation

  • 利用 ActivityInfo 中的信息构建一个 ComponentName 对象,然后设置给 Intent。

  • 返回 ActivityInfo

executeRequest

函数很长,主要功能包含

  • 准备一大堆参数,这些参数大多来自最开始的 startActivity 方法参数

  • 各类权限检测

  • 启动过程拦截器 mInterceptor 处理

  • 构建待启动的目标 Activity 对应的 ActivityRecord 对象

  • 接着调用 startActivityUnchecked 方法

    private int executeRequest(Request request) {
        ...
        if (err == ActivityManager.START_SUCCESS) {
            Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
                    + "} from uid " + callingUid);
        }
        ...
        final ActivityRecord r = new ActivityRecord.Builder(mService)
                .setCaller(callerApp)
                .setLaunchedFromPid(callingPid)
                .setLaunchedFromUid(callingUid)
                .setLaunchedFromPackage(callingPackage)
                .setLaunchedFromFeature(callingFeatureId)
                .setIntent(intent)
                .setResolvedType(resolvedType)
                .setActivityInfo(aInfo)
                .setConfiguration(mService.getGlobalConfiguration())
                .setResultTo(resultRecord)
                .setResultWho(resultWho)
                .setRequestCode(requestCode)
                .setComponentSpecified(request.componentSpecified)
                .setRootVoiceInteraction(voiceSession != null)
                .setActivityOptions(checkedOptions)
                .setSourceRecord(sourceRecord)
                .build();

        mLastStartActivityRecord = r;

        ...

        mLastStartActivityResult = startActivityUnchecked(r, sourceRecord, voiceSession,
                request.voiceInteractor, startFlags, true /* doResume */, checkedOptions,
                inTask, inTaskFragment, restrictedBgActivity, intentGrants);

        if (request.outActivity != null) {
            request.outActivity[0] = mLastStartActivityRecord;
        }

        return mLastStartActivityResult;
}

函数首先有一条日志,这就是我们查看Activity启动日志我们经常会看到的log

ActivityRecord构造方法

ActivityRecord的初始化是由ActivityRecord.Builder完成的,在其构造函数中我们需要关注token

base/services/core/java/com/android/server/wm/ActivityRecord.java

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(), TYPE_APPLICATION, true,
            null /* displayContent */, false /* ownerCanManageAppTokens */);

    mAtmService = _service;
    ((Token) token).mActivityRef = new WeakReference<>(this);
  ...
}

Token

token是一个Binder对象,在super调用的时候创建,其持有ActivityRecord本身的引用

身份标识:每个 Activity 启动时, 都会为其创建一个 ActivityRecord 实体,并生成一个唯一的 IBinder 对象作为其 Token。Activity启动后会持有这个Token的binder代理对象

其中的super函数如下

base/services/core/java/com/android/server/wm/WindowToken.java

    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;
        // dc 始终为null,跳过
        if (dc != null) {
            dc.addWindowToken(token, this);
        }
    }

从上边看到,这里的token是不会调用addWindowToken添加到窗口层级中去的

从ATMS收到启动消息到创建ActivityRecord的时序图

sequenceDiagram participant AMS as ActivityTaskManagerService participant Controller as ActivityStartController participant Starter as ActivityStarter participant Request as ActivityStarter.Request Note over AMS,Starter: Activity启动系统服务流程 AMS->>AMS: startActivity() AMS->>AMS: startActivityAsUser() AMS->>AMS: startActivityAsUser() AMS->>Controller: obtainStarter() Controller-->>AMS: 返回ActivityStarter实例 AMS->>Starter: execute() Note over Starter,Request: Activity解析与准备阶段 Starter->>Request: resolveActivity() Request-->>Starter: 解析完成的Activity信息 Note over Starter: 执行启动请求 Starter->>Starter: executeRequest() Note over Starter: 核心启动逻辑 Starter->>Starter: startActivityUnchecked() Note over Starter: 后续流程: 检查权限、进程、任务栈等

Task的创建

Task创建时序

sequenceDiagram participant AS as ActivityStarter participant RWC as RootWindowContainer participant TDA as TaskDisplayArea participant TB as Task.Builder participant T as Task Note over AS,T: Task获取/创建完整流程 Note over AS: 初始化好ActivityRecord AS-->>AS:startActivityUnChecked AS-->>AS:startActivityInner AS->>AS: getOrCreateRootTask<br>(r, launchFlags, task, aOptions) Note over AS: 参数准备:<br>onTop=true<br>sourceTask=Launcher Task AS->>RWC: getOrCreateRootTask<br>(r, aOptions, task, sourceTask,<br> onTop, mLaunchParams, launchFlags) RWC->>RWC: getOrCreateRootTask<br>(r, options, candidateTask,<br> sourceTask, onTop, launchParams, launchFlags) Note over RWC: 解析activityType RWC->>RWC: resolveActivityType<br>(r, options, candidateTask) RWC->>RWC: canLaunchOnDisplay<br>(r, displayId) RWC->>TDA: getOrCreateRootTask<br>(r, options, candidateTask, sourceTask, <br>launchParams, launchFlags,<br> activityType, onTop) TDA->>TDA: getOrCreateRootTask<br>(windowingMode, activityType,<br> onTop, candidateTask, sourceTask,<br> options, launchFlags) Note over TDA: 检查是否复用现有Task<br>新启动应用→需要新建Task TDA->>TB: new Task.Builder(mAtmService) Note over TB: Builder模式配置参数 TB->>TB: setWindowingMode<br>(windowingMode) TB->>TB: setActivityType(activityType) TB->>TB: setOnTop(true) TB->>TB: setParent(TaskDisplayArea) TB->>TB: setSourceTask(sourceTask) TB->>TB: setActivityOptions(options) TB->>TB: setLaunchFlags(launchFlags) TB->>T: build() T->>T: buildInner() Note over T: 创建Task实例<br>new Task(...) T->>T: setActivityType(mActivityType) alt mParent instanceof TaskDisplayArea T->>TDA: addChild(task, POSITION_TOP) Note over TDA: Task挂载到DefaultTaskDisplayArea顶部 else mParent instanceof Task T->>T: parentTask.addChild<br>(task, POSITION_TOP) end T->>T: setWindowingMode<br>(mWindowingMode, true) T-->>TB: 返回Task实例 TB-->>TDA: 返回新建Task TDA-->>RWC: 返回Task RWC-->>AS: 返回Task Note over AS: Task创建完成<br>mTargetRootTask = 新建的Task

尝试创建Task

在ActivityStarter中创建好ActivityRecord之后,在startActivityUnchecked函数中调用startActivityInner

在startActivityInner中调用getOrCreateRootTask试图创建rootTask

为什么要尝试?因为可能复用

    int startActivityInner(final ActivityRecord r, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            int startFlags, boolean doResume, ActivityOptions options, Task inTask,
            TaskFragment inTaskFragment, boolean restrictedBgActivity,
            NeededUriGrants intentGrants) {
        ...
        if (mTargetRootTask == null) {
            mTargetRootTask = getOrCreateRootTask(mStartActivity, mLaunchFlags, targetTask,
                    mOptions);
        }
        if (newTask) {
            final Task taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
                    ? mSourceRecord.getTask() : null;
            // 将ActivityRecord和Task绑定
            setNewTask(taskToAffiliate);
        } else if (mAddingToTask) {
            addOrReparentStartingActivity(targetTask, "adding to task");
        }
  ...
}

最终进入TaskDisplayArea的getOrCreateRootTask函数创建Task

base/services/core/java/com/android/server/wm/TaskDisplayArea.java

Task getOrCreateRootTask(int windowingMode, int activityType, boolean onTop,
        @Nullable Task candidateTask, @Nullable Task sourceTask,
        @Nullable ActivityOptions options, int launchFlags) {
        ...
        if(...)
            return candidateTask.getRootTask();
        }
        ...
        return new Task.Builder(mAtmService)
                .setWindowingMode(windowingMode)
                .setActivityType(activityType)
                .setOnTop(onTop)
                .setParent(this)
                .setSourceTask(sourceTask)
                .setActivityOptions(options)
                .setLaunchFlags(launchFlags)
                .build();
    }

Task复用条件判断

如果需要创建一个Task则走最后的new 实例化,在此之前会判断是否需要复用Task, 根据启动模式,比如在应用内以复用栈的模式启动另一个Activity就会走上边的candidateTask.getRootTask()

ActivityRecord挂载时序图

先看看整个挂载的时序图,在ActivityStarter中此流程是紧接着Task创建完成之后开始的

sequenceDiagram participant AS as ActivityStarter participant T as Task participant AR as ActivityRecord participant TDA as TaskDisplayArea participant ATS as ActivityTaskSupervisor Note over AS,AR: ActivityRecord挂载到Task流程 AS->>AS: setNewTask<br>(taskToAffiliate) Note left of AS: toTop=true<br>taskToAffiliate=null AS->>T: reuseOrCreateTask<br>(info, intent, toTop, <br>startActivity, options) Note over T: 返回Task实例(同mTargetRootTask) T-->>AS: 返回Task AS->>AS: addOrReparentStartingActivity<br>(task, "setTaskFromReuseOrCreateNewTask") AS->>T: addChild<br>(mStartActivity, POSITION_TOP) Note over T: 将ActivityRecord添加到Task顶部 T->>AR: 建立父子关系 Note over AR: ActivityRecord现在属于Task AS->>AS: ProtoLog日志记录 Note over AS: Starting new activity in new task Note over AS,T: 移动Task到容器顶部 AS->>T: moveToFront<br>("reuseOrNewTask", targetTask) Note over T: targetTask=null → task=this T->>T: moveToFrontInner() T->>TDA: getDisplayArea() TDA-->>T: 返回TaskDisplayArea T->>TDA: positionChildAt(POSITION_TOP, task, true) Note over TDA: 将Task移动到DefaultTaskDisplayArea顶部 TDA->>TDA: positionChildTaskAt<br>(POSITION_TOP, task) TDA->>ATS: updateTopResumed<br>ActivityIfNeeded() ATS->>AR: onTopResumedActivityChanged() Note over AR: 触发<br>TopResumedActivityChangeItem TDA->>TDA: updateLastFocusedRootTask() Note over TDA,AR: 挂载完成:<br>ActivityRecord在Task中<br>Task在DefaultTaskDisplayArea顶部

将ActivityRecord添加到Task

private void setNewTask(Task taskToAffiliate) {
    final boolean toTop = !mLaunchTaskBehind && !mAvoidMoveToFront;
    final Task task = mTargetRootTask.reuseOrCreateTask(
            mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info,
            mNewTaskIntent != null ? mNewTaskIntent : mIntent, mVoiceSession,
            mVoiceInteractor, toTop, mStartActivity, mSourceRecord, mOptions);
    task.mTransitionController.collectExistenceChange(task);
    addOrReparentStartingActivity(task, "setTaskFromReuseOrCreateNewTask");

    ProtoLog.v(WM_DEBUG_TASKS, "Starting new activity %s in new task %s",
            mStartActivity, mStartActivity.getTask());

    if (taskToAffiliate != null) {
        mStartActivity.setTaskToAffiliateWith(taskToAffiliate);
    }
}

这里有条log Starting new activity 分析系统日志经常会看到

重点看下addOrReparentStartingActivity

private void addOrReparentStartingActivity(@NonNull Task task, String reason) {
    TaskFragment newParent = task;
    ...
    if (mStartActivity.getTaskFragment() == null
            || mStartActivity.getTaskFragment() == newParent) {
        newParent.addChild(mStartActivity, POSITION_TOP);
    } else {
        mStartActivity.reparent(newParent, newParent.getChildCount() /* top */, reason);
    }
}

mStartActivity是上面创建的ActivityRecord, 调用 newParent.addChild添加ActivityRecord到Task里边

Move task

将Task移动到容器DefaultTaskDisplayArea顶部,Task就是为目标Activity创建的Task, Task的父容器是DefaultTaskDisplayArea,如果需要深入了解,此处需要理解WMS/AMS的窗口层级结构

//base/services/core/java/com/android/server/wm/ActivityStarter.java
//startActivityInner
if (!mAvoidMoveToFront && mDoResume) {
    //targetTask 为null
    mTargetRootTask.getRootTask().moveToFront("reuseOrNewTask", targetTask);
}

//base/services/core/java/com/android/server/wm/Task.java
//实现函数
    void moveToFrontInner(String reason, Task task) {
        if (!isAttached()) {
            return;
        }

        final TaskDisplayArea taskDisplayArea = getDisplayArea();

        if (!isActivityTypeHome() && returnsToHomeRootTask()) {
            // Make sure the root home task is behind this root task since that is where we
            // should return to when this root task is no longer visible.
            taskDisplayArea.moveHomeRootTaskToFront(reason + " returnToHome");
        }

        final Task lastFocusedTask = isRootTask() ? taskDisplayArea.getFocusedRootTask() : null;
        //true
        if (task == null) {
            task = this;
        }
        task.getParent().positionChildAt(POSITION_TOP, task, true /* includingParents */);
        taskDisplayArea.updateLastFocusedRootTask(lastFocusedTask, reason);
    }

上面的getParent 就是 DefaultTaskDisplayArea ,将当前的 Task 移动到 DefaultTaskDisplayArea 的最前面

命令行查看窗口挂载层级

adb shell dumpsys window displays

  Task display areas in top down Z order:
    TaskDisplayArea DefaultTaskDisplayArea
      overrideConfig={0.0 ?mcc0mnc ?localeList ?layoutDir ?swdp ?wdp ?hdp ?density ?lsize ?long ?ldr ?wideColorGamut ?orien ?uimode ?night ?touch ?keyb/?/? ?nav/? winConfig={ mBounds=Rect(0, 0 - 0, 0) mAppBounds=null mMaxBounds=Rect(0, 0 - 0, 0) mDisplayRotation=undefined mWindowingMode=fullscreen mActivityType=undefined mAlwaysOnTop=undefined mRotation=undefined} ?fontWeightAdjustment}
      mPreferredTopFocusableRootTask=Task{c83b3a2 #32 type=standard A=10211:com.example.androiddemo}
      mLastFocusedRootTask=Task{c83b3a2 #32 type=standard A=10211:com.example.androiddemo}
      Application tokens in top down Z order:
//Begin 新增的Demo Activity
      * Task{c83b3a2 #32 type=standard A=10211:com.example.androiddemo U=0 visible=true visibleRequested=true mode=fullscreen translucent=false sz=1}
        bounds=[0,0][1080,2400]
        * ActivityRecord{241515373 u0 com.example.androiddemo/.MainActivity t32}
//End
      * Task{47cfc2e #1 type=home U=0 visible=false visibleRequested=false mode=fullscreen translucent=true sz=1}
        bounds=[0,0][1080,2400]
        * Task{bef315c #5 type=home I=com.google.android.apps.nexuslauncher/.NexusLauncherActivity U=0 rootTaskId=1 visible=false visibleRequested=false mode=fullscreen translucent=true sz=2}
          bounds=[0,0][1080,2400]
          * ActivityRecord{72491568 u0 com.google.android.apps.nexuslauncher/.NexusLauncherActivity t5}
          * TaskFragment{afb81ba mode=multi-window organizerUid=10176 organizerProc=com.google.android.apps.nexuslauncher}
            bounds=[0,0][1080,2400]
      * Task{2a2e03b #2 type=undefined U=0 visible=false visibleRequested=false mode=fullscreen translucent=true sz=2}
        bounds=[0,0][1080,2400]
        * Task{ee38cb1 #4 type=undefined U=0 rootTaskId=2 visible=false visibleRequested=false mode=multi-window translucent=true sz=0}
          bounds=[0,2400][1080,3600]
        * Task{3ce20e9 #3 type=undefined U=0 rootTaskId=2 visible=false visibleRequested=false mode=multi-window translucent=true sz=0}
          bounds=[0,0][1080,2400]

显示Activity

当Task创建完成,并且处理好窗口层级之后,就要开始准备显示Activity了

resume时序图

sequenceDiagram participant RWC as RootWindowContainer participant T as Task participant TF as TaskFragment participant TDA as TaskDisplayArea participant ATMS as ActivityTaskManagerService participant CLM as ClientLifecycleManager Note over RWC,CLM: Activity Resume流程 - 暂停当前Activity并创建新进程 RWC->>T: resumeFocused<br>TasksTopActivities() Note left of RWC: target=目标Activity<br>deferPause=false T->>T: resumeTopActivity<br>UncheckedLocked() T->>T: resumeTopActivity<br>InnerLocked() T->>TF: resumeTopActivity<br>(prev, options, <br>deferPause) TF->>TF: topRunningActivity<br>(true) Note over TF: 获取目标ActivityRecord TF->>TDA: pauseBackTasks<br>(next) Note over TDA: 暂停Launcher Activity TDA->>TDA: forAllLeafTasks() TDA->>TF: forAllLeafTaskFragments() TF->>TF: startPausing<br>(false, resuming,<br> "pauseBackTasks") Note over TF: 暂停Launcher ActivityRecord TF->>TF: schedulePauseActivity<br>(prev, userLeaving, pauseImmediately,<br> autoEnteringPip, reason) TF->>CLM: scheduleTransaction<br>(prev.app.getThread(), prev.token, PauseActivityItem.obtain()) Note over CLM: 构建PauseActivityItem<br>发送到Launcher进程 %% TF-->>TDA: 返回true <br>(有Activity正在pausing) TDA-->>TF: 返回pausing状态 TF->>ATMS: startProcessAsync<br>(next, false, isTop, <br>HOSTING_TYPE_NEXT_TOP_ACTIVITY) Note over ATMS: 异步创建目标进程 TF-->>T: 返回true T-->>RWC: 返回true Note over ATMS,CLM: 后续流程:<br>1. Launcher执行onPause<br>2. 目标进程创建完成后继续启动

resume入口

startActivityInner调用mRootWindowContainer.resumeFocusedTasksTopActivities进入resume流程,这里的resume不是Activity的Resume生命周期,而是启动Activity,这里的执行时机是发生在system_server进程,而onResume生命周期这个流程是在应用进程里边。

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,
        TaskFragment inTaskFragment, boolean restrictedBgActivity,
        NeededUriGrants intentGrants) {

// 调整Task层级
if (!mAvoidMoveToFront && mDoResume) {
    //targetTask 为null
    mTargetRootTask.getRootTask().moveToFront("reuseOrNewTask", targetTask);
}
        ...
        if (mDoResume) {
                //启动Activity
                mRootWindowContainer.resumeFocusedTasksTopActivities(
                        mTargetRootTask, mStartActivity, mOptions, mTransientLaunch);
        }
}

RootWindowContainer调用链

从resumeFocusedTasksTopActivities开始的关键调用函数如下

RootWindowContainer::resumeFocusedTasksTopActivities
    Task::resumeTopActivityUncheckedLocked
        Task::resumeTopActivityInnerLocked
            TaskFragment::resumeTopActivity 
                TaskDisplayArea::pauseBackTasks  --   pause LauncherActivity 
                    WindowContainer::forAllLeafTask
                        TaskFragment::forAllLeafTaskFragments
                            TaskFragment::startPausing
                                TaskFragment::startPausing
                                    TaskFragment::schedulePauseActivity --构建 PauseActivityItem,触发onPause生命周期
                ActivityTaskManagerService::startProcessAsync     -- 创建进程

从上面的时序图走进TaskFragment中,首先发起对上一个Activity的pause流程

base/services/core/java/com/android/server/wm/TaskFragment.java

    final boolean resumeTopActivity(ActivityRecord prev, ActivityOptions options,
            boolean deferPause) {
        ...
        //暂停Launcher的Activity
        boolean pausing = !deferPause && taskDisplayArea.pauseBackTasks(next);
        if (pausing) {
                ...
                //启动新进程
                mAtmService.startProcessAsync(next, false /* knownToBeDead */, isTop,
                        isTop ? HostingRecord.HOSTING_TYPE_NEXT_TOP_ACTIVITY
                                : HostingRecord.HOSTING_TYPE_NEXT_ACTIVITY);
            }
            return true
        }
}

这里有两个重点:

  1. 暂停上一个Activity

  2. 启动新进程

到这里,我们的启动流程就因为上面两个点而无法启动,等上面两个流程走完后再次尝试启动。

小结

代码走到这里,已经创建了 TargetActivity 所在的 Task 和对应的 ActivityRecord ,并也挂载到 DefaultTaskDisplayArea 下了,而且还将Task移到了顶部,所以得到上面主要的一个关系。 但是这个时候用户还是只能看到 Launcher 的 Activity 。这是因为 TargetActivity 都还没启动,甚至连它的进程都没创建。

要让 TargetActivity 启动起来,所以触发了 RootWindowContainer#resumeFocusedTasksTopActivities 方法,但是在执行到 TaskFragment#resumeTopActivity 方法的时候发现想显示 TargetActivity 的条件2个都没满足,所以就需要触发 Launcher 的pause 和 TargetActivity 所在进程的创建

主要的工作如下:

  1. 在 Launcher 进程构建了启动参数放在了 ActivityOption 中,然后通过 Bundle 传递给 system_server 端

  1. ATMS 先解析参数,放在了 Request 这个类中保存

  1. ATMS 构建出一个 ActivityRecord ,这个类在 system_server 端就代表着 Activity ,同时也是一个窗口容器

  1. 再构建出一个 Task 挂载到窗口树上

  1. 将 ActivityRecord 挂载到 Task 中,这样 ActivityRecord 也就挂载到窗口层级树中了

  1. 触发 Launcher 执行 pause 逻辑

  1. 触发 TargetActivity 所在的进程创建

不管是pause Launcher的Activity还是创建进程,都要转移到其他进程,所以接下来进入到阶段二和阶段三,两个并行的任务执行

pause Activity

跨进程调用到app进程执行onPause

进入第二阶段,首先看看pause activity的触发流程

在RootWindowContainer::resumeFocusedTasksTopActivities函数的调用链中

                TaskDisplayArea::pauseBackTasks  --   pause LauncherActivity 
                    WindowContainer::forAllLeafTask
                        TaskFragment::forAllLeafTaskFragments
                            TaskFragment::startPausing
                                TaskFragment::startPausing
                                    TaskFragment::schedulePauseActivity --构建 PauseActivityItem,触发onPause生命周期

我们留意最后一行schedulePauseActivity,函数实现如下

void schedulePauseActivity(ActivityRecord prev, boolean userLeaving,
        boolean pauseImmediately, String reason) {
    ProtoLog.v(WM_DEBUG_STATES, "Enqueueing pending pause: %s", prev);
  ...
        mAtmService.getLifecycleManager().scheduleTransaction(prev.app.getThread(),
                prev.token, PauseActivityItem.obtain(prev.finishing, userLeaving,
                        prev.configChangeFlags, pauseImmediately));
  ...
}

scheduleTransaction函数的主要作用是发起一个Transaction,注意传入的参数是PauseActivityItem对象, 所以接下来会走到PauseActivityItem的execute函数,当走到execute时就已经完成跨进程调用了,接下来都是在Launcher进程执行了

public class PauseActivityItem extends ActivityLifecycleItem {

    ...
    @Override
    public void execute(ClientTransactionHandler client, ActivityClientRecord r,
            PendingTransactionActions pendingActions) {
        Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
        // ActivityThread实现
        client.handlePauseActivity(r, mFinished, mUserLeaving, mConfigChanges, pendingActions,
                "PAUSE_ACTIVITY_ITEM");
        Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
    }

    @Override
    public void postExecute(ClientTransactionHandler client, IBinder token,
            PendingTransactionActions pendingActions) {
        if (mDontReport) {
            return;
        }
        ActivityClient.getInstance().activityPaused(token);
    }
}

client对象的实现类是ActivityThread,其重写了handlePauseActivity函数

Transaction详细流程参考 Android Activity Transaction

onPause结束

当onPause流程走完之后,回到PauseActivityItem :: postExecute函数,会通知ATMS pause结束,然后尝试显示新Activity

    public void activityPaused(IBinder token) {
        try {
            getActivityClientController().activityPaused(token);
        } catch (RemoteException e) {
            e.rethrowFromSystemServer();
        }
    }

ActivityClientController调用链[2]如下

ActivityClientController::activityPaused
    ActivityRecord::activityPaused
        TaskFragment::completePause
            RootWindowContainer::resumeFocusedTasksTopActivities       -- 显示顶层Activity
                RootWindowContainer::resumeFocusedTasksTopActivities
                    Task::resumeTopActivityUncheckedLocked
                        Task::resumeTopActivityInnerLocked
                            TaskFragment::resumeTopActivity
                                ActivityTaskSupervisor::startSpecificActivity        -- 试图启动 Activity

completePause

上一个activity pause之后,再次尝试显示Activity,TaskFragment::completePause 有两个重要的调用函数:前面出现过的resumeFocusedTasksTopActivities和ensureActivitiesVisible

void completePause(boolean resumeNext, ActivityRecord resuming) {
        ...
        if (resumeNext) {
                // 尝试启动ACtivity
                mRootWindowContainer.resumeFocusedTasksTopActivities(topRootTask, prev,
                        null /* targetOptions */);
        }
        // 确保activity可见
        mRootWindowContainer.ensureActivitiesVisible(resuming, 0, !PRESERVE_WINDOWS);
}

在complete函数中调用了 resumeFocusedTasksTopActivities, 上边 显示Activity-resume入口小节中提到,在startActivityInner函数把Task层级调整到最顶层之后,准备显示activity就调用了这个函数,同一个调用链,直到resumeTopActivity,再看看resumeTopActivity的实现逻辑

final boolean resumeTopActivity(ActivityRecord prev, ActivityOptions options,
        boolean deferPause) {

        // 此时activity已经puase completed了,所以这里不会被拦截
        // 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;
        }
        // 这里同上,尝试pause上一个activity,但是我们已经pause completed了,所以为false
        boolean pausing = !deferPause && taskDisplayArea.pauseBackTasks(next);
       
        if (pausing) {
            // 启动进程,resume的时候走过一次,这里不会走了
            ...
        }

        // 进程还没启动
        if (next.attachedToProcess()) {

        } else {
            // 启动Activity
            ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivity: Restarting %s", next);
            mTaskSupervisor.startSpecificActivity(next, true, true);
        }

        return true;
}

尝试启动activity

函数很简单,两个功能,要么启动activity,要么启动进程

base/services/core/java/com/android/server/wm/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 {
                // 启动activity
                realStartActivityLocked(r, wpc, andResume, checkConfig);
                return;
            }
        }
        // 进程未启动则启动进程
        final boolean isTop = andResume && r.isTopRunningActivity();
        mService.startProcessAsync(r, knownToBeDead, isTop,
                isTop ? HostingRecord.HOSTING_TYPE_TOP_ACTIVITY
                        : HostingRecord.HOSTING_TYPE_ACTIVITY);
    }

进程启动判断条件

这里首先判断了进程是否启动,如果进程启动非常快,此时就会直接调用realStartActivityLocked启动Activity

resumeTopActivity里边也有一个判断进程是否启动,但是这里有个不同点

startSpecificActivity:通过mService.getProcessController获取到进程WindowProcessController对象,这个接口可以认为是实时获取

resumeTopActivity:attachedToProcess里边也是用的WindowProcessController对象,代码如下

boolean hasProcess() {
    return app != null;
}

boolean attachedToProcess() {
    return hasProcess() && app.hasThread();
}

这里的app在setProcess函数里边初始化,而setProcess函数又是在realStartActivityLocked里边调用,所以resumeTopActivity如果activity没有启动,那么那里判断进程是否启动是肯定为false,而在ActivityTaskSupervisor::startSpecificActivity是很可能为true的

ensureActivitiesVisible流程

在completePause函数中的第二个关键函数调用 RootWindowContainer::ensureActivitiesVisible

调用链[2]

            RootWindowContainer::ensureActivitiesVisible              -- 确保设备上 Activity 的可见性
                RootWindowContainer::ensureActivitiesVisible
                    DisplayContent::ensureActivitiesVisible 
                        WindowContainer::forAllRootTasks  --忽略固定逻辑
                            Task::ensureActivitiesVisible
                                Task::forAllLeafTasks --忽略固定逻辑
                                    TaskFragment::updateActivityVisibilities
                                        EnsureActivitiesVisibleHelper::process
                                            EnsureActivitiesVisibleHelper::setActivityVisibilityState
                                                EnsureActivitiesVisibleHelper::makeVisibleAndRestartIfNeeded
                                                    ActivityTaskSupervisor::startSpecificActivity       -- 试图启动 Activity

ensureActivitiesVisible 流程。这个流程执行的概率很高,界面有个风吹草动可能影响 Activity 显示的都会执行这个方法,这个方法的目的就是确保当前设备上的 Activity 正确显示。 比如当前这个场景,一个 Activity 完成了 completePause ,那肯定要有新的 Activity 显示,那整个手机系统的 Activity 规则肯定发生了改变,所以需要执行 ensureActivitiesVisible 流程来确保正确的显示。[2]

遍历所有屏幕

base/services/core/java/com/android/server/wm/RootWindowContainer.java

    void ensureActivitiesVisible(ActivityRecord starting, int configChanges,
            boolean preserveWindows, boolean notifyClients) {

        try {
            mTaskSupervisor.beginActivityVisibilityUpdate();
            // First the front root tasks. In case any are not fullscreen and are in front of home.
            // 遍历屏幕
            for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
                final DisplayContent display = getChildAt(displayNdx);
                display.ensureActivitiesVisible(starting, configChanges, preserveWindows,
                        notifyClients);
            }
        } finally {
            mTaskSupervisor.endActivityVisibilityUpdate();
        }
    }

遍历所有的RootTask

base/services/core/java/com/android/server/wm/DisplayContent.java

    void ensureActivitiesVisible(ActivityRecord starting, int configChanges,
            boolean preserveWindows, boolean notifyClients) {
            ...
            forAllRootTasks(rootTask -> {
                rootTask.ensureActivitiesVisible(starting, configChanges, preserveWindows,
                        notifyClients);
            });
            ...
    }

遍历所有子叶

    void ensureActivitiesVisible(@Nullable ActivityRecord starting, int configChanges,
            boolean preserveWindows, boolean notifyClients) {
            ...
            forAllLeafTasks(task -> {
                task.updateActivityVisibilities(starting, configChanges, preserveWindows,
                        notifyClients);
            }, true /* traverseTopToBottom */);
            ...
    }

调用了一个EnsureActivitiesVisibleHelper::process函数来处理可见性

final void updateActivityVisibilities(@Nullable ActivityRecord starting, int configChanges,
        boolean preserveWindows, boolean notifyClients) {
    mTaskSupervisor.beginActivityVisibilityUpdate();
    try {
        mEnsureActivitiesVisibleHelper.process(
                starting, configChanges, preserveWindows, notifyClients);
    } finally {
        mTaskSupervisor.endActivityVisibilityUpdate();
    }
}

EnsureActivitiesVisibleHelper::process

process函数中遍历了所有children,如果child是TaskFragment则会进入递归调用,这里用了asTaskFragmentasActivityRecord是否返回null来对容器WindowContainer做了具体的类型判断

 void process(@Nullable ActivityRecord starting, int configChanges, boolean preserveWindows,
            boolean notifyClients) {
        reset(starting, configChanges, preserveWindows, notifyClients);
        ...
        ArrayList<TaskFragment> adjacentTaskFragments = null;
        for (int i = mTaskFragment.mChildren.size() - 1; i >= 0; --i) {
            final WindowContainer child = mTaskFragment.mChildren.get(i);
            // 类型判断 TaskFragment
            final TaskFragment childTaskFragment = child.asTaskFragment();
            if (childTaskFragment != null
                    && childTaskFragment.getTopNonFinishingActivity() != null) {
                // 这是一个递归调用,马上又会进入process函数
                childTaskFragment.updateActivityVisibilities(starting, configChanges,
                        preserveWindows, notifyClients);
            ...

            } else if (child.asActivityRecord() != null) {
                // 类型为ActivityRecord
                setActivityVisibilityState(child.asActivityRecord(), starting, resumeTopActivity);
            }
        }
    }

处理ActivityRecord可见性

对于ActivityRecord,也就是对应的Activity的可见性,其可见性的具体设置就是由setActivityVisibilityState函数负责

private void setActivityVisibilityState(ActivityRecord r, ActivityRecord starting,
        final boolean resumeTopActivity) {

    final boolean reallyVisible = r.shouldBeVisibleUnchecked();

    if (reallyVisible) {
        // 进程未启动,启动activity
        if (!r.attachedToProcess()) {
            makeVisibleAndRestartIfNeeded(mStarting, mConfigChanges, isTop,
                    resumeTopActivity && isTop, r);
        } else if (r.mVisibleRequested) {

        } else {
            r.makeVisibleIfNeeded(mStarting, mNotifyClients);
        }

    } else {
        // 不可见
        r.makeInvisible();
    }

}

尝试启动Activity

可以看到,可见性控制函数都是实现在ActivityRecord类里边,如果进程未启动,则尝试启动Activity

makeVisibleAndRestartIfNeeded如下:

private void makeVisibleAndRestartIfNeeded(ActivityRecord starting, int configChanges,
        boolean isTop, boolean andResume, ActivityRecord r) {

    ...
    if (!r.mVisibleRequested || r.mLaunchTaskBehind) {
        // 设置为可见
        r.setVisibility(true);
    }
    if (r != starting) {
        mTaskFragment.mTaskSupervisor.startSpecificActivity(r, andResume,
                true /* checkConfig */);
    }

}

启动activity有一个条件 r!=starting, 这个starting是在调用栈最顶部的completePause函数传递进来的是一个null值,所以在当前逻辑下肯定为true.

pause activity整个流程就结束了,后续仍然是判断进程是否启动,然后判断是继续启动activity还是启动进程

触发进程创建

第一阶段末尾,触发了两个平行的进程,首先pause activity, 然后接着启动进程,pause activity已经分析完了,并且我们已经分析到了pause activity完全结束

现在进入第三阶段

这里只分析如何触发进程创建的以及跨进程通信方式,进程的真正创建是在Linux中通过fork出来的

ATMS发送进程启动消息

我看看到多次尝试启动进程的函数如下

base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java

    void startProcessAsync(ActivityRecord activity, boolean knownToBeDead, boolean isTop,
            String hostingType) {

            // Post message to start process to avoid possible deadlock of calling into AMS with the
            // ATMS lock held.
            final Message m = PooledLambda.obtainMessage(ActivityManagerInternal::startProcess,
                    mAmInternal, activity.processName, activity.info.applicationInfo, knownToBeDead,
                    isTop, hostingType, activity.intent.getComponent());
            mH.sendMessage(m);
    }

这里发了一个消息给Handler去执行,真正的执行函数是ActivityManagerInternal::startProcess,后面的参数都是这个函数需要的参数,真正的实现函数是ActivityManagerService$LocalService::startProcess

base/services/core/java/com/android/server/am/ActivityManagerService.java

@Override
public void startProcess(String processName, ApplicationInfo info, boolean knownToBeDead,
        boolean isTop, String hostingType, ComponentName hostingName) {
        ...
        synchronized (ActivityManagerService.this) {
            startProcessLocked(processName, info, knownToBeDead, 0 /* intentFlags */,
                    new HostingRecord(hostingType, hostingName, isTop),
                    ZYGOTE_POLICY_FLAG_LATENCY_SENSITIVE, false /* allowWhileBooting */,
                    false /* isolated */);
        }
        ...
}

    final ProcessRecord startProcessLocked(String processName,
            ApplicationInfo info, boolean knownToBeDead, int intentFlags,
            HostingRecord hostingRecord, int zygotePolicyFlags, boolean allowWhileBooting,
            boolean isolated) {
        return mProcessList.startProcessLocked(processName, info, knownToBeDead, intentFlags,
                hostingRecord, zygotePolicyFlags, allowWhileBooting, isolated, 0 /* isolatedUid */,
                false /* isSdkSandbox */, 0 /* sdkSandboxClientAppUid */,
                null /* sdkSandboxClientAppPackage */,
                null /* ABI override */, null /* entryPoint */,
                null /* entryPointArgs */, null /* crashHandler */);
    }

ProcessList::startProcessLocked

在ProcessList对象中经过5次startProcessLocked函数的重载调用,略过多次重载调用

    boolean startProcessLocked(HostingRecord hostingRecord, String entryPoint, ProcessRecord app,
            int uid, int[] gids, int runtimeFlags, int zygotePolicyFlags, int mountExternal,
            String seInfo, String requiredAbi, String instructionSet, String invokeWith,
            long startUptime, long startElapsedTime) {
        app.setPendingStart(true);
        app.setRemoved(false);
        if (mService.mConstants.FLAG_PROCESS_START_ASYNC) {
            if (DEBUG_PROCESSES) Slog.i(TAG_PROCESSES,
                    "Posting procStart msg for " + app.toShortString());
            mService.mProcStartHandler.post(() -> handleProcessStart(
                    app, entryPoint, gids, runtimeFlags, zygotePolicyFlags, mountExternal,
                    requiredAbi, instructionSet, invokeWith, startSeq));
            return true;
        }
        ...
    }

从源码来看FLAG_PROCESS_START_ASYNC始终为true,接下来通过AMS的handler post了一个runnable对象,真正的实现在函数 handleProcessStart里边

handleProcessStart

private void handleProcessStart(final ProcessRecord app, final String entryPoint,
        final int[] gids, final int runtimeFlags, int zygotePolicyFlags,
        final int mountExternal, final String requiredAbi, final String instructionSet,
        final String invokeWith, final long startSeq) {
    final Runnable startRunnable = () -> {
       
            final Process.ProcessStartResult startResult = startProcess(app.getHostingRecord(),
                    entryPoint, app, app.getStartUid(), gids, runtimeFlags, zygotePolicyFlags,
                    mountExternal, app.getSeInfo(), requiredAbi, instructionSet, invokeWith,
                    app.getStartTime());

            synchronized (mService) {
                handleProcessStartedLocked(app, startResult, startSeq);
            }
    ...
}

在startProcess函数中对要启动的进程做了一个分类,最后都调用了Process::start来启动进程

private Process.ProcessStartResult startProcess(HostingRecord hostingRecord, String entryPoint,
        ProcessRecord app, int uid, int[] gids, int runtimeFlags, int zygotePolicyFlags,
        int mountExternal, String seInfo, String requiredAbi, String instructionSet,
        String invokeWith, long startTime) {
...
            if (hostingRecord.usesWebviewZygote()) {
                startResult = startWebView(entryPoint,
                        app.processName, uid, uid, gids, runtimeFlags, mountExternal,
                        app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                        app.info.dataDir, null, app.info.packageName,
                        app.getDisabledCompatChanges(),
                        new String[]{PROC_START_SEQ_IDENT + app.getStartSeq()});
            } else if (hostingRecord.usesAppZygote()) {
                final AppZygote appZygote = createAppZygoteForProcessIfNeeded(app);

                // We can't isolate app data and storage data as parent zygote already did that.
                startResult = appZygote.getProcess().start(entryPoint,
                        app.processName, uid, uid, gids, runtimeFlags, mountExternal,
                        app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                        app.info.dataDir, null, app.info.packageName,
                        /*zygotePolicyFlags=*/ ZYGOTE_POLICY_FLAG_EMPTY, isTopApp,
                        app.getDisabledCompatChanges(), pkgDataInfoMap, allowlistedAppDataInfoMap,
                        false, false,
                        new String[]{PROC_START_SEQ_IDENT + app.getStartSeq()});
            } else {
                regularZygote = true;
                startResult = Process.start(entryPoint,
                        app.processName, uid, uid, gids, runtimeFlags, mountExternal,
                        app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                        app.info.dataDir, invokeWith, app.info.packageName, zygotePolicyFlags,
                        isTopApp, app.getDisabledCompatChanges(), pkgDataInfoMap,
                        allowlistedAppDataInfoMap, bindMountAppsData, bindMountAppStorageDirs,
                        new String[]{PROC_START_SEQ_IDENT + app.getStartSeq()});
            }
...
}

Process::start

这里只有一个函数调用startViaZygote

public final Process.ProcessStartResult start(@NonNull final String processClass, ...) {

  return startViaZygote(processClass, niceName, uid, gid, gids,
                    runtimeFlags, mountExternal, targetSdkVersion, seInfo,
                    abi, instructionSet, appDataDir, invokeWith, /*startChildZygote=*/ false,
                    packageName, zygotePolicyFlags, isTopApp, disabledCompatChanges,
                    pkgDataInfoMap, allowlistedDataInfoList, bindMountAppsData,
                    bindMountAppStorageDirs, zygoteArgs);

}

Process::startViaZygote

继续看startViaZygote

private Process.ProcessStartResult startViaZygote(@NonNull final String processClass,
                                                  @Nullable final String niceName,
                                                  final int uid, final int gid,
                                                  @Nullable final int[] gids,
                                                  int runtimeFlags, int mountExternal,
                                                  int targetSdkVersion,
                                                  @Nullable String seInfo,
                                                  @NonNull String abi,
                                                  @Nullable String instructionSet,
                                                  @Nullable String appDataDir,
                                                  @Nullable String invokeWith,
                                                  boolean startChildZygote,
                                                  @Nullable String packageName,
                                                  int zygotePolicyFlags,
                                                  boolean isTopApp,
                                                  @Nullable long[] disabledCompatChanges,
                                                  @Nullable Map<String, Pair<String, Long>>
                                                          pkgDataInfoMap,
                                                  @Nullable Map<String, Pair<String, Long>>
                                                          allowlistedDataInfoList,
                                                  boolean bindMountAppsData,
                                                  boolean bindMountAppStorageDirs,
                                                  @Nullable String[] extraArgs)
                                                  throws ZygoteStartFailedEx {
        ArrayList<String> argsForZygote = new ArrayList<>();
        // --runtime-args, --setuid=, --setgid=,
        // and --setgroups= must go first
        argsForZygote.add("--runtime-args");
        argsForZygote.add("--setuid=" + uid);
        argsForZygote.add("--setgid=" + gid);
        argsForZygote.add("--runtime-flags=" + runtimeFlags);
        ...
        // 将所有的参数都添加到argsForZygote 里边
        ...
        argsForZygote.add(processClass);

        if (extraArgs != null) {
            Collections.addAll(argsForZygote, extraArgs);
        }

        synchronized(mLock) {
            // The USAP pool can not be used if the application will not use the systems graphics
            // driver.  If that driver is requested use the Zygote application start path.
            return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi),
                                              zygotePolicyFlags,
                                              argsForZygote);
        }
}

将所有的进程参数都封装到ArrayList,然后通过zygoteSendArgsAndGetResult发送给Zygote进程

Process::startViaZygote
   Process::zygoteSendArgsAndGetResult
      Process::attemptZygoteSendArgsAndGetResult

Socket通信

我们直接关注 attemptZygoteSendArgsAndGetResult函数,这里就是AMS和Zygote进程通信的IPC代码

private Process.ProcessStartResult attemptZygoteSendArgsAndGetResult(
        ZygoteState zygoteState, String msgStr) throws ZygoteStartFailedEx {
    try {
        final BufferedWriter zygoteWriter = zygoteState.mZygoteOutputWriter;
        final DataInputStream zygoteInputStream = zygoteState.mZygoteInputStream;

        zygoteWriter.write(msgStr);
        zygoteWriter.flush();

        // Always read the entire result from the input stream to avoid leaving
        // bytes in the stream for future process starts to accidentally stumble
        // upon.
        Process.ProcessStartResult result = new Process.ProcessStartResult();
        result.pid = zygoteInputStream.readInt();
        result.usingWrapper = zygoteInputStream.readBoolean();

        if (result.pid < 0) {
            throw new ZygoteStartFailedEx("fork() failed");
        }

        return result;
    } catch (IOException ex) {
        zygoteState.close();
        Log.e(LOG_TAG, "IO Exception while communicating with Zygote - "
                + ex.toString());
        throw new ZygoteStartFailedEx(ex);
    }
}

将应用进程的启动参数argsForZygote写入ZygoteState中,这样Zygote进程就会收到一个创建新的应用程序进程的请求

ZygoteState是怎么来的呢,回到上边的startViaZygote函数,最后调用了openZygoteSocketIfNeeded函数

return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi),
                                              zygotePolicyFlags,
                                              argsForZygote);

Socket连接的建立

openZygoteSocketIfNeeded函数创建了socket连接

private ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx {
   
        attemptConnectionToPrimaryZygote();

        if (primaryZygoteState.matches(abi)) {
            return primaryZygoteState;
        }
    ...
}

    private void attemptConnectionToPrimaryZygote() throws IOException {
        if (primaryZygoteState == null || primaryZygoteState.isClosed()) {
            primaryZygoteState =
                    ZygoteState.connect(mZygoteSocketAddress, mUsapPoolSocketAddress);

            maybeSetApiDenylistExemptions(primaryZygoteState, false);
            maybeSetHiddenApiAccessLogSampleRate(primaryZygoteState);
        }
    }

这里的Socket通信最核心的就是我们上边用到的ZygoteState对象

base/core/java/android/os/ZygoteProcess.java

static ZygoteState connect(@NonNull LocalSocketAddress zygoteSocketAddress,
        @Nullable LocalSocketAddress usapSocketAddress)
        throws IOException {

    DataInputStream zygoteInputStream;
    BufferedWriter zygoteOutputWriter;
    final LocalSocket zygoteSessionSocket = new LocalSocket();

    if (zygoteSocketAddress == null) {
        throw new IllegalArgumentException("zygoteSocketAddress can't be null");
    }

    try {
        zygoteSessionSocket.connect(zygoteSocketAddress);
        zygoteInputStream = new DataInputStream(zygoteSessionSocket.getInputStream());
        zygoteOutputWriter =
                new BufferedWriter(
                        new OutputStreamWriter(zygoteSessionSocket.getOutputStream()),
                        Zygote.SOCKET_BUFFER_SIZE);
    } catch (IOException ex) {
        try {
            zygoteSessionSocket.close();
        } catch (IOException ignore) { }

        throw ex;
    }

    return new ZygoteState(zygoteSocketAddress, usapSocketAddress,
                           zygoteSessionSocket, zygoteInputStream, zygoteOutputWriter,
                           getAbiList(zygoteOutputWriter, zygoteInputStream));
}

通过LocalSocket和目的addr发起连接,然后创建了inputStream和outputStream作为输入输出接口

所以我们看到在attemptZygoteSendArgsAndGetResult函数中使用zygoteWriter.write(msgStr);发起了跨进程通信

总结下Process::startViaZygote函数开始的主要流程如下:

  • 将应用进程的启动参数保存到 argsForZygote 集合中

  • 用 openZygoteSocketIfNeeded() 方法用来创建用于通信的 socket

  • 调用 zygoteSendArgsAndGetResult 方法将应用程序进程的启动参数通过 socket 发送到 Zygote 进程

为什么用Socket?

Zyote是单线程模式

进程的创建是通过fork来的,fork的原理就是copy-on-write机制,这种方式可以提高进程启动速度,因为新的进程所需要资源已经在 zygote 进程中加载和初始化一次,进程被创建时会复制 zygote 的共享的资源,避免重复初始化。

fork操作会复制当前进程(包括线程)到子进程,如果Zygote在fork之前使用了Binder进行通信,那么Binder线程也会被复制到子进程中,子进程中Binder线程可能不再需要,可能引发问题(如死锁或资源竞争)。因此,使用Socket可以避免这些潜在问题(如死锁或资源竞争)

Zygote进程的核心任务是通过fork()克隆自身生成新进程,而Binder机制与fork()存在以下不可调和的矛盾[4]

  1. 状态混乱

    • Binder依赖线程池和接口状态,子进程会继承父进程的Binder线程池和未处理的请求队列。

    • 子进程的Binder驱动状态可能因线程ID冲突或资源竞争导致死锁或崩溃。

  2. 资源释放难题

    • Binder对象成对存在(Client端和Server端),子进程无法安全释放父进程的Binder对象。

    • 如果子进程释放了Server端Binder对象,AMS(Activity Manager Service)将失去与Zygote的通信能力。

  3. 初始化时序问题

    • Binder驱动需要依赖ServiceManager进程完成注册,而ServiceManager的初始化晚于Zygote。

    • Zygote无法保证在ServiceManager完全就绪后注册Binder接口,导致通信失败。

总的来说,在Linux中fork 创建的子进程会继承父进程的虚拟地址空间,但只复制调用 fork 的线程,其他线程会在子进程中“消失”。这种行为可能导致锁、文件描述符等资源的状态不一致,从而引发死锁或其他问题。

Zygote创建进程

Zygote进程启动之后,开启了Socket监听,如果收到来自客户端的创建进程请求,则解析参数,启动进程,查找并执行Main函数

main入口

base/core/java/com/android/internal/os/ZygoteInit.java

    public static void main(String[] argv) {
        ZygoteServer zygoteServer = null;
        Runnable caller;
        try {
            ...
            zygoteServer = new ZygoteServer(isPrimaryZygote);
            // 启动system_server进程
            if (startSystemServer) {
                Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);

                // {@code r == null} in the parent (zygote) process, and {@code r != null} in the
                // child (system_server) process.
                if (r != null) {
                    r.run();
                    return;
                }
            }
            // The select loop returns early in the child process after a fork and
            // loops forever in the zygote.
            //启动其他应用进程
            caller = zygoteServer.runSelectLoop(abiList);
        } catch (Throwable ex) {
            Log.e(TAG, "System zygote died with fatal exception", ex);
            throw ex;
        } finally {
            if (zygoteServer != null) {
                zygoteServer.closeServerSocket();
            }
        }

        // We're in the child process and have exited the select loop. Proceed to execute the
        // command.
        if (caller != null) {
            // 执行子进程的Main函数
            caller.run();
        }

预加载系统资源,包含系统常用类、资源、字体等等

开启 socket 服务,启动system_server进程,然后调用 runSelectLoop 方法进入无限循环中等待 socket 消息

Zygote 收到启动新进程的 socket 消息后,fork 新进程并执行新进程的 main 函数

开启Socket监听

ZygoteServer初始化的时候开启LocalSocket监听

ZygoteServer(boolean isPrimaryZygote) {
    mUsapPoolEventFD = Zygote.getUsapPoolEventFD();

    if (isPrimaryZygote) {
        mZygoteSocket = Zygote.createManagedSocketFromInitSocket(Zygote.PRIMARY_SOCKET_NAME);
        ...
    }
    ...
}

createManagedSocketFromInitSocket从环境变量中获取到 zygote socket,最终返回一个LocalServerSocket对象

static LocalServerSocket createManagedSocketFromInitSocket(String socketName) {
    int fileDesc;
    final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;

        String env = System.getenv(fullSocketName);
        fileDesc = Integer.parseInt(env);

        FileDescriptor fd = new FileDescriptor();
        fd.setInt$(fileDesc);
        //把 socket fd 包装成一个 LocalServerSocket
        return new LocalServerSocket(fd);

}

runSelectLoop等待 socket消息

runSelectLoop开启了while(true)的无限循环,用来监听来自system_server的socket连接

    Runnable runSelectLoop(String abiList) {
        ArrayList<FileDescriptor> socketFDs = new ArrayList<>();
        ArrayList<ZygoteConnection> peers = new ArrayList<>();

        socketFDs.add(mZygoteSocket.getFileDescriptor());
        peers.add(null);

        while (true) {
            int[] usapPipeFDs = null;
            StructPollfd[] pollFDs;

            if (mUsapPoolEnabled) {
               ...
            } else {
                pollFDs = new StructPollfd[socketFDs.size()];
            }
            // 将socket fd存入pollFDs数组,当前的逻辑下就只有一个,mZygoteSocket的fd
            int pollIndex = 0;
            for (FileDescriptor socketFD : socketFDs) {
                pollFDs[pollIndex] = new StructPollfd();
                pollFDs[pollIndex].fd = socketFD;
                // 监听可读事件
                pollFDs[pollIndex].events = (short) POLLIN;
                ++pollIndex;
            }
            ...
            try {
                // poll机制,进入休眠并监听
                pollReturnValue = Os.poll(pollFDs, pollTimeoutMs);
            } catch (ErrnoException ex) {
                throw new RuntimeException("poll failed", ex);
            }
            ...
    }

上面将mZygoteSocket的fd保存到了StructPollfd数组中,system_server创建跨进程时会socket连接到这个fd, Zygote通过poll进入休眠,当有socket连接消息时,就会唤醒进程

Socket唤醒进程

    Runnable runSelectLoop(String abiList) {
        ...
        while (true) {
            ...
            try {
                // socket唤醒
                pollReturnValue = Os.poll(pollFDs, pollTimeoutMs);
            } catch (ErrnoException ex) {
                throw new RuntimeException("poll failed", ex);
            }

           if (pollReturnValue == 0) {
               ...
            } else {
                while (--pollIndex >= 0) {
                    // 只接受POLLIN事件
                    if ((pollFDs[pollIndex].revents & POLLIN) == 0) {
                        continue;
                    }

                    if (pollIndex == 0) {
                        // Zygote server socket
                        // 构建一个与客户端通信的 ZygoteConnection 类型的辅助对象
                        ZygoteConnection newPeer = acceptCommandPeer(abiList);
                        peers.add(newPeer);
                        //加入列表,监听来自客户端的消息
                        socketFDs.add(newPeer.getFileDescriptor());
                    } else if (pollIndex < usapPoolEventFDIndex) {
                        // Session socket accepted from the Zygote server socket

                        try {
                            ZygoteConnection connection = peers.get(pollIndex);
                            boolean multipleForksOK = !isUsapPoolEnabled()
                                    && ZygoteHooks.isIndefiniteThreadSuspensionSafe();
                            final Runnable command =
                                    connection.processCommand(this, multipleForksOK);
                            // 子进程
                            if (mIsForkChild) {
                                // We're in the child. We should always have a command to run at
                                // this stage if processCommand hasn't called "exec".

                                return command;
                            } else {
                                // 父进程/Zygote进程
                                // We're in the server - we should never have any commands to run.
                                if (command != null) {
                                    throw new IllegalStateException("command != null");
                                }

                                // We don't know whether the remote side of the socket was closed or
                                // not until we attempt to read from it from processCommand. This
                                // shows up as a regular POLLIN event in our regular processing
                                // loop.
                                if (connection.isClosedByPeer()) {
                                    connection.closeSocket();
                                    peers.remove(pollIndex);
                                    socketFDs.remove(pollIndex);
                                }
                            }
                        } catch (Exception e) {
                        }
                        ...

Os.poll(pollFDs, pollTimeoutMs)是一种IO多路复用技术,socket收到消息唤醒进程

接下来有一个循环 while (--pollIndex >= 0) , 上面遍历了socketFDs并且将元素添加到pollFDs数组,socketFDs只添加了只有一个mZygoteSocket的fd,所以这里的pollIndex 为1,因此if (pollIndex == 0)条件成立。

此时表示system_server和Zygote进程建立了socket连接,创建一个ZygoteConnection对象保存到peer,将fd添加到socketFDs,进入下一次while(true)循环触发休眠。

接下来如果socketFDs中的连接有消息发过来,那么将会唤醒,此时pollIndex ==2,从peer中获取一个connection对象,调用connection.processCommand(this, multipleForksOK)创建子进程

  • connection.processCommand子进程一旦创建成功,接下来的代码就分别运行在不同的进程中了,这和Linux fork一个进程之后的逻辑是一样的,在子进程中mIsForkChild变量被置为true,将返回 command,结束while循环,在外面执行子进程的main函数

  • 对于Zygote进程,将继续执行后面的代码,关闭connection的socket连接,将其从peer列表中移除,删除对应的fd,然后继续陷入死循环,进入休眠,直到下一个socket连接进来唤醒进程

创建子进程

核心函数processCommand

Runnable processCommand(ZygoteServer zygoteServer, boolean multipleOK) {
    ZygoteArguments parsedArgs;

        try (ZygoteCommandBuffer argBuffer = new ZygoteCommandBuffer(mSocket)) {
            while (true) {
                try {
                    // 解析来自Socket的参数
                    parsedArgs = ZygoteArguments.getInstance(argBuffer);
                    // Keep argBuffer around, since we need it to fork.
                } catch (IOException ex) {
                    throw new IllegalStateException("IOException on command socket", ex);
                }
                int pid;

                if (parsedArgs.mInvokeWith != null || parsedArgs.mStartChildZygote
                        || !multipleOK || peer.getUid() != Process.SYSTEM_UID) {
                    // Continue using old code for now. TODO: Handle these cases in the other path.
                    // 创建子进程
                    // forkAndSpecialize 是对 fork 系统调用的包装
                    pid = Zygote.forkAndSpecialize(parsedArgs.mUid, parsedArgs.mGid,
                            parsedArgs.mGids, parsedArgs.mRuntimeFlags, rlimits,
                            parsedArgs.mMountExternal, parsedArgs.mSeInfo, parsedArgs.mNiceName,
                            fdsToClose, fdsToIgnore, parsedArgs.mStartChildZygote,
                            parsedArgs.mInstructionSet, parsedArgs.mAppDataDir,
                            parsedArgs.mIsTopApp, parsedArgs.mPkgDataInfoList,
                            parsedArgs.mAllowlistedDataInfoList, parsedArgs.mBindMountAppDataDirs,
                            parsedArgs.mBindMountAppStorageDirs);

                    try {
                        //成功创建出子进程
                        if (pid == 0) {
                            // in child
                            zygoteServer.setForkChild();

                            zygoteServer.closeServerSocket();
                            IoUtils.closeQuietly(serverPipeFd);
                            serverPipeFd = null;

                            return handleChildProc(parsedArgs, childPipeFd,
                                    parsedArgs.mStartChildZygote);
                        } else {
                            // In the parent. A pid < 0 indicates a failure and will be handled in
                            // handleParentProc.
                            IoUtils.closeQuietly(childPipeFd);
                            childPipeFd = null;
                            handleParentProc(pid, serverPipeFd);
                            return null;
                        }
                    } finally {
                        IoUtils.closeQuietly(childPipeFd);
                        IoUtils.closeQuietly(serverPipeFd);
                    }
                }
  • 生成ZygoteArguments对象,这个对象创建的时候就开始解析参数,都是以--开头的参数,这些参数正是Process::start函数中传递进来的

private ZygoteArguments(ZygoteCommandBuffer args, int argCount)
        throws IllegalArgumentException, EOFException {
    parseArgs(args, argCount);
}
    private void parseArgs(ZygoteCommandBuffer args, int argCount)
            throws IllegalArgumentException, EOFException {
        for ( /* curArg */ ; curArg < argCount; ++curArg) {
            String arg = args.nextArg();

            if (arg.equals("--")) {
                curArg++;
                break;
            } else if (arg.startsWith("--setuid=")) {
                if (mUidSpecified) {
                    throw new IllegalArgumentException(
                        "Duplicate arg specified");
                }
                mUidSpecified = true;
                mUid = Integer.parseInt(getAssignmentValue(arg));
            }
           ...
  • 调用forkAndSpecialize创建子进程

  • 从参数的mRemainingArgs字段中查找Main函数并且封装为Runnable返回

fork vs java标准API

在Android 中创建子线程是通过jni调用Linux的fork函数,所以进程创建之后共享父进程的所有资源,代码接着fork之后开始执行

在纯Java中,创建子进程要通过 ProcessBuilderRuntime.exec(),没有fork函数,java会“从头启动”新程序:启动一个全新的、独立的进程,并且效率低于fork,每个新进程都是一个完全独立的内存空间,不共享初始化状态

查找Main函数

private Runnable handleChildProc(ZygoteArguments parsedArgs,
        FileDescriptor pipeFd, boolean isZygote) {


        //关闭监听用的 socket 和从 Zygote 中继承的文件描述符
        closeSocket();

        Zygote.setAppProcessName(parsedArgs, TAG);

        // End of the postFork event.
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        if (parsedArgs.mInvokeWith != null) {
           ...
        } else {
            if (!isZygote) {
                return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,
                        parsedArgs.mDisabledCompatChanges,
                        parsedArgs.mRemainingArgs, null /* classLoader */);
            } else {
                return ZygoteInit.childZygoteInit(
                        parsedArgs.mRemainingArgs  /* classLoader */);
            }
        }
    }

  • 关闭socket

  • 设置进程名称

  • 接着调用ZygoteInit::zygoteInit函数

base/core/java/com/android/internal/os/RuntimeInit.java

public static Runnable zygoteInit(int targetSdkVersion, long[] disabledCompatChanges,
        String[] argv, ClassLoader classLoader) {
   
    RuntimeInit.commonInit();
    ZygoteInit.nativeZygoteInit();
    return RuntimeInit.applicationInit(targetSdkVersion, disabledCompatChanges, argv,
            classLoader);
}


    protected static Runnable applicationInit(int targetSdkVersion, long[] disabledCompatChanges,
            String[] argv, ClassLoader classLoader) {

        VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
        VMRuntime.getRuntime().setDisabledCompatChanges(disabledCompatChanges);

        final Arguments args = new Arguments(argv);

        // The end of of the RuntimeInit event (see #zygoteInit).
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);

        // Remaining arguments are passed to the start class's static main
        return findStaticMain(args.startClass, args.startArgs, classLoader);
    }

查找启动类

new Arguments(argv) 通过parseArgs查找启动类,查找的是argv中第一个非--开头的参数,我们探究一下这个class是什么

start class的来源

再来看看启动进程的函数ProcessList::startProcessLocked

boolean startProcessLocked(ProcessRecord app, HostingRecord hostingRecord,
        int zygotePolicyFlags, boolean disableHiddenApiChecks, boolean disableTestApiChecks,
        String abiOverride) {
    if (app.isPendingStart()) {
        return true;
    }
        try {
            ...
            final String entryPoint = "android.app.ActivityThread";

            return startProcessLocked(hostingRecord, entryPoint, app, uid, gids,
                    runtimeFlags, zygotePolicyFlags, mountExternal, seInfo, requiredAbi,
                    instructionSet, invokeWith, startUptime, startElapsedTime);

        } catch (RuntimeException e) {
        }
}

这里定义了一个entryPoint变量,这个变量就是我们的startClass, entryPoint会作为参数传递到ZygoteProcess::startViaZygote,变量名称变为processClass

private Process.ProcessStartResult startViaZygote(@NonNull final String processClass,
                                                  @Nullable final String niceName,
                                                  final int uid, final int gid, ...) {

        ArrayList<String> argsForZygote = new ArrayList<>();

        // --runtime-args, --setuid=, --setgid=,
        // and --setgroups= must go first
        argsForZygote.add("--runtime-args");
        argsForZygote.add("--setuid=" + uid);
        argsForZygote.add("--setgid=" + gid);
        argsForZygote.add("--runtime-flags=" + runtimeFlags);
        // 添加及其他参数,均以--开头
        ....
        // 添加启动类
        argsForZygote.add(processClass);
        // 添加启动类main函数的参数
        if (extraArgs != null) {
            Collections.addAll(argsForZygote, extraArgs);
        }

        synchronized(mLock) {
            // 发起socket连接
            return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi),
                                              zygotePolicyFlags,
                                              argsForZygote);
        }
}

argsForZygote会将所有--开头的参数添加完之后再添加 processClass, 从上层函数传递的值可以看到启动类就是ActivityThread,所以Zygote进程在查找启动类就是从第一个非--参数读出来的,后续的参数作为main函数的参数

封装Runnable

protected static Runnable findStaticMain(String className, String[] argv,
        ClassLoader classLoader) {
    ...
    Class<?> cl;
        cl = Class.forName(className, true, classLoader);
    Method m;
        m = cl.getMethod("main", new Class[] { String[].class });
    int modifiers = m.getModifiers();
    if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
        throw new RuntimeException(
                "Main method is not public and static on " + className);
    }

    return new MethodAndArgsCaller(m, argv);
}

findStaticMain中通过反射查找到public static main()函数,然后封装到MethodAndArgsCaller,这是一个Runnable的实现类

小结

在MainActivity的onCreate函数中打印调用栈如下:

Demo-zygote-stack: java.lang.Throwable: DEBUG
D Demo-zygote-stack:     at com.mercedes.wellbeing.ui.MainActivity.onCreate(MainActivity.kt:126)
D Demo-zygote-stack:     at android.app.Activity.performCreate(Activity.java:8350)
D Demo-zygote-stack:     at android.app.Activity.performCreate(Activity.java:8329)
D Demo-zygote-stack:     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1417)
D Demo-zygote-stack:     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3625)
D Demo-zygote-stack:     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3781)
D Demo-zygote-stack:     at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:101)
D Demo-zygote-stack:     at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:138)
D Demo-zygote-stack:     at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
D Demo-zygote-stack:     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2306)
D Demo-zygote-stack:     at android.os.Handler.dispatchMessage(Handler.java:106)
D Demo-zygote-stack:     at android.os.Looper.loopOnce(Looper.java:201)
D Demo-zygote-stack:     at android.os.Looper.loop(Looper.java:288)
D Demo-zygote-stack:     at android.app.ActivityThread.main(ActivityThread.java:7924)
D Demo-zygote-stack:     at java.lang.reflect.Method.invoke(Native Method)
D Demo-zygote-stack:     at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
D Demo-zygote-stack:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:946)

可以看到,与上面的进程启动分析一致,ZygoteInit::main为Android进程的顶级入口,通过Caller的反射调用进入启动类ActivityThread::main, 所有app的调用栈顶级函数都是固定的这几个函数调用。

自此,子进程创建完毕,找到启动类,并且封装好了Runnable,子进程中断了继承自Zygote进程的while无限循环,回到main函数调用

base/core/java/com/android/internal/os/ZygoteInit.java

    public static void main(String[] argv) {

        ...
        caller = zygoteServer.runSelectLoop(abiList);

        if (caller != null) {
            caller.run();
        }
    }

接下来就执行到了ActivityThread::main函数里边了,Android 应用进程启动了

ActivityThread应用进程启动

现在进入到了第四阶段

我们把ActivityThread::main函数当作真正的应用进程启动入口,或者理解为主线程入口函数,接下来我们继续分析进程启动之后发生了什么

main入口

base/core/java/android/app/ActivityThread.java

public static void main(String[] args) {
    //Trace点 
    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");

    Environment.initForCurrentUser();
    // 创建主线程的looper
    Looper.prepareMainLooper();

    // Find the value for {@link #PROC_START_SEQ_IDENT} if provided on the command line.
    // It will be in the format "seq=114"
    long startSeq = 0;

    ActivityThread thread = new ActivityThread();
    // 绑定AMS
    thread.attach(false, startSeq);

    if (sMainThreadHandler == null) {
        sMainThreadHandler = thread.getHandler();
    }

    // End of event ActivityThreadMain.
    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    // 开启Handler的消息循环
    Looper.loop();

    throw new RuntimeException("Main thread loop unexpectedly exited");
}
  • 创建主线程的Looper, 这个Looper存到ThreadLocal中,主线程在任何时候都能通过Looper::getMainLooper获取到主线程的Looper, 常常在主线程中创建Handler的时候用到

  • 创建ActivityThread对象,并且通过attach将ApplicationThread binder绑定到AMS, 该binder作为AMS和应用进程通信的核心接口

  • 主线程进入无限循环模式,之后的事都交给内部类H:Handler来处理

向AMS注册ActivityThread

ActivityThread和AMS之间的通信主要是ApplicationThread这个binder对象,首先从ServiceManager获取AMS的binder:IActivityManager , IActivityManager 实现类是AMS

private void attach(boolean system, long startSeq) {
    sCurrentActivityThread = this;
    mConfigurationController = new ConfigurationController(this);
    mSystemThread = system;
    if (!system) {

        RuntimeInit.setApplicationObject(mAppThread.asBinder());
        final IActivityManager mgr = ActivityManager.getService();
        try {
            mgr.attachApplication(mAppThread, startSeq);
        } catch (RemoteException ex) {
            throw ex.rethrowFromSystemServer();
        }
    ...

ActivityManagerService类定义如下

base/services/core/java/com/android/server/am/ActivityManagerService.java

public class ActivityManagerService extends IActivityManager.Stub
        implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback, ActivityManagerGlobalLock {
...
}

AMS attachApplication绑定进程信息

函数AMS::attachApplication简单调用attachApplicationLocked

    private boolean attachApplicationLocked(@NonNull IApplicationThread thread,
            int pid, int callingUid, long startSeq) {
        // app进程
        ProcessRecord app;
        long startTime = SystemClock.uptimeMillis();
        long bindApplicationTimeMillis;
        if (pid != MY_PID && pid >= 0) {
            synchronized (mPidsSelfLocked) {
                app = mPidsSelfLocked.get(pid);
            }
            ...
        } else {
            app = null;
        }

        //没有进程直接结束
        if (app == null) {
            ...
            return false;
        }
        // system_server已经准备就绪,或者app允许在BOOT_COMPLETED之前启动
        boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);

        try {
            ...
            if (app.getIsolatedEntryPoint() != null) {
                ...
            } else if (instr2 != null) {
                thread.bindApplication(processName, ...);
            } else {
                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());
            }
            ...
        }

        // See if the top visible activity is waiting to run in this process...
        // 大多情况下为true
        if (normalMode) {
            try {
                // ATMS
                didSomething = mAtmInternal.attachApplication(app.getWindowProcessController());
            } catch (Exception e) {
                Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
                badApp = true;
            }
        }


ProcessRecord的来源

  • 首先获取ProcessRecord, 这个ProcessRecord在ProcessList::startProcessLocked的时候创建,当Zygote创建好进程之后,回到ProcessList::handleProcessStartedLocked函数,通过ActivityManagerService::addPidLocked保存下来

base/services/core/java/com/android/server/am/ProcessList.java

boolean handleProcessStartedLocked(ProcessRecord app, int pid, boolean usingWrapper,
        long expectedStartSeq, boolean procAttached) {
        ...
        // 
        mService.reportUidInfoMessageLocked(TAG, buf.toString(), app.getStartUid());
        mService.addPidLocked(app);
        ...
        return true
}
  • 调用ActivityThread::bindApplication, 将AppicationInfo等信息回传给ActivityThread进程

  • 调用ATMS的attachApplication,这一步就会再次去启动Activity

AMS向ActivityThread注册应用信息

ActivityManagerService::attachApplicationLocked中,马上会调用 thread.bindApplication(processName, appInfo,...),向ActivityThread注册一些App相关的信息,比如appInfo,processName这些都是在ProcessList启动进程的时候创建的

thread.bindApplication是一次binder跨进程,在ActivityThread中有一个H类,会发送一个消息:BIND_APPLICATION,在主线程中处理

// class H extends Handler
public void handleMessage(Message msg) {
    if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
    switch (msg.what) {
        case BIND_APPLICATION:
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
            AppBindData data = (AppBindData)msg.obj;
            handleBindApplication(data);
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
            break;
    ...
}

ATMS 启动Activity

ATMS在AMS中的对象是 mAtmInternal,作为一个系统service获取方式如下

mAtmInternal = LocalServices.getService(ActivityTaskManagerInternal.class);

系统Service都通过LocalServices注册,AMS服务本身也是在初始化的时候注册进去的

ATMS的attachApplication();调用栈如下,直接进入process函数,当调用进入RootWindowContainer之后,处理的就是跟窗口相关的功能了

//ATMS调用链
ActivityTaskManagerService::attachApplication
   RootWindowContainer::attachApplication
      AttachApplicationHelper::process

// WindowContainer$AttachApplicationHelper 
        boolean process(WindowProcessController app) throws RemoteException {
            mApp = app;
            for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
                //遍历所有容器
                getChildAt(displayNdx).forAllRootTasks(this);
                if (mRemoteException != null) {
                    throw mRemoteException;
                }
            }
            if (!mHasActivityStarted) {
                ensureActivitiesVisible(null /* starting */, 0 /* configChanges */,
                        false /* preserveWindows */);
            }
            return mHasActivityStarted;
        }

AttachApplicationHelper 实现了Consumer函数接口,所以forAllRootTasks(this)this表示传入的是一个函数接口Consumer

forAllRootTasks的子类实现在Task,调用的是accept函数

base/services/core/java/com/android/server/wm/Task.java

    void forAllRootTasks(Consumer<Task> callback, boolean traverseTopToBottom) {
        if (isRootTask()) {
            callback.accept(this);
        }
    }

重点关注AttachApplicationHelper::acceptAttachApplicationHelper::test函数

// called by Task
public void accept(Task rootTask) {
    // 跳过不可见的Task
    if (rootTask.getVisibility(null /* starting */)
            == TASK_FRAGMENT_VISIBILITY_INVISIBLE) {
        return;
    }
    mTop = rootTask.topRunningActivity();
    // 遍历Task下的ActivityRecord,并执行test函数
    rootTask.forAllActivities(this);
}

// called by ActivityRecord
@Override
public boolean test(ActivityRecord r) {
    try {
        if (mTaskSupervisor.realStartActivityLocked(r, mApp,
                mTop == r && r.getTask().canBeResumed(r) /* andResume */,
                true /* checkConfig */)) {
            mHasActivityStarted = true;
        }
    } catch (RemoteException e) {
        Slog.w(TAG, "Exception in new application when starting activity " + mTop, e);
        mRemoteException = e;
        return true;
    }
    return false;
}

accept函数遍历了Task下的所有Activity并对其执行forAllActivities函数,forAllActivities实现类是ActivityRecord,这个函数饶了一圈会执行到test函数

test函数的终极功能就是调用realStartActivityLocked启动Activity, 如果启动成功赋值 mHasActivityStarted = true

回到process函数,当遍历完所有Task之后,如果没有activity启动:if (!mHasActivityStarted),触发函数ensureActivitiesVisible,这个函数之前已经分析过,处理所有Activity的可见性

创建Activity

上面分析了启动Activity之前的流程,概括下

  1. 准备Activity启动参数,生成ActivityRecord对象,并且挂载到Task的顶层,然后调用一个很重要的函数resumeFocusedTasksTopActivities来执行下面两步

  2. 让上一个Activity暂停掉,也就是进入Pause状态,应用端暂停之后触发pauseComplete回调,此时如果进程还没有启动,则尝试创建进程

  3. 和第二步并行执行,启动目标应用进程,在ProcessList里边准备进程启动参数,然后在Zygote进程中fork一个子进程,执行ActivityThread::main函数,通过ActivityManagerService::attachApplication函数和AMS/ATMS绑定,ATMS启动Activity

  4. 接着到了Activity创建流程

ATMS发起启动Transaction

在分析ATMS时,曾多次试图启动Activity,调用的是ActivityTaskSupervisor::startSpecificActivity,首先判断进程是否启动,如果进程已经启动,则调用ActivityTaskSupervisor::realStartActivityLocked来启动Activity, 当进程启动之后在RootWindowContainer::test函数中调用realStartActivityLocked函数来启动Activity.

来看看核心的 realStartActivityLocked

base/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java


    boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc,
            boolean andResume, boolean checkConfig) throws RemoteException {
        // 如果还有正在paused的activity没有完成,不会启动Activity
        if (!mRootWindowContainer.allPausedActivitiesComplete()) {
            return false;
        }

        final Task task = r.getTask();
        final Task rootTask = task.getRootTask();

        try {
            // ActivityRecord已连接到相应的进程
            r.setProcess(proc);

            final IActivityClientController activityClientController =
                    proc.hasEverLaunchedActivity() ? null : mService.mActivityClientController;
            r.launchCount++;
            r.lastLaunchTime = SystemClock.uptimeMillis();

            ...
            try {
                // 进程启动了,但是主线程ActivityThread::main还没有执行
                if (!proc.hasThread()) {
                    throw new RemoteException();
                }          
  
                ...

                // Create activity launch transaction.
                final ClientTransaction clientTransaction = ClientTransaction.obtain(
                        proc.getThread(), r.token);

                final boolean isTransitionForward = r.isTransitionForward();
                final IBinder fragmentToken = r.getTaskFragment().getFragmentToken();
                clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),
                        System.identityHashCode(r), r.info,
                        mergedConfiguration.getGlobalConfiguration(),
                        mergedConfiguration.getOverrideConfiguration(), r.compat,
                        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) {
                    lifecycleItem = ResumeActivityItem.obtain(isTransitionForward);
                } else {
                    lifecycleItem = PauseActivityItem.obtain();
                }
                clientTransaction.setLifecycleStateRequest(lifecycleItem);

                // Schedule transaction.
                mService.getLifecycleManager().scheduleTransaction(clientTransaction);

            } 

            ...

        return true;
    }

等待Pause complete

一开始就有个条件判断 allPausedActivitiesComplete

如果进程启动很快,pause的进度比我们慢了,那么此时还不能执行启动,当completePause之后再次尝试启动Activity

当前的分析逻辑是进程启动了,然后启动Activity,但是有个条件

  • 设置ActivityRecord进程信息

  • 创建ClientTransaction

  • 创建一个LaunchActivityItem并且添加到transaction里边,还添加了一个ResumeActivityItem表示启动之后马上Resume

  • 调用scheduleTransaction函数发起transaction

Transaction最终由TransactionExecutor::execute执行,先执行callback,然后执行lifeCycleState

Transaction执行到ActivityThread

transaction的执行最终执行到LaunchActivityItem::execute函数

public void execute(ClientTransactionHandler client, IBinder token,
        PendingTransactionActions pendingActions) {
    Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
    ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo,
            mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState, mPersistentState,
            mPendingResults, mPendingNewIntents, mActivityOptions, mIsForward, mProfilerInfo,
            client, mAssistToken, mShareableActivityToken, mLaunchedFromBubble,
            mTaskFragmentToken);
    client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
    Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}

参数client的实现类是ActivityThread,token是ActivityRecord的token,然后将Activity启动参数封装到ActivityClientRecord对象

ActivityThread执行Activity启动流程

ActivityThread::handleLaunchActivity

@Override
public Activity handleLaunchActivity(ActivityClientRecord r,
        PendingTransactionActions pendingActions, Intent customIntent) {

        final Activity a = performLaunchActivity(r, customIntent);
        return a;
}

里边直接调用了performLaunchActivity

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    ActivityInfo aInfo = r.activityInfo;
    //创建Context
    ContextImpl appContext = createBaseContextForActivity(r);
    Activity activity = null;
    try {
        java.lang.ClassLoader cl = appContext.getClassLoader();
        //创建Activity
        activity = mInstrumentation.newActivity(
                cl, component.getClassName(), r.intent);
        StrictMode.incrementExpectedActivityCount(activity.getClass());
        r.intent.setExtrasClassLoader(cl);
        r.intent.prepareToEnterProcess(isProtectedComponent(r.activityInfo),
                appContext.getAttributionSource());
        if (r.state != null) {
            r.state.setClassLoader(cl);
        }
    }

    try {
        // 创建Application
        Application app = r.packageInfo.makeApplicationInner(false, mInstrumentation);
        ...
        if (activity != null) {
            ...
            activity.attach(appContext, this, getInstrumentation(), r.token,
                    r.ident, app, r.intent, r.activityInfo, title, r.parent,
                    r.embeddedID, r.lastNonConfigurationInstances, config,
                    r.referrer, r.voiceInteractor, window, r.activityConfigCallback,
                    r.assistToken, r.shareableActivityToken);

            r.activity = activity;
            if (r.isPersistable()) {
                mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
            } else {
                mInstrumentation.callActivityOnCreate(activity, r.state);
            }
            
        }
        r.setState(ON_CREATE);

    return activity;
}
  • 生成Context,context实现类是ContextImpl,如果是非默认屏幕则会根据displayId创建新的ContextImpl

  • 生成Activity对象,调用了Instrumentation::newActivity,实际上是通过ClassLoader加载的Activity


    public Activity newActivity(ClassLoader cl, String className,
            Intent intent)
            throws InstantiationException, IllegalAccessException,
            ClassNotFoundException {
        String pkg = intent != null && intent.getComponent() != null
                ? intent.getComponent().getPackageName() : null;
        return getFactory(pkg).instantiateActivity(cl, className, intent);
    }

    public @NonNull Activity instantiateActivity(@NonNull ClassLoader cl, @NonNull String className,
            @Nullable Intent intent)
            throws InstantiationException, IllegalAccessException, ClassNotFoundException {
        // 反射创建
        return (Activity) cl.loadClass(className).newInstance();
    }
  • 执行Activity::attach,绑定Application,Context,Token,创建PhoneWindow对象,初始化LayoutInflator

  • 开始执行Activity::onCreate生命周期

public void callActivityOnCreate(Activity activity, Bundle icicle) {
    prePerformCreate(activity);
    activity.performCreate(icicle);
    postPerformCreate(activity);
}

在performCreate函数中会调用onCreate函数, 这个时候就会开始加载布局了

Activity从点击到实例创建的整个流程就分析完了

参考资料

[1].【Android 14源码分析】Activity启动流程-1

[2].【Android 14源码分析】Activity启动流程-2

[3]. 【Android 14源码分析】Activity启动流程-3

[4]. Zygote为什么用Socket而不用Binder?深度解析Android进程通信机制与实战开发 - Android洋芋 - 博客园

[5]. 010.Android 系统启动之应用进程启动分析 | Ahao's Technical Blog

[6]. android开发基于Android10分析Zygote启动过程以及Fork应用进程的过程分析 - yongfengnice - 博客园

春风花气馥,秋月寒江湛