透析Activity启动流程(三)-Activity启动的详细流程1

本篇博客将开始介绍Activity启动的详细流程,由于详细启动流程非常复杂,故此分成两篇来介绍。

本篇主要介绍前半部分的启动流程:
1. Activity调用ActivityManagerService启动应用
2. ActivityManagerService调用Zygote孵化应用进程
3. Zygote孵化应用进程
下篇介绍后半部分的启动流程:
4. 新进程启动ActivityThread
5. 应用进程绑定到ActivityManagerService

6. ActivityThread的Handler处理启动Activity的消息

1. Activity调用ActivityManagerService启动应用

第一步 Launcher.startActivitySafely()

Launcher继承自Activity

点击launcher图标后,首先去读取AndroidManifest中入口activity,获取intent;它的默认Activity是MainActivity。然后调用了startActivitySafely方法,startActivitySafely里面包含intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)、startActivity(intent)方法;

这里的intent参数传的是AndroidManifest中intent-filter里面的内容:
<action android:name="android.intent.action.MAIN" />    
<category android:name="android.intent.category.LAUNCHER" />  
加上flag内容,一起包装成intent。
Intent.FLAG_ACTIVITY_NEW_TASK表示要在一个新的Task(任务栈,后进先出)中启动这个Activity。
startActivity的方法是Activity的方法。
在launcher应用程序里启动应用时,点击应用图标后,launcher程序会调用startActivity启动应用,
传递的intent参数:
//Launcher类
intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
intent.setComponent(className);

(从Launcher说起,在Android系统中,应用程序是由Launcher启动起来的,其实,Launcher本身也是一个应用程序,其它的应用程序安装后,就会在Launcher的界面上出现一个相应的图标,点击这个图标时,Launcher就会对应的应用程序启动起来。Launcher的源代码工程在packages/apps/Launcher2目录下,负责启动其它应用程序的源代码实现在src/com/android/launcher2/Launcher.java文件中)

第二步:Activity.startActivity()
(它实现在frameworks/base/core/java/android/app/Activity.java文件中)

该方法里面有startActivityForResult(intent, -1); 第二个参数传入-1表示不需要这个Actvity结束后的返回结果。

第三步:Activtiy.startActivityForResult()

(它实现在frameworks/base/core/java/android/app/Activity.java文件中)

//Activity类
public void startActivityForResult(Intent intent, int requestCode) {  
        if (mParent == null) {  
                Instrumentation.ActivityResult ar =  
                mInstrumentation.execStartActivity(  
                this, mMainThread.getApplicationThread(), mToken, this,  
                intent, requestCode);  
        }
            ......  
 }

mInstrumentation是Activity类的成员变量,它的类型是Intrumentation,它用来监控应用程序和系统的交互。(定义在frameworks/base/core/java/android/app/Instrumentation.java文件中)
mMainThread也是Activity类的成员变量,它的类型是ActivityThread。通过mMainThread.getApplicationThread获得它里面的ApplicationThread成员变量,它是一个Binder对象;(ActivityManagerService会使用它来和ActivityThread来进行进程间通信);
这里需注意的是,这里的mMainThread代表的是Launcher应用程序运行的进程。

这里的mToken也是Activity类的成员变量,它是一个Binder对象的远程接口。

第四步:Instrumentation.execStartActivity()

activity最终调用Instrumentation的execStartActivity来启动应用:

(这个函数定义在frameworks/base/core/java/android/app/Instrumentation.java)

//Instrumentation 类
public class Instrumentation {  
    ......  
    public ActivityResult execStartActivity(  
    Context who, IBinder contextThread, IBinder token, Activity target,  
    Intent intent, int requestCode) {  
        IApplicationThread whoThread = (IApplicationThread) contextThread;  
        if (mActivityMonitors != null) {  
            ......  
        }  
        try {  
            int result = ActivityManagerNative.getDefault()  
                .startActivity(whoThread, intent,  
                intent.resolveTypeIfNeeded(who.getContentResolver()),  
                null, 0, token, target != null ? target.mEmbeddedID : null,  
                requestCode, false, false);  
            ......  
        } catch (RemoteException e) {  
        }  
        return null;  
    }  
    ......  
}  

这里的ActivityManagerNative.getDefault返回ActivityManagerService的远程接口,即ActivityManagerProxy代理对象。

第五步:ActivityManagerProxy.StartActivity()

第六步:ActivityManagerService.startActivity

Instrumentation调用ActivityManagerProxy对象的startActivity方法启动Activity,而ActivityManagerProxy只是ActivityManagerService对象在应用进程的一个代理对象,ActivityManagerProxy最终调用ActivityManagerService的startActvity方法启动Activity。

2. ActivityManagerService调用Zygote孵化应用进程

ActivityManagerProxy对象调用ActivityManagerService对象(运行在system_server进程)的startActivity方法以启动应用。

第七步:ActivityManagerService.startActivityAsUser

startActivity方法接下来调用ActivityManagerService的startActivityAsUser方法以启动应用。

第八步:ActivityStack.startActivityMayWait

//ActivityStack类
final int startActivityMayWait(IApplicationThread caller, int callingUid,
            Intent intent, String resolvedType, IBinder resultTo,
            String resultWho, int requestCode, int startFlags, String profileFile,
            ParcelFileDescriptor profileFd, WaitResult outResult, Configuration config,
            Bundle options, int userId) {
//…
//根据intent在系统中找到合适的应用的activity,如果有多个activity可选择,
//则会弹出ResolverActivity让用户选择合适的应用。
  ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags,
                profileFile, profileFd, userId);
//…
int res = startActivityLocked(caller, intent, resolvedType,
                    aInfo, resultTo, resultWho, requestCode, callingPid, callingUid,
                    startFlags, options, componentSpecified, null);
//…
}

在startActivityAsUser方法里会调用ActivityStack的startActivityMayWait方法以启动应用,startActivityMayWait方法里启动应用时,需先根据intent在系统中找到合适的应用的activity,如果有多个activity可选择,则会弹出ResolverActivity让用户选择合适的应用。

第九步:startActivityLocked

在startActivityLocked方法里,对传过来的参数做一些校验,然后创建ActivityRecord对象,再调用startActivityUncheckedLocked方法启动Activity。

第十步:startActivityUncheckedLocked

//ActivityStack类
final int startActivityUncheckedLocked(ActivityRecord r,
          ActivityRecord sourceRecord, int startFlags, boolean doResume,
          Bundle options) {
    //...          
    startActivityLocked(r, newTask, doResume, keepCurTransition, options);
    //...
}

startActivityUncheckedLocked方法负责调度ActivityRecord和Task。startActivityUncheckedLocked方法调度task的算法非常复杂,和当前回退栈,要启动的acitivity的启动模式以及taskAffinity属性,启动activity时设置的intent的flag等诸多要素相关,intent的flag就有很多种情况。

第十一步:resumeTopActivityLocked(null)

//ActivityStack类
private final void startActivityLocked(ActivityRecord r, boolean newTask,
        boolean doResume, boolean keepCurTransition, Bundle options) {
    //...        
    if (doResume) {
        resumeTopActivityLocked(null);
    }  
}

在startActivityLocked里调用resumeTopActivityLocked显示栈顶Activity。

第十二步:resumeTopActivityLocked(prev, null)

//ActivityStack类
final boolean resumeTopActivityLocked(ActivityRecord prev) {
    return resumeTopActivityLocked(prev, null);
}

resumeTopActivityLocked(null)会调用另一个resumeTopActivityLocked方法显示栈顶的acitivity。

第十三步:startSpecificActivityLocked(next, true, true)

//ActivityStack类
final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {
    //...
    if (next.app != null && next.app.thread != null) {
        //…
    }else{
        //…
        startSpecificActivityLocked(next, true, true);
    }
    //... 
}

因为应用还未启动过,所以调用startSpecificActivityLocked启动应用。

第十四步:mService.startProcessLocked

//ActivityStack类
private final void startSpecificActivityLocked(ActivityRecord r,
            boolean andResume, boolean checkConfig) {
    ProcessRecord app = mService.getProcessRecordLocked(r.processName,
              r.info.applicationInfo.uid);
    //...
    mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
        "activity", r.intent.getComponent(), false, false);
}       

在startSpecificActivityLocked里调用mService.startProcessLocked启动应用

第十五步:ActivityManagerService.startProcessLocked

//ActivityManagerService类
final ProcessRecord startProcessLocked(String processName,
          ApplicationInfo info, boolean knownToBeDead, int intentFlags,
          String hostingType, ComponentName hostingName, boolean allowWhileBooting,
          boolean isolated) {
 ProcessRecord app;
 if (!isolated) {
     app = getProcessRecordLocked(processName, info.uid);
 } else {
     //...
 }
 //...
 if (app == null) {
    app = newProcessRecordLocked(null, info, processName, isolated);
    if (app == null) {
        Slog.w(TAG, "Failed making new process record for "
                + processName + "/" + info.uid + " isolated=" + isolated);
        return null;
    }
    mProcessNames.put(processName, app.uid, app);
    if (isolated) {
        mIsolatedProcesses.put(app.uid, app);
    }
  } else {
   //..
 }
 //...
 startProcessLocked(app, hostingType, hostingNameStr);
 //...
} 

第十六步:在ActivityManagerService类的startProcessLocked方法里

//ActivityManagerService类
private final void startProcessLocked(ProcessRecord app,
        String hostingType, String hostingNameStr) {
  //...
  try {
      //...
      // Start the process.  It will either succeed and return a result containing
  // the PID of the new process, or else throw a RuntimeException.
  //Zygote孵化dalvik应用进程后,会执行android.app.ActivityThread类的main方法
      Process.ProcessStartResult startResult = Process.start("android.app.ActivityThread",
              app.processName, uid, uid, gids, debugFlags, mountExternal,
              app.info.targetSdkVersion, app.info.seinfo, null);
      //...    
  } catch (RuntimeException e) {
      //...
  }
}

第十七步:Process类的start方法里

//Process类
public static final ProcessStartResult start(final String processClass,
                              final String niceName,
                              int uid, int gid, int[] gids,
                              int debugFlags, int mountExternal,
                              int targetSdkVersion,
                              String seInfo,
                              String[] zygoteArgs) {
 try{                              
  startViaZygote(processClass, niceName, uid, gid, gids,
                    debugFlags, mountExternal, targetSdkVersion, seInfo, zygoteArgs);
  }catch (ZygoteStartFailedEx ex) {
    //...
  }                    
}         

在Process类的startViaZygote方法里,会计算启动应用进程用的各个参数,然后再调用zygoteSendArgsAndGetResult方法将这些参数通过socket发送给zygote进程,zygote进程会孵化出新的dalvik应用进程,然后告诉ActivityManagerService新启动的进程的pid。

在Process类的startViaZygote方法里,会计算启动应用进程用的各个参数,然后再调用zygoteSendArgsAndGetResult方法将这些参数通过socket发送给zygote进程,zygote进程会孵化出新的dalvik应用进程,然后告诉ActivityManagerService新启动的进程的pid。

在Process类的startViaZygote方法里,会计算启动应用进程用的各个参数,然后再调用zygoteSendArgsAndGetResult方法将这些参数通过socket发送给zygote进程,zygote进程会孵化出新的dalvik应用进程,然后告诉ActivityManagerService新启动的进程的pid。

3. Zygote孵化应用进程


zygote进程将ZygoteInit作为启动类,会执行它的main方法,先注册ZygoteSocket,然后调用runSelectLoop方法,runSelectLoop方法会调用方法在ZygoteSocket上监听请求,如果别的进程通过ZygoteSocket请求孵化进程,则孵化进程。

第十八步:runSelectLoop

//ZygoteInit类
private static void runSelectLoopMode() throws MethodAndArgsCaller {
  //...
  while (true) {
     //...
      try {
          fdArray = fds.toArray(fdArray);
          index = selectReadable(fdArray);
      } catch (IOException ex) {
          throw new RuntimeException("Error in select()", ex);
      }
      if (index < 0) {
          throw new RuntimeException("Error in select()");
      } else if (index == 0) {
          //监听客户连接请求
          ZygoteConnection newPeer = acceptCommandPeer();
          peers.add(newPeer);
          fds.add(newPeer.getFileDesciptor());
      } else {
         //若客户发送孵化进程的请求过来,
         //此时便需要调用ZygoteConnection的runOnce方法孵化进程
          boolean done;
          done = peers.get(index).runOnce();
          if (done) {
              peers.remove(index);
              fds.remove(index);
          }
      }
  }
}  

第十九步:runOnce

//ZygoteConnection类
boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {
  //...
  try {
  //...
      pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
              parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
              parsedArgs.niceName);
  } 
  //...
  try {
      if (pid == 0) {
          // in child
          IoUtils.closeQuietly(serverPipeFd);
          serverPipeFd = null;
          //handleChildProc是一个很重要的函数,在该函数里使用了异常进行逃逸
          handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);
          //...  
      } else {
         //... 
      }
  } finally {
       //...
  }
}

在runOnce方法里调用Zygote.forkAndSpecialize方法孵化进程,如果返回值为0表示是在孵化出来的应用进程里,此时会调用handleChildProc进行一些处理,并使用异常机制进行逃逸,会直接逃逸至ZygoteInit的main方法。

第二十步:Zygote.forkAndSpecialize

Zygote的forkAndSpecialize方法会调用nativeForkAndSpecialize方法孵化进程,nativeForkAndSpecialize是一个本地方法,它的实现在dalvik/vm/native/dalvik_system_Zygote.cpp里,在该cpp文件里与nativeForkAndSpecialize对应的C++方法是Dalvik_dalvik_system_Zygote_forkAndSpecialize,在该方法里会调用forkAndSpecializeCommon孵化进程,在forkAndSpecializeCommon方法里会调用fork系统调用创建进程,因为使用的是fork机制所以创建进程的效率比较高。

第二十一步:handleChildProc

//ZygoteConnection类
private void handleChildProc(Arguments parsedArgs,
            FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr)
            throws ZygoteInit.MethodAndArgsCaller {
  //...
  if (parsedArgs.runtimeInit) {
  //...
  } else {
      String className;
      try {
          //这里得到的classname实际是android.app.ActivityThread
          className = parsedArgs.remainingArgs[0];
      } catch (ArrayIndexOutOfBoundsException ex) {
          logAndPrintError(newStderr,
                  "Missing required class name argument", null);
          return;
      }
      //...
      if (parsedArgs.invokeWith != null) {
      //...
      } else {
          ClassLoader cloader;
          if (parsedArgs.classpath != null) {
              cloader = new PathClassLoader(parsedArgs.classpath,
                      ClassLoader.getSystemClassLoader());
          } else {
              cloader = ClassLoader.getSystemClassLoader();
          }
          //调用ZygoteInit.invokeStaticMain执行android.app.ActivityThread的main方法        
          try {
              ZygoteInit.invokeStaticMain(cloader, className, mainArgs);
          } catch (RuntimeException ex) {
              logAndPrintError(newStderr, "Error starting.", ex);
          }
      }
  }
}

第二十二步:ZygoteInit的invokeStaticMain方法

//ZygoteInit类
static void invokeStaticMain(ClassLoader loader,
        String className, String[] argv)
        throws ZygoteInit.MethodAndArgsCaller {
  //...        
  Method m;
  try {
      m = cl.getMethod("main", new Class[] { String[].class });
  } catch(//...){
  }
  //...
  throw new ZygoteInit.MethodAndArgsCaller(m, argv);
}

第二十三步:ZygoteInit.MethodAndArgsCaller

public static class MethodAndArgsCaller extends Exception
        implements Runnable {
    //...
    public void run() {
        try {
            mMethod.invoke(null, new Object[] { mArgs });
        }//...
    }
}

第二十四步:ZygoteInit的main方法

//ZygoteInit类
public static void main(String argv[]) {
  try {
      //...
  } catch (MethodAndArgsCaller caller) {
      caller.run();
  } catch (RuntimeException ex) {
      //...
  }
}

到此,前三步已经完成,Zygote进程已经孵化完成了新的dalvik进程。

这里大家注意到,ZygoteInit的invokeStaticMain方法并不会直接执行className的main方法,而是会构造一个 ZygoteInit.MethodAndArgsCaller异常,然后抛出来,通过异常机制会直接跳转到ZygoteInit的main方法, ZygoteInit.MethodAndArgsCaller类实现了Runnable方法,在run方法里会执行要求执行的main方法,故此跳转到ZygoteInit的main方法后,异常会被捕获,然后执行方法caller.run(),这样便会执行android.app.ActivityThread的main方法。

在抛出异常后,如果异常没有在当前的函数中捕获,那么当前的函数执行就会异常的退出,从应用程序的栈弹出,并将这个异常传递给上一个函数,直到异常被捕获处理,否则,就会引起程序的崩溃。 
那我们来看一下fork出新的子进程后,函数的执行流程: 

handleChildProc——>ZygoteInit.invokeStaticMain(抛异常)——>ZygoteInit.main——>MethodAndArgsCaller.run——>ActivityThread.main。

大家肯定有疑问,为什么要用抛异常的方式去启动ActivityThread的main函数呢?而不直接在ZygoteInit.invokeStaticMain中通过反射调用ActivityThread.main? 

其实,无论我们写c程序还是java程序,他们都只有一个入口就是main函数,当main函数返回退出后就代表整个程序退出了,根据上面分析的函数的执行模型,程序的main函数应该是每一个应用程序最后退出的函数,应该位于栈的底部。同理,Android应用程序的入口是ActivityThread.main函数,所以它也应该位于新的进程的栈的ZygoteInit.main函数的上面,这样才能实现直接退出应用程序,但是Android每fork一个新进程的时候,它都会先调用handleChildProc函数做一些,子进程的处理,此时应用程序栈的最低部函数是handleChildProc,接着还会压入ZygoteInit.invokeStaticMain函数。

所以通过抛异常的方式启动ActivityThread.main函数主要是清理应用程序栈中ZygoteInit.main以上的函数栈帧,以实现当ActivityThread.main函数退出时,能直接退出整个应用程序。 

当ActivityThread的main退出后,就会退回到MethodAndArgsCaller.run而这个函数直接就退回到ZygoteInit.main函数,而ZygoteInit.main也无其他的操作,直接退出了函数,这样整个应用程序将会完全退出。

透析Activity启动流程(三)-Activity启动的详细流程2

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值