Android—Activity启动过程(Android8.0)

要解决这几个问题

  • 启动过程分几步
  • 每一步解决什么问题
  • 进程怎么创建的
  • 栈怎么维护的
  • LanchMode怎么实现的

4次IPC过程

  • 当前App Activity 发起startactivity->ActivityManagerService
  • AMS->原App Activity 进行暂停
  • 原Activity -> AMS 已经暂停
  • AMS ->通知新activity 开始启动

相关类

  • ActivityThread:App启动的入口
  • ApplicationThread:ActivityThread的内部类,继承Binder,可以进程跨进程通信。
  • ApplicationThreadProxy:ApplicationThread的一个本地代理,其它的client端通过这个对象调用server端ApplicationThread中方法。
  • Instrumentation:负责发起Activity的启动、并具体负责Activity的创建以及Activity生命周期的回调。一个应用进程只会有一个Instrumentation对象,App内的所有Activity都持有该对象的引用。
  • ActivityManagerService:简称AMS,是service端对象,负责管理系统中所有的Activity
  • ActivityManagerProxy:是ActivityManagerService的本地代理
  • ActivityStack:Activity在AMS的栈管理,用来记录已经启动的Activity的先后关系,状态信息等。通过ActivityStack决定是否需要启动新的进程。
  • ActivityRecord:ActivityStack的管理对象,每个Activity在AMS对应一个ActivityRecord,来记录Activity的状态以及其他的管理信息。其实就是服务器端的Activity对象的映像。
  • TaskRecord:AMS抽象出来的一个“任务”的概念,是记录ActivityRecord的栈,一个“Task”包含若干个ActivityRecord。AMS用TaskRecord确保Activity启动和退出的顺序。

启动过程分析

Android—Activity启动过程(Android8.0)_第1张图片

第一步

startActivityForResult ,startActivity最终也是调用这个方法来启动新的Activity。然后跑到Instrumentation

public ActivityResult execStartActivity(
        Context who, IBinder contextThread, IBinder token, String resultWho,
        Intent intent, int requestCode, Bundle options, UserHandle user) {
    IApplicationThread whoThread = (IApplicationThread) contextThread;
    //...
    try {
        intent.migrateExtraStreamToClipData();
        intent.prepareToLeaveProcess(who);
        //1 调用AMS的startActivity
        int result = ActivityManager.getService()
            .startActivity(whoThread, who.getBasePackageName(), intent,
                    intent.resolveTypeIfNeeded(who.getContentResolver()),
                    token, resultWho,
                    requestCode, 0, null, options, user.getIdentifier());
        checkStartActivityResult(result, intent);
    } catch (RemoteException e) {
        throw new RuntimeException("Failure from system", e);
    }
    return null;
}

ActivityManager.getService() 拿到的是AIDL方式获取的AMS的本地对象。或者说,它可以和AMS进行通信。AMS上面说了,是所有activity的管理对象。而Instrumentation在这里就是启动新的Activity。

从下面的代码,就是上面4步里面的第一步,从Activity到AMS。

# com.android.server.am.ActivityManagerService
public final int startActivity(IApplicationThread caller, String callingPackage,
                               Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
                               int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
    return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
            resultWho, requestCode, startFlags, profilerInfo, bOptions,
            UserHandle.getCallingUserId());
}

第二步

第二步是AMS通知原activity pause。所以这个时候原activity需要进入task和stack。接下来看AMS启动activity的过程

public final int startActivity(IApplicationThread caller, String callingPackage,
        Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
        int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
    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) {
    enforceNotIsolatedCaller("startActivity");
    userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
            userId, false, ALLOW_FULL_ONLY, "startActivity", null);
    // TODO: Switch to user app stacks here.
    return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,
            resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
            profilerInfo, null, null, bOptions, false, userId, null, "startActivityAsUser");
}

mActivityStarter是负载启动activity的辅助类。

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

注释翻译过来就是:ActivityStarter这个类,启动Activity的控制器,主要用于用来将Intent和flags转换成activity和相关任务栈;ActivityStackSupervisor:主要管理着mHomeStack和mFocusedStack两个ActivityStack等相关信息;先来看ActivityStarter,整个过程有5层调用:

final int startActivityMayWait(IApplicationThread caller, int callingUid,
        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) {
//...
//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);

//...
}

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) {
//...

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

//...
}

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) {
//...

doPendingActivityLaunchesLocked(false);

return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true,
        options, inTask, outActivity);

}

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

//...
}

private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
        IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
        int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
        ActivityRecord[] outActivity) {
//...
mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
        mOptions);
//...
}

从一开始的输入是intent和flags 到最后的mTargetStack,mOptionsActivityStackSupervisor 后面又调用了ActivityStack.resumeTopActivityUncheckedLocked

boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
//...
result = resumeTopActivityInnerLocked(prev, options);
//...
}

private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
//...
    if (mResumedActivity != null) {
        //同步等待pause当前Activity的结果
        pausing |= startPausingLocked(userLeaving, false, next, false);
    }
//...
}

这个时候需要先pause原activity。往后看,会看到ActivityThread$H.handlePauseActivity到这里就是第二步结束了。

第三步

AMS通知原activity pause:

private void handlePauseActivity(IBinder token, boolean finished,
        boolean userLeaving, int configChanges, boolean dontReport, int seq) {
//...
performPauseActivity(token, finished, r.isPreHoneycomb(), "handlePauseActivity");//执行pause

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

// Tell the activity manager we have paused.
if (!dontReport) {
    try {
        ActivityManager.getService().activityPaused(token);//执行完后通知AMS当前Activity已经pause
    } catch (RemoteException ex) {
        throw ex.rethrowFromSystemServer();
    }
}
}

final Bundle performPauseActivity(IBinder token, boolean finished,
        boolean saveState, String reason) {
    ActivityClientRecord r = mActivities.get(token);
    return r != null ? performPauseActivity(r, finished, saveState, reason) : null;
}

final Bundle performPauseActivity(ActivityClientRecord r, boolean finished,
        boolean saveState, String reason) {
//...
// Next have the activity save its current state and managed dialogs...
if (!r.activity.mFinished && saveState) {
    callCallActivityOnSaveInstanceState(r);
}

performPauseActivityIfNeeded(r, reason);//执行pause
//...
}

private void performPauseActivityIfNeeded(ActivityClientRecord r, String reason) {
//...
mInstrumentation.callActivityOnPause(r.activity);
//...
}

ActivityManager.getService().activityPaused(token);//执行完后通知AMS当前Activity已经pauseInstrumentation 会通知activity做onPause的回调。Instrumentation的作用就会通知Activity的生命周期。这就是第三步。ActivityThread通知AMS,pause完成了。

第四步

从AMS知道pause完成以后,继续流程:StackSupervisor.resumeFocusedStackTopActivityLocked

boolean resumeFocusedStackTopActivityLocked(
        ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {

    if (!readyToResume()) {
        return false;
    }
/如果启动Activity和要启动的Activity在同一个ActivityStack中,调用targetStack对象的方法
    if (targetStack != null && isFocusedStack(targetStack)) {
        return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
    }
final ActivityRecord r = mFocusedStack.topRunningActivityLocked();

//如果不在同一个ActivityStack中,则调用mFocusStack对象的方法
if (r == null || r.state != RESUMED) {
mFocusedStack.resumeTopActivityUncheckedLocked(null, null);
} else if (r.state == RESUMED) {
// Kick off any lingering app transitions form the MoveTaskToFront operation.
mFocusedStack.executeAppTransition(targetOptions);
}

return false;

}
后面会走到ActivityThread的

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 pendingResults, List pendingNewIntents,
        boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {
//...
sendMessage(H.LAUNCH_ACTIVITY, r);
}

然后跑到ActivityThread$H:handleLaunchActivity,然后又回到mInstrumentation,又是这个类

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
//...
ContextImpl appContext = createBaseContextForActivity(r);//1 创建activity的BaseContext
Activity activity = null;
try {
    java.lang.ClassLoader cl = appContext.getClassLoader();
    activity = mInstrumentation.newActivity(
            cl, component.getClassName(), r.intent);//2 创建activity
    StrictMode.incrementExpectedActivityCount(activity.getClass());
    r.intent.setExtrasClassLoader(cl);
    r.intent.prepareToEnterProcess();
    if (r.state != null) {
        r.state.setClassLoader(cl);
    }
}
//...
Application app = r.packageInfo.makeApplication(false, mInstrumentation);//3 创建Application
//...
appContext.setOuterContext(activity);
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);//4 调用attach
//...
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);//5 调用生命周期函数OnCreate
//...
}

哈哈,到这里,new activity已经创建,mInstrumentation call了onCreate。至此,整个页面已经创建完毕。

流程总结

ActivityA 启动ActivityB

  • Instrumentation 向AMS发起启动B的通知。第一步结束
  • AMS 收到通知,通过ActivityStarter开始启动的流程。
  • ActivityStarter 把intent&
    flags,转化成mTargetStack,mOptions,并给到ActivityStackSupervisor(负责Activity的栈管理)
  • ActivityStackSupervisor 开始pause A的流程。
  • ActivityThread$H.handlePauseActivity 完成pause的流程。第二步结束。
  • 然后ActivityThread通知AMS,pause完成。第三步结束
  • AMS 通知ActivityStackSupervisor 启动B

结语

如果有错的地方或者什么想法欢迎提出来,大家一起探讨,谢谢。

最后在文章末尾分享一份Android学习PDF+架构视频+源码笔记,高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料给大家

非常适合近期有面试和想在技术道路上继续精进的朋友。也是希望可以帮助到大家提升进阶

如果你觉得自己学习效率低,缺乏正确的指导,可以加入资源丰富,学习氛围浓厚的技术圈一起学习交流吧!

你可能感兴趣的:(Android技术,Android程序员,移动开发)