Fix a deadlock that occurs when an activity is destroyed without process
termination, such as when an activity is destroyed and recreated due to
a configuration change.
The deadlock occurs because `notify_destroyed` blocks until `destroyed`
is set to `true`. This only occurs when `WaitableNativeActivityState` is
dropped, but the `WaitableNativeActivityState` instance is the very
thing being used to await for destruction, resulting in a deadlock.
Instead of waiting for the `WaitableNativeActivityState` to be dropped
we now wait until the native `android_main` thread has stopped.
So we can tell the difference between the thread not running because it
hasn't started or because it has finished (in case `android_main`
returns immediately) this replaces the `running` boolean with a
tri-state enum.
Co-authored-by: Robert Bragg <robert@sixbynine.org>
I was trying to quickly get to the documentation of this crate and had
the GitHub page open... but there was no link on the front-page: let's
fix that.
In a raw string [no escaping is processed] nor are these quotes treated
specially unless it was postfixed with `#`; the backslashes show up in
the compiler error displayed to the user instead.
For consistency the string this was likely copied from is now also
turned into a raw string literal, with backslashes equivalently removed.
[no escaping is processed]: https://doc.rust-lang.org/reference/tokens.html#raw-string-literals
Ideally information - especially when spamming per `Looper` poll - used
for debugging `android-activity` doesn't show to the user unless they
use the `Trace` level (eventually for this specific crate/module). This
is already adhered to in most places of the code but there were a few
high-volume cases still remaining.
This patch is addressing two notable issues:
1. MotionEvents with the GameActivity backend were extremely large and
forced us to copy lots of redundant padding from the internal
circular buffer of events when calling an apps `input_events()`
callback.
2. MotionEvents + KeyEvents with the NativeActivity backend (re-exported
from the ndk crate) simply wrapped a raw pointer but had no lifetime
that would stop applications from keeping them too long and then
potentially dereferencing an invalid pointer.
The common change is that `InputEvent` is now defined with a lifetime
parameter which makes it possible for Motion and Key events to hold
references that let them avoid copying large amounts of state.
The `Source` and `Class` enums were also moved out of the GameActivity
backend so they could be shared since there was some inconsistency
between the backends with these types.
Overall this doesn't, practically, affect the public API
GameActivity
============
On the GameActivity side the events will now point into the internal
circular buffer that is iterated during `input_events()` and so
the `MotionEvent` type is now a thin wrapper over a reference.
This removes the `Iterator` implementations we had internally for
iterating key/motion events because we effectively need a lending
iterator now. It's also noted that while our MSRV is 1.60 we can't use
GATs to implement the interation in terms of a LendingIterator trait.
(This is fine in practice because this iteration is a private
implementation detail and so we can have lending iteration without any
traits for now)
NativeActivity
==============
On the NativeActivity side we now have newtype wrappers around
MotionEvent and KeyEvent from the ndk crate. These newtypes add a
lifetime and implement all the same passthrough methods as the
corresponding GameActivity types.
This added more boilerplate to the NativeActivity backend but it
also improves consistency between the backends.
Fixes: #40Fixes: #41
This removes the indirection of the `StateSaver` and `StateLoader`
type aliases (which resulted in no documentation for these interfaces)
and we now simply re-export the types from the backend implementation.
This simplifies the tracking of saved state by simply using a Vec and
only copying into a `malloc()` allocation when passing the saved state
to `ANativeActivity`.
This also ensures saved state persists (in Rust) between a
`MainEvent::SaveState` event and a `Resume` event - otherwise the saved
state would only be restored in the situation where `onCreate` is called
again for a new process.
This adds a common `try_with_waitable_activity_ref` utility that handles
upgrading the Weak reference associated with `ANativeActivity` whenever
we get an activity callback.
Previously we weren't converting the Weak reference back to a pointer
before returning from the callback which would result in us dropping the
Weak reference after the first callback.
This is a fairly thorough re-working of all the code that was initially
naively ported from android_native_app_glue.c to be more idiomatic Rust
code (though by it's nature it still involves a lot of unsafe code)
Most of the glue code now lives in src/native_activity/glue.rs as part
of a NativeActivityGlue API
The design as far as the threading model, IPC and synchronization goes
is unchanged.
At this point the C code has been fully ported to Rust but it's not yet
well integrated with the pre-existing Rust code and the port is not yet
particularly idiomatic Rust code.
The callback given to `AndroidApp::input_events()` is now expected to return
`InputStatus::Handled` or `InputStatus::Unhandled`.
When running with NativeActivity then if we know an input event hasn't been
handled we can notify the InputQueue which may result in fallback
handling.
Although the status is currently ignored with the GameActivity backend.
Since this is a breaking change that also affects the current Winit
backend this updates the winit based examples to stick with the 0.3
release of android-activity for now.
Fixes: #31
When building with native-activity then we no longer directly use
the `ndk::InputEvent` type and instead have our own extensible,
`#[non_exhaustive]` enum that ensures we will be able to add an
event for Ime state changes without necessarily needing a semver
bump.
Addresses: #18
This adds `AndroidApp::show/hide_soft_input` APIs for showing or
hiding the user's on-screen keyboard. (supported for NativeActivity
and GameActivity)
Addresses: #18