lib.rs (4458B) - raw
1 #[macro_use] 2 extern crate log; 3 4 mod common; 5 6 mod hook; 7 mod util; 8 mod mapped_lib; 9 mod config; 10 mod sig; 11 12 mod modules; 13 14 use android_logger::Config; 15 use log::LevelFilter; 16 use modules::{composer_hook, custom_font_hook, duplex_hook, fstat_hook, linker_hook, sqlite_hook, unary_call_hook}; 17 18 use jni::objects::{JObject, JString}; 19 use jni::sys::{jint, jstring, JNI_VERSION_1_6}; 20 use jni::{JNIEnv, JavaVM, NativeMethod}; 21 use util::get_jni_string; 22 23 use std::ffi::c_void; 24 use std::thread::JoinHandle; 25 26 fn pre_init() { 27 debug!("Pre init"); 28 linker_hook::init(); 29 custom_font_hook::init(); 30 fstat_hook::init(); 31 } 32 33 fn init(mut env: JNIEnv, _class: JObject, signature_cache: JString) -> jstring { 34 debug!("Initializing native lib"); 35 36 let start_time = std::time::Instant::now(); 37 38 // load signature cache 39 40 if !signature_cache.is_null() { 41 let sig_cache_str = get_jni_string(&mut env, signature_cache).expect("Failed to convert mappings to string"); 42 43 if let Ok(signature_cache) = serde_json::from_str(sig_cache_str.as_str()) { 44 sig::add_signatures(signature_cache); 45 } else { 46 error!("Failed to load signature cache"); 47 } 48 } 49 50 common::set_native_lib_instance(env.new_global_ref(_class).ok().expect("Failed to create global ref")); 51 52 let _ = common::CLIENT_MODULE; 53 54 // initialize modules asynchronously 55 56 let mut threads: Vec<JoinHandle<()>> = Vec::new(); 57 58 macro_rules! async_init { 59 ($($f:expr),*) => { 60 $( 61 threads.push(std::thread::spawn(move || { 62 $f; 63 })); 64 )* 65 }; 66 } 67 68 async_init!( 69 duplex_hook::init(), 70 unary_call_hook::init(), 71 composer_hook::init(), 72 sqlite_hook::init() 73 ); 74 75 threads.into_iter().for_each(|t| t.join().unwrap()); 76 77 info!("native init took {:?}", start_time.elapsed()); 78 79 // send back the signature cache 80 if let Ok(signature_cache) = serde_json::to_string(&sig::get_signatures()) { 81 env.new_string(signature_cache).ok().expect("Failed to create new string").into_raw() 82 } else { 83 std::ptr::null_mut() 84 } 85 } 86 87 88 #[allow(non_snake_case)] 89 #[no_mangle] 90 pub extern "system" fn JNI_OnLoad(_vm: JavaVM, _: *mut c_void) -> jint { 91 android_logger::init_once( 92 Config::default() 93 .with_max_level(LevelFilter::Debug) 94 .with_tag("SnapEnhanceNative") 95 ); 96 97 info!("JNI_OnLoad called"); 98 99 std::panic::set_hook(Box::new(|panic_info| { 100 error!("{:?}", panic_info); 101 })); 102 103 common::set_java_vm(_vm.get_java_vm_pointer()); 104 105 let mut env = _vm.get_env().expect("Failed to get JNIEnv"); 106 107 let native_lib_class = env.find_class("me/rhunk/snapenhance/nativelib/NativeLib").expect("NativeLib class not found"); 108 109 env.register_native_methods( 110 native_lib_class, 111 &[ 112 NativeMethod { 113 name: "preInit".into(), 114 sig: "()V".into(), 115 fn_ptr: pre_init as *mut c_void, 116 }, 117 NativeMethod { 118 name: "init".into(), 119 sig: "(Ljava/lang/String;)Ljava/lang/String;".into(), 120 fn_ptr: init as *mut c_void, 121 }, 122 NativeMethod { 123 name: "loadConfig".into(), 124 sig: "(Lme/rhunk/snapenhance/nativelib/NativeConfig;)V".into(), 125 fn_ptr: config::load_config as *mut c_void, 126 }, 127 NativeMethod { 128 name: "addLinkerSharedLibrary".into(), 129 sig: "(Ljava/lang/String;[B)V".into(), 130 fn_ptr: linker_hook::add_linker_shared_library as *mut c_void, 131 }, 132 NativeMethod { 133 name: "lockDatabase".into(), 134 sig: "(Ljava/lang/String;Ljava/lang/Runnable;)V".into(), 135 fn_ptr: sqlite_hook::lock_database as *mut c_void, 136 }, 137 NativeMethod { 138 name: "setComposerLoader".into(), 139 sig: "(Ljava/lang/String;)V".into(), 140 fn_ptr: composer_hook::set_composer_loader as *mut c_void, 141 }, 142 NativeMethod { 143 name: "composerEval".into(), 144 sig: "(Ljava/lang/String;)Ljava/lang/String;".into(), 145 fn_ptr: composer_hook::composer_eval as *mut c_void, 146 } 147 ] 148 ).expect("Failed to register native methods"); 149 150 JNI_VERSION_1_6 151 }