用户真机 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 未动)。
46 lines
2.8 KiB
C
46 lines
2.8 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;
|
||
}
|
||
|
||
#endif /* MEOW_OVERLAY_GATE_H */
|