Android Application Framework Application startup process detailed _android

Source: Internet
Author: User
Tags socket

In the Android application framework, Activitymanagerservice is a very important component, although the name is Activitymanagerservice, but through the previous blog introduction, we know that the four components are created with AMS to complete , not just the components in the application, but the Android application itself is the AMS startup. The AMS itself is running in a separate process that starts when the system decides to start an activity or service in a new process. The AMS startup process is initiated from the 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); 
      The 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) {...} 

} 
  ...... 
} 

As you can see, the function calls the Process.Start function to create a process where the first argument "Android.app.ActivityThread" is the class that needs to be loaded. The Activitythread.main function is run after the load of this class is completed.

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;
    }
  }
  ......
}

This function eventually calls Startviazygote to create the process, and zygote is the service of the Android incubation process, all processes are zygotefork out, so the task of creating the process here falls to zygote.

3.process.startviazygote

public class Process {... private static int startviazygote (final string processclass, final string Nicenam E, Final int uid, final int gid, final int[] gids, int debugflags, string[] extraargs) throw

    s zygotestartfailedex {int pid;

      Synchronized (process.class) {arraylist<string> argsforzygote = new arraylist<string> (); --runtime-init,--setuid=,--setgid=,//And--setgroups= must go a 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);

 }
  }
  ......
}

The most important task in a function is to assemble argsforzygote parameters that tell zygote specific startup options, such as "–runtime-init", which means that the runtime is initialized for the newly-launched runtime. Then call the Zygotesendandgetpid function for further action.

4.process.zygotesendandgetpid

public class Process {... private static int zygotesendargsandgetpid (Arraylist<string> args) throws

    zygotestartfailedex {int PID;

    Openzygotesocketifneeded ();  try {/** * 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 s Trings equal to Count * * on the zygote process reads these it would 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;

}
  ......
}
 Here's the szygotewriter.

is a socket write stream, which is opened by the openzygotesocketifneeded function. And this socket is made by frameworks/base/core/java/com/android/internal/os/ The Zygoteinit class in the Zygoteinit.java file listens on the Runselectloopmode function. This class returns a Zygoteconnection instance and executes the Zygoteconnection RunOnce function.

5.zygoteconnection.runonce

Class Zygoteconnection {... boolean runOnce () throws Zygoteinit.methodandargscaller {String args[];
    Arguments Parsedargs = null;

    Filedescriptor[] descriptors;
      try {args = Readargumentlist ();
    descriptors = Msocket.getancillaryfiledescriptors ();
    The catch (IOException ex) {... return true;

    /** the stderr of the most recent request, if avail/printstream = null; if (descriptors!= null && descriptors.length >= 3) {newstderr = new PrintStream (New Fileoutput
    Stream (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, RL
    Imits);

    The 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, p
    Arsedargs);

 }
  }
  ......
}

The code that really creates the process is zygote.forkandspecialize, zygote to fork a new process as an application process. The fork function will have two returns, one in the parent process, one in the subprocess, where the process number from the process will be 0, so follow the code above to execute the 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 {
      ...
    }
  }
  ......
}

Because the "–runtime-init" was passed in when it was created, Runtimeinit.zygoteinit is running here.

public class Runtimeinit {... public static final void Zygoteinit (string[] argv) throws Zygoteinit.methoda Ndargscaller {//todo:doing this is 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 theProcess 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);

 }
  ......
}

Here are two key function calls, one is the zygoteinitnative function call, one is the Invokestaticmain function call, the former is the execution of the binder driver initialization related work, it is because of the implementation of this work, The binder object in the process can smoothly binder interprocess communication, and then a function call, which is the entry function to execute the process, here is the execution of the main function of the Startclass class, which is the startclass that we passed in step 1. Android.app.ActivityThread value that represents the main function to perform the Android.app.ActivityThread class.

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);

    The catch (ClassNotFoundException ex) {...}
    Method M;
    try {m = Cl.getmethod ("main", new class[] {string[].class});

    The catch (Nosuchmethodexception ex) {...} catch (SecurityException ex) {...}
    int modifiers = M.getmodifiers (); ... * * * throw gets caught in Zygoteinit.main (), which responds * by invoking the exception ' s run () m Ethod.
    This arrangement * Clears the stack frames which were required in setting * up the process.
  * * Throw new Zygoteinit.methodandargscaller (M, argv);

}
  ......
} 

You can see from the code that the corresponding Android.app.ActivityThread class is loaded by ClassLoader, then the corresponding main function handle is fetched, and the main function of the class is finally called. But the way to call here is more interesting, I do not know the direct call, but by throwing an exception. The way to do this is to empty the stack and let the system think that the new process started with the Activitythread main function.

8.activitythread.main

 Public final class Activitythread {... public static final void Main (string[) a

    RGS) {Samplingprofilerintegration.start ();

    Process.setargv0 ("<pre-initialized>");
    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 (): "<unknown>";
  SLOG.I (TAG, "Main thread of" + name + "is now exiting");

}

  ......
} 

From here we can see that this function first creates a Activitythread object in the process and then goes into the message loop so that we can start the activity or service in the process later.

The above is the entire content of this article, I hope to help you learn, but also hope that we support the cloud habitat community.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.