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