From ac5cbbc49a01933a1b9446810526db76d59b1c64 Mon Sep 17 00:00:00 2001 From: QIU Date: Thu, 13 Aug 2026 00:46:56 +0000 Subject: [PATCH] fix(cw): add crash probes to localize adb-less flash-crash MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 闪回桌面且无任何 Java 日志 => 崩溃发生在 native 层 (ONNX 库内部段错误) 或进程被系统 LMK 直接杀掉 (内存不足) —— 两种情况 Java 的 uncaughtExceptionHandler 都不会触发, crash_log.txt 自然为空。 新增 CwProbe: 在关键节点向 files/probe_cw.txt 追加时间戳行: decoder_constructed -> load_begin -> load_session_ok / load_failed:<类名> -> infer_begin -> infer_done 进程若中途死亡, 最后一行的节点就是崩溃/被杀位置, 无需 adb 即可定位。 验证: :core:data:compileDebugKotlin => BUILD SUCCESSFUL --- .../look4sat/core/data/cw/CwDeepDecoder.kt | 10 ++++ .../rtbishop/look4sat/core/data/cw/CwProbe.kt | 46 +++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 core/data/src/main/java/com/rtbishop/look4sat/core/data/cw/CwProbe.kt diff --git a/core/data/src/main/java/com/rtbishop/look4sat/core/data/cw/CwDeepDecoder.kt b/core/data/src/main/java/com/rtbishop/look4sat/core/data/cw/CwDeepDecoder.kt index 1b5e0336..39d472e5 100644 --- a/core/data/src/main/java/com/rtbishop/look4sat/core/data/cw/CwDeepDecoder.kt +++ b/core/data/src/main/java/com/rtbishop/look4sat/core/data/cw/CwDeepDecoder.kt @@ -87,6 +87,11 @@ class CwDeepDecoder(context: Context) : ICwDecoder { private val appContext = context.applicationContext private var loadAttempted = false + init { + CwProbe.init(appContext) + CwProbe.step("decoder_constructed") + } + /** * Loads metadata and the ONNX session on first use. * @@ -102,6 +107,7 @@ class CwDeepDecoder(context: Context) : ICwDecoder { if (session != null) return true if (loadAttempted) return false loadAttempted = true + CwProbe.step("load_begin") try { val metadata = JSONObject( appContext.assets.open(METADATA_ASSET).bufferedReader().use { it.readText() } @@ -122,11 +128,13 @@ class CwDeepDecoder(context: Context) : ICwDecoder { setIntraOpNumThreads(threads) } session = env.createSession(modelBytes, options) + CwProbe.step("load_session_ok") Log.i(TAG, "DeepCW ready: ${modelBytes.size} bytes, ${chars.size} classes") return true } catch (t: Throwable) { // Catches UnsatisfiedLinkError (missing/mismatched .so) as well as // asset and session failures. + CwProbe.step("load_failed:${t.javaClass.simpleName}") Log.e(TAG, "DeepCW model failed to load", t) _errorMessage.value = "CW model failed to load: ${t.message ?: t.javaClass.simpleName}" @@ -175,6 +183,7 @@ class CwDeepDecoder(context: Context) : ICwDecoder { private suspend fun decodeWindow(window: FloatArray) = withContext(Dispatchers.Default) { val activeSession = session ?: return@withContext val activeEnvironment = environment ?: return@withContext + CwProbe.step("infer_begin frames=${window.size}") val spectrogram = CwDeepSpectrogram.compute(window) val frames = spectrogram.size @@ -195,6 +204,7 @@ class CwDeepDecoder(context: Context) : ICwDecoder { } } _lastInferenceMs.value = (System.currentTimeMillis() - startedAt).toInt() + CwProbe.step("infer_done ms=${_lastInferenceMs.value}") // Replace, never append: the model rewrites earlier characters as more // context arrives, so appending would leave stale guesses on screen. diff --git a/core/data/src/main/java/com/rtbishop/look4sat/core/data/cw/CwProbe.kt b/core/data/src/main/java/com/rtbishop/look4sat/core/data/cw/CwProbe.kt new file mode 100644 index 00000000..3551d552 --- /dev/null +++ b/core/data/src/main/java/com/rtbishop/look4sat/core/data/cw/CwProbe.kt @@ -0,0 +1,46 @@ +/* + * Look4Sat. Amateur radio satellite tracker and pass predictor. + * Copyright (C) 2019-2026 Arty Bishop and contributors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.rtbishop.look4sat.core.data.cw + +import android.content.Context +import android.util.Log + +/** + * Minimal crash-probe logger for diagnosing crashes that produce no Java + * stack trace (native faults, low-memory kills). Each step appends one line + * to `files/probe_cw.txt`; if the process dies mid-way the last line shows + * exactly where. No adb or logcat required. + */ +internal object CwProbe { + + private var dir: java.io.File? = null + + fun init(context: Context) { + dir = context.filesDir + } + + fun step(label: String) { + val target = dir ?: return + runCatching { + val line = "${System.currentTimeMillis()} $label" + val file = java.io.File(target, "probe_cw.txt") + file.appendText("$line\n") + Log.i("CwProbe", line) + } + } +}