AMS启动一个应用程序首先要保证该应用程序的进程已经启动,如果应用程序进程还不存在,则请求 Zygote 进程启动进程。
从前一章内容可知,在Zygote 的Java 框架层会创建Server 端的Socket,用于等待AMS 请求Zygote 创建新的应用程序进程。Zygote 通过fork自身即可创建应用程序进程,这个进程会包含虚拟机实例,并且会创建Binder线程池和消息循环。
本章学习应用程序进程的启动,注意,是应用程序进程而不是应用程序的启动过程。
应用程序进程启动过程介绍
AMS 通过调用 startProcessLocked 向 Zygote 进程发送请求, 主要代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| private final void startProcessLocked(ProcessRecord app, String hostingType, String hostingNameStr, String abiOverride ,String entryPoint ,String [] entryPointArgs) { ... int uid = app.uid; int [] gids = null; if (!app.isolated) { if (ArrayUtils isEmpty(permGids)){ gids =new int[3]; }else { gids = new int[permGids.leng + 3] ; System.arraycopy(permGids, 0, gids, 3, permGids.length) ; gids[O] = UserHandle.getSharedAppGid(UserHandle.getAppid(uid)); gids[1] = UserHandle.getCacheAppGid(UserHandle .getAppid(uid)) ; gids[2] = UserHandle.getUserGid{UserHandle.getUserid(uid)); } ... if (entryPoint = null) entryPoint = "android.app.ActivityThread"; ... startResult = Process.start(entryPoint,xxx,uid, xxx,gids,xxx,xxx);
|
上述代码首先得到应用程序进程的用户ID,之后创建用户组ID 并且赋值,在注释3处判断 entryPoint 为null就赋值 “android.app.ActivityThread”,这个值就是应用程序进程主线程的类名。在最终调用 Process.start 创建进程时,会将进程的用户ID和用户组ID传入。
Process.start会将实现交给 ZygoteProcess(ZygoteProcess用于保持与Zygote进程的通信状态)的start 方法处理,其中首先会执行 openZygoteSocketifNeeded 方法,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| ... if (primaryZygoteState == null || primaryZygoteState.isClosed ()) { try { primaryZygoteState = ZygoteState.connect(mSocket); } catch (IOException ioe} { throw new ZygoteStartFailedEx ("Error connecting to primary zygote", ioe) }
if (primaryZygotestate.matches (abi)) { return primaryZygoteState; }
//如果不匹配,则尝试连接 Zygote 辅模式 if (secondaryZygoteState ==null || secondaryZygoteState.isClosed()) { try { secondaryZygoteState = ZygoteState.connect(mSecondarySocket); } catch (IOException ioe) { throw new ZygoteStartFailedEx ("Error connecting to secondary zygote", ioe) ; }
//连接 Zygote 辅模式返回的 ZygoteState 是否与启动应用程序进程所需要的 ABI 匹配 if (secondaryZygoteState.matches(abi)) { return secondaryZygoteState; } throw new ZygoteStartFailedEx ("Unsupported zygote ABI :" + abi);
|
前面章节提到Zygote的main方法中会创建name为 “zygote” 的server端Socket,注释1就是与Zygote进程建立Socket 连接(name为”zygote”),并得到 ZygoteState 对象primaryZygoteState;注释2处如果primaryZygoteState 与启动应用程序所需要的 ABI 不匹配,则在注释3处连接name为 “zygote_secondary” 的Socket。如果辅模式返回的 ZygoteState 与进程所需的ABI也不匹配,就抛出异常。
通过 openZygoteSocketifNeeded 获取ZygoteState后,将其作为参数调用 ZygoteProcess的 ZygoteSendArgsAndGetResult 方法 获取Process.ProcessStartResult。
Zygote 接收请求并创建应用程序进程
执行完以上步骤后,继续执行 argsForZygote 方法即可让Zygote 收到创建新的应用程序进程的请求。Zygote 接收请求并创建应用程序进程的时序图如下:
由前面章节我们知道,Zygote 中的Server Socket 的runSelectLoop 方法一直在等待 AMS请求创建新的应用程序进程,runSelectLoop 中是通过 runOnce 来创建进程的,runOnce最终调用到 Zygote 的 forkAndSpecialize 方法创建应用程序进程,并返回pid。forkAndSpecialize 通过fork 当前进程来创建一个子进程。此后,便会在应用程序进程中创建 Binder 线程池,*进一步通过反射 ActivityThread 类的main方法调用,令应用程序进程进入了ActivityThread 的main方法中。此时,应用程序进程创建完毕,并且运行了主线程管理类 ActivityThread *。
如果pid为0,说明当前代码运行在新创建的子进程中。
Binder 线程池启动过程
程序中会检查代码,确保Binder线程池只会被启动一次。
消息循环创建过程
通过反射方式 invok 执行 ActivityThread 的main方法时,会执行一系列主线程的工作,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
|
public static void main(String[] args) { ... Looper.prepareMainLooper(); ActivityThread thread= new ActivityThread(); thread.attach(false) ; if (sMainThreadHandler == null ) { sMainThreadHandler = thread . getHandler (); if (false) { Looper.myLooper().setMessageLogging(new LogPrinter(Log.DEBUG, "ActivityThread"); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER) ; Looper.loop (); throw new RuntimeException("Main thread loop unexpectedly exited"); }
|
ActivityThread类用于管理当前应用程序进程的主线程,上述代码中创建了主线程的消息循环Looper,其中的内部类 H 继承 Handler,在注释 5 处调用Looper.loop ,即使得Looper 开始处理消息,可见,系统在应用程序进程启动完成后,就会创建消息循环。