blob: fff9d7c3247b05e3ecb53703f0974286f0b45458 [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
19import android.app.ActivityManagerNative;
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;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080034import java.lang.reflect.Method;
35import java.lang.reflect.Modifier;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080036import java.util.TimeZone;
Jesse Wilson8568db52011-06-28 19:06:31 -070037import java.util.logging.LogManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080038import org.apache.harmony.luni.internal.util.TimezoneGetter;
39
40/**
41 * Main entry point for runtime initialization. Not for
42 * public consumption.
43 * @hide
44 */
45public class RuntimeInit {
46 private final static String TAG = "AndroidRuntime";
Jeff Brownebed7d62011-05-16 17:08:42 -070047 private final static boolean DEBUG = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080048
49 /** true if commonInit() has been called */
50 private static boolean initialized;
51
Dan Egnor60d87622009-12-16 16:32:58 -080052 private static IBinder mApplicationObject;
53
54 private static volatile boolean mCrashing = false;
55
Jeff Brown16f5f5c2012-03-15 16:53:55 -070056 private static final native void nativeZygoteInit();
57 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 /**
65 * Use this to log a message when a thread exits due to an uncaught
66 * exception. The framework catches these for the main threads, so
67 * this should only matter for threads created by applications.
68 */
69 private static class UncaughtHandler implements Thread.UncaughtExceptionHandler {
70 public void uncaughtException(Thread t, Throwable e) {
71 try {
Dan Egnor60d87622009-12-16 16:32:58 -080072 // Don't re-enter -- avoid infinite loops if crash-reporting crashes.
73 if (mCrashing) return;
74 mCrashing = true;
75
76 if (mApplicationObject == null) {
Mark Salyzyn69eb6f52014-04-09 07:39:15 -070077 Clog_e(TAG, "*** FATAL EXCEPTION IN SYSTEM PROCESS: " + t.getName(), e);
Dan Egnor60d87622009-12-16 16:32:58 -080078 } else {
Eric Rowe35980b22013-09-03 10:51:15 -070079 StringBuilder message = new StringBuilder();
80 message.append("FATAL EXCEPTION: ").append(t.getName()).append("\n");
81 final String processName = ActivityThread.currentProcessName();
82 if (processName != null) {
83 message.append("Process: ").append(processName).append(", ");
84 }
85 message.append("PID: ").append(Process.myPid());
Mark Salyzyn69eb6f52014-04-09 07:39:15 -070086 Clog_e(TAG, message.toString(), e);
Dan Egnor60d87622009-12-16 16:32:58 -080087 }
88
Andreas Gampe4c79fea2016-01-28 20:11:41 -080089 // Try to end profiling. If a profiler is running at this point, and we kill the
90 // process (below), the in-memory buffer will be lost. So try to stop, which will
91 // flush the buffer. (This makes method trace profiling useful to debug crashes.)
92 if (ActivityThread.currentActivityThread() != null) {
93 ActivityThread.currentActivityThread().stopProfiling();
94 }
95
Dan Egnor60d87622009-12-16 16:32:58 -080096 // Bring up crash dialog, wait for it to be dismissed
97 ActivityManagerNative.getDefault().handleApplicationCrash(
98 mApplicationObject, new ApplicationErrorReport.CrashInfo(e));
99 } catch (Throwable t2) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700100 if (t2 instanceof DeadObjectException) {
101 // System process is dead; ignore
102 } else {
103 try {
104 Clog_e(TAG, "Error reporting crash", t2);
105 } catch (Throwable t3) {
106 // Even Clog_e() fails! Oh well.
107 }
Dan Egnor60d87622009-12-16 16:32:58 -0800108 }
109 } finally {
110 // Try everything to make sure this process goes away.
111 Process.killProcess(Process.myPid());
112 System.exit(10);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800113 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800114 }
115 }
116
117 private static final void commonInit() {
Jeff Brownebed7d62011-05-16 17:08:42 -0700118 if (DEBUG) Slog.d(TAG, "Entered RuntimeInit!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800119
120 /* set default handler; this applies to all threads in the VM */
121 Thread.setDefaultUncaughtExceptionHandler(new UncaughtHandler());
122
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800123 /*
124 * Install a TimezoneGetter subclass for ZoneInfo.db
125 */
126 TimezoneGetter.setInstance(new TimezoneGetter() {
127 @Override
128 public String getId() {
129 return SystemProperties.get("persist.sys.timezone");
130 }
131 });
132 TimeZone.setDefault(null);
133
134 /*
135 * Sets handler for java.util.logging to use Android log facilities.
136 * The odd "new instance-and-then-throw-away" is a mirror of how
137 * the "java.util.logging.config.class" system property works. We
138 * can't use the system property here since the logger has almost
139 * certainly already been initialized.
140 */
141 LogManager.getLogManager().reset();
142 new AndroidConfig();
143
144 /*
Jesse Wilsond0f80d42009-09-18 18:06:43 -0700145 * Sets the default HTTP User-Agent used by HttpURLConnection.
146 */
147 String userAgent = getDefaultUserAgent();
148 System.setProperty("http.agent", userAgent);
149
150 /*
Jesse Wilson8568db52011-06-28 19:06:31 -0700151 * Wire socket tagging to traffic stats.
152 */
153 NetworkManagementSocketTagger.install();
154
155 /*
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800156 * If we're running in an emulator launched with "-trace", put the
157 * VM into emulator trace profiling mode so that the user can hit
158 * F9/F10 at any time to capture traces. This has performance
159 * consequences, so it's not something you want to do always.
160 */
161 String trace = SystemProperties.get("ro.kernel.android.tracing");
162 if (trace.equals("1")) {
Dianne Hackbornc9421ba2010-03-11 22:23:46 -0800163 Slog.i(TAG, "NOTE: emulator trace profiling enabled");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800164 Debug.enableEmulatorTraceOutput();
165 }
166
167 initialized = true;
168 }
169
170 /**
Jesse Wilsond0f80d42009-09-18 18:06:43 -0700171 * Returns an HTTP user agent of the form
172 * "Dalvik/1.1.0 (Linux; U; Android Eclair Build/MASTER)".
173 */
174 private static String getDefaultUserAgent() {
175 StringBuilder result = new StringBuilder(64);
176 result.append("Dalvik/");
177 result.append(System.getProperty("java.vm.version")); // such as 1.1.0
178 result.append(" (Linux; U; Android ");
179
180 String version = Build.VERSION.RELEASE; // "1.0" or "3.4b5"
181 result.append(version.length() > 0 ? version : "1.0");
182
183 // add the model for the release build
184 if ("REL".equals(Build.VERSION.CODENAME)) {
185 String model = Build.MODEL;
186 if (model.length() > 0) {
187 result.append("; ");
188 result.append(model);
189 }
190 }
191 String id = Build.ID; // "MASTER" or "M4-rc20"
192 if (id.length() > 0) {
193 result.append(" Build/");
194 result.append(id);
195 }
196 result.append(")");
197 return result.toString();
198 }
199
200 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800201 * Invokes a static "main(argv[]) method on class "className".
202 * Converts various failing exceptions into RuntimeExceptions, with
203 * the assumption that they will then cause the VM instance to exit.
204 *
205 * @param className Fully-qualified class name
206 * @param argv Argument vector for main()
Narayan Kamath29564cd2014-08-07 10:57:40 +0100207 * @param classLoader the classLoader to load {@className} with
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800208 */
Narayan Kamath29564cd2014-08-07 10:57:40 +0100209 private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800210 throws ZygoteInit.MethodAndArgsCaller {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800211 Class<?> cl;
212
213 try {
Narayan Kamath29564cd2014-08-07 10:57:40 +0100214 cl = Class.forName(className, true, classLoader);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800215 } catch (ClassNotFoundException ex) {
216 throw new RuntimeException(
217 "Missing class when invoking static main " + className,
218 ex);
219 }
220
221 Method m;
222 try {
223 m = cl.getMethod("main", new Class[] { String[].class });
224 } catch (NoSuchMethodException ex) {
225 throw new RuntimeException(
226 "Missing static main on " + className, ex);
227 } catch (SecurityException ex) {
228 throw new RuntimeException(
229 "Problem getting static main on " + className, ex);
230 }
231
232 int modifiers = m.getModifiers();
233 if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
234 throw new RuntimeException(
235 "Main method is not public and static on " + className);
236 }
237
238 /*
239 * This throw gets caught in ZygoteInit.main(), which responds
240 * by invoking the exception's run() method. This arrangement
241 * clears up all the stack frames that were required in setting
242 * up the process.
243 */
244 throw new ZygoteInit.MethodAndArgsCaller(m, argv);
245 }
246
247 public static final void main(String[] argv) {
Piotr Jastrzebskida74a622015-02-12 13:55:23 +0000248 enableDdms();
Jeff Brownebed7d62011-05-16 17:08:42 -0700249 if (argv.length == 2 && argv[1].equals("application")) {
250 if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application");
251 redirectLogStreams();
252 } else {
253 if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting tool");
254 }
255
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800256 commonInit();
Bob Leee5408332009-09-04 18:31:17 -0700257
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800258 /*
259 * Now that we're running in interpreted code, call back into native code
260 * to run the system.
261 */
Jeff Brown16f5f5c2012-03-15 16:53:55 -0700262 nativeFinishInit();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800263
Jeff Brownebed7d62011-05-16 17:08:42 -0700264 if (DEBUG) Slog.d(TAG, "Leaving RuntimeInit!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800265 }
Bob Leee5408332009-09-04 18:31:17 -0700266
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800267 /**
268 * The main function called when started through the zygote process. This
Jeff Brown16f5f5c2012-03-15 16:53:55 -0700269 * could be unified with main(), if the native code in nativeFinishInit()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800270 * were rationalized with Zygote startup.<p>
271 *
272 * Current recognized args:
273 * <ul>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800274 * <li> <code> [--] &lt;start class name&gt; &lt;args&gt;
275 * </ul>
276 *
Elliott Hughese1dfcb72011-07-08 11:08:07 -0700277 * @param targetSdkVersion target SDK version
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800278 * @param argv arg strings
279 */
Narayan Kamath29564cd2014-08-07 10:57:40 +0100280 public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800281 throws ZygoteInit.MethodAndArgsCaller {
Jeff Brownebed7d62011-05-16 17:08:42 -0700282 if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");
283
Narayan Kamathfbb32f62015-06-12 15:34:35 +0100284 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "RuntimeInit");
Jeff Brownebed7d62011-05-16 17:08:42 -0700285 redirectLogStreams();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800286
287 commonInit();
Jeff Brown16f5f5c2012-03-15 16:53:55 -0700288 nativeZygoteInit();
Narayan Kamath29564cd2014-08-07 10:57:40 +0100289 applicationInit(targetSdkVersion, argv, classLoader);
Jeff Brownebed7d62011-05-16 17:08:42 -0700290 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800291
Jeff Brownebed7d62011-05-16 17:08:42 -0700292 /**
293 * The main function called when an application is started through a
294 * wrapper process.
295 *
296 * When the wrapper starts, the runtime starts {@link RuntimeInit#main}
297 * which calls {@link WrapperInit#main} which then calls this method.
298 * So we don't need to call commonInit() here.
299 *
Elliott Hughese1dfcb72011-07-08 11:08:07 -0700300 * @param targetSdkVersion target SDK version
Jeff Brownebed7d62011-05-16 17:08:42 -0700301 * @param argv arg strings
302 */
Elliott Hughese1dfcb72011-07-08 11:08:07 -0700303 public static void wrapperInit(int targetSdkVersion, String[] argv)
Jeff Brownebed7d62011-05-16 17:08:42 -0700304 throws ZygoteInit.MethodAndArgsCaller {
305 if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from wrapper");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800306
Narayan Kamath29564cd2014-08-07 10:57:40 +0100307 applicationInit(targetSdkVersion, argv, null);
Jeff Brownebed7d62011-05-16 17:08:42 -0700308 }
309
Narayan Kamath29564cd2014-08-07 10:57:40 +0100310 private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
Jeff Brownebed7d62011-05-16 17:08:42 -0700311 throws ZygoteInit.MethodAndArgsCaller {
Jeff Brown4280c4a2012-03-15 17:48:02 -0700312 // If the application calls System.exit(), terminate the process
313 // immediately without running any shutdown hooks. It is not possible to
314 // shutdown an Android application gracefully. Among other things, the
315 // Android runtime shutdown hooks close the Binder driver, which can cause
316 // leftover running threads to crash before the process actually exits.
317 nativeSetExitWithoutCleanup(true);
318
Jeff Brownebed7d62011-05-16 17:08:42 -0700319 // We want to be fairly aggressive about heap utilization, to avoid
320 // holding on to a lot of memory that isn't needed.
321 VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
Elliott Hughese1dfcb72011-07-08 11:08:07 -0700322 VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
Jeff Brownebed7d62011-05-16 17:08:42 -0700323
324 final Arguments args;
325 try {
326 args = new Arguments(argv);
327 } catch (IllegalArgumentException ex) {
328 Slog.e(TAG, ex.getMessage());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800329 // let the process exit
330 return;
331 }
332
Narayan Kamathfbb32f62015-06-12 15:34:35 +0100333 // The end of of the RuntimeInit event (see #zygoteInit).
334 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
335
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800336 // Remaining arguments are passed to the start class's static main
Narayan Kamath29564cd2014-08-07 10:57:40 +0100337 invokeStaticMain(args.startClass, args.startArgs, classLoader);
Jeff Brownebed7d62011-05-16 17:08:42 -0700338 }
Bob Leee5408332009-09-04 18:31:17 -0700339
Jeff Brownebed7d62011-05-16 17:08:42 -0700340 /**
341 * Redirect System.out and System.err to the Android log.
342 */
343 public static void redirectLogStreams() {
344 System.out.close();
345 System.setOut(new AndroidPrintStream(Log.INFO, "System.out"));
346 System.err.close();
347 System.setErr(new AndroidPrintStream(Log.WARN, "System.err"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800348 }
349
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800350 /**
Dan Egnor60d87622009-12-16 16:32:58 -0800351 * Report a serious error in the current process. May or may not cause
352 * the process to terminate (depends on system settings).
Bob Leee5408332009-09-04 18:31:17 -0700353 *
Dan Egnor60d87622009-12-16 16:32:58 -0800354 * @param tag to record with the error
355 * @param t exception describing the error site and conditions
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800356 */
Dianne Hackborn52322712014-08-26 22:47:26 -0700357 public static void wtf(String tag, Throwable t, boolean system) {
Dan Egnor60d87622009-12-16 16:32:58 -0800358 try {
359 if (ActivityManagerNative.getDefault().handleApplicationWtf(
Dianne Hackborn52322712014-08-26 22:47:26 -0700360 mApplicationObject, tag, system, new ApplicationErrorReport.CrashInfo(t))) {
Dan Egnor60d87622009-12-16 16:32:58 -0800361 // The Activity Manager has already written us off -- now exit.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800362 Process.killProcess(Process.myPid());
363 System.exit(10);
364 }
Dan Egnor60d87622009-12-16 16:32:58 -0800365 } catch (Throwable t2) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700366 if (t2 instanceof DeadObjectException) {
367 // System process is dead; ignore
368 } else {
369 Slog.e(TAG, "Error reporting WTF", t2);
370 Slog.e(TAG, "Original WTF:", t);
371 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800372 }
373 }
374
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800375 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800376 * Set the object identifying this application/process, for reporting VM
377 * errors.
378 */
379 public static final void setApplicationObject(IBinder app) {
380 mApplicationObject = app;
381 }
382
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700383 public static final IBinder getApplicationObject() {
384 return mApplicationObject;
385 }
386
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800387 /**
Piotr Jastrzebskida74a622015-02-12 13:55:23 +0000388 * Enable DDMS.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800389 */
Piotr Jastrzebskida74a622015-02-12 13:55:23 +0000390 static final void enableDdms() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800391 // Register handlers for DDM messages.
392 android.ddm.DdmRegister.registerHandlers();
393 }
Jeff Brownebed7d62011-05-16 17:08:42 -0700394
395 /**
396 * Handles argument parsing for args related to the runtime.
397 *
398 * Current recognized args:
399 * <ul>
400 * <li> <code> [--] &lt;start class name&gt; &lt;args&gt;
401 * </ul>
402 */
403 static class Arguments {
404 /** first non-option argument */
405 String startClass;
406
407 /** all following arguments */
408 String[] startArgs;
409
410 /**
411 * Constructs instance and parses args
412 * @param args runtime command-line args
413 * @throws IllegalArgumentException
414 */
415 Arguments(String args[]) throws IllegalArgumentException {
416 parseArgs(args);
417 }
418
419 /**
420 * Parses the commandline arguments intended for the Runtime.
421 */
422 private void parseArgs(String args[])
423 throws IllegalArgumentException {
424 int curArg = 0;
425 for (; curArg < args.length; curArg++) {
426 String arg = args[curArg];
427
428 if (arg.equals("--")) {
429 curArg++;
430 break;
431 } else if (!arg.startsWith("--")) {
432 break;
433 }
434 }
435
436 if (curArg == args.length) {
437 throw new IllegalArgumentException("Missing classname argument to RuntimeInit!");
438 }
439
440 startClass = args[curArg++];
441 startArgs = new String[args.length - curArg];
442 System.arraycopy(args, curArg, startArgs, 0, startArgs.length);
443 }
444 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800445}