真机 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 未动)。
57 lines
3.6 KiB
C
57 lines
3.6 KiB
C
/* overlay_gate.h — SIGSTOP 叠加会话(通知中心 §10.5 / 锁屏 M2.x)关闭与死亡回退的**纯决策**。
|
||
*
|
||
* 宿主可单测(无信号/无设备/无文件系统依赖,全部 static inline);app_launcher.c 的两处叠加
|
||
* 关闭路径(run_app_notif_overlay / run_app_lock_overlay)调用,避免把「排空窗口」「中止条件」
|
||
* 这类时序/判定散落内联难验证。三个 bug 的定案语义都收敛到这里:
|
||
*
|
||
* ① 输入穿透(S1 根因):App 被 SIGSTOP 冻结过 → 关闭时必须在 /tmp/meow_notif_active 仍存在
|
||
* 时先 SIGCONT,让 SDK 输入线程(meow_ui_input.c overlay_input_suppressed)排空冻结期缓冲的
|
||
* evdev 事件副本 + 对齐 EVIOCGKEY,再等 OVERLAY_DRAIN_WINDOW_MS 后 unlink 标记。
|
||
* 若反序(unlink->SIGCONT,改动前写法),App 在无隔离态恢复 → 解冻瞬间把积累的触摸回放成
|
||
* App 内点击(锁屏穿透 /「启动奇怪界面」/ 解锁后状态栏消失的触发源)。
|
||
* ② 状态栏恢复(S2):解锁后强制 g_sb_mode_last=-1 让 app 循环立即重叠加,不等 1s 慢刷。
|
||
* ③ 死亡重绘(S3):锁屏叠加中 App 崩溃(/proc/<pid>/stat==Z)→ 中止锁屏走统一退出路径,
|
||
* 由 waitpid 循环回收 + run_menu dirty=1 重绘主屏(含状态栏)。
|
||
*/
|
||
#ifndef MEOW_OVERLAY_GATE_H
|
||
#define MEOW_OVERLAY_GATE_H
|
||
|
||
/* SDK overlay_input_suppressed() 的标记存在性节流窗是 200ms;排空窗须 > 该值(留 100ms 余量),
|
||
* 保证 App 恢复后 SDK 输入线程确实重新 stat 到标记再整批丢弃缓冲事件。 */
|
||
#define OVERLAY_DRAIN_WINDOW_MS 300
|
||
|
||
/* ① 排空是否必要:App 被 SIGSTOP 冻结过(非保活)才需要「SIGCONT 保持隔离 → 排窗 → unlink」;
|
||
* 媒体保活(keep_running,从未 STOP)直接「恢复帧上屏 → unlink」(自抑随标记消失自然解除)。 */
|
||
static inline int overlay_drain_required(int keep_running)
|
||
{
|
||
return !keep_running ? 1 : 0;
|
||
}
|
||
|
||
/* ③ 锁屏叠加中 App 崩溃是否触发「统一退出路径」(= 中止锁屏、交回 waitpid 循环回收、run_menu 重绘)。
|
||
* proc_zombie=1(/proc/<pid>/stat==Z)→ 走退出(返回 1);否则正常恢复(返回 0)。 */
|
||
static inline int lock_overlay_app_died_exit(int proc_zombie)
|
||
{
|
||
return proc_zombie ? 1 : 0;
|
||
}
|
||
|
||
/* ② 解锁后是否需要强制状态栏重同步(返回 1):始终需要——把 g_sb_mode_last 拨回 -1,
|
||
* 使 run_menu / app 循环的「模式变化→立即重叠加」分支命中(-1 != m 恒真除非 m==-1,
|
||
* 但 m==-1 表示无模式文件=展开态,同样被 app_overlay_statusbar 兜底到展开整条)。 */
|
||
static inline int overlay_force_sb_resync(void)
|
||
{
|
||
return 1;
|
||
}
|
||
|
||
/* 未冻结(媒体保活,keep_running)App 是否**需要 EVIOCGRAB 独占隔离**(返回 1)。
|
||
* §310 问题1真根:媒体保活 App 从不 SIGSTOP(保 PCM),SDK 输入线程**实时读 evdev**(不走缓冲),
|
||
* 标记(/tmp/meow_notif_active)让 SDK 排空只在有该新 SDK 的 App 上生效;launcher 侧可**无条件**
|
||
* 用 EVIOCGRAB 独占触控设备,使包括保活 App 在内的**任何**前台进程在锁屏期收不到触摸(且抓取期
|
||
* 事件不为未抓取 fd 缓冲/回放)。keep_alive=1 → 隔离靠 grab(overlay_drain_required==0,无
|
||
* SIGCONT 排空语义);冻结 App(keep_running=0)→ 隔离靠 SIGSTOP+SIGCONT 排空(drain_required==1)。 */
|
||
static inline int overlay_keepalive_needs_grab(int keep_running)
|
||
{
|
||
return keep_running ? 1 : 0;
|
||
}
|
||
|
||
#endif /* MEOW_OVERLAY_GATE_H */
|