From f8b05ade39561169d22496f5acbdf766d4686312 Mon Sep 17 00:00:00 2001 From: Marijn Suijten Date: Tue, 15 Feb 2022 15:15:24 +0100 Subject: [PATCH] android: Migrate from `ndk-glue` to `ndk-context` `ndk-glue` suffers one fatal flaw: it's "only" supposed to be used by the crate providing `fn main()` and only supposed to end up in the dependency graph once as it has `static` globals which get duplicated across versions. In the current case with `winit 0.26` still on `ndk-glue 0.5` but `cpal` on `ndk-glue 0.6` it'll always panic in `fn native_activity()` as the `static` globals on this version is not initialized. Introducing `ndk-context`: a crate that holds these `static`s, with the intention/premise to not see a breaking release /ever/ and make this a problem of the past. The crate is currently initialized with the VM and Android Context on `ndk-glue` 0.5.1 and 0.6.1 (0.4.1 pending) making it compatible with whatever is current, and the possibility for backporting to older `ndk-glue` versions too. See also: https://github.com/rust-windowing/android-ndk-rs/issues/211 https://github.com/rust-windowing/android-ndk-rs/pull/223 --- Cargo.toml | 5 ++++- src/host/oboe/android_media.rs | 14 ++++++-------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 5785653ac..42b6c41e9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,6 +20,9 @@ hound = "3.4" ringbuf = "0.2" clap = { version = "3", default-features = false, features = ["std"] } +[target.'cfg(target_os = "android")'.dev-dependencies] +ndk-glue = "0.6" + [target.'cfg(target_os = "windows")'.dependencies] winapi = { version = "0.3", features = ["audiosessiontypes", "audioclient", "coml2api", "combaseapi", "debug", "devpkey", "handleapi", "ksmedia", "mmdeviceapi", "objbase", "profileapi", "std", "synchapi", "winbase", "winuser"] } asio-sys = { version = "0.2", path = "asio-sys", optional = true } @@ -55,7 +58,7 @@ web-sys = { version = "0.3.35", features = [ "AudioContext", "AudioContextOption [target.'cfg(target_os = "android")'.dependencies] oboe = { version = "0.4", features = [ "java-interface" ] } ndk = "0.6" -ndk-glue = "0.6" +ndk-context = "0.1" jni = "0.19" [[example]] diff --git a/src/host/oboe/android_media.rs b/src/host/oboe/android_media.rs index 65385c1a9..099c652f6 100644 --- a/src/host/oboe/android_media.rs +++ b/src/host/oboe/android_media.rs @@ -1,10 +1,9 @@ use std::sync::Arc; extern crate jni; -extern crate ndk_glue; use self::jni::Executor; -use self::jni::{errors::Result as JResult, objects::JObject, JNIEnv, JavaVM}; +use self::jni::{errors::Result as JResult, JNIEnv, JavaVM}; // constants from android.media.AudioFormat pub const ENCODING_PCM_16BIT: i32 = 2; @@ -14,12 +13,11 @@ pub const CHANNEL_OUT_STEREO: i32 = 12; fn with_attached(closure: F) -> JResult where - F: FnOnce(&JNIEnv, JObject) -> JResult, + F: FnOnce(&JNIEnv) -> JResult, { - let activity = ndk_glue::native_activity(); - let vm = Arc::new(unsafe { JavaVM::from_raw(activity.vm())? }); - let activity = activity.activity(); - Executor::new(vm).with_attached(|env| closure(env, activity.into())) + let android_context = ndk_context::android_context(); + let vm = Arc::new(unsafe { JavaVM::from_raw(android_context.vm().cast())? }); + Executor::new(vm).with_attached(|env| closure(env)) } fn get_min_buffer_size( @@ -31,7 +29,7 @@ fn get_min_buffer_size( // Unwrapping everything because these operations are not expected to fail // or throw exceptions. Android returns negative values for invalid parameters, // which is what we expect. - with_attached(|env, _activity| { + with_attached(|env| { let class = env.find_class(class).unwrap(); env.call_static_method( class,