重温四大组件(三)—Activity的启动过程

223 阅读11分钟

前言

重温四大组件第四篇,这里分析一下Activity的启动过程。Activity的启动过程分为两种,一种是根Activity的启动,另外一种是普通Activity的启动过程。根Activity也就是默认启动的Activity(在AndroidMinifest.xml配置的启动Activity)。普通Activity指的是除根Activity的其他Activity。其中根Activity和普通Activity的启动过程略有区别,根Activity的启动过程涉及到了应用程序进程的启动过程。

接下来从根Activity的角度启动来说。

以下分析的代码基于Android 9.0

Activity启动过程中的数据结构

我们在看一些技术博客的时候经常会看到一些分析AMS的文章。AMS就是ActivityManagerService,顾名思义就是Activity的管理服务,但它不仅仅管理Activity,其他三个组件的启动也经由AMS。同时,在看Activity的启动过程之前,我们应该了解一些Binder的知识。Binder是Android系统中一种跨进程通信技术。在Activity的启动过程中就涉及到了Binder通信的过程。

Activity的启动过程,可以概括为Launcher到AMS(经过Binder通信),从AMS到ApplicationThread(通过Binder通信)。

以上介绍了AMS在Activity的启动中承担的作用。接下来,我们再介绍一些在Activity启动过程中的一些其他角色。

ActivityStack

从ActivityStack的命名可以看出这个是Activity栈相关的。它的作用是管理和记录一个Activity栈的Activity。接下来我们看下ActivityStack中有哪些属性。

名称 类型 说明
mService ActivityManagerService 目前AMS的引用
mRecentTasks RecentTasks 记录一个最近使用的Activity列表
mPausingActivity ActivityRecord 目前停止状态的Activity信息
mResumedActivity ActivityRecord 目前resume状态的Activity信息

ActivityRecord

ActivityRecord是用来描述一个Activity的数据结构,它记录了Activity的所有信息。

名称 类型 说明
service ActivityManagerService 目前AMS的引用
info ActivityInfo 主要记录了Activity在Manifest文件中的配置信息
launchedFromPid int 启动Activity进程的pid
launchedFromUid int 启动Activity进程的uid
taskAffinity String Activity启动后所在的task
task TaskRecord 记录了所在task的信息
app ProcessRecord 记录了Activity启动所在进程的信息
state ActivityState 当前Activity的状态
theme int Activity的主题

TaskRecord

TaskRecord是关于任务栈的描述。

名称 类型 说明
taskId final int 任务栈的唯一标识
affinity String 任务栈的名称,也就是taskAffinity配置的名称
intent Intent 启动这个任务栈的Intent
mActivities ArrayList 按照在任务栈中历史顺序排序的Activity
mStack ActivityStack 任务栈所在的Activity栈
mService ActivityManagerService 目前AMS的引用

ProcessRecord

ProcessRecord是关于应用进程的描述。

名称 类型 说明
uid int 进程的uid
processName String 进程名称
info ApplicationInfo 记录应用程序信息

在上面介绍了Activity启动过程中关于Activity启动过程中的一些信息记录。比如:Activity栈信息、任务栈信息以及进程信息等。

Activity的启动工程

Activity的启动过程是一个很复杂的过程,接下来的分析过程并不会把所有细节都分析到位。我们分析Activity的启动过程主要是为了学习Android系统对Activity组件的管理过程以及对应用进程的调度。

从Launcher到AMS

我们知道在Android系统中锁呈现的桌面就是一个应用程序。当用户点击桌面上的应用图标是就可以启动相应的应用程序。应用程序由Launcher启动,调用startActivitySafely()方法。

/**Launcher.java**/
 boolean startActivitySafely(Intent intent, Object tag) {
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        try {
            startActivity(intent);
            return true;
        } catch (ActivityNotFoundException e) {
            Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
        } catch (SecurityException e) {
            Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
        }
        return false;
    }

可以看到在startActivitySafely()中继续调用startActivity()方法启动Activity,并且在Intent中设置了flag为FLAG_ACTIVITY_NEW_TASK表示Activity将在一个新的任务栈中启动。这个方法就是在Activity中的。

/**Activity.java**/
public void startActivity(Intent intent, @Nullable Bundle options) {
        if (options != null) {
            startActivityForResult(intent, -1, options);
        } else {
            // Note we want to go through this call for compatibility with
            // applications that may have overridden the method.
            startActivityForResult(intent, -1);
        }
    }

这里继续调用了startActivityForResult(),并且requestCode为-1表示Launcher不需要知道Activity的结果。

/**Activity.java**/
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
            @Nullable Bundle options) {
        if (mParent == null) {
            options = transferSpringboardActivityOptions(options);
            //继续启动Activity
            Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);
            if (ar != null) {
                mMainThread.sendActivityResult(
                    mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                    ar.getResultData());
            }
            if (requestCode >= 0) {
                mStartedActivity = true;
            }
            cancelInputsAndStartExitTransition(options);
        } else {
            if (options != null) {
                mParent.startActivityFromChild(this, intent, requestCode, options);
            } else {
                mParent.startActivityFromChild(this, intent, requestCode);
            }
        }
    }

在这里先判断mParent是否为null,然后根据结果选择走那一步。如果跟代码的话,可以看到mParent在attach()方法中或者setParent()方法中赋值,在根Activity的情况中mParent为null。所以继续调用 mInstrumentation.execStartActivity()。

/**Instrumentation.java**/
public ActivityResult execStartActivity(
        Context who, IBinder contextThread, IBinder token, String target,
        Intent intent, int requestCode, Bundle options) {
        IApplicationThread whoThread = (IApplicationThread) contextThread;
        //......
        try {
            intent.migrateExtraStreamToClipData();
            intent.prepareToLeaveProcess(who);
            //通过Binder接口获取AMS对象
            int result = ActivityManager.getService()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target, requestCode, 0, null, options);
            checkStartActivityResult(result, intent);
        } catch (RemoteException e) {
            throw new RuntimeException("Failure from system", e);
        }
        return null;
    }

在上面的方法中继续启动Activity,在这里我们可以看到通过ActivityManager.getService()我们就获取到了AMS对象。接下来,我们看下AMS的获取过程。

/**ActivityManager.java**/
public static IActivityManager getService() {
        return IActivityManagerSingleton.get();
    }
private static final Singleton<IActivityManager> IActivityManagerSingleton =
            new Singleton<IActivityManager>() {
                @Override
                protected IActivityManager create() {
                    final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
                    final IActivityManager am = IActivityManager.Stub.asInterface(b);
                    return am;
                }
            };

在getService()方法中通过IActivityManagerSingleton获取了AMS的对象。在创建IActivityManagerSingleton的方法中我们可以看到返回的是IActivityManager,IActivityManager就是使用了AIDL的方式生成的。

在AMS中处理Activity的启动

从这里开始,Activity的启动就开始在AMS中进行了。从上面的代码可以知道这个过程是通过Binder通信方式进行的。

/**ActivityManagerService.java**/
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());
    }

在ActivityManagerService中通过startActivity()方法继续进行Activity的启动。接下来我们直接看最终的方法回调。

/**ActivityManagerService.java**/
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) {
        //......
        //从obtainStarter()中获取了ActivityStarter对象
        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) //设置mayWait标志
                .execute();

    }

在上面的方法中,AMS通过startActivityAsUser()方法最终把Activity的启动过程转移到了ActivityStarter中。我们直接看下ActivityStarter的execute()方法。

/**ActivityStarter**/
int execute() {
        try {
            if (mRequest.mayWait) {
                return startActivityMayWait(mRequest.caller, mRequest.callingUid,
                       //....//);
            } else {
                return startActivity(mRequest.caller, mRequest.intent, //....//);
            }
        } finally {
            onExecutionComplete();
        }
    }

这里根据mRequest.mayWait(表示我们应该等待启动请求的结果。)中的标志来判断走哪个逻辑分支。在上面的代码中调用setMayWait(userId),这里将mayWait设置为true。那么接下来我们继续看startActivityMayWait()方法。

private int startActivityMayWait(//....//) {
        //......
        // Collect information about the target of the Intent.
        ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo); //构建Activity的信息

        synchronized (mService) {
            final ActivityStack stack = mSupervisor.mFocusedStack; //获取Activity栈的信息
            stack.mConfigWillChange = globalConfig != null
                    && mService.getGlobalConfiguration().diff(globalConfig) != 0;
            //......
            final ActivityRecord[] outRecord = new ActivityRecord[1]; //获取Activity的信息
            //继续启动Activity
            int res = startActivity(caller, intent, ephemeralIntent, resolvedType, aInfo, rInfo,
                    voiceSession, voiceInteractor, resultTo, resultWho, requestCode, callingPid,
                    callingUid, callingPackage, realCallingPid, realCallingUid, startFlags, options,
                    ignoreTargetSecurity, componentSpecified, outRecord, inTask, reason,
                    allowPendingRemoteAnimationRegistryLookup);

            Binder.restoreCallingIdentity(origId);
            //......
            return res;
        }
    }

我们继续跟代码,接下会调用

private int startActivity(//....//) {
        //......
        ProcessRecord callerApp = null; //获取进程信息
        if (caller != null) {
            //caller是ActivityThread中的Binder接口,用过应用程序进程则不为null
            callerApp = mService.getRecordForAppLocked(caller); //获取进程信息
            if (callerApp != null) {
                callingPid = callerApp.pid;
                callingUid = callerApp.info.uid;
            } 
        }
        //......
        //创建启动Activity的信息类
        ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
                callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
                resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,
                mSupervisor, checkedOptions, sourceRecord);
        if (outActivity != null) {
            outActivity[0] = r;
        }
        final ActivityStack stack = mSupervisor.mFocusedStack; //获取有焦点的Activity栈
        //......
        //继续启动Activity
        return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
                true /* doResume */, checkedOptions, inTask, outActivity);
    }

在上面会看到根据IApplicationThread获取应用进程信息,这里如果应用进程没有被创建的时候,IApplicationThread是null,然后接下来的步骤会创建应用程序进程,这里不再详细说。接下来继续进行Activity启动的分析。

private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
            ActivityRecord[] outActivity) {
        //......
        int result = START_SUCCESS;
            if (mDoResume) {
            final ActivityRecord topTaskActivity =
                    mStartActivity.getTask().topRunningActivityLocked();
            if (!mTargetStack.isFocusable()
                    || (topTaskActivity != null && topTaskActivity.mTaskOverlay
                mTargetStack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
                mService.mWindowManager.executeAppTransition();
            } else {
                if (mTargetStack.isFocusable() && !mSupervisor.isFocusedStack(mTargetStack)) {
                    mTargetStack.moveToFront("startActivityUnchecked");
                }
                //这里继续启动Activity
                mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
                        mOptions);
            }
        }
        return START_SUCCESS;
    }

接下来启动Activity的过程转到ActivityStackSupervisor中。

/**ActivityStackSupervisor**/
boolean resumeFocusedStackTopActivityLocked(
            ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
        //这里从Activity栈中启动
        if (targetStack != null && isFocusedStack(targetStack)) {
            return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
        }
        //......
        return false;
    }

上面的代码中继续启动Activity,这次启动过程转到ActivityStack中。

private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
        //......省略代码
      
       boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, next, false);
        if (mResumedActivity != null) {
            //这里如果mResumedActivity不为null,就停止mResumedActivity
            if (DEBUG_STATES) Slog.d(TAG_STATES,
                    "resumeTopActivityLocked: Pausing " + mResumedActivity);
            pausing |= startPausingLocked(userLeaving, false, next, false);
        }
        //next是ActivityRecord对象,next.app是ProcessRecord对象,next.app.thread是IApplicationThread
        if (next.app != null && next.app.thread != null) {
            //如果都不为null,说明应用进程已经被创建
           //......
            synchronized(mWindowManager.getWindowManagerLock()) {
                try {
                    mStackSupervisor.startSpecificActivityLocked(next, true, false);
                    return true;
                }
            }
        } else {
            ////应用进程没有被创建
            mStackSupervisor.startSpecificActivityLocked(next, true, true);
        }
        return true;
    }

在上面的代码中我们可以看到有一个判断逻辑if (next.app != null && next.app.thread != null),这个是判断应用程序进程是否被创建,从代码中可以看到,无论应用进程是否被创建,都会调用startSpecificActivityLocked()方法。这里Activity的启动又转移到了ActivityStackSupervisor中。

除此之外,还有一个步骤是将mResumedActivity设置为停止状态,在我们查看Activity的生命周期时,一个Activity启动另外一个Activity的时候,在调用过Activity的pause生命周期函数时才会开始下一个Activity的生命周期。

/**ActivityStackSupervisor**/
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);
        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.longVersionCode,
                            mService.mProcessStats);
                }
                //继续启动Activity
                realStartActivityLocked(r, app, andResume, checkConfig);
                return;
            } catch (RemoteException e) {
                
            }
        }
        //创建应用进程
        mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
                "activity", r.intent.getComponent(), false, false, true);
    }

这里就看到了如果应用进程不存在就会通过AMS创建应用进程,这里不再展开分析。如果应用进程存在就继续启动Activity。调用了realStartActivityLocked方法。

/**ActivityStackSupervisor**/ 
final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
            boolean andResume, boolean checkConfig) throws RemoteException {
                //......
                // Create activity launch transaction.
                //Android 9.0的启动方式与其他版本的不同,这里换成了通过ClientTransaction的方式已启动。
                final ClientTransaction clientTransaction = ClientTransaction.obtain(app.thread,
                        r.appToken);
                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));

                // 这里用来处理Activity生命周期回调
                final ActivityLifecycleItem lifecycleItem;
                if (andResume) {
                    lifecycleItem = ResumeActivityItem.obtain(mService.isNextTransitionForward());
                } else {
                    lifecycleItem = PauseActivityItem.obtain();
                }
                clientTransaction.setLifecycleStateRequest(lifecycleItem);

                // Schedule transaction.
                mService.getLifecycleManager().scheduleTransaction(clientTransaction);
                ...

        return true;
    }

在上面可以看到Android 9.0的启动方式与其他版本的不同,在Android 9.0里主要通过回调的方式启动Activity,最终会通过AMS中的ClientLifecycleManager.scheduleTransaction()方法调用ApplicationThread的scheduleTransaction(),最后的是执行的LaunchActivityItem的execute()方法。

/**TransactionExecutor**/
public void execute(ClientTransaction transaction) {
        final IBinder token = transaction.getActivityToken();
        //1.先执行CallBack
        executeCallbacks(transaction);
        //2.再执行Activity生命周期回调
        executeLifecycleState(transaction);
        mPendingActions.clear();
    }
/**LaunchActivityItem**/
public void execute(ClientTransactionHandler client, IBinder token,
            PendingTransactionActions pendingActions) {
        Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
        ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo,
                mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState, mPersistentState,
                mPendingResults, mPendingNewIntents, mIsForward,
                mProfilerInfo, client);
        client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
        Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
    }

可以看到这里调用了ClientTransactionHandler的handleLaunchActivity()方法。从这里Activity的启动过程就从AMS中的调用切换到了ActivityThread中去了。

从AMS到ActivityThread

上面说到,Activity的启动调用了ClientTransactionHandler的handleLaunchActivity()方法。我们可以发现ActivityThread是继承自ClientTransactionHandler的。在ClientTransactionHandler中handleLaunchActivity是抽象方法,我们直接在ActivityThread中看。

从这里开始将开始执行Activity的生命周期函数。

/**ActivityThread**/
public Activity handleLaunchActivity(ActivityClientRecord r,
            PendingTransactionActions pendingActions, Intent customIntent) {
        //......
        //初始化WindowManagerService
        WindowManagerGlobal.initialize();
        final Activity a = performLaunchActivity(r, customIntent);
        //......
        return a;
    }

可以看到在这里继续调用了

/**ActivityThread**/
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
       //......
        Activity activity = null;
        try {
            //获取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) {
            //......
        }

        try {
            //初始化Application
            Application app = r.packageInfo.makeApplication(false, mInstrumentation);

            if (activity != null) {
                //设置Context
                appContext.setOuterContext(activity);
                //调用Activity的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 (r.isPersistable()) {
                    //调用onCreate()生命周期函数
                    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
                } else {
                    mInstrumentation.mInstrumentation(activity, r.state);
                }
                //......
                int theme = r.activityInfo.getThemeResource();
                if (theme != 0) {
                    activity.setTheme(theme); //设置主题
                }
                //......
                r.activity = activity;
            }
            r.setState(ON_CREATE);
        }
        //......
        return activity;
    }

在上面的代码可以看到执行完Activity的attach()方法后,继续执行Instrumentation的callActivityOnCreate()方法。

/**Instrumentation**/
public void callActivityOnCreate(Activity activity, Bundle icicle) {
        prePerformCreate(activity);
        activity.performCreate(icicle);
        postPerformCreate(activity);
    }

这里可以看到,又执行了Activity的performCreate()方法。

/****/
final void performCreate(Bundle icicle, PersistableBundle persistentState) {
        //....
        //调用onCreate()生命周期方法
        if (persistentState != null) {
            onCreate(icicle, persistentState);
        } else {
            onCreate(icicle);
        }
    }

在上面的代码中调用了Activity的onCreate()生命周期方法。到这里,在上面讲到的TransactionExecutor的execute()方法中的回调已经执行完毕,接下来就是开始执行生命周期相关的回调。

我们在分析上面代码的时候知道,生命周期回调是一个ResumeActivityItem。

/**ResumeActivityItem**/ 
public void execute(ClientTransactionHandler client, IBinder token,
            PendingTransactionActions pendingActions) {
        Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityResume");
        client.handleResumeActivity(token, true /* finalStateRequest */, mIsForward,
                "RESUME_ACTIVITY");
        Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
    }

可以看到这里有调用了handleResumeActivity()方法。

public void handleResumeActivity(IBinder token, boolean finalStateRequest, boolean isForward,
            String reason) {
      
        final ActivityClientRecord r = performResumeActivity(token, finalStateRequest, reason); 
    }
public ActivityClientRecord performResumeActivity(IBinder token, boolean finalStateRequest,
            String reason) {
            //执行Activity的performResume
            r.activity.performResume(r.startsNotResumed, reason);

            r.state = null;
            r.persistentState = null;
            r.setState(ON_RESUME);
        } catch (Exception e) {
          
        }
        return r;
    }

在上面的代码中调用了Activity的performResume()方法。进而调用Activity的onResume()方法。这时Activity就呈现到了界面。Activity也算启动完成。

总结

上面以根Activity的视角分析了Activity的启动过程。整个分析下来,感觉到Activity的启动还是十分复杂的,但是在也并不需要面面俱到,能够把握大体,流程理解Android在启动Activity的过程中是怎么调度的,这样就达到了我们的目的。