• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
10 #include <binder/IPCThreadState.h>
11 #include <binder/ProcessState.h>
12 #include <utils/Log.h>
13 #include <cutils/process_name.h>
14 #include <cutils/memory.h>
15 #include <android_runtime/AndroidRuntime.h>
16 
17 #include <stdio.h>
18 #include <unistd.h>
19 
20 namespace android {
21 
app_usage()22 void app_usage()
23 {
24     fprintf(stderr,
25         "Usage: app_process [java-options] cmd-dir start-class-name [options]\n");
26 }
27 
28 class AppRuntime : public AndroidRuntime
29 {
30 public:
AppRuntime()31     AppRuntime()
32         : mParentDir(NULL)
33         , mClassName(NULL)
34         , mClass(NULL)
35         , mArgC(0)
36         , mArgV(NULL)
37     {
38     }
39 
40 #if 0
41     // this appears to be unused
42     const char* getParentDir() const
43     {
44         return mParentDir;
45     }
46 #endif
47 
getClassName() const48     const char* getClassName() const
49     {
50         return mClassName;
51     }
52 
onVmCreated(JNIEnv * env)53     virtual void onVmCreated(JNIEnv* env)
54     {
55         if (mClassName == NULL) {
56             return; // Zygote. Nothing to do here.
57         }
58 
59         /*
60          * This is a little awkward because the JNI FindClass call uses the
61          * class loader associated with the native method we're executing in.
62          * If called in onStarted (from RuntimeInit.finishInit because we're
63          * launching "am", for example), FindClass would see that we're calling
64          * from a boot class' native method, and so wouldn't look for the class
65          * we're trying to look up in CLASSPATH. Unfortunately it needs to,
66          * because the "am" classes are not boot classes.
67          *
68          * The easiest fix is to call FindClass here, early on before we start
69          * executing boot class Java code and thereby deny ourselves access to
70          * non-boot classes.
71          */
72         char* slashClassName = toSlashClassName(mClassName);
73         mClass = env->FindClass(slashClassName);
74         if (mClass == NULL) {
75             LOGE("ERROR: could not find class '%s'\n", mClassName);
76         }
77         free(slashClassName);
78 
79         mClass = reinterpret_cast<jclass>(env->NewGlobalRef(mClass));
80     }
81 
onStarted()82     virtual void onStarted()
83     {
84         sp<ProcessState> proc = ProcessState::self();
85         LOGV("App process: starting thread pool.\n");
86         proc->startThreadPool();
87 
88         AndroidRuntime* ar = AndroidRuntime::getRuntime();
89         ar->callMain(mClassName, mClass, mArgC, mArgV);
90 
91         IPCThreadState::self()->stopProcess();
92     }
93 
onZygoteInit()94     virtual void onZygoteInit()
95     {
96         sp<ProcessState> proc = ProcessState::self();
97         LOGV("App process: starting thread pool.\n");
98         proc->startThreadPool();
99     }
100 
onExit(int code)101     virtual void onExit(int code)
102     {
103         if (mClassName == NULL) {
104             // if zygote
105             IPCThreadState::self()->stopProcess();
106         }
107 
108         AndroidRuntime::onExit(code);
109     }
110 
111 
112     const char* mParentDir;
113     const char* mClassName;
114     jclass mClass;
115     int mArgC;
116     const char* const* mArgV;
117 };
118 
119 }
120 
121 using namespace android;
122 
123 /*
124  * sets argv0 to as much of newArgv0 as will fit
125  */
setArgv0(const char * argv0,const char * newArgv0)126 static void setArgv0(const char *argv0, const char *newArgv0)
127 {
128     strlcpy(const_cast<char *>(argv0), newArgv0, strlen(argv0));
129 }
130 
main(int argc,const char * const argv[])131 int main(int argc, const char* const argv[])
132 {
133     // These are global variables in ProcessState.cpp
134     mArgC = argc;
135     mArgV = argv;
136 
137     mArgLen = 0;
138     for (int i=0; i<argc; i++) {
139         mArgLen += strlen(argv[i]) + 1;
140     }
141     mArgLen--;
142 
143     AppRuntime runtime;
144     const char* argv0 = argv[0];
145 
146     // Process command line arguments
147     // ignore argv[0]
148     argc--;
149     argv++;
150 
151     // Everything up to '--' or first non '-' arg goes to the vm
152 
153     int i = runtime.addVmArguments(argc, argv);
154 
155     // Parse runtime arguments.  Stop at first unrecognized option.
156     bool zygote = false;
157     bool startSystemServer = false;
158     bool application = false;
159     const char* parentDir = NULL;
160     const char* niceName = NULL;
161     const char* className = NULL;
162     while (i < argc) {
163         const char* arg = argv[i++];
164         if (!parentDir) {
165             parentDir = arg;
166         } else if (strcmp(arg, "--zygote") == 0) {
167             zygote = true;
168             niceName = "zygote";
169         } else if (strcmp(arg, "--start-system-server") == 0) {
170             startSystemServer = true;
171         } else if (strcmp(arg, "--application") == 0) {
172             application = true;
173         } else if (strncmp(arg, "--nice-name=", 12) == 0) {
174             niceName = arg + 12;
175         } else {
176             className = arg;
177             break;
178         }
179     }
180 
181     if (niceName && *niceName) {
182         setArgv0(argv0, niceName);
183         set_process_name(niceName);
184     }
185 
186     runtime.mParentDir = parentDir;
187 
188     if (zygote) {
189         runtime.start("com.android.internal.os.ZygoteInit",
190                 startSystemServer ? "start-system-server" : "");
191     } else if (className) {
192         // Remainder of args get passed to startup class main()
193         runtime.mClassName = className;
194         runtime.mArgC = argc - i;
195         runtime.mArgV = argv + i;
196         runtime.start("com.android.internal.os.RuntimeInit",
197                 application ? "application" : "tool");
198     } else {
199         fprintf(stderr, "Error: no class name or --zygote supplied.\n");
200         app_usage();
201         LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
202         return 10;
203     }
204 }
205