mirror of
https://github.com/darkrenaissance/darkfi.git
synced 2026-01-08 22:28:12 -05:00
app: do proper JVM thread mgmt. previously we call AttachThread() everywhere which is wrong, it should be called once per thread and then DetachThread() to cleanup. use thread local storage + Drop to make a thread guard for this.
This commit is contained in:
@@ -22,7 +22,7 @@ DEBUG_FEATURES = --features=enable-filelog,enable-plugins
|
||||
|
||||
#DEV_FEATURES = --features=enable-filelog,enable-netdebug,emulate-android
|
||||
#DEV_FEATURES = --features=enable-filelog,enable-netdebug,enable-plugins
|
||||
DEV_FEATURES = --features=schema-test
|
||||
DEV_FEATURES = --no-default-features --features=schema-app
|
||||
|
||||
default: build-release
|
||||
./darkfi-app
|
||||
|
||||
@@ -22,13 +22,15 @@ use std::{collections::HashMap, path::PathBuf, sync::LazyLock};
|
||||
|
||||
pub mod insets;
|
||||
pub mod textinput;
|
||||
mod util;
|
||||
pub(self) mod util;
|
||||
pub mod vid;
|
||||
|
||||
use util::get_jni_env;
|
||||
|
||||
macro_rules! call_mainactivity_int_method {
|
||||
($method:expr, $sig:expr $(, $args:expr)*) => {{
|
||||
unsafe {
|
||||
let env = android::attach_jni_env();
|
||||
let env = get_jni_env();
|
||||
ndk_utils::call_int_method!(env, android::ACTIVITY, $method, $sig $(, $args)*)
|
||||
}
|
||||
}};
|
||||
@@ -36,7 +38,7 @@ macro_rules! call_mainactivity_int_method {
|
||||
macro_rules! call_mainactivity_str_method {
|
||||
($method:expr) => {{
|
||||
unsafe {
|
||||
let env = android::attach_jni_env();
|
||||
let env = get_jni_env();
|
||||
let text = ndk_utils::call_object_method!(
|
||||
env,
|
||||
android::ACTIVITY,
|
||||
@@ -50,7 +52,7 @@ macro_rules! call_mainactivity_str_method {
|
||||
macro_rules! call_mainactivity_float_method {
|
||||
($method:expr) => {{
|
||||
unsafe {
|
||||
let env = android::attach_jni_env();
|
||||
let env = get_jni_env();
|
||||
ndk_utils::call_method!(CallFloatMethod, env, android::ACTIVITY, $method, "()F")
|
||||
}
|
||||
}};
|
||||
@@ -58,7 +60,7 @@ macro_rules! call_mainactivity_float_method {
|
||||
macro_rules! call_mainactivity_bool_method {
|
||||
($method:expr) => {{
|
||||
unsafe {
|
||||
let env = android::attach_jni_env();
|
||||
let env = get_jni_env();
|
||||
ndk_utils::call_method!(CallBooleanMethod, env, android::ACTIVITY, $method, "()Z") !=
|
||||
0u8
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ use std::{
|
||||
sync::{Arc, OnceLock},
|
||||
};
|
||||
|
||||
use super::{AndroidTextInputState, SharedStatePtr};
|
||||
use super::{super::util::get_jni_env, AndroidTextInputState, SharedStatePtr};
|
||||
|
||||
macro_rules! t { ($($arg:tt)*) => { trace!(target: "android::textinput::gametextinput", $($arg)*); } }
|
||||
macro_rules! w { ($($arg:tt)*) => { warn!(target: "android::textinput::gametextinput", $($arg)*); } }
|
||||
@@ -57,7 +57,7 @@ pub struct GameTextInput {
|
||||
impl GameTextInput {
|
||||
pub fn new() -> Self {
|
||||
unsafe {
|
||||
let env = android::attach_jni_env();
|
||||
let env = get_jni_env();
|
||||
|
||||
let find_class = (**env).FindClass.unwrap();
|
||||
|
||||
@@ -186,7 +186,7 @@ impl GameTextInput {
|
||||
return
|
||||
};
|
||||
unsafe {
|
||||
let env = android::attach_jni_env();
|
||||
let env = get_jni_env();
|
||||
let jstate = self.state_to_java(state);
|
||||
call_void_method!(env, input_connection, "setState", "(Ltextinput/State;)V", jstate);
|
||||
|
||||
@@ -201,7 +201,7 @@ impl GameTextInput {
|
||||
return Err(())
|
||||
};
|
||||
let is_success = unsafe {
|
||||
let env = android::attach_jni_env();
|
||||
let env = get_jni_env();
|
||||
call_bool_method!(env, input_connection, "setSelection", "(II)Z", start, end)
|
||||
};
|
||||
if is_success == 0u8 {
|
||||
@@ -212,7 +212,7 @@ impl GameTextInput {
|
||||
|
||||
pub fn set_input_connection(&self, input_connection: ndk_sys::jobject) {
|
||||
unsafe {
|
||||
let env = android::attach_jni_env();
|
||||
let env = get_jni_env();
|
||||
let mut ic = self.input_connection.write();
|
||||
if let Some(old_ref) = *ic {
|
||||
let delete_global_ref = (**env).DeleteGlobalRef.unwrap();
|
||||
@@ -242,7 +242,7 @@ impl GameTextInput {
|
||||
return
|
||||
};
|
||||
unsafe {
|
||||
let env = android::attach_jni_env();
|
||||
let env = get_jni_env();
|
||||
let call_void_method = (**env).CallVoidMethod.unwrap();
|
||||
call_void_method(
|
||||
env,
|
||||
@@ -260,7 +260,7 @@ impl GameTextInput {
|
||||
return
|
||||
};
|
||||
unsafe {
|
||||
let env = android::attach_jni_env();
|
||||
let env = get_jni_env();
|
||||
let call_void_method = (**env).CallVoidMethod.unwrap();
|
||||
call_void_method(
|
||||
env,
|
||||
@@ -278,7 +278,7 @@ impl GameTextInput {
|
||||
return
|
||||
};
|
||||
unsafe {
|
||||
let env = android::attach_jni_env();
|
||||
let env = get_jni_env();
|
||||
let call_void_method = (**env).CallVoidMethod.unwrap();
|
||||
call_void_method(env, input_connection, self.restart_input_method);
|
||||
}
|
||||
@@ -286,7 +286,7 @@ impl GameTextInput {
|
||||
|
||||
fn state_to_java(&self, state: &AndroidTextInputState) -> ndk_sys::jobject {
|
||||
unsafe {
|
||||
let env = android::attach_jni_env();
|
||||
let env = get_jni_env();
|
||||
let new_string_utf = (**env).NewStringUTF.unwrap();
|
||||
let text_str = CString::new(state.text.as_str()).unwrap();
|
||||
let jtext = new_string_utf(env, text_str.as_ptr());
|
||||
@@ -317,7 +317,7 @@ impl GameTextInput {
|
||||
|
||||
fn state_from_java(&self, event_state: ndk_sys::jobject) -> AndroidTextInputState {
|
||||
unsafe {
|
||||
let env = android::attach_jni_env();
|
||||
let env = get_jni_env();
|
||||
let get_object_field = (**env).GetObjectField.unwrap();
|
||||
let jtext =
|
||||
get_object_field(env, event_state, self.state_class_info.text) as ndk_sys::jstring;
|
||||
@@ -355,7 +355,7 @@ impl GameTextInput {
|
||||
impl Drop for GameTextInput {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
let env = android::attach_jni_env();
|
||||
let env = get_jni_env();
|
||||
let delete_global_ref = (**env).DeleteGlobalRef.unwrap();
|
||||
if self.input_connection_class != std::ptr::null_mut() {
|
||||
delete_global_ref(env, self.input_connection_class);
|
||||
|
||||
@@ -16,7 +16,57 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
use miniquad::native::android::ndk_sys;
|
||||
use miniquad::native::android::{self, ndk_sys};
|
||||
use std::cell::RefCell;
|
||||
|
||||
thread_local! {
|
||||
static JNI_ENV: RefCell<JniEnvHolder> = RefCell::new(JniEnvHolder {
|
||||
env: std::ptr::null_mut(),
|
||||
vm: std::ptr::null_mut(),
|
||||
});
|
||||
}
|
||||
|
||||
struct JniEnvHolder {
|
||||
env: *mut ndk_sys::JNIEnv,
|
||||
vm: *mut ndk_sys::JavaVM,
|
||||
}
|
||||
|
||||
impl Drop for JniEnvHolder {
|
||||
fn drop(&mut self) {
|
||||
assert!(!self.env.is_null());
|
||||
unsafe {
|
||||
let detach_current_thread = (**self.vm).DetachCurrentThread.unwrap();
|
||||
let _ = detach_current_thread(self.vm);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the JNIEnv for the current thread, attaching if necessary.
|
||||
/// The returned pointer is cached per-thread and automatically detached
|
||||
/// when the thread exits.
|
||||
pub unsafe fn get_jni_env() -> *mut ndk_sys::JNIEnv {
|
||||
JNI_ENV.with(|holder| {
|
||||
let mut holder = holder.borrow_mut();
|
||||
if !holder.env.is_null() {
|
||||
return holder.env;
|
||||
}
|
||||
|
||||
// Call miniquad's attach_jni_env to get the env
|
||||
let env = android::attach_jni_env();
|
||||
assert!(!env.is_null());
|
||||
|
||||
// Retrieve the JavaVM from the JNIEnv
|
||||
let get_java_vm = (**env).GetJavaVM.unwrap();
|
||||
let mut vm: *mut ndk_sys::JavaVM = std::ptr::null_mut();
|
||||
let res = get_java_vm(env, &mut vm);
|
||||
assert!(res == 0);
|
||||
assert!(!vm.is_null());
|
||||
|
||||
holder.env = env;
|
||||
holder.vm = vm;
|
||||
env
|
||||
})
|
||||
}
|
||||
|
||||
/// Check for pending Java exceptions and log them
|
||||
///
|
||||
|
||||
@@ -25,6 +25,8 @@ use std::{
|
||||
sync::{mpsc, LazyLock},
|
||||
};
|
||||
|
||||
use super::util::get_jni_env;
|
||||
|
||||
pub struct DecodedFrame {
|
||||
pub width: usize,
|
||||
pub height: usize,
|
||||
@@ -113,7 +115,7 @@ pub struct VideoDecoderHandle {
|
||||
impl Drop for VideoDecoderHandle {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
let env = android::attach_jni_env();
|
||||
let env = get_jni_env();
|
||||
let delete_local_ref = (**env).DeleteLocalRef.unwrap();
|
||||
delete_local_ref(env, self.obj);
|
||||
}
|
||||
@@ -122,7 +124,7 @@ impl Drop for VideoDecoderHandle {
|
||||
|
||||
pub fn videodecoder_init(path: &str) -> Option<VideoDecoderHandle> {
|
||||
unsafe {
|
||||
let env = android::attach_jni_env();
|
||||
let env = get_jni_env();
|
||||
|
||||
let decoder_obj = ndk_utils::call_object_method!(
|
||||
env,
|
||||
@@ -156,14 +158,14 @@ pub fn videodecoder_init(path: &str) -> Option<VideoDecoderHandle> {
|
||||
|
||||
pub fn videodecoder_set_id(decoder_obj: ndk_sys::jobject, id: usize) {
|
||||
unsafe {
|
||||
let env = android::attach_jni_env();
|
||||
let env = get_jni_env();
|
||||
ndk_utils::call_void_method!(env, decoder_obj, "setDecoderId", "(I)V", id as i32);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn videodecoder_decode_all(decoder_obj: ndk_sys::jobject) -> i32 {
|
||||
unsafe {
|
||||
let env = android::attach_jni_env();
|
||||
let env = get_jni_env();
|
||||
ndk_utils::call_int_method!(env, decoder_obj, "decodeAll", "()I")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
use sled_overlay::sled;
|
||||
|
||||
use super::chat::populate_tree;
|
||||
use crate::{
|
||||
app::{
|
||||
node::{
|
||||
@@ -33,20 +34,28 @@ use crate::{
|
||||
ui::{BaseEdit, BaseEditType, ChatView, Layer, Text, VectorArt, VectorShape, Video},
|
||||
util::i18n::I18nBabelFish,
|
||||
};
|
||||
use super::chat::populate_tree;
|
||||
|
||||
const LIGHTMODE: bool = false;
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
mod ui_consts {
|
||||
pub const CHATDB_PATH: &str = "/data/data/darkfi.app/chatdb/";
|
||||
use crate::android::get_appdata_path;
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub fn get_chatdb_path() -> PathBuf {
|
||||
get_appdata_path().join("chatdb")
|
||||
}
|
||||
//pub const KING_PATH: &str = "king.png";
|
||||
pub const VID_PATH: &str = "forest_720x1280.mp4";
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "android"))]
|
||||
mod ui_consts {
|
||||
pub const CHATDB_PATH: &str = "chatdb";
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub fn get_chatdb_path() -> PathBuf {
|
||||
"chatdb"
|
||||
}
|
||||
//pub const KING_PATH: &str = "assets/king.png";
|
||||
pub const VID_PATH: &str = "assets/forest_1920x1080.ivf";
|
||||
}
|
||||
@@ -342,7 +351,7 @@ pub async fn make(app: &App, window: SceneNodePtr, i18n_fish: &I18nBabelFish) {
|
||||
prop.set_f32(atom, Role::App, 3, 1.).unwrap();
|
||||
}
|
||||
|
||||
let db = sled::open(CHATDB_PATH).expect("cannot open sleddb");
|
||||
let db = sled::open(get_chatdb_path()).expect("cannot open sleddb");
|
||||
let chat_tree = db.open_tree(b"chat").unwrap();
|
||||
if chat_tree.is_empty() {
|
||||
populate_tree(&chat_tree);
|
||||
|
||||
Reference in New Issue
Block a user