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上层的启动过程就分析完了。