diff --git a/client/Android/Studio/freeRDPCore/src/main/java/com/freerdp/freerdpcore/services/LibFreeRDP.java b/client/Android/Studio/freeRDPCore/src/main/java/com/freerdp/freerdpcore/services/LibFreeRDP.java index 2d9314e7b..80ee28287 100644 --- a/client/Android/Studio/freeRDPCore/src/main/java/com/freerdp/freerdpcore/services/LibFreeRDP.java +++ b/client/Android/Studio/freeRDPCore/src/main/java/com/freerdp/freerdpcore/services/LibFreeRDP.java @@ -78,7 +78,16 @@ public class LibFreeRDP try { System.loadLibrary("freerdp-android"); + + /* Load dependent libraries too to trigger JNI_OnLoad calls */ String version = freerdp_get_jni_version(); + String[] versions = version.split("."); + if (versions.length > 0) + { + System.loadLibrary("freerdp-client" + versions[0]); + System.loadLibrary("freerdp" + versions[0]); + System.loadLibrary("winpr" + versions[0]); + } Pattern pattern = Pattern.compile("^(\\d+)\\.(\\d+)\\.(\\d+).*"); Matcher matcher = pattern.matcher(version); if (!matcher.matches() || (matcher.groupCount() < 3)) diff --git a/winpr/libwinpr/timezone/timezone.c b/winpr/libwinpr/timezone/timezone.c index 4827d26f5..04f59bcfa 100644 --- a/winpr/libwinpr/timezone/timezone.c +++ b/winpr/libwinpr/timezone/timezone.c @@ -168,14 +168,7 @@ static char* winpr_get_timezone_from_link(const char* links[], size_t count) } #if defined(ANDROID) -#include -static JavaVM* jniVm = NULL; - -JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) -{ - jniVm = vm; - return JNI_VERSION_1_6; -} +#include "../utils/android.h" static char* winpr_get_android_timezone_identifier(void) { diff --git a/winpr/libwinpr/utils/CMakeLists.txt b/winpr/libwinpr/utils/CMakeLists.txt index 62ff18f9f..1a751a29c 100644 --- a/winpr/libwinpr/utils/CMakeLists.txt +++ b/winpr/libwinpr/utils/CMakeLists.txt @@ -105,6 +105,7 @@ set(SRCS ssl.c) if (ANDROID) + list(APPEND SRCS android.h android.c) include_directories(${CMAKE_CURRENT_SOURCE_DIR}) if (NOT HAVE_UNWIND_H) message("[backtrace] android NDK without unwind.h, falling back to corkscrew") diff --git a/winpr/libwinpr/utils/android.c b/winpr/libwinpr/utils/android.c new file mode 100644 index 000000000..4c7113fc1 --- /dev/null +++ b/winpr/libwinpr/utils/android.c @@ -0,0 +1,77 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Winpr android helpers + * + * Copyright 2022 Armin Novak + * + * 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. + */ + +#include "android.h" +#include + +#include +#include + +#include "../log.h" + +#define TAG WINPR_TAG("android") + +JavaVM* jniVm = NULL; + +WINPR_API jint JNI_OnLoad(JavaVM* vm, void* reserved) +{ + WLog_INFO(TAG, "Setting up JNI environement..."); + + jniVm = vm; + return JNI_VERSION_1_6; +} + +WINPR_API void JNICALL JNI_OnUnload(JavaVM* vm, void* reserved) +{ + JNIEnv* env = NULL; + WLog_INFO(TAG, "Tearing down JNI environement..."); + + if ((*jniVm)->GetEnv(vm, (void**)&env, JNI_VERSION_1_6) != JNI_OK) + { + WLog_FATAL(TAG, "Failed to get the environment"); + return; + } +} + +jboolean winpr_jni_attach_thread(JNIEnv** env) +{ + WINPR_ASSERT(jniVm); + + if ((*jniVm)->GetEnv(jniVm, (void**)env, JNI_VERSION_1_4) != JNI_OK) + { + WLog_INFO(TAG, "android_java_callback: attaching current thread"); + (*jniVm)->AttachCurrentThread(jniVm, env, NULL); + + if ((*jniVm)->GetEnv(jniVm, (void**)env, JNI_VERSION_1_4) != JNI_OK) + { + WLog_ERR(TAG, "android_java_callback: failed to obtain current JNI environment"); + } + + return JNI_TRUE; + } + + return JNI_FALSE; +} + +/* attach current thread to JVM */ +void winpr_jni_detach_thread(void) +{ + WINPR_ASSERT(jniVm); + (*jniVm)->DetachCurrentThread(jniVm); +} diff --git a/winpr/libwinpr/utils/android.h b/winpr/libwinpr/utils/android.h new file mode 100644 index 000000000..30b264b53 --- /dev/null +++ b/winpr/libwinpr/utils/android.h @@ -0,0 +1,30 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Winpr android helpers + * + * Copyright 2022 Armin Novak + * + * 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. + */ + +#ifndef WINPR_UTILS_ANDROID_PRIV_H +#define WINPR_UTILS_ANDROID_PRIV_H + +#include + +extern JavaVM* jniVm; + +jboolean winpr_jni_attach_thread(JNIEnv** env); +void winpr_jni_detach_thread(void); + +#endif /* WINPR_UTILS_ANDROID_PRIV_H */