Read an unknown SoC as Qualcomm's

The generic runtime is opened only when the QNN build does not fit, and
the fit rests on ro.soc.manufacturer. A property the app cannot read, or
an Android older than 12 that has none, read as "not Qualcomm" would
put a Qualcomm device on the generic rung and off its Hexagon — what
0.22.1 had just fixed. Only a device that names another vendor is now
not Qualcomm's; the tablet reports QTI.
This commit is contained in:
2026-10-04 22:26:56 -04:00
parent 4b33754482
commit 4822991bec
+26 -7
View File
@@ -95,10 +95,12 @@ pub fn detect() -> Gpus {
#[cfg(target_os = "android")]
pub fn detect() -> Gpus {
// `ro.soc.manufacturer` exists from Android 12. Qualcomm's FastRPC
// library, which the Hexagon path loads anyway, is the second witness:
// a Qualcomm device read as anything else would trade its NPU for the
// generic rung.
// Fail-safe: only a device that names another vendor is not Qualcomm.
// `ro.soc.manufacturer` exists from Android 12, and a property or file
// the app cannot read reads as nothing; nothing keeps the QNN build
// first, as 0.22 had it, where a Qualcomm device mistaken for another
// would trade its NPU for the generic rung. Qualcomm's FastRPC library,
// which the Hexagon path loads anyway, overrules a name.
let soc = crate::probe::system_property("ro.soc.manufacturer");
let fastrpc = [
"/vendor/lib64/libcdsprpc.so",
@@ -107,13 +109,19 @@ pub fn detect() -> Gpus {
.iter()
.any(|p| std::path::Path::new(p).exists());
Gpus {
qualcomm: soc.eq_ignore_ascii_case("QTI")
|| soc.eq_ignore_ascii_case("Qualcomm")
|| fastrpc,
qualcomm: qualcomm_soc(&soc) || fastrpc,
..Gpus::default()
}
}
/// Whether `ro.soc.manufacturer` leaves the device Qualcomm's: it says so,
/// or it says nothing.
#[cfg(any(target_os = "android", test))]
fn qualcomm_soc(manufacturer: &str) -> bool {
let m = manufacturer.trim();
m.is_empty() || m.eq_ignore_ascii_case("QTI") || m.eq_ignore_ascii_case("Qualcomm")
}
#[cfg(not(any(target_os = "linux", target_os = "windows", target_os = "android")))]
pub fn detect() -> Gpus {
Gpus::default()
@@ -127,6 +135,17 @@ mod tests {
p.iter().map(|s| s.to_string()).collect()
}
#[test]
fn only_a_named_other_vendor_is_not_qualcomm() {
assert!(qualcomm_soc("QTI"));
assert!(qualcomm_soc("Qualcomm"));
// Unreadable, or older than Android 12: the QNN build stays first.
assert!(qualcomm_soc(""));
assert!(!qualcomm_soc("Mediatek"));
assert!(!qualcomm_soc("Google"));
assert!(!qualcomm_soc("Samsung"));
}
#[test]
fn the_card_beats_the_integrated_gpu_and_both_beat_the_generic_rung() {
let cpu = offers(&["CPUExecutionProvider"]);