From 1507b37425ac5c61e1a5a75d7a2de4c8e87af13d Mon Sep 17 00:00:00 2001 From: Robert Bragg Date: Sat, 1 Oct 2022 16:08:55 +0100 Subject: [PATCH] native-activity: port android_app_entry (mainloop init) from C to Rust --- .../native_app_glue/android_native_app_glue.c | 34 ++---------- .../native_app_glue/android_native_app_glue.h | 10 ++-- .../src/native_activity/ffi_aarch64.rs | 9 ++-- .../src/native_activity/ffi_arm.rs | 9 ++-- .../src/native_activity/ffi_i686.rs | 9 ++-- .../src/native_activity/ffi_x86_64.rs | 9 ++-- android-activity/src/native_activity/mod.rs | 52 +++++++++++++++++-- 7 files changed, 73 insertions(+), 59 deletions(-) diff --git a/android-activity/native-activity-csrc/native-activity/native_app_glue/android_native_app_glue.c b/android-activity/native-activity-csrc/native-activity/native_app_glue/android_native_app_glue.c index 4c070c4..9377ecc 100644 --- a/android-activity/native-activity-csrc/native-activity/native_app_glue/android_native_app_glue.c +++ b/android-activity/native-activity-csrc/native-activity/native_app_glue/android_native_app_glue.c @@ -61,7 +61,7 @@ int8_t android_app_read_cmd(struct android_app* android_app) { return -1; } -static void print_cur_config(struct android_app* android_app) { +void print_cur_config(struct android_app* android_app) { char lang[2], country[2]; AConfiguration_getLanguage(android_app->config, lang); AConfiguration_getCountry(android_app->config, country); @@ -180,7 +180,7 @@ void android_app_post_exec_cmd(struct android_app* android_app, int8_t cmd) { } } -static void android_app_destroy(struct android_app* android_app) { +void android_app_destroy(struct android_app* android_app) { LOGV("android_app_destroy!"); free_saved_state(android_app); pthread_mutex_lock(&android_app->mutex); @@ -194,37 +194,9 @@ static void android_app_destroy(struct android_app* android_app) { // Can't touch android_app object after this. } -static void process_cmd(struct android_app* app, __attribute__((unused)) struct android_poll_source* source) { +void process_cmd(struct android_app* app, __attribute__((unused)) struct android_poll_source* source) { int8_t cmd = android_app_read_cmd(app); android_app_pre_exec_cmd(app, cmd); if (app->onAppCmd != NULL) app->onAppCmd(app, cmd); android_app_post_exec_cmd(app, cmd); } - -void* android_app_entry(void* param) { - struct android_app* android_app = (struct android_app*)param; - - android_app->config = AConfiguration_new(); - AConfiguration_fromAssetManager(android_app->config, android_app->activity->assetManager); - - print_cur_config(android_app); - - android_app->cmdPollSource.id = LOOPER_ID_MAIN; - android_app->cmdPollSource.app = android_app; - android_app->cmdPollSource.process = process_cmd; - - ALooper* looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS); - ALooper_addFd(looper, android_app->msgread, LOOPER_ID_MAIN, ALOOPER_EVENT_INPUT, NULL, - &android_app->cmdPollSource); - android_app->looper = looper; - - pthread_mutex_lock(&android_app->mutex); - android_app->running = 1; - pthread_cond_broadcast(&android_app->cond); - pthread_mutex_unlock(&android_app->mutex); - - _rust_glue_entry(android_app); - - android_app_destroy(android_app); - return NULL; -} diff --git a/android-activity/native-activity-csrc/native-activity/native_app_glue/android_native_app_glue.h b/android-activity/native-activity-csrc/native-activity/native_app_glue/android_native_app_glue.h index c4609ec..a73f748 100644 --- a/android-activity/native-activity-csrc/native-activity/native_app_glue/android_native_app_glue.h +++ b/android-activity/native-activity-csrc/native-activity/native_app_glue/android_native_app_glue.h @@ -334,13 +334,9 @@ void android_app_post_exec_cmd(struct android_app* android_app, int8_t cmd); void android_app_attach_input_queue_looper(struct android_app* android_app); void android_app_detach_input_queue_looper(struct android_app* android_app); -void* android_app_entry(void* param); - -/** - * This is the function that application code must implement, representing - * the main entry to the app. - */ -extern void _rust_glue_entry(struct android_app* app); +void print_cur_config(struct android_app* android_app); +void process_cmd(struct android_app* app, __attribute__((unused)) struct android_poll_source* source); +void android_app_destroy(struct android_app* android_app); #ifdef __cplusplus } diff --git a/android-activity/src/native_activity/ffi_aarch64.rs b/android-activity/src/native_activity/ffi_aarch64.rs index b8cf4b4..2c91497 100644 --- a/android-activity/src/native_activity/ffi_aarch64.rs +++ b/android-activity/src/native_activity/ffi_aarch64.rs @@ -6329,11 +6329,12 @@ extern "C" { pub fn android_app_detach_input_queue_looper(android_app: *mut android_app); } extern "C" { - pub fn android_app_entry(param: *mut ::std::os::raw::c_void) -> *mut ::std::os::raw::c_void; + pub fn print_cur_config(android_app: *mut android_app); } extern "C" { - #[doc = " This is the function that application code must implement, representing"] - #[doc = " the main entry to the app."] - pub fn _rust_glue_entry(app: *mut android_app); + pub fn process_cmd(app: *mut android_app, source: *mut android_poll_source); +} +extern "C" { + pub fn android_app_destroy(android_app: *mut android_app); } pub type __uint128_t = u128; diff --git a/android-activity/src/native_activity/ffi_arm.rs b/android-activity/src/native_activity/ffi_arm.rs index 9df36b6..30a88ef 100644 --- a/android-activity/src/native_activity/ffi_arm.rs +++ b/android-activity/src/native_activity/ffi_arm.rs @@ -6809,10 +6809,11 @@ extern "C" { pub fn android_app_detach_input_queue_looper(android_app: *mut android_app); } extern "C" { - pub fn android_app_entry(param: *mut ::std::os::raw::c_void) -> *mut ::std::os::raw::c_void; + pub fn print_cur_config(android_app: *mut android_app); } extern "C" { - #[doc = " This is the function that application code must implement, representing"] - #[doc = " the main entry to the app."] - pub fn _rust_glue_entry(app: *mut android_app); + pub fn process_cmd(app: *mut android_app, source: *mut android_poll_source); +} +extern "C" { + pub fn android_app_destroy(android_app: *mut android_app); } diff --git a/android-activity/src/native_activity/ffi_i686.rs b/android-activity/src/native_activity/ffi_i686.rs index 0f8604c..410dca4 100644 --- a/android-activity/src/native_activity/ffi_i686.rs +++ b/android-activity/src/native_activity/ffi_i686.rs @@ -8554,11 +8554,12 @@ extern "C" { pub fn android_app_detach_input_queue_looper(android_app: *mut android_app); } extern "C" { - pub fn android_app_entry(param: *mut ::std::os::raw::c_void) -> *mut ::std::os::raw::c_void; + pub fn print_cur_config(android_app: *mut android_app); } extern "C" { - #[doc = " This is the function that application code must implement, representing"] - #[doc = " the main entry to the app."] - pub fn _rust_glue_entry(app: *mut android_app); + pub fn process_cmd(app: *mut android_app, source: *mut android_poll_source); +} +extern "C" { + pub fn android_app_destroy(android_app: *mut android_app); } pub type __builtin_va_list = *mut ::std::os::raw::c_char; diff --git a/android-activity/src/native_activity/ffi_x86_64.rs b/android-activity/src/native_activity/ffi_x86_64.rs index e2fef1a..c0288f9 100644 --- a/android-activity/src/native_activity/ffi_x86_64.rs +++ b/android-activity/src/native_activity/ffi_x86_64.rs @@ -8572,12 +8572,13 @@ extern "C" { pub fn android_app_detach_input_queue_looper(android_app: *mut android_app); } extern "C" { - pub fn android_app_entry(param: *mut ::std::os::raw::c_void) -> *mut ::std::os::raw::c_void; + pub fn print_cur_config(android_app: *mut android_app); } extern "C" { - #[doc = " This is the function that application code must implement, representing"] - #[doc = " the main entry to the app."] - pub fn _rust_glue_entry(app: *mut android_app); + pub fn process_cmd(app: *mut android_app, source: *mut android_poll_source); +} +extern "C" { + pub fn android_app_destroy(android_app: *mut android_app); } pub type __builtin_va_list = [__va_list_tag; 1usize]; #[repr(C)] diff --git a/android-activity/src/native_activity/mod.rs b/android-activity/src/native_activity/mod.rs index 42e7096..6281265 100644 --- a/android-activity/src/native_activity/mod.rs +++ b/android-activity/src/native_activity/mod.rs @@ -479,10 +479,49 @@ impl AndroidAppInner { } } + +//////////////////////////// +// Rust-side event loop +//////////////////////////// + + extern "C" fn android_app_main(arg: *mut libc::c_void) -> *mut libc::c_void { - unsafe { ffi::android_app_entry(arg) as *mut _ } + unsafe { + let android_app: *mut ffi::android_app = arg.cast(); + + (*android_app).config = ndk_sys::AConfiguration_new(); + ndk_sys::AConfiguration_fromAssetManager((*android_app).config, (*(*android_app).activity).assetManager); + + ffi::print_cur_config(android_app); + + (*android_app).cmdPollSource.id = ffi::LOOPER_ID_MAIN as i32; + (*android_app).cmdPollSource.app = android_app; + (*android_app).cmdPollSource.process = Some(ffi::process_cmd); + + let looper = ndk_sys::ALooper_prepare(ndk_sys::ALOOPER_PREPARE_ALLOW_NON_CALLBACKS as libc::c_int); + ndk_sys::ALooper_addFd(looper, (*android_app).msgread, ffi::LOOPER_ID_MAIN as libc::c_int, ndk_sys::ALOOPER_EVENT_INPUT as libc::c_int, None, + &mut (*android_app).cmdPollSource as *mut _ as *mut _); + (*android_app).looper = looper; + + libc::pthread_mutex_lock(&mut (*android_app).mutex as *mut _); + (*android_app).running = 1; + libc::pthread_cond_broadcast(&mut (*android_app).cond as *mut _); + libc::pthread_mutex_unlock(&mut (*android_app).mutex as *mut _); + + _rust_glue_entry(android_app); + + ffi::android_app_destroy(android_app); + + ptr::null_mut() + } } + +/////////////////////////////// +// Java-side callback handling +/////////////////////////////// + + unsafe fn android_app_create(activity: *mut ffi::ANativeActivity, saved_state_in: *const libc::c_void, saved_state_size: libc::size_t) -> *mut ffi::android_app { @@ -575,10 +614,14 @@ unsafe fn android_app_write_cmd(android_app: *mut ffi::android_app, cmd: i8) { -1 => { let err = std::io::Error::last_os_error(); if err.kind() != std::io::ErrorKind::Interrupted { - panic!("Failure writing android_app cmd: {}", err); + log::error!("Failure writing android_app cmd: {}", err); + return; } } - count => panic!("Spurious write of {count} bytes while writing android_app cmd") + count => { + log::error!("Spurious write of {count} bytes while writing android_app cmd"); + return; + } } } } @@ -762,8 +805,7 @@ extern "Rust" { // This is a spring board between android_native_app_glue and the user's // `app_main` function. This is run on a dedicated thread spawned // by android_native_app_glue. -#[no_mangle] -pub unsafe extern "C" fn _rust_glue_entry(app: *mut ffi::android_app) { +pub unsafe fn _rust_glue_entry(app: *mut ffi::android_app) { // Maybe make this stdout/stderr redirection an optional / opt-in feature?... let mut logpipe: [RawFd; 2] = Default::default(); libc::pipe(logpipe.as_mut_ptr());