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