blob: d6caa0930243c4cbcc70ffb5fc965f602ad167ff [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
Andrei Oneaeecddd52019-03-27 10:32:55 +000019import android.annotation.UnsupportedAppUsage;
Sudheer Shankadc589ac2016-11-10 15:30:17 -080020import android.app.ActivityManager;
Eric Rowe35980b22013-09-03 10:51:15 -070021import android.app.ActivityThread;
Dan Egnorb7f03672009-12-09 16:22:32 -080022import android.app.ApplicationErrorReport;
Dan Egnorb7f03672009-12-09 16:22:32 -080023import android.os.Build;
Jeff Sharkeyf8880562016-02-26 13:03:01 -070024import android.os.DeadObjectException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080025import android.os.Debug;
26import android.os.IBinder;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080027import android.os.Process;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080028import android.os.SystemProperties;
Narayan Kamathfbb32f62015-06-12 15:34:35 +010029import android.os.Trace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080030import android.util.Log;
Dianne Hackbornc9421ba2010-03-11 22:23:46 -080031import android.util.Slog;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080032import com.android.internal.logging.AndroidConfig;
Jesse Wilson8568db52011-06-28 19:06:31 -070033import com.android.server.NetworkManagementSocketTagger;
Neil Fullera84056a2018-07-11 13:59:45 +010034import dalvik.system.RuntimeHooks;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080035import dalvik.system.VMRuntime;
Narayan Kamathac0b4be2017-07-05 14:45:38 +010036import java.lang.reflect.InvocationTargetException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080037import java.lang.reflect.Method;
38import java.lang.reflect.Modifier;
Andreas Gampe50fa1222018-04-02 14:00:47 -070039import java.util.Objects;
Jesse Wilson8568db52011-06-28 19:06:31 -070040import java.util.logging.LogManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080041
42/**
43 * Main entry point for runtime initialization. Not for
44 * public consumption.
45 * @hide
46 */
47public class RuntimeInit {
Andreas Gampe76d4fc82017-02-07 19:44:37 -080048 final static String TAG = "AndroidRuntime";
49 final static boolean DEBUG = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080050
51 /** true if commonInit() has been called */
Andrei Oneaeecddd52019-03-27 10:32:55 +000052 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080053 private static boolean initialized;
54
Andrei Oneaeecddd52019-03-27 10:32:55 +000055 @UnsupportedAppUsage
Dan Egnor60d87622009-12-16 16:32:58 -080056 private static IBinder mApplicationObject;
57
58 private static volatile boolean mCrashing = false;
59
Jeff Brown16f5f5c2012-03-15 16:53:55 -070060 private static final native void nativeFinishInit();
Jeff Brown4280c4a2012-03-15 17:48:02 -070061 private static final native void nativeSetExitWithoutCleanup(boolean exitWithoutCleanup);
Jeff Brown16f5f5c2012-03-15 16:53:55 -070062
Mark Salyzyn69eb6f52014-04-09 07:39:15 -070063 private static int Clog_e(String tag, String msg, Throwable tr) {
Andreas Gamped888beb2016-02-18 14:01:41 -080064 return Log.printlns(Log.LOG_ID_CRASH, Log.ERROR, tag, msg, tr);
Mark Salyzyn69eb6f52014-04-09 07:39:15 -070065 }
66
Andreas Gampe8695b402019-06-18 12:36:46 -070067 public static void logUncaught(String threadName, String processName, int pid, Throwable e) {
68 StringBuilder message = new StringBuilder();
69 // The "FATAL EXCEPTION" string is still used on Android even though
70 // apps can set a custom UncaughtExceptionHandler that renders uncaught
71 // exceptions non-fatal.
72 message.append("FATAL EXCEPTION: ").append(threadName).append("\n");
73 if (processName != null) {
74 message.append("Process: ").append(processName).append(", ");
75 }
76 message.append("PID: ").append(pid);
77 Clog_e(TAG, message.toString(), e);
78 }
79
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080080 /**
Tobias Thiereraddbf902016-07-21 15:05:19 +010081 * Logs a message when a thread encounters an uncaught exception. By
82 * default, {@link KillApplicationHandler} will terminate this process later,
83 * but apps can override that behavior.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080084 */
Tobias Thiereraddbf902016-07-21 15:05:19 +010085 private static class LoggingHandler implements Thread.UncaughtExceptionHandler {
Andreas Gampe50fa1222018-04-02 14:00:47 -070086 public volatile boolean mTriggered = false;
87
Tobias Thiereraddbf902016-07-21 15:05:19 +010088 @Override
89 public void uncaughtException(Thread t, Throwable e) {
Andreas Gampe50fa1222018-04-02 14:00:47 -070090 mTriggered = true;
91
Tobias Thiereraddbf902016-07-21 15:05:19 +010092 // Don't re-enter if KillApplicationHandler has already run
93 if (mCrashing) return;
yuanhuihuie669ac22017-03-18 19:34:31 +080094
95 // mApplicationObject is null for non-zygote java programs (e.g. "am")
96 // There are also apps running with the system UID. We don't want the
97 // first clause in either of these two cases, only for system_server.
98 if (mApplicationObject == null && (Process.SYSTEM_UID == Process.myUid())) {
Tobias Thiereraddbf902016-07-21 15:05:19 +010099 Clog_e(TAG, "*** FATAL EXCEPTION IN SYSTEM PROCESS: " + t.getName(), e);
100 } else {
Andreas Gampe8695b402019-06-18 12:36:46 -0700101 logUncaught(t.getName(), ActivityThread.currentProcessName(), Process.myPid(), e);
Tobias Thiereraddbf902016-07-21 15:05:19 +0100102 }
103 }
104 }
105
106 /**
107 * Handle application death from an uncaught exception. The framework
108 * catches these for the main threads, so this should only matter for
Andreas Gampe50fa1222018-04-02 14:00:47 -0700109 * threads created by applications. Before this method runs, the given
110 * instance of {@link LoggingHandler} should already have logged details
111 * (and if not it is run first).
Tobias Thiereraddbf902016-07-21 15:05:19 +0100112 */
113 private static class KillApplicationHandler implements Thread.UncaughtExceptionHandler {
Andreas Gampe50fa1222018-04-02 14:00:47 -0700114 private final LoggingHandler mLoggingHandler;
115
116 /**
117 * Create a new KillApplicationHandler that follows the given LoggingHandler.
118 * If {@link #uncaughtException(Thread, Throwable) uncaughtException} is called
119 * on the created instance without {@code loggingHandler} having been triggered,
120 * {@link LoggingHandler#uncaughtException(Thread, Throwable)
121 * loggingHandler.uncaughtException} will be called first.
122 *
123 * @param loggingHandler the {@link LoggingHandler} expected to have run before
124 * this instance's {@link #uncaughtException(Thread, Throwable) uncaughtException}
125 * is being called.
126 */
127 public KillApplicationHandler(LoggingHandler loggingHandler) {
128 this.mLoggingHandler = Objects.requireNonNull(loggingHandler);
129 }
130
131 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800132 public void uncaughtException(Thread t, Throwable e) {
133 try {
Andreas Gampe50fa1222018-04-02 14:00:47 -0700134 ensureLogging(t, e);
135
Dan Egnor60d87622009-12-16 16:32:58 -0800136 // Don't re-enter -- avoid infinite loops if crash-reporting crashes.
137 if (mCrashing) return;
138 mCrashing = true;
139
Andreas Gampe4c79fea2016-01-28 20:11:41 -0800140 // Try to end profiling. If a profiler is running at this point, and we kill the
141 // process (below), the in-memory buffer will be lost. So try to stop, which will
142 // flush the buffer. (This makes method trace profiling useful to debug crashes.)
143 if (ActivityThread.currentActivityThread() != null) {
144 ActivityThread.currentActivityThread().stopProfiling();
145 }
146
Dan Egnor60d87622009-12-16 16:32:58 -0800147 // Bring up crash dialog, wait for it to be dismissed
Sudheer Shankadc589ac2016-11-10 15:30:17 -0800148 ActivityManager.getService().handleApplicationCrash(
Sudheer Shankafc46e9b2016-10-21 17:55:27 -0700149 mApplicationObject, new ApplicationErrorReport.ParcelableCrashInfo(e));
Dan Egnor60d87622009-12-16 16:32:58 -0800150 } catch (Throwable t2) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700151 if (t2 instanceof DeadObjectException) {
152 // System process is dead; ignore
153 } else {
154 try {
155 Clog_e(TAG, "Error reporting crash", t2);
156 } catch (Throwable t3) {
157 // Even Clog_e() fails! Oh well.
158 }
Dan Egnor60d87622009-12-16 16:32:58 -0800159 }
160 } finally {
161 // Try everything to make sure this process goes away.
162 Process.killProcess(Process.myPid());
163 System.exit(10);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800164 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800165 }
Andreas Gampe50fa1222018-04-02 14:00:47 -0700166
167 /**
168 * Ensures that the logging handler has been triggered.
169 *
170 * See b/73380984. This reinstates the pre-O behavior of
171 *
172 * {@code thread.getUncaughtExceptionHandler().uncaughtException(thread, e);}
173 *
174 * logging the exception (in addition to killing the app). This behavior
175 * was never documented / guaranteed but helps in diagnostics of apps
176 * using the pattern.
177 *
178 * If this KillApplicationHandler is invoked the "regular" way (by
179 * {@link Thread#dispatchUncaughtException(Throwable)
180 * Thread.dispatchUncaughtException} in case of an uncaught exception)
181 * then the pre-handler (expected to be {@link #mLoggingHandler}) will already
182 * have run. Otherwise, we manually invoke it here.
183 */
184 private void ensureLogging(Thread t, Throwable e) {
185 if (!mLoggingHandler.mTriggered) {
186 try {
187 mLoggingHandler.uncaughtException(t, e);
188 } catch (Throwable loggingThrowable) {
189 // Ignored.
190 }
191 }
192 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800193 }
194
Tobias Thierera45917e2019-09-26 16:03:28 +0100195 /**
196 * Common initialization that (unlike {@link #commonInit()} should happen prior to
197 * the Zygote fork.
198 */
199 public static void preForkInit() {
200 if (DEBUG) Slog.d(TAG, "Entered preForkInit.");
201 RuntimeInit.enableDdms();
202 }
203
Andrei Oneaeecddd52019-03-27 10:32:55 +0000204 @UnsupportedAppUsage
Andreas Gampe76d4fc82017-02-07 19:44:37 -0800205 protected static final void commonInit() {
Jeff Brownebed7d62011-05-16 17:08:42 -0700206 if (DEBUG) Slog.d(TAG, "Entered RuntimeInit!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800207
Tobias Thiereraddbf902016-07-21 15:05:19 +0100208 /*
209 * set handlers; these apply to all threads in the VM. Apps can replace
210 * the default handler, but not the pre handler.
211 */
Andreas Gampe50fa1222018-04-02 14:00:47 -0700212 LoggingHandler loggingHandler = new LoggingHandler();
Neil Fullera84056a2018-07-11 13:59:45 +0100213 RuntimeHooks.setUncaughtExceptionPreHandler(loggingHandler);
Andreas Gampe50fa1222018-04-02 14:00:47 -0700214 Thread.setDefaultUncaughtExceptionHandler(new KillApplicationHandler(loggingHandler));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800215
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800216 /*
Neil Fullera84056a2018-07-11 13:59:45 +0100217 * Install a time zone supplier that uses the Android persistent time zone system property.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800218 */
Neil Fullera84056a2018-07-11 13:59:45 +0100219 RuntimeHooks.setTimeZoneIdSupplier(() -> SystemProperties.get("persist.sys.timezone"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800220
221 /*
222 * Sets handler for java.util.logging to use Android log facilities.
223 * The odd "new instance-and-then-throw-away" is a mirror of how
224 * the "java.util.logging.config.class" system property works. We
225 * can't use the system property here since the logger has almost
226 * certainly already been initialized.
227 */
228 LogManager.getLogManager().reset();
229 new AndroidConfig();
230
231 /*
Jesse Wilsond0f80d42009-09-18 18:06:43 -0700232 * Sets the default HTTP User-Agent used by HttpURLConnection.
233 */
234 String userAgent = getDefaultUserAgent();
235 System.setProperty("http.agent", userAgent);
236
237 /*
Jesse Wilson8568db52011-06-28 19:06:31 -0700238 * Wire socket tagging to traffic stats.
239 */
240 NetworkManagementSocketTagger.install();
241
242 /*
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800243 * If we're running in an emulator launched with "-trace", put the
244 * VM into emulator trace profiling mode so that the user can hit
245 * F9/F10 at any time to capture traces. This has performance
246 * consequences, so it's not something you want to do always.
247 */
248 String trace = SystemProperties.get("ro.kernel.android.tracing");
249 if (trace.equals("1")) {
Dianne Hackbornc9421ba2010-03-11 22:23:46 -0800250 Slog.i(TAG, "NOTE: emulator trace profiling enabled");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800251 Debug.enableEmulatorTraceOutput();
252 }
253
254 initialized = true;
255 }
256
257 /**
Jesse Wilsond0f80d42009-09-18 18:06:43 -0700258 * Returns an HTTP user agent of the form
259 * "Dalvik/1.1.0 (Linux; U; Android Eclair Build/MASTER)".
260 */
261 private static String getDefaultUserAgent() {
262 StringBuilder result = new StringBuilder(64);
263 result.append("Dalvik/");
264 result.append(System.getProperty("java.vm.version")); // such as 1.1.0
265 result.append(" (Linux; U; Android ");
266
267 String version = Build.VERSION.RELEASE; // "1.0" or "3.4b5"
268 result.append(version.length() > 0 ? version : "1.0");
269
270 // add the model for the release build
271 if ("REL".equals(Build.VERSION.CODENAME)) {
272 String model = Build.MODEL;
273 if (model.length() > 0) {
274 result.append("; ");
275 result.append(model);
276 }
277 }
278 String id = Build.ID; // "MASTER" or "M4-rc20"
279 if (id.length() > 0) {
280 result.append(" Build/");
281 result.append(id);
282 }
283 result.append(")");
284 return result.toString();
285 }
286
287 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800288 * Invokes a static "main(argv[]) method on class "className".
289 * Converts various failing exceptions into RuntimeExceptions, with
290 * the assumption that they will then cause the VM instance to exit.
291 *
292 * @param className Fully-qualified class name
293 * @param argv Argument vector for main()
Narayan Kamath29564cd2014-08-07 10:57:40 +0100294 * @param classLoader the classLoader to load {@className} with
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800295 */
Robert Sesekd0a190df2018-02-12 18:46:01 -0500296 protected static Runnable findStaticMain(String className, String[] argv,
Narayan Kamathac0b4be2017-07-05 14:45:38 +0100297 ClassLoader classLoader) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800298 Class<?> cl;
299
300 try {
Narayan Kamath29564cd2014-08-07 10:57:40 +0100301 cl = Class.forName(className, true, classLoader);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800302 } catch (ClassNotFoundException ex) {
303 throw new RuntimeException(
304 "Missing class when invoking static main " + className,
305 ex);
306 }
307
308 Method m;
309 try {
310 m = cl.getMethod("main", new Class[] { String[].class });
311 } catch (NoSuchMethodException ex) {
312 throw new RuntimeException(
313 "Missing static main on " + className, ex);
314 } catch (SecurityException ex) {
315 throw new RuntimeException(
316 "Problem getting static main on " + className, ex);
317 }
318
319 int modifiers = m.getModifiers();
320 if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
321 throw new RuntimeException(
322 "Main method is not public and static on " + className);
323 }
324
325 /*
326 * This throw gets caught in ZygoteInit.main(), which responds
327 * by invoking the exception's run() method. This arrangement
328 * clears up all the stack frames that were required in setting
329 * up the process.
330 */
Narayan Kamathac0b4be2017-07-05 14:45:38 +0100331 return new MethodAndArgsCaller(m, argv);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800332 }
333
Andrei Oneaeecddd52019-03-27 10:32:55 +0000334 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800335 public static final void main(String[] argv) {
Tobias Thierera45917e2019-09-26 16:03:28 +0100336 preForkInit();
Jeff Brownebed7d62011-05-16 17:08:42 -0700337 if (argv.length == 2 && argv[1].equals("application")) {
338 if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application");
339 redirectLogStreams();
340 } else {
341 if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting tool");
342 }
343
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800344 commonInit();
Bob Leee5408332009-09-04 18:31:17 -0700345
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800346 /*
347 * Now that we're running in interpreted code, call back into native code
348 * to run the system.
349 */
Jeff Brown16f5f5c2012-03-15 16:53:55 -0700350 nativeFinishInit();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800351
Jeff Brownebed7d62011-05-16 17:08:42 -0700352 if (DEBUG) Slog.d(TAG, "Leaving RuntimeInit!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800353 }
Bob Leee5408332009-09-04 18:31:17 -0700354
Narayan Kamathac0b4be2017-07-05 14:45:38 +0100355 protected static Runnable applicationInit(int targetSdkVersion, String[] argv,
356 ClassLoader classLoader) {
Jeff Brown4280c4a2012-03-15 17:48:02 -0700357 // If the application calls System.exit(), terminate the process
358 // immediately without running any shutdown hooks. It is not possible to
359 // shutdown an Android application gracefully. Among other things, the
360 // Android runtime shutdown hooks close the Binder driver, which can cause
361 // leftover running threads to crash before the process actually exits.
362 nativeSetExitWithoutCleanup(true);
363
Jeff Brownebed7d62011-05-16 17:08:42 -0700364 // We want to be fairly aggressive about heap utilization, to avoid
365 // holding on to a lot of memory that isn't needed.
366 VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
Elliott Hughese1dfcb72011-07-08 11:08:07 -0700367 VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
Jeff Brownebed7d62011-05-16 17:08:42 -0700368
Narayan Kamathac0b4be2017-07-05 14:45:38 +0100369 final Arguments args = new Arguments(argv);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800370
Narayan Kamathfbb32f62015-06-12 15:34:35 +0100371 // The end of of the RuntimeInit event (see #zygoteInit).
372 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
373
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800374 // Remaining arguments are passed to the start class's static main
Narayan Kamathac0b4be2017-07-05 14:45:38 +0100375 return findStaticMain(args.startClass, args.startArgs, classLoader);
Jeff Brownebed7d62011-05-16 17:08:42 -0700376 }
Bob Leee5408332009-09-04 18:31:17 -0700377
Jeff Brownebed7d62011-05-16 17:08:42 -0700378 /**
379 * Redirect System.out and System.err to the Android log.
380 */
381 public static void redirectLogStreams() {
382 System.out.close();
383 System.setOut(new AndroidPrintStream(Log.INFO, "System.out"));
384 System.err.close();
385 System.setErr(new AndroidPrintStream(Log.WARN, "System.err"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800386 }
387
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800388 /**
Dan Egnor60d87622009-12-16 16:32:58 -0800389 * Report a serious error in the current process. May or may not cause
390 * the process to terminate (depends on system settings).
Bob Leee5408332009-09-04 18:31:17 -0700391 *
Dan Egnor60d87622009-12-16 16:32:58 -0800392 * @param tag to record with the error
393 * @param t exception describing the error site and conditions
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800394 */
Dianne Hackborn52322712014-08-26 22:47:26 -0700395 public static void wtf(String tag, Throwable t, boolean system) {
Dan Egnor60d87622009-12-16 16:32:58 -0800396 try {
Sudheer Shankadc589ac2016-11-10 15:30:17 -0800397 if (ActivityManager.getService().handleApplicationWtf(
Sudheer Shankafc46e9b2016-10-21 17:55:27 -0700398 mApplicationObject, tag, system,
399 new ApplicationErrorReport.ParcelableCrashInfo(t))) {
Dan Egnor60d87622009-12-16 16:32:58 -0800400 // The Activity Manager has already written us off -- now exit.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800401 Process.killProcess(Process.myPid());
402 System.exit(10);
403 }
Dan Egnor60d87622009-12-16 16:32:58 -0800404 } catch (Throwable t2) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700405 if (t2 instanceof DeadObjectException) {
406 // System process is dead; ignore
407 } else {
408 Slog.e(TAG, "Error reporting WTF", t2);
409 Slog.e(TAG, "Original WTF:", t);
410 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800411 }
412 }
413
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800414 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800415 * Set the object identifying this application/process, for reporting VM
416 * errors.
417 */
418 public static final void setApplicationObject(IBinder app) {
419 mApplicationObject = app;
420 }
421
Andrei Oneaeecddd52019-03-27 10:32:55 +0000422 @UnsupportedAppUsage
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700423 public static final IBinder getApplicationObject() {
424 return mApplicationObject;
425 }
426
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800427 /**
Piotr Jastrzebskida74a622015-02-12 13:55:23 +0000428 * Enable DDMS.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800429 */
Tobias Thierera45917e2019-09-26 16:03:28 +0100430 private static void enableDdms() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800431 // Register handlers for DDM messages.
432 android.ddm.DdmRegister.registerHandlers();
433 }
Jeff Brownebed7d62011-05-16 17:08:42 -0700434
435 /**
436 * Handles argument parsing for args related to the runtime.
437 *
438 * Current recognized args:
439 * <ul>
440 * <li> <code> [--] &lt;start class name&gt; &lt;args&gt;
441 * </ul>
442 */
443 static class Arguments {
444 /** first non-option argument */
445 String startClass;
446
447 /** all following arguments */
448 String[] startArgs;
449
450 /**
451 * Constructs instance and parses args
452 * @param args runtime command-line args
453 * @throws IllegalArgumentException
454 */
455 Arguments(String args[]) throws IllegalArgumentException {
456 parseArgs(args);
457 }
458
459 /**
460 * Parses the commandline arguments intended for the Runtime.
461 */
462 private void parseArgs(String args[])
463 throws IllegalArgumentException {
464 int curArg = 0;
465 for (; curArg < args.length; curArg++) {
466 String arg = args[curArg];
467
468 if (arg.equals("--")) {
469 curArg++;
470 break;
471 } else if (!arg.startsWith("--")) {
472 break;
473 }
474 }
475
476 if (curArg == args.length) {
477 throw new IllegalArgumentException("Missing classname argument to RuntimeInit!");
478 }
479
480 startClass = args[curArg++];
481 startArgs = new String[args.length - curArg];
482 System.arraycopy(args, curArg, startArgs, 0, startArgs.length);
483 }
484 }
Narayan Kamathac0b4be2017-07-05 14:45:38 +0100485
486 /**
487 * Helper class which holds a method and arguments and can call them. This is used as part of
488 * a trampoline to get rid of the initial process setup stack frames.
489 */
490 static class MethodAndArgsCaller implements Runnable {
491 /** method to call */
492 private final Method mMethod;
493
494 /** argument array */
495 private final String[] mArgs;
496
497 public MethodAndArgsCaller(Method method, String[] args) {
498 mMethod = method;
499 mArgs = args;
500 }
501
502 public void run() {
503 try {
504 mMethod.invoke(null, new Object[] { mArgs });
505 } catch (IllegalAccessException ex) {
506 throw new RuntimeException(ex);
507 } catch (InvocationTargetException ex) {
508 Throwable cause = ex.getCause();
509 if (cause instanceof RuntimeException) {
510 throw (RuntimeException) cause;
511 } else if (cause instanceof Error) {
512 throw (Error) cause;
513 }
514 throw new RuntimeException(ex);
515 }
516 }
517 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800518}