blob: 1de2e7272f4d1c1c6017c367551584a08c607439 [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
Andrei Oneaeecddd52019-03-27 10:32:55 +0000195 @UnsupportedAppUsage
Andreas Gampe76d4fc82017-02-07 19:44:37 -0800196 protected static final void commonInit() {
Jeff Brownebed7d62011-05-16 17:08:42 -0700197 if (DEBUG) Slog.d(TAG, "Entered RuntimeInit!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800198
Tobias Thiereraddbf902016-07-21 15:05:19 +0100199 /*
200 * set handlers; these apply to all threads in the VM. Apps can replace
201 * the default handler, but not the pre handler.
202 */
Andreas Gampe50fa1222018-04-02 14:00:47 -0700203 LoggingHandler loggingHandler = new LoggingHandler();
Neil Fullera84056a2018-07-11 13:59:45 +0100204 RuntimeHooks.setUncaughtExceptionPreHandler(loggingHandler);
Andreas Gampe50fa1222018-04-02 14:00:47 -0700205 Thread.setDefaultUncaughtExceptionHandler(new KillApplicationHandler(loggingHandler));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800206
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800207 /*
Neil Fullera84056a2018-07-11 13:59:45 +0100208 * Install a time zone supplier that uses the Android persistent time zone system property.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800209 */
Neil Fullera84056a2018-07-11 13:59:45 +0100210 RuntimeHooks.setTimeZoneIdSupplier(() -> SystemProperties.get("persist.sys.timezone"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800211
212 /*
213 * Sets handler for java.util.logging to use Android log facilities.
214 * The odd "new instance-and-then-throw-away" is a mirror of how
215 * the "java.util.logging.config.class" system property works. We
216 * can't use the system property here since the logger has almost
217 * certainly already been initialized.
218 */
219 LogManager.getLogManager().reset();
220 new AndroidConfig();
221
222 /*
Jesse Wilsond0f80d42009-09-18 18:06:43 -0700223 * Sets the default HTTP User-Agent used by HttpURLConnection.
224 */
225 String userAgent = getDefaultUserAgent();
226 System.setProperty("http.agent", userAgent);
227
228 /*
Jesse Wilson8568db52011-06-28 19:06:31 -0700229 * Wire socket tagging to traffic stats.
230 */
231 NetworkManagementSocketTagger.install();
232
233 /*
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800234 * If we're running in an emulator launched with "-trace", put the
235 * VM into emulator trace profiling mode so that the user can hit
236 * F9/F10 at any time to capture traces. This has performance
237 * consequences, so it's not something you want to do always.
238 */
239 String trace = SystemProperties.get("ro.kernel.android.tracing");
240 if (trace.equals("1")) {
Dianne Hackbornc9421ba2010-03-11 22:23:46 -0800241 Slog.i(TAG, "NOTE: emulator trace profiling enabled");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800242 Debug.enableEmulatorTraceOutput();
243 }
244
245 initialized = true;
246 }
247
248 /**
Jesse Wilsond0f80d42009-09-18 18:06:43 -0700249 * Returns an HTTP user agent of the form
250 * "Dalvik/1.1.0 (Linux; U; Android Eclair Build/MASTER)".
251 */
252 private static String getDefaultUserAgent() {
253 StringBuilder result = new StringBuilder(64);
254 result.append("Dalvik/");
255 result.append(System.getProperty("java.vm.version")); // such as 1.1.0
256 result.append(" (Linux; U; Android ");
257
258 String version = Build.VERSION.RELEASE; // "1.0" or "3.4b5"
259 result.append(version.length() > 0 ? version : "1.0");
260
261 // add the model for the release build
262 if ("REL".equals(Build.VERSION.CODENAME)) {
263 String model = Build.MODEL;
264 if (model.length() > 0) {
265 result.append("; ");
266 result.append(model);
267 }
268 }
269 String id = Build.ID; // "MASTER" or "M4-rc20"
270 if (id.length() > 0) {
271 result.append(" Build/");
272 result.append(id);
273 }
274 result.append(")");
275 return result.toString();
276 }
277
278 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800279 * Invokes a static "main(argv[]) method on class "className".
280 * Converts various failing exceptions into RuntimeExceptions, with
281 * the assumption that they will then cause the VM instance to exit.
282 *
283 * @param className Fully-qualified class name
284 * @param argv Argument vector for main()
Narayan Kamath29564cd2014-08-07 10:57:40 +0100285 * @param classLoader the classLoader to load {@className} with
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800286 */
Robert Sesekd0a190df2018-02-12 18:46:01 -0500287 protected static Runnable findStaticMain(String className, String[] argv,
Narayan Kamathac0b4be2017-07-05 14:45:38 +0100288 ClassLoader classLoader) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800289 Class<?> cl;
290
291 try {
Narayan Kamath29564cd2014-08-07 10:57:40 +0100292 cl = Class.forName(className, true, classLoader);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800293 } catch (ClassNotFoundException ex) {
294 throw new RuntimeException(
295 "Missing class when invoking static main " + className,
296 ex);
297 }
298
299 Method m;
300 try {
301 m = cl.getMethod("main", new Class[] { String[].class });
302 } catch (NoSuchMethodException ex) {
303 throw new RuntimeException(
304 "Missing static main on " + className, ex);
305 } catch (SecurityException ex) {
306 throw new RuntimeException(
307 "Problem getting static main on " + className, ex);
308 }
309
310 int modifiers = m.getModifiers();
311 if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
312 throw new RuntimeException(
313 "Main method is not public and static on " + className);
314 }
315
316 /*
317 * This throw gets caught in ZygoteInit.main(), which responds
318 * by invoking the exception's run() method. This arrangement
319 * clears up all the stack frames that were required in setting
320 * up the process.
321 */
Narayan Kamathac0b4be2017-07-05 14:45:38 +0100322 return new MethodAndArgsCaller(m, argv);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800323 }
324
Andrei Oneaeecddd52019-03-27 10:32:55 +0000325 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800326 public static final void main(String[] argv) {
Piotr Jastrzebskida74a622015-02-12 13:55:23 +0000327 enableDdms();
Jeff Brownebed7d62011-05-16 17:08:42 -0700328 if (argv.length == 2 && argv[1].equals("application")) {
329 if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application");
330 redirectLogStreams();
331 } else {
332 if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting tool");
333 }
334
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800335 commonInit();
Bob Leee5408332009-09-04 18:31:17 -0700336
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800337 /*
338 * Now that we're running in interpreted code, call back into native code
339 * to run the system.
340 */
Jeff Brown16f5f5c2012-03-15 16:53:55 -0700341 nativeFinishInit();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800342
Jeff Brownebed7d62011-05-16 17:08:42 -0700343 if (DEBUG) Slog.d(TAG, "Leaving RuntimeInit!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800344 }
Bob Leee5408332009-09-04 18:31:17 -0700345
Narayan Kamathac0b4be2017-07-05 14:45:38 +0100346 protected static Runnable applicationInit(int targetSdkVersion, String[] argv,
347 ClassLoader classLoader) {
Jeff Brown4280c4a2012-03-15 17:48:02 -0700348 // If the application calls System.exit(), terminate the process
349 // immediately without running any shutdown hooks. It is not possible to
350 // shutdown an Android application gracefully. Among other things, the
351 // Android runtime shutdown hooks close the Binder driver, which can cause
352 // leftover running threads to crash before the process actually exits.
353 nativeSetExitWithoutCleanup(true);
354
Jeff Brownebed7d62011-05-16 17:08:42 -0700355 // We want to be fairly aggressive about heap utilization, to avoid
356 // holding on to a lot of memory that isn't needed.
357 VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
Elliott Hughese1dfcb72011-07-08 11:08:07 -0700358 VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
Jeff Brownebed7d62011-05-16 17:08:42 -0700359
Narayan Kamathac0b4be2017-07-05 14:45:38 +0100360 final Arguments args = new Arguments(argv);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800361
Narayan Kamathfbb32f62015-06-12 15:34:35 +0100362 // The end of of the RuntimeInit event (see #zygoteInit).
363 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
364
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800365 // Remaining arguments are passed to the start class's static main
Narayan Kamathac0b4be2017-07-05 14:45:38 +0100366 return findStaticMain(args.startClass, args.startArgs, classLoader);
Jeff Brownebed7d62011-05-16 17:08:42 -0700367 }
Bob Leee5408332009-09-04 18:31:17 -0700368
Jeff Brownebed7d62011-05-16 17:08:42 -0700369 /**
370 * Redirect System.out and System.err to the Android log.
371 */
372 public static void redirectLogStreams() {
373 System.out.close();
374 System.setOut(new AndroidPrintStream(Log.INFO, "System.out"));
375 System.err.close();
376 System.setErr(new AndroidPrintStream(Log.WARN, "System.err"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800377 }
378
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800379 /**
Dan Egnor60d87622009-12-16 16:32:58 -0800380 * Report a serious error in the current process. May or may not cause
381 * the process to terminate (depends on system settings).
Bob Leee5408332009-09-04 18:31:17 -0700382 *
Dan Egnor60d87622009-12-16 16:32:58 -0800383 * @param tag to record with the error
384 * @param t exception describing the error site and conditions
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800385 */
Dianne Hackborn52322712014-08-26 22:47:26 -0700386 public static void wtf(String tag, Throwable t, boolean system) {
Dan Egnor60d87622009-12-16 16:32:58 -0800387 try {
Sudheer Shankadc589ac2016-11-10 15:30:17 -0800388 if (ActivityManager.getService().handleApplicationWtf(
Sudheer Shankafc46e9b2016-10-21 17:55:27 -0700389 mApplicationObject, tag, system,
390 new ApplicationErrorReport.ParcelableCrashInfo(t))) {
Dan Egnor60d87622009-12-16 16:32:58 -0800391 // The Activity Manager has already written us off -- now exit.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800392 Process.killProcess(Process.myPid());
393 System.exit(10);
394 }
Dan Egnor60d87622009-12-16 16:32:58 -0800395 } catch (Throwable t2) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700396 if (t2 instanceof DeadObjectException) {
397 // System process is dead; ignore
398 } else {
399 Slog.e(TAG, "Error reporting WTF", t2);
400 Slog.e(TAG, "Original WTF:", t);
401 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800402 }
403 }
404
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800405 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800406 * Set the object identifying this application/process, for reporting VM
407 * errors.
408 */
409 public static final void setApplicationObject(IBinder app) {
410 mApplicationObject = app;
411 }
412
Andrei Oneaeecddd52019-03-27 10:32:55 +0000413 @UnsupportedAppUsage
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700414 public static final IBinder getApplicationObject() {
415 return mApplicationObject;
416 }
417
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800418 /**
Piotr Jastrzebskida74a622015-02-12 13:55:23 +0000419 * Enable DDMS.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800420 */
Piotr Jastrzebskida74a622015-02-12 13:55:23 +0000421 static final void enableDdms() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800422 // Register handlers for DDM messages.
423 android.ddm.DdmRegister.registerHandlers();
424 }
Jeff Brownebed7d62011-05-16 17:08:42 -0700425
426 /**
427 * Handles argument parsing for args related to the runtime.
428 *
429 * Current recognized args:
430 * <ul>
431 * <li> <code> [--] &lt;start class name&gt; &lt;args&gt;
432 * </ul>
433 */
434 static class Arguments {
435 /** first non-option argument */
436 String startClass;
437
438 /** all following arguments */
439 String[] startArgs;
440
441 /**
442 * Constructs instance and parses args
443 * @param args runtime command-line args
444 * @throws IllegalArgumentException
445 */
446 Arguments(String args[]) throws IllegalArgumentException {
447 parseArgs(args);
448 }
449
450 /**
451 * Parses the commandline arguments intended for the Runtime.
452 */
453 private void parseArgs(String args[])
454 throws IllegalArgumentException {
455 int curArg = 0;
456 for (; curArg < args.length; curArg++) {
457 String arg = args[curArg];
458
459 if (arg.equals("--")) {
460 curArg++;
461 break;
462 } else if (!arg.startsWith("--")) {
463 break;
464 }
465 }
466
467 if (curArg == args.length) {
468 throw new IllegalArgumentException("Missing classname argument to RuntimeInit!");
469 }
470
471 startClass = args[curArg++];
472 startArgs = new String[args.length - curArg];
473 System.arraycopy(args, curArg, startArgs, 0, startArgs.length);
474 }
475 }
Narayan Kamathac0b4be2017-07-05 14:45:38 +0100476
477 /**
478 * Helper class which holds a method and arguments and can call them. This is used as part of
479 * a trampoline to get rid of the initial process setup stack frames.
480 */
481 static class MethodAndArgsCaller implements Runnable {
482 /** method to call */
483 private final Method mMethod;
484
485 /** argument array */
486 private final String[] mArgs;
487
488 public MethodAndArgsCaller(Method method, String[] args) {
489 mMethod = method;
490 mArgs = args;
491 }
492
493 public void run() {
494 try {
495 mMethod.invoke(null, new Object[] { mArgs });
496 } catch (IllegalAccessException ex) {
497 throw new RuntimeException(ex);
498 } catch (InvocationTargetException ex) {
499 Throwable cause = ex.getCause();
500 if (cause instanceof RuntimeException) {
501 throw (RuntimeException) cause;
502 } else if (cause instanceof Error) {
503 throw (Error) cause;
504 }
505 throw new RuntimeException(ex);
506 }
507 }
508 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800509}