diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 18:28:45 -0800 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 18:28:45 -0800 |
commit | d83a98f4ce9cfa908f5c54bbd70f03eec07e7553 (patch) | |
tree | 4b825dc642cb6eb9a060e54bf8d69288fbee4904 /core/java/com/android/internal/os/RuntimeInit.java | |
parent | 076357b8567458d4b6dfdcf839ef751634cd2bfb (diff) | |
download | frameworks_base-d83a98f4ce9cfa908f5c54bbd70f03eec07e7553.zip frameworks_base-d83a98f4ce9cfa908f5c54bbd70f03eec07e7553.tar.gz frameworks_base-d83a98f4ce9cfa908f5c54bbd70f03eec07e7553.tar.bz2 |
auto import from //depot/cupcake/@135843
Diffstat (limited to 'core/java/com/android/internal/os/RuntimeInit.java')
-rw-r--r-- | core/java/com/android/internal/os/RuntimeInit.java | 440 |
1 files changed, 0 insertions, 440 deletions
diff --git a/core/java/com/android/internal/os/RuntimeInit.java b/core/java/com/android/internal/os/RuntimeInit.java deleted file mode 100644 index 8486272..0000000 --- a/core/java/com/android/internal/os/RuntimeInit.java +++ /dev/null @@ -1,440 +0,0 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.internal.os; - -import android.app.ActivityManagerNative; -import android.app.IActivityManager; -import android.os.Debug; -import android.os.IBinder; -import android.os.ICheckinService; -import android.os.Process; -import android.os.RemoteException; -import android.os.ServiceManager; -import android.os.SystemProperties; -import android.server.data.CrashData; -import android.util.Config; -import android.util.Log; - -import com.android.internal.logging.AndroidConfig; - -import dalvik.system.VMRuntime; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.IOException; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.logging.LogManager; -import java.util.TimeZone; - -import org.apache.harmony.luni.internal.util.TimezoneGetter; - -/** - * Main entry point for runtime initialization. Not for - * public consumption. - * @hide - */ -public class RuntimeInit { - private final static String TAG = "AndroidRuntime"; - - /** true if commonInit() has been called */ - private static boolean initialized; - - /** - * Use this to log a message when a thread exits due to an uncaught - * exception. The framework catches these for the main threads, so - * this should only matter for threads created by applications. - */ - private static class UncaughtHandler implements Thread.UncaughtExceptionHandler { - public void uncaughtException(Thread t, Throwable e) { - try { - Log.e(TAG, "Uncaught handler: thread " + t.getName() - + " exiting due to uncaught exception"); - } catch (Throwable error) { - // Ignore the throwable, since we're in the process of crashing anyway. - // If we don't, the crash won't happen properly and the process will - // be left around in a bad state. - } - crash(TAG, e); - } - } - - private static final void commonInit() { - if (Config.LOGV) Log.d(TAG, "Entered RuntimeInit!"); - - /* set default handler; this applies to all threads in the VM */ - Thread.setDefaultUncaughtExceptionHandler(new UncaughtHandler()); - - int hasQwerty = getQwertyKeyboard(); - - if (Config.LOGV) Log.d(TAG, ">>>>> qwerty keyboard = " + hasQwerty); - if (hasQwerty == 1) { - System.setProperty("qwerty", "1"); - } - - /* - * Install a TimezoneGetter subclass for ZoneInfo.db - */ - TimezoneGetter.setInstance(new TimezoneGetter() { - @Override - public String getId() { - return SystemProperties.get("persist.sys.timezone"); - } - }); - TimeZone.setDefault(null); - - /* - * Sets handler for java.util.logging to use Android log facilities. - * The odd "new instance-and-then-throw-away" is a mirror of how - * the "java.util.logging.config.class" system property works. We - * can't use the system property here since the logger has almost - * certainly already been initialized. - */ - LogManager.getLogManager().reset(); - new AndroidConfig(); - - /* - * If we're running in an emulator launched with "-trace", put the - * VM into emulator trace profiling mode so that the user can hit - * F9/F10 at any time to capture traces. This has performance - * consequences, so it's not something you want to do always. - */ - String trace = SystemProperties.get("ro.kernel.android.tracing"); - if (trace.equals("1")) { - Log.i(TAG, "NOTE: emulator trace profiling enabled"); - Debug.enableEmulatorTraceOutput(); - } - - initialized = true; - } - - /** - * Invokes a static "main(argv[]) method on class "className". - * Converts various failing exceptions into RuntimeExceptions, with - * the assumption that they will then cause the VM instance to exit. - * - * @param className Fully-qualified class name - * @param argv Argument vector for main() - */ - private static void invokeStaticMain(String className, String[] argv) - throws ZygoteInit.MethodAndArgsCaller { - - // We want to be fairly aggressive about heap utilization, to avoid - // holding on to a lot of memory that isn't needed. - VMRuntime.getRuntime().setTargetHeapUtilization(0.75f); - - Class<?> cl; - - try { - cl = Class.forName(className); - } catch (ClassNotFoundException ex) { - throw new RuntimeException( - "Missing class when invoking static main " + className, - ex); - } - - Method m; - try { - m = cl.getMethod("main", new Class[] { String[].class }); - } catch (NoSuchMethodException ex) { - throw new RuntimeException( - "Missing static main on " + className, ex); - } catch (SecurityException ex) { - throw new RuntimeException( - "Problem getting static main on " + className, ex); - } - - int modifiers = m.getModifiers(); - if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) { - throw new RuntimeException( - "Main method is not public and static on " + className); - } - - /* - * This throw gets caught in ZygoteInit.main(), which responds - * by invoking the exception's run() method. This arrangement - * clears up all the stack frames that were required in setting - * up the process. - */ - throw new ZygoteInit.MethodAndArgsCaller(m, argv); - } - - public static final void main(String[] argv) { - commonInit(); - - /* - * Now that we're running in interpreted code, call back into native code - * to run the system. - */ - finishInit(); - - if (Config.LOGV) Log.d(TAG, "Leaving RuntimeInit!"); - } - - public static final native void finishInit(); - - /** - * The main function called when started through the zygote process. This - * could be unified with main(), if the native code in finishInit() - * were rationalized with Zygote startup.<p> - * - * Current recognized args: - * <ul> - * <li> --nice-name=<i>nice name to appear in ps</i> - * <li> <code> [--] <start class name> <args> - * </ul> - * - * @param argv arg strings - */ - public static final void zygoteInit(String[] argv) - throws ZygoteInit.MethodAndArgsCaller { - // TODO: Doing this here works, but it seems kind of arbitrary. Find - // a better place. The goal is to set it up for applications, but not - // tools like am. - System.setOut(new AndroidPrintStream(Log.INFO, "System.out")); - System.setErr(new AndroidPrintStream(Log.WARN, "System.err")); - - commonInit(); - zygoteInitNative(); - - int curArg = 0; - for ( /* curArg */ ; curArg < argv.length; curArg++) { - String arg = argv[curArg]; - - if (arg.equals("--")) { - curArg++; - break; - } else if (!arg.startsWith("--")) { - break; - } else if (arg.startsWith("--nice-name=")) { - String niceName = arg.substring(arg.indexOf('=') + 1); - Process.setArgV0(niceName); - } - } - - if (curArg == argv.length) { - Log.e(TAG, "Missing classname argument to RuntimeInit!"); - // let the process exit - return; - } - - // Remaining arguments are passed to the start class's static main - - String startClass = argv[curArg++]; - String[] startArgs = new String[argv.length - curArg]; - - System.arraycopy(argv, curArg, startArgs, 0, startArgs.length); - invokeStaticMain(startClass, startArgs); - } - - public static final native void zygoteInitNative(); - - /** - * Returns 1 if the computer is on. If the computer isn't on, the value returned by this method is undefined. - */ - public static final native int isComputerOn(); - - /** - * Turns the computer on if the computer is off. If the computer is on, the behavior of this method is undefined. - */ - public static final native void turnComputerOn(); - - /** - * - * @return 1 if the device has a qwerty keyboard - */ - public static native int getQwertyKeyboard(); - - /** - * Report a fatal error in the current process. If this is a user-process, - * a dialog may be displayed informing the user of the error. This - * function does not return; it forces the current process to exit. - * - * @param tag to use when logging the error - * @param t exception that was generated by the error - */ - public static void crash(String tag, Throwable t) { - if (mApplicationObject != null) { - byte[] crashData = null; - try { - // Log exception. - Log.e(TAG, Log.getStackTraceString(t)); - crashData = marshallException(tag, t); - if (crashData == null) { - throw new NullPointerException("Can't marshall crash data"); - } - } catch (Throwable t2) { - try { - // Log exception as a string so we don't get in an infinite loop. - Log.e(TAG, "Error reporting crash: " - + Log.getStackTraceString(t2)); - } catch (Throwable t3) { - // Do nothing, must be OOM so we can't format the message - } - } - - try { - // Display user-visible error message. - String msg = t.getMessage(); - if (msg == null) { - msg = t.toString(); - } - - IActivityManager am = ActivityManagerNative.getDefault(); - try { - int res = am.handleApplicationError(mApplicationObject, - 0, tag, msg, t.toString(), crashData); - // Is waiting for the debugger the right thing? - // For now I have turned off the Debug button, because - // I'm not sure what we should do if it is actually - // selected. - //Log.i(TAG, "Got app error result: " + res); - if (res == 1) { - Debug.waitForDebugger(); - return; - } - } catch (RemoteException e) { - } - } catch (Throwable t2) { - try { - // Log exception as a string so we don't get in an infinite loop. - Log.e(TAG, "Error reporting crash: " - + Log.getStackTraceString(t2)); - } catch (Throwable t3) { - // Do nothing, must be OOM so we can't format the message - } - } finally { - // Try everything to make sure this process goes away. - Process.killProcess(Process.myPid()); - System.exit(10); - } - } else { - try { - Log.e(TAG, "*** EXCEPTION IN SYSTEM PROCESS. System will crash."); - Log.e(tag, Log.getStackTraceString(t)); - reportException(tag, t, true); // synchronous - } catch (Throwable t2) { - // Do nothing, must be OOM so we can't format the message - } finally { - // Try everything to make sure this process goes away. - Process.killProcess(Process.myPid()); - System.exit(10); - } - } - } - - /** Counter used to prevent reentrancy in {@link #reportException}. */ - private static final AtomicInteger sInReportException = new AtomicInteger(); - - /** - * Report an error in the current process. The exception information will - * be handed off to the checkin service and eventually uploaded for analysis. - * This is expensive! Only use this when the exception indicates a programming - * error ("should not happen"). - * - * @param tag to use when logging the error - * @param t exception that was generated by the error - * @param sync true to wait for the report, false to "fire and forget" - */ - public static void reportException(String tag, Throwable t, boolean sync) { - if (!initialized) { - // Exceptions during, eg, zygote cannot use this mechanism - return; - } - - // It's important to prevent an infinite crash-reporting loop: - // while this function is running, don't let it be called again. - int reenter = sInReportException.getAndIncrement(); - if (reenter != 0) { - sInReportException.decrementAndGet(); - Log.e(TAG, "Crash logging skipped, already logging another crash"); - return; - } - - // TODO: Enable callers to specify a level (i.e. warn or error). - try { - // Submit crash data to statistics service. - byte[] crashData = marshallException(tag, t); - ICheckinService checkin = ICheckinService.Stub.asInterface( - ServiceManager.getService("checkin")); - if (checkin == null) { - Log.e(TAG, "Crash logging skipped, no checkin service"); - } else if (sync) { - checkin.reportCrashSync(crashData); - } else { - checkin.reportCrashAsync(crashData); - } - } catch (Throwable t2) { - // Log exception as a string so we don't get in an infinite loop. - Log.e(TAG, "Crash logging failed: " + t2); - } finally { - sInReportException.decrementAndGet(); - } - } - - private static byte[] marshallException(String tag, Throwable t) { - // Convert crash data to bytes. - ByteArrayOutputStream bout = new ByteArrayOutputStream(); - DataOutputStream dout = new DataOutputStream(bout); - try { - new CrashData(tag, t).write(dout); - dout.close(); - } catch (IOException e) { - return null; - } - return bout.toByteArray(); - } - - /** - * Replay an encoded CrashData record back into a useable CrashData record. This can be - * helpful for providing debugging output after a process error. - * - * @param crashDataBytes The byte array containing the encoded crash record - * @return new CrashData record, or null if could not create one. - */ - public static CrashData unmarshallException(byte[] crashDataBytes) { - try { - ByteArrayInputStream bin = new ByteArrayInputStream(crashDataBytes); - DataInputStream din = new DataInputStream(bin); - return new CrashData(din); - } catch (IOException e) { - return null; - } - } - - /** - * Set the object identifying this application/process, for reporting VM - * errors. - */ - public static final void setApplicationObject(IBinder app) { - mApplicationObject = app; - } - - /** - * Enable debugging features. - */ - static { - // Register handlers for DDM messages. - android.ddm.DdmRegister.registerHandlers(); - } - - private static IBinder mApplicationObject; - -} |