blob: dd1e4f46a5de8cc1ca98d8a871cc4edd2824c05f [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;
Jing Ji6674e0d2020-04-16 15:02:50 -070022import android.app.IActivityManager;
Artur Satayevae5bcf22019-12-10 17:47:54 +000023import android.compat.annotation.UnsupportedAppUsage;
Tobias Thiereraf0cef92019-09-27 17:08:49 +010024import android.content.type.DefaultMimeMapFactory;
Dan Egnorb7f03672009-12-09 16:22:32 -080025import android.os.Build;
Jeff Sharkeyf8880562016-02-26 13:03:01 -070026import android.os.DeadObjectException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080027import android.os.Debug;
28import android.os.IBinder;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080029import android.os.Process;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080030import android.os.SystemProperties;
Narayan Kamathfbb32f62015-06-12 15:34:35 +010031import android.os.Trace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080032import android.util.Log;
Dianne Hackbornc9421ba2010-03-11 22:23:46 -080033import android.util.Slog;
David Sehra4944492019-12-06 13:03:29 -080034
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080035import com.android.internal.logging.AndroidConfig;
Jesse Wilson8568db52011-06-28 19:06:31 -070036import com.android.server.NetworkManagementSocketTagger;
David Sehra4944492019-12-06 13:03:29 -080037
Neil Fullera84056a2018-07-11 13:59:45 +010038import dalvik.system.RuntimeHooks;
Rick Yiu2c7729e2020-01-08 16:00:59 +080039import dalvik.system.ThreadPrioritySetter;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080040import dalvik.system.VMRuntime;
Tobias Thierer878c77b2019-08-18 15:19:45 +010041
Tobias Thierer8edd8372019-10-03 13:43:21 +010042import libcore.content.type.MimeMap;
Tobias Thierer878c77b2019-08-18 15:19:45 +010043
Narayan Kamathac0b4be2017-07-05 14:45:38 +010044import java.lang.reflect.InvocationTargetException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080045import java.lang.reflect.Method;
46import java.lang.reflect.Modifier;
Andreas Gampe50fa1222018-04-02 14:00:47 -070047import java.util.Objects;
Jesse Wilson8568db52011-06-28 19:06:31 -070048import java.util.logging.LogManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080049
50/**
51 * Main entry point for runtime initialization. Not for
52 * public consumption.
53 * @hide
54 */
55public class RuntimeInit {
Andreas Gampe76d4fc82017-02-07 19:44:37 -080056 final static String TAG = "AndroidRuntime";
57 final static boolean DEBUG = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080058
59 /** true if commonInit() has been called */
Andrei Oneaeecddd52019-03-27 10:32:55 +000060 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080061 private static boolean initialized;
62
Andrei Oneaeecddd52019-03-27 10:32:55 +000063 @UnsupportedAppUsage
Dan Egnor60d87622009-12-16 16:32:58 -080064 private static IBinder mApplicationObject;
65
66 private static volatile boolean mCrashing = false;
67
Jing Ji6674e0d2020-04-16 15:02:50 -070068 private static volatile ApplicationWtfHandler sDefaultApplicationWtfHandler;
69
Jeff Brown16f5f5c2012-03-15 16:53:55 -070070 private static final native void nativeFinishInit();
Jeff Brown4280c4a2012-03-15 17:48:02 -070071 private static final native void nativeSetExitWithoutCleanup(boolean exitWithoutCleanup);
Jeff Brown16f5f5c2012-03-15 16:53:55 -070072
Mark Salyzyn69eb6f52014-04-09 07:39:15 -070073 private static int Clog_e(String tag, String msg, Throwable tr) {
Andreas Gamped888beb2016-02-18 14:01:41 -080074 return Log.printlns(Log.LOG_ID_CRASH, Log.ERROR, tag, msg, tr);
Mark Salyzyn69eb6f52014-04-09 07:39:15 -070075 }
76
Andreas Gampe8695b402019-06-18 12:36:46 -070077 public static void logUncaught(String threadName, String processName, int pid, Throwable e) {
78 StringBuilder message = new StringBuilder();
79 // The "FATAL EXCEPTION" string is still used on Android even though
80 // apps can set a custom UncaughtExceptionHandler that renders uncaught
81 // exceptions non-fatal.
82 message.append("FATAL EXCEPTION: ").append(threadName).append("\n");
83 if (processName != null) {
84 message.append("Process: ").append(processName).append(", ");
85 }
86 message.append("PID: ").append(pid);
87 Clog_e(TAG, message.toString(), e);
88 }
89
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080090 /**
Tobias Thiereraddbf902016-07-21 15:05:19 +010091 * Logs a message when a thread encounters an uncaught exception. By
92 * default, {@link KillApplicationHandler} will terminate this process later,
93 * but apps can override that behavior.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080094 */
Tobias Thiereraddbf902016-07-21 15:05:19 +010095 private static class LoggingHandler implements Thread.UncaughtExceptionHandler {
Andreas Gampe50fa1222018-04-02 14:00:47 -070096 public volatile boolean mTriggered = false;
97
Tobias Thiereraddbf902016-07-21 15:05:19 +010098 @Override
99 public void uncaughtException(Thread t, Throwable e) {
Andreas Gampe50fa1222018-04-02 14:00:47 -0700100 mTriggered = true;
101
Tobias Thiereraddbf902016-07-21 15:05:19 +0100102 // Don't re-enter if KillApplicationHandler has already run
103 if (mCrashing) return;
yuanhuihuie669ac22017-03-18 19:34:31 +0800104
105 // mApplicationObject is null for non-zygote java programs (e.g. "am")
106 // There are also apps running with the system UID. We don't want the
107 // first clause in either of these two cases, only for system_server.
108 if (mApplicationObject == null && (Process.SYSTEM_UID == Process.myUid())) {
Tobias Thiereraddbf902016-07-21 15:05:19 +0100109 Clog_e(TAG, "*** FATAL EXCEPTION IN SYSTEM PROCESS: " + t.getName(), e);
110 } else {
Andreas Gampe8695b402019-06-18 12:36:46 -0700111 logUncaught(t.getName(), ActivityThread.currentProcessName(), Process.myPid(), e);
Tobias Thiereraddbf902016-07-21 15:05:19 +0100112 }
113 }
114 }
115
116 /**
117 * Handle application death from an uncaught exception. The framework
118 * catches these for the main threads, so this should only matter for
Andreas Gampe50fa1222018-04-02 14:00:47 -0700119 * threads created by applications. Before this method runs, the given
120 * instance of {@link LoggingHandler} should already have logged details
121 * (and if not it is run first).
Tobias Thiereraddbf902016-07-21 15:05:19 +0100122 */
123 private static class KillApplicationHandler implements Thread.UncaughtExceptionHandler {
Andreas Gampe50fa1222018-04-02 14:00:47 -0700124 private final LoggingHandler mLoggingHandler;
125
126 /**
127 * Create a new KillApplicationHandler that follows the given LoggingHandler.
128 * If {@link #uncaughtException(Thread, Throwable) uncaughtException} is called
129 * on the created instance without {@code loggingHandler} having been triggered,
130 * {@link LoggingHandler#uncaughtException(Thread, Throwable)
131 * loggingHandler.uncaughtException} will be called first.
132 *
133 * @param loggingHandler the {@link LoggingHandler} expected to have run before
134 * this instance's {@link #uncaughtException(Thread, Throwable) uncaughtException}
135 * is being called.
136 */
137 public KillApplicationHandler(LoggingHandler loggingHandler) {
138 this.mLoggingHandler = Objects.requireNonNull(loggingHandler);
139 }
140
141 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800142 public void uncaughtException(Thread t, Throwable e) {
143 try {
Andreas Gampe50fa1222018-04-02 14:00:47 -0700144 ensureLogging(t, e);
145
Dan Egnor60d87622009-12-16 16:32:58 -0800146 // Don't re-enter -- avoid infinite loops if crash-reporting crashes.
147 if (mCrashing) return;
148 mCrashing = true;
149
Andreas Gampe4c79fea2016-01-28 20:11:41 -0800150 // Try to end profiling. If a profiler is running at this point, and we kill the
151 // process (below), the in-memory buffer will be lost. So try to stop, which will
152 // flush the buffer. (This makes method trace profiling useful to debug crashes.)
153 if (ActivityThread.currentActivityThread() != null) {
154 ActivityThread.currentActivityThread().stopProfiling();
155 }
156
Dan Egnor60d87622009-12-16 16:32:58 -0800157 // Bring up crash dialog, wait for it to be dismissed
Sudheer Shankadc589ac2016-11-10 15:30:17 -0800158 ActivityManager.getService().handleApplicationCrash(
Sudheer Shankafc46e9b2016-10-21 17:55:27 -0700159 mApplicationObject, new ApplicationErrorReport.ParcelableCrashInfo(e));
Dan Egnor60d87622009-12-16 16:32:58 -0800160 } catch (Throwable t2) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700161 if (t2 instanceof DeadObjectException) {
162 // System process is dead; ignore
163 } else {
164 try {
165 Clog_e(TAG, "Error reporting crash", t2);
166 } catch (Throwable t3) {
167 // Even Clog_e() fails! Oh well.
168 }
Dan Egnor60d87622009-12-16 16:32:58 -0800169 }
170 } finally {
171 // Try everything to make sure this process goes away.
172 Process.killProcess(Process.myPid());
173 System.exit(10);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800174 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800175 }
Andreas Gampe50fa1222018-04-02 14:00:47 -0700176
177 /**
178 * Ensures that the logging handler has been triggered.
179 *
180 * See b/73380984. This reinstates the pre-O behavior of
181 *
182 * {@code thread.getUncaughtExceptionHandler().uncaughtException(thread, e);}
183 *
184 * logging the exception (in addition to killing the app). This behavior
185 * was never documented / guaranteed but helps in diagnostics of apps
186 * using the pattern.
187 *
188 * If this KillApplicationHandler is invoked the "regular" way (by
189 * {@link Thread#dispatchUncaughtException(Throwable)
190 * Thread.dispatchUncaughtException} in case of an uncaught exception)
191 * then the pre-handler (expected to be {@link #mLoggingHandler}) will already
192 * have run. Otherwise, we manually invoke it here.
193 */
194 private void ensureLogging(Thread t, Throwable e) {
195 if (!mLoggingHandler.mTriggered) {
196 try {
197 mLoggingHandler.uncaughtException(t, e);
198 } catch (Throwable loggingThrowable) {
199 // Ignored.
200 }
201 }
202 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800203 }
204
Tobias Thierera45917e2019-09-26 16:03:28 +0100205 /**
206 * Common initialization that (unlike {@link #commonInit()} should happen prior to
207 * the Zygote fork.
208 */
209 public static void preForkInit() {
210 if (DEBUG) Slog.d(TAG, "Entered preForkInit.");
Rick Yiu2c7729e2020-01-08 16:00:59 +0800211 RuntimeHooks.setThreadPrioritySetter(new RuntimeThreadPrioritySetter());
Tobias Thierera45917e2019-09-26 16:03:28 +0100212 RuntimeInit.enableDdms();
Tobias Thierer44356062019-10-04 00:31:59 +0100213 // TODO(b/142019040#comment13): Decide whether to load the default instance eagerly, i.e.
214 // MimeMap.setDefault(DefaultMimeMapFactory.create());
Tobias Thierer878c77b2019-08-18 15:19:45 +0100215 /*
216 * Replace libcore's minimal default mapping between MIME types and file
217 * extensions with a mapping that's suitable for Android. Android's mapping
218 * contains many more entries that are derived from IANA registrations but
219 * with several customizations (extensions, overrides).
220 */
Tobias Thierer44356062019-10-04 00:31:59 +0100221 MimeMap.setDefaultSupplier(DefaultMimeMapFactory::create);
Tobias Thierera45917e2019-09-26 16:03:28 +0100222 }
223
Rick Yiu2c7729e2020-01-08 16:00:59 +0800224 private static class RuntimeThreadPrioritySetter implements ThreadPrioritySetter {
225 // Should remain consistent with kNiceValues[] in system/libartpalette/palette_android.cc
226 private static final int[] NICE_VALUES = {
227 Process.THREAD_PRIORITY_LOWEST, // 1 (MIN_PRIORITY)
228 Process.THREAD_PRIORITY_BACKGROUND + 6,
229 Process.THREAD_PRIORITY_BACKGROUND + 3,
230 Process.THREAD_PRIORITY_BACKGROUND,
231 Process.THREAD_PRIORITY_DEFAULT, // 5 (NORM_PRIORITY)
232 Process.THREAD_PRIORITY_DEFAULT - 2,
233 Process.THREAD_PRIORITY_DEFAULT - 4,
234 Process.THREAD_PRIORITY_URGENT_DISPLAY + 3,
235 Process.THREAD_PRIORITY_URGENT_DISPLAY + 2,
236 Process.THREAD_PRIORITY_URGENT_DISPLAY // 10 (MAX_PRIORITY)
237 };
238
239 @Override
240 public void setPriority(int nativeTid, int priority) {
241 // Check NICE_VALUES[] length first.
242 if (NICE_VALUES.length != (1 + Thread.MAX_PRIORITY - Thread.MIN_PRIORITY)) {
243 throw new AssertionError("Unexpected NICE_VALUES.length=" + NICE_VALUES.length);
244 }
245 // Priority should be in the range of MIN_PRIORITY (1) to MAX_PRIORITY (10).
246 if (priority < Thread.MIN_PRIORITY || priority > Thread.MAX_PRIORITY) {
247 throw new IllegalArgumentException("Priority out of range: " + priority);
248 }
249 Process.setThreadPriority(nativeTid, NICE_VALUES[priority - Thread.MIN_PRIORITY]);
250 }
251 }
252
Andrei Oneaeecddd52019-03-27 10:32:55 +0000253 @UnsupportedAppUsage
Andreas Gampe76d4fc82017-02-07 19:44:37 -0800254 protected static final void commonInit() {
Jeff Brownebed7d62011-05-16 17:08:42 -0700255 if (DEBUG) Slog.d(TAG, "Entered RuntimeInit!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800256
Tobias Thiereraddbf902016-07-21 15:05:19 +0100257 /*
258 * set handlers; these apply to all threads in the VM. Apps can replace
259 * the default handler, but not the pre handler.
260 */
Andreas Gampe50fa1222018-04-02 14:00:47 -0700261 LoggingHandler loggingHandler = new LoggingHandler();
Neil Fullera84056a2018-07-11 13:59:45 +0100262 RuntimeHooks.setUncaughtExceptionPreHandler(loggingHandler);
Andreas Gampe50fa1222018-04-02 14:00:47 -0700263 Thread.setDefaultUncaughtExceptionHandler(new KillApplicationHandler(loggingHandler));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800264
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800265 /*
Neil Fullera84056a2018-07-11 13:59:45 +0100266 * Install a time zone supplier that uses the Android persistent time zone system property.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800267 */
Neil Fullera84056a2018-07-11 13:59:45 +0100268 RuntimeHooks.setTimeZoneIdSupplier(() -> SystemProperties.get("persist.sys.timezone"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800269
270 /*
271 * Sets handler for java.util.logging to use Android log facilities.
272 * The odd "new instance-and-then-throw-away" is a mirror of how
273 * the "java.util.logging.config.class" system property works. We
274 * can't use the system property here since the logger has almost
275 * certainly already been initialized.
276 */
277 LogManager.getLogManager().reset();
278 new AndroidConfig();
279
280 /*
Jesse Wilsond0f80d42009-09-18 18:06:43 -0700281 * Sets the default HTTP User-Agent used by HttpURLConnection.
282 */
283 String userAgent = getDefaultUserAgent();
284 System.setProperty("http.agent", userAgent);
285
286 /*
Jesse Wilson8568db52011-06-28 19:06:31 -0700287 * Wire socket tagging to traffic stats.
288 */
289 NetworkManagementSocketTagger.install();
290
291 /*
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800292 * If we're running in an emulator launched with "-trace", put the
293 * VM into emulator trace profiling mode so that the user can hit
294 * F9/F10 at any time to capture traces. This has performance
295 * consequences, so it's not something you want to do always.
296 */
297 String trace = SystemProperties.get("ro.kernel.android.tracing");
298 if (trace.equals("1")) {
Dianne Hackbornc9421ba2010-03-11 22:23:46 -0800299 Slog.i(TAG, "NOTE: emulator trace profiling enabled");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800300 Debug.enableEmulatorTraceOutput();
301 }
302
303 initialized = true;
304 }
305
306 /**
Jesse Wilsond0f80d42009-09-18 18:06:43 -0700307 * Returns an HTTP user agent of the form
308 * "Dalvik/1.1.0 (Linux; U; Android Eclair Build/MASTER)".
309 */
310 private static String getDefaultUserAgent() {
311 StringBuilder result = new StringBuilder(64);
312 result.append("Dalvik/");
313 result.append(System.getProperty("java.vm.version")); // such as 1.1.0
314 result.append(" (Linux; U; Android ");
315
Dianne Hackborndb007452019-10-28 16:34:22 -0700316 String version = Build.VERSION.RELEASE_OR_CODENAME; // "1.0" or "3.4b5"
Jesse Wilsond0f80d42009-09-18 18:06:43 -0700317 result.append(version.length() > 0 ? version : "1.0");
318
319 // add the model for the release build
320 if ("REL".equals(Build.VERSION.CODENAME)) {
321 String model = Build.MODEL;
322 if (model.length() > 0) {
323 result.append("; ");
324 result.append(model);
325 }
326 }
327 String id = Build.ID; // "MASTER" or "M4-rc20"
328 if (id.length() > 0) {
329 result.append(" Build/");
330 result.append(id);
331 }
332 result.append(")");
333 return result.toString();
334 }
335
336 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800337 * Invokes a static "main(argv[]) method on class "className".
338 * Converts various failing exceptions into RuntimeExceptions, with
339 * the assumption that they will then cause the VM instance to exit.
340 *
341 * @param className Fully-qualified class name
342 * @param argv Argument vector for main()
Narayan Kamath29564cd2014-08-07 10:57:40 +0100343 * @param classLoader the classLoader to load {@className} with
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800344 */
Robert Sesekd0a190df2018-02-12 18:46:01 -0500345 protected static Runnable findStaticMain(String className, String[] argv,
Narayan Kamathac0b4be2017-07-05 14:45:38 +0100346 ClassLoader classLoader) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800347 Class<?> cl;
348
349 try {
Narayan Kamath29564cd2014-08-07 10:57:40 +0100350 cl = Class.forName(className, true, classLoader);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800351 } catch (ClassNotFoundException ex) {
352 throw new RuntimeException(
353 "Missing class when invoking static main " + className,
354 ex);
355 }
356
357 Method m;
358 try {
359 m = cl.getMethod("main", new Class[] { String[].class });
360 } catch (NoSuchMethodException ex) {
361 throw new RuntimeException(
362 "Missing static main on " + className, ex);
363 } catch (SecurityException ex) {
364 throw new RuntimeException(
365 "Problem getting static main on " + className, ex);
366 }
367
368 int modifiers = m.getModifiers();
369 if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
370 throw new RuntimeException(
371 "Main method is not public and static on " + className);
372 }
373
374 /*
375 * This throw gets caught in ZygoteInit.main(), which responds
376 * by invoking the exception's run() method. This arrangement
377 * clears up all the stack frames that were required in setting
378 * up the process.
379 */
Narayan Kamathac0b4be2017-07-05 14:45:38 +0100380 return new MethodAndArgsCaller(m, argv);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800381 }
382
Andrei Oneaeecddd52019-03-27 10:32:55 +0000383 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800384 public static final void main(String[] argv) {
Tobias Thierera45917e2019-09-26 16:03:28 +0100385 preForkInit();
Jeff Brownebed7d62011-05-16 17:08:42 -0700386 if (argv.length == 2 && argv[1].equals("application")) {
387 if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application");
388 redirectLogStreams();
389 } else {
390 if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting tool");
391 }
392
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800393 commonInit();
Bob Leee5408332009-09-04 18:31:17 -0700394
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800395 /*
396 * Now that we're running in interpreted code, call back into native code
397 * to run the system.
398 */
Jeff Brown16f5f5c2012-03-15 16:53:55 -0700399 nativeFinishInit();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800400
Jeff Brownebed7d62011-05-16 17:08:42 -0700401 if (DEBUG) Slog.d(TAG, "Leaving RuntimeInit!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800402 }
Bob Leee5408332009-09-04 18:31:17 -0700403
atroste44e1342019-12-11 18:44:20 +0000404 protected static Runnable applicationInit(int targetSdkVersion, long[] disabledCompatChanges,
405 String[] argv, ClassLoader classLoader) {
Jeff Brown4280c4a2012-03-15 17:48:02 -0700406 // If the application calls System.exit(), terminate the process
407 // immediately without running any shutdown hooks. It is not possible to
408 // shutdown an Android application gracefully. Among other things, the
409 // Android runtime shutdown hooks close the Binder driver, which can cause
410 // leftover running threads to crash before the process actually exits.
411 nativeSetExitWithoutCleanup(true);
412
Elliott Hughese1dfcb72011-07-08 11:08:07 -0700413 VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
atroste44e1342019-12-11 18:44:20 +0000414 VMRuntime.getRuntime().setDisabledCompatChanges(disabledCompatChanges);
Jeff Brownebed7d62011-05-16 17:08:42 -0700415
Narayan Kamathac0b4be2017-07-05 14:45:38 +0100416 final Arguments args = new Arguments(argv);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800417
Narayan Kamathfbb32f62015-06-12 15:34:35 +0100418 // The end of of the RuntimeInit event (see #zygoteInit).
419 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
420
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800421 // Remaining arguments are passed to the start class's static main
Narayan Kamathac0b4be2017-07-05 14:45:38 +0100422 return findStaticMain(args.startClass, args.startArgs, classLoader);
Jeff Brownebed7d62011-05-16 17:08:42 -0700423 }
Bob Leee5408332009-09-04 18:31:17 -0700424
Jeff Brownebed7d62011-05-16 17:08:42 -0700425 /**
426 * Redirect System.out and System.err to the Android log.
427 */
428 public static void redirectLogStreams() {
429 System.out.close();
430 System.setOut(new AndroidPrintStream(Log.INFO, "System.out"));
431 System.err.close();
432 System.setErr(new AndroidPrintStream(Log.WARN, "System.err"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800433 }
434
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800435 /**
Dan Egnor60d87622009-12-16 16:32:58 -0800436 * Report a serious error in the current process. May or may not cause
437 * the process to terminate (depends on system settings).
Bob Leee5408332009-09-04 18:31:17 -0700438 *
Dan Egnor60d87622009-12-16 16:32:58 -0800439 * @param tag to record with the error
440 * @param t exception describing the error site and conditions
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800441 */
Dianne Hackborn52322712014-08-26 22:47:26 -0700442 public static void wtf(String tag, Throwable t, boolean system) {
Dan Egnor60d87622009-12-16 16:32:58 -0800443 try {
Jing Ji6674e0d2020-04-16 15:02:50 -0700444 boolean exit = false;
445 final IActivityManager am = ActivityManager.getService();
446 if (am != null) {
447 exit = am.handleApplicationWtf(
448 mApplicationObject, tag, system,
449 new ApplicationErrorReport.ParcelableCrashInfo(t),
450 Process.myPid());
451 } else {
452 // Unlikely but possible in early system boot
453 final ApplicationWtfHandler handler = sDefaultApplicationWtfHandler;
454 if (handler != null) {
455 exit = handler.handleApplicationWtf(
456 mApplicationObject, tag, system,
457 new ApplicationErrorReport.ParcelableCrashInfo(t),
458 Process.myPid());
459 } else {
460 // Simply log the error
461 Slog.e(TAG, "Original WTF:", t);
462 }
463 }
464 if (exit) {
Dan Egnor60d87622009-12-16 16:32:58 -0800465 // The Activity Manager has already written us off -- now exit.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800466 Process.killProcess(Process.myPid());
467 System.exit(10);
468 }
Dan Egnor60d87622009-12-16 16:32:58 -0800469 } catch (Throwable t2) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700470 if (t2 instanceof DeadObjectException) {
471 // System process is dead; ignore
472 } else {
473 Slog.e(TAG, "Error reporting WTF", t2);
474 Slog.e(TAG, "Original WTF:", t);
475 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800476 }
477 }
478
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800479 /**
Jing Ji6674e0d2020-04-16 15:02:50 -0700480 * Set the default {@link ApplicationWtfHandler}, in case the ActivityManager is not ready yet.
481 */
482 public static void setDefaultApplicationWtfHandler(final ApplicationWtfHandler handler) {
483 sDefaultApplicationWtfHandler = handler;
484 }
485
486 /**
487 * The handler to deal with the serious application errors.
488 */
489 public interface ApplicationWtfHandler {
490 /**
491 * @param app object of the crashing app, null for the system server
492 * @param tag reported by the caller
493 * @param system whether this wtf is coming from the system
494 * @param crashInfo describing the context of the error
495 * @param immediateCallerPid the caller Pid
496 * @return true if the process should exit immediately (WTF is fatal)
497 */
498 boolean handleApplicationWtf(IBinder app, String tag, boolean system,
499 ApplicationErrorReport.ParcelableCrashInfo crashInfo, int immediateCallerPid);
500 }
501
502 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800503 * Set the object identifying this application/process, for reporting VM
504 * errors.
505 */
506 public static final void setApplicationObject(IBinder app) {
507 mApplicationObject = app;
508 }
509
Andrei Oneaeecddd52019-03-27 10:32:55 +0000510 @UnsupportedAppUsage
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700511 public static final IBinder getApplicationObject() {
512 return mApplicationObject;
513 }
514
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800515 /**
Piotr Jastrzebskida74a622015-02-12 13:55:23 +0000516 * Enable DDMS.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800517 */
Tobias Thierera45917e2019-09-26 16:03:28 +0100518 private static void enableDdms() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800519 // Register handlers for DDM messages.
520 android.ddm.DdmRegister.registerHandlers();
521 }
Jeff Brownebed7d62011-05-16 17:08:42 -0700522
523 /**
524 * Handles argument parsing for args related to the runtime.
525 *
526 * Current recognized args:
527 * <ul>
528 * <li> <code> [--] &lt;start class name&gt; &lt;args&gt;
529 * </ul>
530 */
531 static class Arguments {
532 /** first non-option argument */
533 String startClass;
534
535 /** all following arguments */
536 String[] startArgs;
537
538 /**
539 * Constructs instance and parses args
540 * @param args runtime command-line args
541 * @throws IllegalArgumentException
542 */
543 Arguments(String args[]) throws IllegalArgumentException {
544 parseArgs(args);
545 }
546
547 /**
548 * Parses the commandline arguments intended for the Runtime.
549 */
550 private void parseArgs(String args[])
551 throws IllegalArgumentException {
552 int curArg = 0;
553 for (; curArg < args.length; curArg++) {
554 String arg = args[curArg];
555
556 if (arg.equals("--")) {
557 curArg++;
558 break;
559 } else if (!arg.startsWith("--")) {
560 break;
561 }
562 }
563
564 if (curArg == args.length) {
565 throw new IllegalArgumentException("Missing classname argument to RuntimeInit!");
566 }
567
568 startClass = args[curArg++];
569 startArgs = new String[args.length - curArg];
570 System.arraycopy(args, curArg, startArgs, 0, startArgs.length);
571 }
572 }
Narayan Kamathac0b4be2017-07-05 14:45:38 +0100573
574 /**
575 * Helper class which holds a method and arguments and can call them. This is used as part of
576 * a trampoline to get rid of the initial process setup stack frames.
577 */
578 static class MethodAndArgsCaller implements Runnable {
579 /** method to call */
580 private final Method mMethod;
581
582 /** argument array */
583 private final String[] mArgs;
584
585 public MethodAndArgsCaller(Method method, String[] args) {
586 mMethod = method;
587 mArgs = args;
588 }
589
590 public void run() {
591 try {
592 mMethod.invoke(null, new Object[] { mArgs });
593 } catch (IllegalAccessException ex) {
594 throw new RuntimeException(ex);
595 } catch (InvocationTargetException ex) {
596 Throwable cause = ex.getCause();
597 if (cause instanceof RuntimeException) {
598 throw (RuntimeException) cause;
599 } else if (cause instanceof Error) {
600 throw (Error) cause;
601 }
602 throw new RuntimeException(ex);
603 }
604 }
605 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800606}