blob: 28752a5315adfaf919182d2d210b08e5188dfcea [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Main entry of app process.
Elliott Hughesd195e5a2011-04-13 15:39:37 -07003 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004 * Starts the interpreted runtime, then starts up the application.
Elliott Hughesd195e5a2011-04-13 15:39:37 -07005 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006 */
7
8#define LOG_TAG "appproc"
9
Nick Kralevichfc17dc22013-04-23 15:30:45 -070010#include <cutils/properties.h>
Mathias Agopian07952722009-05-19 19:08:10 -070011#include <binder/IPCThreadState.h>
12#include <binder/ProcessState.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013#include <utils/Log.h>
14#include <cutils/process_name.h>
15#include <cutils/memory.h>
Jamie Gennis6ad04522013-04-15 18:53:24 -070016#include <cutils/trace.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017#include <android_runtime/AndroidRuntime.h>
Nick Kralevich8a0a9292013-03-14 13:23:52 -070018#include <sys/personality.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080019
Nick Kralevich1fe21bd2013-03-15 11:38:29 -070020#include <stdlib.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080021#include <stdio.h>
22#include <unistd.h>
23
24namespace android {
25
26void app_usage()
27{
28 fprintf(stderr,
29 "Usage: app_process [java-options] cmd-dir start-class-name [options]\n");
30}
31
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080032class AppRuntime : public AndroidRuntime
33{
34public:
35 AppRuntime()
36 : mParentDir(NULL)
37 , mClassName(NULL)
Elliott Hughesd195e5a2011-04-13 15:39:37 -070038 , mClass(NULL)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080039 , mArgC(0)
40 , mArgV(NULL)
41 {
42 }
43
44#if 0
45 // this appears to be unused
46 const char* getParentDir() const
47 {
48 return mParentDir;
49 }
50#endif
51
52 const char* getClassName() const
53 {
54 return mClassName;
55 }
56
Elliott Hughesd195e5a2011-04-13 15:39:37 -070057 virtual void onVmCreated(JNIEnv* env)
58 {
59 if (mClassName == NULL) {
60 return; // Zygote. Nothing to do here.
61 }
62
63 /*
64 * This is a little awkward because the JNI FindClass call uses the
65 * class loader associated with the native method we're executing in.
66 * If called in onStarted (from RuntimeInit.finishInit because we're
67 * launching "am", for example), FindClass would see that we're calling
68 * from a boot class' native method, and so wouldn't look for the class
69 * we're trying to look up in CLASSPATH. Unfortunately it needs to,
70 * because the "am" classes are not boot classes.
71 *
72 * The easiest fix is to call FindClass here, early on before we start
73 * executing boot class Java code and thereby deny ourselves access to
74 * non-boot classes.
75 */
76 char* slashClassName = toSlashClassName(mClassName);
77 mClass = env->FindClass(slashClassName);
78 if (mClass == NULL) {
Steve Block3762c312012-01-06 19:20:56 +000079 ALOGE("ERROR: could not find class '%s'\n", mClassName);
Elliott Hughesd195e5a2011-04-13 15:39:37 -070080 }
81 free(slashClassName);
82
83 mClass = reinterpret_cast<jclass>(env->NewGlobalRef(mClass));
84 }
85
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080086 virtual void onStarted()
87 {
88 sp<ProcessState> proc = ProcessState::self();
Steve Block71f2cf12011-10-20 11:56:00 +010089 ALOGV("App process: starting thread pool.\n");
Jeff Brown10e89712011-07-08 18:52:57 -070090 proc->startThreadPool();
Elliott Hughesd195e5a2011-04-13 15:39:37 -070091
92 AndroidRuntime* ar = AndroidRuntime::getRuntime();
93 ar->callMain(mClassName, mClass, mArgC, mArgV);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080094
Jeff Brown10e89712011-07-08 18:52:57 -070095 IPCThreadState::self()->stopProcess();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080096 }
97
98 virtual void onZygoteInit()
99 {
Jamie Gennis6ad04522013-04-15 18:53:24 -0700100 // Re-enable tracing now that we're no longer in Zygote.
101 atrace_set_tracing_enabled(true);
102
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800103 sp<ProcessState> proc = ProcessState::self();
Steve Block71f2cf12011-10-20 11:56:00 +0100104 ALOGV("App process: starting thread pool.\n");
Jeff Brown10e89712011-07-08 18:52:57 -0700105 proc->startThreadPool();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800106 }
107
108 virtual void onExit(int code)
109 {
110 if (mClassName == NULL) {
111 // if zygote
Jeff Brown10e89712011-07-08 18:52:57 -0700112 IPCThreadState::self()->stopProcess();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800113 }
114
115 AndroidRuntime::onExit(code);
116 }
117
Elliott Hughesd195e5a2011-04-13 15:39:37 -0700118
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800119 const char* mParentDir;
120 const char* mClassName;
Elliott Hughesd195e5a2011-04-13 15:39:37 -0700121 jclass mClass;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800122 int mArgC;
123 const char* const* mArgV;
124};
125
126}
127
128using namespace android;
129
130/*
131 * sets argv0 to as much of newArgv0 as will fit
132 */
133static void setArgv0(const char *argv0, const char *newArgv0)
134{
135 strlcpy(const_cast<char *>(argv0), newArgv0, strlen(argv0));
136}
137
Nick Kralevich8a0a9292013-03-14 13:23:52 -0700138int main(int argc, char* const argv[])
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800139{
Nick Kralevich8a0a9292013-03-14 13:23:52 -0700140#ifdef __arm__
141 /*
142 * b/7188322 - Temporarily revert to the compat memory layout
143 * to avoid breaking third party apps.
144 *
145 * THIS WILL GO AWAY IN A FUTURE ANDROID RELEASE.
146 *
147 * http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=7dbaa466
148 * changes the kernel mapping from bottom up to top-down.
149 * This breaks some programs which improperly embed
150 * an out of date copy of Android's linker.
151 */
Nick Kralevichfc17dc22013-04-23 15:30:45 -0700152 char value[PROPERTY_VALUE_MAX];
153 property_get("ro.kernel.qemu", value, "");
154 bool is_qemu = (strcmp(value, "1") == 0);
155 if ((getenv("NO_ADDR_COMPAT_LAYOUT_FIXUP") == NULL) && !is_qemu) {
Nick Kralevich5fa1ee72013-03-14 16:31:34 -0700156 int current = personality(0xFFFFFFFF);
157 if ((current & ADDR_COMPAT_LAYOUT) == 0) {
158 personality(current | ADDR_COMPAT_LAYOUT);
Nick Kralevich1fe21bd2013-03-15 11:38:29 -0700159 setenv("NO_ADDR_COMPAT_LAYOUT_FIXUP", "1", 1);
Nick Kralevich5fa1ee72013-03-14 16:31:34 -0700160 execv("/system/bin/app_process", argv);
161 return -1;
162 }
Nick Kralevich8a0a9292013-03-14 13:23:52 -0700163 }
Nick Kralevich9a935052013-03-15 13:12:28 -0700164 unsetenv("NO_ADDR_COMPAT_LAYOUT_FIXUP");
Nick Kralevich8a0a9292013-03-14 13:23:52 -0700165#endif
166
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800167 // These are global variables in ProcessState.cpp
168 mArgC = argc;
169 mArgV = argv;
Elliott Hughesd195e5a2011-04-13 15:39:37 -0700170
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800171 mArgLen = 0;
172 for (int i=0; i<argc; i++) {
173 mArgLen += strlen(argv[i]) + 1;
174 }
175 mArgLen--;
176
177 AppRuntime runtime;
Jeff Brownebed7d62011-05-16 17:08:42 -0700178 const char* argv0 = argv[0];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800179
180 // Process command line arguments
181 // ignore argv[0]
182 argc--;
183 argv++;
184
185 // Everything up to '--' or first non '-' arg goes to the vm
Elliott Hughesd195e5a2011-04-13 15:39:37 -0700186
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800187 int i = runtime.addVmArguments(argc, argv);
188
Jeff Brownebed7d62011-05-16 17:08:42 -0700189 // Parse runtime arguments. Stop at first unrecognized option.
190 bool zygote = false;
191 bool startSystemServer = false;
192 bool application = false;
193 const char* parentDir = NULL;
194 const char* niceName = NULL;
195 const char* className = NULL;
196 while (i < argc) {
197 const char* arg = argv[i++];
198 if (!parentDir) {
199 parentDir = arg;
200 } else if (strcmp(arg, "--zygote") == 0) {
201 zygote = true;
202 niceName = "zygote";
203 } else if (strcmp(arg, "--start-system-server") == 0) {
204 startSystemServer = true;
205 } else if (strcmp(arg, "--application") == 0) {
206 application = true;
207 } else if (strncmp(arg, "--nice-name=", 12) == 0) {
208 niceName = arg + 12;
209 } else {
210 className = arg;
211 break;
212 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800213 }
214
Jeff Brownebed7d62011-05-16 17:08:42 -0700215 if (niceName && *niceName) {
216 setArgv0(argv0, niceName);
217 set_process_name(niceName);
218 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800219
Jeff Brownebed7d62011-05-16 17:08:42 -0700220 runtime.mParentDir = parentDir;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800221
Jeff Brownebed7d62011-05-16 17:08:42 -0700222 if (zygote) {
223 runtime.start("com.android.internal.os.ZygoteInit",
224 startSystemServer ? "start-system-server" : "");
225 } else if (className) {
226 // Remainder of args get passed to startup class main()
227 runtime.mClassName = className;
228 runtime.mArgC = argc - i;
229 runtime.mArgV = argv + i;
230 runtime.start("com.android.internal.os.RuntimeInit",
231 application ? "application" : "tool");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800232 } else {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800233 fprintf(stderr, "Error: no class name or --zygote supplied.\n");
234 app_usage();
Brian Carlstromde6d1d82010-10-07 16:02:11 -0700235 LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800236 return 10;
237 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800238}