ROOT CAUSE of the 8-12% slot drops (uniform dec=1/0/1/0: locked, no wake seen, dirty, no render): AOSP Looper::pollInner (system/core/libutils/ Looper.cpp) drains the wake fd in the SAME epoll batch (up to 16 fds) as any ready input fd, and pollOnce returns the input's ident — the POLL_WAKE result is a local that gets dropped. ALooper_wake's byte is consumed WITHOUT PollEvent::Wake ever reaching Slint, unrecoverable. With motion events arriving 1-4 ms after the edge (always for a real 120-240 Hz finger; ~1 in 5 frames for 20 Hz adb input) the wake is lost and the locked decision (saw_wake && slot-guard) drops the dirty frame for that slot. Fix (vendor backend): a dedicated eventfd registered with the MAIN looper under ALOOPER_POLL_CALLBACK. The Looper invokes the C trampoline INSIDE pollInner (before pollOnce returns, regardless of which ident is handed back), so delivery can never be swallowed by a co-batched input response. - frame_callback: note the edge, write the eventfd, then ALooper_wake (secondary). The fd is leaked: it belongs to the main looper for the process lifetime. - trampoline: DRAINS the eventfd (level-triggered — without the drain the counter stays >0, the fd stays readable and the loop busy-spins on POLL_CALLBACK at ~10 kHz: 1812 spin iterations measured) and publishes the edge into delivered_edge. - main loop: saw_wake |= (delivered_edge newer than last seen). - DIRTY BACKSTOP: the 6 ms poll cap was never a backstop — timeout iterations have saw_wake=false so the locked decision never rendered (the 20-40 ms silences). Now: dirty && last render >= 2 slots old renders regardless of wake state. Measured on the phone (Pixel 9 Pro, 120 Hz, sltest, identical capture): buildC (before): 127 drops + 12 stalls in 1142 frames buildE (after): 8 drops + 0 stalls in 1266 frames Phase (p10-p90): 0.72-1.00 ms in all windows. Remaining 8/1266 (0.63%) are slip-and-recover pairs where the UI thread is DESCHEDULED 6-8 ms while sleeping in epoll (wakes arrive on time, cb-lat 0.5 ms) — EAS scheduling variance, no app-side contention in sltest. Referee fixes found while judging this data (tools/jank_eval.py): - NEAREST-OBSERVED-EDGE slot grid: the 120 Hz panel clock phase-slips after idle blanking (re-locks at arbitrary phase), invalidating any grid anchored at ftns[0]. An entire drag window read late=230/ dropped=24 while per-cycle tracing showed presents at edge+2.0 ms. slot_of_ftn assigns each present to the nearest observed hardware edge in a time-continuous slot domain (slip-immune: a constant delta shifts all slots, differences preserved; stall-accurate: ftn times are CLOCK_MONOTONIC). - tools/jank_capture.py: capture is INVALID unless the screen is Awake AND the keyguard is down (a run on a sleeping phone silently injects no input: 49 IT lines, 1 present).
123 lines
3.1 KiB
TOML
123 lines
3.1 KiB
TOML
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
|
|
#
|
|
# When uploading crates to the registry Cargo will automatically
|
|
# "normalize" Cargo.toml files for maximal compatibility
|
|
# with all versions of Cargo and also rewrite `path` dependencies
|
|
# to registry (e.g., crates.io) dependencies.
|
|
#
|
|
# If you are reading this file be aware that the original Cargo.toml
|
|
# will likely look very different (and much more reasonable).
|
|
# See Cargo.toml.orig for the original contents.
|
|
|
|
[package]
|
|
edition = "2024"
|
|
rust-version = "1.92"
|
|
name = "i-slint-backend-android-activity"
|
|
version = "1.18.1"
|
|
authors = ["Slint Developers <info@slint.dev>"]
|
|
build = "build.rs"
|
|
autolib = false
|
|
autobins = false
|
|
autoexamples = false
|
|
autotests = false
|
|
autobenches = false
|
|
description = "OpenGL rendering backend for Slint"
|
|
homepage = "https://slint.dev"
|
|
readme = "README.md"
|
|
license = "GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0"
|
|
repository = "https://github.com/slint-ui/slint"
|
|
|
|
[package.metadata.docs.rs]
|
|
targets = [
|
|
"aarch64-linux-android",
|
|
"armv7-linux-androideabi",
|
|
"i686-linux-android",
|
|
"x86_64-linux-android",
|
|
]
|
|
features = [
|
|
"native-activity",
|
|
"aa-06",
|
|
]
|
|
rustdoc-args = ["--generate-link-to-definition"]
|
|
|
|
[features]
|
|
aa-05 = [
|
|
"android-activity-05",
|
|
"ndk-08",
|
|
]
|
|
aa-06 = [
|
|
"android-activity-06",
|
|
"ndk-09",
|
|
]
|
|
game-activity = [
|
|
"android-activity-06?/game-activity",
|
|
"android-activity-05?/game-activity",
|
|
]
|
|
native-activity = [
|
|
"android-activity-06?/native-activity",
|
|
"android-activity-05?/native-activity",
|
|
]
|
|
unstable-wgpu-29 = ["i-slint-renderer-skia/unstable-wgpu-29"]
|
|
unstable-wgpu-30 = ["i-slint-renderer-skia/unstable-wgpu-30"]
|
|
|
|
[lib]
|
|
name = "i_slint_backend_android_activity"
|
|
path = "lib.rs"
|
|
|
|
[build-dependencies.android-build]
|
|
version = "0.1.2"
|
|
|
|
[target.'cfg(target_os = "android")'.dependencies.android-activity-05]
|
|
version = "0.5"
|
|
optional = true
|
|
package = "android-activity"
|
|
|
|
[target.'cfg(target_os = "android")'.dependencies.android-activity-06]
|
|
version = "0.6"
|
|
optional = true
|
|
package = "android-activity"
|
|
|
|
[target.'cfg(target_os = "android")'.dependencies.i-slint-common]
|
|
version = "=1.18.1"
|
|
default-features = false
|
|
|
|
# Jank-hunt: VSYNC timestamp logging (vsync.rs phase-alignment probes).
|
|
[target.'cfg(target_os = "android")'.dependencies.log]
|
|
version = "0.4"
|
|
|
|
[target.'cfg(target_os = "android")'.dependencies.i-slint-core]
|
|
version = "=1.18.1"
|
|
features = [
|
|
"std",
|
|
"image-decoders",
|
|
"svg",
|
|
]
|
|
default-features = false
|
|
|
|
[target.'cfg(target_os = "android")'.dependencies.i-slint-renderer-skia]
|
|
version = "=1.18.1"
|
|
default-features = false
|
|
|
|
[target.'cfg(target_os = "android")'.dependencies.jni]
|
|
version = "0.22"
|
|
|
|
# eventfd for the vsync delivery fd (vsync.rs wake-fd-race fix)
|
|
[target.'cfg(target_os = "android")'.dependencies.libc]
|
|
version = "0.2"
|
|
|
|
[target.'cfg(target_os = "android")'.dependencies.ndk-08]
|
|
version = "0.8.0"
|
|
features = ["rwh_06"]
|
|
optional = true
|
|
package = "ndk"
|
|
|
|
[target.'cfg(target_os = "android")'.dependencies.ndk-09]
|
|
version = "0.9.0"
|
|
features = ["rwh_06"]
|
|
optional = true
|
|
default-features = false
|
|
package = "ndk"
|
|
|
|
[target.'cfg(target_os = "android")'.dependencies.raw-window-handle]
|
|
version = "0.6"
|