/* * Main entry of app process. * * Starts the interpreted runtime, then starts up the application. * */ #define LOG_TAG "appproc" #include <utils/IPCThreadState.h> #include <utils/ProcessState.h> #include <utils/Log.h> #include <cutils/process_name.h> #include <cutils/memory.h> #include <android_runtime/AndroidRuntime.h> #include <stdio.h> #include <unistd.h> namespace android { void app_usage() { fprintf(stderr, "Usage: app_process [java-options] cmd-dir start-class-name [options]\n"); } status_t app_init(const char* className, int argc, const char* const argv[]) { LOGV("Entered app_init()!\n"); AndroidRuntime* jr = AndroidRuntime::getRuntime(); jr->callMain(className, argc, argv); LOGV("Exiting app_init()!\n"); return NO_ERROR; } class AppRuntime : public AndroidRuntime { public: AppRuntime() : mParentDir(NULL) , mClassName(NULL) , mArgC(0) , mArgV(NULL) { } #if 0 // this appears to be unused const char* getParentDir() const { return mParentDir; } #endif const char* getClassName() const { return mClassName; } virtual void onStarted() { sp<ProcessState> proc = ProcessState::self(); if (proc->supportsProcesses()) { LOGV("App process: starting thread pool.\n"); proc->startThreadPool(); } app_init(mClassName, mArgC, mArgV); if (ProcessState::self()->supportsProcesses()) { IPCThreadState::self()->stopProcess(); } } virtual void onZygoteInit() { sp<ProcessState> proc = ProcessState::self(); if (proc->supportsProcesses()) { LOGV("App process: starting thread pool.\n"); proc->startThreadPool(); } } virtual void onExit(int code) { if (mClassName == NULL) { // if zygote if (ProcessState::self()->supportsProcesses()) { IPCThreadState::self()->stopProcess(); } } AndroidRuntime::onExit(code); } const char* mParentDir; const char* mClassName; int mArgC; const char* const* mArgV; }; } using namespace android; /* * sets argv0 to as much of newArgv0 as will fit */ static void setArgv0(const char *argv0, const char *newArgv0) { strlcpy(const_cast<char *>(argv0), newArgv0, strlen(argv0)); } int main(int argc, const char* const argv[]) { // These are global variables in ProcessState.cpp mArgC = argc; mArgV = argv; mArgLen = 0; for (int i=0; i<argc; i++) { mArgLen += strlen(argv[i]) + 1; } mArgLen--; AppRuntime runtime; const char *arg; const char *argv0; argv0 = argv[0]; // Process command line arguments // ignore argv[0] argc--; argv++; // Everything up to '--' or first non '-' arg goes to the vm int i = runtime.addVmArguments(argc, argv); // Next arg is parent directory if (i < argc) { runtime.mParentDir = argv[i++]; } // Next arg is startup classname or "--zygote" if (i < argc) { arg = argv[i++]; if (0 == strcmp("--zygote", arg)) { bool startSystemServer = (i < argc) ? strcmp(argv[i], "--start-system-server") == 0 : false; setArgv0(argv0, "zygote"); set_process_name("zygote"); runtime.start("com.android.internal.os.ZygoteInit", startSystemServer); } else { set_process_name(argv0); runtime.mClassName = arg; // Remainder of args get passed to startup class main() runtime.mArgC = argc-i; runtime.mArgV = argv+i; LOGV("App process is starting with pid=%d, class=%s.\n", getpid(), runtime.getClassName()); runtime.start(); } } else { LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied."); fprintf(stderr, "Error: no class name or --zygote supplied.\n"); app_usage(); return 10; } }