fix(bootmenu): M23 评审 r2 — 电源键锁存取代「3s 抑制」,缺键视同不可信

P2-2(r2):删除「电源键按下后 3s 内不补」的定时抑制 —— 它到期就会把用户刚熄的屏点亮
(窗内可重复),且该行为被单测固定。改为**锁存**:扫描窗内一看到电源键按下边沿就置
scan_pwr_seen=1,本次窗口内此后一律不补(why="power-key-latched"),窗口结束才清零。
理由:Bug 4 保护的是「无人值守时媒体扫描导致黑屏几分钟」;用户已按键介入,需要亮屏时
自己再按一次即可。锁存同时覆盖「播放器只写 brightness=0 不改 bl_power」与「HibyOS 自动
超时熄屏」两种残余。

bl_power 门保留但降级为纯保险,注释改成诚实表述:据 patch_v2/meow_launcherd/backlight.c:90-95
实测,本机播放器熄屏(brightness 0 + FBIOBLANK 4)后 bl_power **仍为 0**,该门在播放器熄屏
场景不生效;真正的门是电源键锁存。(上一轮注释里的「播放器灭屏会置 bl_power>0」是反向推断,
已删。)

顺手关掉评审指出的竞态:亮度保底判定块从主循环前半(keypoll 之前)移到电源键边沿更新之后,
电源按下与播放器写 0 落在同一 poll 间隙时不会再出现一轮「没看到电源键就补亮」。

非阻塞 1(采纳):settings 文件存在但缺 display.brightness 键 → 返回 -1(视同不可信),
不再走 launcher 设置表的 101→100;否则扫描窗待机补 100 比老 bug 的 60 更亮。

单测(52 → 56 条):
- 删「power key expired -> floors」(把 bug 固定成期望的那条),换「latch 在窗口内永不过期」
  「下一轮窗口(锁存清零)恢复正常补」「latched 时面板暗也不写、why=power-key-latched」;
- 「missing key -> 100」改「missing key -> -1 (untrusted)」,并补 e2e「缺键 → saved=10 不是 100」;
- 两条名字去 degraded:`floor: saved 80 (from settings) floors at 80`、
  `hotkey: blank -> saved 60 (settings value)`(降级路径已封顶 10,80/60 只可能来自 settings)。

只交源码:不含二进制、不改 fw_content.conf、不动 build_bootmenu.sh。
This commit is contained in:
AskaEth committed 2026-11-11 18:42:41 +08:00
1 parent 8cd6e21cad
commit a9281c2d64
2 files changed
+133 -93

No files matched your search

+54 -31
View File
@@ -138,34 +138,41 @@ static void test_floor_decide(void)
const char *why = NULL;
int v;
/* 触发条件回到 pre-M23:面板暗 + 未下电就补(不依赖 /proc 的 D 态 = P2-2 硬要求) */
v = bm_bri_floor_decide(1, 0, 0, 5000, -1, &why); /* settings=1,播放器待机写 0 */
/* 触发条件回到 pre-M23:面板暗就补(不依赖 /proc 的 D 态 = 评审 r1 P2-2 硬要求) */
v = bm_bri_floor_decide(1, 0, 0, 5000, 0, &why); /* settings=1,播放器待机写 0 */
check("floor: writes user value 1 (not 60)", v == 1 && !strcmp(why, "scan-floor"), 1);
v = bm_bri_floor_decide(80, 0, 0, 5000, -1, &why); /* 降级 saved=80 照写 */
check("floor: degraded saved 80 floors at 80", v == 80 && !strcmp(why, "scan-floor"), 1);
v = bm_bri_floor_decide(0, 0, 0, 5000, -1, &why); /* saved 未知 -> 安全低亮 */
v = bm_bri_floor_decide(80, 0, 0, 5000, 0, &why); /* saved=80 只可能来自 settings */
check("floor: saved 80 (from settings) floors at 80", v == 80 && !strcmp(why, "scan-floor"), 1);
v = bm_bri_floor_decide(0, 0, 0, 5000, 0, &why); /* saved 未知 -> 安全低亮 */
check("floor: unknown saved -> safe-low", v == BM_BRI_SAFE_LOW && !strcmp(why, "scan-floor"), 1);
/* Bug 4 防退化回归用例(评审 P2-2):只要面板暗+未下电就必须能补,不能有任何
* 「播放器看起来不忙」的前提 —— 旧 busy 门会让这两条变成 no-write(黑屏几分钟)。 */
v = bm_bri_floor_decide(7, 0, 0, 89999, -1, &why);
check("floor: Bug4 regression — dark+unpowered always floors", v == 7 &&
!strcmp(why, "scan-floor"), 1);
/* Bug 4 防退化回归用例(评审 r1 P2-2):面板暗就必须能补,不能有任何「播放器看起来不忙」
* 的前提 —— 旧 busy 门会让这条变成 no-write(黑屏几分钟)。 */
v = bm_bri_floor_decide(7, 0, 0, 89999, 0, &why);
check("floor: Bug4 regression — dark+unlatched always floors", v == 7 &&
!strcmp(why, "scan-floor"), 1);
v = bm_bri_floor_decide(1, 5, 0, 5000, -1, &why); /* 面板已亮:不动 */
v = bm_bri_floor_decide(1, 5, 0, 5000, 0, &why); /* 面板已亮:不动 */
check("floor: visible -> no write", v == 0 && !strcmp(why, "visible"), 1);
v = bm_bri_floor_decide(1, 0, 1, 5000, -1, &why); /* 面板已下电(bl_power>0):不动 */
v = bm_bri_floor_decide(1, 0, 1, 5000, 0, &why); /* bl_power>0(纯保险):不动 */
check("floor: panel powered off -> no write", v == 0 && !strcmp(why, "panel-off"), 1);
/* 电源键刚按下(用户主动熄屏的第二道保险):3s 内不补 */
v = bm_bri_floor_decide(1, 0, 0, 5000, 1200, &why);
check("floor: recent power key -> no write", v == 0 && !strcmp(why, "power-key"), 1);
v = bm_bri_floor_decide(1, 0, 0, 5000, BM_BRI_PWR_HOLD_MS, &why); /* 到期即恢复补 */
check("floor: power key expired -> floors", v == 1 && !strcmp(why, "scan-floor"), 1);
v = bm_bri_floor_decide(1, 0, 0, 5000, -1, &why); /* 本次开机没按过电源键 */
check("floor: no power edge ever -> floors", v == 1 && !strcmp(why, "scan-floor"), 1);
v = bm_bri_floor_decide(1, 0, 0, 0, -1, &why); /* 90s 窗口结束:放手 */
/* 评审 r2 P2-2 核心:电源键**锁存**。窗内按过电源键 → 本次窗口内此后一律不补,
* 不再「3s 到期就把用户刚熄的屏点亮」。 */
v = bm_bri_floor_decide(1, 0, 0, 5000, 1, &why);
check("floor: power key latched -> no write", v == 0 && !strcmp(why, "power-key-latched"), 1);
/* 锁存不会过期:窗口剩 1ms 也不补(旧实现 3s 后就会补) */
v = bm_bri_floor_decide(1, 0, 0, 1, 1, &why);
check("floor: latch never expires inside window", v == 0 &&
!strcmp(why, "power-key-latched"), 1);
/* 下一轮窗口(锁存已清零)恢复正常补亮 */
v = bm_bri_floor_decide(1, 0, 0, 90000, 0, &why);
check("floor: new window (latch cleared) floors again", v == 1 &&
!strcmp(why, "scan-floor"), 1);
v = bm_bri_floor_decide(1, 0, 0, 0, 0, &why); /* 90s 窗口结束:放手 */
check("floor: window over -> no write", v == 0 && !strcmp(why, "window-over"), 1);
v = bm_bri_floor_decide(1, 0, 0, -1, -1, &why);
v = bm_bri_floor_decide(1, 0, 0, -1, 0, &why);
check("floor: negative window -> no write", v == 0 && !strcmp(why, "window-over"), 1);
}
@@ -177,8 +184,8 @@ static void test_hotkey_saved(void)
v = bm_bri_hotkey_saved(1, 0, 1, 101, &src); /* 电源已熄屏:恢复用户值 1,不再回 60 */
check("hotkey: blank -> saved (settings 1)", v == 1 && !strcmp(src, "saved"), 1);
v = bm_bri_hotkey_saved(60, 0, 1, 101, &src); /* 降级 saved=60(settings 不可读)时才用 60 */
check("hotkey: blank -> degraded saved 60", v == 60 && !strcmp(src, "saved"), 1);
v = bm_bri_hotkey_saved(60, 0, 1, 101, &src); /* saved=60 只可能来自 settings(降级已封顶 10) */
check("hotkey: blank -> saved 60 (settings value)", v == 60 && !strcmp(src, "saved"), 1);
v = bm_bri_hotkey_saved(1, 77, 1, 101, &src); /* 面板亮着:跟随面板(HibyOS 里改过亮度) */
check("hotkey: panel-now wins", v == 77 && !strcmp(src, "panel-now"), 1);
v = bm_bri_hotkey_saved(1, 200, 1, 101, &src); /* 越界值 clamp 到 max_brightness */
@@ -212,7 +219,11 @@ static void test_settings_parse(void)
check("settings: clamp down to 100", bootmenu_settings_brightness(NULL), 100);
put_file(path, "audio.volume = 10\n");
check("settings: missing key -> 100", bootmenu_settings_brightness(NULL), 100);
/* 评审 r2 非阻塞 1(采纳):「文件里没有这个键」与「文件读不到」同属不可信 →
* 返回 -1,而不是 launcher 设置表的默认 101→100(那会让扫描窗待机补到 100)。 */
int mn2 = 0;
check("settings: missing key -> -1 (untrusted)", bootmenu_settings_brightness(&mn2), -1);
check("settings: missing key still reports min", mn2, 1);
unlink(path);
unsigned long long t0 = now_ms();
@@ -252,24 +263,26 @@ static void test_e2e_backlight(void)
check("e2e: panel file read 60", panel, 60);
check("e2e: saved from settings = 1", saved, 1);
/* 扫描窗:播放器待机把背光写 0(面板未下电)→ 保底写用户值 1 */
/* 扫描窗:播放器待机把背光写 0 → 保底写用户值 1 */
put_file(bl, "0\n");
const char *why = NULL;
int floor = bm_bri_floor_decide(saved, read_brightness(), 0, 5000, -1, &why);
int floor = bm_bri_floor_decide(saved, read_brightness(), 0, 5000, 0, &why);
if (floor > 0) write_brightness(floor);
check("e2e: scan floor writes 1 (not 60)", get_file_int(bl), 1);
/* 用户主动熄屏(播放器已 FBIOBLANK,bl_power>0)→ 保底不写,面板保持 0 */
/* bl_power>0(纯保险分支)→ 保底不写 */
put_file(bl, "0\n");
floor = bm_bri_floor_decide(saved, read_brightness(), 1, 5000, -1, &why);
floor = bm_bri_floor_decide(saved, read_brightness(), 1, 5000, 0, &why);
if (floor > 0) write_brightness(floor);
check("e2e: user screen-off (panel-off) stays dark", get_file_int(bl), 0);
/* 用户主动熄屏但 bl_power 没置位:电源键按下 1.2s 内也不补(第二道保险) */
/* 评审 r2 核心场景:用户按电源熄屏(bl_power 仍 0)→ 锁存 → 本次窗口内**永久**不补,
* 不会再出现「3s 后自己亮回来」 */
put_file(bl, "0\n");
floor = bm_bri_floor_decide(saved, read_brightness(), 0, 5000, 1200, &why);
floor = bm_bri_floor_decide(saved, read_brightness(), 0, 5000, 1, &why);
if (floor > 0) write_brightness(floor);
check("e2e: user screen-off (power key) stays dark", get_file_int(bl), 0);
check("e2e: user screen-off (power key latched) stays dark", get_file_int(bl), 0);
check("e2e: latched why", !strcmp(why, "power-key-latched"), 1);
/* 热键确认框:面板黑着 → 按 saved(用户值 1)点亮,不是 60 */
int hk = bm_bri_hotkey_saved(saved, read_brightness(), mn_e2e, 101, &src);
@@ -293,6 +306,16 @@ static void test_e2e_backlight(void)
check("e2e: settings unreadable -> saved SAFE_LOW (not 60)", dsaved, BM_BRI_SAFE_LOW);
check("e2e: degraded src=panel-capped", !strcmp(src, "panel-capped"), 1);
/* 评审 r2 非阻塞 1(采纳):文件存在但缺 display.brightness 键 → 视同不可信 →
* saved 同样封顶 SAFE_LOW,不会补到 launcher 缺省的 100(比老 bug 的 60 更亮)。 */
put_file(st, "display.brightness_min = 1\n");
put_file(bl, "60\n");
src = "?";
int msaved = bm_bri_pick_saved(bootmenu_settings_brightness(&mn_d), read_brightness(),
mn_d, 101, &src);
check("e2e: missing brightness key -> SAFE_LOW (not 100)", msaved, BM_BRI_SAFE_LOW);
check("e2e: missing key src=panel-capped", !strcmp(src, "panel-capped"), 1);
unlink(bl); unlink(st);
unsetenv("MEOW_BACKLIGHT");
unsetenv("MEOW_SETTINGS_FILE");