polyhorn_android_sys/
bridge.rs1use 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}