Replace a custom AndroidRuntime::findClass with a more targeted fix.
This seems simpler and more contained, and I think the comment explaining why hoop-jumping is necessary is a bit clearer now. Change-Id: Ief4afd7cbb42188ed835fce23e497520bdb753a8
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* Main entry of app process.
|
||||
*
|
||||
*
|
||||
* Starts the interpreted runtime, then starts up the application.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#define LOG_TAG "appproc"
|
||||
@@ -25,23 +25,13 @@ void app_usage()
|
||||
"Usage: app_process [java-options] cmd-dir start-class-name [options]\n");
|
||||
}
|
||||
|
||||
status_t app_init(const char* className, int argc, const char* const argv[])
|
||||
{
|
||||
LOGV("Entered app_init()!\n");
|
||||
|
||||
AndroidRuntime* jr = AndroidRuntime::getRuntime();
|
||||
jr->callMain(className, argc, argv);
|
||||
|
||||
LOGV("Exiting app_init()!\n");
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
class AppRuntime : public AndroidRuntime
|
||||
{
|
||||
public:
|
||||
AppRuntime()
|
||||
: mParentDir(NULL)
|
||||
, mClassName(NULL)
|
||||
, mClass(NULL)
|
||||
, mArgC(0)
|
||||
, mArgV(NULL)
|
||||
{
|
||||
@@ -60,6 +50,35 @@ public:
|
||||
return mClassName;
|
||||
}
|
||||
|
||||
virtual void onVmCreated(JNIEnv* env)
|
||||
{
|
||||
if (mClassName == NULL) {
|
||||
return; // Zygote. Nothing to do here.
|
||||
}
|
||||
|
||||
/*
|
||||
* This is a little awkward because the JNI FindClass call uses the
|
||||
* class loader associated with the native method we're executing in.
|
||||
* If called in onStarted (from RuntimeInit.finishInit because we're
|
||||
* launching "am", for example), FindClass would see that we're calling
|
||||
* from a boot class' native method, and so wouldn't look for the class
|
||||
* we're trying to look up in CLASSPATH. Unfortunately it needs to,
|
||||
* because the "am" classes are not boot classes.
|
||||
*
|
||||
* The easiest fix is to call FindClass here, early on before we start
|
||||
* executing boot class Java code and thereby deny ourselves access to
|
||||
* non-boot classes.
|
||||
*/
|
||||
char* slashClassName = toSlashClassName(mClassName);
|
||||
mClass = env->FindClass(slashClassName);
|
||||
if (mClass == NULL) {
|
||||
LOGE("ERROR: could not find class '%s'\n", mClassName);
|
||||
}
|
||||
free(slashClassName);
|
||||
|
||||
mClass = reinterpret_cast<jclass>(env->NewGlobalRef(mClass));
|
||||
}
|
||||
|
||||
virtual void onStarted()
|
||||
{
|
||||
sp<ProcessState> proc = ProcessState::self();
|
||||
@@ -67,8 +86,9 @@ public:
|
||||
LOGV("App process: starting thread pool.\n");
|
||||
proc->startThreadPool();
|
||||
}
|
||||
|
||||
app_init(mClassName, mArgC, mArgV);
|
||||
|
||||
AndroidRuntime* ar = AndroidRuntime::getRuntime();
|
||||
ar->callMain(mClassName, mClass, mArgC, mArgV);
|
||||
|
||||
if (ProcessState::self()->supportsProcesses()) {
|
||||
IPCThreadState::self()->stopProcess();
|
||||
@@ -81,7 +101,7 @@ public:
|
||||
if (proc->supportsProcesses()) {
|
||||
LOGV("App process: starting thread pool.\n");
|
||||
proc->startThreadPool();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual void onExit(int code)
|
||||
@@ -96,9 +116,10 @@ public:
|
||||
AndroidRuntime::onExit(code);
|
||||
}
|
||||
|
||||
|
||||
|
||||
const char* mParentDir;
|
||||
const char* mClassName;
|
||||
jclass mClass;
|
||||
int mArgC;
|
||||
const char* const* mArgV;
|
||||
};
|
||||
@@ -120,7 +141,7 @@ int main(int argc, const char* const argv[])
|
||||
// These are global variables in ProcessState.cpp
|
||||
mArgC = argc;
|
||||
mArgV = argv;
|
||||
|
||||
|
||||
mArgLen = 0;
|
||||
for (int i=0; i<argc; i++) {
|
||||
mArgLen += strlen(argv[i]) + 1;
|
||||
@@ -139,7 +160,7 @@ int main(int argc, const char* const argv[])
|
||||
argv++;
|
||||
|
||||
// Everything up to '--' or first non '-' arg goes to the vm
|
||||
|
||||
|
||||
int i = runtime.addVmArguments(argc, argv);
|
||||
|
||||
// Next arg is parent directory
|
||||
@@ -151,7 +172,7 @@ int main(int argc, const char* const argv[])
|
||||
if (i < argc) {
|
||||
arg = argv[i++];
|
||||
if (0 == strcmp("--zygote", arg)) {
|
||||
bool startSystemServer = (i < argc) ?
|
||||
bool startSystemServer = (i < argc) ?
|
||||
strcmp(argv[i], "--start-system-server") == 0 : false;
|
||||
setArgv0(argv0, "zygote");
|
||||
set_process_name("zygote");
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
#include <binder/IPCThreadState.h>
|
||||
#include <binder/ProcessState.h>
|
||||
#include <utils/Log.h>
|
||||
#include <utils/Log.h>
|
||||
#include <cutils/zygote.h>
|
||||
|
||||
#include <cutils/properties.h>
|
||||
@@ -41,7 +41,7 @@
|
||||
#undef LOG_TAG
|
||||
#define LOG_TAG "runtime"
|
||||
|
||||
static const char* ZYGOTE_ARGV[] = {
|
||||
static const char* ZYGOTE_ARGV[] = {
|
||||
"--setuid=1000",
|
||||
"--setgid=1000",
|
||||
"--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,3001,3002,3003",
|
||||
@@ -68,7 +68,6 @@ extern Condition gEventQCondition;
|
||||
|
||||
namespace android {
|
||||
|
||||
extern status_t app_init(const char* className);
|
||||
extern void set_finish_init_func(void (*func)());
|
||||
|
||||
|
||||
@@ -76,7 +75,7 @@ extern void set_finish_init_func(void (*func)());
|
||||
* This class is used to kill this process (runtime) when the system_server dies.
|
||||
*/
|
||||
class GrimReaper : public IBinder::DeathRecipient {
|
||||
public:
|
||||
public:
|
||||
GrimReaper() { }
|
||||
|
||||
virtual void binderDied(const wp<IBinder>& who)
|
||||
@@ -170,7 +169,7 @@ LOGI("run() sending FIRST_CALL_TRANSACTION to activity manager");
|
||||
|
||||
/*
|
||||
* Post-system-process initialization.
|
||||
*
|
||||
*
|
||||
* This function continues initialization after the system process
|
||||
* has been initialized. It needs to be separate because the system
|
||||
* initialization needs to care of starting the Android runtime if it is not
|
||||
@@ -210,17 +209,17 @@ static bool contextChecker(
|
||||
static void boot_init()
|
||||
{
|
||||
LOGI("Entered boot_init()!\n");
|
||||
|
||||
|
||||
sp<ProcessState> proc(ProcessState::self());
|
||||
LOGD("ProcessState: %p\n", proc.get());
|
||||
proc->becomeContextManager(contextChecker, NULL);
|
||||
|
||||
|
||||
if (proc->supportsProcesses()) {
|
||||
LOGI("Binder driver opened. Multiprocess enabled.\n");
|
||||
} else {
|
||||
LOGI("Binder driver not found. Processes not supported.\n");
|
||||
}
|
||||
|
||||
|
||||
sp<BServiceManager> sm = new BServiceManager;
|
||||
proc->setContextObject(sm);
|
||||
}
|
||||
@@ -258,7 +257,7 @@ static void validateTime()
|
||||
int res;
|
||||
time_t min_time = 1167652800; // jan 1 2007, type 'date -ud "1/1 12:00" +%s' to get value for current year
|
||||
struct timespec ts;
|
||||
|
||||
|
||||
fd = open("/dev/alarm", O_RDWR);
|
||||
if(fd < 0) {
|
||||
LOGW("Unable to open alarm driver: %s\n", strerror(errno));
|
||||
@@ -346,14 +345,14 @@ int main(int argc, char* const argv[])
|
||||
int ic;
|
||||
int result = 1;
|
||||
pid_t systemPid;
|
||||
|
||||
|
||||
sp<ProcessState> proc;
|
||||
|
||||
#ifndef HAVE_ANDROID_OS
|
||||
/* Set stdout/stderr to unbuffered for MinGW/MSYS. */
|
||||
//setvbuf(stdout, NULL, _IONBF, 0);
|
||||
//setvbuf(stderr, NULL, _IONBF, 0);
|
||||
|
||||
|
||||
LOGI("commandline args:\n");
|
||||
for (int i = 0; i < argc; i++)
|
||||
LOGI(" %2d: '%s'\n", i, argv[i]);
|
||||
@@ -455,7 +454,7 @@ int main(int argc, char* const argv[])
|
||||
|
||||
#if 0
|
||||
// Hack to keep libc from beating the filesystem to death. It's
|
||||
// hitting /etc/localtime frequently,
|
||||
// hitting /etc/localtime frequently,
|
||||
//
|
||||
// This statement locks us into Pacific time. We could do better,
|
||||
// but there's not much point until we're sure that the library
|
||||
@@ -467,15 +466,15 @@ int main(int argc, char* const argv[])
|
||||
|
||||
/* track our progress through the boot sequence */
|
||||
const int LOG_BOOT_PROGRESS_START = 3000;
|
||||
LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START,
|
||||
LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START,
|
||||
ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
|
||||
|
||||
validateTime();
|
||||
|
||||
proc = ProcessState::self();
|
||||
|
||||
|
||||
boot_init();
|
||||
|
||||
|
||||
/* If we are in multiprocess mode, have zygote spawn the system
|
||||
* server process and call system_init(). If we are running in
|
||||
* single process mode just call system_init() directly.
|
||||
@@ -488,8 +487,8 @@ int main(int argc, char* const argv[])
|
||||
property_get("log.redirect-stdio", propBuf, "");
|
||||
logStdio = (strcmp(propBuf, "true") == 0);
|
||||
|
||||
zygote_run_oneshot((int)(!logStdio),
|
||||
sizeof(ZYGOTE_ARGV) / sizeof(ZYGOTE_ARGV[0]),
|
||||
zygote_run_oneshot((int)(!logStdio),
|
||||
sizeof(ZYGOTE_ARGV) / sizeof(ZYGOTE_ARGV[0]),
|
||||
ZYGOTE_ARGV);
|
||||
|
||||
//start_process("/system/bin/mediaserver");
|
||||
@@ -497,7 +496,7 @@ int main(int argc, char* const argv[])
|
||||
} else {
|
||||
#ifndef HAVE_ANDROID_OS
|
||||
QuickRuntime* runt = new QuickRuntime();
|
||||
runt->start("com/android/server/SystemServer",
|
||||
runt->start("com/android/server/SystemServer",
|
||||
false /* spontaneously fork system server from zygote */);
|
||||
#endif
|
||||
}
|
||||
@@ -506,11 +505,11 @@ int main(int argc, char* const argv[])
|
||||
|
||||
finish_system_init(proc);
|
||||
run(proc);
|
||||
|
||||
|
||||
bail:
|
||||
if (proc != NULL) {
|
||||
proc->setContextObject(NULL);
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace android {
|
||||
* This class is used to kill this process when the runtime dies.
|
||||
*/
|
||||
class GrimReaper : public IBinder::DeathRecipient {
|
||||
public:
|
||||
public:
|
||||
GrimReaper() { }
|
||||
|
||||
virtual void binderDied(const wp<IBinder>& who)
|
||||
@@ -54,15 +54,15 @@ public:
|
||||
extern "C" status_t system_init()
|
||||
{
|
||||
LOGI("Entered system_init()");
|
||||
|
||||
|
||||
sp<ProcessState> proc(ProcessState::self());
|
||||
|
||||
|
||||
sp<IServiceManager> sm = defaultServiceManager();
|
||||
LOGI("ServiceManager: %p\n", sm.get());
|
||||
|
||||
|
||||
sp<GrimReaper> grim = new GrimReaper();
|
||||
sm->asBinder()->linkToDeath(grim, grim.get(), 0);
|
||||
|
||||
|
||||
char propBuf[PROPERTY_VALUE_MAX];
|
||||
property_get("system_init.startsurfaceflinger", propBuf, "1");
|
||||
if (strcmp(propBuf, "1") == 0) {
|
||||
@@ -97,12 +97,23 @@ extern "C" status_t system_init()
|
||||
// the beginning of their processes's main(), before calling
|
||||
// the init function.
|
||||
LOGI("System server: starting Android runtime.\n");
|
||||
|
||||
AndroidRuntime* runtime = AndroidRuntime::getRuntime();
|
||||
|
||||
LOGI("System server: starting Android services.\n");
|
||||
runtime->callStatic("com/android/server/SystemServer", "init2");
|
||||
|
||||
JNIEnv* env = runtime->getJNIEnv();
|
||||
if (env == NULL) {
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
jclass clazz = env->FindClass("com/android/server/SystemServer");
|
||||
if (clazz == NULL) {
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
jmethodID methodId = env->GetStaticMethodID(clazz, "init2", "()V");
|
||||
if (methodId == NULL) {
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
env->CallStaticVoidMethod(clazz, methodId);
|
||||
|
||||
// If running in our own process, just go into the thread
|
||||
// pool. Otherwise, call the initialization finished
|
||||
// func to let this process continue its initilization.
|
||||
@@ -114,4 +125,3 @@ extern "C" status_t system_init()
|
||||
}
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,19 +1,18 @@
|
||||
/* //device/libs/android_runtime/AndroidRuntime.cpp
|
||||
**
|
||||
** Copyright 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.
|
||||
*/
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "AndroidRuntime"
|
||||
//#define LOG_NDEBUG 0
|
||||
@@ -212,7 +211,7 @@ static jint com_android_internal_os_RuntimeInit_getQwertyKeyboard(JNIEnv* env, j
|
||||
if (value != NULL && strcmp(value, "true") == 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -227,7 +226,7 @@ static JNINativeMethod gMethods[] = {
|
||||
{ "isComputerOn", "()I",
|
||||
(void*) com_android_internal_os_RuntimeInit_isComputerOn },
|
||||
{ "turnComputerOn", "()V",
|
||||
(void*) com_android_internal_os_RuntimeInit_turnComputerOn },
|
||||
(void*) com_android_internal_os_RuntimeInit_turnComputerOn },
|
||||
{ "getQwertyKeyboard", "()I",
|
||||
(void*) com_android_internal_os_RuntimeInit_getQwertyKeyboard },
|
||||
};
|
||||
@@ -278,51 +277,16 @@ AndroidRuntime::~AndroidRuntime()
|
||||
return jniRegisterNativeMethods(env, className, gMethods, numMethods);
|
||||
}
|
||||
|
||||
/*
|
||||
* Call a static Java Programming Language function that takes no arguments and returns void.
|
||||
*/
|
||||
status_t AndroidRuntime::callStatic(const char* className, const char* methodName)
|
||||
status_t AndroidRuntime::callMain(const char* className,
|
||||
jclass clazz, int argc, const char* const argv[])
|
||||
{
|
||||
JNIEnv* env;
|
||||
jclass clazz;
|
||||
jmethodID methodId;
|
||||
|
||||
env = getJNIEnv();
|
||||
if (env == NULL)
|
||||
return UNKNOWN_ERROR;
|
||||
|
||||
clazz = findClass(env, className);
|
||||
if (clazz == NULL) {
|
||||
LOGE("ERROR: could not find class '%s'\n", className);
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
methodId = env->GetStaticMethodID(clazz, methodName, "()V");
|
||||
if (methodId == NULL) {
|
||||
LOGE("ERROR: could not find method %s.%s\n", className, methodName);
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
env->CallStaticVoidMethod(clazz, methodId);
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
status_t AndroidRuntime::callMain(
|
||||
const char* className, int argc, const char* const argv[])
|
||||
{
|
||||
JNIEnv* env;
|
||||
jclass clazz;
|
||||
jmethodID methodId;
|
||||
|
||||
LOGD("Calling main entry %s", className);
|
||||
|
||||
env = getJNIEnv();
|
||||
if (env == NULL)
|
||||
return UNKNOWN_ERROR;
|
||||
|
||||
clazz = findClass(env, className);
|
||||
if (clazz == NULL) {
|
||||
LOGE("ERROR: could not find class '%s'\n", className);
|
||||
if (clazz == NULL || env == NULL) {
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
@@ -351,70 +315,6 @@ status_t AndroidRuntime::callMain(
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the named class.
|
||||
*/
|
||||
jclass AndroidRuntime::findClass(JNIEnv* env, const char* className)
|
||||
{
|
||||
if (env->ExceptionCheck()) {
|
||||
LOGE("ERROR: exception pending on entry to findClass()");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is a little awkward because the JNI FindClass call uses the
|
||||
* class loader associated with the native method we're executing in.
|
||||
* Because this native method is part of a "boot" class, JNI doesn't
|
||||
* look for the class in CLASSPATH, which unfortunately is a likely
|
||||
* location for it. (Had we issued the FindClass call before calling
|
||||
* into the VM -- at which point there isn't a native method frame on
|
||||
* the stack -- the VM would have checked CLASSPATH. We have to do
|
||||
* this because we call into Java Programming Language code and
|
||||
* bounce back out.)
|
||||
*
|
||||
* JNI lacks a "find class in a specific class loader" operation, so we
|
||||
* have to do things the hard way.
|
||||
*/
|
||||
jclass cls = NULL;
|
||||
|
||||
jclass javaLangClassLoader;
|
||||
jmethodID getSystemClassLoader, loadClass;
|
||||
jobject systemClassLoader;
|
||||
jstring strClassName;
|
||||
|
||||
/* find the "system" class loader; none of this is expected to fail */
|
||||
javaLangClassLoader = env->FindClass("java/lang/ClassLoader");
|
||||
assert(javaLangClassLoader != NULL);
|
||||
getSystemClassLoader = env->GetStaticMethodID(javaLangClassLoader,
|
||||
"getSystemClassLoader", "()Ljava/lang/ClassLoader;");
|
||||
loadClass = env->GetMethodID(javaLangClassLoader,
|
||||
"loadClass", "(Ljava/lang/String;)Ljava/lang/Class;");
|
||||
assert(getSystemClassLoader != NULL && loadClass != NULL);
|
||||
systemClassLoader = env->CallStaticObjectMethod(javaLangClassLoader,
|
||||
getSystemClassLoader);
|
||||
assert(systemClassLoader != NULL);
|
||||
|
||||
/* create an object for the class name string; alloc could fail */
|
||||
strClassName = env->NewStringUTF(className);
|
||||
if (env->ExceptionCheck()) {
|
||||
LOGE("ERROR: unable to convert '%s' to string", className);
|
||||
return NULL;
|
||||
}
|
||||
LOGV("system class loader is %p, loading %p (%s)",
|
||||
systemClassLoader, strClassName, className);
|
||||
|
||||
/* try to find the named class */
|
||||
cls = (jclass) env->CallObjectMethod(systemClassLoader, loadClass,
|
||||
strClassName);
|
||||
if (env->ExceptionCheck()) {
|
||||
LOGE("ERROR: unable to load class '%s' from %p",
|
||||
className, systemClassLoader);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return cls;
|
||||
}
|
||||
|
||||
/*
|
||||
* The VM calls this through the "exit" hook.
|
||||
*/
|
||||
@@ -457,7 +357,7 @@ static bool runtime_isSensitiveThread() {
|
||||
int AndroidRuntime::addVmArguments(int argc, const char* const argv[])
|
||||
{
|
||||
int i;
|
||||
|
||||
|
||||
for (i = 0; i<argc; i++) {
|
||||
if (argv[i][0] != '-') {
|
||||
return i;
|
||||
@@ -890,6 +790,17 @@ bail:
|
||||
return result;
|
||||
}
|
||||
|
||||
char* AndroidRuntime::toSlashClassName(const char* className)
|
||||
{
|
||||
char* result = strdup(className);
|
||||
for (char* cp = result; *cp != '\0'; cp++) {
|
||||
if (*cp == '.') {
|
||||
*cp = '/';
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Start the Android runtime. This involves starting the virtual machine
|
||||
* and calling the "static void main(String[] args)" method in the class
|
||||
@@ -900,20 +811,16 @@ void AndroidRuntime::start(const char* className, const bool startSystemServer)
|
||||
LOGD("\n>>>>>> AndroidRuntime START %s <<<<<<\n",
|
||||
className != NULL ? className : "(unknown)");
|
||||
|
||||
char* slashClassName = NULL;
|
||||
char* cp;
|
||||
JNIEnv* env;
|
||||
|
||||
blockSigpipe();
|
||||
|
||||
/*
|
||||
* 'startSystemServer == true' means runtime is obsolete and not run from
|
||||
/*
|
||||
* 'startSystemServer == true' means runtime is obsolete and not run from
|
||||
* init.rc anymore, so we print out the boot start event here.
|
||||
*/
|
||||
if (startSystemServer) {
|
||||
/* track our progress through the boot sequence */
|
||||
const int LOG_BOOT_PROGRESS_START = 3000;
|
||||
LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START,
|
||||
LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START,
|
||||
ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
|
||||
}
|
||||
|
||||
@@ -922,7 +829,7 @@ void AndroidRuntime::start(const char* className, const bool startSystemServer)
|
||||
rootDir = "/system";
|
||||
if (!hasDir("/system")) {
|
||||
LOG_FATAL("No root directory specified, and /android does not exist.");
|
||||
goto bail;
|
||||
return;
|
||||
}
|
||||
setenv("ANDROID_ROOT", rootDir, 1);
|
||||
}
|
||||
@@ -931,15 +838,18 @@ void AndroidRuntime::start(const char* className, const bool startSystemServer)
|
||||
//LOGD("Found LD_ASSUME_KERNEL='%s'\n", kernelHack);
|
||||
|
||||
/* start the virtual machine */
|
||||
if (startVm(&mJavaVM, &env) != 0)
|
||||
goto bail;
|
||||
JNIEnv* env;
|
||||
if (startVm(&mJavaVM, &env) != 0) {
|
||||
return;
|
||||
}
|
||||
onVmCreated(env);
|
||||
|
||||
/*
|
||||
* Register android functions.
|
||||
*/
|
||||
if (startReg(env) < 0) {
|
||||
LOGE("Unable to register all android natives\n");
|
||||
goto bail;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -959,7 +869,7 @@ void AndroidRuntime::start(const char* className, const bool startSystemServer)
|
||||
classNameStr = env->NewStringUTF(className);
|
||||
assert(classNameStr != NULL);
|
||||
env->SetObjectArrayElement(strArray, 0, classNameStr);
|
||||
startSystemServerStr = env->NewStringUTF(startSystemServer ?
|
||||
startSystemServerStr = env->NewStringUTF(startSystemServer ?
|
||||
"true" : "false");
|
||||
env->SetObjectArrayElement(strArray, 1, startSystemServerStr);
|
||||
|
||||
@@ -967,20 +877,13 @@ void AndroidRuntime::start(const char* className, const bool startSystemServer)
|
||||
* Start VM. This thread becomes the main thread of the VM, and will
|
||||
* not return until the VM exits.
|
||||
*/
|
||||
jclass startClass;
|
||||
jmethodID startMeth;
|
||||
|
||||
slashClassName = strdup(className);
|
||||
for (cp = slashClassName; *cp != '\0'; cp++)
|
||||
if (*cp == '.')
|
||||
*cp = '/';
|
||||
|
||||
startClass = env->FindClass(slashClassName);
|
||||
char* slashClassName = toSlashClassName(className);
|
||||
jclass startClass = env->FindClass(slashClassName);
|
||||
if (startClass == NULL) {
|
||||
LOGE("JavaVM unable to locate class '%s'\n", slashClassName);
|
||||
/* keep going */
|
||||
} else {
|
||||
startMeth = env->GetStaticMethodID(startClass, "main",
|
||||
jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
|
||||
"([Ljava/lang/String;)V");
|
||||
if (startMeth == NULL) {
|
||||
LOGE("JavaVM unable to find main() in '%s'\n", className);
|
||||
@@ -994,15 +897,13 @@ void AndroidRuntime::start(const char* className, const bool startSystemServer)
|
||||
#endif
|
||||
}
|
||||
}
|
||||
free(slashClassName);
|
||||
|
||||
LOGD("Shutting down VM\n");
|
||||
if (mJavaVM->DetachCurrentThread() != JNI_OK)
|
||||
LOGW("Warning: unable to detach main thread\n");
|
||||
if (mJavaVM->DestroyJavaVM() != 0)
|
||||
LOGW("Warning: VM did not shut down cleanly\n");
|
||||
|
||||
bail:
|
||||
free(slashClassName);
|
||||
}
|
||||
|
||||
void AndroidRuntime::start()
|
||||
@@ -1017,6 +918,11 @@ void AndroidRuntime::onExit(int code)
|
||||
exit(code);
|
||||
}
|
||||
|
||||
void AndroidRuntime::onVmCreated(JNIEnv* env)
|
||||
{
|
||||
// If AndroidRuntime had anything to do here, we'd have done it in 'start'.
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the JNIEnv pointer for this thread.
|
||||
*
|
||||
@@ -1111,7 +1017,7 @@ static int javaDetachThread(void)
|
||||
* into the VM before it really starts executing.
|
||||
*/
|
||||
/*static*/ int AndroidRuntime::javaCreateThreadEtc(
|
||||
android_thread_func_t entryFunction,
|
||||
android_thread_func_t entryFunction,
|
||||
void* userData,
|
||||
const char* threadName,
|
||||
int32_t threadPriority,
|
||||
@@ -1299,7 +1205,7 @@ static const RegJNIRec gRegJNI[] = {
|
||||
REG_JNI(register_android_backup_BackupDataOutput),
|
||||
REG_JNI(register_android_backup_FileBackupHelperBase),
|
||||
REG_JNI(register_android_backup_BackupHelperDispatcher),
|
||||
|
||||
|
||||
REG_JNI(register_android_app_ActivityThread),
|
||||
REG_JNI(register_android_app_NativeActivity),
|
||||
REG_JNI(register_android_view_InputChannel),
|
||||
|
||||
@@ -103,17 +103,6 @@ static void signalExceptionForGroupError(JNIEnv* env, jobject obj, int err)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void fakeProcessEntry(void* arg)
|
||||
{
|
||||
String8* cls = (String8*)arg;
|
||||
|
||||
AndroidRuntime* jr = AndroidRuntime::getRuntime();
|
||||
jr->callMain(cls->string(), 0, NULL);
|
||||
|
||||
delete cls;
|
||||
}
|
||||
|
||||
jint android_os_Process_myPid(JNIEnv* env, jobject clazz)
|
||||
{
|
||||
return getpid();
|
||||
|
||||
@@ -45,15 +45,11 @@ public:
|
||||
static int registerNativeMethods(JNIEnv* env,
|
||||
const char* className, const JNINativeMethod* gMethods, int numMethods);
|
||||
|
||||
/**
|
||||
* Call a static Java function that takes no arguments and returns void.
|
||||
*/
|
||||
status_t callStatic(const char* className, const char* methodName);
|
||||
|
||||
/**
|
||||
* Call a class's static main method with the given arguments,
|
||||
*/
|
||||
status_t callMain(const char* className, int argc, const char* const argv[]);
|
||||
status_t callMain(const char* className, jclass clazz, int argc,
|
||||
const char* const argv[]);
|
||||
|
||||
/**
|
||||
* Find a class, with the input either of the form
|
||||
@@ -68,6 +64,13 @@ public:
|
||||
|
||||
static AndroidRuntime* getRuntime();
|
||||
|
||||
/**
|
||||
* This gets called after the VM has been created, but before we
|
||||
* run any code. Override it to make any FindClass calls that need
|
||||
* to use CLASSPATH.
|
||||
*/
|
||||
virtual void onVmCreated(JNIEnv* env);
|
||||
|
||||
/**
|
||||
* This gets called after the JavaVM has initialized. Override it
|
||||
* with the system's native entry point.
|
||||
@@ -98,6 +101,9 @@ public:
|
||||
/** return a pointer to the JNIEnv pointer for this thread */
|
||||
static JNIEnv* getJNIEnv();
|
||||
|
||||
/** return a new string corresponding to 'className' with all '.'s replaced by '/'s. */
|
||||
static char* toSlashClassName(const char* className);
|
||||
|
||||
private:
|
||||
static int startReg(JNIEnv* env);
|
||||
void parseExtraOpts(char* extraOptsBuf);
|
||||
|
||||
Reference in New Issue
Block a user