Laucher中activtyA启动APP进程中的ActivityB

第一步:解析要启动的Activity信息

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一共干了一下几种事情:

  1. 存储Launcher所有的App的binder,解析intent里面的参数,也就是ActivityA和ActivityB的相关参数,存储到内部的静态类Request里面
  2. 把ActivityA和ActivityB在AMS端的代表,ActivityRecord创建出来,ActivityRecord里面包含了Activity的相关信息,其中就包括Activity的相关得的栈信息。
  3. 启动之前还没来得及启动的Activity,我的理解是一个屏幕内同时启动两个Activity就是在这里进行处理的,确保启动一个的时候,另外一个Activity也会被启动。
  4. 初始化启动模式,为ActivityRecord存储的启动模式赋值,然后将相关启动模式塞到Intent里面
  5. 创建一个启动时的黑白屏。因为这个时候我们的APP进程还没有被启动,而App进程启动的过程是很缓慢的,可能需要个2秒,但是如果不给这个黑白屏的话,在这两秒之内,用户会以为点击没效果,或者认为自己没有点中app图标,会疯狂点击。先给一个黑白屏让用户知道操作系统已经接受到他的点击事件了。
  6. 把后续的操作交给RootWindowContainer去执行。RootWindowContainer是窗口容器的根容器,管理所有的窗口容器。窗口是需要基于Activity来显示的,后续的操作在resumeFocusedStacksTopActivitys里面进行,个人理解是恢复目前栈的栈顶Activity,可见性和窗口脱不了关系。所以谷歌工程师可能想通过RootWindowContainer来控制Activity的后续流程。

第二步:ActivityStackSupervisor启动Activity

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方法里面执行了这几件事情:

  1. 加载系统类,加载系统资源,加载一些共享so库,加载字体资源,加载webview相关资源
  2. 创建socket服务,zygoteserver
  3. Fork出的第一个进程 system_server
  4. 在zygoteserver死循环等待socket消息,循环等待fork出其他的应用进程,比如Launcher,比如app

一旦我们通过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消息后一共干了这几件事情:

  1. 通过fork操作fork出子进程,fork操作会返回两个pid,因为fork操作是把zygote进程完整复制一遍,就像细胞分裂一样。原来在zygote进程里面进行fork操作的地方在我们的子进程里面也会存在,也会返回一个结果。
  2. 关闭子进程的socket服务,因为ygote进程的socket是进行跨进程通信使用,但是我们子进程跨进程通信使用的是binder
  3. 初始化运行环境
  4. 把子进程的binder驱动打开,创建binder线程池
  5. 反射找到Activity的main方法执行

为什么zygote跨进程通信要使用socket,Linnux里面是不允许在多线程环境下进行fork操作的,fork操作只会把父进程里面发起fork的那个线程复制到子进程里面,而Binder天生就是多线程的,如果有一个线程在等锁的话,那么在子进程里面他将永远在等锁。

为什么要使用反射来执行main方法,拿到socket消息后的所有操作都被封装成了一个runable,最后的runable的run方法就是拿到进程对应的main方法,执行main方法。封装正runable后统一使用反射来调用有点类似泛型,我只需要写一套代码,然后不管是system_service的fork还是activityThread的启动只需要用着一套代码就行了。实现了代码的复用,也方便统一管理。

在ActivityThread里面做了这几件事:

  1. 为我们App进程创建一个Looper对象,并且使用ThreadLocal的set方法保存,赋值为一个static修饰的sMainLooper引用上面
  2. 调用Looper的loop方法,启动一个死循环,不断的从MessageQuene里面取出Message,没有message的时候通过linnux的epoll wait机制让出cpu资源,进行休眠
  3. 通过执行ActivityThread的attach方法,先通过ServiceManage拿到AMS的Binder,然后通过ActivityManager.Stub.asInterface拿到AMS的本地代理,通过和AMS所在的进程System_service进行跨进程通信,把我们App进程的Binder,ApplicationThread传递给AMS。

接下来的事情又回到AMS端了

在System_service进程的SystemServiceManager管理的AMS里面做了这几件事:

  1. 把我们的APP的Binder存到对应的ProcessRecord里面
  2. 把ProcessRecord的顺序在ProcessList重新排序一下
  3. 通过App的Binder调用App端的ApplicationThread的attachApplication,创建一个Application
  4. 回调到ActivityStackSupervisor里面完成剩余的Activity启动流程

通过Binder调用App端创建Application和后面的通过Binder把ClientTranstion传递给App端是通过Binder异步通信。所以有可能存在着Activity创建时,Application还没被创建的问题。会在Activity创建后调用makeApplication确保一下Application是被成功创建的,然后再去执行Activity的相关生命周期。

在ActivityThread里面创建Application做了这几件事情:

  1. ApplicationThread通过sendMessage的方式去切换到主线程,因为AMS和App端跨进程通信使用的是Binder的异步机制,所以ApplicationThread里面的方法都是在异步线程里面执行的,需要通过handler切换到主线程里面。
  2. 通过makeApplication函数,在内部通过反射来创建Application
  3. 执行Appliaction的attach方法,在这个方法里面执行attachBaseContext
  4. 创建contentProvide
  5. 执行Application的onCreate方法

接下来回到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里面一共干了以下几件事:

  1. 根据当前Activity的所在进程有没有被创建去执行Activity的启动逻辑,没有被创建的话通过ProcessList去创建ProcessRecord,再通过工具类Process去操作ZygoteProcess发送socket信息,在ZygoteServer里面收到信息fork出进程。App进程被fork出来第一时间关掉socket服务,然后初始化运行环境,启动binder驱动和binder线程池,最后通过反射去找打ActivityThread的main方法执行。在main方法里面又调用attach,跨进程通信把app的binder传递给System_service里面的AMS。AMS保存当前的App进程的binder到对应的ProcessRecord里面,并且更新ProcessRecord在ProcessList里面的位置。又通过Binder和App进程通信,跨进程调用bindApplication。在App进程里面先通过sendMessage方法,把相关信息通过handler发送到主线程。在主线程通过makeApplication反射创建一个Application,执行application的attach方法,attachBaseContent方法,再创建contentProvide方法,最后才执行Application的onCreate方法。
  2. 执行ActivityA的onPause方法
  3. 把AMS希望App端执行的ActivityB的起始生命周期LaunchActivityItem,结束生命周期ResumeActivityItem包装成一个ClientTranstion。通过ClientLifecycleManager管理ClientTranstion,在ClientLifecycleManager里面拿到App对应的binder,跨进程通信把事务ClientTranstion传递给App端

ActivityThread对Activity生命周期的管理

在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里面对生命周期管理主要分为以下几步:

  1. 拿到AMS跨进程通信传递过来的生命周期事务ClientTranstion,通过sendMessage从子线程发送到主线程的事务处理器处理。
    在主线程的事务处理器里面先执行起始生命周期LaunchActivityItem的exect方法,创建一个ActivityClientRecord,然后把这个对象传递给ActivityThread的handlerlaunchActivity
  2. 在handlerlaunchActivity方法里面通过反射创建出Activity,然后通过makeApplication方法确保此时的Application是被成功创建的,再嘻嘻onCreate方法,并且把此时的生命周期状态ON_CREATE存储在ActivityClientRecord里面
  3. 事务处理器TranstionExect计算起始生命周期状态和结束生命周期状态,发现中间还有一个ON_START的生命周期状态需要执行,于是执行ON_START生命周期
  4. 最后执行ResumeActivityItem的exect方法,调入到handlerResumeActivity里面,执行完activityB的onResume方法,然后把DecorView添加到Window上面
  5. 在handlerResumeActivity尾部,通过一个IdleHandler,在messagequeue没有message执行或者休眠的时候通过binder和AMS通信,调回到ActivityStackSupervior,找到ActivityA对应的ActivityRecord,在ActivityRecord把onStop方法封装成一个事务ClientTranstion,在通过AMS和App进程跨进程通信,把事务传送给App进程,最后通过事务处理器TranstionExect执行ActivityA的相关生命周期
  • 25
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值