From 8f7f282e51c93f9d0ae944b7bd70969eee998f55 Mon Sep 17 00:00:00 2001 From: WiesiDeluxe <7261939+WiesiDeluxe@users.noreply.github.com> Date: Tue, 22 Sep 2026 12:42:51 +0000 Subject: [PATCH 1/2] Disable XNNPACK and NNAPI for the wake word / VAD interpreters (#105) Any TFLite inference on live audio crashed the app on the 32-bit Wall Displays (X2/PEGASUS on Android 8.1 and Gen1/STARGATE on Android 7): SIGSEGV at libtensorflowlite_jni.so+0x1f9b68, XNNPACK's qs8_gemm_minmax 4x8 aarch32 NEON kernel, called with a garbage input pointer (0x14). TFLite enables the XNNPACK delegate by default, so the NNAPI-only change did not reach that code path. With XNNPACK off the segfault is gone, but on the X2 (API 27) the NNAPI runtime then leaks a memory mapping per execution (/proc//maps grows ~7000 entries per 20 s) until it hits vm.max_map_count and pthread_create fails: "thread constructor failed: Try again" in android::nn::StepExecutor::startComputeOnCpu. The wake word and VAD models are 52 KB / 34 KB; the built-in int8 CPU kernels handle them with ~40 % of one core on a quad A7, so neither delegate is needed. Verified on both 32-bit devices (wake word detected and answered end to end, stable for hours) and on the arm64 XL. Co-Authored-By: Claude Fable 5.1 --- .../shellyelevatev2/voice/WakeWordDetector.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/me/rapierxbox/shellyelevatev2/voice/WakeWordDetector.java b/app/src/main/java/me/rapierxbox/shellyelevatev2/voice/WakeWordDetector.java index 55c5764..0715b43 100644 --- a/app/src/main/java/me/rapierxbox/shellyelevatev2/voice/WakeWordDetector.java +++ b/app/src/main/java/me/rapierxbox/shellyelevatev2/voice/WakeWordDetector.java @@ -880,9 +880,14 @@ private static MappedByteBuffer loadMappedFile(File file) throws Exception { static Interpreter buildInterpreter(MappedByteBuffer model) { Interpreter.Options opts = new Interpreter.Options().setNumThreads(1); - if (Build.VERSION.SDK_INT >= 30) { - opts.setUseNNAPI(true); - } + // Plain CPU kernels only (#105): + // - XNNPACK's aarch32 qs8 gemm kernel segfaults on the 32-bit Wall Displays + // (X2/PEGASUS, Gen1/STARGATE) as soon as a model runs on live audio. + // - NNAPI on these SoCs spawns a thread and leaks memory mappings per + // inference until pthread_create fails (~3 min on the X2), and brings + // nothing for these tiny models. + opts.setUseXNNPACK(false); + opts.setUseNNAPI(false); return new Interpreter(model, opts); } From aa0e9671d3880507433842c5b51d95d40a5d1628 Mon Sep 17 00:00:00 2001 From: WiesiDeluxe <7261939+WiesiDeluxe@users.noreply.github.com> Date: Tue, 22 Sep 2026 12:42:33 +0000 Subject: [PATCH 2/2] Target SDK 28 so the WebView accepts CSS hex-alpha colours (#84) Chromium's WebView only enables CSSHexAlphaColor for apps targeting Android P or newer (android_webview AwContents.java). Home Assistant's frontend (2026.7+) minifies every colour with alpha to 4/8-digit hex (`transparent` -> `#0000`, card border -> `#e1e1e11f`), so with targetSdk 24 those declarations are dropped: solid card outlines and solid discs behind icons on every Wall Display, regardless of the installed WebView version. minSdk stays 24. usesCleartextTraffic="true" is already declared, so plain-http HA URLs keep working with targetSdk 28. Verified on a Wall Display X2 (Android 8.1, WebView 128): with targetSdk 28 CSS.supports("color", "#0000") is true and plain buttons / card borders render as on desktop; the XL (Android 11, WebView 131, targetSdk 24) renders them solid. Co-Authored-By: Claude Fable 5.1 --- app/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 00d03b3..229b290 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -53,7 +53,7 @@ android { applicationId = "me.rapierxbox.shellyelevatev2" minSdk = 24 //noinspection ExpiredTargetSdkVersion - targetSdk = 24 + targetSdk = 28 versionCode = versionCodeForBuild() versionName = versionNameForBuild()