Declare the DSP's RPC library, so the app can reach the Hexagon

QNN's Hexagon stub loads libcdsprpc.so, a vendor library, and from API 31
an app's linker namespace refuses a vendor library its manifest does not
name. QNN then fails to create its device - QNN_DEVICE_ERROR_INVALID_CONFIG,
before it reaches the DSP - and every model ran on the CPU on 0.22.0: AI
denoise took 30-131 s a photograph on the tablet.

The same engine code ran on the HTP from adb's shell, whose namespace has
no such rule, which is what hid it. With the declaration the app's probe
chose the Hexagon on the tablet and compiled every model for it. Not
required, so a device without the library still installs and runs on the
CPU. A test holds the line in the manifest.
This commit is contained in:
2026-10-04 20:19:04 -04:00
parent f20e481358
commit a116325991
2 changed files with 21 additions and 0 deletions
@@ -73,6 +73,14 @@
android:requestLegacyExternalStorage="true" android:requestLegacyExternalStorage="true"
android:supportsRtl="true"> android:supportsRtl="true">
<!-- The DSP's RPC library, which QNN's Hexagon stub loads. From API 31
an app's linker namespace refuses a vendor library the manifest
does not name, and QNN then fails to create its device
(QNN_DEVICE_ERROR_INVALID_CONFIG) before it reaches the DSP:
every model ran on the CPU on 0.22.0. Not required, so a device
without one still installs and stays on the CPU. -->
<uses-native-library android:name="libcdsprpc.so" android:required="false" />
<!-- NativeActivity rather than a Kotlin Activity: android-activity's <!-- NativeActivity rather than a Kotlin Activity: android-activity's
glue loads libdarkroom.so and calls android_main. `android.app.lib_name` glue loads libdarkroom.so and calls android_main. `android.app.lib_name`
is how it learns which library to load, and must match [lib].name. is how it learns which library to load, and must match [lib].name.
+13
View File
@@ -538,6 +538,19 @@ mod tests {
Some(value.to_string()) Some(value.to_string())
} }
/// From API 31 the linker refuses a vendor library the manifest does not
/// name, and QNN cannot create its Hexagon device without the DSP's RPC
/// library: 0.22.0 ran every model on the CPU for want of this line.
#[test]
fn the_npu_can_reach_the_dsp() {
assert!(
manifest().contains(
r#"<uses-native-library android:name="libcdsprpc.so" android:required="false" />"#
),
"libcdsprpc.so must be declared, and not required"
);
}
#[test] #[test]
fn a_gallery_can_open_a_photograph_in_this_app() { fn a_gallery_can_open_a_photograph_in_this_app() {
let manifest = manifest(); let manifest = manifest();