summaryrefslogtreecommitdiffstats
path: root/cmds/app_process/app_main.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'cmds/app_process/app_main.cpp')
-rw-r--r--cmds/app_process/app_main.cpp204
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;
+ }
+}