blob: 66475e445efa3df9e0c94375a9b947cf2ab89522 [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
Sudheer Shankadc589ac2016-11-10 15:30:17 -080019import android.app.ActivityManager;
Eric Rowe35980b22013-09-03 10:51:15 -070020import android.app.ActivityThread;
Dan Egnorb7f03672009-12-09 16:22:32 -080021import android.app.ApplicationErrorReport;
Dan Egnorb7f03672009-12-09 16:22:32 -080022import android.os.Build;
Jeff Sharkeyf8880562016-02-26 13:03:01 -070023import android.os.DeadObjectException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080024import android.os.Debug;
25import android.os.IBinder;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080026import android.os.Process;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080027import android.os.SystemProperties;
Narayan Kamathfbb32f62015-06-12 15:34:35 +010028import android.os.Trace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080029import android.util.Log;
Dianne Hackbornc9421ba2010-03-11 22:23:46 -080030import android.util.Slog;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080031import com.android.internal.logging.AndroidConfig;
Jesse Wilson8568db52011-06-28 19:06:31 -070032import com.android.server.NetworkManagementSocketTagger;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080033import dalvik.system.VMRuntime;
Narayan Kamathac0b4be2017-07-05 14:45:38 +010034import java.lang.reflect.InvocationTargetException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080035import java.lang.reflect.Method;
36import java.lang.reflect.Modifier;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080037import java.util.TimeZone;
Jesse Wilson8568db52011-06-28 19:06:31 -070038import java.util.logging.LogManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080039import org.apache.harmony.luni.internal.util.TimezoneGetter;
40
41/**
42 * Main entry point for runtime initialization. Not for
43 * public consumption.
44 * @hide
45 */
46public class RuntimeInit {
Andreas Gampe76d4fc82017-02-07 19:44:37 -080047 final static String TAG = "AndroidRuntime";
48 final static boolean DEBUG = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080049
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
Jeff Brown16f5f5c2012-03-15 16:53:55 -070057 private static final native void nativeFinishInit();
Jeff Brown4280c4a2012-03-15 17:48:02 -070058 private static final native void nativeSetExitWithoutCleanup(boolean exitWithoutCleanup);
Jeff Brown16f5f5c2012-03-15 16:53:55 -070059
Mark Salyzyn69eb6f52014-04-09 07:39:15 -070060 private static int Clog_e(String tag, String msg, Throwable tr) {
Andreas Gamped888beb2016-02-18 14:01:41 -080061 return Log.printlns(Log.LOG_ID_CRASH, Log.ERROR, tag, msg, tr);
Mark Salyzyn69eb6f52014-04-09 07:39:15 -070062 }
63
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080064 /**
Tobias Thiereraddbf902016-07-21 15:05:19 +010065 * Logs a message when a thread encounters an uncaught exception. By
66 * default, {@link KillApplicationHandler} will terminate this process later,
67 * but apps can override that behavior.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080068 */
Tobias Thiereraddbf902016-07-21 15:05:19 +010069 private static class LoggingHandler implements Thread.UncaughtExceptionHandler {
70 @Override
71 public void uncaughtException(Thread t, Throwable e) {
72 // Don't re-enter if KillApplicationHandler has already run
73 if (mCrashing) return;
74 if (mApplicationObject == null) {
75 // The "FATAL EXCEPTION" string is still used on Android even though
76 // apps can set a custom UncaughtExceptionHandler that renders uncaught
77 // exceptions non-fatal.
78 Clog_e(TAG, "*** FATAL EXCEPTION IN SYSTEM PROCESS: " + t.getName(), e);
79 } else {
80 StringBuilder message = new StringBuilder();
81 // The "FATAL EXCEPTION" string is still used on Android even though
82 // apps can set a custom UncaughtExceptionHandler that renders uncaught
83 // exceptions non-fatal.
84 message.append("FATAL EXCEPTION: ").append(t.getName()).append("\n");
85 final String processName = ActivityThread.currentProcessName();
86 if (processName != null) {
87 message.append("Process: ").append(processName).append(", ");
88 }
89 message.append("PID: ").append(Process.myPid());
90 Clog_e(TAG, message.toString(), e);
91 }
92 }
93 }
94
95 /**
96 * Handle application death from an uncaught exception. The framework
97 * catches these for the main threads, so this should only matter for
98 * threads created by applications. Before this method runs,
99 * {@link LoggingHandler} will already have logged details.
100 */
101 private static class KillApplicationHandler implements Thread.UncaughtExceptionHandler {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800102 public void uncaughtException(Thread t, Throwable e) {
103 try {
Dan Egnor60d87622009-12-16 16:32:58 -0800104 // Don't re-enter -- avoid infinite loops if crash-reporting crashes.
105 if (mCrashing) return;
106 mCrashing = true;
107
Andreas Gampe4c79fea2016-01-28 20:11:41 -0800108 // Try to end profiling. If a profiler is running at this point, and we kill the
109 // process (below), the in-memory buffer will be lost. So try to stop, which will
110 // flush the buffer. (This makes method trace profiling useful to debug crashes.)
111 if (ActivityThread.currentActivityThread() != null) {
112 ActivityThread.currentActivityThread().stopProfiling();
113 }
114
Dan Egnor60d87622009-12-16 16:32:58 -0800115 // Bring up crash dialog, wait for it to be dismissed
Sudheer Shankadc589ac2016-11-10 15:30:17 -0800116 ActivityManager.getService().handleApplicationCrash(
Sudheer Shankafc46e9b2016-10-21 17:55:27 -0700117 mApplicationObject, new ApplicationErrorReport.ParcelableCrashInfo(e));
Dan Egnor60d87622009-12-16 16:32:58 -0800118 } catch (Throwable t2) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700119 if (t2 instanceof DeadObjectException) {
120 // System process is dead; ignore
121 } else {
122 try {
123 Clog_e(TAG, "Error reporting crash", t2);
124 } catch (Throwable t3) {
125 // Even Clog_e() fails! Oh well.
126 }
Dan Egnor60d87622009-12-16 16:32:58 -0800127 }
128 } finally {
129 // Try everything to make sure this process goes away.
130 Process.killProcess(Process.myPid());
131 System.exit(10);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800132 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800133 }
134 }
135
Andreas Gampe76d4fc82017-02-07 19:44:37 -0800136 protected static final void commonInit() {
Jeff Brownebed7d62011-05-16 17:08:42 -0700137 if (DEBUG) Slog.d(TAG, "Entered RuntimeInit!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800138
Tobias Thiereraddbf902016-07-21 15:05:19 +0100139 /*
140 * set handlers; these apply to all threads in the VM. Apps can replace
141 * the default handler, but not the pre handler.
142 */
143 Thread.setUncaughtExceptionPreHandler(new LoggingHandler());
144 Thread.setDefaultUncaughtExceptionHandler(new KillApplicationHandler());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800145
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800146 /*
147 * Install a TimezoneGetter subclass for ZoneInfo.db
148 */
149 TimezoneGetter.setInstance(new TimezoneGetter() {
150 @Override
151 public String getId() {
152 return SystemProperties.get("persist.sys.timezone");
153 }
154 });
155 TimeZone.setDefault(null);
156
157 /*
158 * Sets handler for java.util.logging to use Android log facilities.
159 * The odd "new instance-and-then-throw-away" is a mirror of how
160 * the "java.util.logging.config.class" system property works. We
161 * can't use the system property here since the logger has almost
162 * certainly already been initialized.
163 */
164 LogManager.getLogManager().reset();
165 new AndroidConfig();
166
167 /*
Jesse Wilsond0f80d42009-09-18 18:06:43 -0700168 * Sets the default HTTP User-Agent used by HttpURLConnection.
169 */
170 String userAgent = getDefaultUserAgent();
171 System.setProperty("http.agent", userAgent);
172
173 /*
Jesse Wilson8568db52011-06-28 19:06:31 -0700174 * Wire socket tagging to traffic stats.
175 */
176 NetworkManagementSocketTagger.install();
177
178 /*
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800179 * If we're running in an emulator launched with "-trace", put the
180 * VM into emulator trace profiling mode so that the user can hit
181 * F9/F10 at any time to capture traces. This has performance
182 * consequences, so it's not something you want to do always.
183 */
184 String trace = SystemProperties.get("ro.kernel.android.tracing");
185 if (trace.equals("1")) {
Dianne Hackbornc9421ba2010-03-11 22:23:46 -0800186 Slog.i(TAG, "NOTE: emulator trace profiling enabled");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800187 Debug.enableEmulatorTraceOutput();
188 }
189
190 initialized = true;
191 }
192
193 /**
Jesse Wilsond0f80d42009-09-18 18:06:43 -0700194 * Returns an HTTP user agent of the form
195 * "Dalvik/1.1.0 (Linux; U; Android Eclair Build/MASTER)".
196 */
197 private static String getDefaultUserAgent() {
198 StringBuilder result = new StringBuilder(64);
199 result.append("Dalvik/");
200 result.append(System.getProperty("java.vm.version")); // such as 1.1.0
201 result.append(" (Linux; U; Android ");
202
203 String version = Build.VERSION.RELEASE; // "1.0" or "3.4b5"
204 result.append(version.length() > 0 ? version : "1.0");
205
206 // add the model for the release build
207 if ("REL".equals(Build.VERSION.CODENAME)) {
208 String model = Build.MODEL;
209 if (model.length() > 0) {
210 result.append("; ");
211 result.append(model);
212 }
213 }
214 String id = Build.ID; // "MASTER" or "M4-rc20"
215 if (id.length() > 0) {
216 result.append(" Build/");
217 result.append(id);
218 }
219 result.append(")");
220 return result.toString();
221 }
222
223 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800224 * Invokes a static "main(argv[]) method on class "className".
225 * Converts various failing exceptions into RuntimeExceptions, with
226 * the assumption that they will then cause the VM instance to exit.
227 *
228 * @param className Fully-qualified class name
229 * @param argv Argument vector for main()
Narayan Kamath29564cd2014-08-07 10:57:40 +0100230 * @param classLoader the classLoader to load {@className} with
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800231 */
Narayan Kamathac0b4be2017-07-05 14:45:38 +0100232 private static Runnable findStaticMain(String className, String[] argv,
233 ClassLoader classLoader) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800234 Class<?> cl;
235
236 try {
Narayan Kamath29564cd2014-08-07 10:57:40 +0100237 cl = Class.forName(className, true, classLoader);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800238 } catch (ClassNotFoundException ex) {
239 throw new RuntimeException(
240 "Missing class when invoking static main " + className,
241 ex);
242 }
243
244 Method m;
245 try {
246 m = cl.getMethod("main", new Class[] { String[].class });
247 } catch (NoSuchMethodException ex) {
248 throw new RuntimeException(
249 "Missing static main on " + className, ex);
250 } catch (SecurityException ex) {
251 throw new RuntimeException(
252 "Problem getting static main on " + className, ex);
253 }
254
255 int modifiers = m.getModifiers();
256 if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
257 throw new RuntimeException(
258 "Main method is not public and static on " + className);
259 }
260
261 /*
262 * This throw gets caught in ZygoteInit.main(), which responds
263 * by invoking the exception's run() method. This arrangement
264 * clears up all the stack frames that were required in setting
265 * up the process.
266 */
Narayan Kamathac0b4be2017-07-05 14:45:38 +0100267 return new MethodAndArgsCaller(m, argv);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800268 }
269
270 public static final void main(String[] argv) {
Piotr Jastrzebskida74a622015-02-12 13:55:23 +0000271 enableDdms();
Jeff Brownebed7d62011-05-16 17:08:42 -0700272 if (argv.length == 2 && argv[1].equals("application")) {
273 if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application");
274 redirectLogStreams();
275 } else {
276 if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting tool");
277 }
278
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800279 commonInit();
Bob Leee5408332009-09-04 18:31:17 -0700280
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800281 /*
282 * Now that we're running in interpreted code, call back into native code
283 * to run the system.
284 */
Jeff Brown16f5f5c2012-03-15 16:53:55 -0700285 nativeFinishInit();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800286
Jeff Brownebed7d62011-05-16 17:08:42 -0700287 if (DEBUG) Slog.d(TAG, "Leaving RuntimeInit!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800288 }
Bob Leee5408332009-09-04 18:31:17 -0700289
Narayan Kamathac0b4be2017-07-05 14:45:38 +0100290 protected static Runnable applicationInit(int targetSdkVersion, String[] argv,
291 ClassLoader classLoader) {
Jeff Brown4280c4a2012-03-15 17:48:02 -0700292 // If the application calls System.exit(), terminate the process
293 // immediately without running any shutdown hooks. It is not possible to
294 // shutdown an Android application gracefully. Among other things, the
295 // Android runtime shutdown hooks close the Binder driver, which can cause
296 // leftover running threads to crash before the process actually exits.
297 nativeSetExitWithoutCleanup(true);
298
Jeff Brownebed7d62011-05-16 17:08:42 -0700299 // We want to be fairly aggressive about heap utilization, to avoid
300 // holding on to a lot of memory that isn't needed.
301 VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
Elliott Hughese1dfcb72011-07-08 11:08:07 -0700302 VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
Jeff Brownebed7d62011-05-16 17:08:42 -0700303
Narayan Kamathac0b4be2017-07-05 14:45:38 +0100304 final Arguments args = new Arguments(argv);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800305
Narayan Kamathfbb32f62015-06-12 15:34:35 +0100306 // The end of of the RuntimeInit event (see #zygoteInit).
307 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
308
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800309 // Remaining arguments are passed to the start class's static main
Narayan Kamathac0b4be2017-07-05 14:45:38 +0100310 return findStaticMain(args.startClass, args.startArgs, classLoader);
Jeff Brownebed7d62011-05-16 17:08:42 -0700311 }
Bob Leee5408332009-09-04 18:31:17 -0700312
Jeff Brownebed7d62011-05-16 17:08:42 -0700313 /**
314 * Redirect System.out and System.err to the Android log.
315 */
316 public static void redirectLogStreams() {
317 System.out.close();
318 System.setOut(new AndroidPrintStream(Log.INFO, "System.out"));
319 System.err.close();
320 System.setErr(new AndroidPrintStream(Log.WARN, "System.err"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800321 }
322
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800323 /**
Dan Egnor60d87622009-12-16 16:32:58 -0800324 * Report a serious error in the current process. May or may not cause
325 * the process to terminate (depends on system settings).
Bob Leee5408332009-09-04 18:31:17 -0700326 *
Dan Egnor60d87622009-12-16 16:32:58 -0800327 * @param tag to record with the error
328 * @param t exception describing the error site and conditions
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800329 */
Dianne Hackborn52322712014-08-26 22:47:26 -0700330 public static void wtf(String tag, Throwable t, boolean system) {
Dan Egnor60d87622009-12-16 16:32:58 -0800331 try {
Sudheer Shankadc589ac2016-11-10 15:30:17 -0800332 if (ActivityManager.getService().handleApplicationWtf(
Sudheer Shankafc46e9b2016-10-21 17:55:27 -0700333 mApplicationObject, tag, system,
334 new ApplicationErrorReport.ParcelableCrashInfo(t))) {
Dan Egnor60d87622009-12-16 16:32:58 -0800335 // The Activity Manager has already written us off -- now exit.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800336 Process.killProcess(Process.myPid());
337 System.exit(10);
338 }
Dan Egnor60d87622009-12-16 16:32:58 -0800339 } catch (Throwable t2) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700340 if (t2 instanceof DeadObjectException) {
341 // System process is dead; ignore
342 } else {
343 Slog.e(TAG, "Error reporting WTF", t2);
344 Slog.e(TAG, "Original WTF:", t);
345 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800346 }
347 }
348
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800349 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800350 * Set the object identifying this application/process, for reporting VM
351 * errors.
352 */
353 public static final void setApplicationObject(IBinder app) {
354 mApplicationObject = app;
355 }
356
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700357 public static final IBinder getApplicationObject() {
358 return mApplicationObject;
359 }
360
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800361 /**
Piotr Jastrzebskida74a622015-02-12 13:55:23 +0000362 * Enable DDMS.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800363 */
Piotr Jastrzebskida74a622015-02-12 13:55:23 +0000364 static final void enableDdms() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800365 // Register handlers for DDM messages.
366 android.ddm.DdmRegister.registerHandlers();
367 }
Jeff Brownebed7d62011-05-16 17:08:42 -0700368
369 /**
370 * Handles argument parsing for args related to the runtime.
371 *
372 * Current recognized args:
373 * <ul>
374 * <li> <code> [--] &lt;start class name&gt; &lt;args&gt;
375 * </ul>
376 */
377 static class Arguments {
378 /** first non-option argument */
379 String startClass;
380
381 /** all following arguments */
382 String[] startArgs;
383
384 /**
385 * Constructs instance and parses args
386 * @param args runtime command-line args
387 * @throws IllegalArgumentException
388 */
389 Arguments(String args[]) throws IllegalArgumentException {
390 parseArgs(args);
391 }
392
393 /**
394 * Parses the commandline arguments intended for the Runtime.
395 */
396 private void parseArgs(String args[])
397 throws IllegalArgumentException {
398 int curArg = 0;
399 for (; curArg < args.length; curArg++) {
400 String arg = args[curArg];
401
402 if (arg.equals("--")) {
403 curArg++;
404 break;
405 } else if (!arg.startsWith("--")) {
406 break;
407 }
408 }
409
410 if (curArg == args.length) {
411 throw new IllegalArgumentException("Missing classname argument to RuntimeInit!");
412 }
413
414 startClass = args[curArg++];
415 startArgs = new String[args.length - curArg];
416 System.arraycopy(args, curArg, startArgs, 0, startArgs.length);
417 }
418 }
Narayan Kamathac0b4be2017-07-05 14:45:38 +0100419
420 /**
421 * Helper class which holds a method and arguments and can call them. This is used as part of
422 * a trampoline to get rid of the initial process setup stack frames.
423 */
424 static class MethodAndArgsCaller implements Runnable {
425 /** method to call */
426 private final Method mMethod;
427
428 /** argument array */
429 private final String[] mArgs;
430
431 public MethodAndArgsCaller(Method method, String[] args) {
432 mMethod = method;
433 mArgs = args;
434 }
435
436 public void run() {
437 try {
438 mMethod.invoke(null, new Object[] { mArgs });
439 } catch (IllegalAccessException ex) {
440 throw new RuntimeException(ex);
441 } catch (InvocationTargetException ex) {
442 Throwable cause = ex.getCause();
443 if (cause instanceof RuntimeException) {
444 throw (RuntimeException) cause;
445 } else if (cause instanceof Error) {
446 throw (Error) cause;
447 }
448 throw new RuntimeException(ex);
449 }
450 }
451 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800452}