在启动应用程序的时候,首先要保证这个应用程序的进程已经启动了。AMS在启动应用程序的时候会先判断这个应程序的进程是否存在,不存在就会请求Zygote进程启动需要的应用进程。
Zygote在java层创建了Socket,这个Socket就是用来接收AMS创建进程的消息的。Zygote收到消息后会fork一个应用程序进程。应用程序进程创建过程中除了获得虚拟机实例还创建了Binder线程池和消息循环,这样应用进程中的应用程序就可以方便的使用Binder进行进程间通信以及处理消息了。
AMS发送启动应用程序进程请求
AMS会通过startProcessLocked方法向Zygote进程发送请求。
在这个方法中我们会创建应用程序进程的用户ID,然后再对用户组ID进行创建和赋值。接着判断变量entryPoint是否为null,如果为null,则将变量赋值为android.app.ActivityThread。这个值就是应用程序进程主线程的类名。最后再调用Process的start方法,将前面得到的参数都传入进去。
在start方法中调用了zygoteProcess的start方法。ZygoteProcess类用于和Zygote进程保持通信状态。
接着zygoteProcess的start方法调用了startViaZygote方法,在方法中会先创建一个列表argsForZygote,将启动应用程序的参数保存在argsForZygote中。然后调用zygoteSendArgsAndGetResult方法。该方法会传入两个参数,第一个参数是调用openZygoteSocketIfNeeded方法的返回值,一个是传入前面创建的argsForZygote列表。
zygoteSendArgsAndGetResult方法主要作用是将应用程序进程的启动参数argsForZygote写入ZygoteState中。ZygoteState就是调用openZygoteSocketIfNeeded方法的返回值。它是ZygoteProcess的静态内部类,用于标识与Zygote的通信状态。
现在我们来看看openZygoteSocketIfNeeded方法。在方法总会先调用ZygoteState的connect方法与Zygote进程中的Socket连接,并返回ZygoteState类型的primaryZygoteState。接着将primaryZygoteState与启动应用程序进程所需的ABI进行一个匹配判断。如果不匹配,ZygoteState会再次调用connet方法与Zygote的辅模式连接。辅模式Socket的那么为zygote_secondary。Zygote的启动脚本有4种,如果采用的是init.zygote32_64或者init.zygote64_32,则name为zygote的为主模式,name为zygote_secondary的为辅模式。在第二次调用connect方法连接辅模式后,同样会接着将secondaryZygoteState与启动应用程序进程所需的ABI进行一个匹配判断。如果还是不匹配,则抛出ZygoteStartFailedEx异常。
当ZygoteState与Zygote的Socket连接成功,并将要创建应用程序进程的参数成功写入后,我们接下来就到了Zygote这一边,来看看它是怎么接受请求并创建应用程序进程的。
Zygote接收请求并创建应用程序进程
当Zygote收到创建应用程序进程的请求后或做一系列操作,不过我们这里先回到ZygoteInit的main方法。
我们会创建一个Socket来等待AMS的请求。最终会调用ZygoteServer的runSelectLoop方法来等待AMS请求。
我们来看看这个runSelectLoop方法,在方法中可以看到当有AMS请求到达的时候,会调用ZygoteConnection的runOnce方法,在这个方法中会先获取应用程序进程的启动参数,并将参数封装成Arguments。然后调用Zygote的forkAndSpecialize方法并返回一个pid。如果返回的pid为0,则说明当前代码逻辑运行在新创建的子进程中,这时就会调用handleChildProc方法来处理应用程序进程。
handleChildProc又调用了ZygoteInit的zygoteInit方法,该方法中调用ZygoteInit的nativeZygoteInit方法来启动Bindler线程池,接着调用RuntimeInit的applicationInit方法并在方法中调用invokeStaticMain方法,将我们最开始提到的android.app.ActivityThread作为第一个参数传入。
在invokeStaticMain方法中通过反射获取到android.app.ActivityThread类,然后获取该类的main方法,并将该方法传入到Zygote中的MethodAndArgsCaller类中。MethodAndArgsCaller是一个异常,这里会抛出这个异常,在Zygote的main方法中会对这个异常捕获。最终会将传入的main方法调用,这里传入的main方法就是ActivityThread的main方法。
Binder线程池启动过程
在应用程序进程创建的过程中会启动Binder线程池,具体实在ZygoteInit的zygoteInit方法中。这里会调用ZygoteInit的nativeZygoteInit方法。
nativeZygoteInit是一个JNI方法,它对应的函数是com_android_internal_os_ZygoteInit_nativeZygoteInit方法。
这个方法只有一句代码:
gCurRuntime->onZygoteInit();
gCurRuntime是AndroidRuntime类型的指针,在AndroidRuntime初始化就创建了。AppRuntime继承AndroidRuntime,AppRuntime创建时,gCurRuntime就会被初始化,它指的是AppRuntime(在app_main.cpp中实现)。现在来看看AppRuntime的onZygoteInit方法。
onZygoteInit方法会调用proc的startThreadPool方法来启动Binder线程池。支持Binder通信的进程中都有一个ProcessState类。它里面有一个mThreadPoolStarted变量,用来便是Binder线程池是否被启动过,默认为false。每次在调用startThreadPool方法的时候都会做一个判断,保证Binder线程池只被启动一次。如果没有被启动,会将mThreadPoolStarted设置为true,并调用spawnPooledThread函数来创建线程池的第一个线程,主线程。
Binder线程为一个PoolThread,这里会调用run方法来启动新线程。run方法中会调用IPCThreadState的joinTheradPool函数,将当前线程注册到Binder驱动中,这样我们创建的县城就加入Binder线程池中,新创建的应用程序进程就支持Binder进程间通信了。我们只需要创建当前进程的Binder对象,并注册到ServiceManager中就可以实现Binder通信。
消息循环创建过程
前面说过在创建应用程序进程的时候,最后会调用ActivityThead的main方法。ActivityThread用于管理当前进程的主线程,它会在main方法中创建主线程的消息循环Looper,然后创建ActivityThread实例。然后判断sMainThreadHandler是否为null,如果为null,获取到H类,并赋值给sMainThreadHandler。这个H继承自Handler,是ActivityThread的内部类,处理主线程消息循环。最后调用Looper的loop方法,开始处理消息。