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