blob: 718ea67e0142ca6e28f24c7bdfbfaf48430560a2 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001//
2// Copyright 2005 The Android Open Source Project
3//
4// Main entry point for runtime.
5//
6
7#include "ServiceManager.h"
8#include "SignalHandler.h"
9
10#include <utils.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/zygote.h>
15
16#include <cutils/properties.h>
17
18#include <private/utils/Static.h>
19
20#include <ui/ISurfaceComposer.h>
21
22#include <android_runtime/AndroidRuntime.h>
23
24#include <stdlib.h>
25#include <unistd.h>
26#include <fcntl.h>
27#include <stdio.h>
28#include <string.h>
29#include <getopt.h>
30#include <signal.h>
31#include <errno.h>
32#include <sys/stat.h>
33#include <linux/capability.h>
34#include <linux/ioctl.h>
35#ifdef HAVE_ANDROID_OS
36# include <linux/android_alarm.h>
37#endif
38
39#undef LOG_TAG
40#define LOG_TAG "runtime"
41
42static const char* ZYGOTE_ARGV[] = {
43 "--setuid=1000",
44 "--setgid=1000",
45 "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,3001,3002,3003",
46 /* CAP_SYS_TTY_CONFIG & CAP_SYS_RESOURCE & CAP_NET_BROADCAST &
47 * CAP_NET_ADMIN & CAP_NET_RAW & CAP_NET_BIND_SERVICE & CAP_KILL &
48 * CAP_SYS_BOOT
49 */
50 "--capabilities=88161312,88161312",
51 "--runtime-init",
52 "--nice-name=system_server",
53 "com.android.server.SystemServer"
54};
55
56using namespace android;
57
58extern "C" status_t system_init();
59
60enum {
61 SYSTEM_PROCESS_TAG = DEFAULT_PROCESS_TAG+1
62};
63
64extern Mutex gEventQMutex;
65extern Condition gEventQCondition;
66
67namespace android {
68
69extern status_t app_init(const char* className);
70extern void set_finish_init_func(void (*func)());
71
72
73/**
74 * This class is used to kill this process (runtime) when the system_server dies.
75 */
76class GrimReaper : public IBinder::DeathRecipient {
77public:
78 GrimReaper() { }
79
80 virtual void binderDied(const wp<IBinder>& who)
81 {
82 LOGI("Grim Reaper killing runtime...");
83 kill(getpid(), SIGKILL);
84 }
85};
86
87extern void QuickTests();
88
89/*
90 * Print usage info.
91 */
92static void usage(const char* argv0)
93{
94 fprintf(stderr,
95 "Usage: runtime [-g gamma] [-l logfile] [-n] [-s]\n"
96 " [-j app-component] [-v app-verb] [-d app-data]\n"
97 "\n"
98 "-l: File to send log messages to\n"
99 "-n: Don't print to stdout/stderr\n"
100 "-s: Force single-process mode\n"
101 "-j: Custom home app component name\n"
102 "-v: Custom home app intent verb\n"
103 "-d: Custom home app intent data\n"
104 );
105 exit(1);
106}
107
108// Selected application to run.
109static const char* gInitialApplication = NULL;
110static const char* gInitialVerb = NULL;
111static const char* gInitialData = NULL;
112
113static void writeStringToParcel(Parcel& parcel, const char* str)
114{
115 if (str) {
116 parcel.writeString16(String16(str));
117 } else {
118 parcel.writeString16(NULL, 0);
119 }
120}
121
122/*
123 * Starting point for program logic.
124 *
125 * Returns with an exit status code (0 on success, nonzero on error).
126 */
127static int run(sp<ProcessState>& proc)
128{
129 // Temporary hack to call startRunning() on the activity manager.
130 sp<IServiceManager> sm = defaultServiceManager();
131 sp<IBinder> am;
132 while ((am = sm->getService(String16("activity"))) == NULL) {
133 LOGI("Waiting for activity manager...");
134 }
135 Parcel data, reply;
136 // XXX Need to also supply a package name for this to work again.
137 // IActivityManager::getInterfaceDescriptor() is the token for invoking on this interface;
138 // hardcoding it here avoids having to link with the full Activity Manager library
139 data.writeInterfaceToken(String16("android.app.IActivityManager"));
140 writeStringToParcel(data, NULL);
141 writeStringToParcel(data, gInitialApplication);
142 writeStringToParcel(data, gInitialVerb);
143 writeStringToParcel(data, gInitialData);
144LOGI("run() sending FIRST_CALL_TRANSACTION to activity manager");
145 am->transact(IBinder::FIRST_CALL_TRANSACTION, data, &reply);
146
147 if (proc->supportsProcesses()) {
148 // Now we link to the Activity Manager waiting for it to die. If it does kill ourself.
149 // initd will restart this process and bring the system back up.
150 sp<GrimReaper> grim = new GrimReaper();
151 am->linkToDeath(grim, grim.get(), 0);
152
153 // Now join the thread pool. Note this is needed so that the message enqueued in the driver
154 // for the linkToDeath gets processed.
155 IPCThreadState::self()->joinThreadPool();
156 } else {
157 // Keep this thread running forever...
158 while (1) {
159 usleep(100000);
160 }
161 }
162 return 1;
163}
164
165
166}; // namespace android
167
168
169/*
170 * Post-system-process initialization.
171 *
172 * This function continues initialization after the system process
173 * has been initialized. It needs to be separate because the system
174 * initialization needs to care of starting the Android runtime if it is not
175 * running in its own process, which doesn't return until the runtime is
176 * being shut down. So it will call back to here from inside of Dalvik,
177 * to allow us to continue booting up.
178 */
179static void finish_system_init(sp<ProcessState>& proc)
180{
181 // If we are running multiprocess, we now need to have the
182 // thread pool started here. We don't do this in boot_init()
183 // because when running single process we need to start the
184 // thread pool after the Android runtime has been started (so
185 // the pool uses Dalvik threads).
186 if (proc->supportsProcesses()) {
187 proc->startThreadPool();
188 }
189}
190
191
192// This function can be used to enforce security to different
193// root contexts. For now, we just give every access.
194static bool contextChecker(
195 const String16& name, const sp<IBinder>& caller, void* userData)
196{
197 return true;
198}
199
200/*
201 * Initialization of boot services.
202 *
203 * This is where we perform initialization of all of our low-level
204 * boot services. Most importantly, here we become the context
205 * manager and use that to publish the service manager that will provide
206 * access to all other services.
207 */
208static void boot_init()
209{
210 LOGI("Entered boot_init()!\n");
211
212 sp<ProcessState> proc(ProcessState::self());
213 LOGD("ProcessState: %p\n", proc.get());
214 proc->becomeContextManager(contextChecker, NULL);
215
216 if (proc->supportsProcesses()) {
217 LOGI("Binder driver opened. Multiprocess enabled.\n");
218 } else {
219 LOGI("Binder driver not found. Processes not supported.\n");
220 }
221
222 sp<BServiceManager> sm = new BServiceManager;
223 proc->setContextObject(sm);
224}
225
226/*
227 * Redirect stdin/stdout/stderr to /dev/null.
228 */
229static void redirectStdFds(void)
230{
231 int fd = open("/dev/null", O_RDWR, 0);
232 if (fd < 0) {
233 LOGW("Unable to open /dev/null: %s\n", strerror(errno));
234 } else {
235 dup2(fd, 0);
236 dup2(fd, 1);
237 dup2(fd, 2);
238 close(fd);
239 }
240}
241
242static int hasDir(const char* dir)
243{
244 struct stat s;
245 int res = stat(dir, &s);
246 if (res == 0) {
247 return S_ISDIR(s.st_mode);
248 }
249 return 0;
250}
251
252static void validateTime()
253{
254#if HAVE_ANDROID_OS
255 int fd;
256 int res;
257 time_t min_time = 1167652800; // jan 1 2007, type 'date -ud "1/1 12:00" +%s' to get value for current year
258 struct timespec ts;
259
260 fd = open("/dev/alarm", O_RDWR);
261 if(fd < 0) {
262 LOGW("Unable to open alarm driver: %s\n", strerror(errno));
263 return;
264 }
265 res = ioctl(fd, ANDROID_ALARM_GET_TIME(ANDROID_ALARM_RTC_WAKEUP), &ts);
266 if(res < 0) {
267 LOGW("Unable to read rtc, %s\n", strerror(errno));
268 }
269 else if(ts.tv_sec >= min_time) {
270 goto done;
271 }
272 LOGW("Invalid time detected, %ld set to %ld\n", ts.tv_sec, min_time);
273 ts.tv_sec = min_time;
274 ts.tv_nsec = 0;
275 res = ioctl(fd, ANDROID_ALARM_SET_RTC, &ts);
276 if(res < 0) {
277 LOGW("Unable to set rtc to %ld: %s\n", ts.tv_sec, strerror(errno));
278 }
279done:
280 close(fd);
281#endif
282}
283
284#ifndef HAVE_ANDROID_OS
285class QuickRuntime : public AndroidRuntime
286{
287public:
288 QuickRuntime() {}
289
290 virtual void onStarted()
291 {
292 printf("QuickRuntime: onStarted\n");
293 }
294};
295#endif
296
297static status_t start_process(const char* name);
298
299static void restart_me(pid_t child, void* userData)
300{
301 start_process((const char*)userData);
302}
303
304static status_t start_process(const char* name)
305{
306 String8 path(name);
307 Vector<const char*> args;
308 String8 leaf(path.getPathLeaf());
309 String8 parentDir(path.getPathDir());
310 args.insertAt(leaf.string(), 0);
311 args.add(parentDir.string());
312 args.add(NULL);
313 pid_t child = fork();
314 if (child < 0) {
315 status_t err = errno;
316 LOGE("*** fork of child %s failed: %s", leaf.string(), strerror(err));
317 return -errno;
318 } else if (child == 0) {
319 LOGI("Executing: %s", path.string());
320 execv(path.string(), const_cast<char**>(args.array()));
321 int err = errno;
322 LOGE("Exec failed: %s\n", strerror(err));
323 _exit(err);
324 } else {
325 SignalHandler::setChildHandler(child, DEFAULT_PROCESS_TAG,
326 restart_me, (void*)name);
327 }
328 return -errno;
329}
330
331/*
332 * Application entry point.
333 *
334 * Parse arguments, set some values, and pass control off to Run().
335 *
336 * This is redefined to "SDL_main" on SDL simulator builds, and
337 * "runtime_main" on wxWidgets builds.
338 */
339extern "C"
340int main(int argc, char* const argv[])
341{
342 bool singleProcess = false;
343 const char* logFile = NULL;
344 int ic;
345 int result = 1;
346 pid_t systemPid;
347
348 sp<ProcessState> proc;
349
350#ifndef HAVE_ANDROID_OS
351 /* Set stdout/stderr to unbuffered for MinGW/MSYS. */
352 //setvbuf(stdout, NULL, _IONBF, 0);
353 //setvbuf(stderr, NULL, _IONBF, 0);
354
355 LOGI("commandline args:\n");
356 for (int i = 0; i < argc; i++)
357 LOGI(" %2d: '%s'\n", i, argv[i]);
358#endif
359
360 while (1) {
361 ic = getopt(argc, argv, "g:j:v:d:l:ns");
362 if (ic < 0)
363 break;
364
365 switch (ic) {
366 case 'g':
367 break;
368 case 'j':
369 gInitialApplication = optarg;
370 break;
371 case 'v':
372 gInitialVerb = optarg;
373 break;
374 case 'd':
375 gInitialData = optarg;
376 break;
377 case 'l':
378 logFile = optarg;
379 break;
380 case 'n':
381 redirectStdFds();
382 break;
383 case 's':
384 singleProcess = true;
385 break;
386 case '?':
387 default:
388 LOGE("runtime: unrecognized flag -%c\n", ic);
389 usage(argv[0]);
390 break;
391 }
392 }
393 if (optind < argc) {
394 LOGE("runtime: extra stuff: %s\n", argv[optind]);
395 usage(argv[0]);
396 }
397
398 if (singleProcess) {
399 ProcessState::setSingleProcess(true);
400 }
401
402 if (logFile != NULL) {
403 android_logToFile(NULL, logFile);
404 }
405
406 /*
407 * Set up ANDROID_* environment variables.
408 *
409 * TODO: the use of $ANDROID_PRODUCT_OUT will go away soon.
410 */
411 static const char* kSystemDir = "/system";
412 static const char* kDataDir = "/data";
413 static const char* kAppSubdir = "/app";
414 const char* out = NULL;
415#ifndef HAVE_ANDROID_OS
416 //out = getenv("ANDROID_PRODUCT_OUT");
417#endif
418 if (out == NULL)
419 out = "";
420
421 char* systemDir = (char*) malloc(strlen(out) + strlen(kSystemDir) +1);
422 char* dataDir = (char*) malloc(strlen(out) + strlen(kDataDir) +1);
423
424 sprintf(systemDir, "%s%s", out, kSystemDir);
425 sprintf(dataDir, "%s%s", out, kDataDir);
426 setenv("ANDROID_ROOT", systemDir, 1);
427 setenv("ANDROID_DATA", dataDir, 1);
428
429 char* assetDir = (char*) malloc(strlen(systemDir) + strlen(kAppSubdir) +1);
430 sprintf(assetDir, "%s%s", systemDir, kAppSubdir);
431
432 LOGI("Startup: sys='%s' asset='%s' data='%s'\n",
433 systemDir, assetDir, dataDir);
434 free(systemDir);
435 free(dataDir);
436
437#ifdef HAVE_ANDROID_OS
438 /* set up a process group for easier killing on the device */
439 setpgid(0, getpid());
440#endif
441
442 // Change to asset dir. This is only necessary if we've changed to
443 // a different directory, but there's little harm in doing it regardless.
444 //
445 // Expecting assets to live in the current dir is not a great idea,
446 // because some of our code or one of our libraries could change the
447 // directory out from under us. Preserve the behavior for now.
448 if (chdir(assetDir) != 0) {
449 LOGW("WARNING: could not change dir to '%s': %s\n",
450 assetDir, strerror(errno));
451 }
452 free(assetDir);
453
454#if 0
455 // Hack to keep libc from beating the filesystem to death. It's
456 // hitting /etc/localtime frequently,
457 //
458 // This statement locks us into Pacific time. We could do better,
459 // but there's not much point until we're sure that the library
460 // can't be changed to do more along the lines of what we want.
461#ifndef XP_WIN
462 setenv("TZ", "PST+8PDT,M4.1.0/2,M10.5.0/2", true);
463#endif
464#endif
465
466 /* track our progress through the boot sequence */
467 const int LOG_BOOT_PROGRESS_START = 3000;
468 LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START,
469 ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
470
471 validateTime();
472
473 proc = ProcessState::self();
474
475 boot_init();
476
477 /* If we are in multiprocess mode, have zygote spawn the system
478 * server process and call system_init(). If we are running in
479 * single process mode just call system_init() directly.
480 */
481 if (proc->supportsProcesses()) {
482 // If stdio logging is on, system_server should not inherit our stdio
483 // The dalvikvm instance will copy stdio to the log on its own
484 char propBuf[PROPERTY_VALUE_MAX];
485 bool logStdio = false;
486 property_get("log.redirect-stdio", propBuf, "");
487 logStdio = (strcmp(propBuf, "true") == 0);
488
489 zygote_run_oneshot((int)(!logStdio),
490 sizeof(ZYGOTE_ARGV) / sizeof(ZYGOTE_ARGV[0]),
491 ZYGOTE_ARGV);
492
493 //start_process("/system/bin/mediaserver");
494
495 } else {
496#ifndef HAVE_ANDROID_OS
497 QuickRuntime* runt = new QuickRuntime();
498 runt->start("com/android/server/SystemServer",
499 false /* spontaneously fork system server from zygote */);
500#endif
501 }
502
503 //printf("+++ post-zygote\n");
504
505 finish_system_init(proc);
506 run(proc);
507
508bail:
509 if (proc != NULL) {
510 proc->setContextObject(NULL);
511 }
512
513 return 0;
514}