From 37730905d1c2e93a2d482de139e6b3635d692f16 Mon Sep 17 00:00:00 2001 From: John Nunley Date: Sun, 10 Nov 2024 20:04:40 -0800 Subject: [PATCH] feat: Add waker() method to AndroidAppWaker This commit adds an "into_waker()" method to AndroidAppWaker. It converts it into an `std::task::Waker`, which is the type of waker used by asynchronous tasks for scheduling. The goal is to allow AndroidAppWaker to be easily used to set up an asynchronous context. The implementation is a straightforward wrapper for `ALooper_acquire/release/wake()`. Signed-off-by: John Nunley Co-authored-by: Robert Bragg --- android-activity/src/waker.rs | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/android-activity/src/waker.rs b/android-activity/src/waker.rs index 9997f03..0c486e9 100644 --- a/android-activity/src/waker.rs +++ b/android-activity/src/waker.rs @@ -1,4 +1,5 @@ use std::ptr::NonNull; +use std::task::{RawWaker, RawWakerVTable, Waker}; #[cfg(doc)] use crate::AndroidApp; @@ -54,4 +55,37 @@ impl AndroidAppWaker { ndk_sys::ALooper_wake(self.looper.as_ptr()); } } + + /// Creates a [`Waker`] that wakes up the [`AndroidApp`]. + /// + /// This is useful for using this crate in `async` environments. + /// + /// [`Waker`]: std::task::Waker + pub fn into_waker(self) -> Waker { + const VTABLE: RawWakerVTable = RawWakerVTable::new(clone, wake, wake, drop); + + unsafe fn clone(data: *const ()) -> RawWaker { + ndk_sys::ALooper_acquire(data as *const _ as *mut _); + RawWaker::new(data, &VTABLE) + } + + unsafe fn wake(data: *const ()) { + ndk_sys::ALooper_wake(data as *const _ as *mut _) + } + + unsafe fn drop(data: *const ()) { + ndk_sys::ALooper_release(data as *const _ as *mut _); + } + + // Take the existing reference to the looper and use it for the Waker + let looper_ptr = self.looper.as_ptr() as *const (); + std::mem::forget(self); + unsafe { Waker::from_raw(RawWaker::new(looper_ptr, &VTABLE)) } + } +} + +impl From for Waker { + fn from(waker: AndroidAppWaker) -> Self { + waker.into_waker() + } }