app_main.cpp revision 10e89712863f5b91a2982dc1783fbdfe39c1485d
1/* 2 * Main entry of app process. 3 * 4 * Starts the interpreted runtime, then starts up the application. 5 * 6 */ 7 8#define LOG_TAG "appproc" 9 10#include <binder/IPCThreadState.h> 11#include <binder/ProcessState.h> 12#include <utils/Log.h> 13#include <cutils/process_name.h> 14#include <cutils/memory.h> 15#include <android_runtime/AndroidRuntime.h> 16 17#include <stdio.h> 18#include <unistd.h> 19 20namespace android { 21 22void app_usage() 23{ 24 fprintf(stderr, 25 "Usage: app_process [java-options] cmd-dir start-class-name [options]\n"); 26} 27 28class AppRuntime : public AndroidRuntime 29{ 30public: 31 AppRuntime() 32 : mParentDir(NULL) 33 , mClassName(NULL) 34 , mClass(NULL) 35 , mArgC(0) 36 , mArgV(NULL) 37 { 38 } 39 40#if 0 41 // this appears to be unused 42 const char* getParentDir() const 43 { 44 return mParentDir; 45 } 46#endif 47 48 const char* getClassName() const 49 { 50 return mClassName; 51 } 52 53 virtual void onVmCreated(JNIEnv* env) 54 { 55 if (mClassName == NULL) { 56 return; // Zygote. Nothing to do here. 57 } 58 59 /* 60 * This is a little awkward because the JNI FindClass call uses the 61 * class loader associated with the native method we're executing in. 62 * If called in onStarted (from RuntimeInit.finishInit because we're 63 * launching "am", for example), FindClass would see that we're calling 64 * from a boot class' native method, and so wouldn't look for the class 65 * we're trying to look up in CLASSPATH. Unfortunately it needs to, 66 * because the "am" classes are not boot classes. 67 * 68 * The easiest fix is to call FindClass here, early on before we start 69 * executing boot class Java code and thereby deny ourselves access to 70 * non-boot classes. 71 */ 72 char* slashClassName = toSlashClassName(mClassName); 73 mClass = env->FindClass(slashClassName); 74 if (mClass == NULL) { 75 LOGE("ERROR: could not find class '%s'\n", mClassName); 76 } 77 free(slashClassName); 78 79 mClass = reinterpret_cast<jclass>(env->NewGlobalRef(mClass)); 80 } 81 82 virtual void onStarted() 83 { 84 sp<ProcessState> proc = ProcessState::self(); 85 LOGV("App process: starting thread pool.\n"); 86 proc->startThreadPool(); 87 88 AndroidRuntime* ar = AndroidRuntime::getRuntime(); 89 ar->callMain(mClassName, mClass, mArgC, mArgV); 90 91 IPCThreadState::self()->stopProcess(); 92 } 93 94 virtual void onZygoteInit() 95 { 96 sp<ProcessState> proc = ProcessState::self(); 97 LOGV("App process: starting thread pool.\n"); 98 proc->startThreadPool(); 99 } 100 101 virtual void onExit(int code) 102 { 103 if (mClassName == NULL) { 104 // if zygote 105 IPCThreadState::self()->stopProcess(); 106 } 107 108 AndroidRuntime::onExit(code); 109 } 110 111 112 const char* mParentDir; 113 const char* mClassName; 114 jclass mClass; 115 int mArgC; 116 const char* const* mArgV; 117}; 118 119} 120 121using namespace android; 122 123/* 124 * sets argv0 to as much of newArgv0 as will fit 125 */ 126static void setArgv0(const char *argv0, const char *newArgv0) 127{ 128 strlcpy(const_cast<char *>(argv0), newArgv0, strlen(argv0)); 129} 130 131int main(int argc, const char* const argv[]) 132{ 133 // These are global variables in ProcessState.cpp 134 mArgC = argc; 135 mArgV = argv; 136 137 mArgLen = 0; 138 for (int i=0; i<argc; i++) { 139 mArgLen += strlen(argv[i]) + 1; 140 } 141 mArgLen--; 142 143 AppRuntime runtime; 144 const char* argv0 = argv[0]; 145 146 // Process command line arguments 147 // ignore argv[0] 148 argc--; 149 argv++; 150 151 // Everything up to '--' or first non '-' arg goes to the vm 152 153 int i = runtime.addVmArguments(argc, argv); 154 155 // Parse runtime arguments. Stop at first unrecognized option. 156 bool zygote = false; 157 bool startSystemServer = false; 158 bool application = false; 159 const char* parentDir = NULL; 160 const char* niceName = NULL; 161 const char* className = NULL; 162 while (i < argc) { 163 const char* arg = argv[i++]; 164 if (!parentDir) { 165 parentDir = arg; 166 } else if (strcmp(arg, "--zygote") == 0) { 167 zygote = true; 168 niceName = "zygote"; 169 } else if (strcmp(arg, "--start-system-server") == 0) { 170 startSystemServer = true; 171 } else if (strcmp(arg, "--application") == 0) { 172 application = true; 173 } else if (strncmp(arg, "--nice-name=", 12) == 0) { 174 niceName = arg + 12; 175 } else { 176 className = arg; 177 break; 178 } 179 } 180 181 if (niceName && *niceName) { 182 setArgv0(argv0, niceName); 183 set_process_name(niceName); 184 } 185 186 runtime.mParentDir = parentDir; 187 188 if (zygote) { 189 runtime.start("com.android.internal.os.ZygoteInit", 190 startSystemServer ? "start-system-server" : ""); 191 } else if (className) { 192 // Remainder of args get passed to startup class main() 193 runtime.mClassName = className; 194 runtime.mArgC = argc - i; 195 runtime.mArgV = argv + i; 196 runtime.start("com.android.internal.os.RuntimeInit", 197 application ? "application" : "tool"); 198 } else { 199 fprintf(stderr, "Error: no class name or --zygote supplied.\n"); 200 app_usage(); 201 LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied."); 202 return 10; 203 } 204} 205