Skip to content
This repository has been archived by the owner on Nov 8, 2023. It is now read-only.

Commit

Permalink
Clean up argc / argv processing for runtime args.
Browse files Browse the repository at this point in the history
- Make copies of argc, argv before argv is potentially
  overwritten with the process name.
- Allow multiple command line arguments to be passed to
  ZygoteInit (this is required for some of the 64 bit
  zygote work).
- Add an explanatory comment about how these argments
  are processed.

Change-Id: I752be69c5c0f97ed17d1a3dded19f46ee00929b0
  • Loading branch information
narayank committed Apr 9, 2014
1 parent a5608ac commit 22ec1ee
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 60 deletions.
99 changes: 59 additions & 40 deletions cmds/app_process/app_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
}

Expand All @@ -72,10 +62,10 @@ class AppRuntime : public AndroidRuntime
* 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);

Expand All @@ -89,7 +79,7 @@ class AppRuntime : public AndroidRuntime
proc->startThreadPool();

AndroidRuntime* ar = AndroidRuntime::getRuntime();
ar->callMain(mClassName, mClass, mArgC, mArgV);
ar->callMain(mClassName, mClass, mArgs);

IPCThreadState::self()->stopProcess();
}
Expand All @@ -115,11 +105,9 @@ class AppRuntime : public AndroidRuntime
}


const char* mParentDir;
const char* mClassName;
String8 mClassName;
Vector<String8> mArgs;
jclass mClass;
int mArgC;
const char* const* mArgV;
};

}
Expand Down Expand Up @@ -155,22 +143,40 @@ 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);

// 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;
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) {
Expand All @@ -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();
Expand Down
41 changes: 24 additions & 17 deletions core/jni/AndroidRuntime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -270,13 +270,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) {
Expand All @@ -285,7 +285,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;
}

Expand All @@ -296,11 +296,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);
}

Expand Down Expand Up @@ -872,20 +873,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");
Expand Down Expand Up @@ -926,17 +930,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
Expand Down
5 changes: 2 additions & 3 deletions include/android_runtime/AndroidRuntime.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,7 @@ class AndroidRuntime
/**
* 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
Expand All @@ -66,7 +65,7 @@ class AndroidRuntime

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);

Expand Down

0 comments on commit 22ec1ee

Please sign in to comment.