app_main.cpp revision d195e5ab401432ddac659791640a2927fc668699
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 if (proc->supportsProcesses()) { 86 LOGV("App process: starting thread pool.\n"); 87 proc->startThreadPool(); 88 } 89 90 AndroidRuntime* ar = AndroidRuntime::getRuntime(); 91 ar->callMain(mClassName, mClass, mArgC, mArgV); 92 93 if (ProcessState::self()->supportsProcesses()) { 94 IPCThreadState::self()->stopProcess(); 95 } 96 } 97 98 virtual void onZygoteInit() 99 { 100 sp<ProcessState> proc = ProcessState::self(); 101 if (proc->supportsProcesses()) { 102 LOGV("App process: starting thread pool.\n"); 103 proc->startThreadPool(); 104 } 105 } 106 107 virtual void onExit(int code) 108 { 109 if (mClassName == NULL) { 110 // if zygote 111 if (ProcessState::self()->supportsProcesses()) { 112 IPCThreadState::self()->stopProcess(); 113 } 114 } 115 116 AndroidRuntime::onExit(code); 117 } 118 119 120 const char* mParentDir; 121 const char* mClassName; 122 jclass mClass; 123 int mArgC; 124 const char* const* mArgV; 125}; 126 127} 128 129using namespace android; 130 131/* 132 * sets argv0 to as much of newArgv0 as will fit 133 */ 134static void setArgv0(const char *argv0, const char *newArgv0) 135{ 136 strlcpy(const_cast<char *>(argv0), newArgv0, strlen(argv0)); 137} 138 139int main(int argc, const char* const argv[]) 140{ 141 // These are global variables in ProcessState.cpp 142 mArgC = argc; 143 mArgV = argv; 144 145 mArgLen = 0; 146 for (int i=0; i<argc; i++) { 147 mArgLen += strlen(argv[i]) + 1; 148 } 149 mArgLen--; 150 151 AppRuntime runtime; 152 const char *arg; 153 const char *argv0; 154 155 argv0 = argv[0]; 156 157 // Process command line arguments 158 // ignore argv[0] 159 argc--; 160 argv++; 161 162 // Everything up to '--' or first non '-' arg goes to the vm 163 164 int i = runtime.addVmArguments(argc, argv); 165 166 // Next arg is parent directory 167 if (i < argc) { 168 runtime.mParentDir = argv[i++]; 169 } 170 171 // Next arg is startup classname or "--zygote" 172 if (i < argc) { 173 arg = argv[i++]; 174 if (0 == strcmp("--zygote", arg)) { 175 bool startSystemServer = (i < argc) ? 176 strcmp(argv[i], "--start-system-server") == 0 : false; 177 setArgv0(argv0, "zygote"); 178 set_process_name("zygote"); 179 runtime.start("com.android.internal.os.ZygoteInit", 180 startSystemServer); 181 } else { 182 set_process_name(argv0); 183 184 runtime.mClassName = arg; 185 186 // Remainder of args get passed to startup class main() 187 runtime.mArgC = argc-i; 188 runtime.mArgV = argv+i; 189 190 LOGV("App process is starting with pid=%d, class=%s.\n", 191 getpid(), runtime.getClassName()); 192 runtime.start(); 193 } 194 } else { 195 fprintf(stderr, "Error: no class name or --zygote supplied.\n"); 196 app_usage(); 197 LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied."); 198 return 10; 199 } 200 201} 202