Android P ActivityManagerService(六) startActivity的第四小部分

ActivityStarter中,生成ActivityRecord之后startActivity方法;

private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
            ActivityRecord[] outActivity) {
    int result = START_CANCELED;
    try {
        mService.mWindowManager.deferSurfaceLayout();
        result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
                startFlags, doResume, options, inTask, outActivity);
    } finally {
        // If we are not able to proceed, disassociate the activity from the task. Leaving an
        // activity in an incomplete state can lead to issues, such as performing operations
        // without a window container.
        final ActivityStack stack = mStartActivity.getStack();
        if (!ActivityManager.isStartResultSuccessful(result) && stack != null) {
            stack.finishActivityLocked(mStartActivity, RESULT_CANCELED,
                    null /* intentResultData */, "startActivity", true /* oomAdj */);
        }
        mService.mWindowManager.continueSurfaceLayout();
    }

    postStartActivityProcessing(r, result, mTargetStack);

    return result;
}

在AMS的初始化中,SystemServer的startOtherServices方法内,AMS通过setWindowManager方法获得了WindowManagerService;即这里的mService.mWindowManager;

public void setWindowManager(WindowManagerService wm) {
    synchronized (this) {
        mWindowManager = wm;
        mStackSupervisor.setWindowManager(wm);
        mLockTaskController.setWindowManager(wm);
    }
}

WindowManagerService的deferSurfaceLayout方法;通知暂停布局;

/**
 * Starts deferring layout passes. Useful when doing multiple changes but to optimize
 * performance, only one layout pass should be done. This can be called multiple times, and
 * layouting will be resumed once the last caller has called {@link #continueSurfaceLayout}
 */
public void deferSurfaceLayout() {
    synchronized (mWindowMap) {
        mWindowPlacerLocked.deferLayout();
    }
}

continueSurfaceLayout方法;恢复暂停的布局;

/**
 * Resumes layout passes after deferring them. See {@link #deferSurfaceLayout()}
 */
public void continueSurfaceLayout() {
    synchronized (mWindowMap) {
        mWindowPlacerLocked.continueLayout();
    }
}

这两个方法中间,是启动Activity的关键方法;startActivityUnchecked;Unchecked这个词很关键,表示再也不会像之前一样,检查个300行代码了;然后这个启动的代码,也有260行之多;

// Note: This method should only be called from {@link startActivity}.
private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
        IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
        int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
        ActivityRecord[] outActivity) {

    setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
            voiceInteractor);

    computeLaunchingTaskFlags();

    computeSourceStack();

    mIntent.setFlags(mLaunchFlags);

    ActivityRecord reusedActivity = getReusableIntentActivity();

    int preferredWindowingMode = WINDOWING_MODE_UNDEFINED;
    int preferredLaunchDisplayId = DEFAULT_DISPLAY;
    if (mOptions != null) {
        preferredWindowingMode = mOptions.getLaunchWindowingMode();
        preferredLaunchDisplayId = mOptions.getLaunchDisplayId();
    }

    // windowing mode and preferred launch display values from {@link LaunchParams} take
    // priority over those specified in {@link ActivityOptions}.
    if (!mLaunchParams.isEmpty()) {
        if (mLaunchParams.hasPreferredDisplay()) {
            preferredLaunchDisplayId = mLaunchParams.mPreferredDisplayId;
        }

        if (mLaunchParams.hasWindowingMode()) {
            preferredWindowingMode = mLaunchParams.mWindowingMode;
        }
    }

    if (reusedActivity != null) {
        // When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused but
        // still needs to be a lock task mode violation since the task gets cleared out and
        // the device would otherwise leave the locked task.
        if (mService.getLockTaskController().isLockTaskModeViolation(reusedActivity.getTask(),
                (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
                        == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) {
            Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");
            return START_RETURN_LOCK_TASK_MODE_VIOLATION;
        }

        // True if we are clearing top and resetting of a standard (default) launch mode
        // ({@code LAUNCH_MULTIPLE}) activity. The existing activity will be finished.
        final boolean clearTopAndResetStandardLaunchMode =
                (mLaunchFlags & (FLAG_ACTIVITY_CLEAR_TOP | FLAG_ACTIVITY_RESET_TASK_IF_NEEDED))
                        == (FLAG_ACTIVITY_CLEAR_TOP | FLAG_ACTIVITY_RESET_TASK_IF_NEEDED)
                && mLaunchMode == LAUNCH_MULTIPLE;

        // If mStartActivity does not have a task associated with it, associate it with the
        // reused activity's task. Do not do so if we're clearing top and resetting for a
        // standard launchMode activity.
        if (mStartActivity.getTask() == null && !clearTopAndResetStandardLaunchMode) {
            mStartActivity.setTask(reusedActivity.getTask());
        }

        if (reusedActivity.getTask().intent == null) {
            // This task was started because of movement of the activity based on affinity...
            // Now that we are actually launching it, we can assign the base intent.
            reusedActivity.getTask().setIntent(mStartActivity);
        }

        // This code path leads to delivering a new intent, we want to make sure we schedule it
        // as the first operation, in case the activity will be resumed as a result of later
        // operations.
        if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
                || isDocumentLaunchesIntoExisting(mLaunchFlags)
                || isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK)) {
            final TaskRecord task = reusedActivity.getTask();

            // In this situation we want to remove all activities from the task up to the one
            // being started. In most cases this means we are resetting the task to its initial
            // state.
            final ActivityRecord top = task.performClearTaskForReuseLocked(mStartActivity,
                    mLaunchFlags);

            // The above code can remove {@code reusedActivity} from the task, leading to the
            // the {@code ActivityRecord} removing its reference to the {@code TaskRecord}. The
            // task reference is needed in the call below to
            // {@link setTargetStackAndMoveToFrontIfNeeded}.
            if (reusedActivity.getTask() == null) {
                reusedActivity.setTask(task);
            }

            if (top != null) {
                if (top.frontOfTask) {
                    // Activity aliases may mean we use different intents for the top activity,
                    // so make sure the task now has the identity of the new intent.
                    top.getTask().setIntent(mStartActivity);
                }
                deliverNewIntent(top);
            }
        }

        mSupervisor.sendPowerHintForLaunchStartIfNeeded(false /* forceSend */, reusedActivity);

        reusedActivity = setTargetStackAndMoveToFrontIfNeeded(reusedActivity);

        final ActivityRecord outResult =
                outActivity != null && outActivity.length > 0 ? outActivity[0] : null;

        // When there is a reused activity and the current result is a trampoline activity,
        // set the reused activity as the result.
        if (outResult != null && (outResult.finishing || outResult.noDisplay)) {
            outActivity[0] = reusedActivity;
        }

        if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
            // We don't need to start a new activity, and the client said not to do anything
            // if that is the case, so this is it!  And for paranoia, make sure we have
            // correctly resumed the top activity.
            resumeTargetStackIfNeeded();
            return START_RETURN_INTENT_TO_CALLER;
        }

        if (reusedActivity != null) {
            setTaskFromIntentActivity(reusedActivity);

            if (!mAddingToTask && mReuseTask == null) {
                // We didn't do anything...  but it was needed (a.k.a., client don't use that
                // intent!)  And for paranoia, make sure we have correctly resumed the top activity.

                resumeTargetStackIfNeeded();
                if (outActivity != null && outActivity.length > 0) {
                    outActivity[0] = reusedActivity;
                }

                return mMovedToFront ? START_TASK_TO_FRONT : START_DELIVERED_TO_TOP;
            }
        }
    }

    if (mStartActivity.packageName == null) {
        final ActivityStack sourceStack = mStartActivity.resultTo != null
                ? mStartActivity.resultTo.getStack() : null;
        if (sourceStack != null) {
            sourceStack.sendActivityResultLocked(-1 /* callingUid */, mStartActivity.resultTo,
                    mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED,
                    null /* data */);
        }
        ActivityOptions.abort(mOptions);
        return START_CLASS_NOT_FOUND;
    }

    // If the activity being launched is the same as the one currently at the top, then
    // we need to check if it should only be launched once.
    final ActivityStack topStack = mSupervisor.mFocusedStack;
    final ActivityRecord topFocused = topStack.getTopActivity();
    final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);
    final boolean dontStart = top != null && mStartActivity.resultTo == null
            && top.realActivity.equals(mStartActivity.realActivity)
            && top.userId == mStartActivity.userId
            && top.app != null && top.app.thread != null
            && ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
            || isLaunchModeOneOf(LAUNCH_SINGLE_TOP, LAUNCH_SINGLE_TASK));
    if (dontStart) {
        // For paranoia, make sure we have correctly resumed the top activity.
        topStack.mLastPausedActivity = null;
        if (mDoResume) {
            mSupervisor.resumeFocusedStackTopActivityLocked();
        }
        ActivityOptions.abort(mOptions);
        if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
            // We don't need to start a new activity, and the client said not to do
            // anything if that is the case, so this is it!
            return START_RETURN_INTENT_TO_CALLER;
        }

        deliverNewIntent(top);

        // Don't use mStartActivity.task to show the toast. We're not starting a new activity
        // but reusing 'top'. Fields in mStartActivity may not be fully initialized.
        mSupervisor.handleNonResizableTaskIfNeeded(top.getTask(), preferredWindowingMode,
                preferredLaunchDisplayId, topStack);

        return START_DELIVERED_TO_TOP;
    }

    boolean newTask = false;
    final TaskRecord taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
            ? mSourceRecord.getTask() : null;

    // Should this be considered a new task?
    int result = START_SUCCESS;
    if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
            && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
        newTask = true;
        result = setTaskFromReuseOrCreateNewTask(taskToAffiliate, topStack);
    } else if (mSourceRecord != null) {
        result = setTaskFromSourceRecord();
    } else if (mInTask != null) {
        result = setTaskFromInTask();
    } else {
        // This not being started from an existing activity, and not part of a new task...
        // just put it in the top task, though these days this case should never happen.
        setTaskToCurrentTopOrCreateNewTask();
    }
    if (result != START_SUCCESS) {
        return result;
    }

    mService.grantUriPermissionFromIntentLocked(mCallingUid, mStartActivity.packageName,
            mIntent, mStartActivity.getUriPermissionsLocked(), mStartActivity.userId);
    mService.grantEphemeralAccessLocked(mStartActivity.userId, mIntent,
            mStartActivity.appInfo.uid, UserHandle.getAppId(mCallingUid));
    if (newTask) {
        EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, mStartActivity.userId,
                mStartActivity.getTask().taskId);
    }
    ActivityStack.logStartActivity(
            EventLogTags.AM_CREATE_ACTIVITY, mStartActivity, mStartActivity.getTask());
    mTargetStack.mLastPausedActivity = null;

    mSupervisor.sendPowerHintForLaunchStartIfNeeded(false /* forceSend */, mStartActivity);

    mTargetStack.startActivityLocked(mStartActivity, topFocused, newTask, mKeepCurTransition,
            mOptions);
    if (mDoResume) {
        final ActivityRecord topTaskActivity =
                mStartActivity.getTask().topRunningActivityLocked();
        if (!mTargetStack.isFocusable()
                || (topTaskActivity != null && topTaskActivity.mTaskOverlay
                && 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.
            mTargetStack.ensureActivitiesVisibleLocked(null, 0, !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.
            mService.mWindowManager.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.isFocusable() && !mSupervisor.isFocusedStack(mTargetStack)) {
                mTargetStack.moveToFront("startActivityUnchecked");
            }
            mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
                    mOptions);
        }
    } else if (mStartActivity != null) {
        mSupervisor.mRecentTasks.add(mStartActivity.getTask());
    }
    mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);

    mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTask(), preferredWindowingMode,
            preferredLaunchDisplayId, mTargetStack);

    return START_SUCCESS;
}

代码太长;只能一段段分开看;

1. 启动参数的初始化;里面是对一个参数和Flag的设置;

setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
        voiceInteractor);

2. 计算LaunchingTask和一些LaunchMode;

computeLaunchingTaskFlags();

3. 拿到mSourceStack;这里会对正在关闭的source做特殊处理;

computeSourceStack();

4. 设置LaunchFlags;FLAG_ACTIVITY_NEW_TASK、FLAG_ACTIVITY_MULTIPLE_TASK等Flags;

mIntent.setFlags(mLaunchFlags);

5. 判断是否应将新Activity插入现有task;如果不是,则返回null;如果是,则返回包含要添加新Activity的task的ActivityRecord;

ActivityRecord reusedActivity = getReusableIntentActivity();

6. window mode和dispaly id;window mode定义在WindowConfiguration,包括WINDOWING_MODE_UNDEFINED、WINDOWING_MODE_FULLSCREEN、WINDOWING_MODE_PINNED等;display id相关定义在Display中,每个dispay都有一个唯一的id;

int preferredWindowingMode = WINDOWING_MODE_UNDEFINED;
int preferredLaunchDisplayId = DEFAULT_DISPLAY;
if (mOptions != null) {
    preferredWindowingMode = mOptions.getLaunchWindowingMode();
    preferredLaunchDisplayId = mOptions.getLaunchDisplayId();
}

// windowing mode and preferred launch display values from {@link LaunchParams} take
// priority over those specified in {@link ActivityOptions}.
if (!mLaunchParams.isEmpty()) {
    if (mLaunchParams.hasPreferredDisplay()) {
        preferredLaunchDisplayId = mLaunchParams.mPreferredDisplayId;
    }

    if (mLaunchParams.hasWindowingMode()) {
        preferredWindowingMode = mLaunchParams.mWindowingMode;
    }
}

7. 重用Activity;符合条件就直接重用;不走后面的代码;

if (reusedActivity != null) {
    // When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused but
    // still needs to be a lock task mode violation since the task gets cleared out and
    // the device would otherwise leave the locked task.
    if (mService.getLockTaskController().isLockTaskModeViolation(reusedActivity.getTask(),
            (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
                    == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) {
        Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");
        return START_RETURN_LOCK_TASK_MODE_VIOLATION;
    }

    // True if we are clearing top and resetting of a standard (default) launch mode
    // ({@code LAUNCH_MULTIPLE}) activity. The existing activity will be finished.
    final boolean clearTopAndResetStandardLaunchMode =
            (mLaunchFlags & (FLAG_ACTIVITY_CLEAR_TOP | FLAG_ACTIVITY_RESET_TASK_IF_NEEDED))
                    == (FLAG_ACTIVITY_CLEAR_TOP | FLAG_ACTIVITY_RESET_TASK_IF_NEEDED)
            && mLaunchMode == LAUNCH_MULTIPLE;

    // If mStartActivity does not have a task associated with it, associate it with the
    // reused activity's task. Do not do so if we're clearing top and resetting for a
    // standard launchMode activity.
    if (mStartActivity.getTask() == null && !clearTopAndResetStandardLaunchMode) {
        mStartActivity.setTask(reusedActivity.getTask());
    }

    if (reusedActivity.getTask().intent == null) {
        // This task was started because of movement of the activity based on affinity...
        // Now that we are actually launching it, we can assign the base intent.
        reusedActivity.getTask().setIntent(mStartActivity);
    }

    // This code path leads to delivering a new intent, we want to make sure we schedule it
    // as the first operation, in case the activity will be resumed as a result of later
    // operations.
    if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
            || isDocumentLaunchesIntoExisting(mLaunchFlags)
            || isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK)) {
        final TaskRecord task = reusedActivity.getTask();

        // In this situation we want to remove all activities from the task up to the one
        // being started. In most cases this means we are resetting the task to its initial
        // state.
        final ActivityRecord top = task.performClearTaskForReuseLocked(mStartActivity,
                mLaunchFlags);

        // The above code can remove {@code reusedActivity} from the task, leading to the
        // the {@code ActivityRecord} removing its reference to the {@code TaskRecord}. The
        // task reference is needed in the call below to
        // {@link setTargetStackAndMoveToFrontIfNeeded}.
        if (reusedActivity.getTask() == null) {
            reusedActivity.setTask(task);
        }

        if (top != null) {
            if (top.frontOfTask) {
                // Activity aliases may mean we use different intents for the top activity,
                // so make sure the task now has the identity of the new intent.
                top.getTask().setIntent(mStartActivity);
            }
            deliverNewIntent(top);
        }
    }

    mSupervisor.sendPowerHintForLaunchStartIfNeeded(false /* forceSend */, reusedActivity);

    reusedActivity = setTargetStackAndMoveToFrontIfNeeded(reusedActivity);

    final ActivityRecord outResult =
            outActivity != null && outActivity.length > 0 ? outActivity[0] : null;

    // When there is a reused activity and the current result is a trampoline activity,
    // set the reused activity as the result.
    if (outResult != null && (outResult.finishing || outResult.noDisplay)) {
        outActivity[0] = reusedActivity;
    }

    if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
        // We don't need to start a new activity, and the client said not to do anything
        // if that is the case, so this is it!  And for paranoia, make sure we have
        // correctly resumed the top activity.
        resumeTargetStackIfNeeded();
        return START_RETURN_INTENT_TO_CALLER;
    }

    if (reusedActivity != null) {
        setTaskFromIntentActivity(reusedActivity);

        if (!mAddingToTask && mReuseTask == null) {
            // We didn't do anything...  but it was needed (a.k.a., client don't use that
            // intent!)  And for paranoia, make sure we have correctly resumed the top activity.

            resumeTargetStackIfNeeded();
            if (outActivity != null && outActivity.length > 0) {
                outActivity[0] = reusedActivity;
            }

            return mMovedToFront ? START_TASK_TO_FRONT : START_DELIVERED_TO_TOP;
        }
    }
}

8. 检查class not found;

if (mStartActivity.packageName == null) {
    final ActivityStack sourceStack = mStartActivity.resultTo != null
            ? mStartActivity.resultTo.getStack() : null;
    if (sourceStack != null) {
        sourceStack.sendActivityResultLocked(-1 /* callingUid */, mStartActivity.resultTo,
                mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED,
                null /* data */);
    }
    ActivityOptions.abort(mOptions);
    return START_CLASS_NOT_FOUND;
}

9. 对SINGLE_TOP做的CASE处理;

// If the activity being launched is the same as the one currently at the top, then
// we need to check if it should only be launched once.
final ActivityStack topStack = mSupervisor.mFocusedStack;
final ActivityRecord topFocused = topStack.getTopActivity();
final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);
final boolean dontStart = top != null && mStartActivity.resultTo == null
        && top.realActivity.equals(mStartActivity.realActivity)
        && top.userId == mStartActivity.userId
        && top.app != null && top.app.thread != null
        && ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
        || isLaunchModeOneOf(LAUNCH_SINGLE_TOP, LAUNCH_SINGLE_TASK));
if (dontStart) {
    // For paranoia, make sure we have correctly resumed the top activity.
    topStack.mLastPausedActivity = null;
    if (mDoResume) {
        mSupervisor.resumeFocusedStackTopActivityLocked();
    }
    ActivityOptions.abort(mOptions);
    if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
        // We don't need to start a new activity, and the client said not to do
        // anything if that is the case, so this is it!
        return START_RETURN_INTENT_TO_CALLER;
    }

    deliverNewIntent(top);

    // Don't use mStartActivity.task to show the toast. We're not starting a new activity
    // but reusing 'top'. Fields in mStartActivity may not be fully initialized.
    mSupervisor.handleNonResizableTaskIfNeeded(top.getTask(), preferredWindowingMode,
            preferredLaunchDisplayId, topStack);

    return START_DELIVERED_TO_TOP;
}

10. 根据情况选择task,并将其带到前台;如果是new task,就需要创建新的;

boolean newTask = false;
final TaskRecord taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
        ? mSourceRecord.getTask() : null;

// Should this be considered a new task?
int result = START_SUCCESS;
if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
        && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
    newTask = true;
    result = setTaskFromReuseOrCreateNewTask(taskToAffiliate, topStack);
} else if (mSourceRecord != null) {
    result = setTaskFromSourceRecord();
} else if (mInTask != null) {
    result = setTaskFromInTask();
} else {
    // This not being started from an existing activity, and not part of a new task...
    // just put it in the top task, though these days this case should never happen.
    setTaskToCurrentTopOrCreateNewTask();
}
if (result != START_SUCCESS) {
    return result;
}

11. 给予UriPermission;

mService.grantUriPermissionFromIntentLocked(mCallingUid, mStartActivity.packageName,
        mIntent, mStartActivity.getUriPermissionsLocked(), mStartActivity.userId);

12. emmm

mService.grantEphemeralAccessLocked(mStartActivity.userId, mIntent,
        mStartActivity.appInfo.uid, UserHandle.getAppId(mCallingUid));

13. 打LOG

if (newTask) {
    EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, mStartActivity.userId,
            mStartActivity.getTask().taskId);
}
ActivityStack.logStartActivity(
        EventLogTags.AM_CREATE_ACTIVITY, mStartActivity, mStartActivity.getTask());

14. 将mLastPausedActivity 置为null;

mTargetStack.mLastPausedActivity = null;
/**
 * This is the last activity that we put into the paused state.  This is
 * used to determine if we need to do an activity transition while sleeping,
 * when we normally hold the top activity paused.
 */
ActivityRecord mLastPausedActivity = null;

15. emmmm

mSupervisor.sendPowerHintForLaunchStartIfNeeded(false /* forceSend */, mStartActivity);

16. 启动Activity

mTargetStack.startActivityLocked(mStartActivity, topFocused, newTask, mKeepCurTransition,
        mOptions);

17. Resume

if (mDoResume) {
    final ActivityRecord topTaskActivity =
            mStartActivity.getTask().topRunningActivityLocked();
    if (!mTargetStack.isFocusable()
            || (topTaskActivity != null && topTaskActivity.mTaskOverlay
            && 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.
        mTargetStack.ensureActivitiesVisibleLocked(null, 0, !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.
        mService.mWindowManager.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.isFocusable() && !mSupervisor.isFocusedStack(mTargetStack)) {
            mTargetStack.moveToFront("startActivityUnchecked");
        }
        mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
                mOptions);
    }
} else if (mStartActivity != null) {
    mSupervisor.mRecentTasks.add(mStartActivity.getTask());
}

18. 更新stack的userId

mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
/**
 * Update the last used stack id for non-current user (current user's last
 * used stack is the focused stack)
 */
void updateUserStackLocked(int userId, ActivityStack stack) {
    if (userId != mCurrentUser) {
        mUserStackInFront.put(userId, stack != null ? stack.getStackId() : mHomeStack.mStackId);
    }
}

19. 处理分屏

mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTask(), preferredWindowingMode,
        preferredLaunchDisplayId, mTargetStack);

 

startActivityUnchecked的内容很多;后面再摘取有趣的部分深入的阅读;

mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
                mOptions);
targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);

mFocusedStack.resumeTopActivityUncheckedLocked(null, null);

private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options)
mStackSupervisor.startSpecificActivityLocked(next, true, true);

final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
            boolean andResume, boolean checkConfig) throws RemoteException

 

你可能感兴趣的:(Android)