blob: 895be082c679d1b84b364d5eb8cc1fcabe2796cf [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;
yuanhuihuie669ac22017-03-18 19:34:31 +080074
75 // mApplicationObject is null for non-zygote java programs (e.g. "am")
76 // There are also apps running with the system UID. We don't want the
77 // first clause in either of these two cases, only for system_server.
78 if (mApplicationObject == null && (Process.SYSTEM_UID == Process.myUid())) {
Tobias Thiereraddbf902016-07-21 15:05:19 +010079 Clog_e(TAG, "*** FATAL EXCEPTION IN SYSTEM PROCESS: " + t.getName(), e);
80 } else {
81 StringBuilder message = new StringBuilder();
82 // The "FATAL EXCEPTION" string is still used on Android even though
83 // apps can set a custom UncaughtExceptionHandler that renders uncaught
84 // exceptions non-fatal.
85 message.append("FATAL EXCEPTION: ").append(t.getName()).append("\n");
86 final String processName = ActivityThread.currentProcessName();
87 if (processName != null) {
88 message.append("Process: ").append(processName).append(", ");
89 }
90 message.append("PID: ").append(Process.myPid());
91 Clog_e(TAG, message.toString(), e);
92 }
93 }
94 }
95
96 /**
97 * Handle application death from an uncaught exception. The framework
98 * catches these for the main threads, so this should only matter for
99 * threads created by applications. Before this method runs,
100 * {@link LoggingHandler} will already have logged details.
101 */
102 private static class KillApplicationHandler implements Thread.UncaughtExceptionHandler {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800103 public void uncaughtException(Thread t, Throwable e) {
104 try {
Dan Egnor60d87622009-12-16 16:32:58 -0800105 // Don't re-enter -- avoid infinite loops if crash-reporting crashes.
106 if (mCrashing) return;
107 mCrashing = true;
108
Andreas Gampe4c79fea2016-01-28 20:11:41 -0800109 // Try to end profiling. If a profiler is running at this point, and we kill the
110 // process (below), the in-memory buffer will be lost. So try to stop, which will
111 // flush the buffer. (This makes method trace profiling useful to debug crashes.)
112 if (ActivityThread.currentActivityThread() != null) {
113 ActivityThread.currentActivityThread().stopProfiling();
114 }
115
Dan Egnor60d87622009-12-16 16:32:58 -0800116 // Bring up crash dialog, wait for it to be dismissed
Sudheer Shankadc589ac2016-11-10 15:30:17 -0800117 ActivityManager.getService().handleApplicationCrash(
Sudheer Shankafc46e9b2016-10-21 17:55:27 -0700118 mApplicationObject, new ApplicationErrorReport.ParcelableCrashInfo(e));
Dan Egnor60d87622009-12-16 16:32:58 -0800119 } catch (Throwable t2) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700120 if (t2 instanceof DeadObjectException) {
121 // System process is dead; ignore
122 } else {
123 try {
124 Clog_e(TAG, "Error reporting crash", t2);
125 } catch (Throwable t3) {
126 // Even Clog_e() fails! Oh well.
127 }
Dan Egnor60d87622009-12-16 16:32:58 -0800128 }
129 } finally {
130 // Try everything to make sure this process goes away.
131 Process.killProcess(Process.myPid());
132 System.exit(10);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800133 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800134 }
135 }
136
Andreas Gampe76d4fc82017-02-07 19:44:37 -0800137 protected static final void commonInit() {
Jeff Brownebed7d62011-05-16 17:08:42 -0700138 if (DEBUG) Slog.d(TAG, "Entered RuntimeInit!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800139
Tobias Thiereraddbf902016-07-21 15:05:19 +0100140 /*
141 * set handlers; these apply to all threads in the VM. Apps can replace
142 * the default handler, but not the pre handler.
143 */
144 Thread.setUncaughtExceptionPreHandler(new LoggingHandler());
145 Thread.setDefaultUncaughtExceptionHandler(new KillApplicationHandler());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800146
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800147 /*
148 * Install a TimezoneGetter subclass for ZoneInfo.db
149 */
150 TimezoneGetter.setInstance(new TimezoneGetter() {
151 @Override
152 public String getId() {
153 return SystemProperties.get("persist.sys.timezone");
154 }
155 });
156 TimeZone.setDefault(null);
157
158 /*
159 * Sets handler for java.util.logging to use Android log facilities.
160 * The odd "new instance-and-then-throw-away" is a mirror of how
161 * the "java.util.logging.config.class" system property works. We
162 * can't use the system property here since the logger has almost
163 * certainly already been initialized.
164 */
165 LogManager.getLogManager().reset();
166 new AndroidConfig();
167
168 /*
Jesse Wilsond0f80d42009-09-18 18:06:43 -0700169 * Sets the default HTTP User-Agent used by HttpURLConnection.
170 */
171 String userAgent = getDefaultUserAgent();
172 System.setProperty("http.agent", userAgent);
173
174 /*
Jesse Wilson8568db52011-06-28 19:06:31 -0700175 * Wire socket tagging to traffic stats.
176 */
177 NetworkManagementSocketTagger.install();
178
179 /*
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800180 * If we're running in an emulator launched with "-trace", put the
181 * VM into emulator trace profiling mode so that the user can hit
182 * F9/F10 at any time to capture traces. This has performance
183 * consequences, so it's not something you want to do always.
184 */
185 String trace = SystemProperties.get("ro.kernel.android.tracing");
186 if (trace.equals("1")) {
Dianne Hackbornc9421ba2010-03-11 22:23:46 -0800187 Slog.i(TAG, "NOTE: emulator trace profiling enabled");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800188 Debug.enableEmulatorTraceOutput();
189 }
190
191 initialized = true;
192 }
193
194 /**
Jesse Wilsond0f80d42009-09-18 18:06:43 -0700195 * Returns an HTTP user agent of the form
196 * "Dalvik/1.1.0 (Linux; U; Android Eclair Build/MASTER)".
197 */
198 private static String getDefaultUserAgent() {
199 StringBuilder result = new StringBuilder(64);
200 result.append("Dalvik/");
201 result.append(System.getProperty("java.vm.version")); // such as 1.1.0
202 result.append(" (Linux; U; Android ");
203
204 String version = Build.VERSION.RELEASE; // "1.0" or "3.4b5"
205 result.append(version.length() > 0 ? version : "1.0");
206
207 // add the model for the release build
208 if ("REL".equals(Build.VERSION.CODENAME)) {
209 String model = Build.MODEL;
210 if (model.length() > 0) {
211 result.append("; ");
212 result.append(model);
213 }
214 }
215 String id = Build.ID; // "MASTER" or "M4-rc20"
216 if (id.length() > 0) {
217 result.append(" Build/");
218 result.append(id);
219 }
220 result.append(")");
221 return result.toString();
222 }
223
224 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800225 * Invokes a static "main(argv[]) method on class "className".
226 * Converts various failing exceptions into RuntimeExceptions, with
227 * the assumption that they will then cause the VM instance to exit.
228 *
229 * @param className Fully-qualified class name
230 * @param argv Argument vector for main()
Narayan Kamath29564cd2014-08-07 10:57:40 +0100231 * @param classLoader the classLoader to load {@className} with
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800232 */
Narayan Kamathac0b4be2017-07-05 14:45:38 +0100233 private static Runnable findStaticMain(String className, String[] argv,
234 ClassLoader classLoader) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800235 Class<?> cl;
236
237 try {
Narayan Kamath29564cd2014-08-07 10:57:40 +0100238 cl = Class.forName(className, true, classLoader);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800239 } catch (ClassNotFoundException ex) {
240 throw new RuntimeException(
241 "Missing class when invoking static main " + className,
242 ex);
243 }
244
245 Method m;
246 try {
247 m = cl.getMethod("main", new Class[] { String[].class });
248 } catch (NoSuchMethodException ex) {
249 throw new RuntimeException(
250 "Missing static main on " + className, ex);
251 } catch (SecurityException ex) {
252 throw new RuntimeException(
253 "Problem getting static main on " + className, ex);
254 }
255
256 int modifiers = m.getModifiers();
257 if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
258 throw new RuntimeException(
259 "Main method is not public and static on " + className);
260 }
261
262 /*
263 * This throw gets caught in ZygoteInit.main(), which responds
264 * by invoking the exception's run() method. This arrangement
265 * clears up all the stack frames that were required in setting
266 * up the process.
267 */
Narayan Kamathac0b4be2017-07-05 14:45:38 +0100268 return new MethodAndArgsCaller(m, argv);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800269 }
270
271 public static final void main(String[] argv) {
Piotr Jastrzebskida74a622015-02-12 13:55:23 +0000272 enableDdms();
Jeff Brownebed7d62011-05-16 17:08:42 -0700273 if (argv.length == 2 && argv[1].equals("application")) {
274 if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application");
275 redirectLogStreams();
276 } else {
277 if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting tool");
278 }
279
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800280 commonInit();
Bob Leee5408332009-09-04 18:31:17 -0700281
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800282 /*
283 * Now that we're running in interpreted code, call back into native code
284 * to run the system.
285 */
Jeff Brown16f5f5c2012-03-15 16:53:55 -0700286 nativeFinishInit();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800287
Jeff Brownebed7d62011-05-16 17:08:42 -0700288 if (DEBUG) Slog.d(TAG, "Leaving RuntimeInit!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800289 }
Bob Leee5408332009-09-04 18:31:17 -0700290
Narayan Kamathac0b4be2017-07-05 14:45:38 +0100291 protected static Runnable applicationInit(int targetSdkVersion, String[] argv,
292 ClassLoader classLoader) {
Jeff Brown4280c4a2012-03-15 17:48:02 -0700293 // If the application calls System.exit(), terminate the process
294 // immediately without running any shutdown hooks. It is not possible to
295 // shutdown an Android application gracefully. Among other things, the
296 // Android runtime shutdown hooks close the Binder driver, which can cause
297 // leftover running threads to crash before the process actually exits.
298 nativeSetExitWithoutCleanup(true);
299
Jeff Brownebed7d62011-05-16 17:08:42 -0700300 // We want to be fairly aggressive about heap utilization, to avoid
301 // holding on to a lot of memory that isn't needed.
302 VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
Elliott Hughese1dfcb72011-07-08 11:08:07 -0700303 VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
Jeff Brownebed7d62011-05-16 17:08:42 -0700304
Narayan Kamathac0b4be2017-07-05 14:45:38 +0100305 final Arguments args = new Arguments(argv);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800306
Narayan Kamathfbb32f62015-06-12 15:34:35 +0100307 // The end of of the RuntimeInit event (see #zygoteInit).
308 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
309
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800310 // Remaining arguments are passed to the start class's static main
Narayan Kamathac0b4be2017-07-05 14:45:38 +0100311 return findStaticMain(args.startClass, args.startArgs, classLoader);
Jeff Brownebed7d62011-05-16 17:08:42 -0700312 }
Bob Leee5408332009-09-04 18:31:17 -0700313
Jeff Brownebed7d62011-05-16 17:08:42 -0700314 /**
315 * Redirect System.out and System.err to the Android log.
316 */
317 public static void redirectLogStreams() {
318 System.out.close();
319 System.setOut(new AndroidPrintStream(Log.INFO, "System.out"));
320 System.err.close();
321 System.setErr(new AndroidPrintStream(Log.WARN, "System.err"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800322 }
323
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800324 /**
Dan Egnor60d87622009-12-16 16:32:58 -0800325 * Report a serious error in the current process. May or may not cause
326 * the process to terminate (depends on system settings).
Bob Leee5408332009-09-04 18:31:17 -0700327 *
Dan Egnor60d87622009-12-16 16:32:58 -0800328 * @param tag to record with the error
329 * @param t exception describing the error site and conditions
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800330 */
Dianne Hackborn52322712014-08-26 22:47:26 -0700331 public static void wtf(String tag, Throwable t, boolean system) {
Dan Egnor60d87622009-12-16 16:32:58 -0800332 try {
Sudheer Shankadc589ac2016-11-10 15:30:17 -0800333 if (ActivityManager.getService().handleApplicationWtf(
Sudheer Shankafc46e9b2016-10-21 17:55:27 -0700334 mApplicationObject, tag, system,
335 new ApplicationErrorReport.ParcelableCrashInfo(t))) {
Dan Egnor60d87622009-12-16 16:32:58 -0800336 // The Activity Manager has already written us off -- now exit.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800337 Process.killProcess(Process.myPid());
338 System.exit(10);
339 }
Dan Egnor60d87622009-12-16 16:32:58 -0800340 } catch (Throwable t2) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700341 if (t2 instanceof DeadObjectException) {
342 // System process is dead; ignore
343 } else {
344 Slog.e(TAG, "Error reporting WTF", t2);
345 Slog.e(TAG, "Original WTF:", t);
346 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800347 }
348 }
349
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800350 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800351 * Set the object identifying this application/process, for reporting VM
352 * errors.
353 */
354 public static final void setApplicationObject(IBinder app) {
355 mApplicationObject = app;
356 }
357
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700358 public static final IBinder getApplicationObject() {
359 return mApplicationObject;
360 }
361
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800362 /**
Piotr Jastrzebskida74a622015-02-12 13:55:23 +0000363 * Enable DDMS.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800364 */
Piotr Jastrzebskida74a622015-02-12 13:55:23 +0000365 static final void enableDdms() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800366 // Register handlers for DDM messages.
367 android.ddm.DdmRegister.registerHandlers();
368 }
Jeff Brownebed7d62011-05-16 17:08:42 -0700369
370 /**
371 * Handles argument parsing for args related to the runtime.
372 *
373 * Current recognized args:
374 * <ul>
375 * <li> <code> [--] &lt;start class name&gt; &lt;args&gt;
376 * </ul>
377 */
378 static class Arguments {
379 /** first non-option argument */
380 String startClass;
381
382 /** all following arguments */
383 String[] startArgs;
384
385 /**
386 * Constructs instance and parses args
387 * @param args runtime command-line args
388 * @throws IllegalArgumentException
389 */
390 Arguments(String args[]) throws IllegalArgumentException {
391 parseArgs(args);
392 }
393
394 /**
395 * Parses the commandline arguments intended for the Runtime.
396 */
397 private void parseArgs(String args[])
398 throws IllegalArgumentException {
399 int curArg = 0;
400 for (; curArg < args.length; curArg++) {
401 String arg = args[curArg];
402
403 if (arg.equals("--")) {
404 curArg++;
405 break;
406 } else if (!arg.startsWith("--")) {
407 break;
408 }
409 }
410
411 if (curArg == args.length) {
412 throw new IllegalArgumentException("Missing classname argument to RuntimeInit!");
413 }
414
415 startClass = args[curArg++];
416 startArgs = new String[args.length - curArg];
417 System.arraycopy(args, curArg, startArgs, 0, startArgs.length);
418 }
419 }
Narayan Kamathac0b4be2017-07-05 14:45:38 +0100420
421 /**
422 * Helper class which holds a method and arguments and can call them. This is used as part of
423 * a trampoline to get rid of the initial process setup stack frames.
424 */
425 static class MethodAndArgsCaller implements Runnable {
426 /** method to call */
427 private final Method mMethod;
428
429 /** argument array */
430 private final String[] mArgs;
431
432 public MethodAndArgsCaller(Method method, String[] args) {
433 mMethod = method;
434 mArgs = args;
435 }
436
437 public void run() {
438 try {
439 mMethod.invoke(null, new Object[] { mArgs });
440 } catch (IllegalAccessException ex) {
441 throw new RuntimeException(ex);
442 } catch (InvocationTargetException ex) {
443 Throwable cause = ex.getCause();
444 if (cause instanceof RuntimeException) {
445 throw (RuntimeException) cause;
446 } else if (cause instanceof Error) {
447 throw (Error) cause;
448 }
449 throw new RuntimeException(ex);
450 }
451 }
452 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800453}