summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cmds/app_process/app_main.cpp99
-rw-r--r--core/jni/AndroidRuntime.cpp41
-rw-r--r--include/android_runtime/AndroidRuntime.h5
3 files changed, 85 insertions, 60 deletions
diff --git a/cmds/app_process/app_main.cpp b/cmds/app_process/app_main.cpp
index bdbb08c..e0290c3 100644
--- a/cmds/app_process/app_main.cpp
+++ b/cmds/app_process/app_main.cpp
@@ -32,30 +32,20 @@ class AppRuntime : public AndroidRuntime
public:
AppRuntime(char* argBlockStart, const size_t argBlockLength)
: AndroidRuntime(argBlockStart, argBlockLength)
- , 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;
+ void setClassNameAndArgs(const String8& className, int argc, char * const *argv) {
+ mClassName = className;
+ for (int i = 0; i < argc; ++i) {
+ mArgs.add(String8(argv[i]));
+ }
}
virtual void onVmCreated(JNIEnv* env)
{
- if (mClassName == NULL) {
+ if (mClassName.isEmpty()) {
return; // Zygote. Nothing to do here.
}
@@ -72,10 +62,10 @@ public:
* executing boot class Java code and thereby deny ourselves access to
* non-boot classes.
*/
- char* slashClassName = toSlashClassName(mClassName);
+ char* slashClassName = toSlashClassName(mClassName.string());
mClass = env->FindClass(slashClassName);
if (mClass == NULL) {
- ALOGE("ERROR: could not find class '%s'\n", mClassName);
+ ALOGE("ERROR: could not find class '%s'\n", mClassName.string());
}
free(slashClassName);
@@ -89,7 +79,7 @@ public:
proc->startThreadPool();
AndroidRuntime* ar = AndroidRuntime::getRuntime();
- ar->callMain(mClassName, mClass, mArgC, mArgV);
+ ar->callMain(mClassName, mClass, mArgs);
IPCThreadState::self()->stopProcess();
}
@@ -115,11 +105,9 @@ public:
}
- const char* mParentDir;
- const char* mClassName;
+ String8 mClassName;
+ Vector<String8> mArgs;
jclass mClass;
- int mArgC;
- const char* const* mArgV;
};
}
@@ -155,7 +143,26 @@ int main(int argc, char* const argv[])
argc--;
argv++;
- // Everything up to '--' or first non '-' arg goes to the vm
+ // Everything up to '--' or first non '-' arg goes to the vm.
+ //
+ // The first argument after the VM args is the "parent dir", which
+ // is currently unused.
+ //
+ // After the parent dir, we expect one or more the following internal
+ // arguments :
+ //
+ // --zygote : Start in zygote mode
+ // --start-system-server : Start the system server.
+ // --application : Start in application (stand alone, non zygote) mode.
+ // --nice-name : The nice name for this process.
+ //
+ // For non zygote starts, these arguments will be followed by
+ // the main class name. All remaining arguments are passed to
+ // the main method of this class.
+ //
+ // For zygote starts, all remaining arguments are passed to the zygote.
+ // main function.
+
int i = runtime.addVmArguments(argc, argv);
@@ -163,14 +170,13 @@ int main(int argc, char* const argv[])
bool zygote = false;
bool startSystemServer = false;
bool application = false;
- const char* parentDir = NULL;
const char* niceName = NULL;
- const char* className = NULL;
+ String8 className;
+
+ ++i; // Skip unused "parent dir" argument.
while (i < argc) {
const char* arg = argv[i++];
- if (!parentDir) {
- parentDir = arg;
- } else if (strcmp(arg, "--zygote") == 0) {
+ if (strcmp(arg, "--zygote") == 0) {
zygote = true;
niceName = "zygote";
} else if (strcmp(arg, "--start-system-server") == 0) {
@@ -180,28 +186,41 @@ int main(int argc, char* const argv[])
} else if (strncmp(arg, "--nice-name=", 12) == 0) {
niceName = arg + 12;
} else {
- className = arg;
+ className.setTo(arg);
break;
}
}
+ Vector<String8> args;
+ if (!className.isEmpty()) {
+ // We're not in zygote mode, the only argument we need to pass
+ // to RuntimeInit is the application argument.
+ //
+ // The Remainder of args get passed to startup class main(). Make
+ // copies of them before we overwrite them with the process name.
+ args.add(application ? String8("application") : String8("tool"));
+ runtime.setClassNameAndArgs(className, argc - i, argv + i);
+ } else {
+ if (startSystemServer) {
+ args.add(String8("start-system-server"));
+ }
+
+ // In zygote mode, pass all remaining arguments to the zygote
+ // main() method.
+ for (; i < argc; ++i) {
+ args.add(String8(argv[i]));
+ }
+ }
+
if (niceName && *niceName) {
runtime.setArgv0(niceName);
set_process_name(niceName);
}
- runtime.mParentDir = parentDir;
-
if (zygote) {
- runtime.start("com.android.internal.os.ZygoteInit",
- startSystemServer ? "start-system-server" : "");
+ runtime.start("com.android.internal.os.ZygoteInit", args);
} 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");
+ runtime.start("com.android.internal.os.RuntimeInit", args);
} else {
fprintf(stderr, "Error: no class name or --zygote supplied.\n");
app_usage();
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 4759451..aa635c6 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -271,13 +271,13 @@ void AndroidRuntime::setArgv0(const char* argv0) {
strlcpy(mArgBlockStart, argv0, mArgBlockLength);
}
-status_t AndroidRuntime::callMain(const char* className,
- jclass clazz, int argc, const char* const argv[])
+status_t AndroidRuntime::callMain(const String8& className, jclass clazz,
+ const Vector<String8>& args)
{
JNIEnv* env;
jmethodID methodId;
- ALOGD("Calling main entry %s", className);
+ ALOGD("Calling main entry %s", className.string());
env = getJNIEnv();
if (clazz == NULL || env == NULL) {
@@ -286,7 +286,7 @@ status_t AndroidRuntime::callMain(const char* className,
methodId = env->GetStaticMethodID(clazz, "main", "([Ljava/lang/String;)V");
if (methodId == NULL) {
- ALOGE("ERROR: could not find method %s.main(String[])\n", className);
+ ALOGE("ERROR: could not find method %s.main(String[])\n", className.string());
return UNKNOWN_ERROR;
}
@@ -297,11 +297,12 @@ status_t AndroidRuntime::callMain(const char* className,
jclass stringClass;
jobjectArray strArray;
+ const size_t numArgs = args.size();
stringClass = env->FindClass("java/lang/String");
- strArray = env->NewObjectArray(argc, stringClass, NULL);
+ strArray = env->NewObjectArray(numArgs, stringClass, NULL);
- for (int i = 0; i < argc; i++) {
- jstring argStr = env->NewStringUTF(argv[i]);
+ for (size_t i = 0; i < numArgs; i++) {
+ jstring argStr = env->NewStringUTF(args[i].string());
env->SetObjectArrayElement(strArray, i, argStr);
}
@@ -873,20 +874,23 @@ char* AndroidRuntime::toSlashClassName(const char* className)
* Passes the main function two arguments, the class name and the specified
* options string.
*/
-void AndroidRuntime::start(const char* className, const char* options)
+void AndroidRuntime::start(const char* className, const Vector<String8>& options)
{
ALOGD("\n>>>>>> AndroidRuntime START %s <<<<<<\n",
className != NULL ? className : "(unknown)");
+ static const String8 startSystemServer("start-system-server");
+
/*
* 'startSystemServer == true' means runtime is obsolete and not run from
* init.rc anymore, so we print out the boot start event here.
*/
- if (strcmp(options, "start-system-server") == 0) {
- /* track our progress through the boot sequence */
- const int LOG_BOOT_PROGRESS_START = 3000;
- LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START,
- ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
+ for (size_t i = 0; i < options.size(); ++i) {
+ if (options[i] == startSystemServer) {
+ /* track our progress through the boot sequence */
+ const int LOG_BOOT_PROGRESS_START = 3000;
+ LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START, ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
+ }
}
const char* rootDir = getenv("ANDROID_ROOT");
@@ -927,17 +931,20 @@ void AndroidRuntime::start(const char* className, const char* options)
jclass stringClass;
jobjectArray strArray;
jstring classNameStr;
- jstring optionsStr;
stringClass = env->FindClass("java/lang/String");
assert(stringClass != NULL);
- strArray = env->NewObjectArray(2, stringClass, NULL);
+ strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);
assert(strArray != NULL);
classNameStr = env->NewStringUTF(className);
assert(classNameStr != NULL);
env->SetObjectArrayElement(strArray, 0, classNameStr);
- optionsStr = env->NewStringUTF(options);
- env->SetObjectArrayElement(strArray, 1, optionsStr);
+
+ for (size_t i = 0; i < options.size(); ++i) {
+ jstring optionsStr = env->NewStringUTF(options.itemAt(i).string());
+ assert(optionsStr != NULL);
+ env->SetObjectArrayElement(strArray, i + 1, optionsStr);
+ }
/*
* Start VM. This thread becomes the main thread of the VM, and will
diff --git a/include/android_runtime/AndroidRuntime.h b/include/android_runtime/AndroidRuntime.h
index 6f2af90..3dfdb46 100644
--- a/include/android_runtime/AndroidRuntime.h
+++ b/include/android_runtime/AndroidRuntime.h
@@ -55,8 +55,7 @@ public:
/**
* Call a class's static main method with the given arguments,
*/
- status_t callMain(const char* className, jclass clazz, int argc,
- const char* const argv[]);
+ status_t callMain(const String8& className, jclass clazz, const Vector<String8>& args);
/**
* Find a class, with the input either of the form
@@ -66,7 +65,7 @@ public:
int addVmArguments(int argc, const char* const argv[]);
- void start(const char *classname, const char* options);
+ void start(const char *classname, const Vector<String8>& options);
void exit(int code);