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 }