19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Main entry of app process. 3d195e5ab401432ddac659791640a2927fc668699Elliott Hughes * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Starts the interpreted runtime, then starts up the application. 5d195e5ab401432ddac659791640a2927fc668699Elliott Hughes * 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define LOG_TAG "appproc" 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10fc737fb76cc889d0c19bd8bf74d2b5f1fc4fbe6eMark Salyzyn#include <stdio.h> 11fc737fb76cc889d0c19bd8bf74d2b5f1fc4fbe6eMark Salyzyn#include <stdlib.h> 12fc737fb76cc889d0c19bd8bf74d2b5f1fc4fbe6eMark Salyzyn#include <sys/prctl.h> 13fc737fb76cc889d0c19bd8bf74d2b5f1fc4fbe6eMark Salyzyn#include <sys/stat.h> 14fc737fb76cc889d0c19bd8bf74d2b5f1fc4fbe6eMark Salyzyn#include <unistd.h> 15fc737fb76cc889d0c19bd8bf74d2b5f1fc4fbe6eMark Salyzyn 160795272aa226f4e965968a03daddc53ce30b7cdaMathias Agopian#include <binder/IPCThreadState.h> 17b69ffdb2078e2272fa5637a8c8f2b58020946e20Martijn Coenen#include <hwbinder/IPCThreadState.h> 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/Log.h> 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <cutils/memory.h> 20c41638cb759ce569630ffae4c5c4cdee1b0f3b82Narayan Kamath#include <cutils/properties.h> 216ad0452e6301c0650f58f3991f7c523f6f279ddbJamie Gennis#include <cutils/trace.h> 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <android_runtime/AndroidRuntime.h> 23d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath#include <private/android_filesystem_config.h> // for AID_SYSTEM 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectnamespace android { 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 27cfedceb8c180a2e176154d461659e0c3569dc931Andreas Gampestatic void app_usage() 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fprintf(stderr, 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Usage: app_process [java-options] cmd-dir start-class-name [options]\n"); 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectclass AppRuntime : public AndroidRuntime 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic: 36a23fcd7be8e40078a913b1a99222cdd89229e67bNarayan Kamath AppRuntime(char* argBlockStart, const size_t argBlockLength) 37a23fcd7be8e40078a913b1a99222cdd89229e67bNarayan Kamath : AndroidRuntime(argBlockStart, argBlockLength) 38d195e5ab401432ddac659791640a2927fc668699Elliott Hughes , mClass(NULL) 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4222ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath void setClassNameAndArgs(const String8& className, int argc, char * const *argv) { 4322ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath mClassName = className; 4422ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath for (int i = 0; i < argc; ++i) { 4522ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath mArgs.add(String8(argv[i])); 4622ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath } 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 49d195e5ab401432ddac659791640a2927fc668699Elliott Hughes virtual void onVmCreated(JNIEnv* env) 50d195e5ab401432ddac659791640a2927fc668699Elliott Hughes { 5122ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath if (mClassName.isEmpty()) { 52d195e5ab401432ddac659791640a2927fc668699Elliott Hughes return; // Zygote. Nothing to do here. 53d195e5ab401432ddac659791640a2927fc668699Elliott Hughes } 54d195e5ab401432ddac659791640a2927fc668699Elliott Hughes 55d195e5ab401432ddac659791640a2927fc668699Elliott Hughes /* 56d195e5ab401432ddac659791640a2927fc668699Elliott Hughes * This is a little awkward because the JNI FindClass call uses the 57d195e5ab401432ddac659791640a2927fc668699Elliott Hughes * class loader associated with the native method we're executing in. 58d195e5ab401432ddac659791640a2927fc668699Elliott Hughes * If called in onStarted (from RuntimeInit.finishInit because we're 59d195e5ab401432ddac659791640a2927fc668699Elliott Hughes * launching "am", for example), FindClass would see that we're calling 60d195e5ab401432ddac659791640a2927fc668699Elliott Hughes * from a boot class' native method, and so wouldn't look for the class 61d195e5ab401432ddac659791640a2927fc668699Elliott Hughes * we're trying to look up in CLASSPATH. Unfortunately it needs to, 62d195e5ab401432ddac659791640a2927fc668699Elliott Hughes * because the "am" classes are not boot classes. 63d195e5ab401432ddac659791640a2927fc668699Elliott Hughes * 64d195e5ab401432ddac659791640a2927fc668699Elliott Hughes * The easiest fix is to call FindClass here, early on before we start 65d195e5ab401432ddac659791640a2927fc668699Elliott Hughes * executing boot class Java code and thereby deny ourselves access to 66d195e5ab401432ddac659791640a2927fc668699Elliott Hughes * non-boot classes. 67d195e5ab401432ddac659791640a2927fc668699Elliott Hughes */ 6822ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath char* slashClassName = toSlashClassName(mClassName.string()); 69d195e5ab401432ddac659791640a2927fc668699Elliott Hughes mClass = env->FindClass(slashClassName); 70d195e5ab401432ddac659791640a2927fc668699Elliott Hughes if (mClass == NULL) { 7122ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath ALOGE("ERROR: could not find class '%s'\n", mClassName.string()); 72d195e5ab401432ddac659791640a2927fc668699Elliott Hughes } 73d195e5ab401432ddac659791640a2927fc668699Elliott Hughes free(slashClassName); 74d195e5ab401432ddac659791640a2927fc668699Elliott Hughes 75d195e5ab401432ddac659791640a2927fc668699Elliott Hughes mClass = reinterpret_cast<jclass>(env->NewGlobalRef(mClass)); 76d195e5ab401432ddac659791640a2927fc668699Elliott Hughes } 77d195e5ab401432ddac659791640a2927fc668699Elliott Hughes 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project virtual void onStarted() 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sp<ProcessState> proc = ProcessState::self(); 8171f2cf116aab893e224056c38ab146bd1538dd3eSteve Block ALOGV("App process: starting thread pool.\n"); 8210e89712863f5b91a2982dc1783fbdfe39c1485dJeff Brown proc->startThreadPool(); 83d195e5ab401432ddac659791640a2927fc668699Elliott Hughes 84d195e5ab401432ddac659791640a2927fc668699Elliott Hughes AndroidRuntime* ar = AndroidRuntime::getRuntime(); 8522ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath ar->callMain(mClassName, mClass, mArgs); 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8710e89712863f5b91a2982dc1783fbdfe39c1485dJeff Brown IPCThreadState::self()->stopProcess(); 88b69ffdb2078e2272fa5637a8c8f2b58020946e20Martijn Coenen hardware::IPCThreadState::self()->stopProcess(); 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project virtual void onZygoteInit() 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sp<ProcessState> proc = ProcessState::self(); 9471f2cf116aab893e224056c38ab146bd1538dd3eSteve Block ALOGV("App process: starting thread pool.\n"); 9510e89712863f5b91a2982dc1783fbdfe39c1485dJeff Brown proc->startThreadPool(); 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project virtual void onExit(int code) 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 10090c75cf02e8e36be8679273f4ea15fd145001033Narayan Kamath if (mClassName.isEmpty()) { 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // if zygote 10210e89712863f5b91a2982dc1783fbdfe39c1485dJeff Brown IPCThreadState::self()->stopProcess(); 103b69ffdb2078e2272fa5637a8c8f2b58020946e20Martijn Coenen hardware::IPCThreadState::self()->stopProcess(); 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project AndroidRuntime::onExit(code); 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 109d195e5ab401432ddac659791640a2927fc668699Elliott Hughes 11022ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath String8 mClassName; 11122ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath Vector<String8> mArgs; 112d195e5ab401432ddac659791640a2927fc668699Elliott Hughes jclass mClass; 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectusing namespace android; 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 119a23fcd7be8e40078a913b1a99222cdd89229e67bNarayan Kamathstatic size_t computeArgBlockSize(int argc, char* const argv[]) { 120a23fcd7be8e40078a913b1a99222cdd89229e67bNarayan Kamath // TODO: This assumes that all arguments are allocated in 121a23fcd7be8e40078a913b1a99222cdd89229e67bNarayan Kamath // contiguous memory. There isn't any documented guarantee 122a23fcd7be8e40078a913b1a99222cdd89229e67bNarayan Kamath // that this is the case, but this is how the kernel does it 123a23fcd7be8e40078a913b1a99222cdd89229e67bNarayan Kamath // (see fs/exec.c). 124a23fcd7be8e40078a913b1a99222cdd89229e67bNarayan Kamath // 125a23fcd7be8e40078a913b1a99222cdd89229e67bNarayan Kamath // Also note that this is a constant for "normal" android apps. 126a23fcd7be8e40078a913b1a99222cdd89229e67bNarayan Kamath // Since they're forked from zygote, the size of their command line 127a23fcd7be8e40078a913b1a99222cdd89229e67bNarayan Kamath // is the size of the zygote command line. 128a23fcd7be8e40078a913b1a99222cdd89229e67bNarayan Kamath // 129a23fcd7be8e40078a913b1a99222cdd89229e67bNarayan Kamath // We change the process name of the process by over-writing 130a23fcd7be8e40078a913b1a99222cdd89229e67bNarayan Kamath // the start of the argument block (argv[0]) with the new name of 131a23fcd7be8e40078a913b1a99222cdd89229e67bNarayan Kamath // the process, so we'd mysteriously start getting truncated process 132a23fcd7be8e40078a913b1a99222cdd89229e67bNarayan Kamath // names if the zygote command line decreases in size. 133a23fcd7be8e40078a913b1a99222cdd89229e67bNarayan Kamath uintptr_t start = reinterpret_cast<uintptr_t>(argv[0]); 134a23fcd7be8e40078a913b1a99222cdd89229e67bNarayan Kamath uintptr_t end = reinterpret_cast<uintptr_t>(argv[argc - 1]); 13500c0cd4a24bd0f040055f9e786e2df1fa3b7d2d3Jeff Brown end += strlen(argv[argc - 1]) + 1; 136a23fcd7be8e40078a913b1a99222cdd89229e67bNarayan Kamath return (end - start); 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 139d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamathstatic void maybeCreateDalvikCache() { 140d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath#if defined(__aarch64__) 141d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath static const char kInstructionSet[] = "arm64"; 142d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath#elif defined(__x86_64__) 143d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath static const char kInstructionSet[] = "x86_64"; 144d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath#elif defined(__arm__) 145d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath static const char kInstructionSet[] = "arm"; 1466eb1b2611cd2db7f2c2063f8be219d4ef19d11d0Narayan Kamath#elif defined(__i386__) 147d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath static const char kInstructionSet[] = "x86"; 1487e7c6031821e2aa55c756a9c85f97a22f4875552Douglas Leung#elif defined (__mips__) && !defined(__LP64__) 149d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath static const char kInstructionSet[] = "mips"; 1507e7c6031821e2aa55c756a9c85f97a22f4875552Douglas Leung#elif defined (__mips__) && defined(__LP64__) 1517e7c6031821e2aa55c756a9c85f97a22f4875552Douglas Leung static const char kInstructionSet[] = "mips64"; 152d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath#else 153d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath#error "Unknown instruction set" 154d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath#endif 155d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath const char* androidRoot = getenv("ANDROID_DATA"); 156d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath LOG_ALWAYS_FATAL_IF(androidRoot == NULL, "ANDROID_DATA environment variable unset"); 157d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath 158d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath char dalvikCacheDir[PATH_MAX]; 159d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath const int numChars = snprintf(dalvikCacheDir, PATH_MAX, 160d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath "%s/dalvik-cache/%s", androidRoot, kInstructionSet); 161d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath LOG_ALWAYS_FATAL_IF((numChars >= PATH_MAX || numChars < 0), 162d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath "Error constructing dalvik cache : %s", strerror(errno)); 163d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath 16455471dcd0f843e79d8665c63165720eca6a9c980Alex Light int result = mkdir(dalvikCacheDir, 0711); 165d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath LOG_ALWAYS_FATAL_IF((result < 0 && errno != EEXIST), 166d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath "Error creating cache dir %s : %s", dalvikCacheDir, strerror(errno)); 167d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath 168d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath // We always perform these steps because the directory might 169d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath // already exist, with wider permissions and a different owner 170d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath // than we'd like. 17155471dcd0f843e79d8665c63165720eca6a9c980Alex Light result = chown(dalvikCacheDir, AID_ROOT, AID_ROOT); 172d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath LOG_ALWAYS_FATAL_IF((result < 0), "Error changing dalvik-cache ownership : %s", strerror(errno)); 173d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath 17455471dcd0f843e79d8665c63165720eca6a9c980Alex Light result = chmod(dalvikCacheDir, 0711); 175d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath LOG_ALWAYS_FATAL_IF((result < 0), 176d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath "Error changing dalvik-cache permissions : %s", strerror(errno)); 177d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath} 178d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath 179c41638cb759ce569630ffae4c5c4cdee1b0f3b82Narayan Kamath#if defined(__LP64__) 180c41638cb759ce569630ffae4c5c4cdee1b0f3b82Narayan Kamathstatic const char ABI_LIST_PROPERTY[] = "ro.product.cpu.abilist64"; 181d35d3e5d391b8daf20f9af2c5f01d5ff1985c1eeNarayan Kamathstatic const char ZYGOTE_NICE_NAME[] = "zygote64"; 182c41638cb759ce569630ffae4c5c4cdee1b0f3b82Narayan Kamath#else 183c41638cb759ce569630ffae4c5c4cdee1b0f3b82Narayan Kamathstatic const char ABI_LIST_PROPERTY[] = "ro.product.cpu.abilist32"; 184d35d3e5d391b8daf20f9af2c5f01d5ff1985c1eeNarayan Kamathstatic const char ZYGOTE_NICE_NAME[] = "zygote"; 185c41638cb759ce569630ffae4c5c4cdee1b0f3b82Narayan Kamath#endif 186c41638cb759ce569630ffae4c5c4cdee1b0f3b82Narayan Kamath 1878a0a929422682ba3eb6a205dc6c0638e68b909deNick Kralevichint main(int argc, char* const argv[]) 1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 1894f66cb3f534eafff335ec803caff0572d08e8aa5Igor Murashkin if (!LOG_NDEBUG) { 1904f66cb3f534eafff335ec803caff0572d08e8aa5Igor Murashkin String8 argv_String; 1914f66cb3f534eafff335ec803caff0572d08e8aa5Igor Murashkin for (int i = 0; i < argc; ++i) { 1924f66cb3f534eafff335ec803caff0572d08e8aa5Igor Murashkin argv_String.append("\""); 1934f66cb3f534eafff335ec803caff0572d08e8aa5Igor Murashkin argv_String.append(argv[i]); 1944f66cb3f534eafff335ec803caff0572d08e8aa5Igor Murashkin argv_String.append("\" "); 1954f66cb3f534eafff335ec803caff0572d08e8aa5Igor Murashkin } 1964f66cb3f534eafff335ec803caff0572d08e8aa5Igor Murashkin ALOGV("app_process main with argv: %s", argv_String.string()); 1974f66cb3f534eafff335ec803caff0572d08e8aa5Igor Murashkin } 1984f66cb3f534eafff335ec803caff0572d08e8aa5Igor Murashkin 199a23fcd7be8e40078a913b1a99222cdd89229e67bNarayan Kamath AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv)); 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Process command line arguments 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // ignore argv[0] 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project argc--; 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project argv++; 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 20522ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath // Everything up to '--' or first non '-' arg goes to the vm. 20622ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath // 20722ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath // The first argument after the VM args is the "parent dir", which 20822ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath // is currently unused. 20922ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath // 21022ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath // After the parent dir, we expect one or more the following internal 21122ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath // arguments : 21222ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath // 21322ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath // --zygote : Start in zygote mode 21422ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath // --start-system-server : Start the system server. 21522ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath // --application : Start in application (stand alone, non zygote) mode. 21622ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath // --nice-name : The nice name for this process. 21722ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath // 21822ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath // For non zygote starts, these arguments will be followed by 21922ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath // the main class name. All remaining arguments are passed to 22022ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath // the main method of this class. 22122ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath // 22222ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath // For zygote starts, all remaining arguments are passed to the zygote. 22322ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath // main function. 22400c0cd4a24bd0f040055f9e786e2df1fa3b7d2d3Jeff Brown // 22500c0cd4a24bd0f040055f9e786e2df1fa3b7d2d3Jeff Brown // Note that we must copy argument string values since we will rewrite the 22600c0cd4a24bd0f040055f9e786e2df1fa3b7d2d3Jeff Brown // entire argument block when we apply the nice name to argv0. 2274f66cb3f534eafff335ec803caff0572d08e8aa5Igor Murashkin // 2284f66cb3f534eafff335ec803caff0572d08e8aa5Igor Murashkin // As an exception to the above rule, anything in "spaced commands" 2294f66cb3f534eafff335ec803caff0572d08e8aa5Igor Murashkin // goes to the vm even though it has a space in it. 2304f66cb3f534eafff335ec803caff0572d08e8aa5Igor Murashkin const char* spaced_commands[] = { "-cp", "-classpath" }; 2314f66cb3f534eafff335ec803caff0572d08e8aa5Igor Murashkin // Allow "spaced commands" to be succeeded by exactly 1 argument (regardless of -s). 2324f66cb3f534eafff335ec803caff0572d08e8aa5Igor Murashkin bool known_command = false; 23322ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath 23400c0cd4a24bd0f040055f9e786e2df1fa3b7d2d3Jeff Brown int i; 23500c0cd4a24bd0f040055f9e786e2df1fa3b7d2d3Jeff Brown for (i = 0; i < argc; i++) { 2364f66cb3f534eafff335ec803caff0572d08e8aa5Igor Murashkin if (known_command == true) { 2374f66cb3f534eafff335ec803caff0572d08e8aa5Igor Murashkin runtime.addOption(strdup(argv[i])); 2384f66cb3f534eafff335ec803caff0572d08e8aa5Igor Murashkin ALOGV("app_process main add known option '%s'", argv[i]); 2394f66cb3f534eafff335ec803caff0572d08e8aa5Igor Murashkin known_command = false; 2404f66cb3f534eafff335ec803caff0572d08e8aa5Igor Murashkin continue; 2414f66cb3f534eafff335ec803caff0572d08e8aa5Igor Murashkin } 2424f66cb3f534eafff335ec803caff0572d08e8aa5Igor Murashkin 2434f66cb3f534eafff335ec803caff0572d08e8aa5Igor Murashkin for (int j = 0; 2444f66cb3f534eafff335ec803caff0572d08e8aa5Igor Murashkin j < static_cast<int>(sizeof(spaced_commands) / sizeof(spaced_commands[0])); 2454f66cb3f534eafff335ec803caff0572d08e8aa5Igor Murashkin ++j) { 2464f66cb3f534eafff335ec803caff0572d08e8aa5Igor Murashkin if (strcmp(argv[i], spaced_commands[j]) == 0) { 2474f66cb3f534eafff335ec803caff0572d08e8aa5Igor Murashkin known_command = true; 2484f66cb3f534eafff335ec803caff0572d08e8aa5Igor Murashkin ALOGV("app_process main found known command '%s'", argv[i]); 2494f66cb3f534eafff335ec803caff0572d08e8aa5Igor Murashkin } 2504f66cb3f534eafff335ec803caff0572d08e8aa5Igor Murashkin } 2514f66cb3f534eafff335ec803caff0572d08e8aa5Igor Murashkin 25200c0cd4a24bd0f040055f9e786e2df1fa3b7d2d3Jeff Brown if (argv[i][0] != '-') { 25300c0cd4a24bd0f040055f9e786e2df1fa3b7d2d3Jeff Brown break; 25400c0cd4a24bd0f040055f9e786e2df1fa3b7d2d3Jeff Brown } 25500c0cd4a24bd0f040055f9e786e2df1fa3b7d2d3Jeff Brown if (argv[i][1] == '-' && argv[i][2] == 0) { 25600c0cd4a24bd0f040055f9e786e2df1fa3b7d2d3Jeff Brown ++i; // Skip --. 25700c0cd4a24bd0f040055f9e786e2df1fa3b7d2d3Jeff Brown break; 25800c0cd4a24bd0f040055f9e786e2df1fa3b7d2d3Jeff Brown } 2594f66cb3f534eafff335ec803caff0572d08e8aa5Igor Murashkin 26000c0cd4a24bd0f040055f9e786e2df1fa3b7d2d3Jeff Brown runtime.addOption(strdup(argv[i])); 2614f66cb3f534eafff335ec803caff0572d08e8aa5Igor Murashkin ALOGV("app_process main add option '%s'", argv[i]); 26200c0cd4a24bd0f040055f9e786e2df1fa3b7d2d3Jeff Brown } 2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 264ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown // Parse runtime arguments. Stop at first unrecognized option. 265ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown bool zygote = false; 266ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown bool startSystemServer = false; 267ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown bool application = false; 26800c0cd4a24bd0f040055f9e786e2df1fa3b7d2d3Jeff Brown String8 niceName; 26922ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath String8 className; 27022ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath 27122ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath ++i; // Skip unused "parent dir" argument. 272ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown while (i < argc) { 273ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown const char* arg = argv[i++]; 27422ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath if (strcmp(arg, "--zygote") == 0) { 275ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown zygote = true; 276d35d3e5d391b8daf20f9af2c5f01d5ff1985c1eeNarayan Kamath niceName = ZYGOTE_NICE_NAME; 277ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown } else if (strcmp(arg, "--start-system-server") == 0) { 278ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown startSystemServer = true; 279ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown } else if (strcmp(arg, "--application") == 0) { 280ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown application = true; 281ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown } else if (strncmp(arg, "--nice-name=", 12) == 0) { 28200c0cd4a24bd0f040055f9e786e2df1fa3b7d2d3Jeff Brown niceName.setTo(arg + 12); 283d35d3e5d391b8daf20f9af2c5f01d5ff1985c1eeNarayan Kamath } else if (strncmp(arg, "--", 2) != 0) { 28422ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath className.setTo(arg); 285ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown break; 286d35d3e5d391b8daf20f9af2c5f01d5ff1985c1eeNarayan Kamath } else { 287d35d3e5d391b8daf20f9af2c5f01d5ff1985c1eeNarayan Kamath --i; 288d35d3e5d391b8daf20f9af2c5f01d5ff1985c1eeNarayan Kamath break; 289ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown } 290ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown } 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 29222ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath Vector<String8> args; 29322ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath if (!className.isEmpty()) { 29422ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath // We're not in zygote mode, the only argument we need to pass 29522ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath // to RuntimeInit is the application argument. 29622ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath // 29722ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath // The Remainder of args get passed to startup class main(). Make 29822ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath // copies of them before we overwrite them with the process name. 29922ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath args.add(application ? String8("application") : String8("tool")); 30022ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath runtime.setClassNameAndArgs(className, argc - i, argv + i); 3014f66cb3f534eafff335ec803caff0572d08e8aa5Igor Murashkin 3024f66cb3f534eafff335ec803caff0572d08e8aa5Igor Murashkin if (!LOG_NDEBUG) { 3034f66cb3f534eafff335ec803caff0572d08e8aa5Igor Murashkin String8 restOfArgs; 3044f66cb3f534eafff335ec803caff0572d08e8aa5Igor Murashkin char* const* argv_new = argv + i; 3054f66cb3f534eafff335ec803caff0572d08e8aa5Igor Murashkin int argc_new = argc - i; 3064f66cb3f534eafff335ec803caff0572d08e8aa5Igor Murashkin for (int k = 0; k < argc_new; ++k) { 3074f66cb3f534eafff335ec803caff0572d08e8aa5Igor Murashkin restOfArgs.append("\""); 3084f66cb3f534eafff335ec803caff0572d08e8aa5Igor Murashkin restOfArgs.append(argv_new[k]); 3094f66cb3f534eafff335ec803caff0572d08e8aa5Igor Murashkin restOfArgs.append("\" "); 3104f66cb3f534eafff335ec803caff0572d08e8aa5Igor Murashkin } 3114f66cb3f534eafff335ec803caff0572d08e8aa5Igor Murashkin ALOGV("Class name = %s, args = %s", className.string(), restOfArgs.string()); 3124f66cb3f534eafff335ec803caff0572d08e8aa5Igor Murashkin } 31322ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath } else { 314d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath // We're in zygote mode. 315d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath maybeCreateDalvikCache(); 316d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath 31722ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath if (startSystemServer) { 31822ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath args.add(String8("start-system-server")); 31922ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath } 32022ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath 321c41638cb759ce569630ffae4c5c4cdee1b0f3b82Narayan Kamath char prop[PROP_VALUE_MAX]; 322c41638cb759ce569630ffae4c5c4cdee1b0f3b82Narayan Kamath if (property_get(ABI_LIST_PROPERTY, prop, NULL) == 0) { 3236bd762289b911e8876759ebbfd9e8960ba825844Elliott Hughes LOG_ALWAYS_FATAL("app_process: Unable to determine ABI list from property %s.", 324c41638cb759ce569630ffae4c5c4cdee1b0f3b82Narayan Kamath ABI_LIST_PROPERTY); 325c41638cb759ce569630ffae4c5c4cdee1b0f3b82Narayan Kamath return 11; 326c41638cb759ce569630ffae4c5c4cdee1b0f3b82Narayan Kamath } 327c41638cb759ce569630ffae4c5c4cdee1b0f3b82Narayan Kamath 328c41638cb759ce569630ffae4c5c4cdee1b0f3b82Narayan Kamath String8 abiFlag("--abi-list="); 329c41638cb759ce569630ffae4c5c4cdee1b0f3b82Narayan Kamath abiFlag.append(prop); 330c41638cb759ce569630ffae4c5c4cdee1b0f3b82Narayan Kamath args.add(abiFlag); 331c41638cb759ce569630ffae4c5c4cdee1b0f3b82Narayan Kamath 33222ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath // In zygote mode, pass all remaining arguments to the zygote 33322ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath // main() method. 33422ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath for (; i < argc; ++i) { 33522ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath args.add(String8(argv[i])); 33622ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath } 33722ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath } 33822ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath 33900c0cd4a24bd0f040055f9e786e2df1fa3b7d2d3Jeff Brown if (!niceName.isEmpty()) { 340f5b6e5590e0a2c1be10bc0bd0a3b141256fdf7fdDmitriy Filchenko runtime.setArgv0(niceName.string(), true /* setProcName */); 341ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown } 3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 343ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown if (zygote) { 3447a09b8322cab26d6e3da1362d3c74964ae66b5d4Sebastien Hertz runtime.start("com.android.internal.os.ZygoteInit", args, zygote); 345ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown } else if (className) { 3467a09b8322cab26d6e3da1362d3c74964ae66b5d4Sebastien Hertz runtime.start("com.android.internal.os.RuntimeInit", args, zygote); 3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fprintf(stderr, "Error: no class name or --zygote supplied.\n"); 3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project app_usage(); 350de6d1d889ebf15250c04a8ffc204b91af1e447e3Brian Carlstrom LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied."); 3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 353