Home | History | Annotate | Download | only in app_process
      1 /*
      2  * Main entry of app process.
      3  *
      4  * Starts the interpreted runtime, then starts up the application.
      5  *
      6  */
      7 
      8 #define LOG_TAG "appproc"
      9 
     10 #include <binder/IPCThreadState.h>
     11 #include <binder/ProcessState.h>
     12 #include <utils/Log.h>
     13 #include <cutils/process_name.h>
     14 #include <cutils/memory.h>
     15 #include <android_runtime/AndroidRuntime.h>
     16 
     17 #include <stdio.h>
     18 #include <unistd.h>
     19 
     20 namespace android {
     21 
     22 void app_usage()
     23 {
     24     fprintf(stderr,
     25         "Usage: app_process [java-options] cmd-dir start-class-name [options]\n");
     26 }
     27 
     28 status_t app_init(const char* className, int argc, const char* const argv[])
     29 {
     30     LOGV("Entered app_init()!\n");
     31 
     32     AndroidRuntime* jr = AndroidRuntime::getRuntime();
     33     jr->callMain(className, argc, argv);
     34 
     35     LOGV("Exiting app_init()!\n");
     36     return NO_ERROR;
     37 }
     38 
     39 class AppRuntime : public AndroidRuntime
     40 {
     41 public:
     42     AppRuntime()
     43         : mParentDir(NULL)
     44         , mClassName(NULL)
     45         , mArgC(0)
     46         , mArgV(NULL)
     47     {
     48     }
     49 
     50 #if 0
     51     // this appears to be unused
     52     const char* getParentDir() const
     53     {
     54         return mParentDir;
     55     }
     56 #endif
     57 
     58     const char* getClassName() const
     59     {
     60         return mClassName;
     61     }
     62 
     63     virtual void onStarted()
     64     {
     65         sp<ProcessState> proc = ProcessState::self();
     66         if (proc->supportsProcesses()) {
     67             LOGV("App process: starting thread pool.\n");
     68             proc->startThreadPool();
     69         }
     70 
     71         app_init(mClassName, mArgC, mArgV);
     72 
     73         if (ProcessState::self()->supportsProcesses()) {
     74             IPCThreadState::self()->stopProcess();
     75         }
     76     }
     77 
     78     virtual void onZygoteInit()
     79     {
     80         sp<ProcessState> proc = ProcessState::self();
     81         if (proc->supportsProcesses()) {
     82             LOGV("App process: starting thread pool.\n");
     83             proc->startThreadPool();
     84         }
     85     }
     86 
     87     virtual void onExit(int code)
     88     {
     89         if (mClassName == NULL) {
     90             // if zygote
     91             if (ProcessState::self()->supportsProcesses()) {
     92                 IPCThreadState::self()->stopProcess();
     93             }
     94         }
     95 
     96         AndroidRuntime::onExit(code);
     97     }
     98 
     99 
    100     const char* mParentDir;
    101     const char* mClassName;
    102     int mArgC;
    103     const char* const* mArgV;
    104 };
    105 
    106 }
    107 
    108 using namespace android;
    109 
    110 /*
    111  * sets argv0 to as much of newArgv0 as will fit
    112  */
    113 static void setArgv0(const char *argv0, const char *newArgv0)
    114 {
    115     strlcpy(const_cast<char *>(argv0), newArgv0, strlen(argv0));
    116 }
    117 
    118 int main(int argc, const char* const argv[])
    119 {
    120     // These are global variables in ProcessState.cpp
    121     mArgC = argc;
    122     mArgV = argv;
    123 
    124     mArgLen = 0;
    125     for (int i=0; i<argc; i++) {
    126         mArgLen += strlen(argv[i]) + 1;
    127     }
    128     mArgLen--;
    129 
    130     AppRuntime runtime;
    131     const char *arg;
    132     const char *argv0;
    133 
    134     argv0 = argv[0];
    135 
    136     // Process command line arguments
    137     // ignore argv[0]
    138     argc--;
    139     argv++;
    140 
    141     // Everything up to '--' or first non '-' arg goes to the vm
    142 
    143     int i = runtime.addVmArguments(argc, argv);
    144 
    145     // Next arg is parent directory
    146     if (i < argc) {
    147         runtime.mParentDir = argv[i++];
    148     }
    149 
    150     // Next arg is startup classname or "--zygote"
    151     if (i < argc) {
    152         arg = argv[i++];
    153         if (0 == strcmp("--zygote", arg)) {
    154             bool startSystemServer = (i < argc) ?
    155                     strcmp(argv[i], "--start-system-server") == 0 : false;
    156             setArgv0(argv0, "zygote");
    157             set_process_name("zygote");
    158             runtime.start("com.android.internal.os.ZygoteInit",
    159                 startSystemServer);
    160         } else {
    161             set_process_name(argv0);
    162 
    163             runtime.mClassName = arg;
    164 
    165             // Remainder of args get passed to startup class main()
    166             runtime.mArgC = argc-i;
    167             runtime.mArgV = argv+i;
    168 
    169             LOGV("App process is starting with pid=%d, class=%s.\n",
    170                  getpid(), runtime.getClassName());
    171             runtime.start();
    172         }
    173     } else {
    174         LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
    175         fprintf(stderr, "Error: no class name or --zygote supplied.\n");
    176         app_usage();
    177         return 10;
    178     }
    179 
    180 }
    181