Skip to content

Commit

Permalink
chore(deps): Upgrade to ndk 0.9 and fix thread-safety interactions
Browse files Browse the repository at this point in the history
Most changes were copied over from my `wry` PR at
tauri-apps/wry#1296.  Most notably a
`&ThreadLooper` is now passed to `wry::android_setup()` because we
have one, and it gives important safety guarantees when it comes to
registering callbacks on this looper, without (unnecessarily!) requiring
`Send`.  A thread-local requirement already exists for the `JNIEnv` that
is passed around anyway.

Also note that certain workarounds and illogical inverted passes
around `key_code()` handling are no longer needed, as the `ndk` crate
now passes an `enum` with the raw `i32` around so that the `.into()`
conversion for `i32` (the correct type) now becomes lossless.
  • Loading branch information
MarijnS95 committed Jul 18, 2024
1 parent 80e1008 commit e70d8da
Show file tree
Hide file tree
Showing 6 changed files with 35 additions and 28 deletions.
7 changes: 7 additions & 0 deletions .changes/ndk-0.9.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"tao": major
---

**Breaking change**: Upgrade `ndk` crate to `0.9` and `ndk-sys` crate to `0.6`. Types from the `ndk` crate are used in public API surface.
**Breaking change**: Change `NativeKeyCode::Android(u32)` type to use `i32`, which is the native type used by all Android API.
**Breaking change**: The `setup` function passed to `android_binding!()` must now take a `&ThreadLooper` instead of `&ForeignLooper`, matching the `wry` change in https://github.com/tauri-apps/wry/pull/1296.
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,8 @@ once_cell = "1"

[target."cfg(target_os = \"android\")".dependencies]
jni = "0.21"
ndk = "0.7"
ndk-sys = "0.4"
ndk = "0.9"
ndk-sys = "0.6"
ndk-context = "0.1"
tao-macros = { version = "0.1.0", path = "./tao-macros" }

Expand Down
1 change: 1 addition & 0 deletions examples/transparent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Copyright 2021-2023 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0

#[cfg(windows)]
use std::{num::NonZeroU32, rc::Rc};

use tao::{
Expand Down
2 changes: 1 addition & 1 deletion src/keyboard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ pub enum NativeKeyCode {

/// This is the android "key code" of the event as returned by
/// `KeyEvent.getKeyCode()`
Android(u32),
Android(i32),
}

/// Represents the code of a physical key.
Expand Down
19 changes: 6 additions & 13 deletions src/platform_impl/android/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,8 @@ use ndk::{
event::{InputEvent, KeyAction, MotionAction},
looper::{ForeignLooper, Poll, ThreadLooper},
};
use ndk_sys::AKeyEvent_getKeyCode;
use std::{
collections::VecDeque,
convert::TryInto,
sync::RwLock,
time::{Duration, Instant},
};
Expand Down Expand Up @@ -190,7 +188,7 @@ impl<T: 'static> EventLoop<T> {
},
Some(EventSource::InputQueue) => {
if let Some(input_queue) = ndk_glue::input_queue().as_ref() {
while let Ok(Some(event)) = input_queue.get_event() {
while let Ok(Some(event)) = input_queue.event() {
if let Some(event) = input_queue.pre_dispatch(event) {
let mut handled = true;
let window_id = window::WindowId(WindowId);
Expand Down Expand Up @@ -253,16 +251,9 @@ impl<T: 'static> EventLoop<T> {
_ => event::ElementState::Released,
};

// We use the unsafe function directly because
// we want to forward the keycode value even if it doesn't have a variant
// defined in the ndk crate.
let keycode_u32 = unsafe { AKeyEvent_getKeyCode(key.ptr().as_ptr()) as u32 };
let keycode = keycode_u32
.try_into()
.unwrap_or(ndk::event::Keycode::Unknown);
let physical_key =
KeyCode::Unidentified(NativeKeyCode::Android(keycode.into()));
let native = NativeKeyCode::Android(keycode_u32);
let keycode = key.key_code();
let native = NativeKeyCode::Android(keycode.into());
let physical_key = KeyCode::Unidentified(native);
let logical_key = keycode_to_logical(keycode, native);
// TODO: maybe use getUnicodeChar to get the logical key

Expand All @@ -284,6 +275,7 @@ impl<T: 'static> EventLoop<T> {
};
call_event_handler!(event_handler, self.window_target(), control_flow, event);
}
_ => {}
};
input_queue.finish_event(event, handled);
}
Expand Down Expand Up @@ -1202,6 +1194,7 @@ fn keycode_to_logical(keycode: ndk::event::Keycode, native: NativeKeyCode) -> Ke
ThumbsUp => Key::Unidentified(native),
ThumbsDown => Key::Unidentified(native),
ProfileSwitch => Key::Unidentified(native),
_ => Key::Unidentified(native),
}
}

Expand Down
30 changes: 18 additions & 12 deletions src/platform_impl/android/ndk_glue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,17 +120,19 @@ pub fn content_rect() -> Rect {
CONTENT_RECT.read().unwrap().clone()
}

static PIPE: Lazy<[RawFd; 2]> = Lazy::new(|| {
pub static PIPE: Lazy<[OwnedFd; 2]> = Lazy::new(|| {
let mut pipe: [RawFd; 2] = Default::default();
unsafe { libc::pipe(pipe.as_mut_ptr()) };
pipe
pipe.map(|fd| unsafe { OwnedFd::from_raw_fd(fd) })
});

pub fn poll_events() -> Option<Event> {
unsafe {
let size = std::mem::size_of::<Event>();
let mut event = Event::Start;
if libc::read(PIPE[0], &mut event as *mut _ as *mut _, size) == size as libc::ssize_t {
if libc::read(PIPE[0].as_raw_fd(), &mut event as *mut _ as *mut _, size)
== size as libc::ssize_t
{
Some(event)
} else {
None
Expand All @@ -141,7 +143,7 @@ pub fn poll_events() -> Option<Event> {
unsafe fn wake(event: Event) {
log::trace!("{:?}", event);
let size = std::mem::size_of::<Event>();
let res = libc::write(PIPE[1], &event as *const _ as *const _, size);
let res = libc::write(PIPE[1].as_raw_fd(), &event as *const _ as *const _, size);
assert_eq!(res, size as libc::ssize_t);
}

Expand Down Expand Up @@ -179,7 +181,7 @@ pub unsafe fn create(
mut env: JNIEnv,
_jclass: JClass,
jobject: JObject,
setup: unsafe fn(&str, JNIEnv, &ForeignLooper, GlobalRef),
setup: unsafe fn(&str, JNIEnv, &ThreadLooper, GlobalRef),
main: fn(),
) {
//-> jobjectArray {
Expand All @@ -204,16 +206,20 @@ pub unsafe fn create(
activity.as_obj().as_raw() as *mut _,
);

let looper = ThreadLooper::for_thread().unwrap().into_foreign();
let looper = ThreadLooper::for_thread().unwrap();
setup(PACKAGE.get().unwrap(), env, &looper, 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);
let logpipe = {
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);

logpipe.map(|fd| unsafe { OwnedFd::from_raw_fd(fd) })
};
thread::spawn(move || {
let tag = CStr::from_bytes_with_nul(b"RustStdoutStderr\0").unwrap();
let file = File::from_raw_fd(logpipe[0]);
let file = File::from_raw_fd(logpipe[0].as_raw_fd());
let mut reader = BufReader::new(file);
let mut buffer = String::new();
loop {
Expand All @@ -236,7 +242,7 @@ pub unsafe fn create(
let foreign = looper.into_foreign();
foreign
.add_fd(
PIPE[0],
PIPE[0].as_fd(),
NDK_GLUE_LOOPER_EVENT_PIPE_IDENT,
FdEvent::INPUT,
std::ptr::null_mut(),
Expand Down

0 comments on commit e70d8da

Please sign in to comment.