19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2006 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage com.android.internal.os;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.app.ActivityManagerNative;
2035980b2cf51c06c1bdad66b7f8fb629d9c17052fEric Roweimport android.app.ActivityThread;
21b7f0367cec1c744aa66ef397b0244e25d507491cDan Egnorimport android.app.ApplicationErrorReport;
22b7f0367cec1c744aa66ef397b0244e25d507491cDan Egnorimport android.os.Build;
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Debug;
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.IBinder;
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Process;
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.SystemProperties;
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log;
28c9421ba1f46d9f9aeee833e1fde2cc263b058411Dianne Hackbornimport android.util.Slog;
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.internal.logging.AndroidConfig;
308568db534118fc14cc28100306d51626464ff319Jesse Wilsonimport com.android.server.NetworkManagementSocketTagger;
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport dalvik.system.VMRuntime;
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.lang.reflect.Method;
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.lang.reflect.Modifier;
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.TimeZone;
358568db534118fc14cc28100306d51626464ff319Jesse Wilsonimport java.util.logging.LogManager;
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.apache.harmony.luni.internal.util.TimezoneGetter;
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Main entry point for runtime initialization.  Not for
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * public consumption.
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class RuntimeInit {
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final static String TAG = "AndroidRuntime";
45ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown    private final static boolean DEBUG = false;
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** true if commonInit() has been called */
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static boolean initialized;
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5060d8762413e8daba5f73559786312a9ec5e3b827Dan Egnor    private static IBinder mApplicationObject;
5160d8762413e8daba5f73559786312a9ec5e3b827Dan Egnor
5260d8762413e8daba5f73559786312a9ec5e3b827Dan Egnor    private static volatile boolean mCrashing = false;
5360d8762413e8daba5f73559786312a9ec5e3b827Dan Egnor
5416f5f5cc9d4c480fac3dc7f176f3f1edfbd256f4Jeff Brown    private static final native void nativeZygoteInit();
5516f5f5cc9d4c480fac3dc7f176f3f1edfbd256f4Jeff Brown    private static final native void nativeFinishInit();
564280c4a93ea17f2e9d3f651e49d8c13dc3fb92aaJeff Brown    private static final native void nativeSetExitWithoutCleanup(boolean exitWithoutCleanup);
5716f5f5cc9d4c480fac3dc7f176f3f1edfbd256f4Jeff Brown
5869eb6f57e34fb78050adcedcda8479cf2ad0c418Mark Salyzyn    private static int Clog_e(String tag, String msg, Throwable tr) {
5969eb6f57e34fb78050adcedcda8479cf2ad0c418Mark Salyzyn        return Log.println_native(Log.LOG_ID_CRASH, Log.ERROR, tag,
6069eb6f57e34fb78050adcedcda8479cf2ad0c418Mark Salyzyn                msg + '\n' + Log.getStackTraceString(tr));
6169eb6f57e34fb78050adcedcda8479cf2ad0c418Mark Salyzyn    }
6269eb6f57e34fb78050adcedcda8479cf2ad0c418Mark Salyzyn
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Use this to log a message when a thread exits due to an uncaught
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * exception.  The framework catches these for the main threads, so
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * this should only matter for threads created by applications.
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static class UncaughtHandler implements Thread.UncaughtExceptionHandler {
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void uncaughtException(Thread t, Throwable e) {
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
7160d8762413e8daba5f73559786312a9ec5e3b827Dan Egnor                // Don't re-enter -- avoid infinite loops if crash-reporting crashes.
7260d8762413e8daba5f73559786312a9ec5e3b827Dan Egnor                if (mCrashing) return;
7360d8762413e8daba5f73559786312a9ec5e3b827Dan Egnor                mCrashing = true;
7460d8762413e8daba5f73559786312a9ec5e3b827Dan Egnor
7560d8762413e8daba5f73559786312a9ec5e3b827Dan Egnor                if (mApplicationObject == null) {
7669eb6f57e34fb78050adcedcda8479cf2ad0c418Mark Salyzyn                    Clog_e(TAG, "*** FATAL EXCEPTION IN SYSTEM PROCESS: " + t.getName(), e);
7760d8762413e8daba5f73559786312a9ec5e3b827Dan Egnor                } else {
7835980b2cf51c06c1bdad66b7f8fb629d9c17052fEric Rowe                    StringBuilder message = new StringBuilder();
7935980b2cf51c06c1bdad66b7f8fb629d9c17052fEric Rowe                    message.append("FATAL EXCEPTION: ").append(t.getName()).append("\n");
8035980b2cf51c06c1bdad66b7f8fb629d9c17052fEric Rowe                    final String processName = ActivityThread.currentProcessName();
8135980b2cf51c06c1bdad66b7f8fb629d9c17052fEric Rowe                    if (processName != null) {
8235980b2cf51c06c1bdad66b7f8fb629d9c17052fEric Rowe                        message.append("Process: ").append(processName).append(", ");
8335980b2cf51c06c1bdad66b7f8fb629d9c17052fEric Rowe                    }
8435980b2cf51c06c1bdad66b7f8fb629d9c17052fEric Rowe                    message.append("PID: ").append(Process.myPid());
8569eb6f57e34fb78050adcedcda8479cf2ad0c418Mark Salyzyn                    Clog_e(TAG, message.toString(), e);
8660d8762413e8daba5f73559786312a9ec5e3b827Dan Egnor                }
8760d8762413e8daba5f73559786312a9ec5e3b827Dan Egnor
8860d8762413e8daba5f73559786312a9ec5e3b827Dan Egnor                // Bring up crash dialog, wait for it to be dismissed
8960d8762413e8daba5f73559786312a9ec5e3b827Dan Egnor                ActivityManagerNative.getDefault().handleApplicationCrash(
9060d8762413e8daba5f73559786312a9ec5e3b827Dan Egnor                        mApplicationObject, new ApplicationErrorReport.CrashInfo(e));
9160d8762413e8daba5f73559786312a9ec5e3b827Dan Egnor            } catch (Throwable t2) {
9260d8762413e8daba5f73559786312a9ec5e3b827Dan Egnor                try {
9369eb6f57e34fb78050adcedcda8479cf2ad0c418Mark Salyzyn                    Clog_e(TAG, "Error reporting crash", t2);
9460d8762413e8daba5f73559786312a9ec5e3b827Dan Egnor                } catch (Throwable t3) {
9569eb6f57e34fb78050adcedcda8479cf2ad0c418Mark Salyzyn                    // Even Clog_e() fails!  Oh well.
9660d8762413e8daba5f73559786312a9ec5e3b827Dan Egnor                }
9760d8762413e8daba5f73559786312a9ec5e3b827Dan Egnor            } finally {
9860d8762413e8daba5f73559786312a9ec5e3b827Dan Egnor                // Try everything to make sure this process goes away.
9960d8762413e8daba5f73559786312a9ec5e3b827Dan Egnor                Process.killProcess(Process.myPid());
10060d8762413e8daba5f73559786312a9ec5e3b827Dan Egnor                System.exit(10);
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final void commonInit() {
106ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown        if (DEBUG) Slog.d(TAG, "Entered RuntimeInit!");
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /* set default handler; this applies to all threads in the VM */
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Thread.setDefaultUncaughtExceptionHandler(new UncaughtHandler());
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /*
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Install a TimezoneGetter subclass for ZoneInfo.db
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        TimezoneGetter.setInstance(new TimezoneGetter() {
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            @Override
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            public String getId() {
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return SystemProperties.get("persist.sys.timezone");
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        });
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        TimeZone.setDefault(null);
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /*
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Sets handler for java.util.logging to use Android log facilities.
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * The odd "new instance-and-then-throw-away" is a mirror of how
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * the "java.util.logging.config.class" system property works. We
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * can't use the system property here since the logger has almost
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * certainly already been initialized.
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LogManager.getLogManager().reset();
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        new AndroidConfig();
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /*
133d0f80d445644bfc08b62339f01766b924e42dc4dJesse Wilson         * Sets the default HTTP User-Agent used by HttpURLConnection.
134d0f80d445644bfc08b62339f01766b924e42dc4dJesse Wilson         */
135d0f80d445644bfc08b62339f01766b924e42dc4dJesse Wilson        String userAgent = getDefaultUserAgent();
136d0f80d445644bfc08b62339f01766b924e42dc4dJesse Wilson        System.setProperty("http.agent", userAgent);
137d0f80d445644bfc08b62339f01766b924e42dc4dJesse Wilson
138d0f80d445644bfc08b62339f01766b924e42dc4dJesse Wilson        /*
1398568db534118fc14cc28100306d51626464ff319Jesse Wilson         * Wire socket tagging to traffic stats.
1408568db534118fc14cc28100306d51626464ff319Jesse Wilson         */
1418568db534118fc14cc28100306d51626464ff319Jesse Wilson        NetworkManagementSocketTagger.install();
1428568db534118fc14cc28100306d51626464ff319Jesse Wilson
1438568db534118fc14cc28100306d51626464ff319Jesse Wilson        /*
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * If we're running in an emulator launched with "-trace", put the
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * VM into emulator trace profiling mode so that the user can hit
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * F9/F10 at any time to capture traces.  This has performance
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * consequences, so it's not something you want to do always.
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String trace = SystemProperties.get("ro.kernel.android.tracing");
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (trace.equals("1")) {
151c9421ba1f46d9f9aeee833e1fde2cc263b058411Dianne Hackborn            Slog.i(TAG, "NOTE: emulator trace profiling enabled");
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Debug.enableEmulatorTraceOutput();
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        initialized = true;
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
159d0f80d445644bfc08b62339f01766b924e42dc4dJesse Wilson     * Returns an HTTP user agent of the form
160d0f80d445644bfc08b62339f01766b924e42dc4dJesse Wilson     * "Dalvik/1.1.0 (Linux; U; Android Eclair Build/MASTER)".
161d0f80d445644bfc08b62339f01766b924e42dc4dJesse Wilson     */
162d0f80d445644bfc08b62339f01766b924e42dc4dJesse Wilson    private static String getDefaultUserAgent() {
163d0f80d445644bfc08b62339f01766b924e42dc4dJesse Wilson        StringBuilder result = new StringBuilder(64);
164d0f80d445644bfc08b62339f01766b924e42dc4dJesse Wilson        result.append("Dalvik/");
165d0f80d445644bfc08b62339f01766b924e42dc4dJesse Wilson        result.append(System.getProperty("java.vm.version")); // such as 1.1.0
166d0f80d445644bfc08b62339f01766b924e42dc4dJesse Wilson        result.append(" (Linux; U; Android ");
167d0f80d445644bfc08b62339f01766b924e42dc4dJesse Wilson
168d0f80d445644bfc08b62339f01766b924e42dc4dJesse Wilson        String version = Build.VERSION.RELEASE; // "1.0" or "3.4b5"
169d0f80d445644bfc08b62339f01766b924e42dc4dJesse Wilson        result.append(version.length() > 0 ? version : "1.0");
170d0f80d445644bfc08b62339f01766b924e42dc4dJesse Wilson
171d0f80d445644bfc08b62339f01766b924e42dc4dJesse Wilson        // add the model for the release build
172d0f80d445644bfc08b62339f01766b924e42dc4dJesse Wilson        if ("REL".equals(Build.VERSION.CODENAME)) {
173d0f80d445644bfc08b62339f01766b924e42dc4dJesse Wilson            String model = Build.MODEL;
174d0f80d445644bfc08b62339f01766b924e42dc4dJesse Wilson            if (model.length() > 0) {
175d0f80d445644bfc08b62339f01766b924e42dc4dJesse Wilson                result.append("; ");
176d0f80d445644bfc08b62339f01766b924e42dc4dJesse Wilson                result.append(model);
177d0f80d445644bfc08b62339f01766b924e42dc4dJesse Wilson            }
178d0f80d445644bfc08b62339f01766b924e42dc4dJesse Wilson        }
179d0f80d445644bfc08b62339f01766b924e42dc4dJesse Wilson        String id = Build.ID; // "MASTER" or "M4-rc20"
180d0f80d445644bfc08b62339f01766b924e42dc4dJesse Wilson        if (id.length() > 0) {
181d0f80d445644bfc08b62339f01766b924e42dc4dJesse Wilson            result.append(" Build/");
182d0f80d445644bfc08b62339f01766b924e42dc4dJesse Wilson            result.append(id);
183d0f80d445644bfc08b62339f01766b924e42dc4dJesse Wilson        }
184d0f80d445644bfc08b62339f01766b924e42dc4dJesse Wilson        result.append(")");
185d0f80d445644bfc08b62339f01766b924e42dc4dJesse Wilson        return result.toString();
186d0f80d445644bfc08b62339f01766b924e42dc4dJesse Wilson    }
187d0f80d445644bfc08b62339f01766b924e42dc4dJesse Wilson
188d0f80d445644bfc08b62339f01766b924e42dc4dJesse Wilson    /**
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Invokes a static "main(argv[]) method on class "className".
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Converts various failing exceptions into RuntimeExceptions, with
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the assumption that they will then cause the VM instance to exit.
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param className Fully-qualified class name
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param argv Argument vector for main()
19529564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath     * @param classLoader the classLoader to load {@className} with
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
19729564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath    private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throws ZygoteInit.MethodAndArgsCaller {
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Class<?> cl;
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
20229564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath            cl = Class.forName(className, true, classLoader);
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (ClassNotFoundException ex) {
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new RuntimeException(
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    "Missing class when invoking static main " + className,
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ex);
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Method m;
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            m = cl.getMethod("main", new Class[] { String[].class });
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (NoSuchMethodException ex) {
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new RuntimeException(
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    "Missing static main on " + className, ex);
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (SecurityException ex) {
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new RuntimeException(
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    "Problem getting static main on " + className, ex);
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int modifiers = m.getModifiers();
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new RuntimeException(
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    "Main method is not public and static on " + className);
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /*
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * This throw gets caught in ZygoteInit.main(), which responds
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * by invoking the exception's run() method. This arrangement
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * clears up all the stack frames that were required in setting
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * up the process.
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        throw new ZygoteInit.MethodAndArgsCaller(m, argv);
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final void main(String[] argv) {
236ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown        if (argv.length == 2 && argv[1].equals("application")) {
237ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown            if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application");
238ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown            redirectLogStreams();
239ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown        } else {
240ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown            if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting tool");
241ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown        }
242ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        commonInit();
244e540833fdff4d58e37c9ba859388e24e2945ed45Bob Lee
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /*
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Now that we're running in interpreted code, call back into native code
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * to run the system.
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
24916f5f5cc9d4c480fac3dc7f176f3f1edfbd256f4Jeff Brown        nativeFinishInit();
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
251ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown        if (DEBUG) Slog.d(TAG, "Leaving RuntimeInit!");
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
253e540833fdff4d58e37c9ba859388e24e2945ed45Bob Lee
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The main function called when started through the zygote process. This
25616f5f5cc9d4c480fac3dc7f176f3f1edfbd256f4Jeff Brown     * could be unified with main(), if the native code in nativeFinishInit()
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * were rationalized with Zygote startup.<p>
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Current recognized args:
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <ul>
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li> <code> [--] &lt;start class name&gt;  &lt;args&gt;
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * </ul>
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
264e1dfcb7ab01fb991079ec1f70f75281a0ca9073eElliott Hughes     * @param targetSdkVersion target SDK version
2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param argv arg strings
2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
26729564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath    public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throws ZygoteInit.MethodAndArgsCaller {
269ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown        if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");
270ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown
271ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown        redirectLogStreams();
2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        commonInit();
27416f5f5cc9d4c480fac3dc7f176f3f1edfbd256f4Jeff Brown        nativeZygoteInit();
2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
27629564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath        applicationInit(targetSdkVersion, argv, classLoader);
277ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown    }
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
279ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown    /**
280ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown     * The main function called when an application is started through a
281ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown     * wrapper process.
282ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown     *
283ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown     * When the wrapper starts, the runtime starts {@link RuntimeInit#main}
284ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown     * which calls {@link WrapperInit#main} which then calls this method.
285ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown     * So we don't need to call commonInit() here.
286ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown     *
287e1dfcb7ab01fb991079ec1f70f75281a0ca9073eElliott Hughes     * @param targetSdkVersion target SDK version
288ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown     * @param argv arg strings
289ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown     */
290e1dfcb7ab01fb991079ec1f70f75281a0ca9073eElliott Hughes    public static void wrapperInit(int targetSdkVersion, String[] argv)
291ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown            throws ZygoteInit.MethodAndArgsCaller {
292ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown        if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from wrapper");
293ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown
29429564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath        applicationInit(targetSdkVersion, argv, null);
295ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown    }
296ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown
29729564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath    private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
298ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown            throws ZygoteInit.MethodAndArgsCaller {
2994280c4a93ea17f2e9d3f651e49d8c13dc3fb92aaJeff Brown        // If the application calls System.exit(), terminate the process
3004280c4a93ea17f2e9d3f651e49d8c13dc3fb92aaJeff Brown        // immediately without running any shutdown hooks.  It is not possible to
3014280c4a93ea17f2e9d3f651e49d8c13dc3fb92aaJeff Brown        // shutdown an Android application gracefully.  Among other things, the
3024280c4a93ea17f2e9d3f651e49d8c13dc3fb92aaJeff Brown        // Android runtime shutdown hooks close the Binder driver, which can cause
3034280c4a93ea17f2e9d3f651e49d8c13dc3fb92aaJeff Brown        // leftover running threads to crash before the process actually exits.
3044280c4a93ea17f2e9d3f651e49d8c13dc3fb92aaJeff Brown        nativeSetExitWithoutCleanup(true);
3054280c4a93ea17f2e9d3f651e49d8c13dc3fb92aaJeff Brown
306ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown        // We want to be fairly aggressive about heap utilization, to avoid
307ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown        // holding on to a lot of memory that isn't needed.
308ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown        VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
309e1dfcb7ab01fb991079ec1f70f75281a0ca9073eElliott Hughes        VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
310ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown
311ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown        final Arguments args;
312ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown        try {
313ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown            args = new Arguments(argv);
314ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown        } catch (IllegalArgumentException ex) {
315ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown            Slog.e(TAG, ex.getMessage());
3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // let the process exit
3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Remaining arguments are passed to the start class's static main
32129564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath        invokeStaticMain(args.startClass, args.startArgs, classLoader);
322ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown    }
323e540833fdff4d58e37c9ba859388e24e2945ed45Bob Lee
324ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown    /**
325ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown     * Redirect System.out and System.err to the Android log.
326ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown     */
327ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown    public static void redirectLogStreams() {
328ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown        System.out.close();
329ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown        System.setOut(new AndroidPrintStream(Log.INFO, "System.out"));
330ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown        System.err.close();
331ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown        System.setErr(new AndroidPrintStream(Log.WARN, "System.err"));
3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
33560d8762413e8daba5f73559786312a9ec5e3b827Dan Egnor     * Report a serious error in the current process.  May or may not cause
33660d8762413e8daba5f73559786312a9ec5e3b827Dan Egnor     * the process to terminate (depends on system settings).
337e540833fdff4d58e37c9ba859388e24e2945ed45Bob Lee     *
33860d8762413e8daba5f73559786312a9ec5e3b827Dan Egnor     * @param tag to record with the error
33960d8762413e8daba5f73559786312a9ec5e3b827Dan Egnor     * @param t exception describing the error site and conditions
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3415232271a41323594ae406be7476b6ca2f08af3d8Dianne Hackborn    public static void wtf(String tag, Throwable t, boolean system) {
34260d8762413e8daba5f73559786312a9ec5e3b827Dan Egnor        try {
34360d8762413e8daba5f73559786312a9ec5e3b827Dan Egnor            if (ActivityManagerNative.getDefault().handleApplicationWtf(
3445232271a41323594ae406be7476b6ca2f08af3d8Dianne Hackborn                    mApplicationObject, tag, system, new ApplicationErrorReport.CrashInfo(t))) {
34560d8762413e8daba5f73559786312a9ec5e3b827Dan Egnor                // The Activity Manager has already written us off -- now exit.
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Process.killProcess(Process.myPid());
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                System.exit(10);
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
34960d8762413e8daba5f73559786312a9ec5e3b827Dan Egnor        } catch (Throwable t2) {
350c9421ba1f46d9f9aeee833e1fde2cc263b058411Dianne Hackborn            Slog.e(TAG, "Error reporting WTF", t2);
351941adc95e121332b49aedb5406b6037a6395aea6Christopher Tate            Slog.e(TAG, "Original WTF:", t);
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Set the object identifying this application/process, for reporting VM
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * errors.
3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final void setApplicationObject(IBinder app) {
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mApplicationObject = app;
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
363438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick    public static final IBinder getApplicationObject() {
364438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick        return mApplicationObject;
365438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick    }
366438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Enable debugging features.
3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static {
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Register handlers for DDM messages.
3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        android.ddm.DdmRegister.registerHandlers();
3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
374ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown
375ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown    /**
376ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown     * Handles argument parsing for args related to the runtime.
377ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown     *
378ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown     * Current recognized args:
379ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown     * <ul>
380ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown     *   <li> <code> [--] &lt;start class name&gt;  &lt;args&gt;
381ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown     * </ul>
382ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown     */
383ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown    static class Arguments {
384ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown        /** first non-option argument */
385ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown        String startClass;
386ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown
387ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown        /** all following arguments */
388ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown        String[] startArgs;
389ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown
390ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown        /**
391ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown         * Constructs instance and parses args
392ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown         * @param args runtime command-line args
393ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown         * @throws IllegalArgumentException
394ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown         */
395ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown        Arguments(String args[]) throws IllegalArgumentException {
396ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown            parseArgs(args);
397ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown        }
398ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown
399ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown        /**
400ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown         * Parses the commandline arguments intended for the Runtime.
401ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown         */
402ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown        private void parseArgs(String args[])
403ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown                throws IllegalArgumentException {
404ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown            int curArg = 0;
405ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown            for (; curArg < args.length; curArg++) {
406ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown                String arg = args[curArg];
407ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown
408ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown                if (arg.equals("--")) {
409ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown                    curArg++;
410ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown                    break;
411ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown                } else if (!arg.startsWith("--")) {
412ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown                    break;
413ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown                }
414ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown            }
415ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown
416ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown            if (curArg == args.length) {
417ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown                throw new IllegalArgumentException("Missing classname argument to RuntimeInit!");
418ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown            }
419ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown
420ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown            startClass = args[curArg++];
421ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown            startArgs = new String[args.length - curArg];
422ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown            System.arraycopy(args, curArg, startArgs, 0, startArgs.length);
423ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown        }
424ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown    }
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
426