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