fix(android): avoid rsproperties panic on startup, closes #3922 (#3942)
Some checks are pending
CodeQL Advanced / Analyze (actions) (push) Waiting to run
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
CodeQL Advanced / Analyze (rust) (push) Waiting to run
PR checks / build_tauri_app (push) Waiting to run
PR checks / rust_lint (push) Waiting to run
PR checks / build_web_app (push) Waiting to run
Deploy to vercel on merge / build_and_deploy (push) Waiting to run

`rsproperties::get` panics when it can't open or parse the
`/dev/__properties__` layout (documented behavior of the crate).
On some older/unusual Android builds (e.g. MediaTek Android 8.1 on
Xiaomi Mipad), this aborts the app with SIGABRT before the main
window is created.

Replace the crate with a direct FFI call to Android's native
`__system_property_get`, which has existed since the earliest
Android versions and returns an error code instead of panicking.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Huang Xin 2026-04-24 12:00:31 +08:00 committed by GitHub
parent be8b946683
commit 71371130e0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 17 additions and 25 deletions

22
Cargo.lock generated
View file

@ -17,6 +17,7 @@ dependencies = [
"discord-rich-presence",
"futures",
"futures-util",
"libc",
"log",
"objc",
"objc-foundation",
@ -27,7 +28,6 @@ dependencies = [
"rand 0.8.6",
"read-progress-stream",
"reqwest 0.12.28",
"rsproperties",
"serde",
"serde_json",
"tauri",
@ -5081,12 +5081,6 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
[[package]]
name = "pretty-hex"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a65843dfefbafd3c879c683306959a6de478443ffe9c9adf02f5976432402d7"
[[package]]
name = "prettyplease"
version = "0.2.37"
@ -5842,20 +5836,6 @@ dependencies = [
"byteorder",
]
[[package]]
name = "rsproperties"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b98d55abde44982a00d67a84809166ea8f5c143abc86818f555485f19766cfe4"
dependencies = [
"log",
"pretty-hex",
"rustix 1.1.4",
"thiserror 2.0.18",
"zerocopy",
"zerocopy-derive",
]
[[package]]
name = "rust-ini"
version = "0.21.3"

View file

@ -81,4 +81,4 @@ tauri-plugin-window-state = "2"
discord-rich-presence = "1.0.0"
[target.'cfg(target_os = "android")'.dependencies]
rsproperties = "0.3"
libc = "0.2"

View file

@ -46,9 +46,21 @@ const EINK_MODELS: &[&str] = &[
];
fn get_system_property(prop: &str) -> Option<String> {
rsproperties::get::<String>(prop)
.ok()
.filter(|s| !s.is_empty())
use std::ffi::CString;
let name = CString::new(prop).ok()?;
let mut buf = [0u8; libc::PROP_VALUE_MAX as usize];
// SAFETY: __system_property_get writes at most PROP_VALUE_MAX bytes (including the
// trailing NUL) into the provided buffer and returns the number of bytes written
// excluding the NUL. `name` is a valid NUL-terminated C string for the duration
// of the call.
let len = unsafe {
libc::__system_property_get(name.as_ptr(), buf.as_mut_ptr() as *mut libc::c_char)
};
if len <= 0 {
return None;
}
let value = std::str::from_utf8(&buf[..len as usize]).ok()?;
(!value.is_empty()).then(|| value.to_owned())
}
/// Check if the current Android device is an e-ink device.