Merge "Clean up argc / argv processing for runtime args."

This commit is contained in:
Narayan Kamath
2014-04-09 13:55:54 +00:00
committed by Gerrit Code Review
3 changed files with 85 additions and 60 deletions

View File

@ -32,30 +32,20 @@ class AppRuntime : public AndroidRuntime
public: public:
AppRuntime(char* argBlockStart, const size_t argBlockLength) AppRuntime(char* argBlockStart, const size_t argBlockLength)
: AndroidRuntime(argBlockStart, argBlockLength) : AndroidRuntime(argBlockStart, argBlockLength)
, mParentDir(NULL)
, mClassName(NULL)
, mClass(NULL) , mClass(NULL)
, mArgC(0)
, mArgV(NULL)
{ {
} }
#if 0 void setClassNameAndArgs(const String8& className, int argc, char * const *argv) {
// this appears to be unused mClassName = className;
const char* getParentDir() const for (int i = 0; i < argc; ++i) {
{ mArgs.add(String8(argv[i]));
return mParentDir;
} }
#endif
const char* getClassName() const
{
return mClassName;
} }
virtual void onVmCreated(JNIEnv* env) virtual void onVmCreated(JNIEnv* env)
{ {
if (mClassName == NULL) { if (mClassName.isEmpty()) {
return; // Zygote. Nothing to do here. return; // Zygote. Nothing to do here.
} }
@ -72,10 +62,10 @@ public:
* executing boot class Java code and thereby deny ourselves access to * executing boot class Java code and thereby deny ourselves access to
* non-boot classes. * non-boot classes.
*/ */
char* slashClassName = toSlashClassName(mClassName); char* slashClassName = toSlashClassName(mClassName.string());
mClass = env->FindClass(slashClassName); mClass = env->FindClass(slashClassName);
if (mClass == NULL) { if (mClass == NULL) {
ALOGE("ERROR: could not find class '%s'\n", mClassName); ALOGE("ERROR: could not find class '%s'\n", mClassName.string());
} }
free(slashClassName); free(slashClassName);
@ -89,7 +79,7 @@ public:
proc->startThreadPool(); proc->startThreadPool();
AndroidRuntime* ar = AndroidRuntime::getRuntime(); AndroidRuntime* ar = AndroidRuntime::getRuntime();
ar->callMain(mClassName, mClass, mArgC, mArgV); ar->callMain(mClassName, mClass, mArgs);
IPCThreadState::self()->stopProcess(); IPCThreadState::self()->stopProcess();
} }
@ -115,11 +105,9 @@ public:
} }
const char* mParentDir; String8 mClassName;
const char* mClassName; Vector<String8> mArgs;
jclass mClass; jclass mClass;
int mArgC;
const char* const* mArgV;
}; };
} }
@ -155,7 +143,26 @@ int main(int argc, char* const argv[])
argc--; argc--;
argv++; 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); int i = runtime.addVmArguments(argc, argv);
@ -163,14 +170,13 @@ int main(int argc, char* const argv[])
bool zygote = false; bool zygote = false;
bool startSystemServer = false; bool startSystemServer = false;
bool application = false; bool application = false;
const char* parentDir = NULL;
const char* niceName = NULL; const char* niceName = NULL;
const char* className = NULL; String8 className;
++i; // Skip unused "parent dir" argument.
while (i < argc) { while (i < argc) {
const char* arg = argv[i++]; const char* arg = argv[i++];
if (!parentDir) { if (strcmp(arg, "--zygote") == 0) {
parentDir = arg;
} else if (strcmp(arg, "--zygote") == 0) {
zygote = true; zygote = true;
niceName = "zygote"; niceName = "zygote";
} else if (strcmp(arg, "--start-system-server") == 0) { } 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) { } else if (strncmp(arg, "--nice-name=", 12) == 0) {
niceName = arg + 12; niceName = arg + 12;
} else { } else {
className = arg; className.setTo(arg);
break; 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) { if (niceName && *niceName) {
runtime.setArgv0(niceName); runtime.setArgv0(niceName);
set_process_name(niceName); set_process_name(niceName);
} }
runtime.mParentDir = parentDir;
if (zygote) { if (zygote) {
runtime.start("com.android.internal.os.ZygoteInit", runtime.start("com.android.internal.os.ZygoteInit", args);
startSystemServer ? "start-system-server" : "");
} else if (className) { } else if (className) {
// Remainder of args get passed to startup class main() runtime.start("com.android.internal.os.RuntimeInit", args);
runtime.mClassName = className;
runtime.mArgC = argc - i;
runtime.mArgV = argv + i;
runtime.start("com.android.internal.os.RuntimeInit",
application ? "application" : "tool");
} else { } else {
fprintf(stderr, "Error: no class name or --zygote supplied.\n"); fprintf(stderr, "Error: no class name or --zygote supplied.\n");
app_usage(); app_usage();

View File

@ -270,13 +270,13 @@ void AndroidRuntime::setArgv0(const char* argv0) {
strlcpy(mArgBlockStart, argv0, mArgBlockLength); strlcpy(mArgBlockStart, argv0, mArgBlockLength);
} }
status_t AndroidRuntime::callMain(const char* className, status_t AndroidRuntime::callMain(const String8& className, jclass clazz,
jclass clazz, int argc, const char* const argv[]) const Vector<String8>& args)
{ {
JNIEnv* env; JNIEnv* env;
jmethodID methodId; jmethodID methodId;
ALOGD("Calling main entry %s", className); ALOGD("Calling main entry %s", className.string());
env = getJNIEnv(); env = getJNIEnv();
if (clazz == NULL || env == NULL) { if (clazz == NULL || env == NULL) {
@ -285,7 +285,7 @@ status_t AndroidRuntime::callMain(const char* className,
methodId = env->GetStaticMethodID(clazz, "main", "([Ljava/lang/String;)V"); methodId = env->GetStaticMethodID(clazz, "main", "([Ljava/lang/String;)V");
if (methodId == NULL) { 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; return UNKNOWN_ERROR;
} }
@ -296,11 +296,12 @@ status_t AndroidRuntime::callMain(const char* className,
jclass stringClass; jclass stringClass;
jobjectArray strArray; jobjectArray strArray;
const size_t numArgs = args.size();
stringClass = env->FindClass("java/lang/String"); 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++) { for (size_t i = 0; i < numArgs; i++) {
jstring argStr = env->NewStringUTF(argv[i]); jstring argStr = env->NewStringUTF(args[i].string());
env->SetObjectArrayElement(strArray, i, argStr); env->SetObjectArrayElement(strArray, i, argStr);
} }
@ -872,20 +873,23 @@ char* AndroidRuntime::toSlashClassName(const char* className)
* Passes the main function two arguments, the class name and the specified * Passes the main function two arguments, the class name and the specified
* options string. * 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", ALOGD("\n>>>>>> AndroidRuntime START %s <<<<<<\n",
className != NULL ? className : "(unknown)"); className != NULL ? className : "(unknown)");
static const String8 startSystemServer("start-system-server");
/* /*
* 'startSystemServer == true' means runtime is obsolete and not run from * 'startSystemServer == true' means runtime is obsolete and not run from
* init.rc anymore, so we print out the boot start event here. * init.rc anymore, so we print out the boot start event here.
*/ */
if (strcmp(options, "start-system-server") == 0) { for (size_t i = 0; i < options.size(); ++i) {
if (options[i] == startSystemServer) {
/* track our progress through the boot sequence */ /* track our progress through the boot sequence */
const int LOG_BOOT_PROGRESS_START = 3000; const int LOG_BOOT_PROGRESS_START = 3000;
LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START, LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START, ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
ns2ms(systemTime(SYSTEM_TIME_MONOTONIC))); }
} }
const char* rootDir = getenv("ANDROID_ROOT"); const char* rootDir = getenv("ANDROID_ROOT");
@ -926,17 +930,20 @@ void AndroidRuntime::start(const char* className, const char* options)
jclass stringClass; jclass stringClass;
jobjectArray strArray; jobjectArray strArray;
jstring classNameStr; jstring classNameStr;
jstring optionsStr;
stringClass = env->FindClass("java/lang/String"); stringClass = env->FindClass("java/lang/String");
assert(stringClass != NULL); assert(stringClass != NULL);
strArray = env->NewObjectArray(2, stringClass, NULL); strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);
assert(strArray != NULL); assert(strArray != NULL);
classNameStr = env->NewStringUTF(className); classNameStr = env->NewStringUTF(className);
assert(classNameStr != NULL); assert(classNameStr != NULL);
env->SetObjectArrayElement(strArray, 0, classNameStr); 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 * Start VM. This thread becomes the main thread of the VM, and will

View File

@ -55,8 +55,7 @@ public:
/** /**
* Call a class's static main method with the given arguments, * Call a class's static main method with the given arguments,
*/ */
status_t callMain(const char* className, jclass clazz, int argc, status_t callMain(const String8& className, jclass clazz, const Vector<String8>& args);
const char* const argv[]);
/** /**
* Find a class, with the input either of the form * Find a class, with the input either of the form
@ -66,7 +65,7 @@ public:
int addVmArguments(int argc, const char* const argv[]); 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); void exit(int code);