feat(font+sys): 字库内存纪律(agent-215)+sysui接管launcher监管(agent-216)

215: meow_font.c 流式分块解码(gbk峰值40→23.5MB, 逐字节校验一致) + 多字体槽5→4+16MB驻留预算; 量化: gbk稳态驻留17.3MB vs common 4.2MB(OOM主因); meow_font.a→67113c03 meow_ui.a→223d5401
216: bootmenu让位(sysui在则start launcher让位, 不在则exec兜底) + S70预置launcher.conf enabled=1(+旧设备升级迁移); launcher崩溃可自动拉起; bootmenu 4441822d / S70 e435affc / S90 e0ace111
216注: S70早启动与选单共存为真机重点观察项
This commit is contained in:
MeowOS committed 2026-08-31 13:28:07 +08:00
1 parent 90e28e7b7e
commit c0f7a95719
10 files changed
+434 -92

No files matched your search

+5 -4
View File
@@ -8,10 +8,11 @@
# * M2: meow_bootmenu is launched with --fork, so:
# 选 HibyOS -> bootmenu forks /usr/bin/hiby_player (最小启动契约),
# parent becomes supervisor/热键守护, blocks rcS.
# 选 MeowOS -> bootmenu exec /usr/bin/meow_launcherd (MeowOS 基础主屏),
# blocks rcS.
# Either way rcS is blocked by S90 until整机重启/热键切换, so S92 (兜底 patch)
# is normally never reached; SSH was moved to S84 so it is already online.
# 选 MeowOS -> launcher 生命周期已交 meow_sysui(S70 起):sysui 在 → bootmenu
# 让 sysui 拉起 launcher 并让位退出(rcS 推进,S92 见 mode=meow 跳过
# 播放器);sysui 不在 → bootmenu 照旧 exec /usr/bin/meow_launcherd(兜底)。
# HibyOS 模式 rcS 被 S90 阻塞;MeowOS(sysui 托管)rcS 推进到 S92(兜底 patch,mode=meow 跳过)。
# SSH was moved to S84 so it is already online.
# * rcS runs S??* (non-.sh) as fork-ed subprocesses, so `exec` here replaces
# ONLY this script's process.
# * 红线: 启动前清 /data/recovery_all、禁经 hiby_player.sh、禁 killall、
Binary file not shown.
+95 -16
View File
@@ -35,8 +35,12 @@
* ============================================================================
* WHY (设计见 BOOT_SELECTOR_DESIGN.md §3)
* ============================================================================
* - 开机最先显示选单(HibyOS / MeowOS),选择后 fork 播放器(HibyOS)或
* exec MeowOS 主屏(MeowOS);HibyOS 模式热键(电源+音量减)杀播放器接管。
* - 开机最先显示选单(HibyOS / MeowOS),选择后 fork 播放器(HibyOS)或进入
* MeowOS 主屏;HibyOS 模式热键(电源+音量减)杀播放器接管。
* - M2.83 launcher 监管迁移:MeowOS 主屏(meow_launcherd)生命周期已交 meow_sysui
* (S70 起)。故选 MeowOS 时——sysui 在 → 让 sysui 拉起/监管 launcher,本进程让位退出
* (rcS 推进,S92 见 mode=meow 跳过播放器);sysui 不在 → 本进程照旧 exec launcher(兜底,
* 防开不了机)。选 HibyOS 时 sysui 在 → 让 sysui 停 launcher(不与播放器抢 fb0)。
* - 本二进制 = 选单本体(M0)。M0 只做二进制自检:SSH 推 /data 独立跑,
* **不进启动链**(不碰 S90/S92/播放器/SSH 顺序)。
*
@@ -898,8 +902,81 @@ static int sim_confirm_done = 0;
static int sim_hk_done = 0;
static int sim_hotkey_strict = 0; /* M2.14:--sim-hotkey-strict = 让 sim 热键走武装延迟/忙判门(测 pending) */
/* ======================================================================
* M2.83 launcher 监管迁移:launcher 生命周期由 bootmenu 移交给 meow_sysui
* - MeowOS 模式:sysui 在 → 让 sysui 拉起/监管 launcher,bootmenu 让位不 exec
* (rcS 推进 → S92 见 mode=meow 跳过播放器);sysui 不在 → bootmenu 照旧 exec launcher(兜底)。
* - HibyOS 模式:sysui 在 → 让 sysui 停 launcher(会话级 user_stopped,不自动重启),避免与播放器抢 fb0。
* 双保险:sysui 拉 + launcher 崩 sysui 重启(restart=always);bootmenu 仅在 sysui 不在时兜底。
* ====================================================================== */
static int sysui_active(void)
{
/* sysui daemon 是否在跑:/tmp/meow_sysui.pid 存活,且 /proc/<pid>/comm=meow_sysui(防 pid 复用误判) */
FILE *f = fopen("/tmp/meow_sysui.pid", "r");
if (!f) return 0;
long pid = -1;
int n = fscanf(f, "%ld", &pid);
fclose(f);
if (n != 1 || pid <= 1) return 0;
if (kill((pid_t)pid, 0) != 0) return 0; /* ESRCH → 不在 */
char comm[64] = {0}, path[64];
snprintf(path, sizeof path, "/proc/%ld/comm", pid);
int fd = open(path, O_RDONLY);
if (fd >= 0) {
ssize_t r = read(fd, comm, sizeof comm - 1);
close(fd);
if (r > 0) {
char *nl = strchr(comm, '\n');
if (nl) *nl = '\0';
if (strncmp(comm, "meow_sysui", 10) != 0) return 0;
}
}
return 1;
}
static void sysui_cmd_launcher(const char *op)
{
/* 调 /usr/bin/meow_sysui start|stop launcher(best-effort:sysui 缺失/失效 → 无害退出)。
* 等 CLI 返回(CLI 连 socket 快速回),避免僵尸;失败不致命。 */
pid_t pid = fork();
if (pid < 0) {
fprintf(stderr, "bootmenu: sysui %s launcher: fork failed: %s\n", op, strerror(errno));
return;
}
if (pid == 0) {
execl("/usr/bin/meow_sysui", "/usr/bin/meow_sysui", op, "launcher", (char *)NULL);
_exit(127); /* sysui 缺失/不可执行 → 无害退出(fallback 路径会用本地 exec) */
}
int st = 0;
(void)waitpid(pid, &st, 0);
}
static int enter_meow_launcher(void)
{
/* MeowOS 决策点:返回 0=已让位(launcher 由 sysui 继续管理,调用方正常退出/让 rcS 推进);
* 否则已 exec launcher(本函数不返回)。 */
if (sysui_active()) {
fprintf(stderr, "bootmenu: sysui owns launcher -> hand off (start via sysui)\n");
fflush(NULL);
sysui_cmd_launcher("start");
return 0;
}
/* 回退:sysui 不在 → bootmenu 照旧 exec launcher(防开不了机) */
fprintf(stderr, "bootmenu: no sysui -> exec %s (fallback)\n", LAUNCHER_BIN);
fflush(NULL);
execv(LAUNCHER_BIN, (char *[]){ "meow_launcherd", NULL });
fprintf(stderr, "bootmenu: exec launcher failed: %s\n", strerror(errno));
_exit(127);
}
static void fork_hiby_player(void)
{
/* M2.83 迁移:HibyOS 模式下 launcher 不应与播放器抢 fb0——sysui 在则让 sysui 停 launcher */
if (sysui_active()) {
fprintf(stderr, "bootmenu: HibyOS selected -> stop launcher via sysui\n");
fflush(NULL);
sysui_cmd_launcher("stop");
}
pid_t pid = fork();
if (pid < 0) { fprintf(stderr, "fork player failed: %s\n", strerror(errno)); return; }
if (pid == 0) {
@@ -1278,13 +1355,17 @@ static void bootmenu_supervisor(int player_pid)
}
player_alive = 0;
}
/* 播放器已死:面板已在确认框点亮(brightness=saved)。写 mode=meow,
* 然后 exec MeowOS 基础主屏(接管 fb0 画 buffer0+pan0)。 */
/* 播放器已死:面板已在确认框点亮(brightness=saved)。写 mode=meow。
* M2.83 迁移:MeowOS 基础主屏(launcher)已交 sysui 托管——sysui 在则让 sysui
* 拉起 launcher(本 supervisor 让位退出,rcS 推进,S92 见 mode=meow 跳过播放器);
* sysui 不在则照旧 exec launcher(兜底)。 */
write_mode(0);
fprintf(stderr, "supervisor: exec /usr/bin/meow_launcherd\n");
fflush(NULL);
execv(LAUNCHER_BIN, (char *[]){ "meow_launcherd", NULL });
fprintf(stderr, "supervisor: exec launcher failed: %s\n", strerror(errno));
if (enter_meow_launcher() == 0) {
fprintf(stderr, "supervisor: launcher handed off to sysui, supervisor exits\n");
fflush(NULL);
_exit(0);
}
/* 不可达:enter_meow_launcher 在无 sysui 时已 exec launcher(不返回) */
_exit(127);
} else {
/* ===== 否 / -1:留在 HibyOS =====
@@ -1528,15 +1609,14 @@ static int run_menu(int sim_sel, int do_fork)
fb_restore_player_frame();
fb_close();
/* M2(--fork):HibyOS→fork 播放器(父进程转监督者,阻塞 rcS);
* MeowOS→exec meow_launcherd(MeowOS 基础主屏,接管 fb0)。 */
* MeowOS→sysui 在则让 sysui 拉起 launcher 并让位(rcS 推进,S92 见 mode=meow 跳过播放器);
* sysui 不在则 exec meow_launcherd(MeowOS 基础主屏,接管 fb0;兜底)。返回=已让位。 */
if (do_fork) {
if (choice == 1) {
fork_hiby_player(); /* 父进程陷入 supervisor,永不返回 */
} else {
set_boot_default_meow(); /* Bug 1:选 MeowOS → 持久为开机默认 */
execv(LAUNCHER_BIN, (char *[]){ "meow_launcherd", NULL });
fprintf(stderr, "bootmenu: exec launcher failed: %s\n", strerror(errno));
_exit(127);
enter_meow_launcher(); /* 让位返回 0,或 exec launcher(不返回) */
}
}
return 0; /* M0/M1(无 --fork):选单退出,rcS 推进 */
@@ -1556,7 +1636,8 @@ static void usage(void)
" --boot-only 跳过选单,直接取默认(boot_default)\n"
" --timeout-ms N 覆写超时毫秒(测试钩子)\n"
" --fork M2 开启:选 HibyOS 时 fork 播放器并转监督者;\n"
" 选 MeowOS 时 exec /usr/bin/meow_launcherd(默认关)\n"
" 选 MeowOS 时 sysui 在→让 sysui 拉起 launcher(本进程让位退出),\n"
" 否则 exec /usr/bin/meow_launcherd(默认关)\n"
" --sim-hotkey N 监督者启动 N ms 后模拟热键(M2 真机 verif)\n"
" --sim-confirm Y|N 确认框打开 2s 后自动答 Y=是 / N=否\n"
" --version 打印版本并退出\n",
@@ -1617,9 +1698,7 @@ int main(int argc, char **argv)
if (choice == 1) fork_hiby_player();
else {
set_boot_default_meow(); /* Bug 1:选 MeowOS → 持久为开机默认 */
execv(LAUNCHER_BIN, (char *[]){ "meow_launcherd", NULL });
fprintf(stderr, "bootmenu: exec launcher failed: %s\n", strerror(errno));
_exit(127);
enter_meow_launcher(); /* sysui 在→让位返回 0;否则 exec launcher(不返回) */
}
}
return 0;
+26 -12
View File
@@ -4,12 +4,13 @@
#
# 位置:**最早**(早于 S84ssh / S89meow_svcd / S90meow_bootmenu)。
# * 定案启动链:meow_sysui 先起(S70)→ meow_svcd(由 sysui 拉起)→ 各项服务子进程。
# * S90meow_bootmenu 里 `exec /usr/bin/meow_bootmenu --fork` 会阻塞 rcS,故任何 S90 之后
# 的 init.d 都不执行——sysui 必须排在 S90 之前(S70 满足)。
# * S90meow_bootmenu `exec /usr/bin/meow_bootmenu --fork`:HibyOS 模式 fork 播放器并转监督者,
# 阻塞 rcS;MeowOS 模式在 sysui 托管下让位退出(rcS 推进,S92 见 mode=meow 跳过播放器)。
# 故 sysui 必须排在 S90 之前(S70 满足)——launcher 已在 S70 由 sysui 拉起。
#
# 职责:监管系统进程(launcher / meow_svcd / meow_mdns / …),一个崩只拉起它、绝不级联。
# 本脚本只做三件事:
# 1) 预置板载监管配置 /usr/data/meow/sysui.d/*.conf(首启建,已存在不覆盖);
# 1) 预置板载监管配置 /usr/data/meow/sysui.d/*.conf(首启建;除 launcher.conf 迁移升级外已存在不覆盖);
# 2) 拉起 meow_sysui(默认后台 daemon);
# 3) stop 时优雅停 sysui(其会 SIGTERM 被监管的 svcd 并收尸)。
#
@@ -39,24 +40,37 @@ EOF
chmod 644 /usr/data/meow/sysui.d/svcd.conf
echo -n "provisioned svcd.conf "
fi
# launcher 当前由 S90meow_bootmenu 的 exec 拥有生命周期;待 bootmenu 让位后交 sysui。
# 此处仅登记(enabled=0),避免双重拉起。mdns 是 svcd 的服务子进程,由 svcd 负责,
# 本阶段不直接监管(或作兜底条目,默认关)。
# launcher 监管(M2.83 迁移):已交 sysui 托管——bootmenu 在 MeowOS 模式让位(sysui 在则
# 不再 exec launcher,lifecycle 归 sysui:崩→sysui 按 restart=always 重启;bootmenu 仅在
# sysui 不在时兜底 exec)。故此处 enabled=1。检测到旧版(enabled=0,bootmenu 时代)→ 升级。
# mdns 是 svcd 的服务子进程,由 svcd 负责,本阶段不直接监管(或作兜底条目,默认关)。
LAUNCHER_UPGRADE=''
if [ -f /usr/data/meow/sysui.d/launcher.conf ]; then
echo -n "launcher.conf exists "
else
if grep -qE '^[[:space:]]*enabled[[:space:]]*=[[:space:]]*0([[:space:]]|#|$)' /usr/data/meow/sysui.d/launcher.conf; then
LAUNCHER_UPGRADE=1
else
echo -n "launcher.conf exists "
fi
fi
if [ -n "$LAUNCHER_UPGRADE" ] || [ ! -f /usr/data/meow/sysui.d/launcher.conf ]; then
cat > /usr/data/meow/sysui.d/launcher.conf <<'EOF'
# 预留:launcher(系统 UI 渲染宿主)。现网由 S90meow_bootmenu exec 拥有 → 启用前需 bootmenu 让位。
# 真把 launcher 交给 sysui 监管后,把 enabled=1(并停用 bootmenu 的 exec launcher 路径)。
# meow_sysui 监管条目:launcher(系统 UI 渲染宿主)。系统进程总监 → launcher 被监管。
# 语义同 services.d:key=value,'#'/';' 注释,未知键忽略。无 trigger——enabled=1 即常驻监护。
# M2.83 launcher 监管迁移:bootmenu 在 MeowOS 模式让位(sysui 在则不 exec launcher),
# launcher 生命周期归 sysui:崩→sysui 按 restart=always 重启;bootmenu 仅在 sysui 不在时兜底。
exec=/usr/bin/meow_launcherd
args=
enabled=0
enabled=1
restart=always
backoff_ms=3000
max_restart=5
EOF
chmod 644 /usr/data/meow/sysui.d/launcher.conf
echo -n "provisioned launcher.conf "
if [ -n "$LAUNCHER_UPGRADE" ]; then
echo -n "upgraded launcher.conf (enabled 0->1) "
else
echo -n "provisioned launcher.conf "
fi
fi
else
echo -n "skip provision (/usr/data/meow not writable) "
+15 -7
View File
@@ -16,9 +16,10 @@
- **只监护自己 fork+exec 出来的进程**:`waitpid` 需为父进程,这是「一个崩只拉起它」的可靠前提;
sysui **不做**「adopt 外部 pid」式监护(那只 probe `kill(pid,0)`、无法真正 waitpid/重启)。
- 要监管什么由配置决定;**默认配置只开启 `meow_svcd`**(符合定案「sysui 总监 → svcd 被监管 →
服务为 svcd 子进程」)。`launcher` 当前由 S90meow_bootmenu 的 `exec` 拥有,配置中登记但
`enabled=0`(避免双重拉起;真正移交需 bootmenu 让位,见 §6)。
- 要监管什么由配置决定;**默认配置开启 `meow_svcd` + `meow_launcherd`**(`launcher` 于 M2.83
launcher 监管迁移落地:由 S70 预置 `launcher.conf` 且 `enabled=1`,bootmenu 在 MeowOS 模式让位)。
bootmenu 仅在 sysui 不在时兜底 exec launcher;HibyOS 模式下 bootmenu 会让 sysui 停 launcher
(不与播放器抢 fb0)。详见 §6。
- `meow_mdns` 是 svcd 的服务子进程(svcd 负责 spawn/restart),sysui 本阶段**不直接监管**它
(避免与 svcd 双重管理);`§10.1` 的「mdns 崩→svcd 拉起(或 sysui 兜底)」——兜底可后续
在 `sysui.d/` 加一条 meow_mdns 条目实现(默认关)。
@@ -111,9 +112,14 @@ meow_sysui pid
## 6. 迁移说明 / 边界(诚实标注)
- **launcher 监管**:现网 launcher 由 `S90meow_bootmenu` 的 `exec` 拉起(bootmenu 拥有其生命周期)。
sysui **本阶段不拉起 launcher**(`sysui.d/launcher.conf` 默认 `enabled=0` + 注释);
launcher 真正归 sysui 需 bootmenu 让位(后续迁移)。sysui 代码完全支持加一条 launcher 条目即可。
- **launcher 监管(✅ M2.83 已落地)**:launcher 生命周期已由 `S90meow_bootmenu` 的 `exec` 移交
sysui。`sysui.d/launcher.conf` 现 `enabled=1`(`restart=always`/`backoff_ms=3000`/`max_restart=5`)。
- sysui 在 S70 拉起并监管 launcher(崩→按策略重启,稳定 30s 清零次数,超 max_restart→FAILED 停)。
- bootmenu(`meow_bootmenu.c`)MeowOS 模式:sysui 在 → `meow_sysui start launcher` + 让位退出
(不 exec launcher);sysui 不在 → bootmenu 照旧 exec launcher(兜底,防开不了机)。
- bootmenu HibyOS 模式:sysui 在 → `meow_sysui stop launcher`(会话级 user_stopped)再 fork 播放器,
避免 launcher 与播放器抢 fb0。
- 已部署设备兼容:S70 检测旧 `launcher.conf` `enabled=0` → 升级为 `enabled=1`。
- **mdns 监管**:由 svcd 负责;sysui 兜底条目默认关。
## 7. 编译
@@ -125,6 +131,8 @@ meow_sysui pid
## 后续(不在本阶段)
- launcher 正式移交 sysui 监管(依赖 bootmenu 让位)。
- `MeowOS/sysui.d/` TF 双源扩展(复用 svcd 板载优先语义)。
- 与 meow_watchdog / 崩溃捕获的职责对齐(见 WORK_STATE SDK 缺失清单 #5)。
- launcher 已在 S70 由 sysui 拉起(bootmenu 让位,见 §6);**真机待验证**:①MeowOS 模式 bootmenu
让位后 rcS 推进到 S92 是否稳定跳过播放器 ②HibyOS 模式 `sysui stop launcher` 与播放器 fork 的
短暂共存无 fb0 冲突 ③launcher 在 S70 早启动(先于选单)与 boot_menu=1 选单的 fb 共存。