[Android]AMS源码分析(一)Activity生命周期管理

参考资料

AMS源码分析(一)Activity生命周期管理
AMS源码分析(二)onActivityResult执行过程

1. 前言

AMS(ActivityManagerService)是Activity管理的核心组件,提供了Activity的启动、生命周期管理、栈管理等功能,熟悉AMS会对我们认识Activity的工作原理有很大的帮助。当前比较成熟的插件化技术,也是通过对Activity启动流程中的重要组件(如Instrumentation或主线程Handler等)进行Hook完成的,掌握AMS对我们学习插件化技术也有很大的帮助

AMS中内容很多,对它的分析也不可能面面俱到,我期望从Activity的启动、Activity消息回传(onActivityResult)、Activity栈管理、AMS与WMS和PMS的协同工作方面入手,希望本系列文章完成后可以对AMS有一个更新的认识

2. Activity的生命周期

2.1. 一个Activity从启动到销毁所经历的周期

onCreate -> onStart -> onResume -> onPause -> onStop -> onDestory

这属于Android最基础的知识,就不再赘述了

2.2. 从一个Activity启动另一个Activity的生命周期

现在有两个Activity,分别是AActivity和BActivity,如果从AActivity跳转到BActivity,那么它们的生命周期会是下面这个样子:

AActivity#onPause -> BActivity#onCreate -> BActivity#onStart -> BActivity#onResume -> AActivity#onStop

如下图:

image.png

而从BActivity返回时,它们的生命周期是这样的:

BActivity#onPause -> AActivity#onStart -> AActivity#onResume -> BActivity#onStop -> BActivity#onDestroy

image.png

为什么是这样呢?下面我们从源码的角度去分析一下

3.源码分析

在做源码分析之前,我们要先理解两个概念

  • Android Binder IPC机制
  • Hander idleHandler机制

3.1. Binder

Binder是Android跨进程通信的核心,但不是本文的重点,这里不多做讲解,感兴趣的朋友可以看一下我之前写过的Binder系列文章:Binder系列

在本篇文章中,我们只需要知道每当看到类似mRemote.transact
这种调用时,既是跨进程通信的开始

3.2. IdleHandler

当消息队列空闲时会执行IdelHandler的queueIdle()方法,该方法返回一个boolean值,
如果为false则执行完毕之后移除这条消息,
如果为true则保留,等到下次空闲时会再次执行

也就是说,IdleHandler是Handler机制中MessageQueue空闲时才会执行的一种特殊Handler

3.3. Activity在AMS中的标识

每一个Activity实例在AMS中都会对应一个ActivityRecord,ActivityRecord对象是在Activity启动过程中创建的,每个ActivityRecord中又会有一个ProcessRecord标记Activity所在的进程

而在APP进程中,在Activity启动时,也会创建一个ActivityClientRecord,与AMS中的ActivityRecord遥相呼应。

Activity、ActivityClientRecord、ActivityRecord互相联系的纽带是一个token对象,它继承于IApplicationToken.Stub,这是一个Binder对象,在Activity、ActivityClientRecord、ActivityRecord中均有一份。

Activity、ActivityClientRecord、ActivityRecord之间的关系图大致如下---注意区分所在进程:

image.png

3.4. 启动过程时序图

黄色为APP进程,蓝色为AMS进程

image.png

3.5. 从AActivity跳转BActivity的生命周期分析

AMS的逻辑太多,本文只针对Activity声明周期相关的代码,其他相关逻辑后面几篇文章继续分析

从Activity开始

    public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
                                       @Nullable Bundle options) {
        if (mParent == null) {
            options = transferSpringboardActivityOptions(options);
            Instrumentation.ActivityResult ar =
                    mInstrumentation.execStartActivity(
                            this, mMainThread.getApplicationThread(), mToken, this,
                            intent, requestCode, options);
           
        } else {
   
        }
    }

Instrumentation#execStartActivity方法:

public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
        ...
        try {
            intent.migrateExtraStreamToClipData();
            intent.prepareToLeaveProcess(who);
            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;
    }

重要入参及含义:

  • who: 启动源Activity
  • contextThread : 宿主Activity的ApplicationThread
  • token:Activity的身份标识 -> Activity#mToken -> ActivityClientRecord#token -> ActivityRecord#appToken -> IApplicationToken.Stub
  • target: 哪个activity调用的start方法,因此这个Activity会接收任何的返回结果,如果start调用不是从Activity中发起的则有可能为null
  • intent: 启动Activity时的intent
  • requestCoode: 启动Activity时的requestCode
  • options: 启动Activity的选项

注意token参数,本文将重点追踪它的变化,这个参数非常重要,后面会有很多地方用到

继续走逻辑,在这里进行了IPC调用,从APP进程转入AMS进程执行,ActivityManager.getService() .startActivity调用在AMS进程对应的是ActivityManagerService#startActivity,我们看一下

ActivityManagerService#startActivity经过一系列的调用后,会走到ActivityStarter#startActivityMayWait

final int startActivityMayWait(IApplicationThread caller, int callingUid,
            int requestRealCallingPid, int requestRealCallingUid,
            String callingPackage, Intent intent, String resolvedType,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            IBinder resultTo, String resultWho, int requestCode, int startFlags,
            ProfilerInfo profilerInfo, WaitResult outResult,
            Configuration globalConfig, Bundle bOptions, boolean ignoreTargetSecurity, int userId,
            TaskRecord inTask, String reason) {

        ...

        // Collect information about the target of the Intent.
        // zhangyulong 解析Intent中的Activity信息
        ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);

        ...

            // zhangyulong 声明一个ActivityRecord数组
            final ActivityRecord[] outRecord = new ActivityRecord[1];
            int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,
                    aInfo, rInfo, voiceSession, voiceInteractor,
                    resultTo, resultWho, requestCode, callingPid,
                    callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
                    options, ignoreTargetSecurity, componentSpecified, outRecord, inTask,
                    reason);

            Binder.restoreCallingIdentity(origId);

           ...
            return res;
        }
    }

这里进行的工作是解析Intent信息,并继续调用startActivityLocked,注意入参中的resultTo就是从App进程传入的token,依旧是透传给startActivityLocked

    int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
            String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
            String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
            ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
            ActivityRecord[] outActivity, TaskRecord inTask, String reason) {

        if (TextUtils.isEmpty(reason)) {
            throw new IllegalArgumentException("Need to specify a reason.");
        }
        mLastStartReason = reason;
        mLastStartActivityTimeMs = System.currentTimeMillis();
        mLastStartActivityRecord[0] = null;

        mLastStartActivityResult = startActivity(caller, intent, ephemeralIntent, resolvedType,
                aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode,
                callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
                options, ignoreTargetSecurity, componentSpecified, mLastStartActivityRecord,
                inTask);

        if (outActivity != null) {
            // mLastStartActivityRecord[0] is set in the call to startActivity above.
            outActivity[0] = mLastStartActivityRecord[0];
        }

        // Aborted results are treated as successes externally, but we must track them internally.
        return mLastStartActivityResult != START_ABORTED ? mLastStartActivityResult : START_SUCCESS;
    }

这个方法也没做太多事情,将参数透传给startActivity继续执行

private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
            String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
            String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
            ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
            ActivityRecord[] outActivity, TaskRecord inTask) {
        int err = ActivityManager.START_SUCCESS;
        // Pull the optional Ephemeral Installer-only bundle out of the options early.
        final Bundle verificationBundle
                = options != null ? options.popAppVerificationBundle() : null;

        ProcessRecord callerApp = null;
        if (caller != null) {
            callerApp = mService.getRecordForAppLocked(caller);
            if (callerApp != null) {
                callingPid = callerApp.pid;
                callingUid = callerApp.info.uid;
            } else {
                Slog.w(TAG, "Unable to find app for caller " + caller
                        + " (pid=" + callingPid + ") when starting: "
                        + intent.toString());
                err = ActivityManager.START_PERMISSION_DENIED;
            }
        }

        final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;

        if (err == ActivityManager.START_SUCCESS) {
            Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
                    + "} from uid " + callingUid);
        }

        ActivityRecord sourceRecord = null;
        ActivityRecord resultRecord = null;
        if (resultTo != null) {
            // 通过resultTo在寻找记录在AMS中记录的ActivityRecord,这个ActivityRecord和启动Activity的源Activity对应
            sourceRecord = mSupervisor.isInAnyStackLocked(resultTo);
            if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
                    "Will send result to " + resultTo + " " + sourceRecord);
            if (sourceRecord != null) {
                if (requestCode >= 0 && !sourceRecord.finishing) {
                    resultRecord = sourceRecord;
                }
            }
        }

        final int launchFlags = intent.getFlags();

       // 新建一条目标Activity的ActivityRecord,这条ActivityRecord和即将打开的Activity实例对应
        ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
                callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
                resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,
                mSupervisor, options, sourceRecord);
        if (outActivity != null) {
            outActivity[0] = r;
        }
        return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true,
                options, inTask, outActivity);
    }

记的我们在分析源码之前所画的ActivityRecord、ActivityClientRecord、Activity之间的关系图么?这里就派上用场了,入参resultTo就是启动Activity时传递的token,那么,在AMS中,必然会有一条ActivityRecord与之对应,通过mSupervisor.isInAnyStackLocked(resultTo)找到与AActivity对应的ActivityRecord。

这个方法还有一个重要的任务就是新建一条ActivityRecord记录,这条记录和即将打开的Activity,即BActivity对应。完成这些工作后,继续执行startActivity

startActivity继续调用了startActivityUnchecked,这个方法最重要的功能是对Acitivity栈和Activity启动模式进行处理,篇幅很长,逻辑复杂,但是不是本篇的重点,所以我们后面的文章再着重分析,现在只关注Activity启动流程相关的部分

private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
            ActivityRecord[] outActivity) {
      
            ...

        if (mDoResume) {
            final ActivityRecord topTaskActivity =
                    mStartActivity.getTask().topRunningActivityLocked();
            if (!mTargetStack.isFocusable()
                    || (topTaskActivity != null && topTaskActivity.mTaskOverlay
                    && mStartActivity != topTaskActivity)) {
                mTargetStack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
                mWindowManager.executeAppTransition();
            } else {
                if (mTargetStack.isFocusable() && !mSupervisor.isFocusedStack(mTargetStack)) {
                    mTargetStack.moveToFront("startActivityUnchecked");
                }
      
                mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
                        mOptions);
            }
        } else {
            mTargetStack.addRecentActivityLocked(mStartActivity);
        }
        ...
        return START_SUCCESS;
    }
3.5.1. AActivity#onPause

注意看mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity, mOptions),这里,mStartActivity是即将启动的ActivityRecord,mTargetStack是在本方法中计算得到的它所在的ActivityStack,继续看resumeFocusedStackTopActivityLocked

还记得在开篇时讲到的从AActivity跳转到BActivity的生命周期过程么?不记得没关系,复习一下先:
AActivity#onPause -> BActivity#onCreate -> BActivity#onStart -> BActivity#onResume -> AActivity#onStop,
resumeFocusedStackTopActivityLocked这个方法我们将接触到这个过程中的第一个声明周期方法,即AActivity#onPause,而且本身这个方法的调用过程也特别复杂,需要重点解析一下,先看一下代码:

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.
        // 获取栈顶正在聚焦的Activity
        final ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */);

        final boolean hasRunningActivity = next != null;

        // TODO: Maybe this entire condition can get removed?
        if (hasRunningActivity && getDisplay() == null) {
            // zhangyulong 异常情况,有正在运行的activity但getDisplay为空
            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.
        final boolean userLeaving = mStackSupervisor.mUserLeaving;
        mStackSupervisor.mUserLeaving = false;

        if (!hasRunningActivity) {
            // There are no activities left in the stack, let's look somewhere else.
            // zhangyulong  task 退干净了,恢复其他的task
            return resumeTopActivityInNextFocusableStack(prev, options, "noMoreActivities");
        }

        next.delayedResume = false;

        ...
        // Activity栈中有需要Pause操作的Activity
        boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, next, false);
        if (mResumedActivity != null) {
            // 暂停当前正在显示的Activity
            pausing |= startPausingLocked(userLeaving, false, next, false);
        }
        if (pausing && !resumeWhilePausing) {
            if (next.app != null && next.app.thread != null) {
                mService.updateLruProcessLocked(next.app, true, null);
            }
            if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
            return true;
        } 

        ...
            
        ActivityStack lastStack = mStackSupervisor.getLastStack();
        if (next.app != null && next.app.thread != null) {
            ...
        } 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;
    }

这个方法会执行两次,第一次进入时,final ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */);获取到的是栈顶焦点Activity,在执行该方法之前,我们已经将目标ActivityRecord入栈,因此,这里获取的是要打开的目标ActivityRecord,mStackSupervisor.pauseBackStacks(userLeaving, next, false);是判断ActivityStack中是否有需要pause的Activity,如果有,说明还有活动的Activity没有Pause,我们要先执行Pause操作,通过执行startPausingLocked(userLeaving, false, next, false);将当前未Pause的Activity进行Pause,在执行完毕后方法直接return了。先进去看一下startPausingLocked

final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping,
            ActivityRecord resuming, boolean pauseImmediately) {

        // 将mResumedActivity赋值prev,并将mResumedActivity置空
        ActivityRecord prev = mResumedActivity;
        mResumedActivity = null;
        mPausingActivity = prev;
        

        if (prev.app != null && prev.app.thread != null) {
            if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueueing pending pause: " + prev);
            try {
                EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY,
                        prev.userId, System.identityHashCode(prev),
                        prev.shortComponentName);
                mService.updateUsageStats(prev, false);
                // 开始进行Pause操作
                prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,
                        userLeaving, prev.configChangeFlags, pauseImmediately);
            } catch (Exception e) {
                // Ignore exception, if process died other code will cleanup.
                Slog.w(TAG, "Exception thrown during pause", e);
                mPausingActivity = null;
                mLastPausedActivity = null;
                mLastNoHistoryActivity = null;
            }
        } else {
            mPausingActivity = null;
            mLastPausedActivity = null;
            mLastNoHistoryActivity = null;
        }

        if (mPausingActivity != null) {
            if (!uiSleeping) {
                prev.pauseKeyDispatchingLocked();
            } else if (DEBUG_PAUSE) {
                 Slog.v(TAG_PAUSE, "Key dispatch not paused for screen off");
            }

            if (pauseImmediately) {
                completePauseLocked(false, resuming);
                return false;

            } else {
                // 延时500ms处理pause后续操作
                schedulePauseTimeout(prev);
                return true;
            }

        } else {
            if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Activity not running, resuming next.");
            if (resuming == null) {
                mStackSupervisor.resumeFocusedStackTopActivityLocked();
            }
            return false;
        }
    }

mResumedActivity就是将被Pause的Activity,通过prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing, userLeaving, prev.configChangeFlags, pauseImmediately);对其进行Pause,这里实际是一个异步操作,因此,在方法的末端,添加了一个500ms的延时消息防止Pause操作timeout,当然,这个延时消息不一定会执行,如果pause操作在500ms以内完成会将这个消息取消。如果熟悉Activity启动流程的话,我们就会知道schedulePauseActivity最终一定会执行到ApplicationThread#handlePauseActivity,这个ApplicationThread在本文章的场景中是AActivity的ApplicationThread,看下代码:

    private void handlePauseActivity(IBinder token, boolean finished,
            boolean userLeaving, int configChanges, boolean dontReport, int seq) {
        ActivityClientRecord r = mActivities.get(token);
        if (DEBUG_ORDER) Slog.d(TAG, "handlePauseActivity " + r + ", seq: " + seq);
        if (!checkAndUpdateLifecycleSeq(seq, r, "pauseActivity")) {
            return;
        }
        if (r != null) {
            //Slog.v(TAG, "userLeaving=" + userLeaving + " handling pause of " + r);
            if (userLeaving) {
                performUserLeavingActivity(r);
            }

            r.activity.mConfigChangeFlags |= configChanges;
            // 真正调用Activity#onPause
            performPauseActivity(token, finished, r.isPreHoneycomb(), "handlePauseActivity");

            // Make sure any pending writes are now committed.
            if (r.isPreHoneycomb()) {
                QueuedWork.waitToFinish();
            }

            // Tell the activity manager we have paused.
            if (!dontReport) {
                try {
                    // 通知AMS Activity已完成Pause
                    ActivityManager.getService().activityPaused(token);
                } catch (RemoteException ex) {
                    throw ex.rethrowFromSystemServer();
                }
            }
            mSomeActivitiesChanged = true;
        }
    }

其中,performPauseActivity最终会调用AActivity的onPause,继续向下执行会通过ActivityManager.getService().activityPaused(token)通知AMS进程Activity已完成Pause,

// ActivityManagerService
    public final void activityPaused(IBinder token) {
        final long origId = Binder.clearCallingIdentity();
        synchronized(this) {
            ActivityStack stack = ActivityRecord.getStackLocked(token);
            if (stack != null) {
                stack.activityPausedLocked(token, false);
            }
        }
        Binder.restoreCallingIdentity(origId);
    }

继续看ActivityStack#activityPausedLocked


final void activityPausedLocked(IBinder token, boolean timeout) {

    ...

    final ActivityRecord r = isInStackLocked(token);
    if (r != null) {
        // 取消Pause的延时等待消息消息
        mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
        if (mPausingActivity == r) {
            if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to PAUSED: " + r
                    + (timeout ? " (due to timeout)" : " (pause complete)"));
            mService.mWindowManager.deferSurfaceLayout();
            try {
                // 完成Pause的后续操作
                completePauseLocked(true /* resumeNext */, null /* resumingActivity */);
            } finally {
                mService.mWindowManager.continueSurfaceLayout();
            }
            return;
        } 

        ....
}

比较重要的两个操作:

  • 取消Pause的延时等待消息消息
  • 完成Pause的后续操作
    完成Pause后续操作是在ActivityStack#completePauseLocked
private void completePauseLocked(boolean resumeNext, ActivityRecord resuming) {
        ActivityRecord prev = mPausingActivity;
        ...
        if (prev != null) {
           ...
           // 将已被Pause的Activity加入到mStackSupervisor.mStoppingActivities列表中
            addToStopping(prev, true /* scheduleIdle */, false /* idleDelayed */);
            ...
        }
        if (resumeNext) {
            final ActivityStack topStack = mStackSupervisor.getFocusedStack();
            if (!topStack.shouldSleepOrShutDownActivities()) {
                // Resume栈顶Activity, prev是当前在pause的
                mStackSupervisor.resumeFocusedStackTopActivityLocked(topStack, prev, null);
            } else {
                checkReadyForSleep();
                ActivityRecord top = topStack.topRunningActivityLocked();
                if (top == null || (prev != null && top != prev)) {
                    mStackSupervisor.resumeFocusedStackTopActivityLocked();
                }
            }
        }

        ...
    }

重点关注mStackSupervisor.resumeFocusedStackTopActivityLocked(topStack, prev, null);
兜兜转转,又回到了原点,我们即将第二次调用ActivityStack#resumeTopActivityInnerLocked,这次跟上一次又有所不同,因为已经完成活跃Activity的pause,因此,判断是否需要Pause的分支语句就不会执行,继续向下执行到mStackSupervisor.startSpecificActivityLocked(next, true, true);,这个方法还有一个重要的事情就是将已被Pause的Activity加入到mStackSupervisor.mStoppingActivities的列表中,这是一个ArrayList<ActivityRecord>,至于什么时候用,后面会讲到

3.5.2. BActivity#onCreate

讲到这里,我们只是刚完成了AActivity的Pause,有些朋友肯定已经着急了,那得分析到啥时候啊,快了快了,后面就很快了,加快进度,接着看ActivityStackSupervisor#startSpecificActivityLocked

       void startSpecificActivityLocked(ActivityRecord r,
            boolean andResume, boolean checkConfig) {
        // 获取目标Activity的进程信息
        ProcessRecord app = mService.getProcessRecordLocked(r.processName,
                r.info.applicationInfo.uid, true);

        r.getStack().setLaunchTime(r);

        if (app != null && app.thread != null) {
            try {
                if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
                        || !"android".equals(r.info.packageName)) {
                    app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode,
                            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);
    }

这个方法的主要工作是给ActivityRecord分配进程,如果没有进程,则启动新的进程,从AActivity跳BActivity是同一个进程,因此会继续执行realStartActivityLocked(r, app, andResume, checkConfig):

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

            ...
                app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
                        System.identityHashCode(r), r.info,
                       
            ...
        return true;
    }

方法比较长,掐头去尾只看app.thread.scheduleLaunchActivity,从这里开始进入App进程执行,scheduleLaunchActivity方法在APP进程对应的是ApplicationThread#scheduleLaunchActivity:

public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
                ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
                CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,
                int procState, Bundle state, PersistableBundle persistentState,
                List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
                boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {

            updateProcessState(procState, false);

            ActivityClientRecord r = new ActivityClientRecord();

            r.token = token;
            r.ident = ident;
            r.intent = intent;
            r.referrer = referrer;
            r.voiceInteractor = voiceInteractor;
            r.activityInfo = info;
            r.compatInfo = compatInfo;
            r.state = state;
            r.persistentState = persistentState;

            r.pendingResults = pendingResults;
            r.pendingIntents = pendingNewIntents;

            r.startsNotResumed = notResumed;
            r.isForward = isForward;

            r.profilerInfo = profilerInfo;

            r.overrideConfig = overrideConfig;
            updatePendingConfiguration(curConfig);

            sendMessage(H.LAUNCH_ACTIVITY, r);
        }

在这里创建了ActivityClientRecord,因此ActivityClientRecord和AMS中的ActivityRecord就对应起来了。向主线程发送H.LAUNCH_ACTIVITY消息,消息回调后执行handleLaunchActivity:

private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
        // If we are getting ready to gc after going to the background, well
        // we are back active so skip it.
      ...

        Activity a = performLaunchActivity(r, customIntent);

        if (a != null) {
            ....
            handleResumeActivity(r.token, false, r.isForward,
                    !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);
          ...
        }
    ....
    }

这里调用performLaunchActivity:

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        // 创建Context
        ContextImpl appContext = createBaseContextForActivity(r);
        Activity activity = null;
        try {
            // 通过ClassLoader创建Activity实例
            java.lang.ClassLoader cl = appContext.getClassLoader();
            activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);
            StrictMode.incrementExpectedActivityCount(activity.getClass());
            r.intent.setExtrasClassLoader(cl);
            r.intent.prepareToEnterProcess();
            if (r.state != null) {
                r.state.setClassLoader(cl);
            }
        } catch (Exception e) {
            if (!mInstrumentation.onException(activity, e)) {
                throw new RuntimeException(
                    "Unable to instantiate activity " + component
                    + ": " + e.toString(), e);
            }
        }

        try {
            Application app = r.packageInfo.makeApplication(false, mInstrumentation);



            if (activity != null) {
                //读取Activity信息
                CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
                Configuration config = new Configuration(mCompatConfiguration);
                if (r.overrideConfig != null) {
                    config.updateFrom(r.overrideConfig);
                }
                if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
                        + r.activityInfo.name + " with config " + config);
                Window window = null;
                if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {
                    window = r.mPendingRemoveWindow;
                    r.mPendingRemoveWindow = null;
                    r.mPendingRemoveWindowManager = null;
                }
                appContext.setOuterContext(activity);
                // 执行Actiivity attach方法
                activity.attach(appContext, this, getInstrumentation(), r.token,
                        r.ident, app, r.intent, r.activityInfo, title, r.parent,
                        r.embeddedID, r.lastNonConfigurationInstances, config,
                        r.referrer, r.voiceInteractor, window, r.configCallback);

                if (customIntent != null) {
                    activity.mIntent = customIntent;
                }
                r.lastNonConfigurationInstances = null;
                checkAndBlockForNetworkAccess();
                activity.mStartedActivity = false;
                int theme = r.activityInfo.getThemeResource();
                if (theme != 0) {
                    activity.setTheme(theme);
                }

                activity.mCalled = false;
                // Activity onCreate执行
                if (r.isPersistable()) {
                    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
                } else {
                    mInstrumentation.callActivityOnCreate(activity, r.state);
                }
                if (!activity.mCalled) {
                    throw new SuperNotCalledException(
                        "Activity " + r.intent.getComponent().toShortString() +
                        " did not call through to super.onCreate()");
                }
                r.activity = activity;
                r.stopped = true;
                if (!r.activity.mFinished) {
                    // Activity onStart执行
                    activity.performStart();
                    r.stopped = false;
                }
                if (!r.activity.mFinished) {
                    if (r.isPersistable()) {
                        if (r.state != null || r.persistentState != null) {
                            mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state,
                                    r.persistentState);
                        }
                    } else if (r.state != null) {
                        mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
                    }
                }
                
            }
            r.paused = true;

            mActivities.put(r.token, r);

        } catch (SuperNotCalledException e) {
            throw e;

        } catch (Exception e) {
           
        }

        return activity;
    }

这个方法是Activity真正创建实例且onCreate执行的地方,通过调用Activity#attach方法,ActivityClientRecord的token就和Activity联系起来了

3.5.3. BActivity#onStart

onCreate执行完成后,直接调用了activity.performStart();去执行onStart,因此我们可以得出结论:在Activity的onCreate和onStart方法中去处理逻辑,实际没有特别大的区别

3.5.4. BActivity#onResume

performLaunchActivity调用有返回值,即创建的Activity,如果返回值不为空,则说明创建Activity成功,继续执行handleResumeActivity

final void handleResumeActivity(IBinder token,
            boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) {
        ActivityClientRecord r = mActivities.get(token);
        if (!checkAndUpdateLifecycleSeq(seq, r, "resumeActivity")) {
            return;
        }
        ...
        // 执行onResume
        r = performResumeActivity(token, clearHide, reason);
        ...

        if (r != null) {
            final Activity a = r.activity;

            // 向messageQueue发送一个Idle消息
            if (!r.onlyLocalRequest) {
                r.nextIdle = mNewActivities;
                mNewActivities = r;
                if (localLOGV) Slog.v(
                    TAG, "Scheduling idle handler for " + r);
                Looper.myQueue().addIdleHandler(new Idler());
            }
            r.onlyLocalRequest = false;

            // 通知AMS完成了Resume操作
            if (reallyResume) {
                try {
                    ActivityManager.getService().activityResumed(token);
                } catch (RemoteException ex) {
                    throw ex.rethrowFromSystemServer();
                }
            }

        } 
        ...
    }

performResumeActivity是Activity的onResume执行的地方

3.5.5. AActivity#onStop

在执行完成后向住现成的MessageQueue发送了一个idle消息,这个很重要,具体是做什么的呢,我们进去看一下Idler的实现:

private class Idler implements MessageQueue.IdleHandler {
        @Override
        public final boolean queueIdle() {
            ActivityClientRecord a = mNewActivities;
            boolean stopProfiling = false;
            if (mBoundApplication != null && mProfiler.profileFd != null
                    && mProfiler.autoStopProfiler) {
                stopProfiling = true;
            }
            if (a != null) {
                mNewActivities = null;
                IActivityManager am = ActivityManager.getService();
                ActivityClientRecord prev;
                do {
                    if (localLOGV) Slog.v(
                        TAG, "Reporting idle of " + a +
                        " finished=" +
                        (a.activity != null && a.activity.mFinished));
                    if (a.activity != null && !a.activity.mFinished) {
                        try {
                          // 调用ActivityManagerService#activityIdle
                            am.activityIdle(a.token, a.createdConfig, stopProfiling);
                            a.createdConfig = null;
                        } catch (RemoteException ex) {
                            throw ex.rethrowFromSystemServer();
                        }
                    }
                    prev = a;
                    a = a.nextIdle;
                    prev.nextIdle = null;
                } while (a != null);
            }
            if (stopProfiling) {
                mProfiler.stopProfiling();
            }
            ensureJitEnabled();
            return false;
        }
    }

am.activityIdle(a.token, a.createdConfig, stopProfiling)这里,这种调用在本文中出现过很多次了,我们很容易得出结论:这是一次IPC调用,对应的方法在ActivityManagerService#activityIdle:

    @Override
    public final void activityIdle(IBinder token, Configuration config, boolean stopProfiling) {
        final long origId = Binder.clearCallingIdentity();
        synchronized (this) {
            ActivityStack stack = ActivityRecord.getStackLocked(token);
            if (stack != null) {
                ActivityRecord r =
                        mStackSupervisor.activityIdleInternalLocked(token, false /* fromTimeout */,
                                false /* processPausingActivities */, config);
                if (stopProfiling) {
                    if ((mProfileProc == r.app) && mProfilerInfo != null) {
                        clearProfilerLocked();
                    }
                }
            }
        }
        Binder.restoreCallingIdentity(origId);
    }

做的工作不多,调用了mStackSupervisor.activityIdleInternalLocked:

final ActivityRecord activityIdleInternalLocked(final IBinder token, boolean fromTimeout,
            boolean processPausingActivities, Configuration config) {
        if (DEBUG_ALL) Slog.v(TAG, "Activity idle: " + token);
        ....
        // Atomically retrieve all of the other things to do.
        final ArrayList<ActivityRecord> stops = processStoppingActivitiesLocked(r,
                true /* remove */, processPausingActivities);
        NS = stops != null ? stops.size() : 0;
        if ((NF = mFinishingActivities.size()) > 0) {
            finishes = new ArrayList<>(mFinishingActivities);
            mFinishingActivities.clear();
        }

        if (mStartingUsers.size() > 0) {
            startingUsers = new ArrayList<>(mStartingUsers);
            mStartingUsers.clear();
        }
        ...
        // Stop any activities that are scheduled to do so but have been
        // waiting for the next one to start.
        for (int i = 0; i < NS; i++) {
            r = stops.get(i);
            final ActivityStack stack = r.getStack();
            if (stack != null) {
                if (r.finishing) {
                    stack.finishCurrentActivityLocked(r, ActivityStack.FINISH_IMMEDIATELY, false);
                } else {
                    stack.stopActivityLocked(r);
                }
            }
        }
        ...
        return r;
    }

processStoppingActivitiesLocked做的操作就是寻找需要被Stop的Activity,进去看一下:

final ArrayList<ActivityRecord> processStoppingActivitiesLocked(ActivityRecord idleActivity,
            boolean remove, boolean processPausingActivities) {
        ArrayList<ActivityRecord> stops = null;

        final boolean nowVisible = allResumedActivitiesVisible();
        // 遍历mStoppingActivities列表,选择其中符合Stop条件的Activity
        for (int activityNdx = mStoppingActivities.size() - 1; activityNdx >= 0; --activityNdx) {
            ActivityRecord s = mStoppingActivities.get(activityNdx);
            boolean waitingVisible = mActivitiesWaitingForVisibleActivity.contains(s);
            if (DEBUG_STATES) Slog.v(TAG, "Stopping " + s + ": nowVisible=" + nowVisible
                    + " waitingVisible=" + waitingVisible + " finishing=" + s.finishing);
            if (waitingVisible && nowVisible) {
                mActivitiesWaitingForVisibleActivity.remove(s);
                waitingVisible = false;
                if (s.finishing) {
                    s.setVisibility(false);
                }
            }
            if (remove) {
                final ActivityStack stack = s.getStack();
                final boolean shouldSleepOrShutDown = stack != null
                        ? stack.shouldSleepOrShutDownActivities()
                        : mService.isSleepingOrShuttingDownLocked();
                if (!waitingVisible || shouldSleepOrShutDown) {
                    if (!processPausingActivities && s.state == PAUSING) {
                        // Defer processing pausing activities in this iteration and reschedule
                        // a delayed idle to reprocess it again
                        removeTimeoutsForActivityLocked(idleActivity);
                        scheduleIdleTimeoutLocked(idleActivity);
                        continue;
                    }

                    if (DEBUG_STATES) Slog.v(TAG, "Ready to stop: " + s);
                    if (stops == null) {
                        stops = new ArrayList<>();
                    }
                    stops.add(s);
                    mStoppingActivities.remove(activityNdx);
                }
            }
        }

        return stops;
    }

之前在执行AActivity的Pause操作后,我们将AActivity加入到了ActivityStackSupervisor类中一个叫mStoppingActivities的列表中,在这里这个列表就派上用场了,我们会遍历这个列表,从中获取符合条件的Activity并组装到一个新的列表中返回。

完成这个操作后,activityIdleInternalLocked开始遍历这个返回的列表进Stop操作。

stack.stopActivityLocked(r),凭我20年Android开发经验练就的火眼金睛,感觉这里就是AActivity#onStop触发的地方:

// ActivityStack
final void stopActivityLocked(ActivityRecord r) {


        if (r.app != null && r.app.thread != null) {
            adjustFocusedActivityStackLocked(r, "stopActivity");
            r.resumeKeyDispatchingLocked();
            try {

                r.app.thread.scheduleStopActivity(r.appToken, r.visible, r.configChangeFlags);
                if (shouldSleepOrShutDownActivities()) {
                    r.setSleeping(true);
                }
                Message msg = mHandler.obtainMessage(STOP_TIMEOUT_MSG, r);
                mHandler.sendMessageDelayed(msg, STOP_TIMEOUT);
            } catch (Exception e) {

            }
        }
    }

果然,在这个方法内部执行了r.app.thread.scheduleStopActivity,这个方法就不进去看了,我们只需要知道它最终调用了r的onStop就可以了

至此,从AActivity跳转BActivity所经历的生命周期就全部完成了。

为什么要用IdleHandler?

我猜测是因为google的工程师认为既然BActivity已经启动了,那么主线程Handler的首要任务还是处理B进程内部的事情,至于AActivity,反正都已经Pause了,就抽个空闲时间告诉AMS把它Stop就可以了。

3.6. 从BActivity返回到AActivity

先回顾一下从BActivity返回AActivity经历的生命周期

BActivity#onPause -> AActivity#onStart -> AActivity#onResume -> BActivity#onStop -> BActivity#onDestroy

先从BActivity的finish方法说起

BActivity的finish方法最终会调用到AMS的finishActivity方法,

// ActivityManagerService
public final boolean finishActivity(IBinder token, int resultCode, Intent resultData,
            int finishTask) {
        // Refuse possible leaked file descriptors
        if (resultData != null && resultData.hasFileDescriptors() == true) {
            throw new IllegalArgumentException("File descriptors passed in Intent");
        }

        synchronized(this) {
            ActivityRecord r = ActivityRecord.isInStackLocked(token);
            if (r == null) {
                return true;
            }
            // Keep track of the root activity of the task before we finish it
            TaskRecord tr = r.getTask();
            // 正在结束的Activity所在的ActivityTask
            ActivityRecord rootR = tr.getRootActivity();
            if (rootR == null) {
                Slog.w(TAG, "Finishing task with all activities already finished");
            }
            
            final long origId = Binder.clearCallingIdentity();
            try {
                boolean res;
                final boolean finishWithRootActivity =
                        finishTask == Activity.FINISH_TASK_WITH_ROOT_ACTIVITY;
                if (finishTask == Activity.FINISH_TASK_WITH_ACTIVITY
                        || (finishWithRootActivity && r == rootR)) {
                    ...
                } else {
                    res = tr.getStack().requestFinishActivityLocked(token, resultCode,
                            resultData, "app-request", true);
                }
                return res;
            } finally {
                Binder.restoreCallingIdentity(origId);
            }
        }
    }

入参的含义:

  • token : 准备finish的Activity的Binder token引用
  • resultCode: resultCode 字面意思,在onActivityResult接收到的
  • resultData: ResultData 字面意思,在onActivityResult接收得到的
  • finishTask: 是否将ActivityStack一起finish
    在这里我们又和token见面了,在前面从AActivity启动BActivity的流程里我们分析过,这个token是BActivity在AMS中的标识。

ActivityManagerService#finishActivity经过层层调用,会调用到ActivityStack#finishActivityLocked:

final boolean finishActivityLocked(ActivityRecord r, int resultCode, Intent resultData,
            String reason, boolean oomAdj, boolean pauseImmediately) {
        if (r.finishing) {
            Slog.w(TAG, "Duplicate finish request for " + r);
            return false;
        }

        mWindowManager.deferSurfaceLayout();
        try {
            // 将r标记为finishing
            r.makeFinishingLocked();
            ...
            // 将resultCode和resultData设置给resultTo
            finishActivityResultsLocked(r, resultCode, resultData);

            final boolean endTask = index <= 0 && !task.isClearingToReuseTask();
            final int transit = endTask ? TRANSIT_TASK_CLOSE : TRANSIT_ACTIVITY_CLOSE;
            if (mResumedActivity == r) {
                if (DEBUG_VISIBILITY || DEBUG_TRANSITION) Slog.v(TAG_TRANSITION,
                        "Prepare close transition: finishing " + r);
                if (endTask) {
                    mService.mTaskChangeNotificationController.notifyTaskRemovalStarted(
                            task.taskId);
                }
                mWindowManager.prepareAppTransition(transit, false);

                // Tell window manager to prepare for this one to be removed.
                r.setVisibility(false);

                if (mPausingActivity == null) {
                    if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Finish needs to pause: " + r);
                    if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
                            "finish() => pause with userLeaving=false");
                    // 将当前处于活跃状态的Activity进行Pause
                    startPausingLocked(false, false, null, pauseImmediately);
                }

                if (endTask) {
                    mStackSupervisor.removeLockedTaskLocked(task);
                }
            } else if (r.state != ActivityState.PAUSING) {
               ...
            } else {
                if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Finish waiting for pause of: " + r);
            }

            return false;
        } finally {
            mWindowManager.continueSurfaceLayout();
        }
    }

本方法重点事项

  1. 将r(即将要finish的Activity)的finishing标记位置为true
  2. 将将resultCode和resultData设置给resultTo,这个resultTo是我们在创建r的时候传入的,在AActivity跳BActivity的流程中我们介绍过,本场景中resultTo指AActivity的token
  3. 将当前处于活跃状态的Activity进行pause,本场景中活跃状态的Activity就是AActivity
3.6.1. BActivity#onPause

其中startPausingLocked方法我们在前面已经分析过了,这里就不再赘述了,详细的分析可以看3.5.1章节。通过之前的分析我们知道,startPausingLocked会执行BActvity的onPause回调并最终调用到ActivityManagerService#activityPaused方法,这个放我我们之前也做过分析,最终会调用到ActivityStack#resumeTopActivityInnerLocked,这个方法的调用和BActivity的启动流程略有不同

3.6.2 AActivity#onStart、AActivity#onResume

在调用ActivityStack#resumeTopActivityInnerLocked时,因为我们已经完成对BActivity的Pause,因此,获取栈顶Activity 即next时,拿到的会是AActivity,而AActivity的app和thread均不为空,因此,
判断语句if (next.app != null && next.app.thread != null) 成立,它会走入ActivityStack#resumeTopActivityInnerLocked如下分支:

if (next.app != null && next.app.thread != null) {
            if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resume running: " + next
                    + " stopped=" + next.stopped + " visible=" + next.visible);
                try {
                    // 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);
                            next.app.thread.scheduleSendResult(next.appToken, a);
                        }
                    }

                    if (next.newIntents != null) {
                        next.app.thread.scheduleNewIntent(
                                next.newIntents, next.appToken, 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.showUnsupportedZoomDialogIfNeededLocked(next);
                    mService.showAskCompatModeDialogLocked(next);
                    next.app.pendingUiClean = true;
                    next.app.forceProcessStateUpTo(mService.mTopProcessState);
                    next.clearOptionsLocked();
                    // zhangyulong ResumeNextActivity
                    next.app.thread.scheduleResumeActivity(next.appToken, next.app.repProcState,
                            mService.isNextTransitionForward(), resumeAnimOptions);

                    if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Resumed "
                            + next);
                } catch (Exception e) {
                    ...
                    return true;
                }
            }

        }

注意看next.app.thread.scheduleResumeActivity这里,这个方法最终会调用AActivity的onRestart、onStart和onResume,这个部分的调用大家肯定都轻车熟路了,就不跟进去看了

3.6.3. BActivity#onStop、BActivity#onDestroy

在BActivity启动流程分析中,我们知道在onResume时,会向主线程MessageQueue发送一个IdleHandler,这个IdleHandler最终会调用ActivityStackSupervisor#activityIdleInternalLocked,但这次的调用又跟之前有所不同,因为我们在之前的操作时已经将BActivity置为finishing,因此if (r.finishing)判断为true,方法调用会执行

final ActivityRecord activityIdleInternalLocked(final IBinder token, boolean fromTimeout,
            boolean processPausingActivities, Configuration config) {
        if (DEBUG_ALL) Slog.v(TAG, "Activity idle: " + token);


        // Atomically retrieve all of the other things to do.
        final ArrayList<ActivityRecord> stops = processStoppingActivitiesLocked(r,
                true /* remove */, processPausingActivities);
        NS = stops != null ? stops.size() : 0;
        if ((NF = mFinishingActivities.size()) > 0) {
            finishes = new ArrayList<>(mFinishingActivities);
            mFinishingActivities.clear();
        }

        if (mStartingUsers.size() > 0) {
            startingUsers = new ArrayList<>(mStartingUsers);
            mStartingUsers.clear();
        }

        // Stop any activities that are scheduled to do so but have been
        // waiting for the next one to start.
        for (int i = 0; i < NS; i++) {
            r = stops.get(i);
            final ActivityStack stack = r.getStack();
            if (stack != null) {
                if (r.finishing) {
                    // stop 且 pause
                    stack.finishCurrentActivityLocked(r, ActivityStack.FINISH_IMMEDIATELY, false);
                } else {
                    // 仅stop
                    stack.stopActivityLocked(r);
                }
            }
        }

        return r;
    }

方法执行stack.finishCurrentActivityLocked后,在APP进程对应执行BActivity的onStop和onDestroy

至此,BActivity返回AActivity的生命周期也执行完毕

4. 后记

很多博客说Activity启动过程会经历两次跨进程,从App进程到AMS,从AMS再到APP进程,实际情况要远比这复杂的多,具体多少次感兴趣的朋友可以数一下。后面的文章会分析onActiivtyResult的执行,敬请期待

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342

推荐阅读更多精彩内容