app_main.cpp revision 1fe21bd1b6ca8b94c78fbf3666a1e8e0472355de
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 <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 sp<ProcessState> proc = ProcessState::self(); 99 ALOGV("App process: starting thread pool.\n"); 100 proc->startThreadPool(); 101 } 102 103 virtual void onExit(int code) 104 { 105 if (mClassName == NULL) { 106 // if zygote 107 IPCThreadState::self()->stopProcess(); 108 } 109 110 AndroidRuntime::onExit(code); 111 } 112 113 114 const char* mParentDir; 115 const char* mClassName; 116 jclass mClass; 117 int mArgC; 118 const char* const* mArgV; 119}; 120 121} 122 123using namespace android; 124 125/* 126 * sets argv0 to as much of newArgv0 as will fit 127 */ 128static void setArgv0(const char *argv0, const char *newArgv0) 129{ 130 strlcpy(const_cast<char *>(argv0), newArgv0, strlen(argv0)); 131} 132 133int main(int argc, char* const argv[]) 134{ 135#ifdef __arm__ 136 /* 137 * b/7188322 - Temporarily revert to the compat memory layout 138 * to avoid breaking third party apps. 139 * 140 * THIS WILL GO AWAY IN A FUTURE ANDROID RELEASE. 141 * 142 * http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=7dbaa466 143 * changes the kernel mapping from bottom up to top-down. 144 * This breaks some programs which improperly embed 145 * an out of date copy of Android's linker. 146 */ 147 if (getenv("NO_ADDR_COMPAT_LAYOUT_FIXUP") == NULL) { 148 int current = personality(0xFFFFFFFF); 149 if ((current & ADDR_COMPAT_LAYOUT) == 0) { 150 personality(current | ADDR_COMPAT_LAYOUT); 151 setenv("NO_ADDR_COMPAT_LAYOUT_FIXUP", "1", 1); 152 execv("/system/bin/app_process", argv); 153 return -1; 154 } 155 } 156#endif 157 158 // These are global variables in ProcessState.cpp 159 mArgC = argc; 160 mArgV = argv; 161 162 mArgLen = 0; 163 for (int i=0; i<argc; i++) { 164 mArgLen += strlen(argv[i]) + 1; 165 } 166 mArgLen--; 167 168 AppRuntime runtime; 169 const char* argv0 = argv[0]; 170 171 // Process command line arguments 172 // ignore argv[0] 173 argc--; 174 argv++; 175 176 // Everything up to '--' or first non '-' arg goes to the vm 177 178 int i = runtime.addVmArguments(argc, argv); 179 180 // Parse runtime arguments. Stop at first unrecognized option. 181 bool zygote = false; 182 bool startSystemServer = false; 183 bool application = false; 184 const char* parentDir = NULL; 185 const char* niceName = NULL; 186 const char* className = NULL; 187 while (i < argc) { 188 const char* arg = argv[i++]; 189 if (!parentDir) { 190 parentDir = arg; 191 } else if (strcmp(arg, "--zygote") == 0) { 192 zygote = true; 193 niceName = "zygote"; 194 } else if (strcmp(arg, "--start-system-server") == 0) { 195 startSystemServer = true; 196 } else if (strcmp(arg, "--application") == 0) { 197 application = true; 198 } else if (strncmp(arg, "--nice-name=", 12) == 0) { 199 niceName = arg + 12; 200 } else { 201 className = arg; 202 break; 203 } 204 } 205 206 if (niceName && *niceName) { 207 setArgv0(argv0, niceName); 208 set_process_name(niceName); 209 } 210 211 runtime.mParentDir = parentDir; 212 213 if (zygote) { 214 runtime.start("com.android.internal.os.ZygoteInit", 215 startSystemServer ? "start-system-server" : ""); 216 } else if (className) { 217 // Remainder of args get passed to startup class main() 218 runtime.mClassName = className; 219 runtime.mArgC = argc - i; 220 runtime.mArgV = argv + i; 221 runtime.start("com.android.internal.os.RuntimeInit", 222 application ? "application" : "tool"); 223 } else { 224 fprintf(stderr, "Error: no class name or --zygote supplied.\n"); 225 app_usage(); 226 LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied."); 227 return 10; 228 } 229} 230