feat(launcher): M4 后台服务保活+后台播放(FRAMEWORK_DESIGN §5/§9 落地)

- app.json 新字段 background/background_audio 解析入 struct app/meow_acct 注册表
- meow_ipc.h:MSG_REGISTER(m_register_t)/SERVICE_OK(m_ack_t.status=pid)/SERVICE_STOP/
  MSG_SYS(m_sys_t, SHUTDOWN=1/SVC_DEAD=2) 负载结构落地
- 新模块 meow_bgplay.c/h(自包含+ops 注入,仿 meow_media,宿主可单测):
  · 后台播放保活——声明 background_audio 且媒体会话 PLAYING 的 App nav-exit 不终止,
    进程+音频流保留;UI 冻结走 §10.5 /tmp/meow_notif_active SDK present 自抑(非字面
    SIGSTOP:冻结同进程播放线程断供 PCM,§10.5 真机实证);点图标/媒体卡片回前台=
    原进程恢复(chain/picker 忽略),停播后再退出=真退 SIGTERM
  · 无头后台服务——MSG_REGISTER spawn/stop/reap + 退避重启 1/2/4/10s cap +
    max_restart 熔断(清该 App 通知 + 注册连接广播 MSG_SYS{SVC_DEAD},重注册复位)
  · 卡拔例外(卡上二进制后台 App/服务仍 SIGTERM 防 SIGBUS)、崩溃照收、
    关机前 meow_bgplay_kill_all 有界回收(含 MSG_SYS{SHUTDOWN} 广播)
- util.c:MSG_REGISTER/MSG_SERVICE_STOP 分发(权限/声明校验链)+ ipc_conn_alive 连接
  存活查询 + meow_ipc_process 末尾挂 meow_bg_housekeep(drain/reap/退避 tick)
- app_launcher.c:launch_app_chain 入口 resume(bg_take 原进程回前台)+ nav-exit
  保活分支 + 转后台出口(杀看门狗/写自抑标记/复位顶条,跳过退出尾)+ 冷启动自动
  拉起静态 keepalive(mode=0) 服务(exec 路径约定=App 同目录 <svc> 文件)
- main_menu.c:应用列表「·后台」标注(宫格/列表,1s tick 按 change_seq 刷新)+
  两条退出尾 kill_all + unlink NOTIF_ACTIVE
- 宿主单测 test_bgplay.c 50 项全过(真 fork 子进程走状态机 + 假时钟退避熔断);
  test_media/test_notif_panel/test_notif_tf/test_vol_ramp_jack 回归全过;
  zig-mipsel-cc -Wall -Wextra 0 warning。launcher md5=c07d011c0769fca14d3bfb752d735463
This commit is contained in:
MeowOS committed 2026-09-01 18:09:09 +08:00
1 parent 7db8197f9c
commit 5aabede0cd
13 files changed
+1461 -40

No files matched your search

@@ -37,6 +37,7 @@ extern "C" {
#include "meow_settings.h" /* B2a:统一系统设置后端(SYSTEM_SETTINGS.md §3/MEOWOS_API §2) */
#include "meow_notif.h" /* M2a:通知存储 + 分发(NOTIFICATION_SYSTEM.md §4/§7/§8) */
#include "meow_media.h" /* 阶段D附录B:媒体会话注册表(MSG_META/MSG_PLAYCTL/最近活跃源) */
#include "meow_bgplay.h" /* M4:后台播放保活 + 无头后台服务运行时表(§9) */
#include "meow_ui.h" /* A-1/A-2:launcher 用 SDK 渲染栈(meow_ui_fill_rect/text/flush/theme) */
#include "meow_ui_internal.h" /* A-1/A-2:launcher 与 SDK 共用 back_buf + 手动脏模型桥接(mark_full/back_buf) */
#include "meow_notif_panel.h" /* 阶段B:通知中心面板纯逻辑(header-only,可单测) */
@@ -305,6 +306,8 @@ struct app {
char immersive; /* '1'=immersive=true(隐藏虚拟返回键,返回手势归 SDK) */
char fullscreen; /* '1'=app.json fullscreen=true(注入 MEOW_FULLSCREEN=1,SDK 预先设全屏) */
char fonts; /* 字库档:0=默认4K常用 1=大字库GBK 2=Full(app.json "fonts";注入 MEOW_FONT_TIER) */
char background; /* M4:'1'=app.json background=true(可注册无头后台服务) */
char background_audio; /* M4:'1'=background_audio=true(播放中退出转后台保活,§9) */
char icon[129]; /* icon= 路径 */
int nroute; /* route.<id> 行数 */
struct meow_route routes[MEOW_MAX_ROUTES];
@@ -327,6 +330,8 @@ struct meow_acct {
int nsvc;
struct meow_svc svcs[MEOW_MAX_SVCS];
int declared; /* 是否经 HELLO/ACT_DECLARE 运行时声明过 */
char background; /* M4:'1'=app.json background=true(MSG_REGISTER 权限位0) */
char background_audio; /* M4:'1'=background_audio=true(MSG_REGISTER MF_PLAYBACK 权限位1) */
};
@@ -663,6 +668,19 @@ int meow_ams_pending_start_set_ex(const char *pkg, const char *act,
* util.c 转发运行时 declare 与 picker call/result 给 amsd 用。 */
void meow_ams_send(const char *payload, int len);
/* ---- M4 后台保活/后台服务胶水(app_launcher.c 实现;util.c/main_menu.c 消费)---- */
/* launcher 侧 meow_bgplay ops 组装(meow_ipc_init 末尾调一次)。 */
void meow_bgplay_launcher_init(void);
/* 后台表周期维护:drain 各 bg App 的 stdout 管道 + meow_bg_tick + meow_svc_tick。
* 挂载点=meow_ipc_process 末尾(主循环单写者排空点,四处循环都经它)。 */
void meow_bg_housekeep(void);
/* 查静态声明的 service.<svc>;无返回 NULL。 */
const struct meow_svc *meow_acct_svc_find(const struct meow_acct *ac, const char *svc);
/* 后台权限位:bit0=background(可注册服务)bit1=background_audio(后台音频)。 */
int meow_acct_background_perm(const struct meow_acct *ac);
/* M4:服务 exec 路径约定 = App 二进制同目录下的 <svc> 名文件。 */
void meow_svc_exec_path(const char *app_exec, const char *svc, char *out, int olen);
void meow_dac_vol_write(int pct);
void meow_dac_vol_write_throttled(void);
void meow_dirty_add(int x, int y, int w, int h);
@@ -680,6 +698,11 @@ void meow_font_scan_presets(void);
void meow_font_scan_presets_root(const char *card_root);
int meow_ipc_init(void);
void meow_ipc_process(void);
/* M4:IPC 连接存活查询(熔断广播投递前判连接未断;util.c ipc_conns 表查 fd)。 */
int meow_ipc_conn_alive(int fd);
/* M4:ipc_send 公开包装(meow_bgplay send_frame 回调用;同 meow_media 的注入口径)。 */
size_t meow_ipc_send_pub(int fd, uint16_t type, uint32_t req_id,
const void *payload, uint32_t len);
/* §10.5:读并清除待处理的 MSG_NOTIF_OPEN(App 前台顶部下滑请求展开通知中心叠加会话)。
* 调用方=launch_app waitpid 循环;返回 1 并填 *out(待处理),0=无。 */
int meow_notif_open_take(m_notif_open_t *out);