diff options
Diffstat (limited to 'cmds/app_process/app_main.cpp')
-rw-r--r-- | cmds/app_process/app_main.cpp | 204 |
1 files changed, 204 insertions, 0 deletions
diff --git a/cmds/app_process/app_main.cpp b/cmds/app_process/app_main.cpp new file mode 100644 index 0000000..6fe358c --- /dev/null +++ b/cmds/app_process/app_main.cpp @@ -0,0 +1,204 @@ +/* + * Main entry of app process. + * + * Starts the interpreted runtime, then starts up the application. + * + */ + +#define LOG_TAG "appproc" + +#include <binder/IPCThreadState.h> +#include <binder/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"); +} + +class AppRuntime : public AndroidRuntime +{ +public: + AppRuntime() + : mParentDir(NULL) + , mClassName(NULL) + , mClass(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 onVmCreated(JNIEnv* env) + { + if (mClassName == NULL) { + return; // Zygote. Nothing to do here. + } + + /* + * This is a little awkward because the JNI FindClass call uses the + * class loader associated with the native method we're executing in. + * If called in onStarted (from RuntimeInit.finishInit because we're + * launching "am", for example), FindClass would see that we're calling + * from a boot class' native method, and so wouldn't look for the class + * we're trying to look up in CLASSPATH. Unfortunately it needs to, + * because the "am" classes are not boot classes. + * + * The easiest fix is to call FindClass here, early on before we start + * executing boot class Java code and thereby deny ourselves access to + * non-boot classes. + */ + char* slashClassName = toSlashClassName(mClassName); + mClass = env->FindClass(slashClassName); + if (mClass == NULL) { + ALOGE("ERROR: could not find class '%s'\n", mClassName); + } + free(slashClassName); + + mClass = reinterpret_cast<jclass>(env->NewGlobalRef(mClass)); + } + + virtual void onStarted() + { + sp<ProcessState> proc = ProcessState::self(); + ALOGV("App process: starting thread pool.\n"); + proc->startThreadPool(); + + AndroidRuntime* ar = AndroidRuntime::getRuntime(); + ar->callMain(mClassName, mClass, mArgC, mArgV); + + IPCThreadState::self()->stopProcess(); + } + + virtual void onZygoteInit() + { + sp<ProcessState> proc = ProcessState::self(); + ALOGV("App process: starting thread pool.\n"); + proc->startThreadPool(); + } + + virtual void onExit(int code) + { + if (mClassName == NULL) { + // if zygote + IPCThreadState::self()->stopProcess(); + } + + AndroidRuntime::onExit(code); + } + + + const char* mParentDir; + const char* mClassName; + jclass mClass; + 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* 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); + + // Parse runtime arguments. Stop at first unrecognized option. + bool zygote = false; + bool startSystemServer = false; + bool application = false; + const char* parentDir = NULL; + const char* niceName = NULL; + const char* className = NULL; + while (i < argc) { + const char* arg = argv[i++]; + if (!parentDir) { + parentDir = arg; + } else if (strcmp(arg, "--zygote") == 0) { + zygote = true; + niceName = "zygote"; + } else if (strcmp(arg, "--start-system-server") == 0) { + startSystemServer = true; + } else if (strcmp(arg, "--application") == 0) { + application = true; + } else if (strncmp(arg, "--nice-name=", 12) == 0) { + niceName = arg + 12; + } else { + className = arg; + break; + } + } + + if (niceName && *niceName) { + setArgv0(argv0, niceName); + set_process_name(niceName); + } + + runtime.mParentDir = parentDir; + + if (zygote) { + runtime.start("com.android.internal.os.ZygoteInit", + startSystemServer ? "start-system-server" : ""); + } else if (className) { + // Remainder of args get passed to startup class main() + runtime.mClassName = className; + runtime.mArgC = argc - i; + runtime.mArgV = argv + i; + runtime.start("com.android.internal.os.RuntimeInit", + application ? "application" : "tool"); + } else { + fprintf(stderr, "Error: no class name or --zygote supplied.\n"); + app_usage(); + LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied."); + return 10; + } +} |