Activity系列--Activity启动-源码分析

Activity跳转那一节介绍了Activity跳转相关的使用和基础知识,那这节就来升华一下:分析下Activity的启动流程,看它到底是怎么启动的.(下面的分析都是基于app进程已经存在,并且要启动的Activity没有启动过)

Activity启动原理

start-activity
start-activity

上面两张图分别展示了:app启动app内某个Activity的过程和app启动其他app某个Activity的过程,当然上面的图中都是以app/app1进程本身已经存在为前提,app进程不存在的话还需要涉及到进程创建的过程(进程创建属于这节的讨论范畴)

先来介绍几个知识点:

  • ActivityManagerService(为了方便简称为AMS)它位于系统进程,系统进程里面有很多的服务(比如WindowMnagerService),AMS只是其中的一个,它管理android中的四大组件.
  • app是位于它自己进程的,与系统进程完全不同.

不管是启动app内还是app外的Activity,都会经历三个过程:

  1. app请求AMS启动Activity(在app进程)
  2. AMS处理请求(在系统进程)
  3. app接收并处理AMS发出的信息(在app进程)

那就从这三个过程来进行分析

1.app请求AMS启动Activity

在前面章节中介绍过,启动(或跳转)Activity会先配置一个Intent,这个Intent存放的数据可是很丰富了:包含了启动Activity的信息,传递给Activity的数据,甚至还有启动Activity的方式等等.app进程与AMS不处于同一进程,它们之间的通信使用的是binder,Intent会在"binder这条搭建好的公路"上传递到AMS.

2.AMS处理请求

AMS拿到Intent后会做以下处理:

2.1.根据Intent去查询Activity的信息,那去哪查呢?答案是PMS服务

既然涉及到了PMS那就先来了解下它,PMS是PackageManagerService的简称,它也是一个运行在系统进程内的服务。它主要做的事情就是把手机上安装的所有apk里面的AndroidManifest(清单)文件里面的信息解析出来并且存储在内存。还记得在编写一个Activity的时候,需要在AndroidManifest文件中配置该Activity,最终清单文件及Activity等信息全部会打包到apk的文件中。AndroidManifest文件主要就是给PMS来用的,还记得在清单文件中配置Activity的时候,会为Activity配置intent-filter吗?intent-filter里面会包含action,category,data这些配置项目,这些信息也会被PMS解析出来。

为啥要去查询Activity的信息呢,原因是这样的:Intent分为显示和隐示。对于显示Intent,虽然Intent中指明了目标Activity的class信息,但是这个信息太少了,Activity的启动模式,权限等等其他信息完全不知道. 对于隐示Intent,那更需要去查了,隐示的根本就不知道目标Activity是谁.

查到来的Activity信息大体有:目标Activity的class信息,包名,权限,启动模式,action,data等等.

若PMS根据Intent没有查找到Activity,则停止后面的流程,把错误信息返回给app;否则继续后面的流程

2.2.各种检查,校验

需要对启动的参数,启动的进程等等并且结合查询到的Activity信息进行检查,校验.比如权限校验了(有些Activity不是谁都能启动的),是否对外可以启动等校验流程,如果一系列的校验都通过了,继续后面的流程.

2.3.保存启动的Activity,并且放入task

把要启动的Activity信息记录下来(记录的类叫ActivityRecord),依据app传递过来的Intent设置的flag信息及启动Activity的launchmode等信息来决定是否要创建task(对应的类Task)。若新创建了task,则把ActivityRecord放入task中,否则在原先的task放入ActivityRecord。

2.4.把数据返回给app

若启动的Activity对应的进程没有启动,需要等待进程启动完成. AMS会把很多重要的数据(如Activity信息,Intent,token等)数据(数据会被放入ClientTransaction这个类)中返回给app.

到此AMS的流程就结束了。

3.app接收并处理AMS发出的信息

app的AtivityThread的ApplicationThread类的scheduleTransaction方法会收到AMS发过来的ClientTransaction数据, 从中拿到目标Activity信息,通过反射初始化目标Activity实例,实例初始化完成后会接着调用它的onAttach,onCreate回调方法.

同时AtivityThread类也会把启动的Activity记录下来(记录的类是ActivityClientRecord),最终会把AMS传递过来的token作为key,ActivityClientRecord作为value存放在ArrayMap中。

小结

Activity的启动的流程如下:

  1. app把包含启动Activity等其他数据的Intent通过binder调用发送给AMS
  2. AMS通知PMS依据Intent解析出对应的Activity的信息.若解析成功,则对各种参数,进程信息结合解析到的Activity信息进行检查,校验.若成功则记录下启动Activity并把记录放入创建或已有的task中. 把Activity信息,Intent等数据通过binder调用发送给app
  3. app那到Activity信息,通过反射实例化Activity,并且调用它的onAttach,onCreate方法.

Activity启动源码分析

在进行源码分析之前先介绍下用到的前置知识

前置知识

进程之间通信:android app进程之间使用binder进行通信,下面的内容会涉及到binder(关于binder通信后面的章节会介绍)
线程之间通信:线程之间通信方式很多,android中线程之间通信一般都使用handler,下面介绍的内容就会涉及到handler。

相关的类
app相关:

frameworks/base/core/java/android/app/Activity.java
frameworks/base/core/java/android/app/Instrumentation.java
frameworks/base/core/java/android/app/ActivityThread.java

ams相关:

frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
frameworks/base/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
frameworks/base/services/core/java/com/android/server/wm/ActivityRecord.java

pms相关:

frameworks/base/core/java/android/content/pm/ResolveInfo.java
frameworks/base/core/java/android/content/pm/ActivityInfo.java

(以上源码版本是android 12)

关键类的介绍
ActivityThread:这个类的名字看上去容易造成误导,总以为是与Activity相关的Thread。其实它处理的事情可多了,在app进程创建成功后,ActivityThread中会启动一个主线程,这个主线程不断的在循环中取消息和执行消息,这样就能保证app一直能保持”活着“的状态。这个类还执行四大组件的初始化,并根据AMS发的指令调用四大组件的相应回调方法,并且还执行Application的相关初始化等工作。一个app进程中只有一个ActivityThread实例。
ApplicationThread:这个类继承了IApplicationThread.Stub,它也是Binder类型。它的主要作用就是接收来自AMS发送过来的消息。
Instrumentation:这个类的主要作用是对AMS传递过来四大组件及Application对应的字符串类型的Class,通过发射进行初始化;这个类还负责调用四大组件和Application的回调方法(比如Activity的onCreate方法,Application的onCreate方法)
ActivityClientRecord:这个类的主要作用就是在app进程保存启动的Activity等信息与AMS的ActivityRecord是一一对应关系。

ActivityTaskManagerService:简称ATMS,原先老版本的android代码里面是没有ATMS这个类的的。因为原先的AMS代码越来越臃肿,功能也很复杂(Service,Activity,Broadcast,ContentProvider相关的接口都在AMS中)。因此到了后面的android版本就AMS的代码进行了重构,把Activity相关的工作都放在了ATMS类中。
ActivityStarter:这个类的主要职责就是根据各种信息来决定如何启动Activity,并且根据各种信息来决定是把Activity放在一个新task中还是放在roottask中,为了节约宝贵的内存,该类的实例会被缓存在ActivityStartController类中。
ActivityRecord:这个类的主要作用是在系统进程中保存启动的Activity等信息。
ActivityRecord$Token:Token这个类,在原理篇提过,它是ActivityRecord与ActivityClientRecord的桥梁。

开始分析

如原理篇介绍,启动Activity有如下三个过程:

  1. app请求AMS启动Activity(在app进程)
  2. AMS处理请求(在系统进程)
  3. app接收并处理AMS发出的信息(在app进程)
    因此整个源码分析也以这三个过程来进行分析。

1.app请求AMS启动Activity

从Activity的startActivity方法开始吧,下面方法的执行都在app进程。

1.1 Activity#startActivity

    @Override
    public void startActivity(Intent intent) {
        this.startActivity(intent, null);
    }

    @Override
    public void startActivity(Intent intent, @Nullable Bundle options) {
        ......省略代码
        if (options != null) {
            startActivityForResult(intent, -1, options);
        } else {
            //因为options为null,因此进入这个环节
            // Note we want to go through this call for compatibility with
            // applications that may have overridden the method.
            //增加了requestCode为-1的参数,代表不需要关注这个Activity的返回数据
            startActivityForResult(intent, -1);
        }
    }

1.2 Activity#startActivityForResult

    public void startActivityForResult(@RequiresPermission Intent intent, int requestCode) {
        //调用同名方法,增加了一个Bundle为null的参数
        startActivityForResult(intent, requestCode, null);
    }

    public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
            @Nullable Bundle options) {
        //主要分析mParent== null的情况
        if (mParent == null) {
            options = transferSpringboardActivityOptions(options);
            //调用mInstrumentation.execStartActivity方法,
            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());
            }
            //对于requestCode大于0的情况,则把mStartedActivity置为true
            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 {
            ......省略代码
        }
    }

上面的方法主要做的事情:会根据mParent是否存在执行不同的逻辑,但是最终都会调用到同一方法。咱们主要分析mParent== null的情况。

介绍下mInstrumentation.execStartActivity方法的几个关键参数:

  • who:类型为Activity
  • contextThread:类型为IBinder,mMainThread.getApplicationThread()获取的是一个类型为IApplicationThread的对象,这个对象同时也是一个Binder对象,它会被传递给AMS,AMS拿到它可以与app进程进行通信。 mMainThread是ActivityThread的实例,一个进程内就进存在一个
  • token:类型IBinder,mToken是它的值,在上面原理篇介绍过。
  • intent:启动信息,参数等都在Intent内
  • requestCode:若是调用startActivityForResult方法,这个参数有用,否则没用。它若存在会传递给启动的Activity,Activity finish后并且调用了setResult方法,这个参数会被返回。当前值为-1

1.3 Instrumentation#execStartActivity

    public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
        //把contextThread转换为IApplicationThread
        IApplicationThread whoThread = (IApplicationThread) contextThread;
        Uri referrer = target != null ? target.onProvideReferrer() : null;
        if (referrer != null) {
            intent.putExtra(Intent.EXTRA_REFERRER, referrer);
        }
        ......省略代码
        try {
            intent.migrateExtraStreamToClipData(who);
            intent.prepareToLeaveProcess(who);
            //binder调用到ActivityTaskManagerService
            int result = ActivityTaskManager.getService().startActivity(whoThread,
                    who.getOpPackageName(), who.getAttributionTag(), intent,
                    intent.resolveTypeIfNeeded(who.getContentResolver()), token,
                    target != null ? target.mEmbeddedID : null, requestCode, 0, null, options);
            notifyStartActivityResult(result, options);
            checkStartActivityResult(result, intent);
        } catch (RemoteException e) {
            throw new RuntimeException("Failure from system", e);
        }
        return null;
    }

该方法做的事情主要是为intent添加一些额外的信息外,最终通过binder调用把参数发送到系统进程。

ActivityTaskManager.getService():获取的是ActivityTaskManagerService在app进程内的代理类的实例,这个代理类实现了IActivityTaskManager,同时它也是BinderProxy类型。

介绍下ActivityTaskManager.getService().startActivity方法的几个关键的参数:

  • caller:它的类型是IApplicationThread,whoThread是它的值
  • callingPackage:String类型,代表启动者的包名。who.getOpPackageName()是它的值
  • intent:自不必多说,包含启动的各项数据
  • token:代表发起启动的Activity(称它为启动者),在app进程它的类型是BinderProxy
  • requestCode:若使用的是startActivity这方法,这值是-1;否则是上层传递的值

小结

用一张时序图进行小结

image

2. AMS处理请求

下面方法的执行都在系统进程中

2.1 ActivityTaskManagerService#startActivity

    @Override
    public final int startActivity(IApplicationThread caller, String callingPackage,
            String callingFeatureId, Intent intent, String resolvedType, IBinder resultTo,
            String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo,
            Bundle bOptions) {
        //增加一个userId信息它的值是UserHandle.getCallingUserId()
        return startActivityAsUser(caller, callingPackage, callingFeatureId, intent, resolvedType,
                resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions,
                UserHandle.getCallingUserId());
    }

    @Override
    public int startActivityAsUser(IApplicationThread caller, String callingPackage,
            String callingFeatureId, Intent intent, String resolvedType, IBinder resultTo,
            String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo,
            Bundle bOptions, int userId) {
        //增加一个validateIncomingUser参数,它的值为true
        return startActivityAsUser(caller, callingPackage, callingFeatureId, intent, resolvedType,
                resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions, userId,
                true /*validateIncomingUser*/);
    }

     private int startActivityAsUser(IApplicationThread caller, String callingPackage,
            @Nullable String callingFeatureId, Intent intent, String resolvedType,
            IBinder resultTo, String resultWho, int requestCode, int startFlags,
            ProfilerInfo profilerInfo, Bundle bOptions, int userId, boolean validateIncomingUser) {
        assertPackageMatchesCallingUid(callingPackage);
        enforceNotIsolatedCaller("startActivityAsUser");

        userId = getActivityStartController().checkTargetUser(userId, validateIncomingUser,
                Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser");

        // TODO: Switch to user app stacks here.
        [2.1 obtainStarter]
        int res = getActivityStartController().obtainStarter(intent, "startActivityAsUser")
                .setCaller(caller)
                .setCallingPackage(callingPackage)
                .setCallingFeatureId(callingFeatureId)
                .setResolvedType(resolvedType)
                .setResultTo(resultTo)
                .setResultWho(resultWho)
                .setRequestCode(requestCode)
                .setStartFlags(startFlags)
                .setProfilerInfo(profilerInfo)
                .setActivityOptions(bOptions)
                .setUserId(userId)
                .execute();
        return res;
    }

[2.1 obtainStarter]
getActivityStartController().obtainStarter方法的介绍。

getActivityStartController()会获取一个ActivityStartController类的实例,ActivityStartController中缓存了ActivityStarter,这样就不需要每次都new一个ActivityStarter出来,浪费宝贵的内存了。

obtainStarter方法会获取一个已有或创建一个新的ActivityStarter类实例,这个类的主要职责就是根据各种信息来决定如何启动Activity,并且根据各种信息来决定是把Activity放在一个新task中还是放在roottask中。

初始化ActivityStarter的几个关键参数介绍:

  • caller:IApplicationThread类型,app进程中传递过来的IApplicationThread,它现在的类型是BinderProxy
  • callingPackage:String类型,启动者包名,有了这个信息对于分析问题是非常重要的,比如:有时候Activity莫名其妙的就启动了,这时候去看callingPackage就可以知道是谁启动的。
  • resultTo:IBinder类型,代表发起启动的Activity(启动者),在app进程中它的类型是BinderProxy。进入系统进程后它的类型会被转换为Binder。(这是binder机制,后面介绍binder机制的时候会介绍)

ActivityStarter定义了一套可以链式调用的方法,简单看下几个方法:

    ActivityStarter setProfilerInfo(ProfilerInfo info) {
        mRequest.profilerInfo = info;
        return this;
    }

    ActivityStarter setGlobalConfiguration(Configuration config) {
        mRequest.globalConfig = config;
        return this;
    }

    ActivityStarter setUserId(int userId) {
        mRequest.userId = userId;
        return this;
    }

在设置完属性后,返回this,这样就可以接着在调用另外的设置方法了。ActivityStarter设置的属性都存放在了mRequest这个实例中。

初始化完毕ActivityStarter,会调用它的execute方法。

2.2 ActivityStarter#execute

    int execute() {
        try {
            省略代码......

            final LaunchingState launchingState;
            synchronized (mService.mGlobalLock) {
                //获取启动者
                final ActivityRecord caller = ActivityRecord.forTokenLocked(mRequest.resultTo);
                //获取callingUid
                final int callingUid = mRequest.realCallingUid == Request.DEFAULT_REAL_CALLING_UID
                        ?  Binder.getCallingUid() : mRequest.realCallingUid;
                launchingState = mSupervisor.getActivityMetricsLogger().notifyActivityLaunching(
                        mRequest.intent, caller, callingUid);
            }

            // If the caller hasn't already resolved the activity, we're willing
            // to do so here. If the caller is already holding the WM lock here,
            // and we need to check dynamic Uri permissions, then we're forced
            // to assume those permissions are denied to avoid deadlocking.
            //activityInfo为null 则需要去解析
            if (mRequest.activityInfo == null) {
                mRequest.resolveActivity(mSupervisor);
            }

            int res;
            //启动的时候使用mService.mGlobalLock锁保持同步
            synchronized (mService.mGlobalLock) {
                final boolean globalConfigWillChange = mRequest.globalConfig != null
                        && mService.getGlobalConfiguration().diff(mRequest.globalConfig) != 0;
                final Task rootTask = mRootWindowContainer.getTopDisplayFocusedRootTask();
                
                省略代码......

                res = executeRequest(mRequest);

                省略代码......

                if (mRequest.waitResult != null) {
                    mRequest.waitResult.result = res;
                    res = waitResultIfNeeded(mRequest.waitResult, mLastStartActivityRecord,
                            launchingState);
                }
                return getExternalResult(res);
            }
        } finally {
            onExecutionComplete();
        }
    }

该方法主要做了以下事情:

  1. 若mRequest.activityInfo为null,回调用mRequest.resolveActivity(mSupervisor)方法开始解析过程,最终会进入PMS(PackageManagerService)中根据intent解析出ResolveInfo和ActivityInfo
  2. 调用executeRequest方法开始进入下个流程

PMS根据intent解析ResolveInfo和ActivityInfo的流程在这就不赘述了,不过有必要介绍下ResolveInfo和ActivityInfo这两个类。

ResolveInfo

看下它的几个关键属性:

public class ResolveInfo implements Parcelable {
    private static final String TAG = "ResolveInfo";
    private static final String INTENT_FORWARDER_ACTIVITY =
            "com.android.internal.app.IntentForwarderActivity";

    /**
     * The activity or broadcast receiver that corresponds to this resolution
     * match, if this resolution is for an activity or broadcast receiver.
     * Exactly one of {@link #activityInfo}, {@link #serviceInfo}, or
     * {@link #providerInfo} will be non-null.
     */
    public ActivityInfo activityInfo;

    /**
     * The service that corresponds to this resolution match, if this resolution
     * is for a service. Exactly one of {@link #activityInfo},
     * {@link #serviceInfo}, or {@link #providerInfo} will be non-null.
     */
    public ServiceInfo serviceInfo;

    /**
     * The provider that corresponds to this resolution match, if this
     * resolution is for a provider. Exactly one of {@link #activityInfo},
     * {@link #serviceInfo}, or {@link #providerInfo} will be non-null.
     */
    public ProviderInfo providerInfo;

    /**
     * An auxiliary response that may modify the resolved information. This is
     * only set under certain circumstances; such as when resolving instant apps
     * or components defined in un-installed splits.
     * @hide
     */
    public AuxiliaryResolveInfo auxiliaryInfo;

    /**
     * Whether or not an instant app is available for the resolved intent.
     */
    public boolean isInstantAppAvailable;

    /**
     * The IntentFilter that was matched for this ResolveInfo.
     */
    public IntentFilter filter;

    省略代码......
}

ResolveInfo实现了Parcelable,代表它可以通过binder在进程之间进行传递。在AndroidManifest配置的四大组件解析完后的数据会放入ResolveInfo类中。

如上,它里面的几个关键属性:

  • activityInfo,serviceInfo,providerInfo:分别代表Activity,Broadcast,Service,ContentProvider
  • filter:在AndroidManifest里面配置的Intent-filter这一项

用一个AndroidManifest.xml例子来说下ResolveInfo,
AndroidManifest.xml有如下信息:




    
        
            
                

                
            
        
        
    


上面的清单文件信息会被解析成两个ResolveInfo:
其中一个它的activityInfo包含的信息是MainActivity,它的filter包含的信息是action为android.intent.action.MAIN,category为android.intent.category.LAUNCHER。
另一个它的activityInfo包含的信息是SecondActivity,它的filter为null

介绍完ResolveInfo,介绍下ActivityInfo这个类。

ActivityInfo
主要显示它的几个关键属性:

public class ActivityInfo extends ComponentInfo implements Parcelable {
    public int theme;
    public int launchMode;
    public String taskAffinity;
    public String name;
    public String packageName;

    省略代码......
}

ActivityInfo包含了在AndroidManifest里面配置的Activity的信息,它上面的几个属性:

  • theme:Activity的主题
  • launchMode:配置的Activity的启动模式
  • taskAffinity:指定Activity放在哪个名字下面的task
  • name:Activity的完整的classname
  • packageName:包名

2.3 ActivityStarter#executeRequest

    private int executeRequest(Request request) {
        if (TextUtils.isEmpty(request.reason)) {
            throw new IllegalArgumentException("Need to specify a reason.");
        }
        mLastStartReason = request.reason;
        mLastStartActivityTimeMs = System.currentTimeMillis();
        mLastStartActivityRecord = null;

        final IApplicationThread caller = request.caller;
        Intent intent = request.intent;
        NeededUriGrants intentGrants = request.intentGrants;
        String resolvedType = request.resolvedType;
        ActivityInfo aInfo = request.activityInfo;
        ResolveInfo rInfo = request.resolveInfo;
        final IVoiceInteractionSession voiceSession = request.voiceSession;
        final IBinder resultTo = request.resultTo;
        String resultWho = request.resultWho;
        int requestCode = request.requestCode;
        int callingPid = request.callingPid;
        int callingUid = request.callingUid;
        String callingPackage = request.callingPackage;
        String callingFeatureId = request.callingFeatureId;
        final int realCallingPid = request.realCallingPid;
        final int realCallingUid = request.realCallingUid;
        final int startFlags = request.startFlags;
        final SafeActivityOptions options = request.activityOptions;
        Task inTask = request.inTask;

        int err = ActivityManager.START_SUCCESS;
        
        省略代码......

        WindowProcessController callerApp = null;
        //根据caller获取callerApp
        if (caller != null) {
            callerApp = mService.getProcessController(caller);
            if (callerApp != null) {
                callingPid = callerApp.getPid();
                callingUid = callerApp.mInfo.uid;
            } else {
                Slog.w(TAG, "Unable to find app for caller " + caller + " (pid=" + callingPid
                        + ") when starting: " + intent.toString());
                err = ActivityManager.START_PERMISSION_DENIED;
            }
        }

        //获取userId
        final int userId = aInfo != null && aInfo.applicationInfo != 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找到sourceRecord,resultTo是一个Token,sourceRecord启动者
            sourceRecord = mRootWindowContainer.isInAnyTask(resultTo);
            if (DEBUG_RESULTS) {
                Slog.v(TAG_RESULTS, "Will send result to " + resultTo + " " + sourceRecord);
            }
            if (sourceRecord != null) {
                //如果是startActivityForResult启动的,则对resultRecord赋值
                if (requestCode >= 0 && !sourceRecord.finishing) {
                    resultRecord = sourceRecord;
                }
            }
        }

        final int launchFlags = intent.getFlags();
        
        省略各种出错信息的判断代码......

        //根据resultRecord找到resultRootTask
        final Task resultRootTask = resultRecord == null
                ? null : resultRecord.getRootTask();

        if (err != START_SUCCESS) {
            if (resultRecord != null) {
                resultRecord.sendResult(INVALID_UID, resultWho, requestCode, RESULT_CANCELED,
                        null /* data */, null /* dataGrants */);
            }
            SafeActivityOptions.abort(options);
            return err;
        }

        省略权限判断等各种其他代码......

        //构造ActivityRecord
        final ActivityRecord r = new ActivityRecord.Builder(mService)
                .setCaller(callerApp)
                .setLaunchedFromPid(callingPid)
                .setLaunchedFromUid(callingUid)
                .setLaunchedFromPackage(callingPackage)
                .setLaunchedFromFeature(callingFeatureId)
                .setIntent(intent)
                .setResolvedType(resolvedType)
                .setActivityInfo(aInfo)
                .setConfiguration(mService.getGlobalConfiguration())
                .setResultTo(resultRecord)
                .setResultWho(resultWho)
                .setRequestCode(requestCode)
                .setComponentSpecified(request.componentSpecified)
                .setRootVoiceInteraction(voiceSession != null)
                .setActivityOptions(checkedOptions)
                .setSourceRecord(sourceRecord)
                .build();

        mLastStartActivityRecord = r;

        //调用startActivityUnchecked方法开始进入下个启动
        mLastStartActivityResult = startActivityUnchecked(r, sourceRecord, voiceSession,
                request.voiceInteractor, startFlags, true /* doResume */, checkedOptions, inTask,
                restrictedBgActivity, intentGrants);

        if (request.outActivity != null) {
            request.outActivity[0] = mLastStartActivityRecord;
        }

        return mLastStartActivityResult;
    }

该方法主要做了以下工作:

  1. 在启动之前,对各种基础的异常进行检测,发现有异常则退出启动Activity流程
  2. 检测通过后构造了一个ActivityRecord实例
  3. 开始进入启动Activity的流程

构造了一个ActivityRecord实例,对这个实例初始化主要用到了以下参数:

  • callerApp:WindowProcessController类型,主要是启动者相关的信息
  • callingPid:启动者的进程id
  • callingUid:启动者的id,每个安装的app都会分配一个唯一的id,这个id在当前的用户空间内是不会变化的
  • intent:把intent存起来
  • aInfo:从AndroidManifest中解析出来的Activity信息
  • resultRecord:对于startActivityForResult启动activity时候的启动这信息,用于把返回结果返回给resultRecord
  • requestCode:对于startActivityForResult启动activity时候传递的值
  • sourceRecord:启动者,代表谁启动了Activity

ActivityRecord就把app进程要启动的Activity及相关的其他信息保存下来了,要注意这里提到的Activity和app进程中要启动的Activity是两码事。

该方法调用startActivityUnchecked方法进入启动的下个流程,调用的时候关键参数有:

  • r: ActivityRecord类型
  • sourceRecord:启动者,是一个ActivityRecord
  • doResume:它的值为true
  • options:它的值为checkedOptions,checkedOptions的值现在是为null
  • inTask:代表启动的Activity存放的task,当前它的值为null(因为在初始化ActivityRecord的时候就没有设置它)

2.4 ActivityStarter#startActivityUnchecked

    private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
                IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
                int startFlags, boolean doResume, ActivityOptions options, Task inTask,
                boolean restrictedBgActivity, NeededUriGrants intentGrants) {
        int result = START_CANCELED;
        final Task startedActivityRootTask;

        省略代码......

        try {
            mService.deferWindowLayout();
            Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "startActivityInner");
            [2.5]
            //doResume:true,options值为null,inTask:null
            result = startActivityInner(r, sourceRecord, voiceSession, voiceInteractor,
                    startFlags, doResume, options, inTask, restrictedBgActivity, intentGrants);
        } finally {
            省略代码......
        }

        postStartActivityProcessing(r, result, startedActivityRootTask);

        return result;
    }

2.5 ActivityStarter#startActivityInner

    int startActivityInner(final ActivityRecord r, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            int startFlags, boolean doResume, ActivityOptions options, Task inTask,
            boolean restrictedBgActivity, NeededUriGrants intentGrants) {
            
        //调用这个方法重置activityStarter的各种数据
        setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
                voiceInteractor, restrictedBgActivity);

        //设置launchmode
        computeLaunchingTaskFlags();
        //查找mSourceRootTask
        computeSourceRootTask();

        mIntent.setFlags(mLaunchFlags);
        
        //获取reusabletask
        final Task reusedTask = getReusableTask();

        省略冻结task代码......

        // Compute if there is an existing task that should be used for.
        //如果reusedTask为null,则调用computeTargetTask()方法获取
        final Task targetTask = reusedTask != null ? reusedTask : computeTargetTask();
        //newTask是否是新task
        final boolean newTask = targetTask == null;
        mTargetTask = targetTask;

        
        computeLaunchParams(r, sourceRecord, targetTask);

        省略代码......

        //如果mTargetRootTask为null,则调用getLaunchRootTask方法会获取或者创建一个task
        if (mTargetRootTask == null) {
            mTargetRootTask = getLaunchRootTask(mStartActivity, mLaunchFlags, targetTask, mOptions);
        }
        //如果是新的task,则进行创建task流程,并且把ActivityRecord放置在task中
        if (newTask) {
            final Task taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
                    ? mSourceRecord.getTask() : null;
            setNewTask(taskToAffiliate);
        } else if (mAddingToTask) {
            //把ActivityRecord放置在找到的task中
            addOrReparentStartingActivity(targetTask, "adding to task");
        }

        省略代码......
        
        if (mDoResume) {
            final ActivityRecord topTaskActivity =
                    mStartActivity.getTask().topRunningActivityLocked();
            //不关注这块逻辑,直接看下面的else
            if (!mTargetRootTask.isTopActivityFocusable()
                    || (topTaskActivity != null && topTaskActivity.isTaskOverlay()
                    && 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.
                // Passing {@code null} as the start parameter ensures all activities are made
                // visible.
                mTargetRootTask.ensureActivitiesVisible(null /* starting */,
                        0 /* configChanges */, !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.
                mTargetRootTask.mDisplayContent.executeAppTransition();
            } else {
                // If the target root-task was not previously focusable (previous top running
                // activity on that root-task was not visible) then any prior calls to move the
                // root-task to the will not update the focused root-task.  If starting the new
                // activity now allows the task root-task to be focusable, then ensure that we
                // now update the focused root-task accordingly.
                //如果mTargetRootTask在mRootWindowContainer不处于focus状态,则调用mTargetRootTask.moveToFront方法把它设置为focus状态
                if (mTargetRootTask.isTopActivityFocusable()
                        && !mRootWindowContainer.isTopDisplayFocusedRootTask(mTargetRootTask)) {
                    mTargetRootTask.moveToFront("startActivityInner");
                }
                //  开始进入下一步的启动Activity操作
                mRootWindowContainer.resumeFocusedTasksTopActivities(
                        mTargetRootTask, mStartActivity, mOptions, mTransientLaunch);
            }
        }
        
        省略代码......

        return START_SUCCESS;
    }

startActivityInner方法的逻辑相对复杂,下面先简要的分析下调用的几个方法做的事情:

  1. setInitialState方法
    该方法主要对当前ActivityStarter的相关属性进行初始化,介绍下ActivityStarter的几个关键属性:

    • mStartActivity:代表正在启动的Activity,类型为ActivityRecord
    • mIntent:存放启动的其他信息
    • mCallingUid:启动者的uid
    • mSourceRecord:启动这,类型为ActivityRecord
    • mLaunchMode:启动模式
    • mLaunchFlags:启动的flags
    • mInTask:ActivityRecord放入的task
    • mNoAnimation:启动过程中是否有动画
    • mInTask:启动的Activity放入的task
  2. computeLaunchingTaskFlags方法
    该方法做的工作是设置mLaunchFlags,依据以下条件进行设置:

    1. 如果mSourceRecord为null并且mInTask为不null,在根据一些条件判断是否能使用mInTask(这个暂时不在这节的讨论范围)
    2. 如果不满足步骤1,则进入步骤2,把mInTask置为null
    3. 如果mInTask为null,则会有如下情况为mLaunchFlags增加FLAG_ACTIVITY_NEW_TASK
      3.1. mSourceRecord为null(这种情况一般发生于比如在Service中或者Broadcast中启动Activity)
      3.2. mSourceRecord启动者的启动模式是LAUNCH_SINGLE_INSTANCE(singleInstance启动模式代表Activity只能处于自己单独的task中)
      3.3. 正在启动的Activity的mLaunchMode是LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK中的任意一个
  3. computeSourceRootTask
    该方法主要工作是获取mSourceRootTask,简单来介绍下rootTask和task,task不单单可以包含ActivityRecord,它还可以包含task,rootTask就是ActivityRecord的task的task的task等(直到task的parent不是task的时候就结束)

  4. getReusableTask
    这个方法的主要工作就是获取是否有可以重用的task,如果有则返回,否则返回null,大概的一个过程如下:

    1. putIntoExistingTask的值主要由 mInTask == null && mStartActivity.resultTo == null来决定,mInTask如果不为null,肯定不需要查找可重用的task了
    2. 如果putIntoExistingTask为true,则根据一些条件获取intentActivity
    3. 在根据一些条件决定intentActivity是否置为null
    4. 如果intentActivity不为null,则把它的task返回
  5. computeTargetTask
    该方法的主要工作是获取Activity可以放入的task,分以下条件获取:

    1. 根据mInTask,mLaunchFlags,mStartActivity.resultTo,mAddingToTask判断是否需要创建新task,是的话返回null
    2. mSourceRecord不为null的话,返回它的task
    3. mInTask不为null,则返回它
    4. 其他情况获取task

startActivityInner方法主要做了以下事情:

  1. 根据一些条件来决定是创建一个新的task还是使用已有的task,并且把ActivityRecord放入task中
  2. 如果mDoResume为true,则最终会调用mRootWindowContainer.resumeFocusedTasksTopActivities方法进入下一步启动Activity的操作。

调用mRootWindowContainer.resumeFocusedTasksTopActivities方法,来介绍下它的参数:

  • targetRootTask:Task类型,它的值是mTargetRootTask,正在启动的Activity对应的ActivityRecord已经放入了这个task内
  • ActivityRecord: ActivityRecord类型,它的值是mStartActivity(保存了正在启动的activity等信息)
  • targetOptions:ActivityOptions类型,它的值为null
  • deferPause:代表是否延迟pause top Activity,它的值为false(mTransientLaunch默认是false)

2.6 RootWindowContainer#resumeFocusedTasksTopActivities

    boolean resumeFocusedTasksTopActivities(
            Task targetRootTask, ActivityRecord target, ActivityOptions targetOptions,
            boolean deferPause) {
        if (!mTaskSupervisor.readyToResume()) {
            return false;
        }

        boolean result = false;
        //targetRootTask不为null并且targetRootTask是在DisplayArea中是最顶层的roottask,则进入下面逻辑
        if (targetRootTask != null && (targetRootTask.isTopRootTaskInDisplayArea()
                || getTopDisplayFocusedRootTask() == targetRootTask)) {
            [2.7]
            //targetOptions为null,deferPause为false
            result = targetRootTask.resumeTopActivityUncheckedLocked(target, targetOptions,
                    deferPause);
        }

        省略代码......

        return result;
    }

2.7 Task#resumeTopActivityUncheckedLocked

    boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options,
            boolean deferPause) {
        //正在resume top,则直接返回
        if (mInResumeTopActivity) {
            // Don't even start recursing.
            return false;
        }

        boolean someActivityResumed = false;
        try {
            // Protect against recursion.
            mInResumeTopActivity = true;
            //当前的task是叶子task(就是task的孩子都是ActivityRecord),就执行下面逻辑(咱们分析这个流程)
            if (isLeafTask()) {
                //task是否focus并且可见
                if (isFocusableAndVisible()) {
                    [2.8]
                    //prev为正在启动的Activity对应的ActivityRecord,options:null,deferPause:false
                    someActivityResumed = resumeTopActivityInnerLocked(prev, options, deferPause);
                }
            } else {
                //当前的task的孩子还是task,走下面逻辑
                int idx = mChildren.size() - 1;
                while (idx >= 0) {
                    final Task child = (Task) getChildAt(idx--);
                    if (!child.isTopActivityFocusable()) {
                        continue;
                    }
                    if (child.getVisibility(null /* starting */) != TASK_VISIBILITY_VISIBLE) {
                        break;
                    }

                    someActivityResumed |= child.resumeTopActivityUncheckedLocked(prev, options,
                            deferPause);
                    // Doing so in order to prevent IndexOOB since hierarchy might changes while
                    // resuming activities, for example dismissing split-screen while starting
                    // non-resizeable activity.
                    if (idx >= mChildren.size()) {
                        idx = mChildren.size() - 1;
                    }
                }
            }

            省略代码......
        } finally {
            mInResumeTopActivity = false;
        }

        return someActivityResumed;
    }

2.8 Task#resumeTopActivityInnerLocked

    private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options,
            boolean deferPause) {
        if (!mAtmService.isBooting() && !mAtmService.isBooted()) {
            // Not ready yet!
            return false;
        }

        // Find the next top-most activity to resume in this root task 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.
        //next代表当前task中已经显示的Activity
        ActivityRecord next = topRunningActivity(true /* focusableOnly */);

        省略代码......

        //deferPause的值为false
        boolean pausing = !deferPause && taskDisplayArea.pauseBackTasks(next);
        //mResumedActivity代表当前task中已经显示的Activity,若不为null,说明在启动其他Activity的时候,需要让mResumedActivity进入pause状态
        if (mResumedActivity != null) {
            ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivityLocked: Pausing %s", mResumedActivity);
            //下面方法会让mResumedActivity进入pause状态,为启动新的Activity做准备
            pausing |= startPausingLocked(false /* uiSleeping */, next,
                    "resumeTopActivityInnerLocked");
        }
        //如果mResumedActivity正在处于pausing状态,进入下面的逻辑
        if (pausing) {
            ProtoLog.v(WM_DEBUG_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.
            //next.attachedToProcess()为true,代表next已经启动过了,则更新它的进程等信息
            if (next.attachedToProcess()) {
                next.app.updateProcessInfo(false /* updateServiceConnectionActivities */,
                        true /* activityChange */, false /* updateOomAdj */,
                        false /* addPendingTopUid */);
            } else if (!next.isProcessRunning()) {
                // Since the start-process is asynchronous, if we already know the process of next
                // activity isn't running, we can start the process earlier to save the time to wait
                // for the current activity to be paused.
                final boolean isTop = this == taskDisplayArea.getFocusedRootTask();
                //next.isProcessRunning()为false,代表启动的activity的进程还没被启动,乘mResumedActivity处于pausing的状态,去异步启动进程
                mAtmService.startProcessAsync(next, false /* knownToBeDead */, isTop,
                        isTop ? "pre-top-activity" : "pre-activity");
            }
            if (lastResumed != null) {
                lastResumed.setWillCloseOrEnterPip(true);
            }
            return true;
        } else if (mResumedActivity == next && next.isState(RESUMED)
                && taskDisplayArea.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);
            ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivityLocked: Top activity resumed "
                    + "(dontWaitForPause) %s", next);
            return true;
        }

        省略代码......

        //next.attachedToProcess()为true,代表next已经启动过了,执行下面的逻辑,会把让Activity进入resume状态
        if (next.attachedToProcess()) {
            
            省略代码......

            try {
                final ClientTransaction transaction =
                        ClientTransaction.obtain(next.app.getThread(), next.appToken);
                // Deliver all pending results.
                ArrayList a = next.results;
                //a代表从上个Activity是否返回了一些数据
                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);
                        //从上个Activity返回了数据,则给transaction add一个ActivityResultItem
                        transaction.addCallback(ActivityResultItem.obtain(a));
                    }
                }


                if (next.newIntents != null) {
                    //若存在newIntents,则add 一个NewIntentItem,这种情况针对的Activity的启动模式是singleTask,singleInstance,singleTop
                    transaction.addCallback(
                            NewIntentItem.obtain(next.newIntents, true /* resume */));
                }

                // Well the app will no longer be stopped.
                // Clear app token stopped state in window manager if needed.
                next.notifyAppResumed(next.stopped);

                EventLogTags.writeWmResumeActivity(next.mUserId, System.identityHashCode(next),
                        next.getTask().mTaskId, next.shortComponentName);

                mAtmService.getAppWarningsLocked().onResumeActivity(next);
                next.app.setPendingUiCleanAndForceProcessStateUpTo(mAtmService.mTopProcessState);
                next.abortAndClearOptionsAnimation();
                
                //通知Activity进入resume状态
                transaction.setLifecycleStateRequest(
                        ResumeActivityItem.obtain(next.app.getReportedProcState(),
                                dc.isNextTransitionForward()));
                mAtmService.getLifecycleManager().scheduleTransaction(transaction);

                ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivityLocked: Resumed %s", next);
            } catch (Exception e) {
                省略代码......
                return true;
            }

            省略代码......

        } else {
            省略代码......
            //Activity需要从onCreate方法开始执行
            mTaskSupervisor.startSpecificActivity(next, true, true);
        }

        return true;
    }

resumeTopActivityInnerLocked方法的逻辑相对复杂,下面就来介绍下它主要做的事情:

  1. 如果正在显示的Activity(mResumedActivity)存在,则需要让它进入pause状态(最终会把这个消息通知到app对应的Activity)

  2. 如果正在显示的Activity已处于pausing状态,这时候需要分情况来处理:
    2.1 若正在启动的Activity(next)之前已经启动过了,则需要更新它对应的进程状态
    2.2 若正在启动的Activity的进程还没有启动,这时候异步启动进程的操作

    接着暂停启动Activity的操作,直接返回。那什么时候继续开始启动Activity呢?答案是:当mResumedActivity对应的app端的Activity完全的进入pause状态后,才会接着继续启动Activity。
    并且可以借助等待pause完毕的这个时机,更新进程状态或者异步启动进程

  3. 如果正在启动的Activity(next)已经启动过了(next.attachedToProcess()这值为true),则会走下面逻辑:
    3.1 若从上个Activity返回了数据,则把数据返回给app端的Activity(onActivityForResult方法会被调用)
    3.2 若存在newIntents,则把intent返回给app端的Activity(onNewIntent方法会被调用),这种情况针对的Activity的启动模式是singleTask,singleInstance,singleTop

    通知app端Activity进入resume状态(onResume方法会被调用)

  4. 否则,调用mTaskSupervisor.startSpecificActivity正真进入Activity的启动流程

2.9 ActivityTaskSupervisor#startSpecificActivity

    //r:正在启动的Activity,andResume:当前值为true,checkConfig:当前值true
    void startSpecificActivity(ActivityRecord r, boolean andResume, boolean checkConfig) {
        // Is this activity's application already running?
        final WindowProcessController wpc =
                mService.getProcessController(r.processName, r.info.applicationInfo.uid);

        boolean knownToBeDead = false;
        //对应的app进程是否启动,启动则进入下面逻辑
        if (wpc != null && wpc.hasThread()) {
            try {
                [2.10]
                realStartActivityLocked(r, wpc, 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.
            knownToBeDead = true;
        }

        r.notifyUnknownVisibilityLaunchedForKeyguardTransition();
     
        final boolean isTop = andResume && r.isTopRunningActivity();
        //异步启动进程
        mService.startProcessAsync(r, knownToBeDead, isTop, isTop ? "top-activity" : "activity");
    }

2.10 ActivityTaskSupervisor#realStartActivityLocked

    //r:正在启动的Activity,proc:对应的进程,andResume:true,checkConfig:true
    boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc,
            boolean andResume, boolean checkConfig) throws RemoteException {

        if (!mRootWindowContainer.allPausedActivitiesComplete()) {
            // While there are activities pausing we skipping starting any new activities until
            // pauses are complete. NOTE: that we also do this for activities that are starting in
            // the paused state because they will first be resumed then paused on the client side.
            ProtoLog.v(WM_DEBUG_STATES,
                    "realStartActivityLocked: Skipping start of r=%s some activities pausing...",
                    r);
            return false;
        }

        final Task task = r.getTask();
        final Task rootTask = task.getRootTask();

        beginDeferResume();
        // The LaunchActivityItem also contains process configuration, so the configuration change
        // from WindowProcessController#setProcess can be deferred. The major reason is that if
        // the activity has FixedRotationAdjustments, it needs to be applied with configuration.
        // In general, this reduces a binder transaction if process configuration is changed.
        proc.pauseConfigurationDispatch();

        try {
            r.startFreezingScreenLocked(proc, 0);

            // schedule launch ticks to collect information about slow apps.
            r.startLaunchTickingLocked();
            //设置了proc后,r.attachedToProcess()的值就为true
            r.setProcess(proc);

            // Ensure activity is allowed to be resumed after process has set.
            if (andResume && !r.canResumeByCompat()) {
                andResume = false;
            }

            省略代码......

            try {
                //proc.hasThread()代表app端是否活着
                if (!proc.hasThread()) {
                    throw new RemoteException();
                }
                List results = null;
                List newIntents = null;
                if (andResume) {
                    // We don't need to deliver new intents and/or set results if activity is going
                    // to pause immediately after launch.
                    results = r.results;
                    newIntents = r.newIntents;
                }
                if (DEBUG_SWITCH) Slog.v(TAG_SWITCH,
                        "Launching: " + r + " savedState=" + r.getSavedState()
                                + " with results=" + results + " newIntents=" + newIntents
                                + " andResume=" + andResume);
                EventLogTags.writeWmRestartActivity(r.mUserId, System.identityHashCode(r),
                        task.mTaskId, r.shortComponentName);
                if (r.isActivityTypeHome()) {
                    // Home process is the root process of the task.
                    updateHomeProcess(task.getBottomMostActivity().app);
                }
                mService.getPackageManagerInternalLocked().notifyPackageUse(
                        r.intent.getComponent().getPackageName(), NOTIFY_PACKAGE_USE_ACTIVITY);
                r.forceNewConfig = false;
                mService.getAppWarningsLocked().onStartActivity(r);
                r.compat = mService.compatibilityInfoForPackageLocked(r.info.applicationInfo);

                // Because we could be starting an Activity in the system process this may not go
                // across a Binder interface which would create a new Configuration. Consequently
                // we have to always create a new Configuration here.
                final Configuration procConfig = proc.prepareConfigurationForLaunchingActivity();
                final MergedConfiguration mergedConfiguration = new MergedConfiguration(
                        procConfig, r.getMergedOverrideConfiguration());
                r.setLastReportedConfiguration(mergedConfiguration);

                logIfTransactionTooLarge(r.intent, r.getSavedState());

                if (r.isEmbedded()) {
                    // Sending TaskFragmentInfo to client to ensure the info is updated before
                    // the activity creation.
                    mService.mTaskFragmentOrganizerController.dispatchPendingInfoChangedEvent(
                            r.getOrganizedTaskFragment());
                }

                // Create activity launch transaction.
                //ClientTransaction主要用于添加各种callback以及Activity要执行的生命周期方法,它会通过binder传递到app进程
                //proc.getThread()获取的是IApplicationThread的实例,主要通过它给app发送消息,r.appToken发送给app的token
                final ClientTransaction clientTransaction = ClientTransaction.obtain(
                        proc.getThread(), r.appToken);

                final boolean isTransitionForward = r.isTransitionForward();
                //add一个LaunchActivityItem类型的callback
                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.getFilteredReferrer(r.launchedFromPackage), task.voiceInteractor,
                        proc.getReportedProcState(), r.getSavedState(), r.getPersistentSavedState(),
                        results, newIntents, r.takeOptions(), isTransitionForward,
                        proc.createProfilerInfoIfNeeded(), r.assistToken, activityClientController,
                        r.createFixedRotationAdjustmentsIfNeeded(), r.shareableActivityToken,
                        r.getLaunchedFromBubble()));

                // Set desired final state.
                final ActivityLifecycleItem lifecycleItem;
                if (andResume) {
                    //因为andResume为true,进入这,构造一个ResumeActivityItem实例,Activity的onResume方法被执行
                    lifecycleItem = ResumeActivityItem.obtain(isTransitionForward);
                } else {
                    //否则构造一个PauseActivityItem实例,Activity的onPause方法会被执行
                    lifecycleItem = PauseActivityItem.obtain();
                }
                clientTransaction.setLifecycleStateRequest(lifecycleItem);

                // Schedule transaction.
                //clientTransaction会被传递到app进程
                mService.getLifecycleManager().scheduleTransaction(clientTransaction);

                省略代码......

            } catch (RemoteException e) {
                省略代码......
            }
        } finally {
            endDeferResume();
            proc.resumeConfigurationDispatch();
        }

        r.launchFailed = false;

        省略代码......

        return true;
    }

该方法主要做的事情是把各种数据整理收集好后,通过binder发送到app进程,那就来看下这个过程:

1.获取一个ClientTransaction实例
通过ClientTransaction.obtain方法获取一个ClientTransaction实例,为了避免浪费内存从缓存池中获取,ClientTransaction代表要传递给app的事务,它可以包含多个callback和一个lifecycleStateRequest。
来介绍下ClientTransaction.obtain这个方法它的参数:

  • client:IApplicationThread类型,AMS通过它把消息发送给app,它的值是proc.getThread()
  • activityToken:IBinder类型,它的值是r.appToken。AMS并没有把ActiviityRecord传递给app(传过去不安全),而是把ActiviityRecord的appToken传递过去,简单看下这个appToken,它的代码如下:
public final class ActivityRecord extends WindowToken implements WindowManagerService.AppFreezeListener {

    final ActivityRecord.Token appToken;

    static class Token extends IApplicationToken.Stub {
        private WeakReference weakActivity;
        private final String name;
        private final String tokenString;

        Token(Intent intent) {
            name = intent.getComponent().flattenToShortString();
            tokenString = "Token{" + Integer.toHexString(System.identityHashCode(this)) + "}";
        }

        //attach到ActivityRecord,这样就持有它了
        private void attach(ActivityRecord activity) {
            if (weakActivity != null) {
                throw new IllegalStateException("Already attached..." + this);
            }
            weakActivity = new WeakReference<>(activity);
        }

        //根据token来拿到ActivityRecord
        private static @Nullable ActivityRecord tokenToActivityRecordLocked(Token token) {
            if (token == null) {
                return null;
            }
            ActivityRecord r = token.weakActivity.get();
            //r.getRootTask()为null,代表它也是个”废物“了
            if (r == null || r.getRootTask() == null) {
                return null;
            }
            return r;
        }

        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder(128);
            sb.append("Token{");
            sb.append(Integer.toHexString(System.identityHashCode(this)));
            sb.append(' ');
            if (weakActivity != null) {
                sb.append(weakActivity.get());
            }
            sb.append('}');
            return sb.toString();
        }

        @Override
        public String getName() {
            return name;
        }
    }
}

ActivityRecord的appToken是一个类型为Token的实例。Token它继承了IApplicationToken.Stub说明它是一个IBinder类型,它用弱引用的方式持有ActivityRecord,appToken作为一个“令牌”被传递到app进程,就是告诉app,我给了你一个token,如果想给我发送消息,就带上这个token,我就能通过token找到ActivityRecord了(tokenToActivityRecordLocked方法)

Token这个类作为一个binder服务给使用者就提供了一个getName()方法,因此可以看出它在app端完全就是当作“令牌”来使用或者当作ActivityRecord的唯一标识来使用。

2.获取LaunchActivityItem实例
通过LaunchActivityItem.obtain方法获取实例,同样也为了效率和避免浪费内存,LaunchActivityItem也从缓冲池中获取,这个类包含了启动一个Activity的所有信息,来介绍下它的关键的属性:

  • intent:启动时候的intent(包含传递给Activity的数据等等),最终会被传递到“终点”
  • info:ActivityInfo类型,这个属性非常重要,它包含了app端具体Activity的类名,包名等信息
  • curConfig:Configuration类型,配置信息
  • state:Bundle类型,代表Activity在AMS中保存的信息,它会被传递给onCreate方法

会调用第一步ClientTransaction的addCallback方法加入LaunchActivityItem实例

3. 获取ResumeActivityItem实例
ResumeActivityItem代表需要执行Activity的onResume方法,会调用clientTransaction.setLifecycleStateRequest(lifecycleItem)

4. 最后把clientTransaction发送给app
调用mService.getLifecycleManager().scheduleTransaction(clientTransaction)方法把clientTransaction发送到app端

小结

用一张时序图进行小结

image

3. app接收并处理AMS发出的信息

AMS把clientTransaction发送到app端,因为mService.getLifecycleManager().scheduleTransaction(clientTransaction)方法最终执行的代码是mClient.scheduleTransaction(clientTransaction)(mClient是IApplicationThread类型)这是一个binder调用,mClient对应的是app进程的ActivityThread$ApplicationThread类型实例
,因此最终会进入ApplicationThread的scheduleTransaction方法

3.1 ApplicationThread#scheduleTransaction

    @Override
    public void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
        ActivityThread.this.scheduleTransaction(transaction);
    }

3.2 ActivityThread#scheduleTransaction

    public abstract class ClientTransactionHandler {

        /** Prepare and schedule transaction for execution. */
        void scheduleTransaction(ClientTransaction transaction) {
            transaction.preExecute(this);
            sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
        }
    }

ActivityThread继承了ClientTransactionHandler,关于clientTransaction是如何分发的流程在这节中不介绍了,经过分发后会进入LaunchActivityItem的execute方法

3.3 LaunchActivityItem#execute

    @Override
    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, mActivityOptions, mIsForward, mProfilerInfo,
                client, mAssistToken, mFixedRotationAdjustments, mShareableActivityToken,
                mLaunchedFromBubble, mTaskFragmentToken);
        //ActivityThread继承了ClientTransactionHandler,最终进入它的对应方法
        [3.4]
        client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
        Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
    }

该方法,把AMS传递过来的参数放置在了ActivityClientRecord的实例中,还记得AMS中记录Activity的类是ActivityRecord吧,它俩是一一对应的。
ActivityClientRecord

    /** Activity client record, used for bookkeeping for the real {@link Activity} instance. */
    public static final class ActivityClientRecord {
        //tokenAMS传递过来的令牌
        @UnsupportedAppUsage
        public IBinder token;
        
        省略属性......

        @UnsupportedAppUsage
        Intent intent;
        String referrer;
        IVoiceInteractor voiceInteractor;
        //AMS传递过来的保存的数据
        Bundle state;
        PersistableBundle persistentState;
        //app端真正启动的Activity实例
        @UnsupportedAppUsage
        Activity activity;
        //Activity对应的window
        Window window;
        Activity parent;
        String embeddedID;
        Activity.NonConfigurationInstances lastNonConfigurationInstances;
        // TODO(lifecycler): Use mLifecycleState instead.

        //是否paused
        @UnsupportedAppUsage
        boolean paused;
        //是否stoped
        @UnsupportedAppUsage
        boolean stopped;
        boolean hideForNow;

        //config信息
        Configuration createdConfig;
        Configuration overrideConfig;
        
        省略属性......

        //AMS传递过来的activityinfo信息
        @UnsupportedAppUsage
        ActivityInfo activityInfo;
        @UnsupportedAppUsage
        CompatibilityInfo compatInfo;
        @UnsupportedAppUsage
        public LoadedApk packageInfo;

        省略属性......

        //生命周期状态值
        @LifecycleState
        private int mLifecycleState = PRE_ON_CREATE;
    }

ActivityClientRecord不单单包含了AMS传递过来的信息,还包含app端真正启动的Activity实例以及对应的生命周期状态

3.4 ActivityThread#handleLaunchActivity

    @Override
    public Activity handleLaunchActivity(ActivityClientRecord r,
            PendingTransactionActions pendingActions, Intent customIntent) {
        省略代码......

        WindowManagerGlobal.initialize();

        // Hint the GraphicsEnvironment that an activity is launching on the process.
        GraphicsEnvironment.hintActivityLaunch();

        //开始启动Activity
        [3.5]
        final Activity a = performLaunchActivity(r, customIntent);

        省略代码......

        return a;
    }

3.5 ActivityThread#performLaunchActivity

    private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        ActivityInfo aInfo = r.activityInfo;
        if (r.packageInfo == null) {
            r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
                    Context.CONTEXT_INCLUDE_CODE);
        }

        //ComponentName封装了mPackage和mClass,component是真正Activity的对应的信息,先从r.intent.getComponent()获取
        ComponentName component = r.intent.getComponent();
        if (component == null) {
            //没获取到从PMS中去解析
            component = r.intent.resolveActivity(
                mInitialApplication.getPackageManager());
            r.intent.setComponent(component);
        }

        //如果targetActivity存在,则从targetActivity获取
        if (r.activityInfo.targetActivity != null) {
            component = new ComponentName(r.activityInfo.packageName,
                    r.activityInfo.targetActivity);
        }

        //初始化appContext它的类型是ContextImpl,像Activity调用到的Context的方法最终都是通过ContextImpl来实现的
        ContextImpl appContext = createBaseContextForActivity(r);
        Activity activity = null;
        try {
            //获取ClassLoader,来加载Activity
            java.lang.ClassLoader cl = appContext.getClassLoader();
            //mInstrumentation.newActivity方法中通过反射来实例化一个Activity
            activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);
            StrictMode.incrementExpectedActivityCount(activity.getClass());
            r.intent.setExtrasClassLoader(cl);
            r.intent.prepareToEnterProcess(isProtectedComponent(r.activityInfo),
                    appContext.getAttributionSource());
            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 {
            //尝试去make Application(一般情况下都已经创建成功了),如果存在直接返回
            Application app = r.packageInfo.makeApplication(false, mInstrumentation);

            if (localLOGV) Slog.v(TAG, "Performing launch of " + r);
            if (localLOGV) Slog.v(
                    TAG, r + ": app=" + app
                    + ", appName=" + app.getPackageName()
                    + ", pkg=" + r.packageInfo.getPackageName()
                    + ", comp=" + r.intent.getComponent().toShortString()
                    + ", dir=" + r.packageInfo.getAppDir());

            if (activity != null) {
                CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
                Configuration config =
                        new Configuration(mConfigurationController.getCompatConfiguration());
                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;
                }

                // Activity resources must be initialized with the same loaders as the
                // application context.
                appContext.getResources().addLoaders(
                        app.getResources().getLoaders().toArray(new ResourcesLoader[0]));

                appContext.setOuterContext(activity);

                //attach方法把各种数据传递给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,
                        r.assistToken, r.shareableActivityToken);

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

                if (r.mActivityOptions != null) {
                    activity.mPendingOptions = r.mActivityOptions;
                    r.mActivityOptions = null;
                }
                activity.mLaunchedFromBubble = r.mLaunchedFromBubble;
                activity.mCalled = false;

                //下面是根据r.isPersistable(),分别调用Activity的onCreate方法
                if (r.isPersistable()) {
                    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
                } else {
                    mInstrumentation.callActivityOnCreate(activity, r.state);
                }

                //如果自己实现的Activity的onCreate方法没有调用父类的onCreate方法,则抛异常
                if (!activity.mCalled) {
                    throw new SuperNotCalledException(
                        "Activity " + r.intent.getComponent().toShortString() +
                        " did not call through to super.onCreate()");
                }
                r.activity = activity;
                mLastReportedWindowingMode.put(activity.getActivityToken(),
                        config.windowConfiguration.getWindowingMode());
            }
            r.setState(ON_CREATE);

            // updatePendingActivityConfiguration() reads from mActivities to update
            // ActivityClientRecord which runs in a different thread. Protect modifications to
            // mActivities to avoid race.
            synchronized (mResourcesManager) {
                //AMS传递过来的token作为key,r作为value存放在mActivities中
                mActivities.put(r.token, r);
            }

        } catch (SuperNotCalledException e) {
            throw e;

        } catch (Exception e) {
            if (!mInstrumentation.onException(activity, e)) {
                throw new RuntimeException(
                    "Unable to start activity " + component
                    + ": " + e.toString(), e);
            }
        }

        return activity;
    }

该方法是启动Activity的核心方法主要做了以下几件事:

  1. 获取到ComponentName,它包含了真正Activity的包名,class信息
  2. 使用ClassLoader,通过反射对第1步的类进行实例化,会实例化一个Activity
  3. 尝试创建/获取Application的实例
  4. 通过Activity的attach方法把各种信息传递给它
  5. 调用Activity的onCreate方法
  6. AMS传递过来的token作为key,r作为value存放在mActivities中(这样通过tokenActivityRecord和ActivityClientRecord就建立了关系)

最后分析下mInstrumentation.callActivityOnCreate这个方法

3.6 Instrumentation#callActivityOnCreate

    public void callActivityOnCreate(Activity activity, Bundle icicle) {
        prePerformCreate(activity);
        [3.7]
        activity.performCreate(icicle);
        postPerformCreate(activity);
    }

3.7 Activity#performCreate

    final void performCreate(Bundle icicle) {
        performCreate(icicle, null);
    }

    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    final void performCreate(Bundle icicle, PersistableBundle persistentState) {
        if (Trace.isTagEnabled(Trace.TRACE_TAG_WINDOW_MANAGER)) {
            Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "performCreate:"
                    + mComponent.getClassName());
        }
        dispatchActivityPreCreated(icicle);
        mCanEnterPictureInPicture = true;
        // initialize mIsInMultiWindowMode and mIsInPictureInPictureMode before onCreate
        final int windowingMode = getResources().getConfiguration().windowConfiguration
                .getWindowingMode();
        mIsInMultiWindowMode = inMultiWindowMode(windowingMode);
        mIsInPictureInPictureMode = windowingMode == WINDOWING_MODE_PINNED;
        restoreHasCurrentPermissionRequest(icicle);

        //onCreate方法被调用
        if (persistentState != null) {
            onCreate(icicle, persistentState);
        } else {
            onCreate(icicle);
        }
        EventLogTags.writeWmOnCreateCalled(mIdent, getComponentName().getClassName(),
                "performCreate");
        mActivityTransitionState.readState(icicle);

        mVisibleFromClient = !mWindow.getWindowStyle().getBoolean(
                com.android.internal.R.styleable.Window_windowNoDisplay, false);
        mFragments.dispatchActivityCreated();
        mActivityTransitionState.setEnterActivityOptions(this, getActivityOptions());
        dispatchActivityPostCreated(icicle);
        

到此Activity的onCreate方法被调用,因为clientTransaction.setLifecycleStateRequest(lifecycleItem),lifecycleItem是ResumeActivityItem类型,Activity的onResume方法也会被调用,这个流程就不分析了.

小结

同样用一张时序图小结


image

总结

Activity启动源码分析的整个过程就结束了,更多的总结内容可以看上面的原理.

思考

为啥启动Activity必须要经过AMS?
想当年作为android新手的时候,认为app启动其他app内的Activity的时候经过AMS可以理解,毕竟app进程之间是不可以直接通信的,需要经过系统进程的AMS进行"中转".但是app启动自己内部的Activity的时候为啥也要经过AMS,经过AMS启动速度的话会慢,这里的慢是相对不经过AMS直接在app内启动的这样的假设.为啥会慢呢,如上面的分析流程,启动Activity需要在进程之间进行两次通信,Intent等数据也需要在进程之间传递来传递去的.

造成上面这种错误认识的原因是当时我只是把AMS认为只是起一个"中转"的功能.其实不是这样的,AMS的功能并非如此简单,AMS管理着所有的Activity(当然还管理着其他的三大组件),哪个Activity应该进入resume状态了,哪个应该进入pause或者stop状态,哪个应该进入destory状态等等生命周期状态的切换都是AMS来统一的协调处理;还有比如用户修改了系统的字体或者别的设置信息,那都需要AMS去通知Activity是否需要重新启动以来适配新的设置变化等等.

所以启动的目标Activity不管是app内的还是其他app的都需要去AMS,进行查询,检查,校验,记录流程,只有记录成功后,Activity启动才算在AMS环节成功了,AMS会通过记录下来的Activity信息进而来控制Activity的生命周期状态的切换.

AMS就是要管理控制Activity,如果没有它,那app内的Activity“各自为政”那岂不是乱套了。

再谈Token
如果做过web相关的开发,大家应该都了解,在用户登录后,服务器会返回给客户端一些信息,其中就有token,这个token它是一个字符串,并且是整个系统内唯一的.以后客户端与服务器进行通信就需要携带上这个token,服务器就知道到底是哪个用户在与之进行交互.

在启动Activity时候,AMS会返回一个Token类型的token实例给app进程,这里的token和web开发相关的token作用是一样的. AMS把这个token传递给app,app端也会把启动的Activity记录在本地的ActivityClientRecord类中,这个类中会记录下"真正启动的Activity的引用".app端会把token作为key值,ActivityClientRecord作为value值保存起来.ActivityRecord与ActivityClientRecord就通过token建立了联系.

AMS通知某个Activity进入某种生命周期状态,会把token值传递给app端,app端收到这个命令后,会通过这个token拿到ActivityClientRecord进而拿到真正启动的Activity的引用,进而调用它的对应回调方法.

app端某个Activity完成了某个操作后(比如pause操作),会携带token等其他信息通知AMS(因为token是一个IBinder类型,它进入AMS后会被转化为Binder),AMS通过token拿到对应的ActivityRecord,进而调用它相应的方法.

为啥要传递一个IBinder类型的token?
假如传递一个int类型或者String类型的token是不是也可行,当然是可行的,但是有一个问题就是复杂度要比使用IBinder类型高,复杂度高主要是体现在AMS.
原因是这样的:为了维护token与ActivityRecord之间建立一一对应关系可以使用有两种方式:其一token作为key值ActivityRecord作为value存储起来;其二每个ActivityRecord增加一个属性用来存储token. 这两种方式成本都挺高:其一方式使用的内存会多,并且维护成本也高,ActivityRecord的删除,增加,修改都需要去更新相应的存储容器;其二方式虽然不需要增加内存,但是多了查找成本,每次都需要从容器中拿出ActivityRecord依次进行对比.

那来看看IBinder类型的token是怎么解决上面的问题的.首先Token类([2.10]的代码)通过弱引用的方式持有ActivityRecord,这样也不会有内存泄漏的问题,在AMS端构造的token实例肯定是系统内唯一的,因为它是在系统进程中初始化完毕分发给其他进程使用的.

token传递到app进程后它会被转换为BinderProxy类型,并且binder机制是保证一个进程内的同一IBinder类型实例是仅存在一份的,意思就是即使AMS多次发送同一个Binder实例给进程,在这个进程内的BinderProxy类型的实例也是只有一个.在进程内可以通过使用"=="来比较两个token是否是一样的,这和使用int类型或者String类型的token也没有区别,更重要的是这种类型的token扩展性好,比如Token增加一些接口的话,其他进程内是可以使用的.

当app进程传递token到AMS后,token会被转换为Binder类型,这时候的token已经是Token了,直接可以通过它找到ActivityRecord.

IBinder类型的token复杂度也低,扩展性也好,这就是要使用IBinder类型的token的原因.

你可能感兴趣的:(Activity系列--Activity启动-源码分析)