Skip to content

Commit

Permalink
Add android-glue.
Browse files Browse the repository at this point in the history
  • Loading branch information
dvc94ch committed Feb 9, 2020
1 parent 5c6017b commit c0ec254
Show file tree
Hide file tree
Showing 3 changed files with 240 additions and 1 deletion.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[workspace]

members = [
"android-glue",
"android-ndk-sys",
"android-ndk",
]
14 changes: 14 additions & 0 deletions android-glue/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[package]
name = "android-glue"
version = "0.1.0"
authors = ["David Craven <david@craven.ch>"]
edition = "2018"

[dependencies]
android_logger = "0.8.6"
android-ndk-sys = { path = "../android-ndk-sys", default-features = false }
android-ndk = { path = "../android-ndk", default-features = false }
crossbeam = "0.7.3"
lazy_static = "1.4.0"
libc = "0.2.66"
log = "0.4.8"
225 changes: 225 additions & 0 deletions android-glue/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
use android_logger::Config;
use android_ndk::input_queue::InputQueue;
use android_ndk::native_activity::NativeActivity;
use android_ndk::native_window::NativeWindow;
use android_ndk_sys::{AInputQueue, ANativeActivity, ANativeWindow, ARect};
use crossbeam::queue::SegQueue;
use lazy_static::lazy_static;
use log::Level;
use std::fs::File;
use std::io::{BufRead, BufReader};
use std::os::raw;
use std::os::unix::prelude::*;
use std::ptr::NonNull;
use std::sync::Mutex;
use std::thread;

lazy_static! {
static ref NATIVE_WINDOW: Mutex<Option<NativeWindow>> = Default::default();
static ref INPUT_QUEUE: Mutex<Option<InputQueue>> = Default::default();
static ref EVENT_QUEUE: SegQueue<Event> = Default::default();
}

static mut NATIVE_ACTIVITY: Option<NativeActivity> = None;

pub fn native_activity() -> &'static NativeActivity {
unsafe { NATIVE_ACTIVITY.as_ref().unwrap() }
}

pub fn native_window() -> &'static Mutex<Option<NativeWindow>> {
&NATIVE_WINDOW
}

pub fn input_queue() -> &'static Mutex<Option<InputQueue>> {
&INPUT_QUEUE
}

pub fn poll_events() -> Option<Event> {
EVENT_QUEUE.pop().ok()
}

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum Event {
Start,
Resume,
//SaveInstanceState,
Pause,
Stop,
Destroy,
ConfigChanged,
LowMemory,
WindowFocusChanged,
WindowCreated,
WindowResized,
WindowRedrawNeeded,
WindowDestroyed,
InputQueueCreated,
InputQueueDestroyed,
ContentRectChanged,
}

pub unsafe fn init(
activity: *mut ANativeActivity,
_saved_state: *mut u8,
_saved_state_size: usize,
main: fn(),
) {
let mut activity = NonNull::new(activity).unwrap();
let mut callbacks = activity.as_mut().callbacks.as_mut().unwrap();
callbacks.onStart = Some(on_start);
callbacks.onResume = Some(on_resume);
callbacks.onSaveInstanceState = Some(on_save_instance_state);
callbacks.onPause = Some(on_pause);
callbacks.onStop = Some(on_stop);
callbacks.onDestroy = Some(on_destroy);
callbacks.onWindowFocusChanged = Some(on_window_focus_changed);
callbacks.onNativeWindowCreated = Some(on_window_created);
callbacks.onNativeWindowResized = Some(on_window_resized);
callbacks.onNativeWindowRedrawNeeded = Some(on_window_redraw_needed);
callbacks.onNativeWindowDestroyed = Some(on_window_destroyed);
callbacks.onInputQueueCreated = Some(on_input_queue_created);
callbacks.onInputQueueDestroyed = Some(on_input_queue_destroyed);
callbacks.onContentRectChanged = Some(on_content_rect_changed);
callbacks.onConfigurationChanged = Some(on_configuration_changed);
callbacks.onLowMemory = Some(on_low_memory);
let activity = NativeActivity::from_ptr(activity);
NATIVE_ACTIVITY = Some(activity);

let mut logpipe: [RawFd; 2] = Default::default();
libc::pipe(logpipe.as_mut_ptr());
libc::dup2(logpipe[1], libc::STDOUT_FILENO);
libc::dup2(logpipe[1], libc::STDERR_FILENO);
thread::spawn(move || {
android_logger::init_once(
Config::default()
.with_min_level(Level::Trace)
.with_tag("RustStdoutStderr"),
);
let file = File::from_raw_fd(logpipe[0]);
let mut reader = BufReader::new(file);
let mut buffer = String::new();
loop {
buffer.clear();
if let Ok(len) = reader.read_line(&mut buffer) {
if len == 0 {
break;
} else {
log::info!("{}", buffer);
}
}
}
});

thread::spawn(main);
}

unsafe extern "C" fn on_start(_activity: *mut ANativeActivity) {
log::trace!("on_start");
EVENT_QUEUE.push(Event::Start);
}

unsafe extern "C" fn on_resume(_activity: *mut ANativeActivity) {
log::trace!("on_resume");
EVENT_QUEUE.push(Event::Resume);
}

unsafe extern "C" fn on_save_instance_state(
_activity: *mut ANativeActivity,
_out_size: *mut usize,
) -> *mut raw::c_void {
log::trace!("on_save_instance_state");
// TODO
//EVENT_QUEUE.push(Event::Resume);
std::ptr::null_mut()
}

unsafe extern "C" fn on_pause(_activity: *mut ANativeActivity) {
log::trace!("on_pause");
EVENT_QUEUE.push(Event::Pause);
}

unsafe extern "C" fn on_stop(_activity: *mut ANativeActivity) {
log::trace!("on_stop");
EVENT_QUEUE.push(Event::Stop);
}

unsafe extern "C" fn on_destroy(_activity: *mut ANativeActivity) {
log::trace!("on_destroy");
EVENT_QUEUE.push(Event::Destroy);
}

unsafe extern "C" fn on_configuration_changed(_activity: *mut ANativeActivity) {
log::trace!("on_configuration_changed");
EVENT_QUEUE.push(Event::ConfigChanged);
}

unsafe extern "C" fn on_low_memory(_activity: *mut ANativeActivity) {
log::trace!("on_low_memory");
EVENT_QUEUE.push(Event::LowMemory);
}

unsafe extern "C" fn on_window_focus_changed(
_activity: *mut ANativeActivity,
_has_focus: raw::c_int,
) {
log::trace!("on_window_focus_changed");
EVENT_QUEUE.push(Event::WindowFocusChanged);
}

unsafe extern "C" fn on_window_created(
_activity: *mut ANativeActivity,
window: *mut ANativeWindow,
) {
log::trace!("on_window_created");
*NATIVE_WINDOW.lock().unwrap() = Some(NativeWindow::from_ptr(NonNull::new(window).unwrap()));
EVENT_QUEUE.push(Event::WindowCreated);
}

unsafe extern "C" fn on_window_resized(
_activity: *mut ANativeActivity,
_window: *mut ANativeWindow,
) {
log::trace!("on_window_resized");
EVENT_QUEUE.push(Event::WindowResized);
}

unsafe extern "C" fn on_window_redraw_needed(
_activity: *mut ANativeActivity,
_window: *mut ANativeWindow,
) {
log::trace!("on_window_redraw_needed");
EVENT_QUEUE.push(Event::WindowRedrawNeeded);
}

unsafe extern "C" fn on_window_destroyed(
_activity: *mut ANativeActivity,
_window: *mut ANativeWindow,
) {
log::trace!("on_window_destroyed");
EVENT_QUEUE.push(Event::WindowDestroyed);
*NATIVE_WINDOW.lock().unwrap() = None;
}

unsafe extern "C" fn on_input_queue_created(
_activity: *mut ANativeActivity,
queue: *mut AInputQueue,
) {
log::trace!("on_input_queue_created");
*INPUT_QUEUE.lock().unwrap() = Some(InputQueue::from_ptr(NonNull::new(queue).unwrap()));
EVENT_QUEUE.push(Event::InputQueueCreated);
}

unsafe extern "C" fn on_input_queue_destroyed(
_activity: *mut ANativeActivity,
_queue: *mut AInputQueue,
) {
log::trace!("on_input_queue_destroyed");
EVENT_QUEUE.push(Event::InputQueueDestroyed);
*INPUT_QUEUE.lock().unwrap() = None;
}

unsafe extern "C" fn on_content_rect_changed(_activity: *mut ANativeActivity, _rect: *const ARect) {
log::trace!("on_content_rect_changed");
EVENT_QUEUE.push(Event::ContentRectChanged);
// TODO
}

0 comments on commit c0ec254

Please sign in to comment.