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
100795272aa226f4e965968a03daddc53ce30b7cdaMathias Agopian#include <binder/IPCThreadState.h>
110795272aa226f4e965968a03daddc53ce30b7cdaMathias Agopian#include <binder/ProcessState.h>
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/Log.h>
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <cutils/memory.h>
14c41638cb759ce569630ffae4c5c4cdee1b0f3b82Narayan Kamath#include <cutils/process_name.h>
15c41638cb759ce569630ffae4c5c4cdee1b0f3b82Narayan Kamath#include <cutils/properties.h>
166ad0452e6301c0650f58f3991f7c523f6f279ddbJamie Gennis#include <cutils/trace.h>
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <android_runtime/AndroidRuntime.h>
18d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath#include <private/android_filesystem_config.h>  // for AID_SYSTEM
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
201fe21bd1b6ca8b94c78fbf3666a1e8e0472355deNick Kralevich#include <stdlib.h>
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <stdio.h>
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <unistd.h>
23195c73c9b2c5be50ab325099dc2160215ac7562aNick Kralevich#include <sys/prctl.h>
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectnamespace android {
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid 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();
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    virtual void onZygoteInit()
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {
926ad0452e6301c0650f58f3991f7c523f6f279ddbJamie Gennis        // Re-enable tracing now that we're no longer in Zygote.
936ad0452e6301c0650f58f3991f7c523f6f279ddbJamie Gennis        atrace_set_tracing_enabled(true);
946ad0452e6301c0650f58f3991f7c523f6f279ddbJamie Gennis
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        sp<ProcessState> proc = ProcessState::self();
9671f2cf116aab893e224056c38ab146bd1538dd3eSteve Block        ALOGV("App process: starting thread pool.\n");
9710e89712863f5b91a2982dc1783fbdfe39c1485dJeff Brown        proc->startThreadPool();
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    virtual void onExit(int code)
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {
10290c75cf02e8e36be8679273f4ea15fd145001033Narayan Kamath        if (mClassName.isEmpty()) {
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // if zygote
10410e89712863f5b91a2982dc1783fbdfe39c1485dJeff Brown            IPCThreadState::self()->stopProcess();
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        AndroidRuntime::onExit(code);
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
110d195e5ab401432ddac659791640a2927fc668699Elliott Hughes
11122ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath    String8 mClassName;
11222ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath    Vector<String8> mArgs;
113d195e5ab401432ddac659791640a2927fc668699Elliott Hughes    jclass mClass;
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project};
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectusing namespace android;
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
120a23fcd7be8e40078a913b1a99222cdd89229e67bNarayan Kamathstatic size_t computeArgBlockSize(int argc, char* const argv[]) {
121a23fcd7be8e40078a913b1a99222cdd89229e67bNarayan Kamath    // TODO: This assumes that all arguments are allocated in
122a23fcd7be8e40078a913b1a99222cdd89229e67bNarayan Kamath    // contiguous memory. There isn't any documented guarantee
123a23fcd7be8e40078a913b1a99222cdd89229e67bNarayan Kamath    // that this is the case, but this is how the kernel does it
124a23fcd7be8e40078a913b1a99222cdd89229e67bNarayan Kamath    // (see fs/exec.c).
125a23fcd7be8e40078a913b1a99222cdd89229e67bNarayan Kamath    //
126a23fcd7be8e40078a913b1a99222cdd89229e67bNarayan Kamath    // Also note that this is a constant for "normal" android apps.
127a23fcd7be8e40078a913b1a99222cdd89229e67bNarayan Kamath    // Since they're forked from zygote, the size of their command line
128a23fcd7be8e40078a913b1a99222cdd89229e67bNarayan Kamath    // is the size of the zygote command line.
129a23fcd7be8e40078a913b1a99222cdd89229e67bNarayan Kamath    //
130a23fcd7be8e40078a913b1a99222cdd89229e67bNarayan Kamath    // We change the process name of the process by over-writing
131a23fcd7be8e40078a913b1a99222cdd89229e67bNarayan Kamath    // the start of the argument block (argv[0]) with the new name of
132a23fcd7be8e40078a913b1a99222cdd89229e67bNarayan Kamath    // the process, so we'd mysteriously start getting truncated process
133a23fcd7be8e40078a913b1a99222cdd89229e67bNarayan Kamath    // names if the zygote command line decreases in size.
134a23fcd7be8e40078a913b1a99222cdd89229e67bNarayan Kamath    uintptr_t start = reinterpret_cast<uintptr_t>(argv[0]);
135a23fcd7be8e40078a913b1a99222cdd89229e67bNarayan Kamath    uintptr_t end = reinterpret_cast<uintptr_t>(argv[argc - 1]);
13600c0cd4a24bd0f040055f9e786e2df1fa3b7d2d3Jeff Brown    end += strlen(argv[argc - 1]) + 1;
137a23fcd7be8e40078a913b1a99222cdd89229e67bNarayan Kamath    return (end - start);
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
140d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamathstatic void maybeCreateDalvikCache() {
141d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath#if defined(__aarch64__)
142d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath    static const char kInstructionSet[] = "arm64";
143d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath#elif defined(__x86_64__)
144d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath    static const char kInstructionSet[] = "x86_64";
145d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath#elif defined(__arm__)
146d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath    static const char kInstructionSet[] = "arm";
1476eb1b2611cd2db7f2c2063f8be219d4ef19d11d0Narayan Kamath#elif defined(__i386__)
148d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath    static const char kInstructionSet[] = "x86";
149d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath#elif defined (__mips__)
150d1e127e141a8080477f3b3becb792f138ca9ab65Narayan Kamath    static const char kInstructionSet[] = "mips";
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) {
30722ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath        runtime.start("com.android.internal.os.ZygoteInit", args);
308ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown    } else if (className) {
30922ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath        runtime.start("com.android.internal.os.RuntimeInit", args);
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