Skip to content

Commit 04f5bb7

Browse files
committed
fix(android): Fix JNI signature mismatch causing SIGSEGV on Android 11+
- Fixed initialize() function to return jstring instead of void to match Java signature - Changed jstring_to_string() to return Option<String> instead of panicking on error - Updated all call sites to handle the Option return type safely This resolves the crash on newer Android versions where JNI signature mismatch was causing segmentation faults during app initialization.
1 parent c640979 commit 04f5bb7

File tree

1 file changed

+44
-14
lines changed

1 file changed

+44
-14
lines changed

aw-server/src/android/mod.rs

Lines changed: 44 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -82,9 +82,17 @@ pub mod android {
8282
output.into_raw()
8383
}
8484

85-
unsafe fn jstring_to_string(env: &JNIEnv, string: JString) -> String {
86-
let c_str = CStr::from_ptr(env.get_string(string).expect("invalid string").as_ptr());
87-
String::from(c_str.to_str().unwrap())
85+
unsafe fn jstring_to_string(env: &JNIEnv, string: JString) -> Option<String> {
86+
match env.get_string(string) {
87+
Ok(java_str) => {
88+
let c_str = CStr::from_ptr(java_str.as_ptr());
89+
match c_str.to_str() {
90+
Ok(str_slice) => Some(String::from(str_slice)),
91+
Err(_) => None,
92+
}
93+
}
94+
Err(_) => None,
95+
}
8896
}
8997

9098
unsafe fn string_to_jstring(env: &JNIEnv, string: String) -> jstring {
@@ -136,7 +144,7 @@ pub mod android {
136144
pub unsafe extern "C" fn Java_net_activitywatch_android_RustInterface_initialize(
137145
env: JNIEnv,
138146
_: JClass,
139-
) {
147+
) -> jstring {
140148
if !INITIALIZED {
141149
android_logger::init_once(
142150
Config::default()
@@ -154,9 +162,8 @@ pub mod android {
154162
}
155163
INITIALIZED = true;
156164

157-
// Without this it might not work due to weird error probably arising from Rust optimizing away the JNIEnv:
158-
// JNI DETECTED ERROR IN APPLICATION: use of deleted weak global reference
159-
string_to_jstring(&env, "test".to_string());
165+
// Return a string as expected by Java
166+
string_to_jstring(&env, "initialized".to_string())
160167
}
161168

162169
#[no_mangle]
@@ -165,9 +172,16 @@ pub mod android {
165172
_: JClass,
166173
java_dir: JString,
167174
) {
168-
let path = &jstring_to_string(&env, java_dir);
169-
debug!("Setting android data dir as {}", path);
170-
dirs::set_android_data_dir(path);
175+
match jstring_to_string(&env, java_dir) {
176+
Some(path) => {
177+
debug!("Setting android data dir as {}", path);
178+
dirs::set_android_data_dir(&path);
179+
}
180+
None => {
181+
// Failed to convert string - do nothing and return
182+
return;
183+
}
184+
}
171185
}
172186

173187
#[no_mangle]
@@ -185,7 +199,10 @@ pub mod android {
185199
_: JClass,
186200
java_bucket: JString,
187201
) -> jstring {
188-
let bucket = jstring_to_string(&env, java_bucket);
202+
let bucket = match jstring_to_string(&env, java_bucket) {
203+
Some(s) => s,
204+
None => return create_error_object(&env, "Failed to parse bucket string".to_string()),
205+
};
189206
let bucket_json: Bucket = match serde_json::from_str(&bucket) {
190207
Ok(json) => json,
191208
Err(err) => return create_error_object(&env, err.to_string()),
@@ -207,8 +224,16 @@ pub mod android {
207224
java_event: JString,
208225
java_pulsetime: jdouble,
209226
) -> jstring {
210-
let bucket_id = jstring_to_string(&env, java_bucket_id);
211-
let event = jstring_to_string(&env, java_event);
227+
let bucket_id = match jstring_to_string(&env, java_bucket_id) {
228+
Some(s) => s,
229+
None => {
230+
return create_error_object(&env, "Failed to parse bucket_id string".to_string())
231+
}
232+
};
233+
let event = match jstring_to_string(&env, java_event) {
234+
Some(s) => s,
235+
None => return create_error_object(&env, "Failed to parse event string".to_string()),
236+
};
212237
let pulsetime = java_pulsetime as f64;
213238
let event_json: Event = match serde_json::from_str(&event) {
214239
Ok(json) => json,
@@ -233,7 +258,12 @@ pub mod android {
233258
java_bucket_id: JString,
234259
java_limit: jint,
235260
) -> jstring {
236-
let bucket_id = jstring_to_string(&env, java_bucket_id);
261+
let bucket_id = match jstring_to_string(&env, java_bucket_id) {
262+
Some(s) => s,
263+
None => {
264+
return create_error_object(&env, "Failed to parse bucket_id string".to_string())
265+
}
266+
};
237267
let limit = java_limit as u64;
238268
match openDatastore().get_events(&bucket_id, None, None, Some(limit)) {
239269
Ok(events) => string_to_jstring(&env, json!(events).to_string()),

0 commit comments

Comments
 (0)