app_main.cpp revision f5b6e5590e0a2c1be10bc0bd0a3b141256fdf7fd
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Main entry of app process. 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Starts the interpreted runtime, then starts up the application. 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define LOG_TAG "appproc" 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <stdio.h> 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <stdlib.h> 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <sys/prctl.h> 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <sys/stat.h> 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <unistd.h> 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <binder/IPCThreadState.h> 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <binder/ProcessState.h> 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/Log.h> 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <cutils/memory.h> 209b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li#include <cutils/process_name.h> 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <cutils/properties.h> 229b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li#include <cutils/trace.h> 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <android_runtime/AndroidRuntime.h> 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#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 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void app_usage() 29a696f5d667227365da732481770767dcb330dd23Mathias Agopian{ 30fd6f39e147dc077139a41b9c2a4039fbaa20224eJamie Gennis 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{ 36bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnorpublic: 37bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor AppRuntime(char* argBlockStart, const size_t argBlockLength) 38bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor : AndroidRuntime(argBlockStart, argBlockLength) 39df4578e8ab7008a7e528d5af2ae761b33cf2bdf4Scott Main , mClass(NULL) 40bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor { 417478ea6848c0059e65a4089b4ec2ff4158520870Wu-cheng Li } 42df4578e8ab7008a7e528d5af2ae761b33cf2bdf4Scott Main 43df4578e8ab7008a7e528d5af2ae761b33cf2bdf4Scott Main void setClassNameAndArgs(const String8& className, int argc, char * const *argv) { 44bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor mClassName = className; 457478ea6848c0059e65a4089b4ec2ff4158520870Wu-cheng Li for (int i = 0; i < argc; ++i) { 46df4578e8ab7008a7e528d5af2ae761b33cf2bdf4Scott Main mArgs.add(String8(argv[i])); 47df4578e8ab7008a7e528d5af2ae761b33cf2bdf4Scott Main } 48df4578e8ab7008a7e528d5af2ae761b33cf2bdf4Scott Main } 49df4578e8ab7008a7e528d5af2ae761b33cf2bdf4Scott Main 50df4578e8ab7008a7e528d5af2ae761b33cf2bdf4Scott Main virtual void onVmCreated(JNIEnv* env) 51bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor { 52bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor if (mClassName.isEmpty()) { 53bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor return; // Zygote. Nothing to do here. 54341ff13689dfe822b598e626272ac2e80041b482Dan Egnor } 55bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor 56bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor /* 57bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor * This is a little awkward because the JNI FindClass call uses the 58bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor * class loader associated with the native method we're executing in. 59bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor * If called in onStarted (from RuntimeInit.finishInit because we're 60bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor * launching "am", for example), FindClass would see that we're calling 61bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor * from a boot class' native method, and so wouldn't look for the class 62bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor * we're trying to look up in CLASSPATH. Unfortunately it needs to, 63bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor * because the "am" classes are not boot classes. 64bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor * 65bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor * The easiest fix is to call FindClass here, early on before we start 66bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor * executing boot class Java code and thereby deny ourselves access to 67bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor * non-boot classes. 68bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor */ 69bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor char* slashClassName = toSlashClassName(mClassName.string()); 70bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor mClass = env->FindClass(slashClassName); 71bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor if (mClass == NULL) { 72bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor ALOGE("ERROR: could not find class '%s'\n", mClassName.string()); 73bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor } 74bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor free(slashClassName); 75bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor 76bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor mClass = reinterpret_cast<jclass>(env->NewGlobalRef(mClass)); 77bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor } 78bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor 79bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor virtual void onStarted() 80bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor { 81bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor sp<ProcessState> proc = ProcessState::self(); 82bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor ALOGV("App process: starting thread pool.\n"); 83bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor proc->startThreadPool(); 84bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor 85bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor AndroidRuntime* ar = AndroidRuntime::getRuntime(); 86bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor ar->callMain(mClassName, mClass, mArgs); 87bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor 88bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor IPCThreadState::self()->stopProcess(); 89bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor } 90bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor 91bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor virtual void onZygoteInit() 92bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor { 93bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor sp<ProcessState> proc = ProcessState::self(); 94bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor ALOGV("App process: starting thread pool.\n"); 95bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor proc->startThreadPool(); 96bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor } 97bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor 98bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor virtual void onExit(int code) 99bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor { 100bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor if (mClassName.isEmpty()) { 101bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor // if zygote 102bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor IPCThreadState::self()->stopProcess(); 103bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor } 104bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor 105bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor AndroidRuntime::onExit(code); 106341ff13689dfe822b598e626272ac2e80041b482Dan Egnor } 107bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor 108bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor 109df4578e8ab7008a7e528d5af2ae761b33cf2bdf4Scott Main String8 mClassName; 110df4578e8ab7008a7e528d5af2ae761b33cf2bdf4Scott Main Vector<String8> mArgs; 111df4578e8ab7008a7e528d5af2ae761b33cf2bdf4Scott Main jclass mClass; 1127478ea6848c0059e65a4089b4ec2ff4158520870Wu-cheng Li}; 113df4578e8ab7008a7e528d5af2ae761b33cf2bdf4Scott Main 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectusing namespace android; 1179b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li 118d2c2929c94bec68741b85f4174e11307fb65157fWu-cheng Listatic size_t computeArgBlockSize(int argc, char* const argv[]) { 119da83f4674a564007baac03db062a289c8158d940Benny Wong // TODO: This assumes that all arguments are allocated in 120da83f4674a564007baac03db062a289c8158d940Benny Wong // contiguous memory. There isn't any documented guarantee 121da83f4674a564007baac03db062a289c8158d940Benny Wong // that this is the case, but this is how the kernel does it 122da83f4674a564007baac03db062a289c8158d940Benny Wong // (see fs/exec.c). 123da83f4674a564007baac03db062a289c8158d940Benny Wong // 124da83f4674a564007baac03db062a289c8158d940Benny Wong // Also note that this is a constant for "normal" android apps. 125da83f4674a564007baac03db062a289c8158d940Benny Wong // Since they're forked from zygote, the size of their command line 126da83f4674a564007baac03db062a289c8158d940Benny Wong // is the size of the zygote command line. 127da83f4674a564007baac03db062a289c8158d940Benny Wong // 128da83f4674a564007baac03db062a289c8158d940Benny Wong // We change the process name of the process by over-writing 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // the start of the argument block (argv[0]) with the new name of 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // the process, so we'd mysteriously start getting truncated process 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // names if the zygote command line decreases in size. 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uintptr_t start = reinterpret_cast<uintptr_t>(argv[0]); 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uintptr_t end = reinterpret_cast<uintptr_t>(argv[argc - 1]); 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project end += strlen(argv[argc - 1]) + 1; 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (end - start); 136e8b26e197f7c5e4acbdf8a5cd3f014fbc242c8abDave Sparks} 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1383f4639a6611222ae1ae5493de49213250d292139Wu-cheng Listatic void maybeCreateDalvikCache() { 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#if defined(__aarch64__) 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static const char kInstructionSet[] = "arm64"; 14194927dffce1626898b59579dfc5af53b5de8cef6Andrew Harp#elif defined(__x86_64__) 1429b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li static const char kInstructionSet[] = "x86_64"; 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#elif defined(__arm__) 144341ff13689dfe822b598e626272ac2e80041b482Dan Egnor static const char kInstructionSet[] = "arm"; 145e25cc656392d8866e163f78b60c7791455d0fb44Chih-Chung Chang#elif defined(__i386__) 146e25cc656392d8866e163f78b60c7791455d0fb44Chih-Chung Chang static const char kInstructionSet[] = "x86"; 147e25cc656392d8866e163f78b60c7791455d0fb44Chih-Chung Chang#elif defined (__mips__) && !defined(__LP64__) 148e25cc656392d8866e163f78b60c7791455d0fb44Chih-Chung Chang static const char kInstructionSet[] = "mips"; 149341ff13689dfe822b598e626272ac2e80041b482Dan Egnor#elif defined (__mips__) && defined(__LP64__) 150b8bb78f54b48868465a9d69d65fda08524ab5ae1Chih-Chung Chang static const char kInstructionSet[] = "mips64"; 151b8bb78f54b48868465a9d69d65fda08524ab5ae1Chih-Chung Chang#else 152b8bb78f54b48868465a9d69d65fda08524ab5ae1Chih-Chung Chang#error "Unknown instruction set" 153b8bb78f54b48868465a9d69d65fda08524ab5ae1Chih-Chung Chang#endif 154b8bb78f54b48868465a9d69d65fda08524ab5ae1Chih-Chung Chang const char* androidRoot = getenv("ANDROID_DATA"); 155b8bb78f54b48868465a9d69d65fda08524ab5ae1Chih-Chung Chang LOG_ALWAYS_FATAL_IF(androidRoot == NULL, "ANDROID_DATA environment variable unset"); 156b8bb78f54b48868465a9d69d65fda08524ab5ae1Chih-Chung Chang 157b8bb78f54b48868465a9d69d65fda08524ab5ae1Chih-Chung Chang char dalvikCacheDir[PATH_MAX]; 1587836660f5eb45b7b7e1f5119face65c80e2ade17Wu-cheng Li const int numChars = snprintf(dalvikCacheDir, PATH_MAX, 1597836660f5eb45b7b7e1f5119face65c80e2ade17Wu-cheng Li "%s/dalvik-cache/%s", androidRoot, kInstructionSet); 1607836660f5eb45b7b7e1f5119face65c80e2ade17Wu-cheng Li LOG_ALWAYS_FATAL_IF((numChars >= PATH_MAX || numChars < 0), 161b8bb78f54b48868465a9d69d65fda08524ab5ae1Chih-Chung Chang "Error constructing dalvik cache : %s", strerror(errno)); 1627836660f5eb45b7b7e1f5119face65c80e2ade17Wu-cheng Li 1637836660f5eb45b7b7e1f5119face65c80e2ade17Wu-cheng Li int result = mkdir(dalvikCacheDir, 0711); 1647836660f5eb45b7b7e1f5119face65c80e2ade17Wu-cheng Li LOG_ALWAYS_FATAL_IF((result < 0 && errno != EEXIST), 1657836660f5eb45b7b7e1f5119face65c80e2ade17Wu-cheng Li "Error creating cache dir %s : %s", dalvikCacheDir, strerror(errno)); 166b8bb78f54b48868465a9d69d65fda08524ab5ae1Chih-Chung Chang 167b8bb78f54b48868465a9d69d65fda08524ab5ae1Chih-Chung Chang // We always perform these steps because the directory might 168b8bb78f54b48868465a9d69d65fda08524ab5ae1Chih-Chung Chang // already exist, with wider permissions and a different owner 169b8bb78f54b48868465a9d69d65fda08524ab5ae1Chih-Chung Chang // than we'd like. 170b8bb78f54b48868465a9d69d65fda08524ab5ae1Chih-Chung Chang result = chown(dalvikCacheDir, AID_ROOT, AID_ROOT); 171b8bb78f54b48868465a9d69d65fda08524ab5ae1Chih-Chung Chang LOG_ALWAYS_FATAL_IF((result < 0), "Error changing dalvik-cache ownership : %s", strerror(errno)); 1727836660f5eb45b7b7e1f5119face65c80e2ade17Wu-cheng Li 173b8bb78f54b48868465a9d69d65fda08524ab5ae1Chih-Chung Chang result = chmod(dalvikCacheDir, 0711); 174b8bb78f54b48868465a9d69d65fda08524ab5ae1Chih-Chung Chang LOG_ALWAYS_FATAL_IF((result < 0), 175b8bb78f54b48868465a9d69d65fda08524ab5ae1Chih-Chung Chang "Error changing dalvik-cache permissions : %s", strerror(errno)); 176b8bb78f54b48868465a9d69d65fda08524ab5ae1Chih-Chung Chang} 177b8bb78f54b48868465a9d69d65fda08524ab5ae1Chih-Chung Chang 178b8bb78f54b48868465a9d69d65fda08524ab5ae1Chih-Chung Chang#if defined(__LP64__) 1792fe6fcaff4bdab45484055d6c18dd96d1b7b7be1Wu-cheng Listatic const char ABI_LIST_PROPERTY[] = "ro.product.cpu.abilist64"; 1802fe6fcaff4bdab45484055d6c18dd96d1b7b7be1Wu-cheng Listatic const char ZYGOTE_NICE_NAME[] = "zygote64"; 1812fe6fcaff4bdab45484055d6c18dd96d1b7b7be1Wu-cheng Li#else 1822fe6fcaff4bdab45484055d6c18dd96d1b7b7be1Wu-cheng Listatic const char ABI_LIST_PROPERTY[] = "ro.product.cpu.abilist32"; 1832fe6fcaff4bdab45484055d6c18dd96d1b7b7be1Wu-cheng Listatic const char ZYGOTE_NICE_NAME[] = "zygote"; 1842fe6fcaff4bdab45484055d6c18dd96d1b7b7be1Wu-cheng Li#endif 185b8bb78f54b48868465a9d69d65fda08524ab5ae1Chih-Chung Chang 186b8bb78f54b48868465a9d69d65fda08524ab5ae1Chih-Chung Changint main(int argc, char* const argv[]) 18769ea4e15e52c456537575d21443ac1efdb03a902Brad Fitzpatrick{ 18869ea4e15e52c456537575d21443ac1efdb03a902Brad Fitzpatrick if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0) { 18969ea4e15e52c456537575d21443ac1efdb03a902Brad Fitzpatrick // Older kernels don't understand PR_SET_NO_NEW_PRIVS and return 19069ea4e15e52c456537575d21443ac1efdb03a902Brad Fitzpatrick // EINVAL. Don't die on such kernels. 191b8bb78f54b48868465a9d69d65fda08524ab5ae1Chih-Chung Chang if (errno != EINVAL) { 1927836660f5eb45b7b7e1f5119face65c80e2ade17Wu-cheng Li LOG_ALWAYS_FATAL("PR_SET_NO_NEW_PRIVS failed: %s", strerror(errno)); 193b8bb78f54b48868465a9d69d65fda08524ab5ae1Chih-Chung Chang return 12; 194b8bb78f54b48868465a9d69d65fda08524ab5ae1Chih-Chung Chang } 195b8bb78f54b48868465a9d69d65fda08524ab5ae1Chih-Chung Chang } 196341ff13689dfe822b598e626272ac2e80041b482Dan Egnor 197bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv)); 198bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor // Process command line arguments 199bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor // ignore argv[0] 200bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor argc--; 201341ff13689dfe822b598e626272ac2e80041b482Dan Egnor argv++; 202341ff13689dfe822b598e626272ac2e80041b482Dan Egnor 203bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor // Everything up to '--' or first non '-' arg goes to the vm. 204bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor // 205bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor // The first argument after the VM args is the "parent dir", which 206bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor // is currently unused. 207bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor // 208bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor // After the parent dir, we expect one or more the following internal 209bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor // arguments : 210bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor // 211bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor // --zygote : Start in zygote mode 212bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor // --start-system-server : Start the system server. 213bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor // --application : Start in application (stand alone, non zygote) mode. 214341ff13689dfe822b598e626272ac2e80041b482Dan Egnor // --nice-name : The nice name for this process. 215a48b70fa8ff6363d1e5282be70f6be12bc0688dcWu-cheng Li // 216bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor // For non zygote starts, these arguments will be followed by 217bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor // the main class name. All remaining arguments are passed to 218bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor // the main method of this class. 219e25cc656392d8866e163f78b60c7791455d0fb44Chih-Chung Chang // 220e25cc656392d8866e163f78b60c7791455d0fb44Chih-Chung Chang // For zygote starts, all remaining arguments are passed to the zygote. 221e25cc656392d8866e163f78b60c7791455d0fb44Chih-Chung Chang // main function. 222e25cc656392d8866e163f78b60c7791455d0fb44Chih-Chung Chang // 223e25cc656392d8866e163f78b60c7791455d0fb44Chih-Chung Chang // Note that we must copy argument string values since we will rewrite the 224e25cc656392d8866e163f78b60c7791455d0fb44Chih-Chung Chang // entire argument block when we apply the nice name to argv0. 225a48b70fa8ff6363d1e5282be70f6be12bc0688dcWu-cheng Li 226a48b70fa8ff6363d1e5282be70f6be12bc0688dcWu-cheng Li int i; 227a48b70fa8ff6363d1e5282be70f6be12bc0688dcWu-cheng Li for (i = 0; i < argc; i++) { 2287836660f5eb45b7b7e1f5119face65c80e2ade17Wu-cheng Li if (argv[i][0] != '-') { 2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 2309b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li } 231a48b70fa8ff6363d1e5282be70f6be12bc0688dcWu-cheng Li if (argv[i][1] == '-' && argv[i][2] == 0) { 232a48b70fa8ff6363d1e5282be70f6be12bc0688dcWu-cheng Li ++i; // Skip --. 233a48b70fa8ff6363d1e5282be70f6be12bc0688dcWu-cheng Li break; 234a48b70fa8ff6363d1e5282be70f6be12bc0688dcWu-cheng Li } 235a48b70fa8ff6363d1e5282be70f6be12bc0688dcWu-cheng Li runtime.addOption(strdup(argv[i])); 236a48b70fa8ff6363d1e5282be70f6be12bc0688dcWu-cheng Li } 237a48b70fa8ff6363d1e5282be70f6be12bc0688dcWu-cheng Li 238a48b70fa8ff6363d1e5282be70f6be12bc0688dcWu-cheng Li // Parse runtime arguments. Stop at first unrecognized option. 239a48b70fa8ff6363d1e5282be70f6be12bc0688dcWu-cheng Li bool zygote = false; 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bool startSystemServer = false; 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bool application = false; 242e25cc656392d8866e163f78b60c7791455d0fb44Chih-Chung Chang String8 niceName; 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String8 className; 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ++i; // Skip unused "parent dir" argument. 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (i < argc) { 247e8b26e197f7c5e4acbdf8a5cd3f014fbc242c8abDave Sparks const char* arg = argv[i++]; 2483f4639a6611222ae1ae5493de49213250d292139Wu-cheng Li if (strcmp(arg, "--zygote") == 0) { 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project zygote = true; 2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project niceName = ZYGOTE_NICE_NAME; 2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (strcmp(arg, "--start-system-server") == 0) { 2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project startSystemServer = true; 2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (strcmp(arg, "--application") == 0) { 2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project application = true; 2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (strncmp(arg, "--nice-name=", 12) == 0) { 2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project niceName.setTo(arg + 12); 2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (strncmp(arg, "--", 2) != 0) { 2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project className.setTo(arg); 259e25cc656392d8866e163f78b60c7791455d0fb44Chih-Chung Chang break; 2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 2619b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li --i; 2629b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li break; 2639b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li } 2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2659b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li 266e25cc656392d8866e163f78b60c7791455d0fb44Chih-Chung Chang Vector<String8> args; 2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!className.isEmpty()) { 2689b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li // We're not in zygote mode, the only argument we need to pass 2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // to RuntimeInit is the application argument. 2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // 2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // The Remainder of args get passed to startup class main(). Make 272bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor // copies of them before we overwrite them with the process name. 273bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor args.add(application ? String8("application") : String8("tool")); 2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project runtime.setClassNameAndArgs(className, argc - i, argv + i); 2759b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li } else { 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // We're in zygote mode. 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project maybeCreateDalvikCache(); 2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (startSystemServer) { 280bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor args.add(String8("start-system-server")); 281bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor } 282bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor 283bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor char prop[PROP_VALUE_MAX]; 284bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor if (property_get(ABI_LIST_PROPERTY, prop, NULL) == 0) { 285bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor LOG_ALWAYS_FATAL("app_process: Unable to determine ABI list from property %s.", 286bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor ABI_LIST_PROPERTY); 287bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor return 11; 288bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor } 2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 290bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor String8 abiFlag("--abi-list="); 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project abiFlag.append(prop); 292bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor args.add(abiFlag); 2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 294bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor // In zygote mode, pass all remaining arguments to the zygote 2959b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li // main() method. 2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (; i < argc; ++i) { 297bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor args.add(String8(argv[i])); 298bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor } 299bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor } 3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 301bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor if (!niceName.isEmpty()) { 302bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor runtime.setArgv0(niceName.string(), true /* setProcName */); 303bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor } 304bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor 3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (zygote) { 306ffe1cf251a4f8469695b8acfa37270684dc1b70cWu-cheng Li runtime.start("com.android.internal.os.ZygoteInit", args, zygote); 3079b6a8ab8221f2df20c32711b0f1e4f301165fac2Wu-cheng Li } else if (className) { 3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project runtime.start("com.android.internal.os.RuntimeInit", args, zygote); 309bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor } else { 310bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor fprintf(stderr, "Error: no class name or --zygote supplied.\n"); 311bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor app_usage(); 312bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied."); 313bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor return 10; 3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 315bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor} 316bfcbeffc54e93b1c2e2d95fdc301786df4376d6fDan Egnor