blob: 4e90dab413eec558d4cd185e44e3ef0139c36f5d [file] [log] [blame]
Brian Carlstrom27ec9612011-09-19 20:20:38 -07001/*
2 * Main entry of app process.
3 *
4 * Starts the interpreted runtime, then starts up the application.
5 *
6 */
7
8#define LOG_TAG "appproc"
9
Brian Carlstrome10b6972011-09-26 13:49:03 -070010#include "class_loader.h"
11#include "jni_internal.h"
12#include "stringprintf.h"
13#include "thread.h"
14
Brian Carlstrom27ec9612011-09-19 20:20:38 -070015#include <binder/IPCThreadState.h>
16#include <binder/ProcessState.h>
17#include <utils/Log.h>
18#include <cutils/process_name.h>
19#include <cutils/memory.h>
20#include <android_runtime/AndroidRuntime.h>
21
22#include <stdio.h>
23#include <unistd.h>
24
25namespace android {
26
27void app_usage()
28{
29 fprintf(stderr,
30 "Usage: oat_process [java-options] cmd-dir start-class-name [options]\n");
31}
32
33class AppRuntime : public AndroidRuntime
34{
35public:
36 AppRuntime()
37 : mParentDir(NULL)
38 , mClassName(NULL)
39 , mClass(NULL)
40 , mArgC(0)
41 , mArgV(NULL)
42 {
43 }
44
45#if 0
46 // this appears to be unused
47 const char* getParentDir() const
48 {
49 return mParentDir;
50 }
51#endif
52
53 const char* getClassName() const
54 {
55 return mClassName;
56 }
57
58 virtual void onVmCreated(JNIEnv* env)
59 {
60 if (mClassName == NULL) {
61 return; // Zygote. Nothing to do here.
62 }
63
64 /*
65 * This is a little awkward because the JNI FindClass call uses the
66 * class loader associated with the native method we're executing in.
67 * If called in onStarted (from RuntimeInit.finishInit because we're
68 * launching "am", for example), FindClass would see that we're calling
69 * from a boot class' native method, and so wouldn't look for the class
70 * we're trying to look up in CLASSPATH. Unfortunately it needs to,
71 * because the "am" classes are not boot classes.
72 *
73 * The easiest fix is to call FindClass here, early on before we start
74 * executing boot class Java code and thereby deny ourselves access to
75 * non-boot classes.
76 */
77 char* slashClassName = toSlashClassName(mClassName);
78 mClass = env->FindClass(slashClassName);
79 if (mClass == NULL) {
Brian Carlstromdf143242011-10-10 18:05:34 -070080 LOG(FATAL) << "Could not find class: " << mClassName;
Brian Carlstrom27ec9612011-09-19 20:20:38 -070081 }
82 free(slashClassName);
83
84 mClass = reinterpret_cast<jclass>(env->NewGlobalRef(mClass));
85 }
86
87 virtual void onStarted()
88 {
89 sp<ProcessState> proc = ProcessState::self();
90 LOGV("App process: starting thread pool.\n");
91 proc->startThreadPool();
92
93 AndroidRuntime* ar = AndroidRuntime::getRuntime();
94 ar->callMain(mClassName, mClass, mArgC, mArgV);
95
96 IPCThreadState::self()->stopProcess();
97 }
98
99 virtual void onZygoteInit()
100 {
101 sp<ProcessState> proc = ProcessState::self();
102 LOGV("App process: starting thread pool.\n");
103 proc->startThreadPool();
104 }
105
106 virtual void onExit(int code)
107 {
108 if (mClassName == NULL) {
109 // if zygote
110 IPCThreadState::self()->stopProcess();
111 }
112
113 AndroidRuntime::onExit(code);
114 }
115
116
117 const char* mParentDir;
118 const char* mClassName;
119 jclass mClass;
120 int mArgC;
121 const char* const* mArgV;
122};
123
124}
125
126using namespace android;
127
128/*
129 * sets argv0 to as much of newArgv0 as will fit
130 */
131static void setArgv0(const char *argv0, const char *newArgv0)
132{
133 strlcpy(const_cast<char *>(argv0), newArgv0, strlen(argv0));
134}
135
Brian Carlstrom395520e2011-09-25 19:35:00 -0700136int main(int argc, const char* argv[])
Brian Carlstrom27ec9612011-09-19 20:20:38 -0700137{
138 // These are global variables in ProcessState.cpp
139 mArgC = argc;
140 mArgV = argv;
141
142 mArgLen = 0;
143 for (int i=0; i<argc; i++) {
144 mArgLen += strlen(argv[i]) + 1;
145 }
146 mArgLen--;
147
148 AppRuntime runtime;
149 const char* argv0 = argv[0];
150
151 // Process command line arguments
152 // ignore argv[0]
153 argc--;
154 argv++;
155
Brian Carlstrombc2f3e32011-09-22 17:16:54 -0700156 // ignore /system/bin/app_process when invoked via WrapperInit
157 if (strcmp(argv[0], "/system/bin/app_process") == 0) {
Brian Carlstrome10b6972011-09-26 13:49:03 -0700158 LOG(INFO) << "Removing /system/bin/app_process argument";
Brian Carlstrombc2f3e32011-09-22 17:16:54 -0700159 argc--;
160 argv++;
161 for (int i = 0; i < argc; i++) {
Brian Carlstrome10b6972011-09-26 13:49:03 -0700162 LOG(INFO) << StringPrintf("argv[%d]=%s", i, argv[i]);
Brian Carlstrombc2f3e32011-09-22 17:16:54 -0700163 }
164 }
165
Brian Carlstromaded5f72011-10-07 17:15:04 -0700166 // TODO: remove when we default the boot image
167 int oatArgc = argc + 1;
Brian Carlstrombc2f3e32011-09-22 17:16:54 -0700168 const char* oatArgv[oatArgc];
Brian Carlstrom4377a7e2011-10-04 13:19:49 -0700169 if (strcmp(argv[0], "-Ximage:/system/framework/boot.art") != 0) {
Brian Carlstromaded5f72011-10-07 17:15:04 -0700170 LOG(INFO) << "Adding image arguments";
Brian Carlstrom4377a7e2011-10-04 13:19:49 -0700171 oatArgv[0] = "-Ximage:/system/framework/boot.art";
Brian Carlstrombc2f3e32011-09-22 17:16:54 -0700172 memcpy(oatArgv + (oatArgc - argc), argv, argc * sizeof(*argv));
173 argv = oatArgv;
174 argc = oatArgc;
175 for (int i = 0; i < argc; i++) {
Brian Carlstrome10b6972011-09-26 13:49:03 -0700176 LOG(INFO) << StringPrintf("argv[%d]=%s", i, argv[i]);
Brian Carlstrombc2f3e32011-09-22 17:16:54 -0700177 }
178 }
179
180 // TODO: remove the heap arguments when implicit garbage collection enabled
Brian Carlstrome10b6972011-09-26 13:49:03 -0700181 LOG(INFO) << "Adding heap arguments";
Brian Carlstrombc2f3e32011-09-22 17:16:54 -0700182 int heapArgc = argc + 2;
183 const char* heapArgv[heapArgc];
184 heapArgv[0] = "-Xms64m";
185 heapArgv[1] = "-Xmx64m";
186 memcpy(heapArgv + (heapArgc - argc), argv, argc * sizeof(*argv));
187 argv = heapArgv;
188 argc = heapArgc;
189 for (int i = 0; i < argc; i++) {
Brian Carlstrome10b6972011-09-26 13:49:03 -0700190 LOG(INFO) << StringPrintf("argv[%d]=%s", i, argv[i]);
Brian Carlstrombc2f3e32011-09-22 17:16:54 -0700191 }
192
Brian Carlstrom395520e2011-09-25 19:35:00 -0700193 // TODO: change the system default to not perform preloading
Brian Carlstrome10b6972011-09-26 13:49:03 -0700194 LOG(INFO) << "Disabling preloading";
Brian Carlstrom395520e2011-09-25 19:35:00 -0700195 for (int i = 0; i < argc; i++) {
196 if (strcmp(argv[i], "preload") == 0) {
197 argv[i] = "nopreload";
198 break;
199 }
200 }
201 for (int i = 0; i < argc; i++) {
Brian Carlstrome10b6972011-09-26 13:49:03 -0700202 LOG(INFO) << StringPrintf("argv[%d]=%s", i, argv[i]);
Brian Carlstrom395520e2011-09-25 19:35:00 -0700203 }
204
Brian Carlstrom27ec9612011-09-19 20:20:38 -0700205 // Everything up to '--' or first non '-' arg goes to the vm
206
207 int i = runtime.addVmArguments(argc, argv);
208
209 // Parse runtime arguments. Stop at first unrecognized option.
210 bool zygote = false;
211 bool startSystemServer = false;
212 bool application = false;
213 const char* parentDir = NULL;
214 const char* niceName = NULL;
215 const char* className = NULL;
216 while (i < argc) {
217 const char* arg = argv[i++];
218 if (!parentDir) {
219 parentDir = arg;
220 } else if (strcmp(arg, "--zygote") == 0) {
221 zygote = true;
222 niceName = "zygote";
223 } else if (strcmp(arg, "--start-system-server") == 0) {
224 startSystemServer = true;
225 } else if (strcmp(arg, "--application") == 0) {
226 application = true;
227 } else if (strncmp(arg, "--nice-name=", 12) == 0) {
228 niceName = arg + 12;
229 } else {
230 className = arg;
231 break;
232 }
233 }
234
235 if (niceName && *niceName) {
236 setArgv0(argv0, niceName);
237 set_process_name(niceName);
238 }
239
240 runtime.mParentDir = parentDir;
241
242 if (zygote) {
243 runtime.start("com.android.internal.os.ZygoteInit",
244 startSystemServer ? "start-system-server" : "");
245 } else if (className) {
246 // Remainder of args get passed to startup class main()
247 runtime.mClassName = className;
248 runtime.mArgC = argc - i;
249 runtime.mArgV = argv + i;
250 runtime.start("com.android.internal.os.RuntimeInit",
251 application ? "application" : "tool");
252 } else {
253 fprintf(stderr, "Error: no class name or --zygote supplied.\n");
254 app_usage();
Brian Carlstrome10b6972011-09-26 13:49:03 -0700255 LOG(FATAL) << "oat_process: no class name or --zygote supplied.";
Brian Carlstrom27ec9612011-09-19 20:20:38 -0700256 return 10;
257 }
258}