Commit Graph
34 Commits
Author SHA1 Message Date
AskaEth c7ef1ebb04 fw_content: M6.5 收编 audiod b122c9b8(315 孤儿会话回收) 2026-09-02 10:10:36 +08:00
AskaEth bcc016e50e fix(ncm): 播放页歌词解析栈溢出(SIGSEGV)修复 —— lyric_parse 栈上 227KB 临时数组超 128KB 线程栈
根因(真机 sig=11,RA 落 lyric_parse / pc 在 lib):
app/logic/lyric.c lyric_parse() 在栈上定义
  long ttmp[NCM_LYRIC_LINES=600]; char txt[600][192]; char tl[600][192]
  = ~227KB 栈帧,远超 ncm_thread_create 统一设的 NCM_THREAD_STACK=128KB。
播放页 enter → player_manager_load_lyric → lyric_worker(128KB 线程栈) → lyric_parse → 栈溢出 SIGSEGV。
崩溃仅在「播放页前台 + 拉取歌词成功 + 解析」时触发,故与播放进度无关、autoplay 仅后台起播不崩。

修法:排序临时数组移到堆(按 s_n 计,≤600 行,峰值 ~230KB 瞬态),栈帧回到 KB 级。

复现/定位(/dev 调试 + 真机):
- 真机通过 amd 恢复路径:/tmp/ncm_autoplay 起播缓存曲,app_on_tick 于 UI 线程调 player_play_song
  打开播放页(复现用户点曲路径;autoplay_ui_consume 承接)。原崩溃:pid sig=11 dur=3683ms;
  修复后:连续两次 play:start 无崩溃、60s+ 存活、无 crash_report。
- app.c 增 async-signal-safe SIGSEGV/SIGBUS/SIGILL 处理器(MIPS mcontext_t.pc + gregs ra/sp/fp
  → stderr + crash_report.txt),供 addr2line/链接布局定位。

验证:stream/player_flow/window/search/cache_evict sim 全 PASS;test_ncm_core host + qemu-mipsel
PASS;build_ncm.sh -Wall -Wextra 0 warning;ncm_host NCM_PAGE=player/home 离屏渲染 exit=0。
2026-09-02 09:53:34 +08:00
AskaEth 54750a63c5 feat(sdk): SDK 矢量字(meow_ft_*,§10.1)——上收阅读器 FreeType 管线
问题:SDK 位图字库(meow_font)只有离散字号档位,全字形 atlas 稳态 17.3MiB
(27MB 整机装不下)→ 大字库/大字号必出豆腐。阅读器 R1/R2 的 FreeType 管线已真机验证
(MiSans OTF),本 commit 将其上收 SDK,让任意 App 用上无级字号 + CJK 全字形。

设计(追加式,与位图字库并存):
- meow_ui_ft.c(独立 .o):meow_ft_load/unload/loaded/text/width/line_height/
  ascender/descender/cache_set_slots/cache_slots/cache_used。底层按 READER_ENGINE_NOTES §5:
  FT_New_Face(path) 按需读文件(零整载 anon);灰阶 FT_LOAD_RENDER|NO_HINTING|TARGET_LIGHT;
  glyph LRU key=(px<<32)|cp,默认 512(~0.46MB),可配 256/1024;测宽不栅格化。
- meow_ui_gfx.c 只加两个薄封装 meow_gfx_ft_blend_px/dirty(写 back_buf + 标脏),
  使 meow_ui_ft.o 不引入新依赖——「不调 meow_ft_* 的 App 零增量」(freetype 不拉入,已验证)。
- 降级:加载失败/无卡 → meow_ft_loaded()==0 → meow_ft_text 自动改走 meow_ui_text(位图字库,
  5x7 兜底),绝不豆腐不崩;meow_ft_width/line_height 降级位图字库度量。
- FreeType 2.14.3 vendor 进 patch_v2/sdk/vendor/(gitignore)+ build_sdk.sh 可复现拉取+裁剪
  构建(-DFT_DISABLE_ZLIB/BZIP2/PNG/HARFBUZZ/BROTLI=TRUE,静态 musl),freetype .o 编入
  meow_ui.a,App 链接命令不变(meow_ui.a libz.a -lpthread)。

验证:
- 宿主 test_meow_ui_ft 5 项全 PASS(加载/渲染像素非空/宽度测量/LRU 淘汰/降级回退)。
- 全量 SDK 回归:widgets/sdk_fixes/dispatch/notif_gesture/overlay_suppress/listvirt/box/anim/
  scroll/ime_fix/pinyin/notif_open/sb_collapse/theme/notify_ipc/audio_host/vol/str/config/
  sdk_input_keys 全 PASS。
- 交叉 -Wall -Wextra 全 SDK TU 0 warning;qemu-mipsel 冒烟 PASS(mipsel FreeType 真光栅化)。
- meow_ui.a 新 md5 6ff5be9455f9e197b35fa120be012041(未重链不部署 App,四 App 免重链)。

MEOW_APP_SDK.md 补 §10.1 矢量字一节 + 公共头索引/§9 构建约定更新;.gitignore 忽略
patch_v2/sdk/vendor/ 与 test_meow_ui_ft 二进制。
2026-09-02 09:51:23 +08:00
AskaEth 121d30ec95 fix(audiod): 孤儿会话回收 — 客户端崩溃/被杀(sig=9)/正常退出后会话完整回收,STATE 回干净无流基线
根因: cli_free(EOF)与 STOP 路径只置 active=0 + 唤醒排空,未清 sid/written/played/underrun/
rms/peak/lvlseq——ncm 被内核 OOM 杀后面板 /api/overview audio 块残留(active=0 但 sid/统计挂着)。
修法: 两段式 session_end_locked(即时置死+清 sid/app_id,保留 rate/ch/fmt 供排空算 frame_size)+
session_clean_locked(播放线程排空完成后彻底归零 rate/ch/fmt/written/played/underrun/drop/stall/
rms/peak/lvlseq)。顺带修 dac_vol_set 一处 -Wmisleading-indentation。
宿主 51/51 PASS(47 既有 + T9 SIGKILL 孤儿回收断言 STATE 全清,模拟子进程崩溃). meow_audiod b122c9b8 交叉0warning
2026-09-02 09:32:48 +08:00
AskaEth 19f7e59927 docs: 仓库文档同步 M6.4(0.8.4)——README 版本行+新能力(SDK 演进批次/锁屏 PIN/面板批2+overview 自校验);SPEC_REF 补 SDK §3.5 扩展模块速查+system.pin 锁屏键+面板 batch2/UTF-8 加固 2026-09-02 09:12:56 +08:00
AskaEth 54e737a4a2 fix(panel): overview net 块括号配平(批2 DNS 并入时多写一个 },浏览器 Extra data 破页)+自校验换严格平衡检查(jv_parse 容忍尾随垃圾,浏览器不容忍) 2026-09-02 09:00:08 +08:00
AskaEth 524e5d6967 feat(panel): 前端 NOT_JSON 自动回传原始响应到 /api/debug/report_bad_json(落 /tmp/overview_client_bad.txt,抓浏览器收到的真实字节) 2026-09-02 08:39:29 +08:00
AskaEth 57676766c0 fw_content: M6.4 收编 launcher 56dac860(310二期 EVIOCGRAB 锁屏+名称截断) 2026-09-02 08:17:37 +08:00
AskaEth bc9ba3693f feat(panel web): NOT_JSON 错误日志补 响应长度+尾部 200 字节(定位截断点) 2026-09-02 08:16:57 +08:00
AskaEth c730333776 fix(launcher): §310 追加两修——未冻结App锁屏输入穿透(独占触控) + 主界面应用名截断
真机 M6.3 反馈(bcef8e0 三连修复未好全,追加两问题):

P1 锁屏 PIN 输入穿透仍在(媒体保活 App 实时读 evdev)
  根因:媒体保活 App(播放中)从不 SIGSTOP(保 PCM),SDK 输入线程实时读 evdev,不走缓冲。
  bcef8e0 的「SIGCONT 排空」只作用于冻结 App;对未冻结 App,隔离全靠 /tmp/meow_notif_active
  让 SDK 排空——若 App 的 meow_ui.a 缺该排空(或节流窗内漏网),锁屏期触摸依旧抵达 App。
  修法:run_lock_screen() 与 lck_input_pin_modal() 打开 DEV_TOUCH 后 EVIOCGRAB 独占触控设备
  (真机 goodix 实测 EVIOCGRAB 返回 0)——抓取期事件只投递抓取者、不为其它 fd 缓冲/回放,
  故**任何**前台进程(冻结或未冻结)锁屏期都收不到触摸(真全模态)。失败时记日志降级
  (仍靠标记+SIGSTOP 隔离)。overlay_gate.h 增 overlay_keepalive_needs_grab 判据。

P2 主界面应用名只显示 5 字(「流媒体客户」式,半字残形)
  根因:app_launcher.c `strncpy(a->name, name, 16)` 仍把显示名硬截 16 字节——M6.3 只扩了
  name[49]+json_str 整序列,漏改此二处。UTF-8 下 16B = 5 汉字 + 「端」首字节 + 无 NUL,
  显示成「流媒体客户」+ 残形;main_menu.c menu_name_fit 按字节回退又停在半截字符、加 "..." 溢出。
  修法:新增 meow_utf8.h(meow_utf8_char_len / meow_utf8_copy_bounded,纯决策可单测)——
  app_launcher.c 两处 strncpy(16) 改 app_name_copy(=copy_bounded, 拷满 sizeof name=49);
  menu_name_fit 改整字符前进 + 预留省略号宽度(mfont 用「…」/点阵用 "..."),总宽 ≤ maxw,
  绝不劈开多字节字符。

新增 test_utf8_name.c(14 断言:整字符长/整序列有界拷贝,含 cap=16/17/12 边界不劈字)+
  test_overlay_gate.c 扩展(S1b 未冻结 App 靠 EVIOCGRAB 隔离 4 断言)。launcher 全量宿主回归
  + SDK 叠加/状态栏/输入回归全 PASS;mipsel 交叉 -Wall -Wextra 0 warning。
md5 56dac860841c3884b4322707246e22af(/usr/bin 只读,待固件打包 M6.4;fw_content.conf 未动)。
2026-09-02 08:13:55 +08:00
AskaEth 67aa5fc7a8 feat(panel): overview 自校验加严——内嵌 NUL/非法 UTF-8/strlen≠n 全拦并 dump /tmp/overview_bad.json(与浏览器 JSON.parse 对齐) 2026-09-02 08:12:47 +08:00
AskaEth 7a405866af feat(panel web): 调试日志——api() 每请求计时/失败详录(NOT_JSON 附原始内容头 300B)+route 切换日志,控制台过滤 [mp] 2026-09-02 08:07:16 +08:00
AskaEth 908fc53805 feat(panel): /api/overview 服务端自校验——jv_parse 发出前自查,坏则 dump /tmp/overview_bad.json + 500(追查间歇性非 JSON 破页) 2026-09-02 07:56:04 +08:00
AskaEth 44a790dc1d fix(ncm §33): 流媒专项批六项——流式SIGSEGV防御日志/档位保真(无损级必须flac+显示档按实际)/封面4xx不重试/收藏显隐/缓存命名迁移/topbar位图图标
- §2① ncm_api.c level_attempt: 无损级(hires/lossless及以上)命中必须 type=flac,返回 mp3 视为该档不可用续降
  (修「hires 档静默给 mp3 被当命中」)
- §2② player_manager.c eff_level_for_resp: 显示档按响应实际格式/码率——mp3 绝不显示 Hi-Res(≤128k→标准, 否则极高),
  flac 采信链 eff; br 未知钳 ≤EXHIGH
- §1 流式 SIGSEGV(《十面埋伏》sig=11) 审计+UBSAN 探针未复现 → 落地防御日志(dl start/done/interrupt + play done fin/exp/fail/underrun)
- §3 cover.c: download_cover 回填 rc/status; 确定性 4xx(404等)不重试立即跳下一张, 仅瞬时错误退避(rc=%d status=%d 日志)
- §4 playlist.c: pl_show_fav 我创建(is_collected==0)隐藏收藏钮, 我收藏保留, 搜索歌单保守显示(评论槽并入无空洞)
- §5 ncm_cache.c 双点→单点迁移 + player_manager song_local_file 旧键→当前档位键(不重下)
- §6 home.c: topbar 动作 ⚙↻⌕ 迁移 sb_icons 位图(meow_topappbar_set_item_icon, 修 4k 字库豆腐)
- 测试: test_ncm_core 新 test_grade_flac_gate + test_cache 双点迁移断言; degrade_sim/player_flow_sim 桩 flac 化
- 验证: stream/player_flow/window/search/cache_evict/degrade sim 全 PASS + test_ncm_core host+mipsel(qemu) + mem_sim + build_ncm.sh 0 warning
- 新 ncm md5 cb818786 (text 1017110/bss 1362500), 未部署留主会话; 0 真实 NCM 业务请求
2026-09-02 04:20:46 +08:00
AskaEth 68ce46a5d8 fix(ncm §32): 内存瘦身修 OOM 被杀 —— 封面降采样(8.28MB→0.78MB) + 瞬态 rbuf 缩减 + 线程栈显式
真机 dmesg 实锤:OOM Kill ncm (score 460, anon-rss 26.9MB, 设备 56MB)。
画像:封面全分辨率 RGBA 8.28MB(1448x1448 原生解码驻留) 是最大可控块。

瘦身(按收益排序):
1. sdk meow_ui_img 新增纯增量 meow_img_downscale + cover.c cover_cap(≤480px)
   → 封面 8.28MB→0.78MB,-7.65MB(mem_sim 实测 PASS)。
2. ncm_api.c 瞬态响应 rbuf:song_url→64KB、lyric/song_detail/cloudsearch/user_playlist→256KB
   (detail/track_all 保 1MB)。
3. ncm_app_internal.h 新增 ncm_thread_create(显式 128KB 栈),替换全部 14 处 pthread_create。
4. 滑动窗口/meta 复核零回退(window_sim:608B/首,6000 首 280KB 恒定)。

验证:mem_sim 封面收益 PASS + host home/player 渲染 OK + stream_sim/player_flow_sim/
window_sim/search_sim/cache_evict_sim 全 PASS + test_ncm_core host+mipsel(qemu) PASS
+ build_ncm.sh -Wall -Wextra 0 warning。真机 scp 播放在跑确认(缓存曲,0 播放请求)。

新 ncm md5 44fa16fe(text 1015150/bss 1362500)。正式部署留主会话。
2026-09-02 03:43:42 +08:00
AskaEth 202caaf66b fw_content: M6.3 收编 launcher 136dc67c(309 设置页5s+310 锁屏三连) 2026-09-02 03:43:12 +08:00
AskaEth bcef8e092e fix(launcher,lock): §310 锁屏/叠加三连 bug——输入穿透·状态栏消失·App死亡残影
用户真机 M6.2 实测三症状,全部位于锁屏/通知中心叠加路径。根因与修法:

S1 锁屏输入穿透(PIN 触摸打到下层 App / 解锁后「启动奇怪界面」)
  根因:run_app_lock_overlay / run_app_notif_overlay 关闭路径先 unlink
  /tmp/meow_notif_active 再 SIGCONT App——App 被 SIGSTOP 冻结期间缓冲的 evdev
  触摸事件在解除瞬间被 SDK 输入线程在无隔离态回放成 App 内点击(穿透触发)。
  修法:反序——标记仍在时先 SIGCONT,让 SDK 输入线程排空冻结期缓冲事件 +
  EVIOCGKEY 对齐,等 OVERLAY_DRAIN_WINDOW_MS(300ms > SDK 200ms 节流) 再 unlink。

S2 解锁后状态栏消失(App 无状态栏全屏残留)
  根因:S1 的回放点击常把 App 导航进全屏页(状态栏随 app.json/fullscreen 隐掉);
  叠加关闭路径也未强制状态栏重同步。
  修法:解锁后 g_sb_mode_last=-1 + 立即 app_overlay_statusbar() 重叠加(不等 1s 慢刷)。

S3 App 异常死亡(OOM sig=9)残影——fb0 停 App 死帧、无状态栏、launcher 不重绘主屏
  根因:锁屏叠加(run_app_lock_overlay→run_lock_screen)阻塞于 lock_screen 内,
  App 叠加期崩溃不被感知(notif 叠加有 run_notif_center 的 proc_is_zombie 探测,
  锁屏独缺),launcher 卡在锁屏会话永不回 menu 重绘。
  修法:run_app_lock_overlay 置位 g_lock_overlay_pid,run_lock_screen 每圈
  proc_is_zombie 探测,App 死即中止锁屏(LCK_OVERLAY_RET_DIED)走统一退出路径
  (reap_wait 回收 + ams_status_valid + break → run_menu 重绘主屏含状态栏)。

新增 overlay_gate.h(纯决策,宿主可单测)+ test_overlay_gate.c(10 断言)+
test_lock_screen.c 扩展(4 断言 overlay-abort)。launcher 全量宿主回归 +
SDK 叠加/状态栏回归(overlay_suppress/sb_collapse/notif_open/notif_gesture/
sdk_fixes/sdk_input_keys)全 PASS;mipsel 交叉 -Wall -Wextra 0 warning。
md5 136dc67c086a9d75c0ad9c83d519ff0d(/usr/bin 只读,待固件打包;fw_content.conf 未动)。
2026-09-02 03:41:39 +08:00
AskaEth 3611cbbbde sdk: sb_icons 扩充动作图标 + TopAppBar 位图图标支持
TopAppBar 动作项此前用字体码点(⚙↻⌕)绘制,4k 字库无这些码点→豆腐。改走位图:
- sb_icons.h 追加 15 个 Material Symbols Rounded 动作位图(settings/refresh/search/
  play_arrow/pause/skip_next/skip_previous/arrow_back/close/add/check/lyrics/
  queue_music/download/heart),FILL=1 实心与状态栏一致;sb_icons[] 只追加(0-14 不变),
  动作索引 15-29。
- 生成脚本 tools/gen_action_icons.py(cairosvg svg→32x32 单通道 alpha,SVG 缓存
  icons_src/ 可复现、断网可跑)。
- meow_ui_gfx.c 抽取图标 blit 像素核心 icon_blit_px,新增 meow_gfx_blit_icon_ink
  (控件路径不标顶栏脏区);meow_gfx_blit_icon 状态栏路径行为不变。
- meow_ui_widget.c W_TOPAPPBAR 项支持位图模式:新 API meow_topappbar_set_item_icon
  (w, idx, icon_idx),绘制取主题 onSurface/按压向栏底色淡 12%,文本项行为不变;
  hit 用统一项宽。
- 公共头 widgets.h 加 MEOW_ICON_*(15-29) 枚举与 set_item_icon 声明;internal.h 声明
  meow_gfx_blit_icon_ink。
- 宿主测试(test_meow_ui_widgets)加 topbar 位图图标绘制/命中/按压变淡 + 状态栏 blit
  回归断言;test_umbrella 加 MEOW_ICON_* 编译期锁;MEOW_APP_SDK.md 补说明+索引表。
- 验证:宿主测试 ALL PASS(14项);交叉 zig 构建 0 warning;meow_ui.a 新 md5
  1d69cdae55ab5dde3a98f5e2124f3656。
2026-09-02 03:24:46 +08:00
AskaEth 41427fdcb3 launcher: 进设置页不再同步跑串行网络 popen 与逐套字体 sha256(点设置卡≥5s 修复)
- 设置页入口 s_net_sync_from_sys() 改为 toggle 同步(快)+异步 s_net_refresh_kick();
  wifi/bt 状态与列表由 run_settings_page 主循环逐步骤 s_net_refresh_pump() 填充
  (每步一个带超时 popen、~150ms 一步),draw 用 g_net_* 缓存,数据变化即 need_paint
  → 入口不再被 wpa_cli/bluetoothctl/hcitool 5 条串行 popen(各 1.2~2.5s 有界超时)拖住。
- 进设置页字体重扫 meow_font_scan_presets(0) 跳过逐套 sha256(gbk/full 套数 MB,
  逐套双 sha256 真机耗数秒,入口卡顿主因之一);完整性校验保留给启动/热插拔全量(verify=1)。
- s_net_refresh() 保留同步语义(kick+drain) 供通知中心等调用方;WiFi/BT 子页返回、
  网络下拉后改 kick(由主循环承担异步填充)。
- 设置入口加毫秒级分段日志(font rescan / net toggle-sync+kick / page shown)供真机取证。
- 交叉 -Wall -Wextra 0 warning;launcher 宿主测试全 PASS。launcher md5 fbc78c62
2026-09-02 03:18:36 +08:00
AskaEth 0294553096 reader(R2): EPUB/FB2/MOBI/CBZ 加载器落地
- rdsrc 统一文档源抽象:TXT/FB2/EPUB/MOBI/CBZ 都产出「UTF-8 段序列+目录+元数据+图片」,
  与 R1 rdtxt 段契约一致;book.c 改喂 rd_src(文本)或图页(CBZ)。
- EPUB:miniz 解 ZIP → 自写 rdxml 回调解析 OPF(spine/manifest)+NCX/nav → 正文 XHTML 用
  rdhtml 逐行粗解析(坏标签/未闭合/实体容错,不建 DOM),章节按 RDSRC_SEG_MAX 分片。
- FB2:rdxml 严格解析抽 section 段落 + base64 内嵌图;段题进正文+目录。
- MOBI/AZW3:vendor libmobi 最小调用面(mobi_init→load→parse_kf7/8→parse_rawml_opt→
  flow/resources),HTML 走 rdhtml 同款粗解析;LGPL-3.0 合规见 NOTICE(版权+全文+锁定 commit)。
- CBZ:miniz 解 ZIP → 自然序图片序列,rdimg(stb_image) 解码+降采样,阅读页图页模式。
- 目录显示与跳转(EPUB NCX/FB2 section/MOBI 标题);书架开放四格式;进度按
  (段,字符偏移)(TXT/FB2/EPUB/MOBI)/页号(CBZ)。
- 宿主单测 loaders_smoke(四格式抽取/目录/图片/base64/页序)+ qemu-mipsel
  formats_smoke/book_smoke;R1 test_reader_core 58/0 不回归。
- build_reader.sh 集成 miniz/libmobi/stb/zlib 头;NOTICE 入仓;交叉 -Wall -Wextra 0 warning。

新 reader md5: e29036599300eb277b1c960a75b65dbf
2026-09-02 03:11:55 +08:00
AskaEth 10690bc348 fix(ncm §31): 修两处 UI 数据竞态——返回首页行空白(staging发布) + 进第二个歌单显示上一歌单(换歌单清窗)
A. 返回首页各行 2~3s 空白:appstate_load_playlists 就地 memset(g_st.playlists[])
   与 home_src2 无锁逐行绑定竞态,刷新期间 playlist_count 保留旧值 → UI 读清零行。
   照搬 s_build[] staging 范式:网络落 s_pls[] → 成功后锁内原子发布(拷回+更新count),
   失败保留旧快照(断网离线浏览)。绝不就地清零 UI 可见数组。

B. 进第二个歌单显示上一歌单:playlist_open/refresh 同步路径不调 appstate_playlist_reset,
   pl_apply(1) 绑到上一歌单残留窗口(track_ids_count/songs)。
   新增窗口归属(歌单 id 唯一标识, 对搜索歌单同样成立): worker 首屏发布后
   appstate_playlist_window_set;refresh 目标≠归属(窗口is) → 同步 reset 再 pl_apply。
   同歌单手动刷新(id 同)保留旧内容(stale-while-revalidate)。

宿主回归:playlist_race_sim(新 F 并发读无清零态/G 开A→开B 不串)、window/search/
cache_evict/player_flow/stream_sim、test_ncm_core 宿主+mipsel 全 PASS;
build_ncm.sh -Wall -Wextra 0 warning;0 真实请求;未部署。
2026-09-02 03:03:48 +08:00
AskaEth 97b741cf56 fix(ncm): 播放路径接通 auto_av(300 的降级链接线,修「SQ 被跳过掉标准」真机路径) 2026-09-02 02:48:43 +08:00
AskaEth 33414de7c4 fix(ncm §20.3): 降级链账户/fee感知 auto_av —— 修「SQ 被跳过掉标准」(297)
根因:ncm_api_song_url_auto 无账户感知,依赖调用方按会员钳顶;若账户 VIP 态未就绪/
错钳到 EXHIGH,降级链从 EXHIGH 起步,LOSSLESS(无损 SQ) 被跳过,直接掉「标准」。
修法:新增 ncm_api_song_url_auto_av[_f](§20.3 权威形态):fee∈{1,4} 且非 CVIP →
NCM_ERR_VIP 零请求;按 account_vip 自钳顶(NONE→EXHIGH/CVIP→HIRES/SVIP→SURROUND);
只试账户可访问档(ncm_api_level_gate<=vip);落在最近可用档。原 auto/auto_f 行为零回归。
逐级尝试重构为共享 level_attempt(type/url 接受+静默降档采信)。
测试(bench/degrade_sim.c):fee门禁5例 + auto_av矩阵 vip3×desired9×avail9=243例全PASS
+ 真机复现(CVIP+Hi-Res+有SQ无HiRes→落无损SQ flac);原90例零回归。
验证:test_ncm_core_host+qemu-mipsel 全PASS;build_core/build_ncm -Wall -Wextra 0 warning。
新 ncm md5 1064a1d686390cc159f18296ee2980ee(未部署,留主会话)。
遗留:player_manager.c 仍调 auto(不传vip/fee),应改请 auto_av(account_vip()+fee);
真机若仍掉标准需另查旧缓存 song_<id>_hires.mp3 复用或旧二进制。
2026-09-02 02:41:09 +08:00
AskaEth 55f0dfe91d M6.2 备料: S89 amsd.conf 热更 exec→/usr/bin 迁移; fw_content 收编 launcher 03dfcf76(锁屏+门控+名字)/amsd 026cad52(UTF-8 名字)/S89 a1ef9d65 2026-09-02 02:39:11 +08:00
AskaEth 54857bc0fd sdk(ui): 字符串资源外置(i18n 雏形 §13)—— meow_str_* + 内嵌双语表 + TF 覆盖表 + 控件接入
公开 SDK 前把 SDK/App 硬编码文案外置:新增 meow_str/meow_strf/meow_str_set_locale/
meow_str_locale,按当前 locale 取串(永不 NULL),第三方开发者可做多语言。

- 新增 include/meow_ui_str.h + meow_ui_str.c:取串优先级 = TF 覆盖表 > 内嵌当前语言
  (en_us→en 其余→zh) > 内嵌内置默认(zh_cn) > 原样返回 id。内嵌双语表(common.* 21 条 +
  ime.* 9 条);热路径零 malloc(编译期静态表 + ≤256 静态覆盖数组);纯 libc 宿主可单测。
- locale 存系统设置 settings.conf 的 ui.locale(默认 zh_cn,首次调用惰性读取);
  meow_str_set_locale 即时切换 + 重载覆盖表 + best-effort 持久化(流式改写保留其它行)。
- TF 覆盖表 MeowData/<pkg>/strings/<locale>.txt(id=text 行,UTF-8,'=' 两侧去空白);
  无卡/无文件/无该 id → 回落内嵌。meow_strf 用调用方缓冲(snprintf 语义,重入安全)。
- SDK 控件接入:dialog 默认按钮 OK/CANCEL + INPUT 占位、IME 键面/徽标(空格/确定/拼英/
  ?123/清/拼音/(无候选)/中)改走 meow_str;空态/加载态给 App 提供 common.no_data/loading。
- 测试:新增 test_meow_ui_str.c(内嵌回退/TF 覆盖优先级/未知 id 回退/切 locale 即时生效/
  查找正确性/meow_strf,tmp+env 两模式);全量宿主回归(widgets/dispatch/box/anim/scroll/
  listvirt/theme/ime_fix/pinyin/overlay/notif/sdk_input_keys/p1p2p3/config/vol/sb_collapse/
  notify_*) 0 回归;交叉 zig-mipsel -Wall -Wextra 0 warning。
- 文档:MEOW_APP_SDK.md 新增 §13(字符串资源/i18n,遗留顺延为 §14);docs/APP_DEV_GUIDE.md
  新增 §7.11。各宿主 test_*.c 头注释补 meow_ui_str.c 编译依赖。

边界(§13.7):仅 zh_cn/en_us 整串取用;不做复数规则 / BiDi / RTL / 动态字体回退(雏形)。
2026-09-02 02:37:38 +08:00
AskaEth d7bf62f448 fix(meowpanel §UTF-8): JSON 输出 UTF-8 加固——sA_str 统一消毒非法/截断字节,防任一上游坏字节拖垮整页
事故:amsd 的 am list 把「流媒体客户端」(18B) 截成 16B,腰斩「端」字(E7 AB AF→仅剩 E7) →
面板 ams_fill 把非法 UTF-8 嵌进 /api/overview → 浏览器 JSON.parse 拒收(HTTP 200 非 JSON)。
amsd 侧已修(8588a6b),面板侧自此防住任一上游再产坏字节,一个源的坏数据不拖垮整页。

- meowpanel.c: 新增 utf8_seq_len/utf8_seq_ok/utf8_valid_n/utf8_sanitize(C 无依赖);sA_str 收口为
  sA_str_n:逐字节校验 UTF-8,合法序列透传、非法/截断逐字节回退 '?'(保持长度);纯 ASCII 单遍直通。
- 覆盖点(全部经 sA_str/sA_str_n):ams_fill(pkg/name)、svcd_fill(name/exec/state/...)、audio_fill(app/fmt/route_mode)、
  /api/apps(app.json name/pkg/ver/exec)、字体名、通知字段、崩溃/日志中心字段、设置/主题串等。
- 两处日志内联转义(api_net_log、api_logs_read)改走 sA_str_n,日志行同样消毒。
- 原始 IPC JSON(perf/power/net,含 ssid)先 utf8_valid_n 校验:坏字节时 perf/power/net/status 降级
  available:false / 503,不嵌坏字节(api_overview 首页生命线不受影响;api_system network 段坏字节回退 hostname_local)。
- 宿主自测 `--selftest`:喂「流媒体客户\xE7」给 utf8_sanitize/sA_str/ams_fill 桩,断言 JSON 完整可解析 + 无非法字节,
  且不误改完整合法名「流媒体客户端」;`meowpanel --selftest` 通过。
- 验证:build_meowpanel.sh host / 交叉均 -Werror 0 warning;真实 ams_fill 桩复现事故 → 「流媒体客户?」JSON 合法。
- 后端 meowpanel(mipsel) md5: 820b24541ed69f2e27e4a301aff10c98(README 已校正)
2026-09-02 02:32:25 +08:00
AskaEth 3397a702aa fix(ncm §30): 真机四连症状——JSON unescape + 封面流式 + 歌单豆腐/分隔符 tofu + 首屏诊断日志
症状/根因/修法(0 真实 NCM 业务请求;宿主+qemu 全绿):
- ③ LRC 挤一行/时间戳未解析:ncm_json_get_str_at 不做 JSON 转义还原,
  lrc.lyric 的 \n 转义原样进串 → lrc_parse 无真实换行整段一行。修:ncm_json.c 加
  json_unescape(RFC8259 全转义 + \uXXXX/代理对),get_str_at 返回前还原。
- ⑤ 封面全 failed→give up:cover.c 静态 g_buf 288KB < 封面 1.34MB → NCM_ERR_FULL。
  设备 RAM 仅 56MB。修:cover.c 改流式写文件(ncm_http_download cb→ncm_cache_write +
  meow_img_load_file 临时文件),NCM_COVER_MAX 8MB 改下载上限(非缓冲,bss 未涨)。
- ① 162 首歌单所有条目「三个豆腐」+「加载中」:占位符 ···(U+00B7)在 default 字体缺
  该字形 → 3 豆腐(font.idx glyph 扫实证 U+00B7 MISSING)。修:占位 ···→...、全 App
  · 分隔符→/;playlist_worker 首屏打 first-screen 诊断日志。
- ② 返回首页歌单列表 1 秒方框:字体缺 U+00B7/特殊字形(◢◤/Kannada)tofu;瞬态疑 glyph
  atlas 冷缓存(SDK 内部未深挖)。修:·→/。
验证:test_ncm_core(+test_json_unescape, host+qemu) / listvirt44 / dispatch / box42 /
scroll17 / anim32 / widgets / overlay_suppress / sdk_input_keys / theme / vol / ime_fix /
pinyin / notif_gesture / notif_open / sdk_fixes / sb_collapse / ui_audio_host / notify_ipc /
notify_integration + playlist_race_sim / window_sim / search_sim / cache_evict_sim(1-9) /
player_flow_sim(P1-12) / stream_sim(16+2resume) 全 PASS;mipsel -Wall -Wextra 0 warning。
新 md5:ncm d91cd906、ncm_host b731654a、test_ncm_core_host 7a38194c。

(症状④ VOL_DOWN×3 杀 App 的 launcher 源修复 app_launcher.c 门控 !a->framework 已随
 并发 commit 54a6e82 存入 HEAD;launcher 二进制 03dfcf76 留主会话/固件打包。)
注:build_ncm_host.sh 补 SDK 292/295 的 anim/box/scroll 源(宿主链接)。
2026-09-02 02:25:37 +08:00
AskaEth 54a6e828b7 fix(launcher): app 显示名缓冲 name[17]→[49] + json_str 截断 UTF-8 整序列保护(同 amsd 修复,M6.2 备料 launcher 03dfcf76) 2026-09-02 02:20:06 +08:00
AskaEth 8588a6b453 fix(amsd): app 显示名 name[17]→[49] + UTF-8 整序列截断(utf8_trim_incomplete)——修「流媒体客户端」18 字节被砍成 16 致 am list 输出非法 UTF-8、面板 /api/overview 被浏览器 JSON.parse 拒收(非 JSON 响应) 2026-09-02 02:15:19 +08:00
AskaEth 9d54cf89c5 sdk(ui): W_LISTVIEW 虚拟化层 — 固定 item 池 + 多行富 item + 完全自绘 (§5.5)
在既有 W_LISTVIEW (src2 每帧取行) 之上叠加虚拟化层 (API 追加式, 旧 API 一字不改):
- 数据源 count_fn + bind_fn (index, meow_lv_item*, ctx); count 每帧实时查 (任意长度≥65535,
  不常驻 item 对象); bind 仅在行进入视口时被调一次
- 固定 item 池: 视口行数+2 静态槽 (有界 ≤96), 回滚不重绑 (同 index 命中同槽); 整表扫过后
  wrap 回收合法但每次 draw 有界 (≤视口窗口)
- 多行富 item: 主标题/副标题/左图标·缩略图/右尾件; 行高 set_item_h(px) 或 set_item_tier(1→48/2→56);
  默认 renderer 主题语义色绘制; set_item_draw 完全自绘; section 段头占位行(非粘性); 空态占位
- 集成: tap_at→meow_ui_focus_acquire (§6.4); meow_scroll_wrap(lv,1) track+fling+snap(行边界);
  选中/按压态走主题; enabled=0 变淡不响应
- 兼容: src2==NULL 走既有路径; W_LIST/W_LISTVIEW 单行用法零改动

验证(宿主): 新测试 test_meow_ui_listvirt T1-T5 全 44 PASS (10000 项滚动窗口内容正确/hit 映射/
bind 有界=count/回滚不重绑/多行渲染/截断/图标占位/段头/空态/自绘/焦点/fling 吸附);
全量回归 widgets/dispatch/box/anim/scroll/ime/pinyin/overlay/notif/sdk_input_keys/p1p2p3 全 PASS;
交叉 zig-mipsel -Wall -Wextra 全 SDK TU 0 warning; meow_ui.a 新 md5=2a2d8000b95dd211d09dc736d5538ad0

文档: MEOW_APP_SDK.md §5.5 同步虚拟化层(API 一览/池语义/集成/回归).
2026-09-02 01:36:48 +08:00
AskaEth 85e1d03157 feat(panel): 锁屏一次性解锁端点 POST /api/system/pin-unlock-once(写 /tmp/meow_pin_unlock_once,launcher 锁屏页消费放行一次)+ 设置页 PIN 卡「一次性解锁设备」按钮 2026-09-02 01:01:54 +08:00
AskaEth 54d2791f48 sdk: 事件分发形式化(§6.4)—— 统一命中/捕获/消费/层间隔离/焦点
根治「焦点/事件穿透」一类反复 bug。此前命中/捕获/消费/层间隔离各处 ad-hoc;
现上收为单一仲裁者(meow_ui_input.c),公共 API 只追加、不删改既有签名。

分发模型:
- 触摸沿 z 序自顶向下命中(meow_draw_hit_topdown,owner==active+enable 过滤);
- 命中即消费;模态层永远先审(meow_ui_modal_begin/end/active/depth);
- down 捕获(meow_ui_gesture_begin/owner/end):命中目标捕获手势直到 up,防滑出误触下层;
- 模态存在时下层完全收不到事件——hit_topdown 恒返回模态哨兵(背板消费,不透传);
- meow_ui_run 在 TOUCH_DOWN 自动 begin、TAP/SWIPE/LONG_PRESS/NOTIF_PULL 自动 end。

焦点模型:
- 唯一持有者(meow_ui_focus_acquire/release/owner/tap);
- 点非 focus 区域→释放并通知(meow_ui_focus_tap,list 焦点残留根治);
- 滚动容器(list/listview)tap_at 命中行自动 acquire,点外由 run 的 focus_tap 释放;
- lost 回调(meow_ui_focus_set_lost_cb)通知转移。

迁移(行为修复,正常交互语义不变):
- dialog/sheet → meow_ui_modal_begin/end(模态期下层收不到;叠黑由既有整帧快照+卡片仅重绘保证);
- list/listview tap → meow_ui_focus_acquire;
- 注入/叠加让位(overlay_input_suppressed)与模态层隔离互补,语义不变。

验证:新穿透矩阵 test_meow_ui_dispatch(M1 模态点下层不触发 / M2 弹层叠开两层层隔离 /
M3 捕获手势滑出不误触 / M4 list 焦点点外释放)ALL PASS;
全量回归 widgets/ime_fix/pinyin/overlay_suppress/notif_gesture/sdk_fixes/sb_collapse/
p1p2p3_repro/box/anim/scroll/sdk_input_keys 全 PASS;交叉 -Wall -Wextra 0 warning。

meow_ui.a 新 md5:a9fcfb6eeb07ddbdd48039df4f8f18ce(主会话统一重链,本仓未重链 App)
2026-09-02 00:57:58 +08:00
AskaEth c3abc3fee4 feat(launcher,lock): 锁屏补充三定案—面板一次性解锁恢复口 / 设置页 PIN 管理 / 电源菜单主动锁强化
- 面板一次性解锁恢复口:/tmp/meow_pin_unlock_once 存在即被锁屏页消费删除并放行一次
  (不校验 PIN、不清 system.pin、不重置失败计数;重启标志自然消失;lck_unlock_once_consume,
  launcher 侧只做检查/消费,panel 端点由主会话另实现)。
- 系统设置「安全 → 锁屏 PIN」页(lock_settings.c,subpage.c 脚手架):状态(未设置/已设置/
  锁定中+剩余)/ 设置(4 位双输确认)/ 修改(需旧 PIN 一次)/ 清除(**免旧 PIN**,仅二次确认弹窗)
  / system.pin_lock_on_wake 开关;数字输入用 SDK 按钮键盘(lck_input_pin_modal)。
- 电源菜单「锁定」主动锁强化:立即熄屏 + 写 /tmp/meow_pin_locked(主动锁标志,重启消失,
  唤醒时无论 pin_lock_on_wake 是否开都必锁屏)+ rm /tmp/meow_pin_unlock_once 作废挂起绕过;
  lck_wake_should_lock() 作为唤醒门取代 lck_lock_required(1)(主菜单 2 处 + App 会话 2 处)。
- 测试:test_lock_screen 扩 51 ok——bypass 存在即消费/不存在不影响/消费后删除;清除免旧 PIN;
  主动锁标志唤醒必锁/清除后回退;全回归 settings_brightness/notif_panel/notif_tf/vol_ramp_jack 无碍;
  交叉 -Wall -Wextra 0 warning。meow_launcherd md5 bdf884756ef8a8353aa8e5dfb6e10a0a。
- SYSTEM_SETTINGS.md 同步锁屏行为段。
2026-09-02 00:57:17 +08:00
AskaEth e948a0a44e feat(launcher,lock): MeowOS 锁屏 4 位 PIN(system.pin 同源面板,错5锁5分钟持久化,唤醒/电源菜单手动锁)
- system.pin:4 位数字 PIN,sha256+salt 存 settings.conf(格式与面板 panel.pin 全等,绝无明文)。
  panel.pin 已设且 system.pin 未设时锁屏接受 panel.pin,首次验证成功后并入 system.pin。
- 锁屏时机:息屏唤醒后(默认开,system.pin_lock_on_wake=1 可关)+ 电源菜单「锁定」手动锁;
  开机不锁(boot 进主屏不拦)。
- 锁屏页:launcher 渲染系统级全屏页,App 不可见不可触;SDK 按钮画数字键盘(不调 IME),
  输入 4 位自动校验;● 遮罩不回显数字;错 5 次锁 5 分钟(持久化锁定戳/计数,重启不清)。
- 安全细节:锁屏页电源键=息屏(允许再睡),音量键不动,不响应左缘返回/通知中心手势。
  兜底:SSH root 删 system.pin 键即解锁(无其它后门)。HibyOS 不涉及。
- 宿主测试(test_lock_screen):设置/校验/错5锁定持久化(重载模拟重启)/唤醒触发/开机不锁
  /panel.pin 迁移,全 PASS;既有 settings_brightness/notif_panel/notif_tf/vol_ramp_jack 回归
  无碍;交叉 -Wall -Wextra 0 warning。meow_launcherd md5 670f978e71c1e81cfe86d47c21248c9d。
2026-09-02 00:48:23 +08:00