FileDocCategorySizeDatePackage
RuntimeInit.javaAPI DocAndroid 1.5 API16249Wed May 06 22:41:56 BST 2009com.android.internal.os

RuntimeInit

public class RuntimeInit extends Object
Main entry point for runtime initialization. Not for public consumption.
hide

Fields Summary
private static final String
TAG
private static boolean
initialized
true if commonInit() has been called
private static final AtomicInteger
sInReportException
Counter used to prevent reentrancy in {@link #reportException}.
private static android.os.IBinder
mApplicationObject
Enable debugging features.
Constructors Summary
Methods Summary
private static final voidcommonInit()

        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;
    
public static voidcrash(java.lang.String tag, java.lang.Throwable t)
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

        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);
            }
        }
    
public static final native voidfinishInit()

public static native intgetQwertyKeyboard()

return
1 if the device has a qwerty keyboard

private static voidinvokeStaticMain(java.lang.String className, java.lang.String[] argv)
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()

        
        // 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 native intisComputerOn()
Returns 1 if the computer is on. If the computer isn't on, the value returned by this method is undefined.

public static final voidmain(java.lang.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!");
    
private static byte[]marshallException(java.lang.String tag, java.lang.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();
    
public static voidreportException(java.lang.String tag, java.lang.Throwable t, boolean sync)
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"


                                                                                
             
        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();
        }
    
public static final voidsetApplicationObject(android.os.IBinder app)
Set the object identifying this application/process, for reporting VM errors.

        mApplicationObject = app;
    
public static final native voidturnComputerOn()
Turns the computer on if the computer is off. If the computer is on, the behavior of this method is undefined.

public static android.server.data.CrashDataunmarshallException(byte[] crashDataBytes)
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.

        try {
            ByteArrayInputStream bin = new ByteArrayInputStream(crashDataBytes);
            DataInputStream din = new DataInputStream(bin);
            return new CrashData(din);
        } catch (IOException e) {
            return null;
        }
    
public static final voidzygoteInit(java.lang.String[] argv)
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.

Current recognized args:

  • --nice-name=nice name to appear in ps
  • [--] <start class name> <args>

param
argv arg strings

        // 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 voidzygoteInitNative()