88 string_from_utf8_lossy_owned
99) ]
1010
11- extern crate core; #[ cfg( not( target_os = "android" ) ) ]
11+ extern crate core;
12+ #[ cfg( not( target_os = "android" ) ) ]
1213compile_error ! ( "Terracotta lib mode is intended for Android platform." ) ;
1314
1415#[ macro_export]
@@ -22,10 +23,9 @@ use lazy_static::lazy_static;
2223
2324use chrono:: { FixedOffset , TimeZone , Utc } ;
2425use jni:: signature:: { Primitive , ReturnType } ;
25- use jni:: sys:: { jbyte , jshort , jvalue, JNI_GetCreatedJavaVMs , JNI_OK } ;
26+ use jni:: sys:: { jshort , jsize , jvalue, JavaVM } ;
2627use jni:: { objects:: JString , strings:: JavaStr , sys:: { jboolean, jint, jobject, JNI_FALSE , JNI_TRUE } , JNIEnv } ;
2728use libc:: { c_char, c_int} ;
28- use std:: sync:: { LazyLock , OnceLock } ;
2929use std:: time:: Duration ;
3030use std:: {
3131 env, ffi:: CString , fs, net:: { IpAddr , Ipv4Addr , Ipv6Addr } , ptr:: null_mut, sync:: { Arc , Mutex } , thread,
@@ -96,7 +96,13 @@ static VPN_SERVICE_CFG: Mutex<Option<crate::easytier::EasyTierTunRequest>> = Mut
9696
9797#[ unsafe( no_mangle) ]
9898#[ allow( non_snake_case) ]
99- extern "system" fn Java_net_burningtnt_terracotta_TerracottaAndroidAPI_start0 ( _env : JNIRawEnv ) -> jint {
99+ extern "system" fn JNI_GetCreatedJavaVMs ( vmBuf : * mut * mut JavaVM , bufLen : jsize , nVMs : * mut jsize ) -> jint {
100+ unreachable ! ( ) ;
101+ }
102+
103+ #[ unsafe( no_mangle) ]
104+ #[ allow( non_snake_case) ]
105+ extern "system" fn Java_net_burningtnt_terracotta_TerracottaAndroidAPI_start0 ( env : JNIRawEnv ) -> jint {
100106 cfg_if:: cfg_if! {
101107 if #[ cfg( debug_assertions) ] {
102108 std:: panic:: set_backtrace_style( std:: panic:: BacktraceStyle :: Short ) ;
@@ -140,19 +146,15 @@ extern "system" fn Java_net_burningtnt_terracotta_TerracottaAndroidAPI_start0(_e
140146 return 2 ;
141147 }
142148
143- thread:: spawn ( || {
144- let jvm = unsafe {
145- let mut vm: * mut jni:: sys:: JavaVM = null_mut ( ) ;
146- let mut count: i32 = 0 ;
147- if JNI_GetCreatedJavaVMs ( & mut vm, 1 , & mut count) == JNI_OK && count > 0 {
148- jni:: JavaVM :: from_raw ( vm) . unwrap ( )
149- } else {
150- panic ! ( "Cannot locate created VMs." ) ;
151- }
152- } ;
149+ let mut jenv = unsafe { JNIEnv :: from_raw ( env) } . unwrap ( ) ;
150+ let jvm = jenv. get_java_vm ( ) . unwrap ( ) ;
153151
152+ // In Native daemon thread, it's impossible to access TerracottaAndroidAPI with find_class.
153+ // So we find them here and use a global ref to hold it.
154+ let callback_class = jenv. find_class ( "net/burningtnt/terracotta/TerracottaAndroidAPI" ) . unwrap ( ) ;
155+ let callback_class = jenv. new_global_ref ( callback_class) . unwrap ( ) ;
156+ thread:: spawn ( move || {
154157 let mut jenv = jvm. attach_current_thread_as_daemon ( ) . unwrap ( ) ;
155- let callback_class = jenv. find_class ( "net/burningtnt/terracotta/TerracottaAndroidAPI" ) . unwrap ( ) ;
156158 let callback_method = jenv. get_static_method_id (
157159 & callback_class, "onVpnServiceStateChanged" , "(BBBBSLjava/lang/String;)I"
158160 ) . unwrap ( ) ;
0 commit comments