polyhorn_android_sys/
bridge.rs

1use jni::objects::{JObject, JValue};
2use jni::{sys, JNIEnv, JavaVM, NativeMethod};
3
4use super::Reference;
5
6pub trait Object {
7    fn from_reference(reference: Reference) -> Self;
8    fn as_reference(&self) -> &Reference;
9}
10
11pub struct VM(JavaVM);
12
13impl VM {
14    pub fn env(&self) -> Env {
15        Env::from(self.0.get_env().unwrap())
16    }
17
18    pub(crate) fn internal_clone(&self) -> VM {
19        unsafe { VM(JavaVM::from_raw(self.0.get_java_vm_pointer()).unwrap()) }
20    }
21}
22
23#[derive(Clone)]
24pub struct Env<'a> {
25    env: JNIEnv<'a>,
26}
27
28static mut SHARED_VM: Option<JavaVM> = None;
29
30impl<'a> Env<'a> {
31    pub unsafe fn new(env: *mut sys::JNIEnv) -> Env<'a> {
32        let env = Env {
33            env: JNIEnv::from_raw(env).unwrap(),
34        };
35
36        Self::set_vm(env.env.get_java_vm().unwrap());
37
38        env
39    }
40
41    pub fn set_vm(vm: JavaVM) {
42        unsafe {
43            SHARED_VM.replace(vm);
44        }
45    }
46
47    pub fn current() -> Env<'a> {
48        unsafe {
49            Env {
50                env: SHARED_VM.as_ref().map(|vm| vm.get_env()).unwrap().unwrap(),
51            }
52            .prolong_lifetime()
53        }
54    }
55
56    pub unsafe fn retain(&self, object: JObject<'a>) -> Reference {
57        Reference {
58            global_ref: self.unwrap(self.env.new_global_ref(object)),
59            vm: VM(self.env.get_java_vm().unwrap()),
60        }
61    }
62
63    pub unsafe fn prolong_lifetime<'b>(&self) -> Env<'b> {
64        Env {
65            env: std::mem::transmute(self.env.clone()),
66        }
67    }
68
69    pub unsafe fn call_constructor(
70        &self,
71        name: &str,
72        sig: &str,
73        args: &[JValue<'a>],
74    ) -> JObject<'a> {
75        let class = self.unwrap(self.env.find_class(name));
76        let args = args.into_iter().map(|&arg| arg.into()).collect::<Vec<_>>();
77        self.unwrap(self.env.new_object(class, sig, &args))
78    }
79
80    pub unsafe fn call_static_method(
81        &self,
82        class: &str,
83        name: &str,
84        sig: &str,
85        args: &[JValue],
86    ) -> JValue<'a> {
87        let class = self.unwrap(self.env.find_class(class));
88        let args = args.into_iter().map(|&arg| arg.into()).collect::<Vec<_>>();
89        self.unwrap(self.env.call_static_method(class, name, sig, &args))
90    }
91
92    pub unsafe fn call_method(
93        &self,
94        object: JObject<'a>,
95        name: &str,
96        sig: &str,
97        args: &[JValue],
98    ) -> JValue<'a> {
99        let args = args.into_iter().map(|&arg| arg.into()).collect::<Vec<_>>();
100        self.unwrap(self.env.call_method(object, name, sig, &args))
101    }
102
103    pub unsafe fn register_natives(
104        &self,
105        name: &str,
106        methods: impl IntoIterator<Item = NativeMethod>,
107    ) {
108        let class = self.unwrap(self.env.find_class(name));
109        self.unwrap(
110            self.env.register_native_methods(
111                class,
112                &methods
113                    .into_iter()
114                    .map(|method| jni::NativeMethod {
115                        name: method.name.into(),
116                        sig: method.sig.into(),
117                        fn_ptr: method.fn_ptr,
118                    })
119                    .collect::<Vec<_>>(),
120            ),
121        );
122    }
123
124    unsafe fn unwrap<T>(&self, value: jni::errors::Result<T>) -> T {
125        if value.is_err() {
126            let _ = self.env.exception_describe();
127        }
128
129        value.unwrap()
130    }
131
132    pub unsafe fn assume_object(&self, value: JValue<'a>) -> JObject<'a> {
133        match value {
134            JValue::Object(object) => object,
135            _ => unreachable!(),
136        }
137    }
138
139    pub unsafe fn byte_array(&self, values: &[u8]) -> JObject<'a> {
140        assert!(values.len() <= std::i32::MAX as usize);
141
142        let array = self.unwrap(self.env.new_byte_array(values.len() as i32));
143        let elements = self.unwrap(self.env.get_byte_array_elements(array));
144        std::ptr::copy_nonoverlapping(values.as_ptr(), elements.0 as *mut u8, values.len());
145
146        self.unwrap(self.env.release_byte_array_elements(
147            array,
148            elements.0.as_mut().unwrap(),
149            jni::objects::ReleaseMode::NoCopyBack,
150        ));
151
152        array.into()
153    }
154}
155
156impl<'a> From<JNIEnv<'a>> for Env<'a> {
157    fn from(env: JNIEnv<'a>) -> Self {
158        Env { env }
159    }
160}