diff --git a/patch_v2/meow_launcherd/lock_screen_ui.c b/patch_v2/meow_launcherd/lock_screen_ui.c index f61a348..3402d8c 100644 --- a/patch_v2/meow_launcherd/lock_screen_ui.c +++ b/patch_v2/meow_launcherd/lock_screen_ui.c @@ -164,6 +164,15 @@ int run_lock_screen(void) int unlocked = 0; unsigned long long entry_ms = now_ms(); int covered_once = 0; /* §310 问题2-②:标记节流窗后重铺一次全屏底,盖掉 App 残帧 */ + /* §310 M6.7 锁屏页自睡(294 遗留):锁屏页不应常亮耗电。 + * 阈值 = min(系统 screen_off_timeout, 30s):系统未设/设 0(常亮)/超 30 → 锁屏页封顶 30s, + * 系统设更短则尊重更短。超阈值 → meow_panel_off()(与息屏路径一致)+ asleep=1(锁态保持, + * 仍留在锁屏循环);asleep 后电源键按下边沿/触摸活动 → meow_panel_on() + 重画锁屏页回锁。 */ + int lk_off_sec = overlay_lock_idle_off_sec(screen_off_timeout); + unsigned long long lk_off_ms = (unsigned long long)lk_off_sec * 1000; + unsigned long long last_act = now_ms(); + int asleep = 0; + int prev_pwr_down = 0; for (;;) { time_t now = time(NULL); int redraw = 0; @@ -179,7 +188,7 @@ int run_lock_screen(void) /* §310 问题2-②:媒体保活 App 不冻结、SDK present 抑制有 ≤200ms 标记节流窗——锁屏首扑后 * App 仍可能再进 1-2 帧(部分脏区盖到锁屏上)。等标记窗过后(≥300ms)重铺一次全屏不透明底 * 盖掉 App 残帧;App 此后被抑制不再上屏,锁屏稳定遮盖(真机「App 控件盖到锁屏上」)。 */ - if (!covered_once && now_ms() - entry_ms >= OVERLAY_LOCK_COVER_MS) { + if (!covered_once && !asleep && now_ms() - entry_ms >= OVERLAY_LOCK_COVER_MS) { covered_once = 1; logmsg("lock: re-cover full opaque after marker window (app stave suppressed)"); lk_draw(entered, status, lock_until); @@ -212,23 +221,58 @@ int run_lock_screen(void) redraw = 1; } - /* 电源键=息屏(允许再睡);音量键本页不动 */ - if (kp_power.ok) { - kp_poll(&kp_power, NULL, NULL); - if (kp_is_down(&kp_power, KEY_POWER)) { - logmsg("lock: power key -> screen off (stay locked)"); - meow_panel_off(); - break; /* return 0 */ + /* 电源键/音量键轮询 + 输入活动检测(重置自睡计时) + 自睡/唤醒切换。 + * 活跃态:电源键按下 → 息屏并退出锁屏(回 App/主屏,下次唤醒再锁)——沿用原语义; + * 空闲超 lk_off_ms → 自睡(asleep=1,锁态保持,仍在本循环)。 + * asleep:电源键按下边沿 / 触摸活动 → meow_panel_on + 重画锁屏页(本循环唤醒链回锁)。 + * 音量键本页不动(仅视为输入活动,重置计时)。 */ + { + int chg = 0; + if (kp_power.ok) chg |= kp_poll(&kp_power, NULL, NULL); + chg |= kp_poll(&kp_keys, NULL, NULL); + if (chg) last_act = now_ms(); /* 任意按键活动重置自睡计时 */ + int pwr_down = kp_is_down(&kp_power, KEY_POWER); + int pwr_edge = pwr_down && !prev_pwr_down; /* 按下边沿 */ + prev_pwr_down = pwr_down; + + if (asleep) { + int touch_ready = (tfd >= 0); + if (touch_ready) { + struct pollfd tp = { tfd, POLLIN, 0 }; + if (poll(&tp, 1, 0) <= 0) touch_ready = 0; + } + if (pwr_edge || touch_ready) { + logmsg("lock: wake from self-sleep (power=%d touch=%d)", pwr_edge, touch_ready); + meow_panel_on(); + asleep = 0; + last_act = now_ms(); + lk_draw(entered, status, lock_until); /* 重画锁屏页回锁 */ + continue; + } + } else { + /* 电源键=息屏(允许再睡;下次唤醒按 lck_wake_should_lock 再锁) */ + if (pwr_down) { + logmsg("lock: power key -> screen off (stay locked)"); + meow_panel_off(); + break; /* return 0 */ + } + /* 空闲超时 → 自睡(锁态保持,仍在锁屏循环,唤醒回锁屏页) */ + if (meow_screen_on && now_ms() - last_act >= lk_off_ms) { + logmsg("lock: idle %ds -> self screen off (stay locked)", lk_off_sec); + meow_panel_off(); + asleep = 1; + continue; + } } } - kp_poll(&kp_keys, NULL, NULL); (void)kp_is_down(&kp_keys, KEY_VOLUMEDOWN); (void)kp_is_down(&kp_keys, KEY_VOLUMEUP); - /* 触摸:只认键盘 tap(滑动手势忽略:不左缘返回、不通知中心下拉) */ - if (tfd >= 0) { + /* 触摸:只认键盘 tap(滑动手势忽略:不左缘返回、不通知中心下拉);触摸即输入活动,重置自睡计时 */ + if (tfd >= 0 && !asleep) { struct pollfd pfd = { tfd, POLLIN, 0 }; if (poll(&pfd, 1, 0) > 0) { + last_act = now_ms(); /* §310 M6.7:任意触摸重置自睡计时 */ unsigned char ev[16]; while (read(tfd, ev, sizeof ev) == (ssize_t)sizeof ev) { uint16_t type = *(uint16_t *)(ev + 8), code = *(uint16_t *)(ev + 10); @@ -290,8 +334,8 @@ int run_lock_screen(void) } } - /* 整页重绘(锁屏低频交互,简单整页即可) */ - if (redraw) lk_draw(entered, status, lock_until); + /* 整页重绘(锁屏低频交互,简单整页即可);自睡(面板已关)期间不重绘(唤醒时统一重画) */ + if (redraw && !asleep) lk_draw(entered, status, lock_until); usleep(POLL_MS * 1000); } done: diff --git a/patch_v2/meow_launcherd/meow_launcherd b/patch_v2/meow_launcherd/meow_launcherd index 0a0e8d9..6edc939 100755 Binary files a/patch_v2/meow_launcherd/meow_launcherd and b/patch_v2/meow_launcherd/meow_launcherd differ diff --git a/patch_v2/meow_launcherd/overlay_gate.h b/patch_v2/meow_launcherd/overlay_gate.h index d7718cf..f887315 100644 --- a/patch_v2/meow_launcherd/overlay_gate.h +++ b/patch_v2/meow_launcherd/overlay_gate.h @@ -67,4 +67,27 @@ 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 */ diff --git a/patch_v2/meow_launcherd/test_overlay_gate.c b/patch_v2/meow_launcherd/test_overlay_gate.c index e87efdd..5f5cc53 100644 --- a/patch_v2/meow_launcherd/test_overlay_gate.c +++ b/patch_v2/meow_launcherd/test_overlay_gate.c @@ -15,6 +15,9 @@ * (watchdog blank → manual_panel_off)两类唤醒都须走 lock 语义。 * S2b 锁屏重铺盖 App 残帧 → OVERLAY_LOCK_COVER_MS:锁屏进场后重铺全屏不透明底的阈值必须 * > SDK present 抑制标记节流窗(200ms),盖住 App 抑制窗内的残帧。 + * S4 锁屏页自睡(294 遗留) → overlay_lock_idle_off_sec():阈值 = min(系统 screen_off_timeout, 30s) + * (0/超30→30,尊重更短);overlay_lock_should_sleep()/overlay_lock_wake_now() + * 判定超时灭屏(锁态保持)与唤醒回锁屏。 * * 编译运行(在 patch_v2/meow_launcherd 下,无其它依赖): * gcc -Wall -Wextra -o test_overlay_gate test_overlay_gate.c && ./test_overlay_gate @@ -63,6 +66,20 @@ int main(void) CHECK(overlay_wake_should_lock(0, 1) == 1, "S1c manual power sleep (manual) -> lock (was missing)"); CHECK(overlay_wake_should_lock(1, 1) == 1, "S1c both -> lock"); + /* ---- S4 锁屏页自睡(294 遗留):阈值 min(系统,30s),超时灭屏锁态保持,唤醒回锁屏 ---- */ + CHECK(overlay_lock_idle_off_sec(0) == 30, "S4 system 0 (never) -> lock caps 30s"); + CHECK(overlay_lock_idle_off_sec(-1) == 30, "S4 system absent -> lock caps 30s"); + CHECK(overlay_lock_idle_off_sec(30) == 30, "S4 system 30 -> 30"); + CHECK(overlay_lock_idle_off_sec(60) == 30, "S4 system 60 -> 30 (cap, shorter)"); + CHECK(overlay_lock_idle_off_sec(10) == 10, "S4 system 10 -> 10 (respect shorter)"); + CHECK(overlay_lock_idle_off_sec(1) == 1, "S4 system 1 -> 1 (respect shorter)"); + CHECK(overlay_lock_should_sleep(1, 30000, 30000) == 1, "S4 idle>=off & screen on -> self sleep"); + CHECK(overlay_lock_should_sleep(1, 29999, 30000) == 0, "S4 idle not yet"); + CHECK(overlay_lock_should_sleep(0, 99999, 30000) == 0, "S4 screen off -> no re-sleep"); + CHECK(overlay_lock_wake_now(1, 0) == 1, "S4 power edge -> wake to lock"); + CHECK(overlay_lock_wake_now(0, 1) == 1, "S4 touch -> wake to lock"); + CHECK(overlay_lock_wake_now(0, 0) == 0, "S4 no wake input -> stay asleep"); + /* ---- S3 App 死亡触发主屏重绘:崩溃必须走统一退出路径 ---- */ CHECK(lock_overlay_app_died_exit(1) == 1, "S3 app died -> unified exit path (redraw home)"); CHECK(lock_overlay_app_died_exit(0) == 0, "S3 app alive -> normal restore");