Launcher通过Instrumentation类,在Instrumentation中通过ServiceManager拿到AMS的Binder和AMS通信,调用AMS里面的startActivity方法,同时把Launcher进程的包名和所对应的ApplicationThread(Binder),intent里面所包含的信息全部传递给AMS的ActivityStart里面的静态的Request。
ActivityStart这个类专门用于解析Activity信息,配置activity关联的任务和堆栈,里面有一个静态的Request类,这个类里面的参数包含了启动activityA的相关信息和被启动activityB的相关信息。
static class Request {
...
IApplicationThread caller;//Launcher的Binder,也代表着谁来调用我们的启动流程
Intent intent;//startActivity里面传入的Intent
NeededUriGrants intentGrants;
// A copy of the original requested intent, in case for ephemeral app launch.
Intent ephemeralIntent;
String resolvedType;
ActivityInfo activityInfo;
ResolveInfo resolveInfo;
IVoiceInteractionSession voiceSession;
IVoiceInteractor voiceInteractor;
IBinder resultTo;
String resultWho;
int requestCode;//activity启动的返回结果
...
}
AMS创建和管理ActivityStart是通过ActivityStartController。AMS每次启动一个Activity都会需要创建一个ActivityStart类来管理Activity的启动信息。在App中启动Activity是一件非常频繁的事情,如果每一次启动Activity都重新创建ActivityStart对象的话,当相关方法执行完毕,ActivityStart对象会被回收。频繁的创建和频繁的回收就势必会造成内存抖动。我们在JVM的新生代使用的垃圾回收算法是复制清除算法,在老年代是标志清除算法或者标记整理清除算法,除了标记清除算法外,其余两种都会造成对象的移动,除了垃圾回收线程外的其余所有线程都必须暂停,会造成一定的卡顿。所以在AMS中并不是直接去创建ActivityStart对象的,通过ActivityStartController去创建和管理ActivityStart对象。使用了享元设计模式。当相关方法执行完毕,把ActivityStart对象先清除里面所有的数据,然后放置在被final修饰(final修饰的变量存在在常量池,是一个GC root)的一个对象的里面的池子里面,池子的容量是3。每次创建先从池子里面拿,拿不到再创建ActivityStart对象,用完后抹除对象里面所有的数据放回到池子里面。这样做避免了内存抖动。和Message的创建是一样的。
ActivityStartController创建完ActivityStart后,把Launcher的包名,Launcher的ApplicationThread和intent里面所有的信息存储到ActivityStart的Request类里面。然后在ActivityStart里面创建两个ActivityRecord,这个ActivityRecord我理解为Activity在AMS里面的一种体现吧,我们的Activity目前还没创建,真正创建实在ActivityThread的handLaunchActivty里面,在创建Activity之前,AMS怎么对Activity操作呢?就弄了一个ActivityRecord来代表Activity。ActivityRecord里面就包含了一个Activity的所有信息,比如说Activity所处的栈,处于哪个栈。
ActivityStart一共干了一下几种事情:
ActivityRecord:一个ActivityRecord对应着一个Activity,保存一个Activity的所有信息;但是一个Activity可能对应着多个ActivityRecord,这与Activity的启动模式有关,一个Activity可能会被启动多次。
Task:Android系统中的每个Activity都位于一个Task中。一个Task能够包括多个Activity,同一个Activity也可能有多
个实例。 在AndroidManifest.xml中,我们能够通过 android:launchMode 来控制Activity在Task中的实例。Task管
理的意义还在于近期任务列表以及Back栈。 当你通过多任务键(有些设备上是长按Home键。有些设备上是专门提
供的多任务键)调出多任务时,事实上就是从ActivityManagerService获取了近期启动的Task列表。
ActivityStack:Task是它的父类,是一个管理类,管理着所有 Activity ,内部维护了 Activity 的所有状态、特
殊状态的Actvity和Activity以及相关的列表数据。
ActivityStackSupervisor: ActivityStack 是由 ActivityStackSupervisor 来进行管理,而这个是在ATMS的
initialize 中被创建出来的。ATMS初始化的时候,会创建一个ActivityStackSupervisor对象用于统一管理一些事
务:1)将显示层次结构相关的内容移动到RootWindowContainer中;2)将与activity生命周期相关的事务的处理转
交给ActivityLifeCyler处理;3)处理点击物理按键Menu键后任务栈的处理。
RootWindowContainer通过拿到ActivityStack执行ActivtyA的onPase方法,之后把后续流程交给ActivityStackSupervisor来处理。ActivityStackSupervisor是ActivityStack的大管家,管理着所有的ActivityStack。在ActivityStackSupervisor里面会判断当前要启动的Activity所在的进程有没有被创建,如果没有被创建的话。会通过ProcessList去拿到对应的RrocessRecord。
ProcessRecord记录App进程相关信息的重要类,AMS管理所有App进程,每一个App进程都对应着一个ProcessRecord类,里面存储着App进程的所有信息。AMS为了管理这些进程信息,创建了一个ProcessList,通过ProcessList来管理这些ProcessRecord。
ProcessList里面会有一个列表存放这最近使用的进程所对应的ProcessReocrd。
ActivityStackSupervisor里面会为当前进程创建一个RrocessRecord,通过ProcessList对ProcessRecord进行管理。然后通过ProcessList调用Process工具类,通过Process工具类去调用ZygoteProcess的start方法,通过socket发送消息给到zygotesever。
ZygoteInit进程在被创建出来后,在main方法里面执行了这几件事情:
一旦我们通过Launcher和AMS通信,要求启动App进程里面的ActivityB,在ActivityStackSupervior里面判断ActivityB所在的进程没有被启动,则会通过ProcessList创建一个ProcessRecord存储当前要创建的进程的信息,然后再通过对工具类Process的调用进阶对ZygoteProcess的调用发送一条socket信息。这时候在ZygoteServer中的死循环就能检测到这条socket信息。然后获取socket命令,拿到发送过来的要fork的进程的相关信息,最后通过fork操作得到两个pid。之所以是得到两个pid是因为fork操作是把zygote进程完整复制一遍,就像细胞分裂一样。原来在zygote进程里面进行fork操作的地方在我们的子进程里面也会存在,也会返回一个结果。pid如果大于0是父进程Zygote,等于0是子进程,小与0说明执行fork操作失败。fork进程后第一时间把我们子进程的socket关闭,因为zygote进程的socket是进行跨进程通信使用,但是我们子进程跨进程通信使用的是binder。然后初始化运行环境,把我们子进程的binder驱动打开,创建binder线程池,最后通过反射去找到ActivityThread的main方法执行。
拿到socket消息后一共干了这几件事情:
为什么zygote跨进程通信要使用socket,Linnux里面是不允许在多线程环境下进行fork操作的,fork操作只会把父进程里面发起fork的那个线程复制到子进程里面,而Binder天生就是多线程的,如果有一个线程在等锁的话,那么在子进程里面他将永远在等锁。
为什么要使用反射来执行main方法,拿到socket消息后的所有操作都被封装成了一个runable,最后的runable的run方法就是拿到进程对应的main方法,执行main方法。封装正runable后统一使用反射来调用有点类似泛型,我只需要写一套代码,然后不管是system_service的fork还是activityThread的启动只需要用着一套代码就行了。实现了代码的复用,也方便统一管理。
在ActivityThread里面做了这几件事:
接下来的事情又回到AMS端了
在System_service进程的SystemServiceManager管理的AMS里面做了这几件事:
通过Binder调用App端创建Application和后面的通过Binder把ClientTranstion传递给App端是通过Binder异步通信。所以有可能存在着Activity创建时,Application还没被创建的问题。会在Activity创建后调用makeApplication确保一下Application是被成功创建的,然后再去执行Activity的相关生命周期。
在ActivityThread里面创建Application做了这几件事情:
接下来回到Activity的启动流程,我们目前已经解析完了Activity的启动参数,创建出Activity的进程,创建出一个Application了。接下来会回到ActivityStackSupervior里面,先执行一下ActivityA的onPause方法,让ActivityA处于一个可见不可交互状态。然后在ActivityStackSupervior里面,把ActivityB的生命周期封装成一个事务ClientTranstion,在ClientTranstion事务里面保存了AMS希望App端处理的ActivityB的起始生命周期状态LaunchActivityItem,ActivityB的结束生命周期状态ResumeActivityItem。然后通过ClientLifecycleManager对ClientTranstion进行管理,拿到app端的binder,通过跨进程通信,在ClientLifecycleManager里面把当前的ClientTranstion传递给ActivityThread。
ActivityStackSupervisor里面一共干了以下几件事:
在ActivityThread里面接受到AMS传递的生命周期事务ClientTranstion后,通过sendMessage切换到主线程。利用事务处理器TranstioneExector处理事务里面的生命周期,起始生命周期LaunchActivityItem和结束生命周期ResumeActivityItem。在处理LauncherActivityItem方法的时候,首先创建ActivityClientRecord,ActivityClientRecord是Activity在App进程里面的一个实体,里面会存有一个变量Activity。然后会调用handleLaunchActivity方法,把这个创建的ActivityClientRecord传递给它,实际上调用performLaunchActivity反射创建一个Activity,之前说过AMS和App跨进程通信创建Application和AMS和App跨进程通信传输ClientTranstion是使用了Binder的异步通信机制,所以创建Activity后会进行makeApplication,确保在执行activity的onCreate方法前,application已经被成功创建出来。执行完onCreate后,把当前的生命周期状态ON_CREATE存储在ActivityClientRecord里面。接下来事务处理器拿到结束生命周期ResumeActivityItem的生命周期状态ON_RESUME,计算存储在ActivityClientRecord里面的生命周期状态和结束生命周期状态,发现中间还有一个ON_START生命周期,接着执行ON_START生命周期。最后再执行ON_RESUME生命周期。在handleResumeActivity执行完ActivityB的onResume方法后,会通过IdlerHandler的queueIdle方法里面拿到AMS的Binder,然后和AMS通信,跑到ActivityStackSupervisor类里面,找到Activity对应的ActivityRecord,在ActivityRecord里面把onStop包装成一个事务ClientTranstion,然后通过ClientLicycleManager对事物进行管理,拿到对应的App进程的Binder,最后把包装好的事务跨进程通信传递回Launcher进程,使用事务处理器TranstionExector进行生命周期的执行。
在ActivityThread里面对生命周期管理主要分为以下几步: