Give a phone without a Qualcomm SoC the generic WebGPU runtime

The APK's ONNX Runtime is the QNN build, which carries no WebGPU, so a
non-Qualcomm phone had nothing above the CPU provider. The APK now also
carries Microsoft's stock onnxruntime-android 1.29.0 (32 MB) as
libonnxruntime_generic.so, and the app offers it after the QNN build.

The runtime search stops at a perfect fit, so on a Qualcomm device the
QNN build — listed first — is all that is opened, and the generic build
never loads beside it. A Qualcomm SoC is read from ro.soc.manufacturer
or, before Android 12, from Qualcomm's FastRPC library being present:
a Qualcomm device mistaken for another would trade its Hexagon for the
generic rung.
This commit is contained in:
2026-10-04 21:00:15 -04:00
parent cb97ebe7ac
commit 43402bfe5b
6 changed files with 59 additions and 19 deletions
+17 -7
View File
@@ -3,17 +3,23 @@
#
# ./tools/fetch-android-runtime.sh [DEST]
#
# Two Maven artefacts, pinned to each other by ONNX Runtime's own POM:
# Three Maven artefacts, the first two pinned to each other by ONNX Runtime's
# own POM:
#
# com.microsoft.onnxruntime:onnxruntime-android-qnn MIT
# com.qualcomm.qti:qnn-runtime Qualcomm AI Engine Direct SDK licence
# com.microsoft.onnxruntime:onnxruntime-android MIT
#
# The first is ONNX Runtime built with the CPU, QNN, XNNPACK, NNAPI and WebGPU
# providers; the second is Qualcomm's HTP backend — the ARM-side compiler and
# the per-generation Hexagon "skel" the DSP loads. Both ship as AARs whose
# `jni/arm64-v8a/` is what an APK's `lib/arm64-v8a/` wants, so this script
# unpacks exactly that and nothing else, plus the licence texts, which travel
# with the libraries (§3.1).
# The first is ONNX Runtime built with the CPU and QNN providers; the second
# is Qualcomm's HTP backend — the ARM-side compiler and the per-generation
# Hexagon "skel" the DSP loads. The third is Microsoft's stock build, which
# carries WebGPU (Dawn on Vulkan) and the QNN build does not: the generic
# rung for a phone without a Qualcomm SoC (§3.2). It lands as
# `libonnxruntime_generic.so` beside the QNN build; the engine opens the QNN
# build first, and on a Qualcomm device stops there. All three ship as AARs
# whose `jni/arm64-v8a/` is what an APK's `lib/arm64-v8a/` wants, so this
# script unpacks exactly that and nothing else, plus the licence texts, which
# travel with the libraries (§3.1).
#
# ## What is and is not taken from the Qualcomm package
#
@@ -65,6 +71,8 @@ fetch com.microsoft.onnxruntime onnxruntime-android-qnn "${ORT_VERSION}" \
"${DEST}/aar/onnxruntime-android-qnn-${ORT_VERSION}.aar"
fetch com.qualcomm.qti qnn-runtime "${QNN_VERSION}" \
"${DEST}/aar/qnn-runtime-${QNN_VERSION}.aar"
fetch com.microsoft.onnxruntime onnxruntime-android "${ORT_VERSION}" \
"${DEST}/aar/onnxruntime-android-${ORT_VERSION}.aar"
# The ONNX Runtime POM names the QNN version it was built against; a pair
# that disagrees loads and then fails at the first graph, which is the kind
@@ -82,6 +90,8 @@ rm -rf "${DEST}/lib"
mkdir -p "${DEST}/lib"
unzip -q -o -j "${DEST}/aar/onnxruntime-android-qnn-${ORT_VERSION}.aar" \
'jni/arm64-v8a/libonnxruntime.so' -d "${DEST}/lib"
unzip -q -o -p "${DEST}/aar/onnxruntime-android-${ORT_VERSION}.aar" \
'jni/arm64-v8a/libonnxruntime.so' > "${DEST}/lib/libonnxruntime_generic.so"
members=(jni/arm64-v8a/libQnnHtp.so jni/arm64-v8a/libQnnHtpPrepare.so jni/arm64-v8a/libQnnSystem.so)
for arch in ${QNN_HTP_ARCHS}; do
members+=("jni/arm64-v8a/libQnnHtpV${arch}Skel.so" "jni/arm64-v8a/libQnnHtpV${arch}Stub.so")