美文网首页
Activity的启动过程分析

Activity的启动过程分析

作者: zyc_214 | 来源:发表于2018-10-08 16:03 被阅读0次

    Activity的启动过程分析

    本次分析的源码基于SDK24
    Activity的启动过程:


    5307960-6e9e56aac1703347.png
    1. 一般在启动一个Activity的时候使用startActivity,所有这次就从startActivity为入口进行分析,最后会调用startActivityForResult方法以下:
    public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
                @Nullable Bundle options) {
            //判断是否有父Activity
            if (mParent == null) {
                options = transferSpringboardActivityOptions(options);
                //真正的调用
                Instrumentation.ActivityResult ar =
                    mInstrumentation.execStartActivity(
                        this, mMainThread.getApplicationThread(), mToken, this,
                        intent, requestCode, options);
                if (ar != null) {
                    //返回相应的的结果调用onActivityResult(requestCode, resultCode, data);
                    mMainThread.sendActivityResult(
                        mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                        ar.getResultData());
                }
                if (requestCode >= 0) {
                    // If this start is requesting a result, we can avoid making
                    // the activity visible until the result is received.  Setting
                    // this code during onCreate(Bundle savedInstanceState) or onResume() will keep the
                    // activity hidden during this time, to avoid flickering.
                    // This can only be done when a result is requested because
                    // that guarantees we will get information back when the
                    // activity is finished, no matter what happens to it.
                    mStartedActivity = true;
                }
    
                cancelInputsAndStartExitTransition(options);
                // TODO Consider clearing/flushing other event sources and events for child windows.
            } else {
                if (options != null) {
                    mParent.startActivityFromChild(this, intent, requestCode, options);
                } else {
                    // Note we want to go through this method for compatibility with
                    // existing applications that may have overridden it.
                    mParent.startActivityFromChild(this, intent, requestCode);
                }
            }
        }
    
    1. Instrumentation.execStartActivity()
    public ActivityResult execStartActivity(
                Context who, IBinder contextThread, IBinder token, Activity target,
                Intent intent, int requestCode, Bundle options) {
            IApplicationThread whoThread = (IApplicationThread) contextThread;
            //设置提供来源
            Uri referrer = target != null ? target.onProvideReferrer() : null;
            if (referrer != null) {
                intent.putExtra(Intent.EXTRA_REFERRER, referrer);
            }
            //Activity的监视器
            if (mActivityMonitors != null) {
                synchronized (mSync) {
                    final int N = mActivityMonitors.size();
                    for (int i=0; i<N; i++) {
                        //判断当前是否有匹配的,顺便更新击中数
                        final ActivityMonitor am = mActivityMonitors.get(i);
                        ActivityResult result = null;
                        if (am.ignoreMatchingSpecificIntents()) {
                            result = am.onStartActivity(intent);
                        }
                        if (result != null) {
                            am.mHits++;
                            return result;
                        } else if (am.match(who, null, intent)) {
                            am.mHits++;
                            if (am.isBlocking()) {
                                return requestCode >= 0 ? am.getResult() : null;
                            }
                            break;
                        }
                    }
                }
            }
            try {
                intent.migrateExtraStreamToClipData();
                intent.prepareToLeaveProcess(who);
                //最终调到AMS中
                int result = ActivityManager.getService()
                    .startActivity(whoThread, who.getBasePackageName(), 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;
        }
    
    1. 调到AMS中执行startActivity>startActivityAsUser>startActivityAsUser:
    public final int startActivity(IApplicationThread caller, String callingPackage,
                Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
                int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
           //传入caller的UserID用于验证相关权限
            return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
                    resultWho, requestCode, startFlags, profilerInfo, bOptions,
                    UserHandle.getCallingUserId());
        }
    
    public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
                Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
                int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId,
                boolean validateIncomingUser) {
            enforceNotIsolatedCaller("startActivity");
           //检测当前用户
            userId = mActivityStartController.checkTargetUser(userId, validateIncomingUser,
                    Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser");
            //创建一个ActivityStarter该类主要用于把将Intent和Flag转化为相应的请求
            // TODO: Switch to user app stacks here.
            return mActivityStartController.obtainStarter(intent, "startActivityAsUser")
                    .setCaller(caller)
                    .setCallingPackage(callingPackage)
                    .setResolvedType(resolvedType)
                    .setResultTo(resultTo)
                    .setResultWho(resultWho)
                    .setRequestCode(requestCode)
                    .setStartFlags(startFlags)
                    .setProfilerInfo(profilerInfo)
                    .setActivityOptions(bOptions)
                    .setMayWait(userId)
                    .execute();
    
        }
    

    4.随后调用ActivityStarter.execute()
    ActivityStarter的解释:

    Controller for interpreting how and then launching an activity.This class collects all the logic for determining how an intent and flags should be turned into an activity and associated task and stack.

    自己理解为是一个Activity的启动器,根据Intent和flags来打开Activity已经关联的栈信息。

    int execute() {
            try {
                // TODO(b/64750076): Look into passing request directly to these methods to allow
                // for transactional diffs and preprocessing.
                //当前为true在setMayWait中赋值
                if (mRequest.mayWait) {
                    return startActivityMayWait(mRequest.caller, mRequest.callingUid,
                            mRequest.callingPackage, mRequest.intent, mRequest.resolvedType,
                            mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo,
                            mRequest.resultWho, mRequest.requestCode, mRequest.startFlags,
                            mRequest.profilerInfo, mRequest.waitResult, mRequest.globalConfig,
                            mRequest.activityOptions, mRequest.ignoreTargetSecurity, mRequest.userId,
                            mRequest.inTask, mRequest.reason,
                            mRequest.allowPendingRemoteAnimationRegistryLookup);
                } else {
                    return startActivity(mRequest.caller, mRequest.intent, mRequest.ephemeralIntent,
                            mRequest.resolvedType, mRequest.activityInfo, mRequest.resolveInfo,
                            mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo,
                            mRequest.resultWho, mRequest.requestCode, mRequest.callingPid,
                            mRequest.callingUid, mRequest.callingPackage, mRequest.realCallingPid,
                            mRequest.realCallingUid, mRequest.startFlags, mRequest.activityOptions,
                            mRequest.ignoreTargetSecurity, mRequest.componentSpecified,
                            mRequest.outActivity, mRequest.inTask, mRequest.reason,
                            mRequest.allowPendingRemoteAnimationRegistryLookup);
                }
            } finally {
                onExecutionComplete();
            }
        }
    

    5.在ActivityStarter中经过一系列操作后最终调用到startActivityUnchecked()主要处理栈的相关逻辑:

    private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
                IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
                int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
                ActivityRecord[] outActivity) {
            //设置当前的初始状态,包括来源页面信息sourceRecord、inTask
            setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
                    voiceInteractor);
            //根据来源ActivityRecord、Task来判断启动task信息
            computeLaunchingTaskFlags();
            //判断来源的task信息
            computeSourceStack();
           //设置启动flag
            mIntent.setFlags(mLaunchFlags);
            //获取启动Activity如果满足复用就使用之前的
            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;
           // 比较熟悉的FLAG_ACTIVITY_NEW_TASK,如果设置就会新砌一个Task
            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;
        }
    

    6.最后跳转到ActivityStackSupervisor.resumeFocusedStackTopActivityLocked()方法:

    boolean resumeFocusedStackTopActivityLocked(
                ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
    
            if (!readyToResume()) {
                return false;
            }
    
            if (targetStack != null && isFocusedStack(targetStack)) {
                return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
            }
    
            final ActivityRecord r = mFocusedStack.topRunningActivityLocked();
           //判断当前的状态,当前状态为INITIALIZING
            if (r == null || !r.isState(RESUMED)) {
                //ActivityStack中
                mFocusedStack.resumeTopActivityUncheckedLocked(null, null);
            } else if (r.isState(RESUMED)) {
                // Kick off any lingering app transitions form the MoveTaskToFront operation.
                mFocusedStack.executeAppTransition(targetOptions);
            }
    
            return false;
        }
    

    7.在ActivityStack.resumeTopActivityInnerLocked()

    @GuardedBy("mService")
        private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
            if (!mService.mBooting && !mService.mBooted) {
                // Not ready yet!
                return false;
            }
    
            // Find the next top-most activity to resume in this stack that is not finishing and is
            // focusable. If it is not focusable, we will fall into the case below to resume the
            // top activity in the next focusable task.
            //获取现在栈顶的ActivityRecord
            final ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */);
    
            final boolean hasRunningActivity = next != null;
    
            // TODO: Maybe this entire condition can get removed?
            if (hasRunningActivity && !isAttached()) {
                return false;
            }
    
            mStackSupervisor.cancelInitializingActivities();
    
            // Remember how we'll process this pause/resume situation, and ensure
            // that the state is reset however we wind up proceeding.
            boolean userLeaving = mStackSupervisor.mUserLeaving;
            mStackSupervisor.mUserLeaving = false;
            //当前的栈内查不到
            if (!hasRunningActivity) {
                // There are no activities left in the stack, let's look somewhere else.
                return resumeTopActivityInNextFocusableStack(prev, options, "noMoreActivities");
            }
    
            next.delayedResume = false;
    
            // If the top activity is the resumed one, nothing to do.
            //判断当前显示的和将要启动的是否一致判断是否是恢复Activity
            if (mResumedActivity == next && next.isState(RESUMED)
                    && mStackSupervisor.allResumedActivitiesComplete()) {
                // Make sure we have executed any pending transitions, since there
                // should be nothing left to do at this point.
                executeAppTransition(options);
                if (DEBUG_STATES) Slog.d(TAG_STATES,
                        "resumeTopActivityLocked: Top activity resumed " + next);
                if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
                return false;
            }
    
            // If we are sleeping, and there is no resumed activity, and the top
            // activity is paused, well that is the state we want.
            if (shouldSleepOrShutDownActivities()
                    && mLastPausedActivity == next
                    && mStackSupervisor.allPausedActivitiesComplete()) {
                // Make sure we have executed any pending transitions, since there
                // should be nothing left to do at this point.
                executeAppTransition(options);
                if (DEBUG_STATES) Slog.d(TAG_STATES,
                        "resumeTopActivityLocked: Going to sleep and all paused");
                if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
                return false;
            }
    
            // Make sure that the user who owns this activity is started.  If not,
            // we will just leave it as is because someone should be bringing
            // another user's activities to the top of the stack.
            if (!mService.mUserController.hasStartedUserState(next.userId)) {
                Slog.w(TAG, "Skipping resume of top activity " + next
                        + ": user " + next.userId + " is stopped");
                if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
                return false;
            }
    
            // The activity may be waiting for stop, but that is no longer
            // appropriate for it.
            mStackSupervisor.mStoppingActivities.remove(next);
            mStackSupervisor.mGoingToSleepActivities.remove(next);
            next.sleeping = false;
            mStackSupervisor.mActivitiesWaitingForVisibleActivity.remove(next);
    
            if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resuming " + next);
    
            // If we are currently pausing an activity, then don't do anything until that is done.
            if (!mStackSupervisor.allPausedActivitiesComplete()) {
                if (DEBUG_SWITCH || DEBUG_PAUSE || DEBUG_STATES) Slog.v(TAG_PAUSE,
                        "resumeTopActivityLocked: Skip resume: some activity pausing.");
                if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
                return false;
            }
    
            mStackSupervisor.setLaunchSource(next.info.applicationInfo.uid);
    
            boolean lastResumedCanPip = false;
            ActivityRecord lastResumed = null;
            final ActivityStack lastFocusedStack = mStackSupervisor.getLastStack();
            if (lastFocusedStack != null && lastFocusedStack != this) {
                // So, why aren't we using prev here??? See the param comment on the method. prev doesn't
                // represent the last resumed activity. However, the last focus stack does if it isn't null.
                lastResumed = lastFocusedStack.mResumedActivity;
                if (userLeaving && inMultiWindowMode() && lastFocusedStack.shouldBeVisible(next)) {
                    // The user isn't leaving if this stack is the multi-window mode and the last
                    // focused stack should still be visible.
                    if(DEBUG_USER_LEAVING) Slog.i(TAG_USER_LEAVING, "Overriding userLeaving to false"
                            + " next=" + next + " lastResumed=" + lastResumed);
                    userLeaving = false;
                }
                lastResumedCanPip = lastResumed != null && lastResumed.checkEnterPictureInPictureState(
                        "resumeTopActivity", userLeaving /* beforeStopping */);
            }
            // If the flag RESUME_WHILE_PAUSING is set, then continue to schedule the previous activity
            // to be paused, while at the same time resuming the new resume activity only if the
            // previous activity can't go into Pip since we want to give Pip activities a chance to
            // enter Pip before resuming the next activity.
            final boolean resumeWhilePausing = (next.info.flags & FLAG_RESUME_WHILE_PAUSING) != 0
                    && !lastResumedCanPip;
    
            boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, next, false);
            if (mResumedActivity != null) {
                if (DEBUG_STATES) Slog.d(TAG_STATES,
                        "resumeTopActivityLocked: Pausing " + mResumedActivity);
                pausing |= startPausingLocked(userLeaving, false, next, false);
            }
            if (pausing && !resumeWhilePausing) {
                if (DEBUG_SWITCH || DEBUG_STATES) Slog.v(TAG_STATES,
                        "resumeTopActivityLocked: Skip resume: need to start pausing");
                // At this point we want to put the upcoming activity's process
                // at the top of the LRU list, since we know we will be needing it
                // very soon and it would be a waste to let it get killed if it
                // happens to be sitting towards the end.
                if (next.app != null && next.app.thread != null) {
                    mService.updateLruProcessLocked(next.app, true, null);
                }
                if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
                if (lastResumed != null) {
                    lastResumed.setWillCloseOrEnterPip(true);
                }
                return true;
            } else if (mResumedActivity == next && next.isState(RESUMED)
                    && mStackSupervisor.allResumedActivitiesComplete()) {
                // It is possible for the activity to be resumed when we paused back stacks above if the
                // next activity doesn't have to wait for pause to complete.
                // So, nothing else to-do except:
                // Make sure we have executed any pending transitions, since there
                // should be nothing left to do at this point.
                executeAppTransition(options);
                if (DEBUG_STATES) Slog.d(TAG_STATES,
                        "resumeTopActivityLocked: Top activity resumed (dontWaitForPause) " + next);
                if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
                return true;
            }
    
            // If the most recent activity was noHistory but was only stopped rather
            // than stopped+finished because the device went to sleep, we need to make
            // sure to finish it as we're making a new activity topmost.
            if (shouldSleepActivities() && mLastNoHistoryActivity != null &&
                    !mLastNoHistoryActivity.finishing) {
                if (DEBUG_STATES) Slog.d(TAG_STATES,
                        "no-history finish of " + mLastNoHistoryActivity + " on new resume");
                requestFinishActivityLocked(mLastNoHistoryActivity.appToken, Activity.RESULT_CANCELED,
                        null, "resume-no-history", false);
                mLastNoHistoryActivity = null;
            }
    
            if (prev != null && prev != next) {
                if (!mStackSupervisor.mActivitiesWaitingForVisibleActivity.contains(prev)
                        && next != null && !next.nowVisible) {
                    mStackSupervisor.mActivitiesWaitingForVisibleActivity.add(prev);
                    if (DEBUG_SWITCH) Slog.v(TAG_SWITCH,
                            "Resuming top, waiting visible to hide: " + prev);
                } else {
                    // The next activity is already visible, so hide the previous
                    // activity's windows right now so we can show the new one ASAP.
                    // We only do this if the previous is finishing, which should mean
                    // it is on top of the one being resumed so hiding it quickly
                    // is good.  Otherwise, we want to do the normal route of allowing
                    // the resumed activity to be shown so we can decide if the
                    // previous should actually be hidden depending on whether the
                    // new one is found to be full-screen or not.
                    if (prev.finishing) {
                        prev.setVisibility(false);
                        if (DEBUG_SWITCH) Slog.v(TAG_SWITCH,
                                "Not waiting for visible to hide: " + prev + ", waitingVisible="
                                + mStackSupervisor.mActivitiesWaitingForVisibleActivity.contains(prev)
                                + ", nowVisible=" + next.nowVisible);
                    } else {
                        if (DEBUG_SWITCH) Slog.v(TAG_SWITCH,
                                "Previous already visible but still waiting to hide: " + prev
                                + ", waitingVisible="
                                + mStackSupervisor.mActivitiesWaitingForVisibleActivity.contains(prev)
                                + ", nowVisible=" + next.nowVisible);
                    }
                }
            }
    
            // Launching this app's activity, make sure the app is no longer
            // considered stopped.
            try {
                AppGlobals.getPackageManager().setPackageStoppedState(
                        next.packageName, false, next.userId); /* TODO: Verify if correct userid */
            } catch (RemoteException e1) {
            } catch (IllegalArgumentException e) {
                Slog.w(TAG, "Failed trying to unstop package "
                        + next.packageName + ": " + e);
            }
    
            // We are starting up the next activity, so tell the window manager
            // that the previous one will be hidden soon.  This way it can know
            // to ignore it when computing the desired screen orientation.
           //是否需要执行动画
            boolean anim = true;
            if (prev != null) {
                if (prev.finishing) {
                    if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION,
                            "Prepare close transition: prev=" + prev);
                    if (mStackSupervisor.mNoAnimActivities.contains(prev)) {
                        anim = false;
                        mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
                    } else {
                        mWindowManager.prepareAppTransition(prev.getTask() == next.getTask()
                                ? TRANSIT_ACTIVITY_CLOSE
                                : TRANSIT_TASK_CLOSE, false);
                    }
                    prev.setVisibility(false);
                } else {
                    if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION,
                            "Prepare open transition: prev=" + prev);
                    if (mStackSupervisor.mNoAnimActivities.contains(next)) {
                        anim = false;
                        mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
                    } else {
                        mWindowManager.prepareAppTransition(prev.getTask() == next.getTask()
                                ? TRANSIT_ACTIVITY_OPEN
                                : next.mLaunchTaskBehind
                                        ? TRANSIT_TASK_OPEN_BEHIND
                                        : TRANSIT_TASK_OPEN, false);
                    }
                }
            } else {
                if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "Prepare open transition: no previous");
                if (mStackSupervisor.mNoAnimActivities.contains(next)) {
                    anim = false;
                    mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
                } else {
                    mWindowManager.prepareAppTransition(TRANSIT_ACTIVITY_OPEN, false);
                }
            }
    
            if (anim) {
                next.applyOptionsLocked();
            } else {
                next.clearOptionsLocked();
            }
    
            mStackSupervisor.mNoAnimActivities.clear();
    
            ActivityStack lastStack = mStackSupervisor.getLastStack();
            //如果Activity所在的进程已经存在
            if (next.app != null && next.app.thread != null) {
                if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resume running: " + next
                        + " stopped=" + next.stopped + " visible=" + next.visible);
    
                // If the previous activity is translucent, force a visibility update of
                // the next activity, so that it's added to WM's opening app list, and
                // transition animation can be set up properly.
                // For example, pressing Home button with a translucent activity in focus.
                // Launcher is already visible in this case. If we don't add it to opening
                // apps, maybeUpdateTransitToWallpaper() will fail to identify this as a
                // TRANSIT_WALLPAPER_OPEN animation, and run some funny animation.
                final boolean lastActivityTranslucent = lastStack != null
                        && (lastStack.inMultiWindowMode()
                        || (lastStack.mLastPausedActivity != null
                        && !lastStack.mLastPausedActivity.fullscreen));
    
                // The contained logic must be synchronized, since we are both changing the visibility
                // and updating the {@link Configuration}. {@link ActivityRecord#setVisibility} will
                // ultimately cause the client code to schedule a layout. Since layouts retrieve the
                // current {@link Configuration}, we must ensure that the below code updates it before
                // the layout can occur.
                synchronized(mWindowManager.getWindowManagerLock()) {
                    // This activity is now becoming visible.
                    if (!next.visible || next.stopped || lastActivityTranslucent) {
                        next.setVisibility(true);
                    }
    
                    // schedule launch ticks to collect information about slow apps.
                    next.startLaunchTickingLocked();
    
                    ActivityRecord lastResumedActivity =
                            lastStack == null ? null :lastStack.mResumedActivity;
                    final ActivityState lastState = next.getState();
    
                    mService.updateCpuStats();
    
                    if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to RESUMED: " + next
                            + " (in existing)");
                    //用于更新当前状态
                    next.setState(RESUMED, "resumeTopActivityInnerLocked");
    
                    mService.updateLruProcessLocked(next.app, true, null);
                    updateLRUListLocked(next);
                    mService.updateOomAdjLocked();
    
                    // Have the window manager re-evaluate the orientation of
                    // the screen based on the new activity order.
                    boolean notUpdated = true;
    
                    if (mStackSupervisor.isFocusedStack(this)) {
                        // We have special rotation behavior when here is some active activity that
                        // requests specific orientation or Keyguard is locked. Make sure all activity
                        // visibilities are set correctly as well as the transition is updated if needed
                        // to get the correct rotation behavior. Otherwise the following call to update
                        // the orientation may cause incorrect configurations delivered to client as a
                        // result of invisible window resize.
                        // TODO: Remove this once visibilities are set correctly immediately when
                        // starting an activity.
                        notUpdated = !mStackSupervisor.ensureVisibilityAndConfig(next, mDisplayId,
                                true /* markFrozenIfConfigChanged */, false /* deferResume */);
                    }
    
                    if (notUpdated) {
                        // The configuration update wasn't able to keep the existing
                        // instance of the activity, and instead started a new one.
                        // We should be all done, but let's just make sure our activity
                        // is still at the top and schedule another run if something
                        // weird happened.
                        ActivityRecord nextNext = topRunningActivityLocked();
                        if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG_STATES,
                                "Activity config changed during resume: " + next
                                        + ", new next: " + nextNext);
                        if (nextNext != next) {
                            // Do over!
                            mStackSupervisor.scheduleResumeTopActivities();
                        }
                        if (!next.visible || next.stopped) {
                            next.setVisibility(true);
                        }
                        next.completeResumeLocked();
                        if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
                        return true;
                    }
    
                    try {
                        final ClientTransaction transaction = ClientTransaction.obtain(next.app.thread,
                                next.appToken);
                        // Deliver all pending results.
                        ArrayList<ResultInfo> a = next.results;
                        if (a != null) {
                            final int N = a.size();
                            if (!next.finishing && N > 0) {
                                if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
                                        "Delivering results to " + next + ": " + a);
                                transaction.addCallback(ActivityResultItem.obtain(a));
                            }
                        }
    
                        if (next.newIntents != null) {
                            transaction.addCallback(NewIntentItem.obtain(next.newIntents,
                                    false /* andPause */));
                        }
    
                        // Well the app will no longer be stopped.
                        // Clear app token stopped state in window manager if needed.
                        next.notifyAppResumed(next.stopped);
    
                        EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY, next.userId,
                                System.identityHashCode(next), next.getTask().taskId,
                                next.shortComponentName);
                        //是否睡眠
                        next.sleeping = false;
                        mService.getAppWarningsLocked().onResumeActivity(next);
                        mService.showAskCompatModeDialogLocked(next);
                        next.app.pendingUiClean = true;
                        next.app.forceProcessStateUpTo(mService.mTopProcessState);
                        next.clearOptionsLocked();
                        transaction.setLifecycleStateRequest(
                                ResumeActivityItem.obtain(next.app.repProcState,
                                        mService.isNextTransitionForward()));
                        mService.getLifecycleManager().scheduleTransaction(transaction);
    
                        if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Resumed "
                                + next);
                    } catch (Exception e) {
                        // Whoops, need to restart this activity!
                        if (DEBUG_STATES) Slog.v(TAG_STATES, "Resume failed; resetting state to "
                                + lastState + ": " + next);
                        next.setState(lastState, "resumeTopActivityInnerLocked");
    
                        // lastResumedActivity being non-null implies there is a lastStack present.
                        if (lastResumedActivity != null) {
                            lastResumedActivity.setState(RESUMED, "resumeTopActivityInnerLocked");
                        }
    
                        Slog.i(TAG, "Restarting because process died: " + next);
                        if (!next.hasBeenLaunched) {
                            next.hasBeenLaunched = true;
                        } else  if (SHOW_APP_STARTING_PREVIEW && lastStack != null
                                && lastStack.isTopStackOnDisplay()) {
                            next.showStartingWindow(null /* prev */, false /* newTask */,
                                    false /* taskSwitch */);
                        }
                        mStackSupervisor.startSpecificActivityLocked(next, true, false);
                        if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
                        return true;
                    }
                }
    
                // From this point on, if something goes wrong there is no way
                // to recover the activity.
                try {
                    next.completeResumeLocked();
                } catch (Exception e) {
                    // If any exception gets thrown, toss away this
                    // activity and try the next one.
                    Slog.w(TAG, "Exception thrown during resume of " + next, e);
                    requestFinishActivityLocked(next.appToken, Activity.RESULT_CANCELED, null,
                            "resume-exception", true);
                    if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
                    return true;
                }
            } else {
                // Whoops, need to restart this activity!
                if (!next.hasBeenLaunched) {
                    next.hasBeenLaunched = true;
                } else {
                    if (SHOW_APP_STARTING_PREVIEW) {
                        next.showStartingWindow(null /* prev */, false /* newTask */,
                                false /* taskSwich */);
                    }
                    if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Restarting: " + next);
                }
                if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Restarting " + next);
                mStackSupervisor.startSpecificActivityLocked(next, true, true);
            }
    
            if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
            return true;
        }
    
    1. 最终执行到mStackSupervisor.startSpecificActivityLocked();
    void startSpecificActivityLocked(ActivityRecord r,
                boolean andResume, boolean checkConfig) {
            // Is this activity's application already running?
           //获取当前进程
            ProcessRecord app = mService.getProcessRecordLocked(r.processName,
                    r.info.applicationInfo.uid, true);
    
            getLaunchTimeTracker().setLaunchTime(r);
            //判断当前进程状态
            if (app != null && app.thread != null) {
                try {
                    if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
                            || !"android".equals(r.info.packageName)) {
                        // Don't add this if it is a platform component that is marked
                        // to run in multiple processes, because this is actually
                        // part of the framework so doesn't make sense to track as a
                        // separate apk in the process.
                        app.addPackage(r.info.packageName, r.info.applicationInfo.longVersionCode,
                                mService.mProcessStats);
                    }
                   //启动Activity
                    realStartActivityLocked(r, app, andResume, checkConfig);
                    return;
                } catch (RemoteException e) {
                    Slog.w(TAG, "Exception when starting activity "
                            + r.intent.getComponent().flattenToShortString(), e);
                }
    
                // If a dead object exception was thrown -- fall through to
                // restart the application.
            }
    
            mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
                    "activity", r.intent.getComponent(), false, false, true);
        }
    
    

    8.realStartActivityLocked核心内容

                    // 创建一个启动Activity的事务
                    final ClientTransaction clientTransaction = ClientTransaction.obtain(app.thread,
                            r.appToken);
                    //添加回调用于启动Activity
                    clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),
                            System.identityHashCode(r), r.info,
                            // TODO: Have this take the merged configuration instead of separate global
                            // and override configs.
                            mergedConfiguration.getGlobalConfiguration(),
                            mergedConfiguration.getOverrideConfiguration(), r.compat,
                            r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
                            r.persistentState, results, newIntents, mService.isNextTransitionForward(),
                            profilerInfo));
    
                    // Set desired final state.
                    final ActivityLifecycleItem lifecycleItem;
                    if (andResume) {
                        lifecycleItem = ResumeActivityItem.obtain(mService.isNextTransitionForward());
                    } else {
                        lifecycleItem = PauseActivityItem.obtain();
                    }
                    clientTransaction.setLifecycleStateRequest(lifecycleItem);
    
                    // Schedule transaction.
                    //开始执行
                    mService.getLifecycleManager().scheduleTransaction(clientTransaction);
    

    9.跳转到ClientLifecycleManager.scheduleTransaction()

    void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
            final IApplicationThread client = transaction.getClient();
            transaction.schedule();
            if (!(client instanceof Binder)) {
                // If client is not an instance of Binder - it's a remote call and at this point it is
                // safe to recycle the object. All objects used for local calls will be recycled after
                // the transaction is executed on client in ActivityThread.
                transaction.recycle();
            }
        }
    
    case EXECUTE_TRANSACTION:
                        final ClientTransaction transaction = (ClientTransaction) msg.obj;
                        mTransactionExecutor.execute(transaction);
                        if (isSystem()) {
                            // Client transactions inside system process are recycled on the client side
                            // instead of ClientLifecycleManager to avoid being cleared before this
                            // message is handled.
                            transaction.recycle();
                        }
                        // TODO(lifecycler): Recycle locally scheduled transactions.
                        break;
    

    相关文章

      网友评论

          本文标题:Activity的启动过程分析

          本文链接:https://www.haomeiwen.com/subject/sarjaftx.html