From f35b158aa552003b7bcbac8ac31c1e82237fc402 Mon Sep 17 00:00:00 2001 From: Arnold Loubriat Date: Wed, 16 Sep 2026 18:36:51 +0200 Subject: [PATCH] perf: Only return QueuedEvents when needed on Android --- adapters/android/src/adapter.rs | 8 ++---- adapters/android/src/inject.rs | 49 ++++++++++++++++----------------- 2 files changed, 26 insertions(+), 31 deletions(-) diff --git a/adapters/android/src/adapter.rs b/adapters/android/src/adapter.rs index 7dca54e3..be693f58 100644 --- a/adapters/android/src/adapter.rs +++ b/adapters/android/src/adapter.rs @@ -295,21 +295,19 @@ impl Adapter { &mut self, update_factory: impl FnOnce() -> TreeUpdate, ) -> Option { + let mut events = Vec::new(); match &mut self.state { - State::Inactive => None, + State::Inactive => return None, State::Placeholder(_) => { let tree = Tree::new(update_factory(), true); - let mut events = Vec::new(); enqueue_window_content_changed(&mut events); let state = tree.state(); if let Some(focus) = state.focus() { enqueue_focus_event_if_applicable(&mut events, &mut self.node_id_map, &focus); } self.state = State::Active(tree); - Some(QueuedEvents(events)) } State::Active(tree) => { - let mut events = Vec::new(); update_tree( &mut events, &mut self.node_id_map, @@ -317,9 +315,9 @@ impl Adapter { tree, update_factory(), ); - Some(QueuedEvents(events)) } } + (!events.is_empty()).then_some(QueuedEvents(events)) } /// Create an `AccessibilityNodeInfo` for the AccessKit node diff --git a/adapters/android/src/inject.rs b/adapters/android/src/inject.rs index 5b369972..8c9fb8cb 100644 --- a/adapters/android/src/inject.rs +++ b/adapters/android/src/inject.rs @@ -400,27 +400,33 @@ impl InjectingAdapter { /// which is expensive; callers that update frequently from a native /// thread should attach that thread permanently. pub fn update_if_active(&mut self, update_factory: impl FnOnce() -> TreeUpdate) { - let mut env = self.vm.attach_current_thread().unwrap(); - env.with_local_frame(LOCAL_FRAME_CAPACITY, |env| -> Result<()> { + let events = self + .inner + .lock() + .unwrap() + .adapter + .update_if_active(update_factory); + let Some(events) = events else { + return; + }; + self.attach_and_post_to_ui_thread(|env, _delegate_class, host| { + events.raise(env, host); + }) + .unwrap(); + } + + fn attach_and_post_to_ui_thread( + &self, + callback: impl FnOnce(&mut JNIEnv, &JClass, &JObject) + Send + 'static, + ) -> Result<()> { + let mut env = self.vm.attach_current_thread()?; + env.with_local_frame(LOCAL_FRAME_CAPACITY, |env| { let Some(host) = self.host.upgrade_local(env)? else { return Ok(()); }; - let mut inner = self.inner.lock().unwrap(); - let Some(events) = inner.adapter.update_if_active(update_factory) else { - return Ok(()); - }; - drop(inner); - post_to_ui_thread( - env, - self.delegate_class, - &host, - |env, _delegate_class, host| { - events.raise(env, host); - }, - ); + post_to_ui_thread(env, self.delegate_class, &host, callback); Ok(()) }) - .unwrap(); } } @@ -457,16 +463,7 @@ fn uninstall_delegate(env: &mut JNIEnv, delegate_class: &JClass, host: &JObject) impl Drop for InjectingAdapter { fn drop(&mut self) { - let res = self.vm.attach_current_thread().and_then(|mut env| { - env.with_local_frame(LOCAL_FRAME_CAPACITY, |env| { - let Some(host) = self.host.upgrade_local(env)? else { - return Ok(()); - }; - post_to_ui_thread(env, self.delegate_class, &host, uninstall_delegate); - Ok(()) - }) - }); - if let Err(err) = res { + if let Err(err) = self.attach_and_post_to_ui_thread(uninstall_delegate) { debug!("error dropping InjectingAdapter: {:#?}", err); } HANDLE_MAP.lock().unwrap().remove(&self.handle);