main_runtime.cpp revision 54b6cfa9a9e5b861a9930af873580d6dc20f773c
1// 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> 11#include <utils/IPCThreadState.h> 12#include <utils/ProcessState.h> 13#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} 515