Loading core/jni/platform/host/HostRuntime.cpp +109 −182 Original line number Diff line number Diff line Loading @@ -17,6 +17,8 @@ #include <android-base/logging.h> #include <android-base/properties.h> #include <android/graphics/jni_runtime.h> #include <android_runtime/AndroidRuntime.h> #include <jni_wrappers.h> #include <nativehelper/JNIHelp.h> #include <nativehelper/jni_macros.h> #include <unicode/putil.h> Loading @@ -27,9 +29,6 @@ #include <unordered_map> #include <vector> #include "android_view_InputDevice.h" #include "core_jni_helpers.h" #include "jni.h" #ifdef _WIN32 #include <windows.h> #else Loading @@ -38,8 +37,6 @@ #include <sys/stat.h> #endif #include <iostream> using namespace std; /* Loading @@ -49,12 +46,6 @@ using namespace std; * (see AndroidRuntime.cpp). */ static JavaVM* javaVM; static jclass bridge; static jclass layoutLog; static jmethodID getLogId; static jmethodID logMethodId; extern int register_android_os_Binder(JNIEnv* env); extern int register_libcore_util_NativeAllocationRegistry_Delegate(JNIEnv* env); Loading Loading @@ -168,28 +159,9 @@ static int register_jni_procs(const std::unordered_map<std::string, RegJNIRec>& } } if (register_android_graphics_classes(env) < 0) { return -1; } return 0; } int AndroidRuntime::registerNativeMethods(JNIEnv* env, const char* className, const JNINativeMethod* gMethods, int numMethods) { return jniRegisterNativeMethods(env, className, gMethods, numMethods); } JNIEnv* AndroidRuntime::getJNIEnv() { JNIEnv* env; if (javaVM->GetEnv((void**)&env, JNI_VERSION_1_6) != JNI_OK) return nullptr; return env; } JavaVM* AndroidRuntime::getJavaVM() { return javaVM; } static vector<string> parseCsv(const string& csvString) { vector<string> result; istringstream stream(csvString); Loading @@ -200,29 +172,6 @@ static vector<string> parseCsv(const string& csvString) { return result; } void LayoutlibLogger(base::LogId, base::LogSeverity severity, const char* tag, const char* file, unsigned int line, const char* message) { JNIEnv* env = AndroidRuntime::getJNIEnv(); jint logPrio = severity; jstring tagString = env->NewStringUTF(tag); jstring messageString = env->NewStringUTF(message); jobject bridgeLog = env->CallStaticObjectMethod(bridge, getLogId); env->CallVoidMethod(bridgeLog, logMethodId, logPrio, tagString, messageString); env->DeleteLocalRef(tagString); env->DeleteLocalRef(messageString); env->DeleteLocalRef(bridgeLog); } void LayoutlibAborter(const char* abort_message) { // Layoutlib should not call abort() as it would terminate Studio. // Throw an exception back to Java instead. JNIEnv* env = AndroidRuntime::getJNIEnv(); jniThrowRuntimeException(env, "The Android framework has encountered a fatal error"); } // This method has been copied/adapted from system/core/init/property_service.cpp // If the ro.product.cpu.abilist* properties have not been explicitly // set, derive them from ro.system.product.cpu.abilist* properties. Loading Loading @@ -311,62 +260,49 @@ static void* mmapFile(const char* dataFilePath) { #endif } static bool init_icu(const char* dataPath) { void* addr = mmapFile(dataPath); // Loads the ICU data file from the location specified in the system property ro.icu.data.path static void loadIcuData() { string icuPath = base::GetProperty("ro.icu.data.path", ""); if (!icuPath.empty()) { // Set the location of ICU data void* addr = mmapFile(icuPath.c_str()); UErrorCode err = U_ZERO_ERROR; udata_setCommonData(addr, &err); if (err != U_ZERO_ERROR) { return false; ALOGE("Unable to load ICU data\n"); } } return true; } // Creates an array of InputDevice from key character map files static void init_keyboard(JNIEnv* env, const vector<string>& keyboardPaths) { jclass inputDevice = FindClassOrDie(env, "android/view/InputDevice"); jobjectArray inputDevicesArray = env->NewObjectArray(keyboardPaths.size(), inputDevice, nullptr); int keyboardId = 1; for (const string& path : keyboardPaths) { base::Result<std::shared_ptr<KeyCharacterMap>> charMap = KeyCharacterMap::load(path, KeyCharacterMap::Format::BASE); static int register_android_core_classes(JNIEnv* env) { jclass system = FindClassOrDie(env, "java/lang/System"); jmethodID getPropertyMethod = GetStaticMethodIDOrDie(env, system, "getProperty", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"); InputDeviceInfo info = InputDeviceInfo(); info.initialize(keyboardId, 0, 0, InputDeviceIdentifier(), "keyboard " + std::to_string(keyboardId), true, false, ui::LogicalDisplayId::DEFAULT); info.setKeyboardType(AINPUT_KEYBOARD_TYPE_ALPHABETIC); info.setKeyCharacterMap(*charMap); // Get the names of classes that need to register their native methods auto nativesClassesJString = (jstring)env->CallStaticObjectMethod(system, getPropertyMethod, env->NewStringUTF("core_native_classes"), env->NewStringUTF("")); const char* nativesClassesArray = env->GetStringUTFChars(nativesClassesJString, nullptr); string nativesClassesString(nativesClassesArray); vector<string> classesToRegister = parseCsv(nativesClassesString); env->ReleaseStringUTFChars(nativesClassesJString, nativesClassesArray); jobject inputDeviceObj = android_view_InputDevice_create(env, info); if (inputDeviceObj) { env->SetObjectArrayElement(inputDevicesArray, keyboardId - 1, inputDeviceObj); env->DeleteLocalRef(inputDeviceObj); } keyboardId++; if (register_jni_procs(gRegJNIMap, classesToRegister, env) < 0) { return JNI_ERR; } if (bridge == nullptr) { bridge = FindClassOrDie(env, "com/android/layoutlib/bridge/Bridge"); bridge = MakeGlobalRefOrDie(env, bridge); } jmethodID setInputManager = GetStaticMethodIDOrDie(env, bridge, "setInputManager", "([Landroid/view/InputDevice;)V"); env->CallStaticVoidMethod(bridge, setInputManager, inputDevicesArray); env->DeleteLocalRef(inputDevicesArray); return 0; } } // namespace android using namespace android; // Called right before aborting by LOG_ALWAYS_FATAL. Print the pending exception. void abort_handler(const char* abort_message) { ALOGE("About to abort the process..."); JNIEnv* env = NULL; if (javaVM->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) { JNIEnv* env = AndroidRuntime::getJNIEnv(); if (env == nullptr) { ALOGE("vm->GetEnv() failed"); return; } Loading @@ -377,107 +313,98 @@ void abort_handler(const char* abort_message) { ALOGE("Aborting because: %s", abort_message); } JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void*) { javaVM = vm; JNIEnv* env = nullptr; if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) { return JNI_ERR; } __android_log_set_aborter(abort_handler); // ------------------ Host implementation of AndroidRuntime ------------------ init_android_graphics(); /*static*/ JavaVM* AndroidRuntime::mJavaVM; // Configuration is stored as java System properties. // Get a reference to System.getProperty jclass system = FindClassOrDie(env, "java/lang/System"); jmethodID getPropertyMethod = GetStaticMethodIDOrDie(env, system, "getProperty", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"); // Java system properties that contain LayoutLib config. The initial values in the map // are the default values if the property is not specified. std::unordered_map<std::string, std::string> systemProperties = {{"core_native_classes", ""}, {"register_properties_during_load", ""}, {"icu.data.path", ""}, {"use_bridge_for_logging", ""}, {"keyboard_paths", ""}}; for (auto& [name, defaultValue] : systemProperties) { jstring propertyString = (jstring)env->CallStaticObjectMethod(system, getPropertyMethod, env->NewStringUTF(name.c_str()), env->NewStringUTF(defaultValue.c_str())); const char* propertyChars = env->GetStringUTFChars(propertyString, 0); systemProperties[name] = string(propertyChars); env->ReleaseStringUTFChars(propertyString, propertyChars); /*static*/ int AndroidRuntime::registerNativeMethods(JNIEnv* env, const char* className, const JNINativeMethod* gMethods, int numMethods) { return jniRegisterNativeMethods(env, className, gMethods, numMethods); } // Get the names of classes that need to register their native methods vector<string> classesToRegister = parseCsv(systemProperties["core_native_classes"]); if (systemProperties["register_properties_during_load"] == "true") { // Set the system properties first as they could be used in the static initialization of // other classes if (register_android_os_SystemProperties(env) < 0) { return JNI_ERR; /*static*/ JNIEnv* AndroidRuntime::getJNIEnv() { JNIEnv* env; JavaVM* vm = AndroidRuntime::getJavaVM(); if (vm->GetEnv((void**)&env, JNI_VERSION_1_6) != JNI_OK) { return nullptr; } classesToRegister.erase(find(classesToRegister.begin(), classesToRegister.end(), "android.os.SystemProperties")); bridge = FindClassOrDie(env, "com/android/layoutlib/bridge/Bridge"); bridge = MakeGlobalRefOrDie(env, bridge); jmethodID setSystemPropertiesMethod = GetStaticMethodIDOrDie(env, bridge, "setSystemProperties", "()V"); env->CallStaticVoidMethod(bridge, setSystemPropertiesMethod); property_initialize_ro_cpu_abilist(); return env; } if (register_jni_procs(gRegJNIMap, classesToRegister, env) < 0) { return JNI_ERR; /*static*/ JavaVM* AndroidRuntime::getJavaVM() { return mJavaVM; } if (!systemProperties["icu.data.path"].empty()) { // Set the location of ICU data bool icuInitialized = init_icu(systemProperties["icu.data.path"].c_str()); if (!icuInitialized) { /*static*/ int AndroidRuntime::startReg(JNIEnv* env) { if (register_android_core_classes(env) < 0) { return JNI_ERR; } if (register_android_graphics_classes(env) < 0) { return JNI_ERR; } if (systemProperties["use_bridge_for_logging"] == "true") { layoutLog = FindClassOrDie(env, "com/android/ide/common/rendering/api/ILayoutLog"); layoutLog = MakeGlobalRefOrDie(env, layoutLog); logMethodId = GetMethodIDOrDie(env, layoutLog, "logAndroidFramework", "(ILjava/lang/String;Ljava/lang/String;)V"); if (bridge == nullptr) { bridge = FindClassOrDie(env, "com/android/layoutlib/bridge/Bridge"); bridge = MakeGlobalRefOrDie(env, bridge); return 0; } getLogId = GetStaticMethodIDOrDie(env, bridge, "getLog", "()Lcom/android/ide/common/rendering/api/ILayoutLog;"); android::base::SetLogger(LayoutlibLogger); android::base::SetAborter(LayoutlibAborter); } else { // initialize logging, so ANDROD_LOG_TAGS env variable is respected android::base::InitLogging(nullptr, android::base::StderrLogger); void AndroidRuntime::onVmCreated(JNIEnv* env) { env->GetJavaVM(&mJavaVM); } void AndroidRuntime::onStarted() { property_initialize_ro_cpu_abilist(); loadIcuData(); // Use English locale for number format to ensure correct parsing of floats when using strtof setlocale(LC_NUMERIC, "en_US.UTF-8"); } if (!systemProperties["keyboard_paths"].empty()) { vector<string> keyboardPaths = parseCsv(systemProperties["keyboard_paths"]); init_keyboard(env, keyboardPaths); } else { fprintf(stderr, "Skip initializing keyboard\n"); void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote) { JNIEnv* env = AndroidRuntime::getJNIEnv(); // Register native functions. if (startReg(env) < 0) { ALOGE("Unable to register all android native methods\n"); } onStarted(); } return JNI_VERSION_1_6; AndroidRuntime::AndroidRuntime(char* argBlockStart, const size_t argBlockLength) : mExitWithoutCleanup(false), mArgBlockStart(argBlockStart), mArgBlockLength(argBlockLength) { init_android_graphics(); } AndroidRuntime::~AndroidRuntime() {} // Version of AndroidRuntime to run on host class HostRuntime : public AndroidRuntime { public: HostRuntime() : AndroidRuntime(nullptr, 0) {} void onVmCreated(JNIEnv* env) override { AndroidRuntime::onVmCreated(env); // initialize logging, so ANDROD_LOG_TAGS env variable is respected android::base::InitLogging(nullptr, android::base::StderrLogger, abort_handler); } JNIEXPORT void JNI_OnUnload(JavaVM* vm, void*) { void onStarted() override { AndroidRuntime::onStarted(); } }; } // namespace android using namespace android; JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void*) { JNIEnv* env = nullptr; vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6); env->DeleteGlobalRef(bridge); env->DeleteGlobalRef(layoutLog); if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) { return JNI_ERR; } Vector<String8> args; HostRuntime runtime; runtime.onVmCreated(env); runtime.start("HostRuntime", args, false); return JNI_VERSION_1_6; } Loading
core/jni/platform/host/HostRuntime.cpp +109 −182 Original line number Diff line number Diff line Loading @@ -17,6 +17,8 @@ #include <android-base/logging.h> #include <android-base/properties.h> #include <android/graphics/jni_runtime.h> #include <android_runtime/AndroidRuntime.h> #include <jni_wrappers.h> #include <nativehelper/JNIHelp.h> #include <nativehelper/jni_macros.h> #include <unicode/putil.h> Loading @@ -27,9 +29,6 @@ #include <unordered_map> #include <vector> #include "android_view_InputDevice.h" #include "core_jni_helpers.h" #include "jni.h" #ifdef _WIN32 #include <windows.h> #else Loading @@ -38,8 +37,6 @@ #include <sys/stat.h> #endif #include <iostream> using namespace std; /* Loading @@ -49,12 +46,6 @@ using namespace std; * (see AndroidRuntime.cpp). */ static JavaVM* javaVM; static jclass bridge; static jclass layoutLog; static jmethodID getLogId; static jmethodID logMethodId; extern int register_android_os_Binder(JNIEnv* env); extern int register_libcore_util_NativeAllocationRegistry_Delegate(JNIEnv* env); Loading Loading @@ -168,28 +159,9 @@ static int register_jni_procs(const std::unordered_map<std::string, RegJNIRec>& } } if (register_android_graphics_classes(env) < 0) { return -1; } return 0; } int AndroidRuntime::registerNativeMethods(JNIEnv* env, const char* className, const JNINativeMethod* gMethods, int numMethods) { return jniRegisterNativeMethods(env, className, gMethods, numMethods); } JNIEnv* AndroidRuntime::getJNIEnv() { JNIEnv* env; if (javaVM->GetEnv((void**)&env, JNI_VERSION_1_6) != JNI_OK) return nullptr; return env; } JavaVM* AndroidRuntime::getJavaVM() { return javaVM; } static vector<string> parseCsv(const string& csvString) { vector<string> result; istringstream stream(csvString); Loading @@ -200,29 +172,6 @@ static vector<string> parseCsv(const string& csvString) { return result; } void LayoutlibLogger(base::LogId, base::LogSeverity severity, const char* tag, const char* file, unsigned int line, const char* message) { JNIEnv* env = AndroidRuntime::getJNIEnv(); jint logPrio = severity; jstring tagString = env->NewStringUTF(tag); jstring messageString = env->NewStringUTF(message); jobject bridgeLog = env->CallStaticObjectMethod(bridge, getLogId); env->CallVoidMethod(bridgeLog, logMethodId, logPrio, tagString, messageString); env->DeleteLocalRef(tagString); env->DeleteLocalRef(messageString); env->DeleteLocalRef(bridgeLog); } void LayoutlibAborter(const char* abort_message) { // Layoutlib should not call abort() as it would terminate Studio. // Throw an exception back to Java instead. JNIEnv* env = AndroidRuntime::getJNIEnv(); jniThrowRuntimeException(env, "The Android framework has encountered a fatal error"); } // This method has been copied/adapted from system/core/init/property_service.cpp // If the ro.product.cpu.abilist* properties have not been explicitly // set, derive them from ro.system.product.cpu.abilist* properties. Loading Loading @@ -311,62 +260,49 @@ static void* mmapFile(const char* dataFilePath) { #endif } static bool init_icu(const char* dataPath) { void* addr = mmapFile(dataPath); // Loads the ICU data file from the location specified in the system property ro.icu.data.path static void loadIcuData() { string icuPath = base::GetProperty("ro.icu.data.path", ""); if (!icuPath.empty()) { // Set the location of ICU data void* addr = mmapFile(icuPath.c_str()); UErrorCode err = U_ZERO_ERROR; udata_setCommonData(addr, &err); if (err != U_ZERO_ERROR) { return false; ALOGE("Unable to load ICU data\n"); } } return true; } // Creates an array of InputDevice from key character map files static void init_keyboard(JNIEnv* env, const vector<string>& keyboardPaths) { jclass inputDevice = FindClassOrDie(env, "android/view/InputDevice"); jobjectArray inputDevicesArray = env->NewObjectArray(keyboardPaths.size(), inputDevice, nullptr); int keyboardId = 1; for (const string& path : keyboardPaths) { base::Result<std::shared_ptr<KeyCharacterMap>> charMap = KeyCharacterMap::load(path, KeyCharacterMap::Format::BASE); static int register_android_core_classes(JNIEnv* env) { jclass system = FindClassOrDie(env, "java/lang/System"); jmethodID getPropertyMethod = GetStaticMethodIDOrDie(env, system, "getProperty", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"); InputDeviceInfo info = InputDeviceInfo(); info.initialize(keyboardId, 0, 0, InputDeviceIdentifier(), "keyboard " + std::to_string(keyboardId), true, false, ui::LogicalDisplayId::DEFAULT); info.setKeyboardType(AINPUT_KEYBOARD_TYPE_ALPHABETIC); info.setKeyCharacterMap(*charMap); // Get the names of classes that need to register their native methods auto nativesClassesJString = (jstring)env->CallStaticObjectMethod(system, getPropertyMethod, env->NewStringUTF("core_native_classes"), env->NewStringUTF("")); const char* nativesClassesArray = env->GetStringUTFChars(nativesClassesJString, nullptr); string nativesClassesString(nativesClassesArray); vector<string> classesToRegister = parseCsv(nativesClassesString); env->ReleaseStringUTFChars(nativesClassesJString, nativesClassesArray); jobject inputDeviceObj = android_view_InputDevice_create(env, info); if (inputDeviceObj) { env->SetObjectArrayElement(inputDevicesArray, keyboardId - 1, inputDeviceObj); env->DeleteLocalRef(inputDeviceObj); } keyboardId++; if (register_jni_procs(gRegJNIMap, classesToRegister, env) < 0) { return JNI_ERR; } if (bridge == nullptr) { bridge = FindClassOrDie(env, "com/android/layoutlib/bridge/Bridge"); bridge = MakeGlobalRefOrDie(env, bridge); } jmethodID setInputManager = GetStaticMethodIDOrDie(env, bridge, "setInputManager", "([Landroid/view/InputDevice;)V"); env->CallStaticVoidMethod(bridge, setInputManager, inputDevicesArray); env->DeleteLocalRef(inputDevicesArray); return 0; } } // namespace android using namespace android; // Called right before aborting by LOG_ALWAYS_FATAL. Print the pending exception. void abort_handler(const char* abort_message) { ALOGE("About to abort the process..."); JNIEnv* env = NULL; if (javaVM->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) { JNIEnv* env = AndroidRuntime::getJNIEnv(); if (env == nullptr) { ALOGE("vm->GetEnv() failed"); return; } Loading @@ -377,107 +313,98 @@ void abort_handler(const char* abort_message) { ALOGE("Aborting because: %s", abort_message); } JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void*) { javaVM = vm; JNIEnv* env = nullptr; if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) { return JNI_ERR; } __android_log_set_aborter(abort_handler); // ------------------ Host implementation of AndroidRuntime ------------------ init_android_graphics(); /*static*/ JavaVM* AndroidRuntime::mJavaVM; // Configuration is stored as java System properties. // Get a reference to System.getProperty jclass system = FindClassOrDie(env, "java/lang/System"); jmethodID getPropertyMethod = GetStaticMethodIDOrDie(env, system, "getProperty", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"); // Java system properties that contain LayoutLib config. The initial values in the map // are the default values if the property is not specified. std::unordered_map<std::string, std::string> systemProperties = {{"core_native_classes", ""}, {"register_properties_during_load", ""}, {"icu.data.path", ""}, {"use_bridge_for_logging", ""}, {"keyboard_paths", ""}}; for (auto& [name, defaultValue] : systemProperties) { jstring propertyString = (jstring)env->CallStaticObjectMethod(system, getPropertyMethod, env->NewStringUTF(name.c_str()), env->NewStringUTF(defaultValue.c_str())); const char* propertyChars = env->GetStringUTFChars(propertyString, 0); systemProperties[name] = string(propertyChars); env->ReleaseStringUTFChars(propertyString, propertyChars); /*static*/ int AndroidRuntime::registerNativeMethods(JNIEnv* env, const char* className, const JNINativeMethod* gMethods, int numMethods) { return jniRegisterNativeMethods(env, className, gMethods, numMethods); } // Get the names of classes that need to register their native methods vector<string> classesToRegister = parseCsv(systemProperties["core_native_classes"]); if (systemProperties["register_properties_during_load"] == "true") { // Set the system properties first as they could be used in the static initialization of // other classes if (register_android_os_SystemProperties(env) < 0) { return JNI_ERR; /*static*/ JNIEnv* AndroidRuntime::getJNIEnv() { JNIEnv* env; JavaVM* vm = AndroidRuntime::getJavaVM(); if (vm->GetEnv((void**)&env, JNI_VERSION_1_6) != JNI_OK) { return nullptr; } classesToRegister.erase(find(classesToRegister.begin(), classesToRegister.end(), "android.os.SystemProperties")); bridge = FindClassOrDie(env, "com/android/layoutlib/bridge/Bridge"); bridge = MakeGlobalRefOrDie(env, bridge); jmethodID setSystemPropertiesMethod = GetStaticMethodIDOrDie(env, bridge, "setSystemProperties", "()V"); env->CallStaticVoidMethod(bridge, setSystemPropertiesMethod); property_initialize_ro_cpu_abilist(); return env; } if (register_jni_procs(gRegJNIMap, classesToRegister, env) < 0) { return JNI_ERR; /*static*/ JavaVM* AndroidRuntime::getJavaVM() { return mJavaVM; } if (!systemProperties["icu.data.path"].empty()) { // Set the location of ICU data bool icuInitialized = init_icu(systemProperties["icu.data.path"].c_str()); if (!icuInitialized) { /*static*/ int AndroidRuntime::startReg(JNIEnv* env) { if (register_android_core_classes(env) < 0) { return JNI_ERR; } if (register_android_graphics_classes(env) < 0) { return JNI_ERR; } if (systemProperties["use_bridge_for_logging"] == "true") { layoutLog = FindClassOrDie(env, "com/android/ide/common/rendering/api/ILayoutLog"); layoutLog = MakeGlobalRefOrDie(env, layoutLog); logMethodId = GetMethodIDOrDie(env, layoutLog, "logAndroidFramework", "(ILjava/lang/String;Ljava/lang/String;)V"); if (bridge == nullptr) { bridge = FindClassOrDie(env, "com/android/layoutlib/bridge/Bridge"); bridge = MakeGlobalRefOrDie(env, bridge); return 0; } getLogId = GetStaticMethodIDOrDie(env, bridge, "getLog", "()Lcom/android/ide/common/rendering/api/ILayoutLog;"); android::base::SetLogger(LayoutlibLogger); android::base::SetAborter(LayoutlibAborter); } else { // initialize logging, so ANDROD_LOG_TAGS env variable is respected android::base::InitLogging(nullptr, android::base::StderrLogger); void AndroidRuntime::onVmCreated(JNIEnv* env) { env->GetJavaVM(&mJavaVM); } void AndroidRuntime::onStarted() { property_initialize_ro_cpu_abilist(); loadIcuData(); // Use English locale for number format to ensure correct parsing of floats when using strtof setlocale(LC_NUMERIC, "en_US.UTF-8"); } if (!systemProperties["keyboard_paths"].empty()) { vector<string> keyboardPaths = parseCsv(systemProperties["keyboard_paths"]); init_keyboard(env, keyboardPaths); } else { fprintf(stderr, "Skip initializing keyboard\n"); void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote) { JNIEnv* env = AndroidRuntime::getJNIEnv(); // Register native functions. if (startReg(env) < 0) { ALOGE("Unable to register all android native methods\n"); } onStarted(); } return JNI_VERSION_1_6; AndroidRuntime::AndroidRuntime(char* argBlockStart, const size_t argBlockLength) : mExitWithoutCleanup(false), mArgBlockStart(argBlockStart), mArgBlockLength(argBlockLength) { init_android_graphics(); } AndroidRuntime::~AndroidRuntime() {} // Version of AndroidRuntime to run on host class HostRuntime : public AndroidRuntime { public: HostRuntime() : AndroidRuntime(nullptr, 0) {} void onVmCreated(JNIEnv* env) override { AndroidRuntime::onVmCreated(env); // initialize logging, so ANDROD_LOG_TAGS env variable is respected android::base::InitLogging(nullptr, android::base::StderrLogger, abort_handler); } JNIEXPORT void JNI_OnUnload(JavaVM* vm, void*) { void onStarted() override { AndroidRuntime::onStarted(); } }; } // namespace android using namespace android; JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void*) { JNIEnv* env = nullptr; vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6); env->DeleteGlobalRef(bridge); env->DeleteGlobalRef(layoutLog); if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) { return JNI_ERR; } Vector<String8> args; HostRuntime runtime; runtime.onVmCreated(env); runtime.start("HostRuntime", args, false); return JNI_VERSION_1_6; }