ATMS启动Activity流程 - 安卓R

本文详细解析了Android中Activity从启动到显示的整个过程,包括如何通过Context的startActivity方法触发Activity启动,system_server中ActivityRecord对象的创建,以及ActivityRecord如何被放置进ActivityStack中。

一般在app中通过context.startActivity方法启动Activity,这个方法最终会通过binder调用frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java的startActivity方法:

    @Override
    public final int startActivity(IApplicationThread caller, String callingPackage,
            String callingFeatureId, Intent intent, String resolvedType, IBinder resultTo,
            String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo,
            Bundle bOptions) {
        return startActivityAsUser(caller, callingPackage, callingFeatureId, intent, resolvedType,
                resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions,
                UserHandle.getCallingUserId());
    }

调用了ActivityTaskManagerService的startActivityAsUser方法:

    @Override
    public int startActivityAsUser(IApplicationThread caller, String callingPackage,
            String callingFeatureId, Intent intent, String resolvedType, IBinder resultTo,
            String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo,
            Bundle bOptions, int userId) {
        return startActivityAsUser(caller, callingPackage, callingFeatureId, intent, resolvedType,
                resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions, userId,
                true /*validateIncomingUser*/);
    }

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

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

        // TODO: Switch to user app stacks here.
        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();
    }

调用了frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java的execute方法:

    /**
     * Resolve necessary information according the request parameters provided earlier, and execute
     * the request which begin the journey of starting an activity.
     * @return The starter result.
     */
    int execute() {
        try {
            ......
            synchronized (mService.mGlobalLock) {
                ......
                res = executeRequest(mRequest);
                ......
            }
        } finally {
            onExecutionComplete();
        }
    }

调用了ActivityStarter的executeRequest方法:

    /**
     * Executing activity start request and starts the journey of starting an activity. Here
     * begins with performing several preliminary checks. The normally activity launch flow will
     * go through {@link #startActivityUnchecked} to {@link #startActivityInner}.
     */
    private int executeRequest(Request request) {
        ......
        final ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
                callingPackage, callingFeatureId, intent, resolvedType, aInfo,
                mService.getGlobalConfiguration(), resultRecord, resultWho, requestCode,
                request.componentSpecified, voiceSession != null, mSupervisor, checkedOptions,
                sourceRecord);
        ......
        mLastStartActivityResult = startActivityUnchecked(r, sourceRecord, voiceSession,
                request.voiceInteractor, startFlags, true /* doResume */, checkedOptions, inTask,
                restrictedBgActivity, intentGrants);
        ......
    }

在这里创建了ActivityRecord对象,然后调用了ActivityStarter的startActivityUnchecked方法:

    /**
     * Start an activity while most of preliminary checks has been done and caller has been
     * confirmed that holds necessary permissions to do so.
     * Here also ensures that the starting activity is removed if the start wasn't successful.
     */
    private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
                IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
                int startFlags, boolean doResume, ActivityOptions options, Task inTask,
                boolean restrictedBgActivity, NeededUriGrants intentGrants) {
        int result = START_CANCELED;
        final ActivityStack startedActivityStack;
        try {
            mService.deferWindowLayout();
            Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "startActivityInner");
            result = startActivityInner(r, sourceRecord, voiceSession, voiceInteractor,
                    startFlags, doResume, options, inTask, restrictedBgActivity, intentGrants);
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
            startedActivityStack = handleStartResult(r, result);
            mService.continueWindowLayout();
        }

        postStartActivityProcessing(r, result, startedActivityStack);

        return result;
    }

调用了ActivityStarter的startActivityInner方法:

    /**
     * Start an activity and determine if the activity should be adding to the top of an existing
     * task or delivered new intent to an existing activity. Also manipulating the activity task
     * onto requested or valid stack/display.
     *
     * Note: This method should only be called from {@link #startActivityUnchecked}.
     */

    // TODO(b/152429287): Make it easier to exercise code paths through startActivityInner
    @VisibleForTesting
    int startActivityInner(final ActivityRecord r, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            int startFlags, boolean doResume, ActivityOptions options, Task inTask,
            boolean restrictedBgActivity, NeededUriGrants intentGrants) {
        ......
        if (newTask) {
            EventLogTags.writeWmCreateTask(mStartActivity.mUserId,
                    mStartActivity.getTask().mTaskId);
        }
        mStartActivity.logStartActivity(
                EventLogTags.WM_CREATE_ACTIVITY, mStartActivity.getTask());
        ......
        mTargetStack.startActivityLocked(mStartActivity,
                topStack != null ? topStack.getTopNonFinishingActivity() : null, newTask,
                mKeepCurTransition, mOptions);
        if (mDoResume) {
            final ActivityRecord topTaskActivity =
                    mStartActivity.getTask().topRunningActivityLocked();
            if (!mTargetStack.isTopActivityFocusable()
                    || (topTaskActivity != null && topTaskActivity.isTaskOverlay()
                    && mStartActivity != topTaskActivity)) {
                // If the activity is not focusable, we can't resume it, but still would like to
                // make sure it becomes visible as it starts (this will also trigger entry
                // animation). An example of this are PIP activities.
                // Also, we don't want to resume activities in a task that currently has an overlay
                // as the starting activity just needs to be in the visible paused state until the
                // over is removed.
                // Passing {@code null} as the start parameter ensures all activities are made
                // visible.
                mTargetStack.ensureActivitiesVisible(null /* starting */,
                        0 /* configChanges */, !PRESERVE_WINDOWS);
                // Go ahead and tell window manager to execute app transition for this activity
                // since the app transition will not be triggered through the resume channel.
                mTargetStack.getDisplay().mDisplayContent.executeAppTransition();
            } else {
                // If the target stack was not previously focusable (previous top running activity
                // on that stack was not visible) then any prior calls to move the stack to the
                // will not update the focused stack.  If starting the new activity now allows the
                // task stack to be focusable, then ensure that we now update the focused stack
                // accordingly.
                if (mTargetStack.isTopActivityFocusable()
                        && !mRootWindowContainer.isTopDisplayFocusedStack(mTargetStack)) {
                    mTargetStack.moveToFront("startActivityInner");
                }
                mRootWindowContainer.resumeFocusedStacksTopActivities(
                        mTargetStack, mStartActivity, mOptions);
            }
        }
        ......
    }

这里如果建了新的栈,即newTask为true时会打印event log:wm_create_task,还会打印event log:wm_create_activity,然后使用现有的或创建了ActivityStack对象mTargetStack,调用了frameworks/base/services/core/java/com/android/server/wm/ActivityStack.java的startActivityLocked方法:

    void startActivityLocked(ActivityRecord r, @Nullable ActivityRecord focusedTopActivity,
            boolean newTask, boolean keepCurTransition, ActivityOptions options) {
        Task rTask = r.getTask();
        final boolean allowMoveToFront = options == null || !options.getAvoidMoveToFront();
        final boolean isOrhasTask = rTask == this || hasChild(rTask);
        // mLaunchTaskBehind tasks get placed at the back of the task stack.
        if (!r.mLaunchTaskBehind && allowMoveToFront && (!isOrhasTask || newTask)) {
            // Last activity in task had been removed or ActivityManagerService is reusing task.
            // Insert or replace.
            // Might not even be in.
            positionChildAtTop(rTask);
        }
        Task task = null;
        if (!newTask && isOrhasTask) {
            // Starting activity cannot be occluding activity, otherwise starting window could be
            // remove immediately without transferring to starting activity.
            final ActivityRecord occludingActivity = getOccludingActivityAbove(r);
            if (occludingActivity != null) {
                // Here it is!  Now, if this is not yet visible (occluded by another task) to the
                // user, then just add it without starting; it will get started when the user
                // navigates back to it.
                if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Adding activity " + r + " to task " + task,
                        new RuntimeException("here").fillInStackTrace());
                rTask.positionChildAtTop(r);
                ActivityOptions.abort(options);
                return;
            }
        }

        // Place a new activity at top of stack, so it is next to interact with the user.

        // If we are not placing the new activity frontmost, we do not want to deliver the
        // onUserLeaving callback to the actual frontmost activity
        final Task activityTask = r.getTask();
        if (task == activityTask && mChildren.indexOf(task) != (getChildCount() - 1)) {
            mStackSupervisor.mUserLeaving = false;
            if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
                    "startActivity() behind front, mUserLeaving=false");
        }

        task = activityTask;

        // Slot the activity into the history stack and proceed
        if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Adding activity " + r + " to stack to task " + task,
                new RuntimeException("here").fillInStackTrace());
        task.positionChildAtTop(r);

        // The transition animation and starting window are not needed if {@code allowMoveToFront}
        // is false, because the activity won't be visible.
        if ((!isHomeOrRecentsStack() || hasActivity()) && allowMoveToFront) {
            final DisplayContent dc = getDisplay().mDisplayContent;
            if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION,
                    "Prepare open transition: starting " + r);
            if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
                dc.prepareAppTransition(TRANSIT_NONE, keepCurTransition);
                mStackSupervisor.mNoAnimActivities.add(r);
            } else {
                int transit = TRANSIT_ACTIVITY_OPEN;
                if (newTask) {
                    if (r.mLaunchTaskBehind) {
                        transit = TRANSIT_TASK_OPEN_BEHIND;
                    } else if (getDisplay().isSingleTaskInstance()) {
                        // If a new task is being launched in a single task display, we don't need
                        // to play normal animation, but need to trigger a callback when an app
                        // transition is actually handled. So ignore already prepared activity, and
                        // override it.
                        transit = TRANSIT_SHOW_SINGLE_TASK_DISPLAY;
                        keepCurTransition = false;
                    } else {
                        // If a new task is being launched, then mark the existing top activity as
                        // supporting picture-in-picture while pausing only if the starting activity
                        // would not be considered an overlay on top of the current activity
                        // (eg. not fullscreen, or the assistant)
                        if (canEnterPipOnTaskSwitch(focusedTopActivity,
                                null /* toFrontTask */, r, options)) {
                            focusedTopActivity.supportsEnterPipOnTaskSwitch = true;
                        }
                        transit = TRANSIT_TASK_OPEN;
                    }
                }
                dc.prepareAppTransition(transit, keepCurTransition);
                mStackSupervisor.mNoAnimActivities.remove(r);
            }
            boolean doShow = true;
            if (newTask) {
                // Even though this activity is starting fresh, we still need
                // to reset it to make sure we apply affinities to move any
                // existing activities from other tasks in to it.
                // If the caller has requested that the target task be
                // reset, then do so.
                if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
                    resetTaskIfNeeded(r, r);
                    doShow = topRunningNonDelayedActivityLocked(null) == r;
                }
            } else if (options != null && options.getAnimationType()
                    == ActivityOptions.ANIM_SCENE_TRANSITION) {
                doShow = false;
            }
            if (r.mLaunchTaskBehind) {
                // Don't do a starting window for mLaunchTaskBehind. More importantly make sure we
                // tell WindowManager that r is visible even though it is at the back of the stack.
                r.setVisibility(true);
                ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
                // Go ahead to execute app transition for this activity since the app transition
                // will not be triggered through the resume channel.
                getDisplay().mDisplayContent.executeAppTransition();
            } else if (SHOW_APP_STARTING_PREVIEW && doShow) {
                // Figure out if we are transitioning from another activity that is
                // "has the same starting icon" as the next one.  This allows the
                // window manager to keep the previous window it had previously
                // created, if it still had one.
                Task prevTask = r.getTask();
                ActivityRecord prev = prevTask.topActivityWithStartingWindow();
                if (prev != null) {
                    // We don't want to reuse the previous starting preview if:
                    // (1) The current activity is in a different task.
                    if (prev.getTask() != prevTask) {
                        prev = null;
                    }
                    // (2) The current activity is already displayed.
                    else if (prev.nowVisible) {
                        prev = null;
                    }
                }
                r.showStartingWindow(prev, newTask, isTaskSwitch(r, focusedTopActivity));
            }
        } else {
            // If this is the first activity, don't do any fancy animations,
            // because there is nothing for it to animate on top of.
            ActivityOptions.abort(options);
        }
    }

这里首先通过positionChildAtTop方法将ActivityRecord放入栈顶,然后通过dc.prepareAppTransition方法准备进行app过渡动画,最后调用了ActivityRecord的showStartingWindow方法进入StartingWindow显示流程

回到ActivityStarter的startActivityInner方法中,最后如果mDoResume为true,则使用mTargetStack.ensureActivitiesVisible方法或mRootWindowContainer.resumeFocusedStacksTopActivities方法确保栈中Activity的可见性或去resume栈顶的Activity。app端Activity的生命周期触发流程可以看Activity生命周期调用流程,Activity的启动流程可以看Activity的启动流程

总结

1 app中通过context.startActivity方法启动Activity时,通过binder调用了ActivityTaskManagerService的startActivity方法去启动Activity;

2 启动Activity过程中在system_server中创建了ActivityRecord对象,对应了app中的Activity对象;

3 启动Activity过程中在system_server中将ActivityRecord对象放进了ActivityStack中。

<think>我们聚焦于从源码角度分析Activity启动流程,主要环节如下: ### 1. **Launcher发起启动请求** - **入口**:`Launcher`点击应用图标触发`startActivity()` - **关键调用链**: ```java // frameworks/base/core/java/android/app/Activity.java public void startActivity(Intent intent) { mInstrumentation.execStartActivity(...); // 通过Instrumentation发起 } ``` - **跨进程通信**:通过Binder调用到`ActivityTaskManagerService` (ATMS)[^1] ### 2. **ATMS处理启动请求** - **核心逻辑**:`frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java` ```java class ActivityTaskManagerService { int startActivity(...) { return getActivityStartController().obtainStarter(...).execute(); } } ``` - **关键步骤**: - 验证权限及Intent - 创建`ActivityRecord`对象记录Activity信息 - 决策是否新建进程[^1][^2] ### 3. **进程创建(若需新建)** - **调用路径**: ``` ATMS.startProcessAsync() → LocalService.startProcess() → ProcessList.startProcessLocked() ``` - **Zygote孵化**: ```java // frameworks/base/services/core/java/com/android/server/am/ProcessList.java final Process.ProcessStartResult startResult = Process.start(...); ``` - 通过Socket连接Zygote fork新进程[^1] ### 4. **目标进程初始化** - **入口**:`ActivityThread.main()` ```java // frameworks/base/core/java/android/app/ActivityThread.java public static void main(String[] args) { Looper.prepareMainLooper(); ActivityThread thread = new ActivityThread(); thread.attach(false); // 绑定到AMS Looper.loop(); } ``` - **绑定系统服务**:通过`ApplicationThread` Binder对象与ATMS通信[^3] ### 5. **Activity实例化与生命周期** - **ATMS回调**:`ApplicationThread.scheduleLaunchActivity()` - **核心处理**: ```java // ActivityThread.handleLaunchActivity() final Activity a = performLaunchActivity(r, customIntent); if (a != null) { handleResumeActivity(...); // 触发onResume() } ``` - **关键源码**: ```java // ActivityThread.performLaunchActivity() Activity activity = mInstrumentation.newActivity(...); // 反射创建实例 Application app = r.packageInfo.makeApplication(...); // 创建Application activity.attach(...); // 关联Context mInstrumentation.callActivityOnCreate(activity, ...); // 回调onCreate() ``` - **视图渲染**:`onCreate()`中调用`setContentView()`触发DecorView创建[^3] ### 6. **界面绘制与显示** - **首帧同步**:`handleResumeActivity()`中触发View绘制 ```java // ActivityThread.handleResumeActivity() wm.addView(decor, layoutParams); // 添加DecorView到WindowManager ``` - **VSync同步流程**: 1. `ViewRootImpl.scheduleTraversals()`请求VSync信号 2. Choreographer通过SF进程同步VSync 3. 收到VSync后执行`performTraversals()`(测量/布局/绘制)[^3] ### 性能优化关键点 1. **进程复用**:通过`android:process`共享进程减少fork开销 2. **异步加载**:在`onCreate()`中延迟加载非必要资源 3. **渲染优化**:使用`<merge>`标签减少视图层级 4. **冷启动加速**:借助StartingWindow展示预览界面 --- §§相关问题§§ 1. `Instrumentation`在Activity启动中承担什么角色? 2. Zygote孵化新进程时如何复制内存页? 3. `ViewRootImpl.performTraversals()`的测量-布局-绘制三个阶段如何协同工作? </think>以下是从源码角度分析的Android Activity启动主要流程环节,涵盖从Launcher点击到界面渲染的核心过程: --- ### 1. **Launcher发起启动请求** - **入口**:`Launcher.onClick()` (packages/apps/Launcher3) - **关键调用链**: ```java // Launcher.java onClick(View v) { startActivitySafely(v, intent, item); // 启动目标应用 } → startActivity(intent) → Instrumentation.execStartActivity() // 跨进程通信枢纽 ``` - **跨进程通信**:通过Binder调用`ActivityTaskManagerService` (ATMS)[^1] --- ### 2. **ATMS处理启动请求** - **核心逻辑**:`ActivityTaskManagerService.startActivity()` ```java // frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java public int startActivity(...) { return getActivityStartController().obtainStarter(intent).execute(); } ``` - **关键步骤**: 1. 解析Intent获取目标Activity信息 2. 检查权限及进程状态 3. 决策是否需创建新进程(`ProcessRecord`) 4. 创建`ActivityRecord`对象[^1] --- ### 3. **进程创建(若需新建)** - **Zygote孵化流程**: ```java // frameworks/base/services/core/java/com/android/server/am/ProcessList.java final Process.ProcessStartResult startResult = Process.start(...); ``` - 通过Socket联系Zygote - fork新进程并执行`ActivityThread.main()` - **内存优化**:Copy-on-Write复用Zygote预加载资源[^1] --- ### 4. **目标进程初始化** - **入口**:`ActivityThread.main()` ```java // frameworks/base/core/java/android/app/ActivityThread.java public static void main(String[] args) { Looper.prepareMainLooper(); ActivityThread thread = new ActivityThread(); thread.attach(false); // 绑定到AMS Looper.loop(); } ``` - **关键动作**: - 创建`ApplicationThread` Binder对象 - 通过`ATTACH_APPLICATION`消息注册到AMS[^3] --- ### 5. **Activity实例化与生命周期** - **ATMS回调**:`ApplicationThread.scheduleLaunchActivity()` - **核心处理**: ```java // ActivityThread.handleLaunchActivity() private void handleLaunchActivity(...) { final Activity a = performLaunchActivity(r, customIntent); // 创建实例 handleResumeActivity(...); // 触发onResume() } ``` - **创建细节**: ```java // performLaunchActivity() Activity activity = mInstrumentation.newActivity(...); // 反射创建 Application app = r.packageInfo.makeApplication(...); // 创建Application activity.attach(...); // 关联Context mInstrumentation.callActivityOnCreate(activity, ...); // 回调onCreate() ``` - **视图初始化**:`onCreate()`中调用`setContentView()`触发DecorView创建[^3] --- ### 6. **界面绘制与显示** - **添加到窗口**:`ActivityThread.handleResumeActivity()` ```java wm.addView(decor, layoutParams); // 添加DecorView到WindowManager ``` - **VSync同步绘制**: 1. `ViewRootImpl.scheduleTraversals()`请求VSync信号 2. Choreographer通过`FrameDisplayEventReceiver`接收VSync 3. 执行`performTraversals()`(测量/布局/绘制) 4. SurfaceFlinger合成帧缓存[^3] --- ### 性能优化关键点 1. **进程复用**:通过`android:process`共享进程减少fork开销 2. **异步加载**:在`onCreate()`中延迟初始化非必要资源 3. **渲染管线优化**: ```java // 启用硬件加速 <activity android:hardwareAccelerated="true"/> ``` 4. **冷启动优化**:使用SplashScreen API展示即时预览 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SSSxCCC

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值