Files
MeowOS-For-R3P2/patch_v2/meow_launcherd/overlay_gate.h
T
AskaEth 986e3814bc fix(launcher,lock): §310 M6.7 锁屏页自睡——空闲超时自动灭屏(294 遗留补)
背景:锁屏页(run_lock_screen)此前常亮不灭屏——用户停在锁屏页不操作,屏幕一直亮着耗电。
M6.6 上机后用户反馈,补 294 遗留项「锁屏页未做空闲超时自动息屏」。

实现(/usr/bin 只读,待 M6.7 固件打包,fw_content.conf 未动):
- run_lock_screen 循环加空闲跟踪(last_act)+ 自睡状态(asleep):
  ① 阈值 = overlay_lock_idle_off_sec(screen_off_timeout) = min(系统 screen_off_timeout, 30s)。
     系统未设/设 0(常亮)/超 30 → 锁屏页封顶 30s(锁屏页不应常亮耗电);系统设更短 → 尊重更短。
  ② 活跃态空闲超阈值 → meow_panel_off()(与息屏路径一致:panel 模式 FBIOBLANK 4 挂起 goodix /
     black 模式仅背光 0)+ asleep=1 —— 锁态保持,仍留在锁屏循环(=「锁屏页自己也会睡」)。
  ③ asleep 后电源键按下边沿 或 触摸活动 → meow_panel_on() + lk_draw 重画锁屏页(本循环唤醒链
     回锁),输入活动(任意按键 change / 触摸)都重置 last_act。
  ④ 音量键本页不动,仅计入输入活动重置计时;自睡期面板已关,不重绘(唤醒时统一重画)。
- EVIOCGRAB 与灭屏交互(核对结论):灭屏期 grab **保持**(tfd 不关)。panel 模式 FBIOBLANK 4
  挂起 goodix → 灭屏期无触摸事件,唤醒只走电源键;black 模式触摸仍活动且被抓取者(launcher)独占
  → 唤醒第一下触摸进锁屏(不穿透 App、不被吞——被锁屏作为活动消费,可能命中 PIN 键)。唤醒后
  FBIOBLANK 0 + grab 仍在,全程无穿透。
- App 前台叠加锁屏(run_app_lock_overlay)期间 App 的 /tmp/meow_notif_active 标记在整个自睡/
  唤醒周期保持(仅锁屏退出才 unlink),故媒体保活 App 自睡期仍被 present 抑制,不覆盖锁屏。

overlay_gate.h 增 overlay_lock_idle_off_sec / overlay_lock_should_sleep / overlay_lock_wake_now
(纯决策,可单测)。test_overlay_gate.c 扩展 S4(12 断言:阈值 tradeoff / 超时灭屏 / 唤醒回锁屏 /
屏幕关不重睡)。launcher 全量宿主回归 + SDK 叠加/状态栏/输入回归全 PASS;mipsel 交叉 -Wall -Wextra
0 warning。md5 42b6633afde37035585fc36b074a73c6(待 M6.7 固件打包,不部署)。
2026-09-02 13:35:56 +08:00

94 lines
5.7 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* 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;
}
/* 锁屏进场后「重铺全屏不透明底」的阈值(ms)。SDK present 抑制标记节流窗(MEOW_OVERLAY_CHK_MS)
* 是 200ms——媒体保活 App 不冻结、锁定瞬间还会进 1-2 帧(部分脏区盖到锁屏上)。阈值取 300ms
* (> 200ms),保证覆盖到抑制窗内 App 的残帧;App 此后被抑制不再上屏,锁屏稳定遮盖。
* 由 lock_screen_ui.c 的 run_lock_screen 重铺逻辑使用(单测同源断言)。 */
#define OVERLAY_LOCK_COVER_MS 300
/* 唤醒是否应触发锁屏(§310 M6.5 问题1):超时息屏(meow_auto_slept)与电源键手动息屏(watchdog
* 直接 blank 面板、背光 0 → launcher 检测得 app_panel_manual_off)两类唤醒都须走 lck_wake_should_lock
* 语义——真机实测「App 内电源键手动息屏→亮屏无锁屏」(手动路径丢了锁屏触发、超时路径接了)。 */
static inline int overlay_wake_should_lock(int auto_slept, int manual_panel_off)
{
return (auto_slept || manual_panel_off) ? 1 : 0;
}
/* 锁屏页自睡阈值(秒,§310 M6.7,294 遗留):min(系统 screen_off_timeout, 30s)。
* 系统未设/设 0(常亮)/超 30 → 锁屏页封顶 30s(锁屏页不应常亮耗电);系统设更短 → 尊重更短。
* 返回正数秒。lock_screen_ui.c 的 run_lock_screen 空闲超时用它(单测同源断言)。 */
static inline int overlay_lock_idle_off_sec(int screen_off_timeout)
{
return (screen_off_timeout > 0 && screen_off_timeout < 30)
? screen_off_timeout : 30;
}
/* 锁屏页是否应自睡(§310 M6.7):屏幕亮(meow_screen_on)且在本循环 && 空闲(now-last_act) ≥ 阈值。
* 返回 1=超时灭屏(锁态保持)。 */
static inline int overlay_lock_should_sleep(int screen_on, unsigned long long idle_ms,
unsigned long long off_ms)
{
return (screen_on && idle_ms >= off_ms) ? 1 : 0;
}
/* 锁屏自睡后应否唤醒回锁屏页:电源键按下边沿 或 触摸活动。返回 1=唤醒(meow_panel_on+重画锁屏)。 */
static inline int overlay_lock_wake_now(int pwr_edge, int touch_ready)
{
return (pwr_edge || touch_ready) ? 1 : 0;
}
#endif /* MEOW_OVERLAY_GATE_H */