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> 170795272aa226f4e965968a03daddc53ce30b7cdaMathias Agopian#include <binder/ProcessState.h> 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/Log.h> 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <cutils/memory.h> 20c41638cb759ce569630ffae4c5c4cdee1b0f3b82Narayan Kamath#include <cutils/process_name.h> 21c41638cb759ce569630ffae4c5c4cdee1b0f3b82Narayan Kamath#include <cutils/properties.h> 226ad0452e6301c0650f58f3991f7c523f6f279ddbJamie Gennis#include <cutils/trace.h> 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <android_runtime/AndroidRuntime.h> 24d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath#include <private/android_filesystem_config.h> // for AID_SYSTEM 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectnamespace android { 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 28cfedceb8c180a2e176154d461659e0c3569dc931Andreas Gampestatic void app_usage() 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fprintf(stderr, 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Usage: app_process [java-options] cmd-dir start-class-name [options]\n"); 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectclass AppRuntime : public AndroidRuntime 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic: 37a23fcd7be8e40078a913b1a99222cdd89229e67bNarayan Kamath AppRuntime(char* argBlockStart, const size_t argBlockLength) 38a23fcd7be8e40078a913b1a99222cdd89229e67bNarayan Kamath : AndroidRuntime(argBlockStart, argBlockLength) 39d195e5ab401432ddac659791640a2927fc668699Elliott Hughes , mClass(NULL) 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4322ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath void setClassNameAndArgs(const String8& className, int argc, char * const *argv) { 4422ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath mClassName = className; 4522ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath for (int i = 0; i < argc; ++i) { 4622ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath mArgs.add(String8(argv[i])); 4722ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath } 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 50d195e5ab401432ddac659791640a2927fc668699Elliott Hughes virtual void onVmCreated(JNIEnv* env) 51d195e5ab401432ddac659791640a2927fc668699Elliott Hughes { 5222ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath if (mClassName.isEmpty()) { 53d195e5ab401432ddac659791640a2927fc668699Elliott Hughes return; // Zygote. Nothing to do here. 54d195e5ab401432ddac659791640a2927fc668699Elliott Hughes } 55d195e5ab401432ddac659791640a2927fc668699Elliott Hughes 56d195e5ab401432ddac659791640a2927fc668699Elliott Hughes /* 57d195e5ab401432ddac659791640a2927fc668699Elliott Hughes * This is a little awkward because the JNI FindClass call uses the 58d195e5ab401432ddac659791640a2927fc668699Elliott Hughes * class loader associated with the native method we're executing in. 59d195e5ab401432ddac659791640a2927fc668699Elliott Hughes * If called in onStarted (from RuntimeInit.finishInit because we're 60d195e5ab401432ddac659791640a2927fc668699Elliott Hughes * launching "am", for example), FindClass would see that we're calling 61d195e5ab401432ddac659791640a2927fc668699Elliott Hughes * from a boot class' native method, and so wouldn't look for the class 62d195e5ab401432ddac659791640a2927fc668699Elliott Hughes * we're trying to look up in CLASSPATH. Unfortunately it needs to, 63d195e5ab401432ddac659791640a2927fc668699Elliott Hughes * because the "am" classes are not boot classes. 64d195e5ab401432ddac659791640a2927fc668699Elliott Hughes * 65d195e5ab401432ddac659791640a2927fc668699Elliott Hughes * The easiest fix is to call FindClass here, early on before we start 66d195e5ab401432ddac659791640a2927fc668699Elliott Hughes * executing boot class Java code and thereby deny ourselves access to 67d195e5ab401432ddac659791640a2927fc668699Elliott Hughes * non-boot classes. 68d195e5ab401432ddac659791640a2927fc668699Elliott Hughes */ 6922ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath char* slashClassName = toSlashClassName(mClassName.string()); 70d195e5ab401432ddac659791640a2927fc668699Elliott Hughes mClass = env->FindClass(slashClassName); 71d195e5ab401432ddac659791640a2927fc668699Elliott Hughes if (mClass == NULL) { 7222ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath ALOGE("ERROR: could not find class '%s'\n", mClassName.string()); 73d195e5ab401432ddac659791640a2927fc668699Elliott Hughes } 74d195e5ab401432ddac659791640a2927fc668699Elliott Hughes free(slashClassName); 75d195e5ab401432ddac659791640a2927fc668699Elliott Hughes 76d195e5ab401432ddac659791640a2927fc668699Elliott Hughes mClass = reinterpret_cast<jclass>(env->NewGlobalRef(mClass)); 77d195e5ab401432ddac659791640a2927fc668699Elliott Hughes } 78d195e5ab401432ddac659791640a2927fc668699Elliott Hughes 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project virtual void onStarted() 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sp<ProcessState> proc = ProcessState::self(); 8271f2cf116aab893e224056c38ab146bd1538dd3eSteve Block ALOGV("App process: starting thread pool.\n"); 8310e89712863f5b91a2982dc1783fbdfe39c1485dJeff Brown proc->startThreadPool(); 84d195e5ab401432ddac659791640a2927fc668699Elliott Hughes 85d195e5ab401432ddac659791640a2927fc668699Elliott Hughes AndroidRuntime* ar = AndroidRuntime::getRuntime(); 8622ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath ar->callMain(mClassName, mClass, mArgs); 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8810e89712863f5b91a2982dc1783fbdfe39c1485dJeff Brown 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(); 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project AndroidRuntime::onExit(code); 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 108d195e5ab401432ddac659791640a2927fc668699Elliott Hughes 10922ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath String8 mClassName; 11022ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath Vector<String8> mArgs; 111d195e5ab401432ddac659791640a2927fc668699Elliott Hughes jclass mClass; 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectusing namespace android; 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 118a23fcd7be8e40078a913b1a99222cdd89229e67bNarayan Kamathstatic size_t computeArgBlockSize(int argc, char* const argv[]) { 119a23fcd7be8e40078a913b1a99222cdd89229e67bNarayan Kamath // TODO: This assumes that all arguments are allocated in 120a23fcd7be8e40078a913b1a99222cdd89229e67bNarayan Kamath // contiguous memory. There isn't any documented guarantee 121a23fcd7be8e40078a913b1a99222cdd89229e67bNarayan Kamath // that this is the case, but this is how the kernel does it 122a23fcd7be8e40078a913b1a99222cdd89229e67bNarayan Kamath // (see fs/exec.c). 123a23fcd7be8e40078a913b1a99222cdd89229e67bNarayan Kamath // 124a23fcd7be8e40078a913b1a99222cdd89229e67bNarayan Kamath // Also note that this is a constant for "normal" android apps. 125a23fcd7be8e40078a913b1a99222cdd89229e67bNarayan Kamath // Since they're forked from zygote, the size of their command line 126a23fcd7be8e40078a913b1a99222cdd89229e67bNarayan Kamath // is the size of the zygote command line. 127a23fcd7be8e40078a913b1a99222cdd89229e67bNarayan Kamath // 128a23fcd7be8e40078a913b1a99222cdd89229e67bNarayan Kamath // We change the process name of the process by over-writing 129a23fcd7be8e40078a913b1a99222cdd89229e67bNarayan Kamath // the start of the argument block (argv[0]) with the new name of 130a23fcd7be8e40078a913b1a99222cdd89229e67bNarayan Kamath // the process, so we'd mysteriously start getting truncated process 131a23fcd7be8e40078a913b1a99222cdd89229e67bNarayan Kamath // names if the zygote command line decreases in size. 132a23fcd7be8e40078a913b1a99222cdd89229e67bNarayan Kamath uintptr_t start = reinterpret_cast<uintptr_t>(argv[0]); 133a23fcd7be8e40078a913b1a99222cdd89229e67bNarayan Kamath uintptr_t end = reinterpret_cast<uintptr_t>(argv[argc - 1]); 13400c0cd4a24bd0f040055f9e786e2df1fa3b7d2d3Jeff Brown end += strlen(argv[argc - 1]) + 1; 135a23fcd7be8e40078a913b1a99222cdd89229e67bNarayan Kamath return (end - start); 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 138d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamathstatic void maybeCreateDalvikCache() { 139d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath#if defined(__aarch64__) 140d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath static const char kInstructionSet[] = "arm64"; 141d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath#elif defined(__x86_64__) 142d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath static const char kInstructionSet[] = "x86_64"; 143d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath#elif defined(__arm__) 144d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath static const char kInstructionSet[] = "arm"; 1456eb1b2611cd2db7f2c2063f8be219d4ef19d11d0Narayan Kamath#elif defined(__i386__) 146d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath static const char kInstructionSet[] = "x86"; 1477e7c6031821e2aa55c756a9c85f97a22f4875552Douglas Leung#elif defined (__mips__) && !defined(__LP64__) 148d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath static const char kInstructionSet[] = "mips"; 1497e7c6031821e2aa55c756a9c85f97a22f4875552Douglas Leung#elif defined (__mips__) && defined(__LP64__) 1507e7c6031821e2aa55c756a9c85f97a22f4875552Douglas Leung static const char kInstructionSet[] = "mips64"; 151d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath#else 152d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath#error "Unknown instruction set" 153d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath#endif 154d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath const char* androidRoot = getenv("ANDROID_DATA"); 155d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath LOG_ALWAYS_FATAL_IF(androidRoot == NULL, "ANDROID_DATA environment variable unset"); 156d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath 157d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath char dalvikCacheDir[PATH_MAX]; 158d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath const int numChars = snprintf(dalvikCacheDir, PATH_MAX, 159d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath "%s/dalvik-cache/%s", androidRoot, kInstructionSet); 160d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath LOG_ALWAYS_FATAL_IF((numChars >= PATH_MAX || numChars < 0), 161d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath "Error constructing dalvik cache : %s", strerror(errno)); 162d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath 16355471dcd0f843e79d8665c63165720eca6a9c980Alex Light int result = mkdir(dalvikCacheDir, 0711); 164d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath LOG_ALWAYS_FATAL_IF((result < 0 && errno != EEXIST), 165d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath "Error creating cache dir %s : %s", dalvikCacheDir, strerror(errno)); 166d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath 167d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath // We always perform these steps because the directory might 168d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath // already exist, with wider permissions and a different owner 169d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath // than we'd like. 17055471dcd0f843e79d8665c63165720eca6a9c980Alex Light result = chown(dalvikCacheDir, AID_ROOT, AID_ROOT); 171d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath LOG_ALWAYS_FATAL_IF((result < 0), "Error changing dalvik-cache ownership : %s", strerror(errno)); 172d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath 17355471dcd0f843e79d8665c63165720eca6a9c980Alex Light result = chmod(dalvikCacheDir, 0711); 174d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath LOG_ALWAYS_FATAL_IF((result < 0), 175d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath "Error changing dalvik-cache permissions : %s", strerror(errno)); 176d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath} 177d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath 178c41638cb759ce569630ffae4c5c4cdee1b0f3b82Narayan Kamath#if defined(__LP64__) 179c41638cb759ce569630ffae4c5c4cdee1b0f3b82Narayan Kamathstatic const char ABI_LIST_PROPERTY[] = "ro.product.cpu.abilist64"; 180d35d3e5d391b8daf20f9af2c5f01d5ff1985c1eeNarayan Kamathstatic const char ZYGOTE_NICE_NAME[] = "zygote64"; 181c41638cb759ce569630ffae4c5c4cdee1b0f3b82Narayan Kamath#else 182c41638cb759ce569630ffae4c5c4cdee1b0f3b82Narayan Kamathstatic const char ABI_LIST_PROPERTY[] = "ro.product.cpu.abilist32"; 183d35d3e5d391b8daf20f9af2c5f01d5ff1985c1eeNarayan Kamathstatic const char ZYGOTE_NICE_NAME[] = "zygote"; 184c41638cb759ce569630ffae4c5c4cdee1b0f3b82Narayan Kamath#endif 185c41638cb759ce569630ffae4c5c4cdee1b0f3b82Narayan Kamath 1868a0a929422682ba3eb6a205dc6c0638e68b909deNick Kralevichint main(int argc, char* const argv[]) 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 188195c73c9b2c5be50ab325099dc2160215ac7562aNick Kralevich if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0) { 189195c73c9b2c5be50ab325099dc2160215ac7562aNick Kralevich // Older kernels don't understand PR_SET_NO_NEW_PRIVS and return 190195c73c9b2c5be50ab325099dc2160215ac7562aNick Kralevich // EINVAL. Don't die on such kernels. 191195c73c9b2c5be50ab325099dc2160215ac7562aNick Kralevich if (errno != EINVAL) { 192195c73c9b2c5be50ab325099dc2160215ac7562aNick Kralevich LOG_ALWAYS_FATAL("PR_SET_NO_NEW_PRIVS failed: %s", strerror(errno)); 193195c73c9b2c5be50ab325099dc2160215ac7562aNick Kralevich return 12; 194195c73c9b2c5be50ab325099dc2160215ac7562aNick Kralevich } 195195c73c9b2c5be50ab325099dc2160215ac7562aNick Kralevich } 196195c73c9b2c5be50ab325099dc2160215ac7562aNick Kralevich 197a23fcd7be8e40078a913b1a99222cdd89229e67bNarayan Kamath AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv)); 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Process command line arguments 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // ignore argv[0] 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project argc--; 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project argv++; 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 20322ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath // Everything up to '--' or first non '-' arg goes to the vm. 20422ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath // 20522ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath // The first argument after the VM args is the "parent dir", which 20622ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath // is currently unused. 20722ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath // 20822ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath // After the parent dir, we expect one or more the following internal 20922ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath // arguments : 21022ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath // 21122ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath // --zygote : Start in zygote mode 21222ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath // --start-system-server : Start the system server. 21322ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath // --application : Start in application (stand alone, non zygote) mode. 21422ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath // --nice-name : The nice name for this process. 21522ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath // 21622ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath // For non zygote starts, these arguments will be followed by 21722ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath // the main class name. All remaining arguments are passed to 21822ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath // the main method of this class. 21922ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath // 22022ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath // For zygote starts, all remaining arguments are passed to the zygote. 22122ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath // main function. 22200c0cd4a24bd0f040055f9e786e2df1fa3b7d2d3Jeff Brown // 22300c0cd4a24bd0f040055f9e786e2df1fa3b7d2d3Jeff Brown // Note that we must copy argument string values since we will rewrite the 22400c0cd4a24bd0f040055f9e786e2df1fa3b7d2d3Jeff Brown // entire argument block when we apply the nice name to argv0. 22522ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath 22600c0cd4a24bd0f040055f9e786e2df1fa3b7d2d3Jeff Brown int i; 22700c0cd4a24bd0f040055f9e786e2df1fa3b7d2d3Jeff Brown for (i = 0; i < argc; i++) { 22800c0cd4a24bd0f040055f9e786e2df1fa3b7d2d3Jeff Brown if (argv[i][0] != '-') { 22900c0cd4a24bd0f040055f9e786e2df1fa3b7d2d3Jeff Brown break; 23000c0cd4a24bd0f040055f9e786e2df1fa3b7d2d3Jeff Brown } 23100c0cd4a24bd0f040055f9e786e2df1fa3b7d2d3Jeff Brown if (argv[i][1] == '-' && argv[i][2] == 0) { 23200c0cd4a24bd0f040055f9e786e2df1fa3b7d2d3Jeff Brown ++i; // Skip --. 23300c0cd4a24bd0f040055f9e786e2df1fa3b7d2d3Jeff Brown break; 23400c0cd4a24bd0f040055f9e786e2df1fa3b7d2d3Jeff Brown } 23500c0cd4a24bd0f040055f9e786e2df1fa3b7d2d3Jeff Brown runtime.addOption(strdup(argv[i])); 23600c0cd4a24bd0f040055f9e786e2df1fa3b7d2d3Jeff Brown } 2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 238ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown // Parse runtime arguments. Stop at first unrecognized option. 239ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown bool zygote = false; 240ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown bool startSystemServer = false; 241ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown bool application = false; 24200c0cd4a24bd0f040055f9e786e2df1fa3b7d2d3Jeff Brown String8 niceName; 24322ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath String8 className; 24422ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath 24522ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath ++i; // Skip unused "parent dir" argument. 246ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown while (i < argc) { 247ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown const char* arg = argv[i++]; 24822ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath if (strcmp(arg, "--zygote") == 0) { 249ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown zygote = true; 250d35d3e5d391b8daf20f9af2c5f01d5ff1985c1eeNarayan Kamath niceName = ZYGOTE_NICE_NAME; 251ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown } else if (strcmp(arg, "--start-system-server") == 0) { 252ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown startSystemServer = true; 253ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown } else if (strcmp(arg, "--application") == 0) { 254ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown application = true; 255ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown } else if (strncmp(arg, "--nice-name=", 12) == 0) { 25600c0cd4a24bd0f040055f9e786e2df1fa3b7d2d3Jeff Brown niceName.setTo(arg + 12); 257d35d3e5d391b8daf20f9af2c5f01d5ff1985c1eeNarayan Kamath } else if (strncmp(arg, "--", 2) != 0) { 25822ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath className.setTo(arg); 259ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown break; 260d35d3e5d391b8daf20f9af2c5f01d5ff1985c1eeNarayan Kamath } else { 261d35d3e5d391b8daf20f9af2c5f01d5ff1985c1eeNarayan Kamath --i; 262d35d3e5d391b8daf20f9af2c5f01d5ff1985c1eeNarayan Kamath break; 263ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown } 264ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown } 2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 26622ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath Vector<String8> args; 26722ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath if (!className.isEmpty()) { 26822ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath // We're not in zygote mode, the only argument we need to pass 26922ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath // to RuntimeInit is the application argument. 27022ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath // 27122ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath // The Remainder of args get passed to startup class main(). Make 27222ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath // copies of them before we overwrite them with the process name. 27322ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath args.add(application ? String8("application") : String8("tool")); 27422ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath runtime.setClassNameAndArgs(className, argc - i, argv + i); 27522ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath } else { 276d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath // We're in zygote mode. 277d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath maybeCreateDalvikCache(); 278d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath 27922ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath if (startSystemServer) { 28022ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath args.add(String8("start-system-server")); 28122ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath } 28222ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath 283c41638cb759ce569630ffae4c5c4cdee1b0f3b82Narayan Kamath char prop[PROP_VALUE_MAX]; 284c41638cb759ce569630ffae4c5c4cdee1b0f3b82Narayan Kamath if (property_get(ABI_LIST_PROPERTY, prop, NULL) == 0) { 2856bd762289b911e8876759ebbfd9e8960ba825844Elliott Hughes LOG_ALWAYS_FATAL("app_process: Unable to determine ABI list from property %s.", 286c41638cb759ce569630ffae4c5c4cdee1b0f3b82Narayan Kamath ABI_LIST_PROPERTY); 287c41638cb759ce569630ffae4c5c4cdee1b0f3b82Narayan Kamath return 11; 288c41638cb759ce569630ffae4c5c4cdee1b0f3b82Narayan Kamath } 289c41638cb759ce569630ffae4c5c4cdee1b0f3b82Narayan Kamath 290c41638cb759ce569630ffae4c5c4cdee1b0f3b82Narayan Kamath String8 abiFlag("--abi-list="); 291c41638cb759ce569630ffae4c5c4cdee1b0f3b82Narayan Kamath abiFlag.append(prop); 292c41638cb759ce569630ffae4c5c4cdee1b0f3b82Narayan Kamath args.add(abiFlag); 293c41638cb759ce569630ffae4c5c4cdee1b0f3b82Narayan Kamath 29422ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath // In zygote mode, pass all remaining arguments to the zygote 29522ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath // main() method. 29622ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath for (; i < argc; ++i) { 29722ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath args.add(String8(argv[i])); 29822ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath } 29922ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath } 30022ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath 30100c0cd4a24bd0f040055f9e786e2df1fa3b7d2d3Jeff Brown if (!niceName.isEmpty()) { 30200c0cd4a24bd0f040055f9e786e2df1fa3b7d2d3Jeff Brown runtime.setArgv0(niceName.string()); 30300c0cd4a24bd0f040055f9e786e2df1fa3b7d2d3Jeff Brown set_process_name(niceName.string()); 304ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown } 3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 306ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown if (zygote) { 3077a09b8322cab26d6e3da1362d3c74964ae66b5d4Sebastien Hertz runtime.start("com.android.internal.os.ZygoteInit", args, zygote); 308ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown } else if (className) { 3097a09b8322cab26d6e3da1362d3c74964ae66b5d4Sebastien Hertz runtime.start("com.android.internal.os.RuntimeInit", args, zygote); 3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fprintf(stderr, "Error: no class name or --zygote supplied.\n"); 3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project app_usage(); 313de6d1d889ebf15250c04a8ffc204b91af1e447e3Brian Carlstrom LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied."); 3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 10; 3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 317