在Android的应用框架中,ActivityManagerService是非常重要的一个组件,尽管名字叫做ActivityManagerService,但通过之前的博客介绍,我们知道,四大组件的创建都是有AMS来完成的,其实不仅是应用程序中的组件,连Android应用程序本身也是AMS负责启动的。AMS本身运行在一个独立的进程中,当系统决定要在一个新的进程中启动一个Activity或者Service时就会先启动这个进程。而AMS启动进程的过程是从startProcessLocked启动的。

1.ActivityManagerService.startProcessLocked

public final class ActivityManagerService extends ActivityManagerNative     implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {   ......   private final void startProcessLocked(ProcessRecord app,         String hostingType, String hostingNameStr) {     ......     try {       int uid = app.info.uid;       int[] gids = null;       try {         gids = mContext.getPackageManager().getPackageGids(           app.info.packageName);       } catch (PackageManager.NameNotFoundException e) {         ......       }       ......       int debugFlags = 0;       ......       int pid = Process.start("android.app.ActivityThread",         mSimpleProcessManagement ? app.processName : null, uid, uid,         gids, debugFlags, null);       ......     } catch (RuntimeException e) {       ......     }   }   ...... } 

可以看到,函数会调用Process.start函数来创建一个进程,其中第一个参数”android.app.ActivityThread”是需要加载的类,而在完成这个类的加载之后就会运行ActivityThread.main函数。

2.Process.start

public class Process {  ......  public static final int start(final String processClass,    final String niceName,    int uid, int gid, int[] gids,    int debugFlags,    String[] zygoteArgs)  {    if (supportsProcesses()) {      try {        return startViaZygote(processClass, niceName, uid, gid, gids,          debugFlags, zygoteArgs);      } catch (ZygoteStartFailedEx ex) {        ......      }    } else {      ......      return 0;    }  }  ......}

这个函数最后会调用startViaZygote来创建进程,而Zygote正是Android孵化进程的服务,所有的进程都是通过Zygotefork出来的,所以这里创建进程的任务又落到了Zygote头上了。

3.Process.startViaZygote

public class Process {  ......  private static int startViaZygote(final String processClass,      final String niceName,      final int uid, final int gid,      final int[] gids,      int debugFlags,      String[] extraArgs)      throws ZygoteStartFailedEx {    int pid;    synchronized(Process.class) {      ArrayList argsForZygote = new ArrayList();      // --runtime-init, --setuid=, --setgid=,      // and --setgroups= must go first      argsForZygote.add("--runtime-init");      argsForZygote.add("--setuid=" + uid);      argsForZygote.add("--setgid=" + gid);      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");      }      if ((debugFlags & Zygote.DEBUG_ENABLE_ASSERT) != 0) {        argsForZygote.add("--enable-assert");      }      //TODO optionally enable debuger      //argsForZygote.add("--enable-debugger");      // --setgroups is a comma-separated list      if (gids != null && gids.length > 0) {        StringBuilder sb = new StringBuilder();        sb.append("--setgroups=");        int sz = gids.length;        for (int i = 0; i < sz; i++) {          if (i != 0) {            sb.append(',');          }          sb.append(gids[i]);        }        argsForZygote.add(sb.toString());      }      if (niceName != null) {        argsForZygote.add("--nice-name=" + niceName);      }      argsForZygote.add(processClass);      if (extraArgs != null) {        for (String arg : extraArgs) {          argsForZygote.add(arg);        }      }      pid = zygoteSendArgsAndGetPid(argsForZygote);    }  }  ......}

函数里面最为重要的工作就是组装argsForZygote参数,这些参数将告诉Zygote具体的启动选项,例如”�Cruntime-init”就表示要为新启动的运行程序初始化运行库。然后调用zygoteSendAndGetPid函数进一步操作。

4.Process.zygoteSendAndGetPid

public class Process {  ......  private static int zygoteSendArgsAndGetPid(ArrayList args)      throws ZygoteStartFailedEx {    int pid;    openZygoteSocketIfNeeded();    try {      /**      * See com.android.internal.os.ZygoteInit.readArgumentList()      * Presently the wire format to the zygote process is:      * a) a count of arguments (argc, in essence)      * b) a number of newline-separated argument strings equal to count      *      * After the zygote process reads these it will write the pid of      * the child or -1 on failure.      */      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();      // Should there be a timeout on this?      pid = sZygoteInputStream.readInt();      if (pid < 0) {        throw new ZygoteStartFailedEx("fork() failed");      }    } catch (IOException ex) {      ......    }    return pid;  }  ......}这里的sZygoteWriter

是一个Socket写入流,是由openZygoteSocketIfNeeded函数打开的。而这个Socket由frameworks/base/core/java/com/android/internal/os/ZygoteInit.java文件中的ZygoteInit类在runSelectLoopMode函数侦听的。这个类会返回一个ZygoteConnection实例,并执行ZygoteConnection的runOnce函数。

5.ZygoteConnection.runOnce

class ZygoteConnection {  ......  boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {    String args[];    Arguments parsedArgs = null;    FileDescriptor[] descriptors;    try {      args = readArgumentList();      descriptors = mSocket.getAncillaryFileDescriptors();    } catch (IOException ex) {      ......      return true;    }    ......    /** the stderr of the most recent request, if avail */    PrintStream newStderr = null;    if (descriptors != null && descriptors.length >= 3) {      newStderr = new PrintStream(        new FileOutputStream(descriptors[2]));    }    int pid;    try {      parsedArgs = new Arguments(args);      applyUidSecurityPolicy(parsedArgs, peer);      applyDebuggerSecurityPolicy(parsedArgs);      applyRlimitSecurityPolicy(parsedArgs, peer);      applyCapabilitiesSecurityPolicy(parsedArgs, peer);      int[][] rlimits = null;      if (parsedArgs.rlimits != null) {        rlimits = parsedArgs.rlimits.toArray(intArray2d);      }      pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid,        parsedArgs.gids, parsedArgs.debugFlags, rlimits);    } catch (IllegalArgumentException ex) {      ......    } catch (ZygoteSecurityException ex) {      ......    }    if (pid == 0) {      // in child      handleChildProc(parsedArgs, descriptors, newStderr);      // should never happen      return true;    } else { /* pid != 0 */      // in parent...pid of < 0 means failure      return handleParentProc(pid, descriptors, parsedArgs);    }  }  ......}

真正创建进程的代码在Zygote.forkAndSpecialize,通过Zygote来fork出一个新的进程作为应用进程。fork函数会有两个返回,其中一个在父进程,一个在子进程,其中自进程的进程号会为0,所以按照上面的代码,这里会执行handleChildProc。

6.ZygoteConnection.handleChildProc

class ZygoteConnection {  ......  private void handleChildProc(Arguments parsedArgs,      FileDescriptor[] descriptors, PrintStream newStderr)      throws ZygoteInit.MethodAndArgsCaller {    ......    if (parsedArgs.runtimeInit) {      RuntimeInit.zygoteInit(parsedArgs.remainingArgs);    } else {      ......    }  }  ......}

因为在创建的时候传入了“�Cruntime-init”,所以这里会运行RuntimeInit.zygoteInit。

public class RuntimeInit {  ......  public static final void zygoteInit(String[] argv)      throws ZygoteInit.MethodAndArgsCaller {    // TODO: Doing this here works, but it seems kind of arbitrary. Find    // a better place. The goal is to set it up for applications, but not    // tools like am.    System.setOut(new AndroidPrintStream(Log.INFO, "System.out"));    System.setErr(new AndroidPrintStream(Log.WARN, "System.err"));    commonInit();    zygoteInitNative();    int curArg = 0;    for ( /* curArg */ ; curArg < argv.length; curArg++) {      String arg = argv[curArg];      if (arg.equals("--")) {        curArg++;        break;      } else if (!arg.startsWith("--")) {        break;      } else if (arg.startsWith("--nice-name=")) {        String niceName = arg.substring(arg.indexOf('=') + 1);        Process.setArgV0(niceName);      }    }    if (curArg == argv.length) {      Slog.e(TAG, "Missing classname argument to RuntimeInit!");      // let the process exit      return;    }    // Remaining arguments are passed to the start class's static main    String startClass = argv[curArg++];    String[] startArgs = new String[argv.length - curArg];    System.arraycopy(argv, curArg, startArgs, 0, startArgs.length);    invokeStaticMain(startClass, startArgs);  }  ......}

这里有两个关键的函数调用,一个是zygoteInitNative函数调用,一个是invokeStaticMain函数调用,前者就是执行Binder驱动程序初始化的相关工作了,正是由于执行了这个工作,才使得进程中的Binder对象能够顺利地进行Binder进程间通信,而后一个函数调用,就是执行进程的入口函数,这里就是执行startClass类的main函数了,而这个startClass即是我们在Step 1中传进来的”android.app.ActivityThread”值,表示要执行android.app.ActivityThread类的main函数。

7. Zygote.invokeStaticMain

public class ZygoteInit {  ......  static void invokeStaticMain(ClassLoader loader,      String className, String[] argv)      throws ZygoteInit.MethodAndArgsCaller {    Class<?> cl;    try {      cl = loader.loadClass(className);    } catch (ClassNotFoundException ex) {      ......    }    Method m;    try {      m = cl.getMethod("main", new Class[] { String[].class });    } catch (NoSuchMethodException ex) {      ......    } catch (SecurityException ex) {      ......    }    int modifiers = m.getModifiers();    ......    /*    * This throw gets caught in ZygoteInit.main(), which responds    * by invoking the exception's run() method. This arrangement    * clears up all the stack frames that were required in setting    * up the process.    */    throw new ZygoteInit.MethodAndArgsCaller(m, argv);  }  ......}

从代码中可以看到,通过ClassLoader加载对应的android.app.ActivityThread类,然后再获取到对应的main函数句柄,最后调用该类的main函数。不过这里的调用方式比较有意思,不知直接调用,而是通过抛出一个异常。这样做的方式是为了清空堆栈,让系统认为新进程是从ActivityThread的main函数开始的。

8.ActivityThread.main

public final class ActivityThread {  ......  public static final void main(String[] args) {    SamplingProfilerIntegration.start();    Process.setArgV0("");    Looper.prepareMainLooper();    if (sMainThreadHandler == null) {      sMainThreadHandler = new Handler();    }    ActivityThread thread = new ActivityThread();    thread.attach(false);    if (false) {      Looper.myLooper().setMessageLogging(new        LogPrinter(Log.DEBUG, "ActivityThread"));    }    Looper.loop();    if (Process.supportsProcesses()) {      throw new RuntimeException("Main thread loop unexpectedly exited");    }    thread.detach();    String name = (thread.mInitialApplication != null)      ? thread.mInitialApplication.getPackageName()      : "";    Slog.i(TAG, "Main thread of " + name + " is now exiting");  }  ......}

从这里我们可以看出,这个函数首先会在进程中创建一个ActivityThread对象,然后进入消息循环中,这样,我们以后就可以在这个进程中启动Activity或者Service了。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

更多相关文章

  1. C语言函数的递归(上)
  2. Android(安卓)Material Design:CoordinatorLayout与NestedScrollV
  3. android studio adb连接不上手机 ADB server didn't ACK
  4. Android中使用讯飞语音合成(报21001)组件未安装
  5. Android(安卓)ListView拖动时背景颜色会变成黑色的解决办法
  6. delphi XE Android四大组件ContentProvider:delphi XE可调用的And
  7. 关于Android(安卓)ListView组件中android:drawSelectorOnTop含义
  8. adb server is out of date. killing...
  9. androidUI控件下载地址

随机推荐

  1. MySQL8.0内存相关参数总结
  2. mysql解决时区相关问题
  3. 详细分析mysql视图的原理及使用方法
  4. mysql如何在线修改主从复制选项
  5. MySQL INT类型全解析
  6. 详解MySQL 外键约束
  7. MySQL数据库使用规范总结
  8. MySQL 常用函数总结
  9. 如何选择合适的MySQL日期时间类型来存储
  10. mysql 时间戳的用法