diff --git a/android-activity/src/native_activity/mod.rs b/android-activity/src/native_activity/mod.rs index e923a4a..3753362 100644 --- a/android-activity/src/native_activity/mod.rs +++ b/android-activity/src/native_activity/mod.rs @@ -60,10 +60,10 @@ impl<'a> StateSaver<'a> { // In case the application calls store() multiple times for some reason we // make sure to free any pre-existing state... - if (*app_ptr).savedState != ptr::null_mut() { - libc::free((*app_ptr).savedState); - (*app_ptr).savedState = ptr::null_mut(); - (*app_ptr).savedStateSize = 0; + if (*app_ptr).saved_state != ptr::null_mut() { + libc::free((*app_ptr).saved_state); + (*app_ptr).saved_state = ptr::null_mut(); + (*app_ptr).saved_state_size = 0; } let buf = libc::malloc(state.len()); @@ -80,8 +80,8 @@ impl<'a> StateSaver<'a> { buf.copy_from_slice(state); } - (*app_ptr).savedState = buf; - (*app_ptr).savedStateSize = state.len() as _; + (*app_ptr).saved_state = buf; + (*app_ptr).saved_state_size = state.len() as _; } } } @@ -94,10 +94,10 @@ impl<'a> StateLoader<'a> { pub fn load(&self) -> Option> { unsafe { let app_ptr = self.app.native_app.as_ptr(); - if (*app_ptr).savedState != ptr::null_mut() && (*app_ptr).savedStateSize > 0 { + if (*app_ptr).saved_state != ptr::null_mut() && (*app_ptr).saved_state_size > 0 { let buf: &mut [u8] = std::slice::from_raw_parts_mut( - (*app_ptr).savedState.cast(), - (*app_ptr).savedStateSize as usize, + (*app_ptr).saved_state.cast(), + (*app_ptr).saved_state_size as usize, ); let state = buf.to_vec(); Some(state) @@ -127,74 +127,97 @@ impl AndroidAppWaker { } /// These are the original C structs / constants from android_native_app_glue.c naively -/// ported to Rust via bindgen. +/// ported to Rust. /// /// TODO: start integrating all this state directly into `AndroidApp`/`NativeAppGlue` mod ffi { - pub const LOOPER_ID_MAIN: ::std::os::raw::c_uint = 1; - pub const LOOPER_ID_INPUT: ::std::os::raw::c_uint = 2; + pub const LOOPER_ID_MAIN: libc::c_uint = 1; + pub const LOOPER_ID_INPUT: libc::c_uint = 2; //pub const LOOPER_ID_USER: ::std::os::raw::c_uint = 3; - pub const APP_CMD_INPUT_CHANGED: ::std::os::raw::c_uint = 0; - pub const APP_CMD_INIT_WINDOW: ::std::os::raw::c_uint = 1; - pub const APP_CMD_TERM_WINDOW: ::std::os::raw::c_uint = 2; - pub const APP_CMD_WINDOW_RESIZED: ::std::os::raw::c_uint = 3; - pub const APP_CMD_WINDOW_REDRAW_NEEDED: ::std::os::raw::c_uint = 4; - pub const APP_CMD_CONTENT_RECT_CHANGED: ::std::os::raw::c_uint = 5; - pub const APP_CMD_GAINED_FOCUS: ::std::os::raw::c_uint = 6; - pub const APP_CMD_LOST_FOCUS: ::std::os::raw::c_uint = 7; - pub const APP_CMD_CONFIG_CHANGED: ::std::os::raw::c_uint = 8; - pub const APP_CMD_LOW_MEMORY: ::std::os::raw::c_uint = 9; - pub const APP_CMD_START: ::std::os::raw::c_uint = 10; - pub const APP_CMD_RESUME: ::std::os::raw::c_uint = 11; - pub const APP_CMD_SAVE_STATE: ::std::os::raw::c_uint = 12; - pub const APP_CMD_PAUSE: ::std::os::raw::c_uint = 13; - pub const APP_CMD_STOP: ::std::os::raw::c_uint = 14; - pub const APP_CMD_DESTROY: ::std::os::raw::c_uint = 15; + #[derive(Clone, Copy, Eq, PartialEq, Debug)] + pub enum AppCmd { + InputChanged = 0, + InitWindow = 1, + TermWindow = 2, + WindowResized = 3, + WindowRedrawNeeded = 4, + ContentRectChanged = 5, + GainedFocus = 6, + LostFocus = 7, + ConfigChanged = 8, + LowMemory = 9, + Start = 10, + Resume = 11, + SaveState = 12, + Pause = 13, + Stop = 14, + Destroy = 15, + } + impl TryFrom for AppCmd { + type Error = (); - pub struct android_poll_source { + fn try_from(value: i8) -> Result { + match value { + 0 => Ok(AppCmd::InputChanged), + 1 => Ok(AppCmd::InitWindow), + 2 => Ok(AppCmd::TermWindow), + 3 => Ok(AppCmd::WindowResized), + 4 => Ok(AppCmd::WindowRedrawNeeded), + 5 => Ok(AppCmd::ContentRectChanged), + 6 => Ok(AppCmd::GainedFocus), + 7 => Ok(AppCmd::LostFocus), + 8 => Ok(AppCmd::ConfigChanged), + 9 => Ok(AppCmd::LowMemory), + 10 => Ok(AppCmd::Start), + 11 => Ok(AppCmd::Resume), + 12 => Ok(AppCmd::SaveState), + 13 => Ok(AppCmd::Pause), + 14 => Ok(AppCmd::Stop), + 15 => Ok(AppCmd::Destroy), + _ => Err(()) + } + } + } + + pub struct NativeActivityPollSource { pub id: i32, - pub app: *mut android_app, + pub app: *mut NativeActivityGlue, pub process: ::std::option::Option< - unsafe extern "C" fn(app: *mut android_app, source: *mut android_poll_source), + unsafe extern "C" fn(app: *mut NativeActivityGlue, source: *mut NativeActivityPollSource), >, } - pub struct android_app { - pub userData: *mut ::std::os::raw::c_void, - pub onAppCmd: ::std::option::Option, - pub onInputEvent: ::std::option::Option< - unsafe extern "C" fn(app: *mut android_app, event: *mut ndk_sys::AInputEvent) -> i32, - >, + pub struct NativeActivityGlue { pub activity: *mut ndk_sys::ANativeActivity, pub config: *mut ndk_sys::AConfiguration, - pub savedState: *mut ::std::os::raw::c_void, - pub savedStateSize: libc::size_t, + pub saved_state: *mut libc::c_void, + pub saved_state_size: libc::size_t, pub looper: *mut ndk_sys::ALooper, - pub inputQueue: *mut ndk_sys::AInputQueue, + pub input_queue: *mut ndk_sys::AInputQueue, pub window: *mut ndk_sys::ANativeWindow, - pub contentRect: ndk_sys::ARect, - pub activityState: ::std::os::raw::c_int, - pub destroyRequested: ::std::os::raw::c_int, + pub content_rect: ndk_sys::ARect, + pub activity_state: libc::c_int, + pub destroy_requested: bool, pub mutex: libc::pthread_mutex_t, pub cond: libc::pthread_cond_t, - pub msgread: ::std::os::raw::c_int, - pub msgwrite: ::std::os::raw::c_int, + pub msg_read: libc::c_int, + pub msg_write: libc::c_int, pub thread: libc::pthread_t, - pub cmdPollSource: android_poll_source, - pub inputPollSource: android_poll_source, - pub running: ::std::os::raw::c_int, - pub stateSaved: ::std::os::raw::c_int, - pub destroyed: ::std::os::raw::c_int, - pub redrawNeeded: ::std::os::raw::c_int, - pub pendingInputQueue: *mut ndk_sys::AInputQueue, - pub pendingWindow: *mut ndk_sys::ANativeWindow, - pub pendingContentRect: ndk_sys::ARect, + pub cmd_poll_source: NativeActivityPollSource, + pub input_poll_source: NativeActivityPollSource, + pub running: bool, + pub state_saved: bool, + pub destroyed: bool, + pub redraw_needed: bool, + pub pending_input_queue: *mut ndk_sys::AInputQueue, + pub pending_window: *mut ndk_sys::ANativeWindow, + pub pending_content_rect: ndk_sys::ARect, } } impl AndroidApp { - pub(crate) unsafe fn from_ptr(ptr: NonNull) -> AndroidApp { + pub(crate) unsafe fn from_ptr(ptr: NonNull) -> AndroidApp { // Note: we don't use from_ptr since we don't own the android_app.config // and need to keep in mind that the Drop handler is going to call // AConfiguration_delete() @@ -212,10 +235,10 @@ impl AndroidApp { #[derive(Debug)] struct NativeAppGlue { - ptr: NonNull, + ptr: NonNull, } impl Deref for NativeAppGlue { - type Target = NonNull; + type Target = NonNull; fn deref(&self) -> &Self::Target { &self.ptr @@ -292,53 +315,50 @@ impl AndroidAppInner { match id as u32 { ffi::LOOPER_ID_MAIN => { trace!("ALooper_pollAll returned ID_MAIN"); - let source: *mut ffi::android_poll_source = source.cast(); + let source: *mut ffi::NativeActivityPollSource = source.cast(); if source != ptr::null_mut() { - if let Some(cmd_i) = android_app_read_cmd(native_app.as_ptr()) { - let cmd = match cmd_i as libc::c_uint { + if let Some(ipc_cmd) = android_app_read_cmd(native_app.as_ptr()) { + let main_cmd = match ipc_cmd { // We don't forward info about the AInputQueue to apps since it's // an implementation details that's also not compatible with // GameActivity - ffi::APP_CMD_INPUT_CHANGED => None, + ffi::AppCmd::InputChanged => None, - ffi::APP_CMD_INIT_WINDOW => Some(MainEvent::InitWindow {}), - ffi::APP_CMD_TERM_WINDOW => Some(MainEvent::TerminateWindow {}), - ffi::APP_CMD_WINDOW_RESIZED => { + ffi::AppCmd::InitWindow => Some(MainEvent::InitWindow {}), + ffi::AppCmd::TermWindow => Some(MainEvent::TerminateWindow {}), + ffi::AppCmd::WindowResized => { Some(MainEvent::WindowResized {}) } - ffi::APP_CMD_WINDOW_REDRAW_NEEDED => { + ffi::AppCmd::WindowRedrawNeeded => { Some(MainEvent::RedrawNeeded {}) } - ffi::APP_CMD_CONTENT_RECT_CHANGED => { + ffi::AppCmd::ContentRectChanged => { Some(MainEvent::ContentRectChanged {}) } - ffi::APP_CMD_GAINED_FOCUS => Some(MainEvent::GainedFocus), - ffi::APP_CMD_LOST_FOCUS => Some(MainEvent::LostFocus), - ffi::APP_CMD_CONFIG_CHANGED => { + ffi::AppCmd::GainedFocus => Some(MainEvent::GainedFocus), + ffi::AppCmd::LostFocus => Some(MainEvent::LostFocus), + ffi::AppCmd::ConfigChanged => { Some(MainEvent::ConfigChanged {}) } - ffi::APP_CMD_LOW_MEMORY => Some(MainEvent::LowMemory), - ffi::APP_CMD_START => Some(MainEvent::Start), - ffi::APP_CMD_RESUME => Some(MainEvent::Resume { + ffi::AppCmd::LowMemory => Some(MainEvent::LowMemory), + ffi::AppCmd::Start => Some(MainEvent::Start), + ffi::AppCmd::Resume => Some(MainEvent::Resume { loader: StateLoader { app: &self }, }), - ffi::APP_CMD_SAVE_STATE => Some(MainEvent::SaveState { + ffi::AppCmd::SaveState => Some(MainEvent::SaveState { saver: StateSaver { app: &self }, }), - ffi::APP_CMD_PAUSE => Some(MainEvent::Pause), - ffi::APP_CMD_STOP => Some(MainEvent::Stop), - ffi::APP_CMD_DESTROY => Some(MainEvent::Destroy), - - //ffi::NativeAppGlueAppCmd_APP_CMD_WINDOW_INSETS_CHANGED => MainEvent::InsetsChanged {}, - _ => unreachable!(), + ffi::AppCmd::Pause => Some(MainEvent::Pause), + ffi::AppCmd::Stop => Some(MainEvent::Stop), + ffi::AppCmd::Destroy => Some(MainEvent::Destroy), }; - trace!("Calling android_app_pre_exec_cmd({cmd_i})"); - android_app_pre_exec_cmd(native_app.as_ptr(), cmd_i); + trace!("Calling android_app_pre_exec_cmd({ipc_cmd:#?})"); + android_app_pre_exec_cmd(native_app.as_ptr(), ipc_cmd); - if let Some(cmd) = cmd { - trace!("Read ID_MAIN command {cmd_i} = {cmd:?}"); - match cmd { + if let Some(main_cmd) = main_cmd { + trace!("Read ID_MAIN command {ipc_cmd:#?} = {main_cmd:#?}"); + match main_cmd { MainEvent::ConfigChanged { .. } => { self.config.replace(Configuration::clone_from_ptr( NonNull::new_unchecked( @@ -362,12 +382,12 @@ impl AndroidAppInner { _ => {} } - trace!("Invoking callback for ID_MAIN command = {:?}", cmd); - callback(PollEvent::Main(cmd)); + trace!("Invoking callback for ID_MAIN command = {main_cmd:?}"); + callback(PollEvent::Main(main_cmd)); } - trace!("Calling android_app_post_exec_cmd({cmd_i})"); - android_app_post_exec_cmd(native_app.as_ptr(), cmd_i); + trace!("Calling android_app_post_exec_cmd({ipc_cmd:#?})"); + android_app_post_exec_cmd(native_app.as_ptr(), ipc_cmd); } } else { panic!("ALooper_pollAll returned ID_MAIN event with NULL android_poll_source!"); @@ -414,10 +434,10 @@ impl AndroidAppInner { unsafe { let app_ptr = self.native_app.as_ptr(); Rect { - left: (*app_ptr).contentRect.left, - right: (*app_ptr).contentRect.right, - top: (*app_ptr).contentRect.top, - bottom: (*app_ptr).contentRect.bottom, + left: (*app_ptr).content_rect.left, + right: (*app_ptr).content_rect.right, + top: (*app_ptr).content_rect.top, + bottom: (*app_ptr).content_rect.bottom, } } } @@ -486,7 +506,7 @@ impl AndroidAppInner { { let queue = unsafe { let app_ptr = self.native_app.as_ptr(); - if (*app_ptr).inputQueue == ptr::null_mut() { + if (*app_ptr).input_queue == ptr::null_mut() { return; } @@ -494,7 +514,7 @@ impl AndroidAppInner { // `InputAvailable` event. android_app_attach_input_queue_looper(app_ptr); - let queue = NonNull::new_unchecked((*app_ptr).inputQueue); + let queue = NonNull::new_unchecked((*app_ptr).input_queue); InputQueue::from_ptr(queue) }; @@ -549,45 +569,50 @@ impl AndroidAppInner { // Rust-side event loop //////////////////////////// -unsafe fn free_saved_state(android_app: *mut ffi::android_app) { +unsafe fn free_saved_state(android_app: *mut ffi::NativeActivityGlue) { libc::pthread_mutex_lock(&mut (*android_app).mutex as *mut _); - if (*android_app).savedState != ptr::null_mut() { - libc::free((*android_app).savedState); - (*android_app).savedState = ptr::null_mut(); - (*android_app).savedStateSize = 0; + if (*android_app).saved_state != ptr::null_mut() { + libc::free((*android_app).saved_state); + (*android_app).saved_state = ptr::null_mut(); + (*android_app).saved_state_size = 0; } libc::pthread_mutex_unlock(&mut (*android_app).mutex as *mut _); } -unsafe fn android_app_read_cmd(android_app: *mut ffi::android_app) -> Option { - let mut cmd: i8 = 0; +unsafe fn android_app_read_cmd(android_app: *mut ffi::NativeActivityGlue) -> Option { + let mut cmd_i: i8 = 0; loop { - match libc::read((*android_app).msgread, &mut cmd as *mut _ as *mut _, 1) { + match libc::read((*android_app).msg_read, &mut cmd_i as *mut _ as *mut _, 1) { 1 => { - match cmd as libc::c_uint { - ffi::APP_CMD_SAVE_STATE => { + let cmd = ffi::AppCmd::try_from(cmd_i); + return match cmd { + Ok(ffi::AppCmd::SaveState) => { free_saved_state(android_app); + Some(ffi::AppCmd::SaveState) } - _ => {} - } - return Some(cmd); + Ok(cmd) => Some(cmd), + Err(_) => { + log::error!("Spurious, unknown NativeActivityGlue cmd: {}", cmd_i); + None + } + }; } -1 => { let err = std::io::Error::last_os_error(); if err.kind() != std::io::ErrorKind::Interrupted { - log::error!("Failure reading android_app cmd: {}", err); + log::error!("Failure reading NativeActivityGlue cmd: {}", err); return None; } } count => { - log::error!("Spurious read of {count} bytes while reading android_app cmd"); + log::error!("Spurious read of {count} bytes while reading NativeActivityGlue cmd"); return None; } } } } -unsafe fn print_cur_config(android_app: *mut ffi::android_app) { +unsafe fn print_cur_config(android_app: *mut ffi::NativeActivityGlue) { let mut lang = [0u8; 2]; ndk_sys::AConfiguration_getLanguage((*android_app).config, lang[..].as_mut_ptr()); let lang = if lang[0] == 0 { @@ -619,101 +644,101 @@ unsafe fn print_cur_config(android_app: *mut ffi::android_app) { ndk_sys::AConfiguration_getUiModeNight((*android_app).config)); } -unsafe fn android_app_attach_input_queue_looper(android_app: *mut ffi::android_app) { - if (*android_app).inputQueue != ptr::null_mut() { +unsafe fn android_app_attach_input_queue_looper(android_app: *mut ffi::NativeActivityGlue) { + if (*android_app).input_queue != ptr::null_mut() { log::debug!("Attaching input queue to looper"); - ndk_sys::AInputQueue_attachLooper((*android_app).inputQueue, + ndk_sys::AInputQueue_attachLooper((*android_app).input_queue, (*android_app).looper, ffi::LOOPER_ID_INPUT as libc::c_int, None, - &mut (*android_app).inputPollSource as *mut _ as *mut _); + &mut (*android_app).input_poll_source as *mut _ as *mut _); } } -unsafe fn android_app_detach_input_queue_looper(android_app: *mut ffi::android_app) { - if (*android_app).inputQueue != ptr::null_mut() { +unsafe fn android_app_detach_input_queue_looper(android_app: *mut ffi::NativeActivityGlue) { + if (*android_app).input_queue != ptr::null_mut() { log::debug!("Detaching input queue from looper"); - ndk_sys::AInputQueue_detachLooper((*android_app).inputQueue); + ndk_sys::AInputQueue_detachLooper((*android_app).input_queue); } } -unsafe fn android_app_pre_exec_cmd(android_app: *mut ffi::android_app, cmd: i8) { - match cmd as libc::c_uint { - ffi::APP_CMD_INPUT_CHANGED => { - log::debug!("APP_CMD_INPUT_CHANGED\n"); +unsafe fn android_app_pre_exec_cmd(android_app: *mut ffi::NativeActivityGlue, cmd: ffi::AppCmd) { + match cmd { + ffi::AppCmd::InputChanged => { + log::debug!("AppCmd::INPUT_CHANGED\n"); libc::pthread_mutex_lock(&mut (*android_app).mutex as *mut _); - if (*android_app).inputQueue != ptr::null_mut() { + if (*android_app).input_queue != ptr::null_mut() { android_app_detach_input_queue_looper(android_app); } - (*android_app).inputQueue = (*android_app).pendingInputQueue; - if (*android_app).inputQueue != ptr::null_mut() { + (*android_app).input_queue = (*android_app).pending_input_queue; + if (*android_app).input_queue != ptr::null_mut() { android_app_attach_input_queue_looper(android_app); } libc::pthread_cond_broadcast(&mut (*android_app).cond as *mut _); libc::pthread_mutex_unlock(&mut (*android_app).mutex as *mut _); } - ffi::APP_CMD_INIT_WINDOW => { - log::debug!("APP_CMD_INIT_WINDOW"); + ffi::AppCmd::InitWindow => { + log::debug!("AppCmd::INIT_WINDOW"); libc::pthread_mutex_lock(&mut (*android_app).mutex as *mut _); - (*android_app).window = (*android_app).pendingWindow; + (*android_app).window = (*android_app).pending_window; libc::pthread_cond_broadcast(&mut (*android_app).cond as *mut _); libc::pthread_mutex_unlock(&mut (*android_app).mutex as *mut _); } - ffi::APP_CMD_TERM_WINDOW => { - log::debug!("APP_CMD_TERM_WINDOW"); + ffi::AppCmd::TermWindow => { + log::debug!("AppCmd::TERM_WINDOW"); libc::pthread_cond_broadcast(&mut (*android_app).cond as *mut _); } - ffi::APP_CMD_RESUME | ffi::APP_CMD_START | ffi::APP_CMD_PAUSE | ffi::APP_CMD_STOP => { - log::debug!("activityState={}", cmd); + ffi::AppCmd::Resume | ffi::AppCmd::Start | ffi::AppCmd::Pause | ffi::AppCmd::Stop => { + log::debug!("activityState={:#?}", cmd); libc::pthread_mutex_lock(&mut (*android_app).mutex as *mut _); - (*android_app).activityState = cmd as i32; + (*android_app).activity_state = cmd as i32; libc::pthread_cond_broadcast(&mut (*android_app).cond as *mut _); libc::pthread_mutex_unlock(&mut (*android_app).mutex as *mut _); } - ffi::APP_CMD_CONFIG_CHANGED => { - log::debug!("APP_CMD_CONFIG_CHANGED"); + ffi::AppCmd::ConfigChanged => { + log::debug!("AppCmd::CONFIG_CHANGED"); ndk_sys::AConfiguration_fromAssetManager((*android_app).config, (*(*android_app).activity).assetManager); print_cur_config(android_app); } - ffi::APP_CMD_DESTROY => { - log::debug!("APP_CMD_DESTROY"); - (*android_app).destroyRequested = 1; + ffi::AppCmd::Destroy => { + log::debug!("AppCmd::DESTROY"); + (*android_app).destroy_requested = true; } - _ => {} + _ => { } } } -unsafe fn android_app_post_exec_cmd(android_app: *mut ffi::android_app, cmd: i8) { - match cmd as libc::c_uint { - ffi::APP_CMD_TERM_WINDOW => { - log::debug!("APP_CMD_TERM_WINDOW"); +unsafe fn android_app_post_exec_cmd(android_app: *mut ffi::NativeActivityGlue, cmd: ffi::AppCmd) { + match cmd { + ffi::AppCmd::TermWindow => { + log::debug!("AppCmd::TERM_WINDOW"); libc::pthread_mutex_lock(&mut (*android_app).mutex as *mut _); (*android_app).window = ptr::null_mut(); libc::pthread_cond_broadcast(&mut (*android_app).cond as *mut _); libc::pthread_mutex_unlock(&mut (*android_app).mutex as *mut _); } - ffi::APP_CMD_SAVE_STATE => { - log::debug!("APP_CMD_SAVE_STATE"); + ffi::AppCmd::SaveState => { + log::debug!("AppCmd::SAVE_STATE"); libc::pthread_mutex_lock(&mut (*android_app).mutex as *mut _); - (*android_app).stateSaved = 1; + (*android_app).state_saved = true; libc::pthread_cond_broadcast(&mut (*android_app).cond as *mut _); libc::pthread_mutex_unlock(&mut (*android_app).mutex as *mut _); } - ffi::APP_CMD_RESUME => { + ffi::AppCmd::Resume => { free_saved_state(android_app); } _ => { } } } -unsafe fn android_app_destroy(android_app: *mut ffi::android_app) { +unsafe fn android_app_destroy(android_app: *mut ffi::NativeActivityGlue) { log::debug!("android_app_destroy!"); free_saved_state(android_app); libc::pthread_mutex_lock(&mut (*android_app).mutex as *mut _); - if (*android_app).inputQueue != ptr::null_mut() { - ndk_sys::AInputQueue_detachLooper((*android_app).inputQueue); + if (*android_app).input_queue != ptr::null_mut() { + ndk_sys::AInputQueue_detachLooper((*android_app).input_queue); } ndk_sys::AConfiguration_delete((*android_app).config); - (*android_app).destroyed = 1; + (*android_app).destroyed = true; libc::pthread_cond_broadcast(&mut (*android_app).cond as *mut _); libc::pthread_mutex_unlock(&mut (*android_app).mutex as *mut _); // Can't touch android_app object after this. @@ -721,24 +746,24 @@ unsafe fn android_app_destroy(android_app: *mut ffi::android_app) { extern "C" fn android_app_main(arg: *mut libc::c_void) -> *mut libc::c_void { unsafe { - let android_app: *mut ffi::android_app = arg.cast(); + let android_app: *mut ffi::NativeActivityGlue = arg.cast(); (*android_app).config = ndk_sys::AConfiguration_new(); ndk_sys::AConfiguration_fromAssetManager((*android_app).config, (*(*android_app).activity).assetManager); 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 = None; + (*android_app).cmd_poll_source.id = ffi::LOOPER_ID_MAIN as i32; + (*android_app).cmd_poll_source.app = android_app; + (*android_app).cmd_poll_source.process = None; 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 _); + ndk_sys::ALooper_addFd(looper, (*android_app).msg_read, ffi::LOOPER_ID_MAIN as libc::c_int, ndk_sys::ALOOPER_EVENT_INPUT as libc::c_int, None, + &mut (*android_app).cmd_poll_source as *mut _ as *mut _); (*android_app).looper = looper; libc::pthread_mutex_lock(&mut (*android_app).mutex as *mut _); - (*android_app).running = 1; + (*android_app).running = true; libc::pthread_cond_broadcast(&mut (*android_app).cond as *mut _); libc::pthread_mutex_unlock(&mut (*android_app).mutex as *mut _); @@ -757,7 +782,7 @@ extern "C" fn android_app_main(arg: *mut libc::c_void) -> *mut libc::c_void { unsafe fn android_app_create(activity: *mut ndk_sys::ANativeActivity, - saved_state_in: *const libc::c_void, saved_state_size: libc::size_t) -> *mut ffi::android_app + saved_state_in: *const libc::c_void, saved_state_size: libc::size_t) -> *mut ffi::NativeActivityGlue { let mut msgpipe: [libc::c_int; 2] = [ -1, -1 ]; if libc::pipe(msgpipe.as_mut_ptr()) != 0 { @@ -773,34 +798,31 @@ unsafe fn android_app_create(activity: *mut ndk_sys::ANativeActivity, libc::memcpy(saved_state, saved_state_in, saved_state_size); } - let android_app = Box::into_raw(Box::new(ffi::android_app { - userData: ptr::null_mut(), - onAppCmd: None, - onInputEvent: None, + let android_app = Box::into_raw(Box::new(ffi::NativeActivityGlue { activity, config: ptr::null_mut(), - savedState: saved_state, - savedStateSize: saved_state_size, + saved_state, + saved_state_size, looper: ptr::null_mut(), - inputQueue: ptr::null_mut(), + input_queue: ptr::null_mut(), window: ptr::null_mut(), - contentRect: Rect::empty().into(), - activityState: 0, - destroyRequested: 0, + content_rect: Rect::empty().into(), + activity_state: 0, + destroy_requested: false, mutex: libc::PTHREAD_MUTEX_INITIALIZER, cond: libc::PTHREAD_COND_INITIALIZER, - msgread: msgpipe[0], - msgwrite: msgpipe[1], + msg_read: msgpipe[0], + msg_write: msgpipe[1], thread: 0, - cmdPollSource: ffi::android_poll_source { id: 0, app: ptr::null_mut(), process: None }, - inputPollSource: ffi::android_poll_source { id: 0, app: ptr::null_mut(), process: None }, - running: 0, - stateSaved: 0, - destroyed: 0, - redrawNeeded: 0, - pendingInputQueue: ptr::null_mut(), - pendingWindow: ptr::null_mut(), - pendingContentRect: Rect::empty().into(), + cmd_poll_source: ffi::NativeActivityPollSource { id: 0, app: ptr::null_mut(), process: None }, + input_poll_source: ffi::NativeActivityPollSource { id: 0, app: ptr::null_mut(), process: None }, + running: false, + state_saved: false, + destroyed: false, + redraw_needed: false, + pending_input_queue: ptr::null_mut(), + pending_window: ptr::null_mut(), + pending_content_rect: Rect::empty().into(), })); // TODO: use std::os::spawn and drop the handle to detach instead of directly @@ -816,7 +838,7 @@ unsafe fn android_app_create(activity: *mut ndk_sys::ANativeActivity, // TODO: switch to std::sync::Condvar // Wait for thread to start. libc::pthread_mutex_lock(&mut (*android_app).mutex as *mut _); - while (*android_app).running == 0 { + while (*android_app).running == false { libc::pthread_cond_wait(&mut (*android_app).cond as *mut _, &mut (*android_app).mutex as *mut _); } libc::pthread_mutex_unlock(&mut (*android_app).mutex as *mut _); @@ -824,16 +846,16 @@ unsafe fn android_app_create(activity: *mut ndk_sys::ANativeActivity, android_app } -unsafe fn android_app_drop(android_app: *mut ffi::android_app) { +unsafe fn android_app_drop(android_app: *mut ffi::NativeActivityGlue) { libc::pthread_mutex_lock(&mut (*android_app).mutex as *mut _); - android_app_write_cmd(android_app, ffi::APP_CMD_DESTROY as i8); - while !(*android_app).destroyed == 0 { + android_app_write_cmd(android_app, ffi::AppCmd::Destroy as i8); + while !(*android_app).destroyed == false { libc::pthread_cond_wait(&mut (*android_app).cond as *mut _, &mut (*android_app).mutex as *mut _); } libc::pthread_mutex_unlock(&mut (*android_app).mutex as *mut _); - libc::close((*android_app).msgread); - libc::close((*android_app).msgwrite); + libc::close((*android_app).msg_read); + libc::close((*android_app).msg_write); libc::pthread_cond_destroy(&mut (*android_app).cond as *mut _); libc::pthread_mutex_destroy(&mut (*android_app).mutex as *mut _); @@ -841,54 +863,54 @@ unsafe fn android_app_drop(android_app: *mut ffi::android_app) { // Box dropped here } -unsafe fn android_app_write_cmd(android_app: *mut ffi::android_app, cmd: i8) { +unsafe fn android_app_write_cmd(android_app: *mut ffi::NativeActivityGlue, cmd: i8) { loop { - match libc::write((*android_app).msgwrite, &cmd as *const _ as *const _, 1) { + match libc::write((*android_app).msg_write, &cmd as *const _ as *const _, 1) { 1 => break, -1 => { let err = std::io::Error::last_os_error(); if err.kind() != std::io::ErrorKind::Interrupted { - log::error!("Failure writing android_app cmd: {}", err); + log::error!("Failure writing NativeActivityGlue cmd: {}", err); return; } } count => { - log::error!("Spurious write of {count} bytes while writing android_app cmd"); + log::error!("Spurious write of {count} bytes while writing NativeActivityGlue cmd"); return; } } } } -unsafe fn android_app_set_input(android_app: *mut ffi::android_app, input_queue: *mut ndk_sys::AInputQueue) { +unsafe fn android_app_set_input(android_app: *mut ffi::NativeActivityGlue, input_queue: *mut ndk_sys::AInputQueue) { libc::pthread_mutex_lock(&mut (*android_app).mutex as *mut _); - (*android_app).pendingInputQueue = input_queue; - android_app_write_cmd(android_app, ffi::APP_CMD_INPUT_CHANGED as i8); - while (*android_app).inputQueue != (*android_app).pendingInputQueue { + (*android_app).pending_input_queue = input_queue; + android_app_write_cmd(android_app, ffi::AppCmd::InputChanged as i8); + while (*android_app).input_queue != (*android_app).pending_input_queue { libc::pthread_cond_wait(&mut (*android_app).cond as *mut _, &mut (*android_app).mutex as *mut _); } libc::pthread_mutex_unlock(&mut (*android_app).mutex as *mut _); } -unsafe fn android_app_set_window(android_app: *mut ffi::android_app, window: *mut ndk_sys::ANativeWindow) { +unsafe fn android_app_set_window(android_app: *mut ffi::NativeActivityGlue, window: *mut ndk_sys::ANativeWindow) { libc::pthread_mutex_lock(&mut (*android_app).mutex as *mut _); - if (*android_app).pendingWindow != ptr::null_mut() { - android_app_write_cmd(android_app, ffi::APP_CMD_TERM_WINDOW as i8); + if (*android_app).pending_window != ptr::null_mut() { + android_app_write_cmd(android_app, ffi::AppCmd::TermWindow as i8); } - (*android_app).pendingWindow = window; + (*android_app).pending_window = window; if window != ptr::null_mut() { - android_app_write_cmd(android_app, ffi::APP_CMD_INIT_WINDOW as i8); + android_app_write_cmd(android_app, ffi::AppCmd::InitWindow as i8); } - while (*android_app).window != (*android_app).pendingWindow { + while (*android_app).window != (*android_app).pending_window { libc::pthread_cond_wait(&mut (*android_app).cond as *mut _, &mut (*android_app).mutex as *mut _); } libc::pthread_mutex_unlock(&mut (*android_app).mutex as *mut _); } -unsafe fn android_app_set_activity_state(android_app: *mut ffi::android_app, cmd: i8) { +unsafe fn android_app_set_activity_state(android_app: *mut ffi::NativeActivityGlue, cmd: i8) { libc::pthread_mutex_lock(&mut (*android_app).mutex as *mut _); android_app_write_cmd(android_app, cmd); - while (*android_app).activityState as i8 != cmd { + while (*android_app).activity_state as i8 != cmd { libc::pthread_cond_wait(&mut (*android_app).cond as *mut _, &mut (*android_app).mutex as *mut _); } libc::pthread_mutex_unlock(&mut (*android_app).mutex as *mut _); @@ -897,7 +919,7 @@ unsafe fn android_app_set_activity_state(android_app: *mut ffi::android_app, cmd unsafe extern "C" fn on_destroy(activity: *mut ndk_sys::ANativeActivity) { log::debug!("Destroy: {:p}\n", activity); - let android_app: *mut ffi::android_app = (*activity).instance.cast(); + let android_app: *mut ffi::NativeActivityGlue = (*activity).instance.cast(); (*activity).instance = ptr::null_mut(); android_app_drop(android_app); } @@ -905,33 +927,33 @@ unsafe extern "C" fn on_destroy(activity: *mut ndk_sys::ANativeActivity) { unsafe extern "C" fn on_start(activity: *mut ndk_sys::ANativeActivity) { log::debug!("Start: {:p}\n", activity); - let android_app: *mut ffi::android_app = (*activity).instance.cast(); - android_app_set_activity_state(android_app, ffi::APP_CMD_START as i8); + let android_app: *mut ffi::NativeActivityGlue = (*activity).instance.cast(); + android_app_set_activity_state(android_app, ffi::AppCmd::Start as i8); } unsafe extern "C" fn on_resume(activity: *mut ndk_sys::ANativeActivity) { log::debug!("Resume: {:p}\n", activity); - let android_app: *mut ffi::android_app = (*activity).instance.cast(); - android_app_set_activity_state(android_app, ffi::APP_CMD_RESUME as i8); + let android_app: *mut ffi::NativeActivityGlue = (*activity).instance.cast(); + android_app_set_activity_state(android_app, ffi::AppCmd::Resume as i8); } unsafe extern "C" fn on_save_instance_state(activity: *mut ndk_sys::ANativeActivity, out_len: *mut ndk_sys::size_t) -> *mut libc::c_void { - let android_app: *mut ffi::android_app = (*activity).instance.cast(); + let android_app: *mut ffi::NativeActivityGlue = (*activity).instance.cast(); let mut saved_state: *mut libc::c_void = ptr::null_mut(); log::debug!("SaveInstanceState: {:p}\n", activity); libc::pthread_mutex_lock(&mut (*android_app).mutex as *mut _); - (*android_app).stateSaved = 0; - android_app_write_cmd(android_app, ffi::APP_CMD_SAVE_STATE as i8); - while (*android_app).stateSaved == 0 { + (*android_app).state_saved = false; + android_app_write_cmd(android_app, ffi::AppCmd::SaveState as i8); + while (*android_app).state_saved == false { libc::pthread_cond_wait(&mut (*android_app).cond as *mut _, &mut (*android_app).mutex as *mut _); } - if (*android_app).savedState != ptr::null_mut() { - saved_state = (*android_app).savedState; - *out_len = (*android_app).savedStateSize as _; - (*android_app).savedState = ptr::null_mut(); - (*android_app).savedStateSize = 0; + if (*android_app).saved_state != ptr::null_mut() { + saved_state = (*android_app).saved_state; + *out_len = (*android_app).saved_state_size as _; + (*android_app).saved_state = ptr::null_mut(); + (*android_app).saved_state_size = 0; } libc::pthread_mutex_unlock(&mut (*android_app).mutex as *mut _); @@ -941,56 +963,56 @@ unsafe extern "C" fn on_save_instance_state(activity: *mut ndk_sys::ANativeActiv unsafe extern "C" fn on_pause(activity: *mut ndk_sys::ANativeActivity) { log::debug!("Pause: {:p}\n", activity); - let android_app: *mut ffi::android_app = (*activity).instance.cast(); - android_app_set_activity_state(android_app, ffi::APP_CMD_PAUSE as i8); + let android_app: *mut ffi::NativeActivityGlue = (*activity).instance.cast(); + android_app_set_activity_state(android_app, ffi::AppCmd::Pause as i8); } unsafe extern "C" fn on_stop(activity: *mut ndk_sys::ANativeActivity) { log::debug!("Stop: {:p}\n", activity); - let android_app: *mut ffi::android_app = (*activity).instance.cast(); - android_app_set_activity_state(android_app, ffi::APP_CMD_STOP as i8); + let android_app: *mut ffi::NativeActivityGlue = (*activity).instance.cast(); + android_app_set_activity_state(android_app, ffi::AppCmd::Stop as i8); } unsafe extern "C" fn on_configuration_changed(activity: *mut ndk_sys::ANativeActivity) { log::debug!("ConfigurationChanged: {:p}\n", activity); - let android_app: *mut ffi::android_app = (*activity).instance.cast(); - android_app_write_cmd(android_app, ffi::APP_CMD_CONFIG_CHANGED as i8); + let android_app: *mut ffi::NativeActivityGlue = (*activity).instance.cast(); + android_app_write_cmd(android_app, ffi::AppCmd::ConfigChanged as i8); } unsafe extern "C" fn on_low_memory(activity: *mut ndk_sys::ANativeActivity) { log::debug!("LowMemory: {:p}\n", activity); - let android_app: *mut ffi::android_app = (*activity).instance.cast(); - android_app_write_cmd(android_app, ffi::APP_CMD_LOW_MEMORY as i8); + let android_app: *mut ffi::NativeActivityGlue = (*activity).instance.cast(); + android_app_write_cmd(android_app, ffi::AppCmd::LowMemory as i8); } unsafe extern "C" fn on_window_focus_changed(activity: *mut ndk_sys::ANativeActivity, focused: libc::c_int) { log::debug!("WindowFocusChanged: {:p} -- {}\n", activity, focused); - let android_app: *mut ffi::android_app = (*activity).instance.cast(); + let android_app: *mut ffi::NativeActivityGlue = (*activity).instance.cast(); android_app_write_cmd(android_app, - if focused != 0 { ffi::APP_CMD_GAINED_FOCUS as i8 } else { ffi::APP_CMD_LOST_FOCUS as i8}); + if focused != 0 { ffi::AppCmd::GainedFocus as i8 } else { ffi::AppCmd::LostFocus as i8}); } unsafe extern "C" fn on_native_window_created(activity: *mut ndk_sys::ANativeActivity, window: *mut ndk_sys::ANativeWindow) { log::debug!("NativeWindowCreated: {:p} -- {:p}\n", activity, window); - let android_app: *mut ffi::android_app = (*activity).instance.cast(); + let android_app: *mut ffi::NativeActivityGlue = (*activity).instance.cast(); android_app_set_window(android_app, window); } unsafe extern "C" fn on_native_window_destroyed(activity: *mut ndk_sys::ANativeActivity, window: *mut ndk_sys::ANativeWindow) { log::debug!("NativeWindowDestroyed: {:p} -- {:p}\n", activity, window); - let android_app: *mut ffi::android_app = (*activity).instance.cast(); + let android_app: *mut ffi::NativeActivityGlue = (*activity).instance.cast(); android_app_set_window(android_app, ptr::null_mut()); } unsafe extern "C" fn on_input_queue_created(activity: *mut ndk_sys::ANativeActivity, queue: *mut ndk_sys::AInputQueue) { log::debug!("InputQueueCreated: {:p} -- {:p}\n", activity, queue); - let android_app: *mut ffi::android_app = (*activity).instance.cast(); + let android_app: *mut ffi::NativeActivityGlue = (*activity).instance.cast(); android_app_set_input(android_app, queue); } unsafe extern "C" fn on_input_queue_destroyed(activity: *mut ndk_sys::ANativeActivity, queue: *mut ndk_sys::AInputQueue) { log::debug!("InputQueueDestroyed: {:p} -- {:p}\n", activity, queue); - let android_app: *mut ffi::android_app = (*activity).instance.cast(); + let android_app: *mut ffi::NativeActivityGlue = (*activity).instance.cast(); android_app_set_input(android_app, ptr::null_mut()); } @@ -1039,7 +1061,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. -pub unsafe fn _rust_glue_entry(app: *mut ffi::android_app) { +pub unsafe fn _rust_glue_entry(app: *mut ffi::NativeActivityGlue) { // Maybe make this stdout/stderr redirection an optional / opt-in feature?... let mut logpipe: [RawFd; 2] = Default::default(); libc::pipe(logpipe.as_mut_ptr());