4.4 zygote处理Home启动请求

还记得ServerThread的run方法中,调用了一系列systemReady()方法吗?这些方法里做了什么导致系统准备就绪?是否也包括准备Home界面呢?这里就不具体分析每一个Service准备就绪都做了什么工作了,直接给出问题的答案:Home界面是在ActivityManagerService调用systemReady()的过程中启动的。直接定位到该方法,代码如下:


public void systemReady(final Runnable goingCallback){

synchronized(this){

if(mSystemReady){

if(goingCallback!=null)goingCallback.run();

return;

}

……//省略部分内容

/mMainStack是ActivityStack类型的对象,系统启动之初,Activity栈中没有Activity/

mMainStack.resumeTopActivityLocked(null);

……


systemReady方法中做了很多判断工作,其详细执行流程在第10章分析。systemReady方法最终调用了ActivityStack的resumeTopActivityLocked方法,代码如下:


final boolean resumeTopActivityLocked(ActivityRecord prev){

return resumeTopActivityLocked(prev, null);

}

resumeTopActivityLocked调用了其重载方法,代码如下:

final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options){

/返回Activity栈中栈顶的Activity,系统启动时没有返回null/

ActivityRecord next=topRunningActivityLocked(null);

//是否是用户行为导致离开Activity,在第11章进行详细分析

final boolean userLeaving=mUserLeaving;

mUserLeaving=false;

if(next==null){//此时next为null

if(mMainStack){

/mService便是ActivityManagerService/

return mService.startHomeActivityLocked(0);//在此返回

}

}

……//省略其他内容


resumeTopActivityLocked中调用了ActivityManagerService中的startHomeActivityLocked方法。startHomeActivityLocked方法便是启动Home桌面的入口,其代码如下:


boolean startHomeActivityLocked(int userId){

if(mHeadless){//无GUI的系统,不需要启动Home

ensureBootCompleted();

return false;

}

……//省略其他内容

Intent intent=new Intent(mTopAction,

mTopData!=null?Uri.parse(mTopData):null);

/指定Intent的Component,这里便是Home应用的包名/

intent.setComponent(mTopComponent);

/指定Intent类别为CATEGORY_HOME/

if(mFactoryTest!=SystemServer.FACTORY_TEST_LOW_LEVEL){

intent.addCategory(Intent.CATEGORY_HOME);

}

/通过PackageManagerService查询该类型的Activity/

ActivityInfo aInfo=

intent.resolveActivityInfo(mContext.getPackageManager(),STOCK_PM_FLAGS);

if(aInfo!=null){//找到该类型的Activity

/获取Activity的包名,并设置给intent/

intent.setComponent(new ComponentName(

aInfo.applicationInfo.packageName, aInfo.name));

……

/查询这个Activity是否已经启动,此时会有对应进程信息/

ProcessRecord app=getProcessRecordLocked(aInfo.processName,

aInfo.applicationInfo.uid);

if(app==null||app.instrumentationClass==null){

/在新任务中启动这个Activity/

intent.setFlags(intent.getFlags()|Intent.FLAG_ACTIVITY_NEW_TASK);

/通过发送Intent,启动Home应用/

mMainStack.startActivityLocked(null, intent, null,

aInfo, null, null,0,0,0,null, false, null);

}

}

return true;

}


startHomeActivityLocked方法通过Intent保存将要启动的应用程序信息,接下来进入ActivityStack的startActivityLocked方法,代码如下:


final int startActivityLocked(IApplicationThread caller,

Intent intent, String resolvedType, ActivityInfo aInfo,

IBinder resultTo, String resultWho, int requestCode,

int callingPid, int callingUid, int startFlags, Bundle options,

boolean componentSpecified, ActivityRecord[]outActivity){

/*startActivityLocked的代码很多,因为只考虑启动Home的流程,可以根据传

*入的参数过滤掉不需要的代码。传入的参数如下(第11章会分析这些参数的作用):

*caller=null;resolvedType=null;

*resultTo=null;

*resultWho=null;requestCode=0;callingPid=0;

*callingUid=0;componentSpecified=false;

*outActivity=null

*/

int err=START_SUCCESS;

……

ActivityRecord sourceRecord=null;

ActivityRecord resultRecord=null;

……//省略不满足条件的内容

int launchFlags=intent.getFlags();

……//省略不满足条件的内容

/要创建的Activity的信息/

ActivityRecord r=new ActivityRecord(mService, this,

callerApp, callingUid, intent, resolvedType, aInfo,

mService.mConfiguration, resultRecord, resultWho,

requestCode, componentSpecified);

……//省略不满足条件的内容

/调用startActivityUncheckedLocked/

err=startActivityUncheckedLocked(r, sourceRecord, startFlags, true, options);

……


startActivityLocked方法虽然复杂,但经过传入参数的过滤,其执行过程就很清晰了,方法最后调用了startActivityUncheckedLocked。接下来分析该函数,代码如下:


final int startActivityUncheckedLocked(ActivityRecord r, ActivityRecord sourceRecord,

int startFlags, boolean doResume, Bundle options){

if(!doResume){//判断是否需要延迟启动,这里需要立即启动

r.delayedResume=true;

}

……//省略启动模式及创建任务的过程,这部分内容在第11章详细分析

startActivityLocked(r, newTask, doResume, keepCurTransition, options);

return START_SUCCESS;


startActivityUncheckedLocked相当复杂,第11章对其详细分析,这里只关注核心流程。该方法执行后期,调用了startActivityLocked方法,代码如下:


private final void startActivityLocked(ActivityRecord r, boolean newTask,

boolean doResume, boolean keepCurTransition, Bundle options){

final int NH=mHistory.size();//历史记录为0

int addPos=-1;

if(!newTask){//本例需要创建新任务,所以不执行这步

……//省略部分内容

}

//如果addPos<0,就把该Activity放入Activity历史栈的顶部,直接与用户交互

if(addPos<0){

addPos=NH;

}

……

mHistory.add(addPos, r);//将ActivityRecord添加到Activity历史栈中

r.putInHistory();//标记已经将Activity加入到历史栈中

r.frontOfTask=newTask;

if(NH>0){

……//省略Window Manager准备切换动画和过渡窗口的过程

}

……

if(doResume){//立即启动Activity

resumeTopActivityLocked(null);

}


startActivityLocked代码比较多,这里只关注启动Home的部分,最终调用resumeTopActi-vityLocked方法启动Activity历史栈的栈顶Activity,代码如下:


final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options){

//从历史栈中获取栈顶Activity

ActivityRecord next=topRunningActivityLocked(null);

/*next中保存要启动的Activity。没有Activity需要启动的时候,就启

动Home。前面已经发过Intent启动了Home,所以这里next!=null/

if(next==null){

if(mMainStack){

return mService.startHomeActivityLocked();

}

}

/*如果栈顶的Activity就是要启动的Activity,不需要做

任何事情,直接返回。这里Home还未启动,不执行这个流程/

if(mResumedActivity==next&&next.state==ActivityState.RESUMED)

{

……

}

……

/*启动新Activity就要暂停之前的Activity,这里没有需要

暂停的Activity,因此mResumedActivity为null/

if(mResumedActivity!=null){

startPausingLocked(userLeaving, false);

return true;

}

……//省略部分内容

if(next.app!=null&&next.app.thread!=null){

……//处理Activity切换的状态

}else{//next引用的ActivityRecord的app(进程信息)为null

……//省略部分内容

startSpecificActivityLocked(next, true, true);

}

return true;

}


resumeTopActivityLocked最终调用了startSpecificActivityLocked,代码如下:


private final void startSpecificActivityLocked(ActivityRecord r,

boolean andResume, boolean checkConfig){

//此时,Home对应的应用程序进程还未启动,返回null

ProcessRecord app=mService.getProcessRecordLocked(r.processName,

r.info.applicationInfo.uid);

……//省略部分内容

if(app!=null&&app.thread!=null){

……//app为null,省略部分内容

}

/mService便是ActivityManagerService,调用startProcessLocked/

mService.startProcessLocked(r.processName, r.info.applicationInfo,

true,0,"activity",r.intent.getComponent(),false, false);

}


startSpecificActivityLocked最终调用了startProcessLocked,代码如下:


final ProcessRecord startProcessLocked(String processName,

ApplicationInfo info, boolean knownToBeDead, int intentFlags,

String hostingType, ComponentName hostingName,

boolean allowWhileBooting, boolean isolated){

ProcessRecord app;

if(!isolated){//非isolated进程,复用已有进程信息

app=getProcessRecordLocked(processName, info.uid);

}else{

app=null;

}

……//省略部分内容

//对应Home app的进程还不存在,所以app为null

if(app==null){

/创建Home应用程序对应的进程信息ProcessRecord/

app=newProcessRecordLocked(null, info, processName);

……

mProcessNames.put(processName, info.uid, app);//记录该进程信息

……

}else{

app.addPackage(info.packageName);

}

……//省略部分内容

/调用重载的startProcessLocked方法/

startProcessLocked(app, hostingType, hostingNameStr);

return(app.pid!=0)?app:null;

}


startProcessLocked调用了其重载方法完成进程的创建工作,代码如下:


private final void startProcessLocked(ProcessRecord app,

String hostingType, String hostingNameStr){

……//省略部分内容

try{

int uid=app.info.uid;

int[]gids=null;

if(!app.isolated){

try{//通过PackageManagerService查询该Activity的组ID

gids=mContext.getPackageManager().getPackageGids(

app.info.packageName);

}

……//省略部分内容

/调用Process的start方法创建进程,并在该进程中运行ActivityThread的main方法/

Process.ProcessStartResult startResult=

Process.start("android.app.ActivityThread",

app.processName, uid, uid, gids, debugFlags,

app.info.targetSdkVersion, null);

……//省略部分内容

app.pid=startResult.pid;

……//省略部分内容


startProcessLocked方法很简单,其核心工作是调用Process.start方法。Process位于frameworks/base/core/java/anroid/os/Process.java中。接下来看看start方法做了些什么,代码如下:


public static final ProcessStartResult start(final String processClass,

final String niceName, int uid, int gid,

int[]gids, int debugFlags,

int targetSdkVersion, String[]zygoteArgs){

try{

return startViaZygote(processClass, niceName, uid, gid, gids,

debugFlags, targetSdkVersion, zygoteArgs);

}catch(ZygoteStartFailedEx ex){

……//省略异常处理代码

}

}


start方法只是对startViaZygote方法的封装。startViaZygote方法代码如下:


private static ProcessStartResult startViaZygote(……)

throws ZygoteStartFailedEx{

synchronized(Process.class){

ArrayList<String>argsForZygote=new ArrayList<String>();

argsForZygote.add("—runtime-init");//初始化运行环境,以后要用到

argsForZygote.add("—setuid="+uid);

argsForZygote.add("—setgid="+gid);

if((debugFlags&Zygote.DEBUG_ENABLE_JNI_LOGGING)!=0){

argsForZygote.add("—enable-jni-logging");

}

if((debugFlags&Zygote.DEBUG_ENABLE_SAFEMODE)!=0){

argsForZygote.add("—enable-safemode");

}

if((debugFlags&Zygote.DEBUG_ENABLE_DEBUGGER)!=0){

argsForZygote.add("—enable-debugger");

}

if((debugFlags&Zygote.DEBUG_ENABLE_CHECKJNI)!=0){

argsForZygote.add("—enable-checkjni");

……//省略其他参数设置代码

return zygoteSendArgsAndGetResult(argsForZygote);

}

}


startViaZygote设置参数后,便调用zygoteSendArgsAndGetResult方法,代码如下:


private static ProcessStartResult zygoteSendArgsAndGetResult(

ArrayList<String>args)throws ZygoteStartFailedEx{

/与zygote通信/

openZygoteSocketIfNeeded();

/按照一定格式往zygote的Socket写入数据/

try{

sZygoteWriter.write(Integer.toString(args.size()));

sZygoteWriter.newLine();//每个参数以行分隔

int sz=args.size();

for(int i=0;i<sz;i++){

String arg=args.get(i);

if(arg.indexOf('\n')>=0){

throw new ZygoteStartFailedEx(

"embedded newlines not allowed");

}

sZygoteWriter.write(arg);

sZygoteWriter.newLine();

}

sZygoteWriter.flush();

/从zygote的Socket读取处理结果,放入result中。result中包含新启动进程的PID/

ProcessStartResult result=new ProcessStartResult();

result.pid=sZygoteInputStream.readInt();

……

result.usingWrapper=sZygoteInputStream.readBoolean();

return result;

}

……//省略异常处理代码


zygoteSendArgsAndGetResult方法中首先调用了openZygoteSocketIfNeeded(),代码如下:


private static void openZygoteSocketIfNeeded()

throws ZygoteStartFailedEx{

int retryCount;//最多10次

……//省略部分代码

for(int retry=0

;(sZygoteSocket==null)&&(retry<(retryCount+1))

;retry++){

……

try{

/创建Socket/

sZygoteSocket=new LocalSocket();

/调用系统函数connect连接到zygote的Socket。ZYGOTE_SOCKET的值为zygote/

sZygoteSocket.connect(new LocalSocketAddress(ZYGOTE_SOCKET,

LocalSocketAddress.Namespace.RESERVED));

sZygoteInputStream=

new DataInputStream(sZygoteSocket.getInputStream());

sZygoteWriter=

new BufferedWriter(new OutputStreamWriter(

sZygoteSocket.getOutputStream()),256);

sPreviousZygoteOpenFailed=false;

break;

}catch(IOException ex){

……//省略异常处理部分代码

}

……

}


从ActivityManagerService的systemReady一路分析下来,又回到了zygote。还记得zygote此时已经在runSelectLoopMode方法中等待响应吗?原来,zygote等待的客户端就是ActivityManagerService。ActivityManagerService发送连接请求到zygote的Socket。

现在回顾runSelectLoopMode方法,该方法在接收到客户端请求后,便调用runOnce方法处理请求。该方法位于ZygoteConnection.java中,代码如下:


boolean runOnce()throws ZygoteInit.MethodAndArgsCaller{

String args[];

Arguments parsedArgs=null;

FileDescriptor[]descriptors;

try{

args=readArgumentList();//读取ActivityManagerService传过来的参数

descriptors=mSocket.getAncillaryFileDescriptors();

}

……

int pid=-1;

FileDescriptor childPipeFd=null;

FileDescriptor serverPipeFd=null;

try{//处理参数

parsedArgs=new Arguments(args);

applyUidSecurityPolicy(parsedArgs, peer);

……//省略部分代码

int[][]rlimits=null;

if(parsedArgs.rlimits!=null){

rlimits=parsedArgs.rlimits.toArray(intArray2d);

}

……

/调用forkAndSpecialize方法fork出一个子进程/

pid=Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid,

parsedArgs.gids, parsedArgs.debugFlags, rlimits);

}catch(IOException ex){

……//省略异常处理部分代码

}

try{

if(pid==0){

//在子进程中,这里是Home应用程序所需的进程

IoUtils.closeQuietly(serverPipeFd);

serverPipeFd=null;

/处理子进程/

handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);

return true;

}else{

//父进程或者出错处理

IoUtils.closeQuietly(childPipeFd);

childPipeFd=null;

/父进程zygote处理/

return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs);

}

……


runOnce方法中已经出现Home应用程序启动所需的子进程了,接着分析fork出子进程后,在子进程中都做了什么工作。handleChildProc位于ZygoteConnection.java中,代码如下:


private void handleChildProc(Arguments parsedArgs, FileDescriptor[]descriptors,

FileDescriptor pipeFd, PrintStream newStderr)

throws ZygoteInit.MethodAndArgsCaller{

……//省略部分代码

if(parsedArgs.niceName!=null){

Process.setArgV0(parsedArgs.niceName);

}

/参数中配置了—runtime-init,这里runtimeInit为true/

if(parsedArgs.runtimeInit){

if(parsedArgs.invokeWith!=null){

……//省略部分代码

}else{//根据参数判断走到这里

RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion,

parsedArgs.remainingArgs);

}

}else{

……//省略部分无关代码

}

}


handleChildProc方法中最终调用了RuntimeInit.zygoteInit方法。这个方法是不是很熟悉?我们在zygote启动system_server的时候分析过它,当时该方法依次调用了redirectLogStreams()、commonInit()、zygoteInitNative()、applicationInit(),并最终调用了invokeStaticMain启动了指定类的main函数。只不过这里指定的类名变成了android.app.ActivityThread,因此此时将执行ActivityThread的main方法。

启动ActivityThread后,Home应用程序的主线程便被启动,这里不再详述。通过system_server和Home的启动过程可以看出,Android框架层运行的进程都是由zygote分裂出来的。它们最终运行的都是同一套机制,即RuntimeInit.zygoteInit。

到这里Android上层的启动过程就分析完了。