blob: f58f26112115899b1a0de4f31679788b37b75a8e [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.internal.os;
18
19import android.app.ActivityManagerNative;
Dan Egnorb7f03672009-12-09 16:22:32 -080020import android.app.ApplicationErrorReport;
Dan Egnorb7f03672009-12-09 16:22:32 -080021import android.os.Build;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080022import android.os.Debug;
23import android.os.IBinder;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080024import android.os.Process;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080025import android.os.SystemProperties;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080026import android.util.Config;
27import android.util.Log;
Dianne Hackbornc9421ba2010-03-11 22:23:46 -080028import android.util.Slog;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080029
30import com.android.internal.logging.AndroidConfig;
31
32import dalvik.system.VMRuntime;
33
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080034import java.lang.reflect.Method;
35import java.lang.reflect.Modifier;
36import java.util.concurrent.atomic.AtomicInteger;
37import java.util.logging.LogManager;
38import java.util.TimeZone;
39
40import org.apache.harmony.luni.internal.util.TimezoneGetter;
41
42/**
43 * Main entry point for runtime initialization. Not for
44 * public consumption.
45 * @hide
46 */
47public class RuntimeInit {
48 private final static String TAG = "AndroidRuntime";
49
50 /** true if commonInit() has been called */
51 private static boolean initialized;
52
Dan Egnor60d87622009-12-16 16:32:58 -080053 private static IBinder mApplicationObject;
54
55 private static volatile boolean mCrashing = false;
56
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080057 /**
58 * Use this to log a message when a thread exits due to an uncaught
59 * exception. The framework catches these for the main threads, so
60 * this should only matter for threads created by applications.
61 */
62 private static class UncaughtHandler implements Thread.UncaughtExceptionHandler {
63 public void uncaughtException(Thread t, Throwable e) {
64 try {
Dan Egnor60d87622009-12-16 16:32:58 -080065 // Don't re-enter -- avoid infinite loops if crash-reporting crashes.
66 if (mCrashing) return;
67 mCrashing = true;
68
69 if (mApplicationObject == null) {
Dianne Hackbornc9421ba2010-03-11 22:23:46 -080070 Slog.e(TAG, "*** FATAL EXCEPTION IN SYSTEM PROCESS: " + t.getName(), e);
Dan Egnor60d87622009-12-16 16:32:58 -080071 } else {
Dianne Hackbornc9421ba2010-03-11 22:23:46 -080072 Slog.e(TAG, "FATAL EXCEPTION: " + t.getName(), e);
Dan Egnor60d87622009-12-16 16:32:58 -080073 }
74
75 // Bring up crash dialog, wait for it to be dismissed
76 ActivityManagerNative.getDefault().handleApplicationCrash(
77 mApplicationObject, new ApplicationErrorReport.CrashInfo(e));
78 } catch (Throwable t2) {
79 try {
Dianne Hackbornc9421ba2010-03-11 22:23:46 -080080 Slog.e(TAG, "Error reporting crash", t2);
Dan Egnor60d87622009-12-16 16:32:58 -080081 } catch (Throwable t3) {
Dianne Hackbornc9421ba2010-03-11 22:23:46 -080082 // Even Slog.e() fails! Oh well.
Dan Egnor60d87622009-12-16 16:32:58 -080083 }
84 } finally {
85 // Try everything to make sure this process goes away.
86 Process.killProcess(Process.myPid());
87 System.exit(10);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080088 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080089 }
90 }
91
92 private static final void commonInit() {
Dianne Hackbornc9421ba2010-03-11 22:23:46 -080093 if (Config.LOGV) Slog.d(TAG, "Entered RuntimeInit!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080094
95 /* set default handler; this applies to all threads in the VM */
96 Thread.setDefaultUncaughtExceptionHandler(new UncaughtHandler());
97
98 int hasQwerty = getQwertyKeyboard();
Bob Leee5408332009-09-04 18:31:17 -070099
Dianne Hackbornc9421ba2010-03-11 22:23:46 -0800100 if (Config.LOGV) Slog.d(TAG, ">>>>> qwerty keyboard = " + hasQwerty);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800101 if (hasQwerty == 1) {
102 System.setProperty("qwerty", "1");
103 }
104
105 /*
106 * Install a TimezoneGetter subclass for ZoneInfo.db
107 */
108 TimezoneGetter.setInstance(new TimezoneGetter() {
109 @Override
110 public String getId() {
111 return SystemProperties.get("persist.sys.timezone");
112 }
113 });
114 TimeZone.setDefault(null);
115
116 /*
117 * Sets handler for java.util.logging to use Android log facilities.
118 * The odd "new instance-and-then-throw-away" is a mirror of how
119 * the "java.util.logging.config.class" system property works. We
120 * can't use the system property here since the logger has almost
121 * certainly already been initialized.
122 */
123 LogManager.getLogManager().reset();
124 new AndroidConfig();
125
126 /*
Jesse Wilsond0f80d42009-09-18 18:06:43 -0700127 * Sets the default HTTP User-Agent used by HttpURLConnection.
128 */
129 String userAgent = getDefaultUserAgent();
130 System.setProperty("http.agent", userAgent);
131
132 /*
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800133 * If we're running in an emulator launched with "-trace", put the
134 * VM into emulator trace profiling mode so that the user can hit
135 * F9/F10 at any time to capture traces. This has performance
136 * consequences, so it's not something you want to do always.
137 */
138 String trace = SystemProperties.get("ro.kernel.android.tracing");
139 if (trace.equals("1")) {
Dianne Hackbornc9421ba2010-03-11 22:23:46 -0800140 Slog.i(TAG, "NOTE: emulator trace profiling enabled");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800141 Debug.enableEmulatorTraceOutput();
142 }
143
144 initialized = true;
145 }
146
147 /**
Jesse Wilsond0f80d42009-09-18 18:06:43 -0700148 * Returns an HTTP user agent of the form
149 * "Dalvik/1.1.0 (Linux; U; Android Eclair Build/MASTER)".
150 */
151 private static String getDefaultUserAgent() {
152 StringBuilder result = new StringBuilder(64);
153 result.append("Dalvik/");
154 result.append(System.getProperty("java.vm.version")); // such as 1.1.0
155 result.append(" (Linux; U; Android ");
156
157 String version = Build.VERSION.RELEASE; // "1.0" or "3.4b5"
158 result.append(version.length() > 0 ? version : "1.0");
159
160 // add the model for the release build
161 if ("REL".equals(Build.VERSION.CODENAME)) {
162 String model = Build.MODEL;
163 if (model.length() > 0) {
164 result.append("; ");
165 result.append(model);
166 }
167 }
168 String id = Build.ID; // "MASTER" or "M4-rc20"
169 if (id.length() > 0) {
170 result.append(" Build/");
171 result.append(id);
172 }
173 result.append(")");
174 return result.toString();
175 }
176
177 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800178 * Invokes a static "main(argv[]) method on class "className".
179 * Converts various failing exceptions into RuntimeExceptions, with
180 * the assumption that they will then cause the VM instance to exit.
181 *
182 * @param className Fully-qualified class name
183 * @param argv Argument vector for main()
184 */
Bob Leee5408332009-09-04 18:31:17 -0700185 private static void invokeStaticMain(String className, String[] argv)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800186 throws ZygoteInit.MethodAndArgsCaller {
Bob Leee5408332009-09-04 18:31:17 -0700187
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800188 // We want to be fairly aggressive about heap utilization, to avoid
189 // holding on to a lot of memory that isn't needed.
190 VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
Bob Leee5408332009-09-04 18:31:17 -0700191
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800192 Class<?> cl;
193
194 try {
195 cl = Class.forName(className);
196 } catch (ClassNotFoundException ex) {
197 throw new RuntimeException(
198 "Missing class when invoking static main " + className,
199 ex);
200 }
201
202 Method m;
203 try {
204 m = cl.getMethod("main", new Class[] { String[].class });
205 } catch (NoSuchMethodException ex) {
206 throw new RuntimeException(
207 "Missing static main on " + className, ex);
208 } catch (SecurityException ex) {
209 throw new RuntimeException(
210 "Problem getting static main on " + className, ex);
211 }
212
213 int modifiers = m.getModifiers();
214 if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
215 throw new RuntimeException(
216 "Main method is not public and static on " + className);
217 }
218
219 /*
220 * This throw gets caught in ZygoteInit.main(), which responds
221 * by invoking the exception's run() method. This arrangement
222 * clears up all the stack frames that were required in setting
223 * up the process.
224 */
225 throw new ZygoteInit.MethodAndArgsCaller(m, argv);
226 }
227
228 public static final void main(String[] argv) {
229 commonInit();
Bob Leee5408332009-09-04 18:31:17 -0700230
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800231 /*
232 * Now that we're running in interpreted code, call back into native code
233 * to run the system.
234 */
235 finishInit();
236
Dianne Hackbornc9421ba2010-03-11 22:23:46 -0800237 if (Config.LOGV) Slog.d(TAG, "Leaving RuntimeInit!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800238 }
Bob Leee5408332009-09-04 18:31:17 -0700239
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800240 public static final native void finishInit();
241
242 /**
243 * The main function called when started through the zygote process. This
244 * could be unified with main(), if the native code in finishInit()
245 * were rationalized with Zygote startup.<p>
246 *
247 * Current recognized args:
248 * <ul>
249 * <li> --nice-name=<i>nice name to appear in ps</i>
250 * <li> <code> [--] &lt;start class name&gt; &lt;args&gt;
251 * </ul>
252 *
253 * @param argv arg strings
254 */
255 public static final void zygoteInit(String[] argv)
256 throws ZygoteInit.MethodAndArgsCaller {
257 // TODO: Doing this here works, but it seems kind of arbitrary. Find
258 // a better place. The goal is to set it up for applications, but not
259 // tools like am.
Jesse Wilson8718a512010-10-15 13:45:14 -0700260 System.out.close();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800261 System.setOut(new AndroidPrintStream(Log.INFO, "System.out"));
Jesse Wilson8718a512010-10-15 13:45:14 -0700262 System.err.close();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800263 System.setErr(new AndroidPrintStream(Log.WARN, "System.err"));
264
265 commonInit();
266 zygoteInitNative();
267
268 int curArg = 0;
269 for ( /* curArg */ ; curArg < argv.length; curArg++) {
270 String arg = argv[curArg];
271
272 if (arg.equals("--")) {
273 curArg++;
274 break;
275 } else if (!arg.startsWith("--")) {
276 break;
277 } else if (arg.startsWith("--nice-name=")) {
278 String niceName = arg.substring(arg.indexOf('=') + 1);
279 Process.setArgV0(niceName);
280 }
281 }
282
283 if (curArg == argv.length) {
Dianne Hackbornc9421ba2010-03-11 22:23:46 -0800284 Slog.e(TAG, "Missing classname argument to RuntimeInit!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800285 // let the process exit
286 return;
287 }
288
289 // Remaining arguments are passed to the start class's static main
Bob Leee5408332009-09-04 18:31:17 -0700290
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800291 String startClass = argv[curArg++];
292 String[] startArgs = new String[argv.length - curArg];
293
294 System.arraycopy(argv, curArg, startArgs, 0, startArgs.length);
295 invokeStaticMain(startClass, startArgs);
296 }
297
298 public static final native void zygoteInitNative();
Bob Leee5408332009-09-04 18:31:17 -0700299
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800300 /**
301 * Returns 1 if the computer is on. If the computer isn't on, the value returned by this method is undefined.
302 */
303 public static final native int isComputerOn();
304
305 /**
Bob Leee5408332009-09-04 18:31:17 -0700306 * Turns the computer on if the computer is off. If the computer is on, the behavior of this method is undefined.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800307 */
308 public static final native void turnComputerOn();
309
310 /**
Bob Leee5408332009-09-04 18:31:17 -0700311 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800312 * @return 1 if the device has a qwerty keyboard
313 */
314 public static native int getQwertyKeyboard();
Bob Leee5408332009-09-04 18:31:17 -0700315
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800316 /**
Dan Egnor60d87622009-12-16 16:32:58 -0800317 * Report a serious error in the current process. May or may not cause
318 * the process to terminate (depends on system settings).
Bob Leee5408332009-09-04 18:31:17 -0700319 *
Dan Egnor60d87622009-12-16 16:32:58 -0800320 * @param tag to record with the error
321 * @param t exception describing the error site and conditions
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800322 */
Dan Egnor60d87622009-12-16 16:32:58 -0800323 public static void wtf(String tag, Throwable t) {
324 try {
325 if (ActivityManagerNative.getDefault().handleApplicationWtf(
326 mApplicationObject, tag, new ApplicationErrorReport.CrashInfo(t))) {
327 // The Activity Manager has already written us off -- now exit.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800328 Process.killProcess(Process.myPid());
329 System.exit(10);
330 }
Dan Egnor60d87622009-12-16 16:32:58 -0800331 } catch (Throwable t2) {
Dianne Hackbornc9421ba2010-03-11 22:23:46 -0800332 Slog.e(TAG, "Error reporting WTF", t2);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800333 }
334 }
335
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800336 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800337 * Set the object identifying this application/process, for reporting VM
338 * errors.
339 */
340 public static final void setApplicationObject(IBinder app) {
341 mApplicationObject = app;
342 }
343
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700344 public static final IBinder getApplicationObject() {
345 return mApplicationObject;
346 }
347
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800348 /**
349 * Enable debugging features.
350 */
351 static {
352 // Register handlers for DDM messages.
353 android.ddm.DdmRegister.registerHandlers();
354 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800355}