fix(watchdog+launcher+sdk): M40 电源键 time64 ABI + 锁屏/叠加残留链

- sdk/meow_time32: 抽出可独立链接的 o32 time32 取时/睡眠设施(不依赖 meow_ui.a,
  watchdog 等独立静态组件可直接链;可选 -DMEOW_TIME32_LIBC_OVERRIDES 接管 libc 入口)
- watchdog: now_ms/usleep 改走 time32(修复 held 变天文数字→每次单击都弹菜单);
  阈值读 power.longpress_menu_ms/forceoff_ms(缺省 3000/8000),删除
  PWR_TOGGLE_MS==PWR_MENU_MS;新增 wd_power.h 纯判定 + 宿主行为矩阵测试
- launcher: App 前台电源菜单补齐 §10.5(notif 全抑制 + 帧恢复 + SIGCONT 排空 +
  标记翻回前台);show_power_menu 恢复进入前背景帧(关闭后不再停留菜单画面);
  重绘挪到首轮按键采样之后;activity 标记排空窗 + 会话入口清理 + manual_off 去闩锁
- lock_screen: 电源改按下边沿 + 进场 300ms 才熄屏;电源熄屏退出也恢复底层帧;
  launcher 在 SIGCONT 前写 /tmp/meow_app_repaint,SDK present 消费并 dirty_full
- power_menu: 菜单内强关接 power.forceoff_ms(按 longpress 抵扣),日志不再谎称 8s
- 重编 meow_ui.a 并重链 meow_launcherd/ncm/files/hello/reader(picbrowser 无源码)
- fw_content.conf: 同步 launcherd/watchdog 新 md5;顺带修正 M35 遗留的 nyai 失效钉值

Host: test_wd_fw 66/66、test_overlay_gate 40/40、test_meow_time64/time/repaint PASS。
真机未验证(设备关机);未刷机、未写设备。
This commit is contained in:
AskaEth committed 2026-11-10 22:51:00 +08:00
1 parent b1acc9096b
commit 63b278e13e
28 files changed
+977 -217

No files matched your search

+92 -44
View File
@@ -355,22 +355,59 @@ int meow_power_action(uint32_t cmd)
}
/* M40 F2/P2:关闭菜单时恢复进入前的背景帧并 present。
* dim_screen() 就地压暗 back_buf;若不恢复,app_launcher 关闭会话时的 pm_capture_app_frame()
* 会把「压暗 App 帧 + 菜单卡」当成 App 帧拍回并上屏 → 菜单关闭后屏幕仍是菜单画面,
* 用户看到「再次单击没反应」(P2 主因)。所有退出路径(取消/锁定/关机/强关)统一恢复。 */
static void pm_restore_bg(unsigned char *snap, size_t len)
{
if (!snap || !len || !back_buf_ok || !fb) return;
memcpy(fb, snap, len);
meow_dirty_full();
meow_ui_flush();
}
/* 电源菜单(M2.6):2×2 网格,dirty 绘制消频闪;输入修复:
* - 触摸按下捕获坐标、抬起命中按钮即确认(同 run_menu MT 防抖);
* - 音量上/下导航;播放=确认;电源新按(松开长按后)=确认当前钮(非取消);
* - 取消=选「取消」钮;8s 持续按住=强制关机(绕过)。
* - 取消=选「取消」钮;按住 power.forceoff_ms(缺省 8s,从按下起算)=强制关机(绕过)。
* 返回 1=采取动作,0=取消。 */
int show_power_menu(void)
{
int fbfd = open(FB_DEV, O_RDWR);
if (fbfd >= 0) { ioctl(fbfd, FBIOBLANK, 0); close(fbfd); } /* 亮起面板 */
pm_capture_app_frame(); /* A-0:菜单背景 = app 当前帧(fb0 buffer0),再压暗绘制其上 */
meow_screen_on = 1; /* 菜单打开即视为亮屏 */
/* M40 F2:先开输入设备并采样第一轮基线。旧顺序把这一步放在 pm_capture/dim/建卡之后
* (真机实测菜单请求→keypoll ready 相隔 75ms),一次完整的按下+抬起若落在这段阻塞绘制里
* 就永远看不到边沿(EVIOCGKEY 是电平采样,不回溯事件队列)。重活挪到采样之后。 */
meow_touch mt;
mt_reset(&mt);
int tfd = open(DEV_TOUCH, O_RDONLY | O_NONBLOCK);
struct keypoll kp_power, kp_keys;
kp_open(&kp_power, DEV_POWER);
kp_open(&kp_keys, DEV_KEYS);
int prev_vold = 0, prev_volu = 0, prev_pwr = 0;
kp_poll(&kp_power, NULL, NULL); kp_poll(&kp_keys, NULL, NULL);
prev_pwr = kp_is_down(&kp_power, KEY_POWER) ? 1 : 0;
prev_vold = kp_is_down(&kp_keys, KEY_VOLUMEDOWN) ? 1 : 0;
prev_volu = kp_is_down(&kp_keys, KEY_VOLUMEUP) ? 1 : 0;
/* 背景帧:先把 app 当前帧读回 back_buf,快照后再压暗绘制 */
pm_capture_app_frame(); /* A-0:菜单背景 = app 当前帧(fb0 buffer0) */
unsigned char *pm_bg_snap = NULL;
size_t pm_bg_len = 0;
if (back_buf_ok && fb && fb_line > 0 && fb_yres > 0) {
pm_bg_len = (size_t)fb_line * (size_t)fb_yres;
pm_bg_snap = malloc(pm_bg_len);
if (pm_bg_snap) memcpy(pm_bg_snap, fb, pm_bg_len);
else { pm_bg_len = 0; logmsg("pm: bg snapshot malloc fail (len=%zu)", pm_bg_len); }
}
dim_screen();
/* M2.8 Bug 3-residual:若电源菜单是在「息屏」态打开(按住 3s),此处 FBIOBLANK(0)
* 刚上电,LCDC 扫描地址可能非 buffer0;强制 re-pan 让压暗的应用列表 + 菜单落在被显示的
* 缓冲,否则菜单画在非显示缓冲上不可见。 */
fb_pan_buf0_force();
meow_screen_on = 1; /* 菜单打开即视为亮屏 */
/* M2.11 B:默认光标 = 「取消」(安全项,index 4)。用户打开菜单后未导航就按电源/播放,
* 只会取消关菜单,绝不因「按电源键」本身关机/重启。要真关机必须先导航到「关机」再确认。 */
@@ -383,29 +420,25 @@ int show_power_menu(void)
pm_draw_card(); /* 卡片 + 标题 POWER MENU + 底部提示(SDK 主题色,i18n 文案) */
meow_dirty_full(); /* M2.16:把压暗列表+卡片+标题+(下方圆钮)作为一整帧呈现 */
/* 触摸状态(按下→抬起):统一 meow_touch 接口(goodix 时序免疫,原点由首个有效 ABS 锁) */
meow_touch mt;
mt_reset(&mt);
int tfd = open(DEV_TOUCH, O_RDONLY | O_NONBLOCK);
struct keypoll kp_power, kp_keys;
kp_open(&kp_power, DEV_POWER);
kp_open(&kp_keys, DEV_KEYS);
int prev_vold = 0, prev_volu = 0, prev_pwr = 0;
kp_poll(&kp_power, NULL, NULL); kp_poll(&kp_keys, NULL, NULL);
prev_pwr = kp_is_down(&kp_power, KEY_POWER) ? 1 : 0;
prev_vold = kp_is_down(&kp_keys, KEY_VOLUMEDOWN) ? 1 : 0;
prev_volu = kp_is_down(&kp_keys, KEY_VOLUMEUP) ? 1 : 0;
int act = -1;
int pm_rc = 0;
unsigned long long pm_t0 = now_ms();
/* 强关阈值:power.forceoff_ms 是**从按下起算**的总时长;菜单在 longpress 阈值处打开,
* 因此菜单内剩余等待 = forceoff - longpress(缺省 8000-3000=5000ms,与原硬编码值一致,
* 但不再忽略 settings)。配置异常(剩余<1s)时退回完整 forceoff。 */
unsigned long long pm_forceoff_after_ms = 5000;
if (power_forceoff_ms > power_longpress_menu_ms &&
power_forceoff_ms - power_longpress_menu_ms >= 1000)
pm_forceoff_after_ms = (unsigned long long)(power_forceoff_ms - power_longpress_menu_ms);
else if (power_forceoff_ms > 0)
pm_forceoff_after_ms = (unsigned long long)power_forceoff_ms;
unsigned long long pm_last_interact = pm_t0; /* M2.33:菜单空闲自动关闭基准(任何互动刷新) */
int pm_init = 0, last_sel = -1;
/* M2.10 Bug:电源菜单 8s 强关(按住电源≥8s=绕过强关)会覆盖用户的菜单操作 —— 用户按住
* 电源打开菜单后(尤其仍按着电源)点选「回到HibyOS/重启」等按钮,8s 一到先触发强关 → 关机
/* M2.10 Bug:电源菜单强关(按住电源到 forceoff)会覆盖用户的菜单操作 —— 用户按住
* 电源打开菜单后(尤其仍按着电源)点选「回到HibyOS/重启」等按钮,强关一到先触发 → 关机
* 而非执行所选动作。修法:一旦用户与菜单互动(音量导航/触摸/播放/电源确认),置 pm_interacted=1
* 取消 8s 强关,让所选动作(如「回到HibyOS」→ reboot RESTART)生效。仅当全程未互动才保留「按住
* 8s=强关」。*/
* 取消强关,让所选动作(如「回到HibyOS」→ reboot RESTART)生效。仅当全程未互动才保留「按住
* 到 forceoff=强关」。*/
int pm_interacted = 0;
int pm_press_idx = -1; /* M7.0b:当前按下钮(按压态走 SDK 状态机位) */
for (;;) {
@@ -488,17 +521,25 @@ int show_power_menu(void)
}
}
/* 8s 强关(绕过):仅当电源持续按住、且用户全程未与菜单互动才触发 —— 放在触摸/按键处理
* 之后,避免「用户已点选按钮」的同一轮被强关抢先(M2.10 Bug)。 */
if (pwr && !pm_interacted && now_ms() - pm_t0 >= 5000) {
if (sim_no_exec) { logmsg("pm: [sim-no-exec] POWER HOLD 8s -> would force poweroff"); meow_ui_activity_pop(); return 1; }
logmsg("pm: POWER HOLD 8s -> force poweroff");
/* 强关(绕过):仅当电源持续按住、且用户全程未与菜单互动才触发 —— 放在触摸/按键处理
* 之后,避免「用户已点选按钮」的同一轮被强关抢先(M2.10 Bug)。
* M40:阈值接 power.forceoff_ms(从按下起算的剩余时长),不再硬编码 5000/日志谎称 8s。 */
if (pwr && !pm_interacted && now_ms() - pm_t0 >= pm_forceoff_after_ms) {
if (sim_no_exec) {
logmsg("pm: [sim-no-exec] POWER HOLD %dms (menu-open + %llums) -> would force poweroff",
power_forceoff_ms, pm_forceoff_after_ms);
pm_rc = 1;
goto out;
}
logmsg("pm: POWER HOLD %dms (menu-open + %llums) -> force poweroff",
power_forceoff_ms, pm_forceoff_after_ms);
if (meow_power_action(POWER_SHUTDOWN) != MEOW_OK) {
logmsg("pm: power service unavailable, abort force-off (menu closed, no action)");
meow_ui_activity_pop(); return 0;
pm_rc = 0;
goto out;
}
meow_ui_activity_pop();
return 1;
pm_rc = 1;
goto out;
}
/* M2.33 菜单空闲超时自动关闭:菜单受 MeowOS screen_off_timeout 管理(系统界面不豁免)。
@@ -516,57 +557,64 @@ int show_power_menu(void)
if (act >= 0) break;
usleep(POLL_MS * 1000);
}
if (tfd >= 0) close(tfd);
meow_ui_activity_pop(); /* M7.0b:退出电源菜单,回主 activity(控件 owner 仍钉哨兵,复用) */
/* M2.11 B:电源键在菜单 = 按当前项确认。act 与电源动作逐项核对:
* act==PM_NUM-1(取消) -> 只关菜单,绝不关机(return 0,永不到电源动作);
* act==PM_NUM-1(取消) -> 只关菜单,绝不关机(rc=0,永不到电源动作);
* act==4(锁定) -> 手动锁(meow_lock_screen_engage,未配 PIN 则 no-op),关菜单;
* act==0(关机)/act==1(重启)/act==2(回HibyOS)/act==3(升级模式) -> 才经服务 IPC 执行电源动作。
* 只有 act 为 0/1/2/3 才可能发电源动作;power 键本身绝不触发关机。 */
logmsg("pm: act=%d -> %s", act,
act == 0 ? "关机" : act == 1 ? "重启" : act == 2 ? "回HibyOS" : act == 3 ? "升级模式"
: act == 4 ? "锁定" : "取消");
if (act == PM_NUM - 1) { logmsg("pm: cancel (close menu only)"); return 0; }
if (act == PM_NUM - 1) { logmsg("pm: cancel (close menu only)"); pm_rc = 0; goto out; }
if (act == 4) {
logmsg("pm: LOCK SCREEN");
meow_lock_screen_engage();
return 0; /* 关菜单;run_menu 继续(锁屏页已阻塞到解锁或电源息屏) */
pm_rc = 0; /* 关菜单;run_menu 继续(锁屏页已阻塞到解锁或电源息屏) */
goto out;
}
/* 动作统一经电源管理服务 IPC(meow_svc_power);launcher 不再直连 poweroff/reboot(2)/写 mtd5/
* 写 boot 默认——关机/重启/升级/回HiBy 的动作原语都在服务内实现(§3.2 单一动作链路)。 */
/* 公共服务:执行动作;服务不可达 → 按「取消」返回(launcher 存活,绝不误报已动作卡死)。
* meow_power_action 内部已先 meow_notif_before_poweroff()(转储未上卡通知)。 */
pm_rc = 1;
if (act == 0) {
logmsg("pm: POWER OFF");
if (sim_no_exec) { logmsg("pm: [sim-no-exec] would poweroff"); return 1; }
if (sim_no_exec) { logmsg("pm: [sim-no-exec] would poweroff"); goto out; }
if (meow_power_action(POWER_SHUTDOWN) != MEOW_OK) {
logmsg("pm: power service unavailable, abort (menu closed, no action)");
return 0;
pm_rc = 0;
}
} else if (act == 1) {
logmsg("pm: REBOOT");
if (sim_no_exec) { logmsg("pm: [sim-no-exec] would reboot"); return 1; }
if (sim_no_exec) { logmsg("pm: [sim-no-exec] would reboot"); goto out; }
if (meow_power_action(POWER_REBOOT) != MEOW_OK) {
logmsg("pm: power service unavailable, abort (menu closed, no action)");
return 0;
pm_rc = 0;
}
} else if (act == 2) {
logmsg("pm: RETURN TO HIBYOS");
if (sim_no_exec) { logmsg("pm: [sim-no-exec] would reboot to hiby"); return 1; }
if (sim_no_exec) { logmsg("pm: [sim-no-exec] would reboot to hiby"); goto out; }
if (meow_power_action(POWER_BACK_HIBY) != MEOW_OK) {
logmsg("pm: power service unavailable, abort (menu closed, no action)");
return 0;
pm_rc = 0;
}
} else if (act == 3) {
logmsg("pm: ENTER UPGRADE");
if (sim_no_exec) { logmsg("pm: [sim-no-exec] would enter upgrade"); return 1; }
if (sim_no_exec) { logmsg("pm: [sim-no-exec] would enter upgrade"); goto out; }
if (meow_power_action(POWER_UPGRADE) != MEOW_OK) {
logmsg("pm: power service unavailable, abort (menu closed, no action)");
return 0;
pm_rc = 0;
}
}
return 1;
out:
if (tfd >= 0) close(tfd);
meow_ui_activity_pop(); /* M7.0b:退出电源菜单,回主 activity(控件 owner 仍钉哨兵,复用) */
/* M40 F2:恢复进入前的背景帧(否则 app_launcher 会把菜单帧当 App 帧上屏 = P2)。
* 放在动作执行之后:锁屏动作已 meow_panel_off(),此时恢复只写 fb0(面板黑),
* 下次唤醒 / App 整帧重画时得到的是正确底层帧而不是 PIN/菜单帧。 */
pm_restore_bg(pm_bg_snap, pm_bg_len);
if (pm_bg_snap) free(pm_bg_snap);
return pm_rc;
}