fix(bootmenu): M23 评审 r1 — 修 P2-1 降级路径 + P2-2 Bug4 防护退化
P2-1(降级路径把老 bug 请回来):settings 不可读时不再原样采信面板瞬时值。 bm_bri_pick_saved 的 panel 分支改为 min(面板, BM_BRI_SAFE_LOW),src 改名 panel-capped; BM_BRI_SAFE_LOW 20 → 10,与 meow_watchdog 的 WD_BRI_SAFE_LOW 对齐(同一系统同一个安全下限)。 这样 settings 不可读 + 面板 60(播放器启动画面值)时 saved 是 10,扫描窗/确认框不会再写 60。 注释改掉「与 wd_bri_decide 同构」的断言:方向相同,但 bootmenu 没有运行期亮度快照, 降级走安全下限而不是 M20 的「快照 → cur>0 不写」链。 单测:把原先钉死 bug 的 "fallback keeps panel 60" 改成 "caps panel 60 -> SAFE_LOW 10", 并补「比 SAFE_LOW 更暗的真实值保留」「SAFE_LOW 与 M20 对齐」两个断言。 P2-2(busy 门可能让 Bug 4 防护变成空操作):删除 /proc D 态门,触发条件回到 pre-M23 的 「窗口内 + 面板暗(bri<=0)+ 面板未下电(bl_power<=0)」。 避免「熄屏瞬间爆亮」改由两条可观测信号承担:bl_power>0(播放器 FBIOBLANK)与 「电源键按下后 3s 内不补」(supervisor 已在 10ms 轮询 evdev,记录按下边沿)。 单测补 Bug4 防退化回归用例(窗口剩余 89999ms、面板暗、未下电 → 必须补)。 评审非阻塞三条: - 日志节流:同一原因 ≥2s 一条、原因跃迁也 ≥1s(防 visible↔scan-floor 每 400ms 交替刷屏, 90s 窗口最坏 ~90 行);日志字段 busy= 换成 pwr_ago=。 - 单测复跑配方补 TMPDIR;tmp_root() 增加自愈(TMPDIR → 可写 /tmp → $HOME/tmp/m23test)。 - 验收配方(3 次亮/灭屏 + 进一次开机菜单 + 期望日志行)写进报文。 只交源码:不含二进制、不改 fw_content.conf、不动 build_bootmenu.sh。
This commit is contained in:
1 parent
bc7bafa5dc
commit
8cd6e21cad
2 files changed
+162
-77
No files matched your search
@@ -40,13 +40,16 @@
|
||||
* - HibyOS 亮/灭屏:supervisor 起始把「启动瞬间面板读数」当保底亮度,且 >60 一律钉 60;
|
||||
* 扫描窗保底只要读到亮度<=0 就 400ms 内写回该值 —— 用户主动熄屏(播放器写 0)会被
|
||||
* 强行点亮成 60。现改为:settings.conf 的 display.brightness 为唯一权威(与 watchdog
|
||||
* wd_bri_decide / launcher 同源同 clamp),面板读数只在 settings 不可读时兜底;旧的
|
||||
* `>60 → 60` 改为 clamp 进 [display.brightness_min, max_brightness](为什么不会重新引入
|
||||
* M2.9 的开机闪屏见 bm_bri_pick_saved 注释);两者都不可知才写 BM_BRI_SAFE_LOW。
|
||||
* 扫描窗保底另加「播放器忙(媒体扫描)+ 面板未下电」两门,窗口结束彻底放手。
|
||||
* wd_bri_decide / launcher 同源同 clamp);旧的 `>60 → 60` 改为 clamp 进
|
||||
* [display.brightness_min, max_brightness](为什么不会重新引入 M2.9 的开机闪屏见
|
||||
* bm_bri_pick_saved 注释)。settings 不可读的降级路径**不采信面板瞬时值**,取
|
||||
* min(面板, BM_BRI_SAFE_LOW=10)(与 watchdog 的 WD_BRI_SAFE_LOW 对齐)。
|
||||
* 扫描窗保底恢复 pre-M23 的「面板暗 + 未下电」触发(不依赖 /proc 的 D 态,避免媒体扫描
|
||||
* 在子线程时 Bug 4 防护失效),另用两条可观测信号避让用户熄屏:bl_power>0、电源键按下
|
||||
* 后 3s 内不补;窗口结束彻底停手;日志同原因 ≥2s 一条。
|
||||
* 决策全部抽成纯函数(bm_bri_pick_saved / bm_bri_floor_decide / bm_bri_hotkey_saved),
|
||||
* 宿主单测见 test_bm_fw.c。亮度判定改为 bm_log 落卡(stderr 原行保留)。
|
||||
* 本单一律**只交源码**:二进制由 M43 rebase 后统一重编并回写 fw_content.conf 钉值。
|
||||
* 本单一律**只交源码**:二进制由 M43/M51 统一重编并回写 fw_content.conf 钉值。
|
||||
*
|
||||
* ============================================================================
|
||||
* WHY (设计见 BOOT_SELECTOR_DESIGN.md §3)
|
||||
@@ -927,9 +930,12 @@ static int bootmenu_settings_brightness(int *min_out)
|
||||
}
|
||||
|
||||
/* ---- M23:亮度决策(纯函数,宿主单测见 test_bm_fw.c)----
|
||||
* 与 meow_watchdog wd_bri_decide() 同构:settings 是唯一权威,任何分支都不再写「固定 60」。 */
|
||||
* 方向同 meow_watchdog wd_bri_decide()(settings 是唯一权威,任何分支都不再写「固定 60」),
|
||||
* 但 bootmenu **没有运行期亮度快照**(supervisor 起始只有一次读取),所以降级时转而走
|
||||
* 安全下限,而不是 M20 的「运行期快照 → cur>0 不写」那条链。 */
|
||||
#define BM_BRI_MIN_DEFAULT 1 /* display.brightness_min 缺省(与 launcher/watchdog 同值:极暗但可见) */
|
||||
#define BM_BRI_SAFE_LOW 20 /* settings/面板都不可知且面板已灭 → 低亮点亮(≈max 的 1/5,绝不 60) */
|
||||
#define BM_BRI_SAFE_LOW 10 /* 与 meow_watchdog 的 WD_BRI_SAFE_LOW 对齐(同一系统同一个安全下限) */
|
||||
#define BM_BRI_PWR_HOLD_MS 3000 /* 电源键按下后 N ms 内不补亮度(用户主动熄屏信号,见 floor_decide) */
|
||||
|
||||
/* 把任意亮度读数夹进面板合法区间 [mn, max_brightness](M23:取代旧 `>60 → 60` 的硬钉)。
|
||||
* mn < 1 时按 1(防黑屏:亮着总比黑屏好,但也不伪造「比用户下限更亮」);
|
||||
@@ -944,40 +950,52 @@ static int bm_bri_clamp(int v, int mn, int maxb)
|
||||
}
|
||||
|
||||
/* supervisor 起始「保底亮度」取值。
|
||||
* settings(已 clamp 到 [brightness_min,100])→ 面板读数(>0)→ BM_BRI_SAFE_LOW;
|
||||
* settings(已 clamp 到 [brightness_min,100])→ min(面板读数, SAFE_LOW) → SAFE_LOW;
|
||||
* 后两者再夹进 [brightness_min, max_brightness]。
|
||||
* *src 回填来源,原样进日志(settings / panel / safe-low)。
|
||||
* *src 回填来源,原样进日志(settings / panel-capped / safe-low)。
|
||||
* 真机症状来源:旧实现把「启动瞬间面板读数」当权威、且 >60 一律钉 60,用户值 1 被 60 顶掉。
|
||||
*
|
||||
* 降级路径(settings 不可读)**不再原样采信面板读数**(P2-1 评审):启动瞬间面板上可能是
|
||||
* 播放器启动画面的 60/101,若原值保存,后续扫描窗保底/确认框 unblank 就会把 60 写回去 ——
|
||||
* 正是 M20 把「当前面板值」排除出权威源的原因。bootmenu 也没有运行期快照可退,所以取
|
||||
* min(cur, SAFE_LOW=10):宁可暗一点,也不把瞬时值当用户亮度回放(这就是 M2.9 闪屏防护的正确形态)。
|
||||
* HibyOS 运行期由用户改的亮度**不走这条路径**,而走热键 `panel-now`(明确用户动作,见
|
||||
* bm_bri_hotkey_saved),所以这里不跟随面板不会丢用户意图。
|
||||
*
|
||||
* 为什么 clamp[min,max] 不会重新引入 M2.9 Bug 3 的「开机闪一下最高亮度」:
|
||||
* M2.9 的前置条件是「supervisor 启动时面板上是**播放器启动画面**的瞬时值,还没有人写过用户值」,
|
||||
* 于是一旦该瞬时值(101)被当作保底、在后续写回时就会跳一次 max。现在三个条件都不成立:
|
||||
* ① 有 settings 时**根本不看面板值**,写回的就是用户设置本身(写回 == 用户值,不存在跳变);
|
||||
* ② M21/S22 之后 /usr/data 挂载即写用户值,supervisor 启动时面板上已经不是播放器启动画面的
|
||||
* 瞬时值,而是用户值本身 —— 降级路径里「观测值」≈「用户值」,clamp 不会把它抬高;
|
||||
* ③ 写回只发生在「面板已暗」时(扫描窗保底要求 busy 且 未下电;确认框只在 was_blank 时点亮),
|
||||
* 即「从暗到用户值」,方向永远是向上回到用户原本的亮度,不是从暗跳到 max。
|
||||
* 换句话说:旧写法的问题不是「60 这个数」,而是「用常量顶替用户值」;clamp 保留的是观测/设置到的
|
||||
* 合法值,且上限就是面板自己的 max_brightness —— 不会再出现「用户 1、亮屏 60」这种越权抬亮。 */
|
||||
* M2.9 的前置条件是「supervisor 启动时面板上是播放器启动画面的瞬时值、还没人写过用户值」。
|
||||
* 现在:① 有 settings 时根本不看面板值,写回的就是用户设置本身;② M21/S22 之后 /usr/data
|
||||
* 一挂载就写用户值,主路径上不存在「瞬时值当权威」;③ 写回只发生在面板已暗时,方向是
|
||||
* 「暗 → 回到用户值」,而退化路径已被 SAFE_LOW 封顶,不会跳 max。 */
|
||||
static int bm_bri_pick_saved(int user, int cur, int mn, int maxb, const char **src)
|
||||
{
|
||||
if (user > 0) { *src = "settings"; return bm_bri_clamp(user, mn, maxb); }
|
||||
if (cur > 0) { *src = "panel"; return bm_bri_clamp(cur, mn, maxb); }
|
||||
if (cur > 0) {
|
||||
*src = "panel-capped";
|
||||
return bm_bri_clamp((cur < BM_BRI_SAFE_LOW) ? cur : BM_BRI_SAFE_LOW, mn, maxb);
|
||||
}
|
||||
*src = "safe-low";
|
||||
return bm_bri_clamp(BM_BRI_SAFE_LOW, mn, maxb);
|
||||
}
|
||||
|
||||
/* 扫描窗保底(Bug 4)决策:返回 >0 = 要写的亮度,0 = 不动;*why 回填原因供日志。
|
||||
* 旧实现只看「亮度<=0」,于是用户主动熄屏(播放器写 0 + blank)会在 400ms 内被强行写回
|
||||
* saved/60 → 「熄屏瞬间爆亮」。现在要求:窗口内 + 面板暗 + 播放器忙(媒体扫描,proc 态 D)
|
||||
* + 面板未下电(bl_power<=0)。窗口结束 / 播放器不忙 → 完全放手,不再与播放器抢面板。 */
|
||||
static int bm_bri_floor_decide(int saved, int cur, int busy, int bl_power,
|
||||
long long win_left_ms, const char **why)
|
||||
* 触发条件**回到 pre-M23 的形态**(P2-2 评审):窗口内 + 面板暗(bri<=0)+ 面板未下电
|
||||
* (bl_power<=0)→ 补。**不依赖 /proc 的 D 态**:媒体扫描若在子线程,主线程是 S,D 态门会
|
||||
* 让 Bug 4 的防护变成空操作(黑屏几分钟回归),那比亮度偏高严重得多。
|
||||
* 避免「熄屏瞬间爆亮」改由两条**可观测**信号承担:
|
||||
* ① bl_power>0 —— 播放器 FBIOBLANK 会置面板下电(bootmenu 确认框 unblank 时就把它写回 0,
|
||||
* 说明本机确实有这个行为),用户主动熄屏走这条;
|
||||
* ② 电源键按下后 BM_BRI_PWR_HOLD_MS 内不补 —— 10ms 轮询 evdev 就能看到,媒体扫描不会按电源键;
|
||||
* 这是「播放器只写 brightness=0 但没碰 bl_power」时的第二道保险。
|
||||
* 窗口结束 → *why="window-over",调用方彻底停手。 */
|
||||
static int bm_bri_floor_decide(int saved, int cur, int bl_power,
|
||||
long long win_left_ms, long long since_pwr_ms,
|
||||
const char **why)
|
||||
{
|
||||
if (win_left_ms <= 0) { *why = "window-over"; return 0; }
|
||||
if (cur > 0) { *why = "visible"; return 0; }
|
||||
if (!busy) { *why = "idle-blank"; return 0; }
|
||||
if (bl_power > 0) { *why = "panel-off"; return 0; }
|
||||
if (since_pwr_ms >= 0 && since_pwr_ms < BM_BRI_PWR_HOLD_MS) { *why = "power-key"; return 0; }
|
||||
*why = "scan-floor";
|
||||
return saved > 0 ? saved : BM_BRI_SAFE_LOW;
|
||||
}
|
||||
@@ -1334,11 +1352,13 @@ static void bootmenu_supervisor(int player_pid)
|
||||
/* Bug 4:HibyOS 开机媒体扫描窗内做亮度保底。播放器忙(媒体扫描)时其背光
|
||||
* 待机会把亮度降到 0、面板 blank → 黑屏几分钟。**只写 brightness、绝不碰 FBIOBLANK**
|
||||
* (不抢播放器的面板归属语义,参考 §18.30 面板归属)。扫描窗结束即放手。
|
||||
* M23:补的值改为用户设置(不再 60),并加「播放器忙 + 面板未下电」两门(见
|
||||
* bm_bri_floor_decide)—— 用户主动熄屏不再被强行点亮。 */
|
||||
* M23:补的值改为用户设置(不再 60);触发条件回到 pre-M23 的「面板暗 + 未下电」,
|
||||
* 另加「电源键按下后 3s 内不补」(可观测信号,见 bm_bri_floor_decide)。 */
|
||||
unsigned long long scan_keep_until = now_ms() + SCAN_KEEP_MS;
|
||||
unsigned long long last_bri_floor_at = 0; /* 亮度保底节流:≥400ms 才判定/写一次 */
|
||||
const char *last_floor_why = "init"; /* 只在判定原因跃迁时打日志(控日志量) */
|
||||
const char *last_floor_why = "init"; /* 判定原因(日志只在跃迁或 ≥2s 时打) */
|
||||
unsigned long long last_floor_log_at = 0; /* 上次 scan-window 日志时刻(同原因 ≥2s 一条) */
|
||||
unsigned long long last_pwr_edge_at = 0; /* 最近一次电源键按下边沿(0=本次开机尚未按过) */
|
||||
|
||||
struct keypoll kp_power, kp_keys;
|
||||
if (kp_open(&kp_power, DEV_POWER) != 0) fprintf(stderr, "supervisor: WARN no power dev\n");
|
||||
@@ -1394,34 +1414,41 @@ static void bootmenu_supervisor(int player_pid)
|
||||
}
|
||||
}
|
||||
|
||||
/* 2a) Bug 4 亮度保底(M23 重做):扫描窗内、播放器**忙**(媒体扫描)且亮度被降到 0
|
||||
* → 写回**用户设置**亮度(不再 60)。门条件见 bm_bri_floor_decide:
|
||||
* 窗口结束 / 面板已亮 / 播放器不忙(用户主动熄屏)/ 面板已下电(bl_power>0)→ 不写。
|
||||
* 旧实现只判「亮度<=0」,用户按电源熄屏后 400ms 内被写回 60 → 熄屏瞬间爆亮。
|
||||
/* 2a) Bug 4 亮度保底(M23):扫描窗内、面板暗(bri<=0)且**面板未下电**(bl_power<=0)
|
||||
* → 写回用户设置亮度(不再 60)。触发条件回到 pre-M23 形态,**不依赖 /proc 的 D 态**
|
||||
* (P2-2:媒体扫描若在子线程,主线程是 S,D 态门会让 Bug 4 防护变成空操作 → 黑屏回归)。
|
||||
* 避免「熄屏瞬间爆亮」由两条可观测信号承担:bl_power>0(播放器 FBIOBLANK)与
|
||||
* 电源键按下后 3s 内不补(见 bm_bri_floor_decide)。
|
||||
* (播放器扫描忙时无法响应唤醒,我们只把背光拉回,画面仍为播放器最后帧;不碰 blank。)
|
||||
* 判定按 400ms 节流(原写入节流同粒度),只在原因跃迁时打日志,避免刷卡。 */
|
||||
* 判定按 400ms 节流;日志同一原因 ≥2s 一条、跃迁也 ≥1s(防 `visible↔scan-floor`
|
||||
* 每 400ms 交替刷屏;90s 窗口最坏 ~90 行)。 */
|
||||
if (player_alive && scan_keep_until) {
|
||||
unsigned long long now2 = now_ms();
|
||||
if (now2 - last_bri_floor_at >= 400) {
|
||||
long long win_left = (scan_keep_until > now2)
|
||||
? (long long)(scan_keep_until - now2) : 0;
|
||||
long long since_pwr = (last_pwr_edge_at > 0)
|
||||
? (long long)(now2 - last_pwr_edge_at) : -1;
|
||||
int bri = read_brightness();
|
||||
int busy = proc_is_busy(player_pid);
|
||||
int blp = read_file_int(BACKLIGHT_POWER);
|
||||
const char *why = "?";
|
||||
int floor = bm_bri_floor_decide(saved_brightness, bri, busy, blp, win_left, &why);
|
||||
int floor = bm_bri_floor_decide(saved_brightness, bri, blp, win_left, since_pwr, &why);
|
||||
last_bri_floor_at = now2;
|
||||
if (floor > 0) {
|
||||
write_brightness(floor);
|
||||
/* 保留 M2 时代原有的 stderr 行(串口调试仍看它),另加一路 bm_log 落卡。 */
|
||||
fprintf(stderr, "supervisor: scan-window brightness floor -> %d\n", floor);
|
||||
}
|
||||
if (strcmp(why, last_floor_why) != 0) {
|
||||
/* 日志节流:同一原因 ≥2s 一条;原因跃迁也至少隔 1s(防 visible↔scan-floor
|
||||
* 每 400ms 交替时刷屏)。最坏 ~90 行/90s 窗口。 */
|
||||
unsigned long long gap = now2 - last_floor_log_at;
|
||||
if ((strcmp(why, last_floor_why) != 0 && gap >= 1000) || gap >= 2000) {
|
||||
last_floor_why = why;
|
||||
bm_log("supervisor: scan-window brightness %s -> %d (user=%d panel=%d busy=%d bl_power=%d left=%lldms)",
|
||||
(floor > 0) ? "floor" : "skip", floor, bri_user, bri, busy, blp, win_left);
|
||||
last_floor_log_at = now2;
|
||||
bm_log("supervisor: scan-window brightness %s -> %d (user=%d panel=%d bl_power=%d pwr_ago=%lldms left=%lldms)",
|
||||
(floor > 0) ? "floor" : "skip", floor, bri_user, bri, blp, since_pwr, win_left);
|
||||
}
|
||||
/* 窗口结束 → 彻底放手:此后不再读背光/进程态,绝不与播放器抢面板。 */
|
||||
/* 窗口结束 → 彻底放手:此后不再读背光/bl_power,绝不与播放器抢面板。 */
|
||||
if (win_left <= 0) scan_keep_until = 0;
|
||||
}
|
||||
}
|
||||
@@ -1439,8 +1466,10 @@ static void bootmenu_supervisor(int player_pid)
|
||||
if (se >= sim_hotkey_ms + 800 && se < sim_hotkey_ms + 950) vold = 1;
|
||||
}
|
||||
|
||||
/* 3) 热键:电源按下边沿 arming,窗口内音量减按下边沿触发 */
|
||||
if (pwr && !prev_pwr) { pwr_hold_armed = 1; pwr_down_at = t; }
|
||||
/* 3) 热键:电源按下边沿 arming,窗口内音量减按下边沿触发。
|
||||
* 同一边沿也记到 last_pwr_edge_at:亮度保底据此避让「用户主动熄屏」(可观测信号,
|
||||
* 不依赖 /proc 的 D 态;媒体扫描不会按电源键)。 */
|
||||
if (pwr && !prev_pwr) { pwr_hold_armed = 1; pwr_down_at = t; last_pwr_edge_at = t; }
|
||||
if (!pwr && prev_pwr) pwr_hold_armed = 0; /* 松开:disarm */
|
||||
if (pwr_hold_armed && pwr && (t - pwr_down_at) > HK_PWRWIN_MAX)
|
||||
pwr_hold_armed = 0; /* 超窗:disarm */
|
||||
|
||||
@@ -4,11 +4,13 @@
|
||||
* ① 开机菜单/选单亮度 = 面板继承值 60(用户设置 1)—— 选单路径 bootmenu_settings_brightness()
|
||||
* ② HibyOS 亮/灭屏瞬间爆亮 —— supervisor 起始 saved、扫描窗保底、热键熄屏恢复三处决策
|
||||
*
|
||||
* 编译(build_bootmenu.sh host;与 meow_watchdog 的 test_wd_fw.c 同款 include 打法):
|
||||
* gcc -Wall -Wextra -Os -I../meow_launcherd -DBM_NO_MAIN \
|
||||
* -Wno-unused-function -Wno-unused-parameter -Wno-unused-variable \
|
||||
* test_bm_fw.c ../meow_launcherd/meow_touch.c -o test_bm_fw
|
||||
* 运行:./test_bm_fw;全 PASS -> exit 0。
|
||||
* 编译/运行(Termux 上 /tmp 不可写,**必须带 TMPDIR**,否则 mkstemp 两条用例会 FAIL):
|
||||
* TMPDIR=$HOME/tmp/m23test mkdir -p "$HOME/tmp/m23test"
|
||||
* gcc -Wall -Wextra -Os -I../meow_launcherd -Wno-unused-function \
|
||||
* -Wno-unused-parameter -Wno-unused-variable \
|
||||
* test_bm_fw.c ../meow_launcherd/meow_touch.c -o "$HOME/tmp/m23test/test_bm_fw"
|
||||
* TMPDIR=$HOME/tmp/m23test "$HOME/tmp/m23test/test_bm_fw" # 全 PASS -> exit 0
|
||||
* (TMPDIR 未设时本文件会自己退到可写的 /tmp 或 $HOME/tmp,但显式给最稳。)
|
||||
* env MEOW_BACKLIGHT / MEOW_SETTINGS_FILE 把背光与 settings 指到临时文件(真机无这两个 env,
|
||||
* 走 /sys 与 /usr/data 默认路径),因此这里的读写断言就是真机同一条代码路径。
|
||||
*/
|
||||
@@ -19,6 +21,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
static int g_pass = 0, g_fail = 0;
|
||||
|
||||
@@ -28,12 +31,29 @@ static void check(const char *name, int got, int want)
|
||||
else { g_fail++; printf("FAIL %s: got %d want %d\n", name, got, want); }
|
||||
}
|
||||
|
||||
/* 临时目录根:优先 $TMPDIR(Termux/Android 上 /tmp 属 shell 用户、本进程不可写),
|
||||
* 否则 /tmp(Linux 构建容器)——与 test_wd_fw.c 一致。 */
|
||||
/* 临时目录根(返回可写目录;结果缓存在静态缓冲里):
|
||||
* ① $TMPDIR(Termux/Android 上 /tmp 属别的用户、本进程不可写)
|
||||
* ② /tmp(Linux 构建容器)
|
||||
* ③ $HOME/tmp/m23test(两者都不可写时的兜底,自动 mkdir)
|
||||
* 评审 r1 反馈:只靠 $TMPDIR 会让没设环境变量的复跑出现 2 条 mkstemp FAIL,故这里自愈。 */
|
||||
static const char *tmp_root(void)
|
||||
{
|
||||
static char buf[512];
|
||||
if (buf[0]) return buf;
|
||||
const char *t = getenv("TMPDIR");
|
||||
return (t && t[0]) ? t : "/tmp";
|
||||
if (t && t[0]) { snprintf(buf, sizeof buf, "%s", t); return buf; }
|
||||
const char *home = getenv("HOME");
|
||||
snprintf(buf, sizeof buf, "%s", "/tmp");
|
||||
char probe[560];
|
||||
snprintf(probe, sizeof probe, "%s/.bm_probeXXXXXX", buf);
|
||||
int fd = mkstemp(probe);
|
||||
if (fd >= 0) { close(fd); unlink(probe); return buf; }
|
||||
if (home && home[0]) {
|
||||
snprintf(buf, sizeof buf, "%s/tmp/m23test", home);
|
||||
mkdir(buf, 0700);
|
||||
return buf;
|
||||
}
|
||||
return buf; /* 实在不行也返回 /tmp,让失败信息可读 */
|
||||
}
|
||||
|
||||
static void put_file(const char *path, const char *body)
|
||||
@@ -69,19 +89,27 @@ static void test_pick_saved(void)
|
||||
v = bm_bri_pick_saved(7, 7, 1, 101, &src);
|
||||
check("saved: settings 7", v == 7 && !strcmp(src, "settings"), 1);
|
||||
|
||||
/* settings 不可读(降级路径):沿用面板读数,夹进 [brightness_min, max_brightness](M23 新语义) */
|
||||
/* settings 不可读(降级路径):**不**原样采信面板瞬时值,封顶 SAFE_LOW=10(P2-1 修复)。
|
||||
* 这是 M2.9 闪屏防护的正确形态:宁可用安全低亮,也不把「启动瞬间的面板值」当用户亮度回放。 */
|
||||
v = bm_bri_pick_saved(-1, 60, 1, 101, &src);
|
||||
check("saved: fallback keeps panel 60", v == 60 && !strcmp(src, "panel"), 1);
|
||||
v = bm_bri_pick_saved(-1, 80, 1, 101, &src); /* 用户真设 80:不再被旧 `>60→60` 顶成 60 */
|
||||
check("saved: fallback keeps 80 (old code pinned 60)", v == 80 && !strcmp(src, "panel"), 1);
|
||||
v = bm_bri_pick_saved(-1, 200, 1, 101, &src); /* 越界读数夹到 max_brightness */
|
||||
check("saved: fallback clamps 200 -> max 101", v == 101 && !strcmp(src, "panel"), 1);
|
||||
v = bm_bri_pick_saved(-1, 37, 1, 32, &src); /* 面板上限 32 时按 32 */
|
||||
check("saved: fallback clamps to max_brightness 32", v == 32 && !strcmp(src, "panel"), 1);
|
||||
v = bm_bri_pick_saved(-1, 2, 6, 101, &src); /* 低于 brightness_min 时抬到 min(防黑屏) */
|
||||
check("saved: fallback clamps up to brightness_min 6", v == 6 && !strcmp(src, "panel"), 1);
|
||||
check("saved: fallback caps panel 60 -> SAFE_LOW 10",
|
||||
v == BM_BRI_SAFE_LOW && v == 10 && !strcmp(src, "panel-capped"), 1);
|
||||
v = bm_bri_pick_saved(-1, 80, 1, 101, &src); /* 用户可能真设 80,但降级时不敢信面板 → 10 */
|
||||
check("saved: fallback caps 80 -> SAFE_LOW (old bug shape)",
|
||||
v == BM_BRI_SAFE_LOW && !strcmp(src, "panel-capped"), 1);
|
||||
v = bm_bri_pick_saved(-1, 200, 1, 101, &src); /* 越界(播放器瞬时 max)同样封顶 */
|
||||
check("saved: fallback caps 200 -> SAFE_LOW",
|
||||
v == BM_BRI_SAFE_LOW && !strcmp(src, "panel-capped"), 1);
|
||||
v = bm_bri_pick_saved(-1, 90, 1, 0, &src); /* max 读不到也不抬高 */
|
||||
check("saved: fallback caps 90 -> SAFE_LOW (unknown max)",
|
||||
v == BM_BRI_SAFE_LOW && !strcmp(src, "panel-capped"), 1);
|
||||
/* 比 SAFE_LOW 更暗的真实值保留(用户刻意调很暗,不要替用户调亮) */
|
||||
v = bm_bri_pick_saved(-1, 3, 1, 101, &src);
|
||||
check("saved: fallback keeps darker 3", v == 3 && !strcmp(src, "panel-capped"), 1);
|
||||
v = bm_bri_pick_saved(-1, 2, 6, 101, &src); /* 低于 brightness_min 时抬到 min(防全黑) */
|
||||
check("saved: fallback clamps up to brightness_min 6", v == 6 && !strcmp(src, "panel-capped"), 1);
|
||||
v = bm_bri_pick_saved(0, 3, 1, 101, &src); /* 非正值按住「未知」处理 */
|
||||
check("saved: user<=0 treated unknown", v == 3 && !strcmp(src, "panel"), 1);
|
||||
check("saved: user<=0 treated unknown", v == 3 && !strcmp(src, "panel-capped"), 1);
|
||||
|
||||
/* settings 与面板都不可知且面板黑:安全低亮,绝不再写 60 */
|
||||
v = bm_bri_pick_saved(-1, 0, 1, 101, &src);
|
||||
@@ -89,9 +117,8 @@ static void test_pick_saved(void)
|
||||
v > 0 && !strcmp(src, "safe-low"), 1);
|
||||
v = bm_bri_pick_saved(-1, -1, 1, 0, &src); /* 读失败 + max 读不到 */
|
||||
check("saved: read-fail -> safe-low", v == BM_BRI_SAFE_LOW && !strcmp(src, "safe-low"), 1);
|
||||
/* max 读不到(0)时只夹下限,不臆造上限 */
|
||||
v = bm_bri_pick_saved(-1, 90, 1, 0, &src);
|
||||
check("saved: unknown max keeps 90", v == 90 && !strcmp(src, "panel"), 1);
|
||||
/* 与 M20 watchdog 同一安全下限(同一系统不该有两个安全值) */
|
||||
check("saved: SAFE_LOW aligned with WD_BRI_SAFE_LOW (10)", BM_BRI_SAFE_LOW, 10);
|
||||
}
|
||||
|
||||
/* ---- A2) clamp 语义单测:取代旧的 `>60 → 60` 硬钉 ---- */
|
||||
@@ -111,22 +138,34 @@ static void test_floor_decide(void)
|
||||
const char *why = NULL;
|
||||
int v;
|
||||
|
||||
v = bm_bri_floor_decide(1, 0, 1, 0, 5000, &why); /* settings=1 + 扫描忙把面板写 0 */
|
||||
/* 触发条件回到 pre-M23:面板暗 + 未下电就补(不依赖 /proc 的 D 态 = P2-2 硬要求) */
|
||||
v = bm_bri_floor_decide(1, 0, 0, 5000, -1, &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, 1, 0, 5000, &why); /* 降级路径 saved=80 照写 80(旧码钉 60) */
|
||||
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, 1, 0, 5000, &why); /* saved 未知 -> 安全低亮 */
|
||||
v = bm_bri_floor_decide(0, 0, 0, 5000, -1, &why); /* saved 未知 -> 安全低亮 */
|
||||
check("floor: unknown saved -> safe-low", v == BM_BRI_SAFE_LOW && !strcmp(why, "scan-floor"), 1);
|
||||
|
||||
v = bm_bri_floor_decide(1, 5, 1, 0, 5000, &why); /* 面板已亮:不动 */
|
||||
/* 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);
|
||||
|
||||
v = bm_bri_floor_decide(1, 5, 0, 5000, -1, &why); /* 面板已亮:不动 */
|
||||
check("floor: visible -> no write", v == 0 && !strcmp(why, "visible"), 1);
|
||||
v = bm_bri_floor_decide(1, 0, 0, 0, 5000, &why); /* ← 用户主动熄屏(播放器不忙):不动 */
|
||||
check("floor: user screen-off (idle) -> no write", v == 0 && !strcmp(why, "idle-blank"), 1);
|
||||
v = bm_bri_floor_decide(1, 0, 1, 1, 5000, &why); /* 面板已下电(bl_power>0):不动 */
|
||||
v = bm_bri_floor_decide(1, 0, 1, 5000, -1, &why); /* 面板已下电(bl_power>0):不动 */
|
||||
check("floor: panel powered off -> no write", v == 0 && !strcmp(why, "panel-off"), 1);
|
||||
v = bm_bri_floor_decide(1, 0, 1, 0, 0, &why); /* 90s 窗口结束:放手 */
|
||||
/* 电源键刚按下(用户主动熄屏的第二道保险):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 窗口结束:放手 */
|
||||
check("floor: window over -> no write", v == 0 && !strcmp(why, "window-over"), 1);
|
||||
v = bm_bri_floor_decide(1, 0, 1, 0, -1, &why);
|
||||
v = bm_bri_floor_decide(1, 0, 0, -1, -1, &why);
|
||||
check("floor: negative window -> no write", v == 0 && !strcmp(why, "window-over"), 1);
|
||||
}
|
||||
|
||||
@@ -213,18 +252,24 @@ 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(), 1, 0, 5000, &why);
|
||||
int floor = bm_bri_floor_decide(saved, read_brightness(), 0, 5000, -1, &why);
|
||||
if (floor > 0) write_brightness(floor);
|
||||
check("e2e: scan floor writes 1 (not 60)", get_file_int(bl), 1);
|
||||
|
||||
/* 用户主动熄屏(不忙)→ 保底不写,面板保持 0 */
|
||||
/* 用户主动熄屏(播放器已 FBIOBLANK,bl_power>0)→ 保底不写,面板保持 0 */
|
||||
put_file(bl, "0\n");
|
||||
floor = bm_bri_floor_decide(saved, read_brightness(), 0, 0, 5000, &why);
|
||||
floor = bm_bri_floor_decide(saved, read_brightness(), 1, 5000, -1, &why);
|
||||
if (floor > 0) write_brightness(floor);
|
||||
check("e2e: user screen-off stays dark", get_file_int(bl), 0);
|
||||
check("e2e: user screen-off (panel-off) stays dark", get_file_int(bl), 0);
|
||||
|
||||
/* 用户主动熄屏但 bl_power 没置位:电源键按下 1.2s 内也不补(第二道保险) */
|
||||
put_file(bl, "0\n");
|
||||
floor = bm_bri_floor_decide(saved, read_brightness(), 0, 5000, 1200, &why);
|
||||
if (floor > 0) write_brightness(floor);
|
||||
check("e2e: user screen-off (power key) stays dark", get_file_int(bl), 0);
|
||||
|
||||
/* 热键确认框:面板黑着 → 按 saved(用户值 1)点亮,不是 60 */
|
||||
int hk = bm_bri_hotkey_saved(saved, read_brightness(), mn_e2e, 101, &src);
|
||||
@@ -237,6 +282,17 @@ static void test_e2e_backlight(void)
|
||||
saved = bm_bri_pick_saved(bootmenu_settings_brightness(NULL), read_brightness(), mn_e2e, 101, &src);
|
||||
check("e2e: saved follows new settings 5", saved, 5);
|
||||
|
||||
/* 降级路径回归(评审 P2-1):settings 不可读 + 面板瞬时 60(播放器启动画面)
|
||||
* → saved 只能是 SAFE_LOW=10,绝不能原样 60,否则扫描窗/确认框会把 60 写回去。 */
|
||||
unlink(st);
|
||||
put_file(bl, "60\n");
|
||||
int mn_d = 1;
|
||||
src = "?";
|
||||
int dsaved = bm_bri_pick_saved(bootmenu_settings_brightness(&mn_d), read_brightness(),
|
||||
mn_d, 101, &src);
|
||||
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);
|
||||
|
||||
unlink(bl); unlink(st);
|
||||
unsetenv("MEOW_BACKLIGHT");
|
||||
unsetenv("MEOW_SETTINGS_FILE");
|
||||
|
||||
Reference in new issue
Block a user