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 22 void app_usage() 23 { 24 fprintf(stderr, 25 "Usage: app_process [java-options] cmd-dir start-class-name [options]\n"); 26 } 27 28 status_t app_init(const char* className, int argc, const char* const argv[]) 29 { 30 LOGV("Entered app_init()!\n"); 31 32 AndroidRuntime* jr = AndroidRuntime::getRuntime(); 33 jr->callMain(className, argc, argv); 34 35 LOGV("Exiting app_init()!\n"); 36 return NO_ERROR; 37 } 38 39 class AppRuntime : public AndroidRuntime 40 { 41 public: 42 AppRuntime() 43 : mParentDir(NULL) 44 , mClassName(NULL) 45 , mArgC(0) 46 , mArgV(NULL) 47 { 48 } 49 50 #if 0 51 // this appears to be unused 52 const char* getParentDir() const 53 { 54 return mParentDir; 55 } 56 #endif 57 58 const char* getClassName() const 59 { 60 return mClassName; 61 } 62 63 virtual void onStarted() 64 { 65 sp<ProcessState> proc = ProcessState::self(); 66 if (proc->supportsProcesses()) { 67 LOGV("App process: starting thread pool.\n"); 68 proc->startThreadPool(); 69 } 70 71 app_init(mClassName, mArgC, mArgV); 72 73 if (ProcessState::self()->supportsProcesses()) { 74 IPCThreadState::self()->stopProcess(); 75 } 76 } 77 78 virtual void onZygoteInit() 79 { 80 sp<ProcessState> proc = ProcessState::self(); 81 if (proc->supportsProcesses()) { 82 LOGV("App process: starting thread pool.\n"); 83 proc->startThreadPool(); 84 } 85 } 86 87 virtual void onExit(int code) 88 { 89 if (mClassName == NULL) { 90 // if zygote 91 if (ProcessState::self()->supportsProcesses()) { 92 IPCThreadState::self()->stopProcess(); 93 } 94 } 95 96 AndroidRuntime::onExit(code); 97 } 98 99 100 const char* mParentDir; 101 const char* mClassName; 102 int mArgC; 103 const char* const* mArgV; 104 }; 105 106 } 107 108 using namespace android; 109 110 /* 111 * sets argv0 to as much of newArgv0 as will fit 112 */ 113 static void setArgv0(const char *argv0, const char *newArgv0) 114 { 115 strlcpy(const_cast<char *>(argv0), newArgv0, strlen(argv0)); 116 } 117 118 int main(int argc, const char* const argv[]) 119 { 120 // These are global variables in ProcessState.cpp 121 mArgC = argc; 122 mArgV = argv; 123 124 mArgLen = 0; 125 for (int i=0; i<argc; i++) { 126 mArgLen += strlen(argv[i]) + 1; 127 } 128 mArgLen--; 129 130 AppRuntime runtime; 131 const char *arg; 132 const char *argv0; 133 134 argv0 = argv[0]; 135 136 // Process command line arguments 137 // ignore argv[0] 138 argc--; 139 argv++; 140 141 // Everything up to '--' or first non '-' arg goes to the vm 142 143 int i = runtime.addVmArguments(argc, argv); 144 145 // Next arg is parent directory 146 if (i < argc) { 147 runtime.mParentDir = argv[i++]; 148 } 149 150 // Next arg is startup classname or "--zygote" 151 if (i < argc) { 152 arg = argv[i++]; 153 if (0 == strcmp("--zygote", arg)) { 154 bool startSystemServer = (i < argc) ? 155 strcmp(argv[i], "--start-system-server") == 0 : false; 156 setArgv0(argv0, "zygote"); 157 set_process_name("zygote"); 158 runtime.start("com.android.internal.os.ZygoteInit", 159 startSystemServer); 160 } else { 161 set_process_name(argv0); 162 163 runtime.mClassName = arg; 164 165 // Remainder of args get passed to startup class main() 166 runtime.mArgC = argc-i; 167 runtime.mArgV = argv+i; 168 169 LOGV("App process is starting with pid=%d, class=%s.\n", 170 getpid(), runtime.getClassName()); 171 runtime.start(); 172 } 173 } else { 174 LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied."); 175 fprintf(stderr, "Error: no class name or --zygote supplied.\n"); 176 app_usage(); 177 return 10; 178 } 179 180 } 181